/* Generates the fov settings from map tiles */ void map_fov_build(map_t *map) { int x, y; for (y = 0; y < map->height; y++) { for (x = 0; x < map->width; x++) { tile_t *tile = tile_at(map, x, y); TCOD_map_set_properties(map->fov, x, y, tile->transparent, tile->walkable); } } }
extern State *update_free( State * const state , const double time ) { Entity * const player_entity = & state->player.entity; const TileType non_walkable = TILE_WALL; TileType dst_tile = update_entity( player_entity, & state->map, non_walkable, time ); const int current = tile_at( & state->map, player_entity->position ); if (current == TILE_TRAP) { die(state); } else if (current == TILE_TRADER) { change_state(state, STATE_TRADE); } else if (current == TILE_BOSS) { change_state(state, STATE_BOSS); } if (player_entity->position.x == state->map.width - 1) { state->current_level_no += 1; clean_map_data( & state-> map ); change_level( & state->map, state->current_level_no ); reset_entities( state ); player_entity->position.x = 0; player_entity->destination = player_entity->previous_position = player_entity->position; } for (int i = 0; i < state->enemies_count; i++) { Enemy *enemy = state->enemies + i; update_enemy( enemy, & state->map, time ); if ( POINT_EQ( state->player.entity.position , enemy->entity.position ) ) { die(state); } Boulder * b = boulder_at( state, enemy->entity.destination ); if ( b != NULL ) { cancel_move( & enemy->entity ); swap_enemy_direction( enemy ); } } for (int i = 0; i < state->boulders_count; i++) { Boulder *boulder = state->boulders + i; update_entity( & boulder->entity, & state->map, 0, time ); } return state; }
ei_bool_t handle_tile_press(ei_widget_t* widget, ei_event_t* event, void* user_param) { tile_t* tile = (tile_t*)user_param; puzzle_t* puzzle = tile->puzzle; ei_point_t offsets[] = {{0, -1}, {-1, 0}, {1, 0}, {0, 1}}; ei_point_t current = tile->current_position; ei_point_t swap_pos; ei_point_t swap_coordinates; int i; for (i = 0; i < 4; i++) { swap_pos = ei_point_add(current, offsets[i]); if (valid(puzzle, swap_pos) && tile_at(puzzle, swap_pos) == NULL) { puzzle->current[index_at(puzzle, current)] = NULL; puzzle->current[index_at(puzzle, swap_pos)] = tile; tile->current_position = swap_pos; swap_coordinates = place_coordinates(swap_pos); ei_place(tile->button, NULL, &(swap_coordinates.x), &(swap_coordinates.y), NULL, NULL, NULL, NULL, NULL, NULL); } } return EI_TRUE; }
extern State *process_free( State * const state , const int new_keys , const int old_keys ) { Entity * const player_entity = & state->player.entity; int moved = 0; if ( is_moving( player_entity ) == 0 ) { if (new_keys & KEY_UP) { player_entity->destination.y -= 1; moved = 1; } else if (new_keys & KEY_DOWN) { player_entity->destination.y += 1; moved = 1; } else if (new_keys & KEY_LEFT) { player_entity->destination.x -= 1; moved = 1; } else if (new_keys & KEY_RIGHT) { player_entity->destination.x += 1; moved = 1; } } if ( moved ) { const int destination = tile_at( & state->map , player_entity->destination ); const int current = tile_at( & state->map , player_entity->position ); const int antydest = antydestination_tile(state); if ( ( ! POINT_EQ( player_entity->destination , player_entity->previous_position ) ) && ( destination == TILE_STRING && antydest == TILE_STRING ) ) { cancel_move( player_entity ); } else { if (current == TILE_FLOOR && destination != TILE_STRING) { set_tile( & state->map, TILE_STRING, player_entity->position); } else if ( current == TILE_STRING && destination != TILE_FLOOR) { set_tile( & state->map, TILE_FLOOR, player_entity->position); } } Boulder * b = boulder_at( state, player_entity->destination ); if ( b != NULL ) { int i = player_entity->destination.x - player_entity->position.x; int j = player_entity->destination.y - player_entity->position.y; Point boulder_dest; boulder_dest.x = player_entity->destination.x + i; boulder_dest.y = player_entity->destination.y + j; TileType boulder_dest_tile = tile_at( & state->map, boulder_dest); if ( boulder_dest_tile == TILE_FLOOR ) { b->entity.destination = boulder_dest; } else { cancel_move( player_entity ); } } } return state; }
Tile * Board::operator[] (int _aIndex) { return tile_at(_aIndex); }
void icCanvasManager::CanvasView::draw_tiles(cairo_t* ctxt, cairo_rectangle_t* rect) { float square_size = std::max(rect->width, rect->height); int lowest_zoom = std::floor(31 - log2(square_size * this->zoom)); int highest_zoom = this->highest_zoom(); int canvas_x_min = this->x_scroll + (rect->x * this->zoom), canvas_x_max = this->x_scroll + (rect->x + rect->width) * this->zoom, canvas_y_min = this->y_scroll + (rect->y * this->zoom), canvas_y_max = this->y_scroll + (rect->y + rect->height) * this->zoom; //Phase 1: Look up tiles from cache icCanvasManager::TileCache::TileCacheQuery qu1; qu1.query_x_gte(canvas_x_min); qu1.query_x_lt(canvas_x_max); qu1.query_y_gte(canvas_y_min); qu1.query_y_lt(canvas_y_max); qu1.query_size_gte(lowest_zoom); qu1.query_size_lt(highest_zoom+2); qu1.query_time_limit(1); auto tilecache = this->drawing->get_tilecache(); auto tilelist = tilecache->execute(qu1); auto begin = tilelist.begin(), end = tilelist.end(); RefPtr<DisplaySuite> currentDS = tilecache->display_suite(), cairoDS = dynamic_cast<icCanvasManager::Cairo::DisplaySuite*>((icCanvasManager::DisplaySuite*)currentDS); bool must_copy = false, must_copy_direct = false; if (!cairoDS) { cairoDS = new icCanvasManager::Cairo::DisplaySuite(); must_copy = true; must_copy_direct = cairoDS->can_direct_transfer(currentDS); } //Phase 2: Copy/scale tiles onto view for (; begin != end; begin++) { auto &tile = tilecache->tile_at(*begin); cairo_surface_t* image; if (must_copy) { if (must_copy_direct) { image = (cairo_surface_t*)cairoDS->direct_transfer(currentDS, tile.current_tile, true); } else { auto generic_data = currentDS->export_tile(tile.current_tile); image = (cairo_surface_t*)cairoDS->import_tile(generic_data); delete[] generic_data; } } else { image = (cairo_surface_t*)tile.current_tile; } cairo_save(ctxt); auto tile_size = UINT32_MAX >> tile.size; auto tile_wndsize = tile_size / this->zoom; auto scale_factor = tile_wndsize / (float)icCanvasManager::TileCache::TILE_SIZE; int txpos, typos; //yes I know, typos this->coordToWindowspace(tile.x - tile_size / 2, tile.y - tile_size / 2, &txpos, &typos); cairo_translate(ctxt, (double)txpos, (double)typos); cairo_scale(ctxt, scale_factor, scale_factor); cairo_move_to(ctxt, 0, 0); cairo_line_to(ctxt, icCanvasManager::TileCache::TILE_SIZE, 0); cairo_line_to(ctxt, icCanvasManager::TileCache::TILE_SIZE, icCanvasManager::TileCache::TILE_SIZE); cairo_line_to(ctxt, 0, icCanvasManager::TileCache::TILE_SIZE); cairo_line_to(ctxt, 0, 0); cairo_set_operator(ctxt, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba(ctxt, 1.0, 1.0, 1.0, 1.0); cairo_fill_preserve(ctxt); cairo_set_operator(ctxt, CAIRO_OPERATOR_OVER); cairo_set_source_surface(ctxt, image, 0, 0); cairo_fill(ctxt); cairo_restore(ctxt); if (must_copy) { cairoDS->free_tile((DisplaySuiteTILE)image); } } };
/* The main game loop */ void play(void) { int playing = 1; int x, y, vpx, vpy; /* A messy way to do the map, works for now */ map_t *map = map_new(50, 50); generate_cave(map); map_fov_build(map); /* Set up the offscreen consoles */ map_layer = TCOD_console_new(ui_viewport_width, ui_viewport_height); psion_layer = TCOD_console_new(ui_viewport_width, ui_viewport_height); TCOD_console_set_key_color(psion_layer, C_KEY); bgcolor(psion_layer, C_KEY); /* Set up the player */ init_player(); rename_player("Gu the Cabeboy"); blink_player(map); /* Initialize the inventory */ /* Enter the main game loop! */ while (playing) { /* Prepare the screen for drawing */ clear(NULL); /* Calculate the position of the viewport */ vpx = player->x - ui_viewport_width/2 > 0 ? player->x - ui_viewport_width/2 : 0; vpy = player->y - ui_viewport_height/2 > 0 ? player->y - ui_viewport_height/2 : 0; if ((vpx + ui_viewport_width) > map->width) { vpx = map->width - ui_viewport_width; } if ((vpy + ui_viewport_height) > map->height) { vpy = map->height - ui_viewport_height; } if (ui_viewport_width > map->width) { vpx = 0; } if (ui_viewport_height > map->height) { vpy = 0; } /* Calculate the field of view */ map_fov_do(map, player->x, player->y); /* Only display the part of the map inside the viewport */ for (y = 0; y < ui_viewport_height; y++) { for (x = 0; x < ui_viewport_width; x++) { if (((vpy+y) < map->height) && ((vpx+x) < map->width)) { tile_t *tile = tile_at(map, vpx+x, vpy+y); if (TCOD_map_is_in_fov(map->fov, vpx+x, vpy+y)) { fgcolor(map_layer, tile->fg_lit); } else { fgcolor(map_layer, tile->fg_dark); } putch(map_layer, x, y, tile->glyph); } } } TCOD_console_blit(map_layer, 0, 0, ui_viewport_width, ui_viewport_height, NULL, ui_viewport_x, ui_viewport_y, 255); /* Draw the player and status */ fgcolor(NULL, C_WHITE); putch(NULL, ui_viewport_x+player->x-vpx, ui_viewport_y+player->y-vpy, '@'); fgcolor(NULL, C_MSG); putstr(NULL, 1, 23, player->name); /* Redraw the screen */ update(); /* Handle keypress */ TCOD_key_t k = getkey(); if (k.c == 0) { switch (k.vk) { /* Move around */ case TCODK_KP7: /* up left */ attempt_move(map, player->x-1, player->y-1); break; case TCODK_KP8: /* up */ case TCODK_UP: attempt_move(map, player->x, player->y-1); break; case TCODK_KP9: /* up right */ attempt_move(map, player->x+1, player->y-1); break; case TCODK_KP1: /* down left */ attempt_move(map, player->x-1, player->y+1); break; case TCODK_KP2: /* down */ case TCODK_DOWN: attempt_move(map, player->x, player->y+1); break; case TCODK_KP3: /* down right */ attempt_move(map, player->x+1, player->y+1); break; case TCODK_KP4: /* left */ case TCODK_LEFT: attempt_move(map, player->x-1, player->y); break; case TCODK_KP6: /* right */ case TCODK_RIGHT: attempt_move(map, player->x+1, player->y); break; /* View character summary */ case TCODK_TAB: character(); break; default: printf("%d %d\n", TCODK_TAB, k.vk); break; } } else { switch (k.c) { /* Quit the game */ case 'Q': playing = quit(); break; /* Open up the inventory */ case 'i': inventory(); break; /* View character summary */ case 'c': character(); break; /* Use scan ability */ case 's': psion_scan(map); break; default: break; } } } /* Clean up, the game is over */ map_destroy(map); }
/* Can probably be made more efficient - like only checking one area */ static level_mask_t check_bg_collision(game_t *p_game, sprite_t *p_sprite, dir_t dir, point_t new_pt, point_t *p_overlap) { rect_t rect; int16_t x,y; rect = rect_add_pt(p_sprite->p_bounds[p_sprite->frame], new_pt); switch (dir) { case LEFT: rect.bottom_right.x = rect.top_left.x + TILE_W; rect.bottom_right.y-=TILE_H; break; case RIGHT: rect.top_left.x = rect.bottom_right.x - TILE_W; rect.bottom_right.y-=TILE_H; /* FIXME! Better with allow left/right */ break; case UP: rect.bottom_right.y = rect.top_left.y + TILE_W; break; case DOWN: rect.top_left.y = rect.bottom_right.y - TILE_W; break; } #ifndef NDEBUG { rect_t rect2 = rect_add_pt(p_sprite->p_bounds[p_sprite->frame], p_sprite->pt); draw_rect(p_game, rect2, vRGB(255,255,255)); } #endif draw_rect(p_game, rect, vRGB(255,0,0)); for (y = rect.top_left.y/TILE_H; y <= rect.bottom_right.y/TILE_H; y++) { for (x = rect.top_left.x/TILE_W; x <= rect.bottom_right.x/TILE_W; x++) { level_mask_t tile = tile_at(p_game, pt(x,y)); if (tile > 1) { rect_t tile_rect = rect_add_pt(tile_bounds[tile-1], pt_to_sprite(pt(x,y))); draw_rect(p_game, tile_rect, vRGB(0,255,0)); if (rect_overlap(tile_rect, rect, p_overlap)) { assert(tile != 0); #ifndef NDEBUG DbgPrintf(" %d:%d Tile %d rect %d:%d -> %d:%d (overlap %d,%d)\n\n", dir, p_sprite->state, tile, tile_rect.top_left.x,tile_rect.top_left.y, tile_rect.bottom_right.x, tile_rect.bottom_right.y, p_overlap->x, p_overlap->y ); vFlipScreen(0); #endif return tile; } } } } /* TMP! */ DbgPrintf("\n"); #ifndef NDEBUG vFlipScreen(0); #endif return 0; }