PoP roomtest (план v2, шаг 2): общая геометрия в pop_geom
Сведены дубли, разъехавшиеся по модулям: - x_bump[20] был в pop_kid (uint8_t!) и в pop_map (int16_t) — теперь одна таблица int16_t; - y_land[5] — две копии; - y_to_row_mod4 — в pop_bg и pop_map; - 32-битный LCG оригинала (prandom) — в pop_bg и pop_trob; функция теперь одна, а СИДЫ остались раздельными (у раскладки кладки и у фаз факелов свои последовательности, смешивать нельзя — иначе поедет рисунок стен). Экономия по коду скромная (_CODE 24462 -> 24421, W3 11643 -> 11632: часть выигрыша съели межмодульные вызовы). Главное здесь другое: pop_geom лежит в W1/W2 и не трогает графику, то есть это тот самый «чистый» слой, который сможет звать __banked-код стражей (docs/layout_plan_v2.md §4, §5.2). Проверено в MAME: комната 1 после пересборки отрисована ПОБАЙТОВО так же, как до правки (0 различающихся пикселей в области комнаты) — значит последовательности PRNG и геометрия не поехали; Kid бегает. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* FRAME_NEEDS_FLOOR (0x40), под персонажем не floor -> start_fall();
|
||||
* стена -> in_wall();
|
||||
* freefall (action 4) -> do_fall(): fall_y-ускорение (в fall_accel/speed),
|
||||
* достиг y_land[curr_row+1] -> land()/inc_curr_row.
|
||||
* достиг pop_y_land[curr_row+1] -> land()/inc_curr_row.
|
||||
*
|
||||
* Координатная система PoP: экран.left = 58, тайл = 14 ед. (TILE_SIZEX);
|
||||
* col = (xpos-58)/14 (округл. вниз), xl = остаток; get_tile_div_mod_m7 =
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "pop_kid.h"
|
||||
#include "pop_map.h"
|
||||
#include "pop_ctrl.h" /* pop_ctrl_shift_held() — для check_grab */
|
||||
#include "pop_geom.h" /* общая геометрия (x_bump/y_land/y_to_row) */
|
||||
#include "pop_redraw.h" /* пометки перерисовки (порт set_redraw_*) */
|
||||
/* pop_bg нужен ТОЛЬКО падающему куску (mob): spawn/tick/pos — это движущийся
|
||||
* ОБЪЕКТ, а не перерисовка тайла (в оригинале он и живёт отдельно: mobs +
|
||||
@@ -88,23 +89,17 @@
|
||||
|
||||
#define FRAME_NEEDS_FLOOR 0x40
|
||||
#define FRAME_WEIGHT_X 0x1F
|
||||
#define TILE_SIZEX 14
|
||||
#define TILE_RIGHTX 13
|
||||
#define SCREENSPACE_X 58
|
||||
#define FALL_ACCEL 3
|
||||
#define FALL_MAX 33
|
||||
|
||||
#define TILE_MIDX 7
|
||||
#define FIRST_ONSCREEN_COLUMN 5
|
||||
#define FRAME_THIN 0x20
|
||||
|
||||
static const int16_t y_land[5] = {-8, 55, 118, 181, 244};
|
||||
|
||||
static const int8_t dir_front[2] = {-1, 1}; /* [dir+1]: dir=-1->-1, 0->+1 */
|
||||
static const int8_t dir_behind[2] = {1, -1}; /* [dir+1]: назад по направлению */
|
||||
static const int16_t x_bump[20] = {
|
||||
-12, 2, 16, 30, 44, 58, 72, 86, 100, 114,
|
||||
128, 142, 156, 170, 184, 198, 212, 226, 240, 254
|
||||
};
|
||||
/* wall_type(tile): gate/doortop=1, mirror=2, chomper=3, wall=4, иначе 0. */
|
||||
static const int8_t wall_dl[6] = {0, 10, 0, -1, 0, 0}; /* wall_dist_from_left */
|
||||
static const int8_t wall_dr[6] = {0, 0, 10, 13, 0, 0}; /* wall_dist_from_right */
|
||||
@@ -372,7 +367,7 @@ static int dist_from_wall_forward(uint8_t tiletype, int8_t tcol)
|
||||
uint8_t type = wall_type(tiletype);
|
||||
int coll_left, cx;
|
||||
if (type == 0) return 127;
|
||||
coll_left = x_bump[tcol + FIRST_ONSCREEN_COLUMN] + TILE_MIDX;
|
||||
coll_left = pop_x_bump[tcol + FIRST_ONSCREEN_COLUMN] + TILE_MIDX;
|
||||
cx = char_front_coll();
|
||||
if (Kid.direction < 0) /* лицом влево */
|
||||
return cx - (coll_left + TILE_RIGHTX - wall_dr[type]);
|
||||
@@ -428,7 +423,7 @@ static uint8_t fell_on_spikes(void)
|
||||
static void land(void)
|
||||
{
|
||||
uint8_t seq;
|
||||
Kid.y = (uint8_t)y_land[Kid.curr_row + 1];
|
||||
Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1];
|
||||
if (fell_on_spikes()) return; /* упал на вредные пики — смерть */
|
||||
/* к краю пола — чуть назад (как оригинал) */
|
||||
if (!tile_is_floor(get_tile_infrontof_char()) && distance_to_edge_weight() < 3)
|
||||
@@ -523,7 +518,7 @@ static void check_grab(void)
|
||||
uint8_t old_x;
|
||||
if (!pop_ctrl_shift_held()) return; /* Shift не зажат */
|
||||
if ((uint8_t)Kid.fall_y >= 32) return; /* падает слишком быстро */
|
||||
if ((uint16_t)y_land[Kid.curr_row + 1] > (uint16_t)(Kid.y + 25)) return;
|
||||
if ((uint16_t)pop_y_land[Kid.curr_row + 1] > (uint16_t)(Kid.y + 25)) return;
|
||||
old_x = Kid.x;
|
||||
Kid.x = (uint8_t)char_dx_forward(-8);
|
||||
determine_col();
|
||||
@@ -532,7 +527,7 @@ static void check_grab(void)
|
||||
determine_col();
|
||||
} else {
|
||||
Kid.x = (uint8_t)char_dx_forward((int8_t)distance_to_edge_weight());
|
||||
Kid.y = (uint8_t)y_land[Kid.curr_row + 1];
|
||||
Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1];
|
||||
Kid.fall_y = 0;
|
||||
kid_set_seq(SEQ_15_GRAB_LEDGE_MIDAIR);
|
||||
play_seq();
|
||||
@@ -544,8 +539,8 @@ static void check_grab(void)
|
||||
static void do_fall(void)
|
||||
{
|
||||
uint8_t nrow = (uint8_t)(Kid.curr_row + 1);
|
||||
if (nrow > 4) nrow = 4; /* защита y_land[] от выхода */
|
||||
if ((uint16_t)y_land[nrow] > (uint16_t)Kid.y) {
|
||||
if (nrow > 4) nrow = 4; /* защита pop_y_land[] от выхода */
|
||||
if ((uint16_t)pop_y_land[nrow] > (uint16_t)Kid.y) {
|
||||
check_grab(); /* ещё летит — попытка зацепа */
|
||||
} else {
|
||||
if (get_tile_at_char() == TILE_WALL)
|
||||
@@ -905,11 +900,11 @@ static void bumped_floor(void)
|
||||
uint8_t frame;
|
||||
/* Оригинал сравнивает БЕЗЗНАКОВО: если персонаж НИЖЕ уровня пола,
|
||||
* разность заворачивается в большое число и тоже даёт «падать». */
|
||||
if ((uint16_t)(y_land[Kid.curr_row + 1] - (int16_t)Kid.y) >= 15) {
|
||||
if ((uint16_t)(pop_y_land[Kid.curr_row + 1] - (int16_t)Kid.y) >= 15) {
|
||||
bumped_fall(); /* высоко над полом — в воздухе */
|
||||
return;
|
||||
}
|
||||
Kid.y = (uint8_t)y_land[Kid.curr_row + 1]; /* ПРИЖАТЬ к полу */
|
||||
Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1]; /* ПРИЖАТЬ к полу */
|
||||
if (Kid.fall_y >= 22) { /* влетел быстро — только отжать */
|
||||
Kid.x = (uint8_t)char_dx_forward(-5);
|
||||
return;
|
||||
@@ -947,7 +942,7 @@ static void check_bumped(void)
|
||||
* hang->hang_fall->seq_11 (правильное приземление). */
|
||||
if (Kid.frame >= 87 && Kid.frame < 100) return;
|
||||
/* Вне рядов комнаты (падение мимо пола): get_tile даёт WALL, а
|
||||
* dist_from_wall_forward/x_bump[] — мусор с большим отриц. сдвигом →
|
||||
* dist_from_wall_forward/pop_x_bump[] — мусор с большим отриц. сдвигом →
|
||||
* underflow X и уход в стену. fell_out ловит do_fall. */
|
||||
if (Kid.curr_row < 0 || Kid.curr_row > 2) return;
|
||||
/* seg004 check_collisions: на кадрах разворота коллизии НЕ считаются
|
||||
@@ -978,7 +973,7 @@ static void check_bumped(void)
|
||||
{
|
||||
uint8_t f = 0, prev, need;
|
||||
if (wt) {
|
||||
int coll_left = x_bump[tcol + FIRST_ONSCREEN_COLUMN] + TILE_MIDX;
|
||||
int coll_left = pop_x_bump[tcol + FIRST_ONSCREEN_COLUMN] + TILE_MIDX;
|
||||
int lw = wall_dl[wt] + coll_left; /* get_left_wall_xpos */
|
||||
int rw = coll_left - wall_dr[wt] + TILE_RIGHTX; /* get_right_wall_xpos */
|
||||
int e = char_x_forward_edge(), wh = ((int)kid_fp_width() + 1) >> 1;
|
||||
@@ -1157,7 +1152,7 @@ static void fell_on_your_head(void)
|
||||
uint8_t frame = Kid.frame, action = Kid.action;
|
||||
if ((frame < 5 || frame >= 15) &&
|
||||
(action < ACT_HANGCLIMB || action == ACT_TURN)) {
|
||||
Kid.y = (uint8_t)y_land[Kid.curr_row + 1];
|
||||
Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1];
|
||||
pop_kid_hurt = 1; /* hitp_delta<0 → draw_hurt_splash */
|
||||
if (take_hp(1)) {
|
||||
kid_set_seq(SEQ_22_CRUSHED);
|
||||
@@ -1269,8 +1264,7 @@ void pop_loose_tick(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* y_to_row_mod4 (seg006): ряд по y с оборотом mod4 (TILE_SIZEY=63). */
|
||||
static int8_t y_to_row(int16_t y) { return (int8_t)(((y + 60) / 63) % 4 - 1); }
|
||||
|
||||
|
||||
/* ---- clip_char (seg006:1749), первый блок: обрезка спрайта СВЕРХУ ----- *
|
||||
* Оригинал перед add_objtable кладёт в objtable прямоугольник клипа; блиттер
|
||||
@@ -1299,7 +1293,7 @@ int pop_clip_char_top(int obj_x, int obj_y, uint16_t w, uint16_t h)
|
||||
xr = xl + wh; /* char_x_right */
|
||||
top_y = obj_y - (int)h + 1; /* char_top_y */
|
||||
if (top_y >= 192) top_y = 0; /* весь спрайт ниже комнаты */
|
||||
trow = y_to_row((int16_t)top_y); /* char_top_row */
|
||||
trow = pop_y_to_row((int16_t)top_y); /* char_top_row */
|
||||
cL = get_tile_div_mod(xl); if (cL < 0) cL = 0;
|
||||
cR = get_tile_div_mod(xr); if (cR > 9) cR = 9;
|
||||
|
||||
@@ -1337,13 +1331,13 @@ static void check_leave_below(void)
|
||||
Kid.action != ACT_MIDAIR &&
|
||||
(int8_t)Kid.y < 10 && (int8_t)Kid.y > -16) {
|
||||
Kid.y = (uint8_t)(Kid.y + 189);
|
||||
Kid.curr_row = y_to_row((int16_t)Kid.y);
|
||||
Kid.curr_row = pop_y_to_row((int16_t)Kid.y);
|
||||
pop_leave_dir = 3;
|
||||
return;
|
||||
}
|
||||
if (Kid.y >= 211) {
|
||||
Kid.y = (uint8_t)(Kid.y - 189);
|
||||
Kid.curr_row = y_to_row((int16_t)Kid.y);
|
||||
Kid.curr_row = pop_y_to_row((int16_t)Kid.y);
|
||||
pop_fell_out = 1;
|
||||
}
|
||||
}
|
||||
@@ -1429,8 +1423,8 @@ static int is_spike_harmful(uint8_t tilepos)
|
||||
static void spiked(uint8_t tilepos)
|
||||
{
|
||||
pop_trob_modif(g_room)[tilepos] = 0xFF;
|
||||
Kid.y = (uint8_t)y_land[Kid.curr_row + 1];
|
||||
Kid.x = (uint8_t)(x_bump[Kid.curr_col + FIRST_ONSCREEN_COLUMN] + 10);
|
||||
Kid.y = (uint8_t)pop_y_land[Kid.curr_row + 1];
|
||||
Kid.x = (uint8_t)(pop_x_bump[Kid.curr_col + FIRST_ONSCREEN_COLUMN] + 10);
|
||||
Kid.x = (uint8_t)char_dx_forward(8);
|
||||
Kid.fall_y = 0;
|
||||
take_hp(100); /* (TODO: sound_48_spiked) */
|
||||
|
||||
Reference in New Issue
Block a user