#include "asset.h" #include "random.h" #include "map.h" #include "rect.h" #include "render.h" #include "world.h" #define null_tile 0xffff Rect tile_rects[] = { #define x(n, x, y) \ { x, y, map_tile_size, map_tile_size }, tiles_xmacro #undef x }; void generate_room(Map* m) { const Bitmap* b = get_bitmap(asset_id_rooms_img); const unsigned* p = (const unsigned*)&b[1]; const int max_rooms = b->h / map_h; const int r = get_r() % max_rooms; int o = r * map_w * map_h; int e = map_w * map_h, i; for (i = 0; i < e; i++, o++) { int bit = 1 << (o & 0x1f); if (p[o >> 5] & bit) m->tiles[i] = tile_brick; else m->tiles[i] = null_tile; } } unsigned short get_collider(Map_Tile t) { switch (t) { case tile_stone: case tile_block1: case tile_block2: case tile_window_top: case tile_window_mid: case tile_window_bot: case tile_brick_floor: case tile_trapdoor1: case tile_trapdoor2: case tile_brick: return 1; case tile_brick_ramp5: case tile_stone_ramp5: return 2; case tile_brick_ramp6: case tile_stone_ramp6: return 3; case tile_brick_ramp7: case tile_stone_ramp7: return 4; case tile_brick_ramp8: case tile_stone_ramp8: return 5; default: return 0; } } void generate_collision(Map* m) { int e = map_w * map_h, i; for (i = 0; i < e; i++) m->collision[i] = get_collider(m->tiles[i]); } int imp_check(Map* m, Map_Tile t, int x, int y) { return x >= 0 && y >= 0 && x < map_w && y < map_h && m->tiles[x + y * map_w] == t; } #define check(ox, oy, t) \ imp_check(m, t, x + ox, y + oy) #define place(t) \ m->tiles[x + y * map_w] = t #define place_o(t, ox, oy) \ m->tiles[x + ox + (y + oy) * map_w] = t #define place_a(t, x, y) \ m->tiles[x + y * map_w] = t void generate_ramps(Map* m) { int x, y; for (y = 0; y < map_h; y++) for (x = 0; x < map_w; x++) { if ( check( 0, 0, null_tile) && check( 1, 0, null_tile) && check(-1, 0, tile_brick) && !check(-1, -1, tile_brick) && check( 0, 1, tile_brick) && check( 1, 1, tile_brick) ) { place(tile_brick_ramp7); place_o(tile_brick_ramp8, 1, 0); } if ( check( 0, 0, null_tile) && check(-1, 0, null_tile) && check( 1, 0, tile_brick) && !check( 1, -1, tile_brick) && check( 0, 1, tile_brick) && check(-1, 1, tile_brick) ) { place(tile_brick_ramp6); place_o(tile_brick_ramp5, -1, 0); } if ( check(0, 0, tile_brick) && check(0, 1, tile_brick) && check(0, 2, tile_brick) && (( check(1, 0, null_tile) && check(1, 1, null_tile) && check(1, 2, null_tile)) || ( check(-1, 0, null_tile) && check(-1, 1, null_tile) && check(-1, 2, null_tile))) ) { place(tile_window_top); place_o(tile_window_mid, 0, 1); place_o(tile_window_bot, 0, 2); } } } void generate_floors(Map* m) { int x, y; for (y = 0; y < map_h; y++) for (x = 0; x < map_w; x++) { if ( check(0, 0, tile_brick) && check(0, -1, null_tile) ) place(tile_brick_floor); } } void generate_doors(Map* m) { const int hx = map_w >> 1; const int t = 0; const int b = map_h - 1; place_a(tile_trapdoor1, hx, b); place_a(tile_trapdoor2, hx + 1, b); place_a(tile_trapdoor3, hx, t); place_a(tile_trapdoor4, hx + 1, t); } #undef check #undef place void generate_enemies(const Map* m, World* w) { #define check \ (m->collision[x + y * map_w] == 1 && \ m->collision[x + (y - 1) * map_w] == 0) int x, y, ex = map_w - 1, ey = map_h - 1; for (y = 1; y < ey; y++) { for (x = 1; x < ex; x++) { int plat = -1; for (; x < ex; x++) if (check) { plat = 0; break; } if (!plat) for (; check && x < ex; x++, plat++); if (plat >= 3) { Enemy* e; int sx = x - (plat >> 1); e = inst_enemy( w, enemy_demon, (sx * map_tile_size) << fbits, ((y - 1) * map_tile_size) << fbits ); e->face = get_r() & 1; } for (; check && x < ex; x++); } } } void generate_floor(Map* m, World* w) { Player* p = &w->player; w->enemy_count = 0; w->effect_count = 0; w->deathzone_count = 0; generate_room(m); generate_ramps(m); generate_doors(m); generate_floors(m); generate_collision(m); generate_enemies(m, w); p->x = (map_w >> 1) << fbits; p->y = (map_h - 2) << fbits; p->x *= map_tile_size; p->y *= map_tile_size; p->x += (map_tile_size >> 1) << fbits; p->vx = 0; p->vy = 0; } void render_map(const Map* m, Renderer* r) { const Bitmap* tm = get_bitmap(asset_id_map_img); int t = 0, x, y; for (y = 0; y < map_h; y++) { for (x = 0; x < map_w; x++, t++) { int tile = m->tiles[t]; if (tile != null_tile) ren_map( r, x * map_tile_size, y * map_tile_size, &tile_rects[tile], tm ); } } }