diff --git a/src/sys/nact_gakuenking.cpp b/src/sys/nact_gakuenking.cpp index 0a25e0f..082c6bb 100644 --- a/src/sys/nact_gakuenking.cpp +++ b/src/sys/nact_gakuenking.cpp @@ -514,38 +514,25 @@ private: int view_step_x = static_cast(map_view_x) - map_view_drawn_x; int view_step_y = static_cast(map_view_y) - map_view_drawn_y; - int sprite_step_x = 0; - int sprite_step_y = 0; - if (map_sprite_frame != SPRITE_HIDDEN && - map_sprite_drawn_frame != SPRITE_HIDDEN) { - sprite_step_x = static_cast(map_sprite_x) - map_sprite_drawn_x; - sprite_step_y = static_cast(map_sprite_y) - map_sprite_drawn_y; - } - bool animate = can_animate(view_step_x, view_step_y, sprite_step_x, sprite_step_y); + int sprite_step_x = static_cast(map_sprite_x) - map_sprite_drawn_x; + int sprite_step_y = static_cast(map_sprite_y) - map_sprite_drawn_y; + if (map_sprite_frame == SPRITE_HIDDEN || map_sprite_drawn_frame == SPRITE_HIDDEN) + sprite_step_x = sprite_step_y = 0; + if (!can_animate(view_step_x, view_step_y, sprite_step_x, sprite_step_y)) + view_step_x = view_step_y = sprite_step_x = sprite_step_y = 0; - if (animate) { - // One column and row more than the view, so that the old and the - // new view both fit in the composed image. The sprite is not part - // of it; it is drawn on top of every animation frame. - int origin_x = map_view_x - 5 - std::max(view_step_x, 0); - int origin_y = map_view_y - 4 - std::max(view_step_y, 0); - int cols = VIEW_COLS + std::abs(view_step_x); - int rows = VIEW_ROWS + std::abs(view_step_y); - draw_map_cells(MAP_WORK_SCREEN, 0, 0, origin_x, origin_y, cols, rows); - } else { - draw_map_cells(0, VIEW_X, VIEW_Y, - map_view_x - 5, map_view_y - 4, VIEW_COLS, VIEW_ROWS); - draw_view_sprite(); - } + // The composed image holds the cells of both the old and the new view. + // The sprite is not part of it; it is drawn on top of every animation + // frame, because it can move on its own. + int origin_x = map_view_x - 5 - std::max(view_step_x, 0); + int origin_y = map_view_y - 4 - std::max(view_step_y, 0); + draw_map_cells(origin_x, origin_y, VIEW_COLS + std::abs(view_step_x), + VIEW_ROWS + std::abs(view_step_y)); update_map_overview(); - // A step spends map_animation_ticks moving, instead of waiting after an - // instant jump, so walking speed stays the same either way. - if (animate) - animate_map_view(view_step_x, view_step_y, sprite_step_x, sprite_step_y); - else - wait_ticks(map_animation_ticks); + animate_map_view(origin_x, origin_y, view_step_x, view_step_y, + sprite_step_x, sprite_step_y); map_overview_rebuild_pending = false; map_view_drawn_x = map_view_x; @@ -560,16 +547,12 @@ private: bool can_animate(int view_step_x, int view_step_y, int sprite_step_x, int sprite_step_y) { - if (!map_view_drawn || map_overview_rebuild_pending) - return false; - if (!is_single_step(view_step_x) || !is_single_step(view_step_y) || - !is_single_step(sprite_step_x) || !is_single_step(sprite_step_y)) - return false; - return view_step_x || view_step_y || sprite_step_x || sprite_step_y; + return map_view_drawn && !map_overview_rebuild_pending && + is_single_step(view_step_x) && is_single_step(view_step_y) && + is_single_step(sprite_step_x) && is_single_step(sprite_step_y); } - void draw_map_cells(int dest, int dest_x, int dest_y, - int cell_x0, int cell_y0, int cols, int rows) { + void draw_map_cells(int cell_x0, int cell_y0, int cols, int rows) { for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { int cell_x = cell_x0 + col; @@ -582,62 +565,54 @@ private: uint8_t layer_z = inside ? map_layer_z[offset] : CELL_EMPTY; uint8_t layer_w = inside ? map_layer_w[offset] : CELL_EMPTY; - int px = dest_x + col * TILE_SIZE; - int py = dest_y + row * TILE_SIZE; + int px = col * TILE_SIZE; + int py = row * TILE_SIZE; if (!map_base_visible_view) base = CELL_EMPTY; if (base == CELL_EMPTY) { - ags->box_fill(dest, px, py, px + TILE_SIZE - 1, py + TILE_SIZE - 1, 0); + ags->box_fill(MAP_WORK_SCREEN, px, py, + px + TILE_SIZE - 1, py + TILE_SIZE - 1, 0); } else { - draw_map_tile(dest, base, px, py, false); + draw_map_tile(base, px, py, false); } if (layer_z != CELL_EMPTY) - draw_map_tile(dest, layer_z, px, py, false); + draw_map_tile(layer_z, px, py, false); if (layer_w != CELL_EMPTY) - draw_map_tile(dest, layer_w, px, py, true); + draw_map_tile(layer_w, px, py, true); } } } - void draw_view_sprite() { - if (map_sprite_frame == SPRITE_HIDDEN || - map_sprite_x >= MAP_WIDTH || map_sprite_y >= MAP_HEIGHT) - return; - draw_map_sprite(map_sprite_frame, - VIEW_X + (map_sprite_x - (map_view_x - 5)) * TILE_SIZE, - VIEW_Y + (map_sprite_y - (map_view_y - 4)) * TILE_SIZE); + // The pixel position of something that moves `step` cells and arrives at + // `to`, at animation frame `frame` of `frames`. + static int step_position(int to, int step, int frame, int frames) { + return to - step * TILE_SIZE * (frames - frame) / frames; } - // Moves the view window over the composed map and the sprite over the - // window, each from where it was drawn last to where it is now, using the - // time the view would otherwise wait. - void animate_map_view(int view_step_x, int view_step_y, + // Draws the view window of the composed map and the sprite on top of it, + // moving both from where they were drawn last to where they are now over + // the time a map redraw takes. + void animate_map_view(int origin_x, int origin_y, + int view_step_x, int view_step_y, int sprite_step_x, int sprite_step_y) { int duration = ticks_to_ms(map_animation_ticks); int frames = std::clamp(duration / ANIMATION_FRAME_MS, 2, TILE_SIZE); - // Positions on the composed image, which starts at the top left cell - // of the two views. - int window_to_x = std::max(view_step_x, 0) * TILE_SIZE; - int window_to_y = std::max(view_step_y, 0) * TILE_SIZE; - int window_from_x = window_to_x - view_step_x * TILE_SIZE; - int window_from_y = window_to_y - view_step_y * TILE_SIZE; - int sprite_to_x = (map_sprite_x - (map_view_x - 5)) * TILE_SIZE + window_to_x; - int sprite_to_y = (map_sprite_y - (map_view_y - 4)) * TILE_SIZE + window_to_y; - int sprite_from_x = sprite_to_x - sprite_step_x * TILE_SIZE; - int sprite_from_y = sprite_to_y - sprite_step_y * TILE_SIZE; - bool draw_sprite = map_sprite_frame != SPRITE_HIDDEN && - map_sprite_x < MAP_WIDTH && map_sprite_y < MAP_HEIGHT; + // Pixel positions on the composed image. + int window_x = (map_view_x - 5 - origin_x) * TILE_SIZE; + int window_y = (map_view_y - 4 - origin_y) * TILE_SIZE; + int sprite_x = (map_sprite_x - origin_x) * TILE_SIZE; + int sprite_y = (map_sprite_y - origin_y) * TILE_SIZE; uint32_t start = SDL_GetTicks(); for (int frame = 1; frame <= frames && !terminate; frame++) { - int wx = window_from_x + (window_to_x - window_from_x) * frame / frames; - int wy = window_from_y + (window_to_y - window_from_y) * frame / frames; + int wx = step_position(window_x, view_step_x, frame, frames); + int wy = step_position(window_y, view_step_y, frame, frames); ags->copy_screen(MAP_WORK_SCREEN, 0, wx, wy, wx + VIEW_COLS * TILE_SIZE - 1, wy + VIEW_ROWS * TILE_SIZE - 1, VIEW_X, VIEW_Y); - if (draw_sprite) { - int sx = sprite_from_x + (sprite_to_x - sprite_from_x) * frame / frames; - int sy = sprite_from_y + (sprite_to_y - sprite_from_y) * frame / frames; + if (map_sprite_frame != SPRITE_HIDDEN) { + int sx = step_position(sprite_x, sprite_step_x, frame, frames); + int sy = step_position(sprite_y, sprite_step_y, frame, frames); draw_map_sprite(map_sprite_frame, VIEW_X + sx - wx, VIEW_Y + sy - wy); } uint32_t deadline = start + duration * frame / frames; @@ -656,14 +631,14 @@ private: return cg; } - void draw_map_tile(int dest, uint8_t tile, int px, int py, bool transparent) { + void draw_map_tile(uint8_t tile, int px, int py, bool transparent) { int bank = tile / TILES_PER_BANK; if (bank >= NR_TILE_BANKS || !map_tile_cg[bank]) { WARNING("map tile %d has no loaded bank", tile); return; } int index = tile % TILES_PER_BANK; - blit_sheet(dest, map_tile_cg[bank], + blit_sheet(MAP_WORK_SCREEN, map_tile_cg[bank], (index % SHEET_COLS) * TILE_SIZE, (index / SHEET_COLS) * TILE_SIZE, TILE_SIZE, TILE_SIZE, px, py, transparent);