#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 ));
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 ));
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,
};
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;
}
/* 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;
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);
}
#ifndef INCLUDED_COLLISION_H
#define INCLUDED_COLLISION_H
+#include "moveable.h"
#include "jumpnrun.h"
#include "../util/rectangle.h"
#include <stdbool.h>
-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
#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" }
{ 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) {
(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;
}
}
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
#include "../ui/sprite.h"
#include "../util/rectangle.h"
+#include "moveable.h"
#include "tiles.h"
struct jumpnrun_game_state;
size_t animation_length;
badge_sprite const *animation_frames;
+ vec2d extent;
+ rectangle hitbox;
vec2d spawn_inertia;
void (*collision_tiles)(struct jumpnrun_enemy *self,
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,
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
#include "../ui/display.h"
#include "../ui/event.h"
#include "../ui/sprite.h"
+#include "../util/util.h"
#include <assert.h>
#include <math.h>
#include <stddef.h>
#include <stdio.h>
-#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);
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" },
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) {
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 {
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;
}
}
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);
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);
}
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;
}
}
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();
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;
#include "levels.h"
#include "tiles.h"
-#include "../util/fixed_point.h"
-#include "../util/rectangle.h"
#include "../ui/sprite.h"
+#include "../util/util.h"
#include <stdbool.h>
#include <stddef.h>
};
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];
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__
--- /dev/null
+#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
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; }
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); }
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) {