From 4cb2d309b35bc7acc33483bdcd0af2a749206369 Mon Sep 17 00:00:00 2001 From: Wintermute Date: Sun, 13 Oct 2013 23:00:48 +0200 Subject: [PATCH] Major refactoring. Hitboxes. --- badge/jumpnrun/collision.c | 47 +++++++------ badge/jumpnrun/collision.h | 15 ++--- badge/jumpnrun/enemies.c | 127 ++++++++++++++++++++++-------------- badge/jumpnrun/enemies.h | 31 +++++---- badge/jumpnrun/jumpnrun.c | 110 ++++++++++++++----------------- badge/jumpnrun/jumpnrun.h | 17 ++--- badge/jumpnrun/level_load.c | 17 +++-- badge/jumpnrun/moveable.h | 18 +++++ badge/util/fixed_point.h | 3 + badge/util/rectangle.h | 11 +++- 10 files changed, 217 insertions(+), 179 deletions(-) create mode 100644 badge/jumpnrun/moveable.h diff --git a/badge/jumpnrun/collision.c b/badge/jumpnrun/collision.c index 66b6e2b..34ab099 100644 --- a/badge/jumpnrun/collision.c +++ b/badge/jumpnrun/collision.c @@ -1,33 +1,30 @@ #include "collision.h" -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof*(arr)) - -void collision_displace(vec2d *desired_pos, - rectangle const *current, - rectangle const *obstacle, - vec2d *inertia, - bool *touching_ground) { - rectangle desired = *current; +void collision_displace(vec2d *desired_pos, + jumpnrun_moveable *current, + rectangle const *obstacle, + vec2d *inertia_mod) { + rectangle desired = current->current_box; rectangle_move_to(&desired, *desired_pos); if(!rectangle_intersect(obstacle, &desired)) { return; } - fixed_point x = FIXED_POINT(1000, 0), y = FIXED_POINT(1000, 0); + fixed_point x = FIXED_INT(1000), y = FIXED_INT(1000); fixed_point dx = desired_pos->x, dy = desired_pos->y; bool bottom_collision = false; if(fixed_point_le(rectangle_top ( obstacle), rectangle_top(&desired)) && fixed_point_gt(rectangle_bottom( obstacle), rectangle_top(&desired)) && - fixed_point_lt(rectangle_top (&desired ), rectangle_top( current))) { + fixed_point_lt(rectangle_top (&desired ), rectangle_top(¤t->current_box))) { y = fixed_point_sub(rectangle_bottom(obstacle), rectangle_top(&desired)); dy = rectangle_bottom(obstacle); } else if(fixed_point_gt(rectangle_bottom( obstacle), rectangle_bottom(&desired)) && fixed_point_le(rectangle_top ( obstacle), rectangle_bottom(&desired)) && - fixed_point_gt(rectangle_top (&desired ), rectangle_top ( current))) { + fixed_point_gt(rectangle_top (&desired ), rectangle_top (¤t->current_box))) { y = fixed_point_sub(rectangle_bottom(&desired ), rectangle_top ( obstacle)); dy = fixed_point_sub(rectangle_top ( obstacle), rectangle_height(&desired )); @@ -38,14 +35,14 @@ void collision_displace(vec2d *desired_pos, if(fixed_point_le(rectangle_left ( obstacle), rectangle_left(&desired)) && fixed_point_gt(rectangle_right( obstacle), rectangle_left(&desired)) && - fixed_point_lt(rectangle_left (&desired ), rectangle_left( current))) { + fixed_point_lt(rectangle_left (&desired ), rectangle_left(¤t->current_box))) { x = fixed_point_sub(rectangle_right(obstacle), rectangle_left(&desired)); dx = rectangle_right(obstacle); } else if(fixed_point_gt(rectangle_right( obstacle), rectangle_right(&desired)) && fixed_point_le(rectangle_left ( obstacle), rectangle_right(&desired)) && - fixed_point_gt(rectangle_left (&desired ), rectangle_left ( current))) { + fixed_point_gt(rectangle_left (&desired ), rectangle_left (¤t->current_box))) { x = fixed_point_sub(rectangle_right(&desired ), rectangle_left ( obstacle)); dx = fixed_point_sub(rectangle_left ( obstacle), rectangle_width(&desired )); @@ -57,23 +54,22 @@ void collision_displace(vec2d *desired_pos, desired_pos->y = dy; } else if(fixed_point_gt(x, y)) { desired_pos->y = dy; - inertia->y = FIXED_POINT(0, 0); + inertia_mod->y = FIXED_INT(0); - *touching_ground = bottom_collision; + current->touching_ground = bottom_collision; } else { desired_pos->x = dx; - inertia->x = FIXED_POINT(0, 0); + inertia_mod->x = FIXED_INT(0); } return; } void collisions_tiles_displace(vec2d *desired_position, - rectangle const *current, + jumpnrun_moveable *thing, jumpnrun_level const *lv, jumpnrun_tile_range const *visible_tiles, - vec2d *inertia, - bool *touching_ground) + vec2d *inertia_mod) { int collision_tile[] = { -1, -1, -1, -1, -1, -1, @@ -81,11 +77,11 @@ void collisions_tiles_displace(vec2d *desired_position, }; static int const collision_order[] = { 7, 1, 3, 5, 6, 8, 0, 2 }; - vec2d midpoint = rectangle_mid(current); + vec2d midpoint = rectangle_mid(&thing->current_box); jumpnrun_tile_position midtile_pos = { - fixed_point_cast_int(fixed_point_div(midpoint.x, FIXED_POINT(JUMPNRUN_TILE_PIXEL_WIDTH , 0))), - fixed_point_cast_int(fixed_point_div(midpoint.y, FIXED_POINT(JUMPNRUN_TILE_PIXEL_HEIGHT, 0))) + fixed_point_cast_int(fixed_point_div(midpoint.x, FIXED_INT(JUMPNRUN_TILE_PIXEL_WIDTH ))), + fixed_point_cast_int(fixed_point_div(midpoint.y, FIXED_INT(JUMPNRUN_TILE_PIXEL_HEIGHT))) }; int tile; @@ -128,9 +124,8 @@ void collisions_tiles_displace(vec2d *desired_position, } /* collision: sort by priority (top/bottom, left/right, then diagonal) */ - *touching_ground = false; + thing->touching_ground = false; - // printf("mid: %d, %d\n", midtile_pos.x, midtile_pos.y); for(size_t collision_index = 0; collision_index < ARRAY_SIZE(collision_order); ++collision_index) { if(collision_tile[collision_order[collision_index]] == -1) { continue; @@ -138,6 +133,8 @@ void collisions_tiles_displace(vec2d *desired_position, rectangle tile_rect = rect_from_tile(&lv->tiles[collision_tile[collision_order[collision_index]]]); - collision_displace(desired_position, current, &tile_rect, inertia, touching_ground); + collision_displace(desired_position, thing, &tile_rect, inertia_mod); } + + rectangle_move_to(&thing->current_box, *desired_position); } diff --git a/badge/jumpnrun/collision.h b/badge/jumpnrun/collision.h index 2ae4e10..65016e9 100644 --- a/badge/jumpnrun/collision.h +++ b/badge/jumpnrun/collision.h @@ -1,21 +1,20 @@ #ifndef INCLUDED_COLLISION_H #define INCLUDED_COLLISION_H +#include "moveable.h" #include "jumpnrun.h" #include "../util/rectangle.h" #include -void collision_displace(vec2d *desired_pos, - rectangle const *current, - rectangle const *obstacle, - vec2d *inertia_mod, - bool *touching_ground); +void collision_displace(vec2d *desired_pos, + jumpnrun_moveable *current, + rectangle const *obstacle, + vec2d *inertia_mod); void collisions_tiles_displace(vec2d *desired_position, - rectangle const *current, + jumpnrun_moveable *thing, jumpnrun_level const *level, jumpnrun_tile_range const *visible_tiles, - vec2d *inertia_mod, - bool *touching_ground); + vec2d *inertia_mod); #endif diff --git a/badge/jumpnrun/enemies.c b/badge/jumpnrun/enemies.c index 70461b6..3cdd7cf 100644 --- a/badge/jumpnrun/enemies.c +++ b/badge/jumpnrun/enemies.c @@ -4,8 +4,6 @@ #include "tiles.h" #include "jumpnrun.h" -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof*(arr)) - static badge_sprite const anim_cat[] = { { 8, 5, (uint8_t const *) "\xc7\x3f\xce\x38\x11" }, { 8, 5, (uint8_t const *) "\xd7\x7d\xc6\x19\x25" } @@ -28,27 +26,40 @@ static badge_sprite const anim_kaninchen[] = { { 7, 5, (uint8_t const *) "\x60\x30\xbe\x31\x01" } }; +static void enemy_animation_advance(jumpnrun_enemy *enemy) { + ++enemy->base.tick_minor; + if(enemy->base.tick_minor == enemy->type->animation_ticks_per_frame) { + enemy->base.tick_minor = 0; + + ++enemy->base.anim_frame; + if(enemy->base.anim_frame >= enemy->type->animation_length) { + enemy->base.anim_frame = 0; + } + } +} + void jumpnrun_process_enemy(jumpnrun_enemy *self, badge_framebuffer *fb, struct jumpnrun_game_state *state, struct jumpnrun_level *lv, - struct jumpnrun_tile_range const *visible_tiles) { - int const spawn_margin = 1 + self->type->animation_frames[self->current_frame].width; + struct jumpnrun_tile_range const *visible_tiles, + vec2d *player_inertia_mod) { + int const spawn_margin = 1 + self->type->animation_frames[self->base.anim_frame].width; if(self->flags & JUMPNRUN_ENEMY_SPAWNED) { - if(fixed_point_lt(self->current_pos.x, FIXED_POINT(state->left - spawn_margin, 0)) || - fixed_point_gt(self->current_pos.x, FIXED_POINT(state->left + BADGE_DISPLAY_WIDTH + spawn_margin, 0)) || - fixed_point_cast_int(self->current_pos.y) > BADGE_DISPLAY_HEIGHT) { + if(fixed_point_lt(rectangle_left(enemy_box(self)), FIXED_POINT(state->left - spawn_margin, 0)) || + fixed_point_gt(rectangle_left(enemy_box(self)), FIXED_POINT(state->left + BADGE_DISPLAY_WIDTH + spawn_margin, 0)) || + fixed_point_gt(rectangle_top (enemy_box(self)), FIXED_POINT(BADGE_DISPLAY_HEIGHT , 0))) { self->flags &= ~JUMPNRUN_ENEMY_SPAWNED; } else { - self->type->game_tick(self, state, lv, visible_tiles); + self->type->game_tick(self, state, lv, visible_tiles, player_inertia_mod); - if(state->tick_minor == 0) { + if(fb) { badge_framebuffer_blt(fb, - fixed_point_cast_int(self->current_pos.x) - state->left, - fixed_point_cast_int(self->current_pos.y), - &self->type->animation_frames[self->current_frame], - fixed_point_lt(self->inertia.x, FIXED_POINT(0, 0)) ? 0 : BADGE_BLT_MIRRORED); + fixed_point_cast_int(rectangle_left(enemy_box(self))) - state->left, + fixed_point_cast_int(rectangle_top (enemy_box(self))), + enemy_sprite(self), + enemy_render_flags(self)); } } } else if(self->flags & JUMPNRUN_ENEMY_UNAVAILABLE) { @@ -61,11 +72,13 @@ void jumpnrun_process_enemy(jumpnrun_enemy *self, (fixed_point_lt(self->spawn_pos.x, FIXED_POINT(state->left + BADGE_DISPLAY_WIDTH + spawn_margin, 0)) && fixed_point_gt(self->spawn_pos.x, FIXED_POINT(state->left + BADGE_DISPLAY_WIDTH, 0)))) { // enemy unspawned, available and in spawn zone. - self->flags |= JUMPNRUN_ENEMY_SPAWNED | JUMPNRUN_ENEMY_UNAVAILABLE; - self->current_pos = self->spawn_pos; - self->inertia = self->type->spawn_inertia; - self->current_frame = 0; - self->tick_counter = 0; + self->flags |= JUMPNRUN_ENEMY_SPAWNED | JUMPNRUN_ENEMY_UNAVAILABLE; + self->base.current_box = rectangle_new(self->spawn_pos, self->type->extent); + self->base.inertia = self->type->spawn_inertia; + self->base.anim_frame = 0; + self->base.tick_minor = 0; + self->base.touching_ground = false; + self->base.jumpable_frames = 0; } } @@ -73,78 +86,94 @@ void enemy_collision_tiles_bounce_horiz(jumpnrun_enemy *self, vec2d *desired_position, jumpnrun_level *lv, jumpnrun_tile_range const *visible_tiles) { - rectangle rect_self = rect_from_enemy(self); - vec2d inertia_copy = self->inertia; - bool touching_ground = false; + vec2d inertia_mod = self->base.inertia; collisions_tiles_displace(desired_position, - &rect_self, + &self->base, lv, visible_tiles, - &inertia_copy, - &touching_ground); + &inertia_mod); - if(fixed_point_ne(inertia_copy.x, self->inertia.x)) { - self->inertia.x = fixed_point_neg(self->inertia.x); + if(fixed_point_ne(inertia_mod.x, self->base.inertia.x)) { + self->base.inertia.x = fixed_point_neg(self->base.inertia.x); } } void enemy_collision_player_jumpable(jumpnrun_enemy *self, - jumpnrun_game_state *state) + jumpnrun_game_state *state, + vec2d *player_inertia_mod) { - rectangle rect_self = rect_from_enemy(self); - rectangle rect_hacker = hacker_rect_current(state); + rectangle rect_self = enemy_hitbox(self); - if(rectangle_intersect(&rect_self, &rect_hacker)) { - if(fixed_point_gt(state->inertia.y, FIXED_POINT(0, 0))) { + if(rectangle_intersect(&rect_self, &state->player.current_box)) { + if(fixed_point_gt(state->player.inertia.y, FIXED_POINT(0, 0))) { self->flags &= ~JUMPNRUN_ENEMY_SPAWNED; - state->inertia_mod.y = FIXED_POINT(0, -250); - state->jumpable_frames = 12; + player_inertia_mod->y = FIXED_POINT(0, -250); + state->player.jumpable_frames = 12; } else { state->status = JUMPNRUN_DEAD; } } } -void enemy_tick_cat(jumpnrun_enemy *self, - jumpnrun_game_state *state, - jumpnrun_level *lv, - jumpnrun_tile_range const *visible_tiles) { - int screenpos = fixed_point_cast_int(self->current_pos.x); +void enemy_tick_cat(jumpnrun_enemy *self, + jumpnrun_game_state *state, + jumpnrun_level *lv, + jumpnrun_tile_range const *visible_tiles, + vec2d *player_inertia_mod) { + int screenpos = fixed_point_cast_int(rectangle_left(&self->base.current_box)); if(screenpos + JUMPNRUN_MAX_SPAWN_MARGIN < state->left || screenpos >= state->left + BADGE_DISPLAY_WIDTH + JUMPNRUN_MAX_SPAWN_MARGIN) { return; } - jumpnrun_passive_movement(&self->inertia); + jumpnrun_passive_movement(&self->base.inertia); - vec2d new_pos = vec2d_add(self->current_pos, self->inertia); + vec2d new_pos = vec2d_add(enemy_position(self), self->base.inertia); self->type->collision_tiles(self, &new_pos, lv, visible_tiles); - self->type->collision_player(self, state); - self->current_pos = new_pos; + self->type->collision_player(self, state, player_inertia_mod); + rectangle_move_to(&self->base.current_box, new_pos); - self->tick_counter = (self->tick_counter + 1) % self->type->animation_ticks_per_frame; - if(self->tick_counter == 0) { - self->current_frame = (self->current_frame + 1) % self->type->animation_length; - } + enemy_animation_advance(self); } jumpnrun_enemy_type const jumpnrun_enemy_type_data[JUMPNRUN_ENEMY_TYPE_COUNT] = { { 16, ARRAY_SIZE(anim_cat), anim_cat, - { FIXED_POINT_I(0, -100), FIXED_POINT_I(0, 0) }, + { + FIXED_INT_I(8), FIXED_INT_I(5) + }, { + { FIXED_INT_I(0), FIXED_INT_I(0) }, + { FIXED_INT_I(8), FIXED_INT_I(5) } + }, { + FIXED_POINT_I(0, -100), FIXED_INT_I(0) + }, enemy_collision_tiles_bounce_horiz, enemy_collision_player_jumpable, enemy_tick_cat }, { 12, ARRAY_SIZE(anim_mushroom), anim_mushroom, - { FIXED_POINT_I(0, -50), FIXED_POINT_I(0, 0) }, + { + FIXED_INT_I(7), FIXED_INT_I(7) + }, { + { FIXED_INT_I(0), FIXED_INT_I(0) }, + { FIXED_INT_I(7), FIXED_INT_I(7) } + }, { + FIXED_POINT_I(0, -50), FIXED_INT_I(0) + }, enemy_collision_tiles_bounce_horiz, enemy_collision_player_jumpable, enemy_tick_cat }, { 9, ARRAY_SIZE(anim_kaninchen), anim_kaninchen, - { FIXED_POINT_I(0, -80), FIXED_POINT_I(0, 0) }, + { + FIXED_INT_I(7), FIXED_INT_I(5) + }, { + { FIXED_INT_I(1), FIXED_INT_I(2) }, + { FIXED_INT_I(6), FIXED_INT_I(3) } + }, { + FIXED_POINT_I(0, -80), FIXED_POINT_I(0, 0) + }, enemy_collision_tiles_bounce_horiz, enemy_collision_player_jumpable, enemy_tick_cat diff --git a/badge/jumpnrun/enemies.h b/badge/jumpnrun/enemies.h index cb88647..64348cb 100644 --- a/badge/jumpnrun/enemies.h +++ b/badge/jumpnrun/enemies.h @@ -4,6 +4,7 @@ #include "../ui/sprite.h" #include "../util/rectangle.h" +#include "moveable.h" #include "tiles.h" struct jumpnrun_game_state; @@ -17,6 +18,8 @@ typedef struct jumpnrun_enemy_type { size_t animation_length; badge_sprite const *animation_frames; + vec2d extent; + rectangle hitbox; vec2d spawn_inertia; void (*collision_tiles)(struct jumpnrun_enemy *self, @@ -24,29 +27,28 @@ typedef struct jumpnrun_enemy_type { struct jumpnrun_level *lv, struct jumpnrun_tile_range const *visible_tiles); void (*collision_player)(struct jumpnrun_enemy *self, - struct jumpnrun_game_state *state); + struct jumpnrun_game_state *state, + vec2d *player_inertia_mod); void (*game_tick)(struct jumpnrun_enemy *self, struct jumpnrun_game_state *state, struct jumpnrun_level *lv, - struct jumpnrun_tile_range const *visible_tiles); + struct jumpnrun_tile_range const *visible_tiles, + vec2d *player_inertia_mod); } jumpnrun_enemy_type; typedef struct jumpnrun_enemy { - vec2d spawn_pos; - vec2d current_pos; - vec2d inertia; - unsigned flags; - unsigned tick_counter; - unsigned current_frame; + jumpnrun_moveable base; + vec2d spawn_pos; + unsigned flags; jumpnrun_enemy_type const *type; } jumpnrun_enemy; -static inline rectangle rect_from_enemy(jumpnrun_enemy const *enemy) { - badge_sprite const *cur_sprite = &enemy->type->animation_frames[(enemy->tick_counter / enemy->type->animation_ticks_per_frame) % enemy->type->animation_length]; - rectangle r = { enemy->current_pos, { FIXED_POINT(cur_sprite->width, 0), FIXED_POINT(cur_sprite->height, 0) } }; - return r; -} +static inline rectangle const *enemy_box (jumpnrun_enemy const *enemy) { return &enemy->base.current_box ; } +static inline vec2d enemy_position (jumpnrun_enemy const *enemy) { return enemy->base.current_box.pos; } +static inline rectangle enemy_hitbox (jumpnrun_enemy const *enemy) { rectangle r = enemy->type->hitbox; rectangle_move_rel(&r, enemy_position(enemy)); return r; } +static inline badge_sprite const *enemy_sprite (jumpnrun_enemy const *enemy) { return &enemy->type->animation_frames[enemy->base.anim_frame]; } +static inline uint8_t enemy_render_flags(jumpnrun_enemy const *enemy) { return fixed_point_lt(enemy->base.inertia.x, FIXED_POINT(0, 0)) ? 0 : BADGE_BLT_MIRRORED; } enum { JUMPNRUN_ENEMY_SPAWNED = 1, @@ -67,5 +69,6 @@ void jumpnrun_process_enemy(jumpnrun_enemy *self, badge_framebuffer *fb, struct jumpnrun_game_state *state, struct jumpnrun_level *lv, - struct jumpnrun_tile_range const *visible_tiles); + struct jumpnrun_tile_range const *visible_tiles, + vec2d *player_inertia_mod); #endif diff --git a/badge/jumpnrun/jumpnrun.c b/badge/jumpnrun/jumpnrun.c index 3f950a7..380cc1e 100644 --- a/badge/jumpnrun/jumpnrun.c +++ b/badge/jumpnrun/jumpnrun.c @@ -5,14 +5,13 @@ #include "../ui/display.h" #include "../ui/event.h" #include "../ui/sprite.h" +#include "../util/util.h" #include #include #include #include -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof*(arr)) - static vec2d const gravity = { FIXED_POINT_I(0, 0), FIXED_POINT_I(0, 56) }; static vec2d const move_max = { FIXED_POINT_I(0, 600), FIXED_POINT_I(1, 300) }; static fixed_point const accel_horiz = FIXED_POINT_I(0, 50); @@ -20,6 +19,8 @@ static fixed_point const accel_vert = FIXED_POINT_I(0, 167); static fixed_point const drag_factor = FIXED_POINT_I(0, 854); static fixed_point const speed_jump_x = FIXED_POINT_I(0, 600); +static vec2d const hacker_extent = { FIXED_INT_I(5), FIXED_INT_I(8) }; + static badge_sprite const anim_hacker[] = { { 5, 8, (uint8_t const *) "\x1c\xff\xfd\x04\x04" }, { 5, 8, (uint8_t const *) "\x1c\xff\x3d\xc4\x04" }, @@ -53,23 +54,14 @@ static inline int imax(int x, int y) { static inline fixed_point hacker_left (vec2d const *pos, jumpnrun_game_state const *state) { (void) state; return pos->x; } static inline fixed_point hacker_top (vec2d const *pos, jumpnrun_game_state const *state) { (void) state; return pos->y; } -static inline fixed_point hacker_right (vec2d const *pos, jumpnrun_game_state const *state) { return fixed_point_add(hacker_left(pos, state), FIXED_POINT(anim_hacker[state->anim_frame].width , 0)); } -static inline fixed_point hacker_bottom(vec2d const *pos, jumpnrun_game_state const *state) { return fixed_point_add(hacker_top (pos, state), FIXED_POINT(anim_hacker[state->anim_frame].height, 0)); } - -static inline rectangle hacker_rect(vec2d const *pos, - jumpnrun_game_state const *state) { - return (rectangle) { { hacker_left(pos, state), hacker_top(pos, state) }, { FIXED_POINT(anim_hacker[state->anim_frame].width, 0), FIXED_POINT(anim_hacker[state->anim_frame].height, 0) } }; -} - -rectangle hacker_rect_current(jumpnrun_game_state const *state) { - return hacker_rect(&state->current_pos, state); -} +static inline fixed_point hacker_right (vec2d const *pos, jumpnrun_game_state const *state) { return fixed_point_add(hacker_left(pos, state), hacker_extent.x); } +static inline fixed_point hacker_bottom(vec2d const *pos, jumpnrun_game_state const *state) { return fixed_point_add(hacker_top (pos, state), hacker_extent.y); } int jumpnrun_level_assert_left_side(jumpnrun_game_state const *state) { static int const lmargin = 20; static int const rmargin = 50; - int pos_cur = fixed_point_cast_int(state->current_pos.x); + int pos_cur = fixed_point_cast_int(state->player.current_box.pos.x); int pos_rel = pos_cur - state->left; if(pos_rel < lmargin) { @@ -88,7 +80,7 @@ static int jumpnrun_bsearch_tile(jumpnrun_level const *lv, jumpnrun_game_state c while(len > 0) { int mid = front + len / 2; - if(fixed_point_lt(tile_right(&lv->tiles[mid]), FIXED_POINT(state->left - JUMPNRUN_MAX_SPAWN_MARGIN, 0))) { + if(fixed_point_lt(tile_right(&lv->tiles[mid]), FIXED_INT(state->left - JUMPNRUN_MAX_SPAWN_MARGIN))) { front = mid + 1; len -= len / 2 + 1; } else { @@ -123,56 +115,54 @@ void jumpnrun_passive_movement(vec2d *inertia) static void jumpnrun_apply_movement(jumpnrun_level const *lv, jumpnrun_tile_range const *tilerange, - jumpnrun_game_state *state) { + jumpnrun_game_state *state, + vec2d *inertia_mod) { switch(badge_event_current_input_state() & (BADGE_EVENT_KEY_LEFT | BADGE_EVENT_KEY_RIGHT)) { case BADGE_EVENT_KEY_LEFT: - // state->inertia.x = state->touching_ground ? fixed_point_sub(state->inertia.x, accel_horiz) : fixed_point_neg(speed_jump_x); - state->inertia.x = fixed_point_sub(state->inertia.x, accel_horiz); + // state->player.inertia.x = state->player.touching_ground ? fixed_point_sub(state->player.inertia.x, accel_horiz) : fixed_point_neg(speed_jump_x); + state->player.inertia.x = fixed_point_sub(state->player.inertia.x, accel_horiz); state->anim_direction = BADGE_BLT_MIRRORED; break; case BADGE_EVENT_KEY_RIGHT: - // state->inertia.x = state->touching_ground ? fixed_point_add(state->inertia.x, accel_horiz) : speed_jump_x; - state->inertia.x = fixed_point_add(state->inertia.x, accel_horiz); + // state->player.inertia.x = state->player.touching_ground ? fixed_point_add(state->player.inertia.x, accel_horiz) : speed_jump_x; + state->player.inertia.x = fixed_point_add(state->player.inertia.x, accel_horiz); state->anim_direction = 0; break; default: - if(state->touching_ground) { - state->inertia.x = fixed_point_mul(state->inertia.x, drag_factor); + if(state->player.touching_ground) { + state->player.inertia.x = fixed_point_mul(state->player.inertia.x, drag_factor); } //else { - //state->inertia.x = FIXED_POINT(0, 0); + //state->player.inertia.x = FIXED_INT(0); //} break; } - if(state->jumpable_frames == 0) { + if(state->player.jumpable_frames == 0) { // intentionally left blank. } else if(badge_event_current_input_state() & BADGE_EVENT_KEY_BTN_A) { - state->inertia.y = fixed_point_sub(state->inertia.y, accel_vert); - // fixed_point_neg(move_max.y) - --state->jumpable_frames; + state->player.inertia.y = fixed_point_sub(state->player.inertia.y, accel_vert); + --state->player.jumpable_frames; } else { - state->jumpable_frames = 0; + state->player.jumpable_frames = 0; } - jumpnrun_passive_movement(&state->inertia); + jumpnrun_passive_movement(&state->player.inertia); - vec2d new_pos = vec2d_add(state->current_pos, state->inertia); + vec2d new_pos = vec2d_add(state->player.current_box.pos, state->player.inertia); - if(fixed_point_lt(new_pos.x, FIXED_POINT(state->left, 0))) { - new_pos.x = FIXED_POINT(state->left, 0); - state->inertia.x = FIXED_POINT(0, 0); + if(fixed_point_lt(new_pos.x, FIXED_INT(state->left))) { + new_pos.x = FIXED_INT(state->left); + state->player.inertia.x = FIXED_INT(0); } - rectangle hacker_rect_c = hacker_rect(&state->current_pos, state); - collisions_tiles_displace(&new_pos, &hacker_rect_c, lv, tilerange, &state->inertia, &state->touching_ground); - state->inertia_mod = state->inertia; - - state->current_pos = new_pos; + *inertia_mod = state->player.inertia; + collisions_tiles_displace(&new_pos, &state->player, lv, tilerange, inertia_mod); + state->player.inertia = *inertia_mod; - if(fixed_point_gt(state->current_pos.y, FIXED_POINT(BADGE_DISPLAY_HEIGHT, 0))) { + if(fixed_point_gt(state->player.current_box.pos.y, FIXED_INT(BADGE_DISPLAY_HEIGHT))) { state->status = JUMPNRUN_DEAD; } } @@ -181,11 +171,12 @@ void jumpnrun_level_tick(jumpnrun_level *lv, jumpnrun_game_state *state) { jumpnrun_tile_range tilerange = jumpnrun_visible_tiles(lv, state); - jumpnrun_apply_movement(lv, &tilerange, state); + vec2d inertia_mod = state->player.inertia; + jumpnrun_apply_movement(lv, &tilerange, state, &inertia_mod); state->left = jumpnrun_level_assert_left_side(state); - if(state->tick_minor == 0) { + if(state->player.tick_minor == 0) { badge_framebuffer fb; badge_framebuffer_clear(&fb); @@ -201,10 +192,9 @@ void jumpnrun_level_tick(jumpnrun_level *lv, int screenpos = fixed_point_cast_int(lv->items[item].pos.x) - state->left; if(screenpos > -lv->items[item].type->sprite.width && screenpos < BADGE_DISPLAY_WIDTH) { - rectangle hack_rect = hacker_rect(&state->current_pos, state); rectangle item_rect = rect_from_item(&lv->items[item]); - if(rectangle_intersect(&hack_rect, &item_rect)) { + if(rectangle_intersect(&state->player.current_box, &item_rect)) { lv->items[item].type->on_collect(state); } @@ -218,35 +208,35 @@ void jumpnrun_level_tick(jumpnrun_level *lv, for(size_t enemy_ix = 0; enemy_ix < lv->header.enemy_count; ++enemy_ix) { jumpnrun_enemy *enemy = &lv->enemies[enemy_ix]; - jumpnrun_process_enemy(enemy, &fb, state, lv, &tilerange); + jumpnrun_process_enemy(enemy, &fb, state, lv, &tilerange, &inertia_mod); } badge_framebuffer_blt(&fb, - fixed_point_cast_int(state->current_pos.x) - state->left, - fixed_point_cast_int(state->current_pos.y), - &anim_hacker[state->anim_frame], + fixed_point_cast_int(state->player.current_box.pos.x) - state->left, + fixed_point_cast_int(state->player.current_box.pos.y), + &anim_hacker[state->player.anim_frame], state->anim_direction); badge_framebuffer_flush(&fb); - if(!state->touching_ground) { - state->anim_frame = 2; - } else if(fixed_point_gt(fixed_point_abs(state->inertia.x), FIXED_POINT(0, 200))) { - state->anim_frame = (state->anim_frame + 1) % ARRAY_SIZE(anim_hacker); + if(!state->player.touching_ground) { + state->player.anim_frame = 2; + } else if(fixed_point_gt(fixed_point_abs(state->player.inertia.x), FIXED_POINT(0, 200))) { + state->player.anim_frame = (state->player.anim_frame + 1) % ARRAY_SIZE(anim_hacker); } else { - state->anim_frame = 0; + state->player.anim_frame = 0; } } else { for(size_t enemy_ix = 0; enemy_ix < lv->header.enemy_count; ++enemy_ix) { jumpnrun_enemy *enemy = &lv->enemies[enemy_ix]; - jumpnrun_process_enemy(enemy, NULL, state, lv, &tilerange); + jumpnrun_process_enemy(enemy, NULL, state, lv, &tilerange, &inertia_mod); } } - state->inertia = state->inertia_mod; - ++state->tick_minor; - if(state->tick_minor == 3) { - state->tick_minor = 0; + state->player.inertia = inertia_mod; + ++state->player.tick_minor; + if(state->player.tick_minor == 3) { + state->player.tick_minor = 0; } } @@ -258,7 +248,7 @@ uint8_t jumpnrun_play(char const *lvname) { jumpnrun_game_state gs; memset(&gs, 0, sizeof(gs)); - gs.current_pos = lv.start_pos; + gs.player.current_box = rectangle_new(lv.start_pos, hacker_extent); while(gs.status == JUMPNRUN_PLAYING) { badge_event_t ev = badge_event_wait(); @@ -270,8 +260,8 @@ uint8_t jumpnrun_play(char const *lvname) { uint8_t new_state = badge_event_new_input_state(ev); uint8_t new_buttons = new_state & (old_state ^ new_state); - if((new_buttons & BADGE_EVENT_KEY_BTN_A) && gs.touching_ground) { - gs.jumpable_frames = 12; + if((new_buttons & BADGE_EVENT_KEY_BTN_A) && gs.player.touching_ground) { + gs.player.jumpable_frames = 12; } break; diff --git a/badge/jumpnrun/jumpnrun.h b/badge/jumpnrun/jumpnrun.h index 598e8da..2437c36 100644 --- a/badge/jumpnrun/jumpnrun.h +++ b/badge/jumpnrun/jumpnrun.h @@ -6,9 +6,8 @@ #include "levels.h" #include "tiles.h" -#include "../util/fixed_point.h" -#include "../util/rectangle.h" #include "../ui/sprite.h" +#include "../util/util.h" #include #include @@ -26,19 +25,11 @@ enum { }; typedef struct jumpnrun_game_state { - vec2d current_pos; - vec2d inertia; - vec2d inertia_mod; - uint8_t status; - - uint8_t tick_minor; - uint8_t anim_frame; - uint8_t anim_direction; + jumpnrun_moveable player; + uint8_t status; int left; - - bool touching_ground; - uint8_t jumpable_frames; + uint8_t anim_direction; size_t spawned_enemies_counter; size_t spawned_enemies[JUMPNRUN_MAX_SPAWNED_ENEMIES]; diff --git a/badge/jumpnrun/level_load.c b/badge/jumpnrun/level_load.c index 180b33d..a945fc9 100644 --- a/badge/jumpnrun/level_load.c +++ b/badge/jumpnrun/level_load.c @@ -40,13 +40,16 @@ static void jumpnrun_level_make_item(jumpnrun_item *dest, level_thing thing) { static void jumpnrun_level_make_enemy(jumpnrun_enemy *dest, level_thing thing) { dest->type = &jumpnrun_enemy_type_data[thing.type]; - dest->spawn_pos.x = FIXED_POINT(thing.x * JUMPNRUN_TILE_PIXEL_WIDTH , 0); - dest->spawn_pos.y = FIXED_POINT(thing.y * JUMPNRUN_TILE_PIXEL_HEIGHT, 0); - dest->current_pos = dest->spawn_pos; - dest->inertia = dest->type->spawn_inertia; - dest->flags = 0; - dest->tick_counter = 0; - dest->current_frame = 0; + dest->spawn_pos.x = FIXED_POINT(thing.x * JUMPNRUN_TILE_PIXEL_WIDTH , 0); + dest->spawn_pos.y = FIXED_POINT(thing.y * JUMPNRUN_TILE_PIXEL_HEIGHT, 0); + dest->base.current_box = rectangle_new(dest->spawn_pos, dest->type->extent); + dest->base.inertia = dest->type->spawn_inertia; + dest->flags = 0; + dest->base.tick_minor = 0; + dest->base.anim_frame = 0; + dest->base.anim_direction = 0; + dest->base.touching_ground = 0; + dest->base.jumpable_frames = 0; } #ifdef __linux__ diff --git a/badge/jumpnrun/moveable.h b/badge/jumpnrun/moveable.h new file mode 100644 index 0000000..5e7514b --- /dev/null +++ b/badge/jumpnrun/moveable.h @@ -0,0 +1,18 @@ +#ifndef INCLUDED_BADGE_JUMPNRUN_MOVEABLE_H +#define INCLUDED_BADGE_JUMPNRUN_MOVEABLE_H + +#include "../util/util.h" + +typedef struct jumpnrun_moveable { + rectangle current_box; + vec2d inertia; + + uint8_t tick_minor; + uint8_t anim_frame; + uint8_t anim_direction; + + bool touching_ground; + uint8_t jumpable_frames; +} jumpnrun_moveable; + +#endif diff --git a/badge/util/fixed_point.h b/badge/util/fixed_point.h index 05a8c79..8af7e82 100644 --- a/badge/util/fixed_point.h +++ b/badge/util/fixed_point.h @@ -23,12 +23,15 @@ static inline bool fixed_point_eq(fixed_point x, fixed_point y) { return x.data static inline bool fixed_point_ne(fixed_point x, fixed_point y) { return x.data != y.data; } #define FIXED_POINT_I(x, y) { ((x) * 256) + ((y) * 256 / 1000) } +#define FIXED_INT_I(x) FIXED_POINT_I(x, 0) static inline fixed_point FIXED_POINT(unsigned x, unsigned y) { fixed_point r = { ((int) x * 256) + ((int) y * 256 / 1000) }; return r; } +static inline fixed_point FIXED_INT(unsigned x) { return FIXED_POINT(x, 0); } + static inline int fixed_point_cast_int(fixed_point x) { return x.data / 256; } static inline fixed_point fixed_point_min(fixed_point x, fixed_point y) { return fixed_point_lt(x, y) ? x : y; } diff --git a/badge/util/rectangle.h b/badge/util/rectangle.h index 8653e6b..39ba5ca 100644 --- a/badge/util/rectangle.h +++ b/badge/util/rectangle.h @@ -22,6 +22,8 @@ typedef struct { vec2d extent; } rectangle; +static inline rectangle rectangle_new(vec2d pos, vec2d extent) { rectangle r = { pos, extent }; return r; } + static inline fixed_point rectangle_top (rectangle const *r) { return r->pos.y; } static inline fixed_point rectangle_left (rectangle const *r) { return r->pos.x; } static inline fixed_point rectangle_bottom(rectangle const *r) { return fixed_point_add(rectangle_top (r), r->extent.y); } @@ -37,9 +39,12 @@ static inline vec2d rectangle_mid(rectangle const *r) { return v; } -static inline void rectangle_move_to (rectangle *r, vec2d new_pos) { r->pos = new_pos; } -static inline void rectangle_move_to_x(rectangle *r, fixed_point new_x ) { r->pos.x = new_x; } -static inline void rectangle_move_to_y(rectangle *r, fixed_point new_y ) { r->pos.x = new_y; } +static inline void rectangle_move_to (rectangle *r, vec2d new_pos) { r->pos = new_pos; } +static inline void rectangle_move_to_x(rectangle *r, fixed_point new_x ) { r->pos.x = new_x; } +static inline void rectangle_move_to_y(rectangle *r, fixed_point new_y ) { r->pos.x = new_y; } + +static inline void rectangle_move_rel (rectangle *r, vec2d vec ) { r->pos = vec2d_add(r->pos, vec); } +static inline void rectangle_expand (rectangle *r, vec2d extent ) { r->extent = extent; } static inline bool rectangle_intersect(rectangle const *r1, rectangle const *r2) { -- 2.20.1