jumpnrun_moveable *current,
rectangle const *obstacle,
vec2d *inertia_mod) {
- rectangle desired = current->current_box;
+ rectangle desired = current->hitbox;
rectangle_move_to(&desired, *desired_pos);
if(!rectangle_intersect(obstacle, &desired)) {
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(¤t->current_box))) {
+ fixed_point_lt(rectangle_top (&desired ), rectangle_top(¤t->hitbox))) {
coll_y = JUMPNRUN_COLLISION_BOTTOM;
y = fixed_point_sub(rectangle_bottom(obstacle), rectangle_top(&desired));
} 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 (¤t->current_box))) {
+ fixed_point_gt(rectangle_top (&desired ), rectangle_top (¤t->hitbox))) {
coll_y = JUMPNRUN_COLLISION_TOP;
y = fixed_point_sub(rectangle_bottom(&desired ), rectangle_top ( obstacle));
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(¤t->current_box))) {
+ fixed_point_lt(rectangle_left (&desired ), rectangle_left(¤t->hitbox))) {
coll_x = JUMPNRUN_COLLISION_RIGHT;
x = fixed_point_sub(rectangle_right(obstacle), rectangle_left(&desired));
} 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 (¤t->current_box))) {
+ fixed_point_gt(rectangle_left (&desired ), rectangle_left (¤t->hitbox))) {
coll_x = JUMPNRUN_COLLISION_LEFT;
x = fixed_point_sub(rectangle_right(&desired ), rectangle_left ( obstacle));
} else if(fixed_point_gt(x, y)) {
desired_pos->y = dy;
inertia_mod->y = FIXED_INT(0);
- current->touching_ground = bottom_collision;
+
+ if(bottom_collision) {
+ current->flags |= JUMPNRUN_MOVEABLE_TOUCHING_GROUND;
+ } else {
+ current->flags &= ~JUMPNRUN_MOVEABLE_TOUCHING_GROUND;
+ }
+
coll = coll_y;
} else {
desired_pos->x = dx;
};
static int const collision_order[] = { 7, 1, 3, 5, 6, 8, 0, 2 };
- vec2d midpoint = rectangle_mid(&thing->current_box);
+ vec2d midpoint = rectangle_mid(&thing->hitbox);
jumpnrun_tile_position midtile_pos = {
fixed_point_cast_int(fixed_point_div(midpoint.x, FIXED_INT(JUMPNRUN_TILE_PIXEL_WIDTH ))),
/* collision: sort by priority (top/bottom, left/right, then diagonal) */
bool lethal = false;
- thing->touching_ground = false;
+ thing->flags &= ~JUMPNRUN_MOVEABLE_TOUCHING_GROUND;
for(size_t collision_index = 0; collision_index < ARRAY_SIZE(collision_order); ++collision_index) {
if(collision_tile[collision_order[collision_index]] == -1) {
}
}
- rectangle_move_to(&thing->current_box, *desired_position);
+ rectangle_move_to(&thing->hitbox, *desired_position);
return lethal;
}
#include "enemies.h"
#include "collision.h"
+#include "game_state.h"
#include "tiles.h"
#include "jumpnrun.h"
+#include "moveable.h"
+#include "render.h"
static badge_sprite const anim_cat[] = {
{ 8, 5, (uint8_t const *) "\xc7\x3f\xce\x38\x11" },
}
}
+static void enemy_spawn(jumpnrun_enemy *self) {
+ // enemy unspawned, available and in spawn zone.
+ self->base.flags = JUMPNRUN_ENEMY_SPAWNED | JUMPNRUN_ENEMY_UNAVAILABLE;
+ self->base.anim_frame = 0;
+ self->base.tick_minor = 0;
+ self->base.jumpable_frames = 0;
+}
+
+void jumpnrun_enemy_despawn(jumpnrun_enemy *self) {
+ // Despawned enemies are reset to their spawn position, so enemy_in_spawn_area will determine whether the spawn point is in the spawn area.
+ self->base.flags &= ~JUMPNRUN_ENEMY_SPAWNED;
+ self->base.hitbox = rectangle_new(self->spawn_pos, self->type->hitbox.extent);
+ self->base.inertia = self->type->spawn_inertia;
+}
+
+void jumpnrun_enemy_reset (jumpnrun_enemy *self) {
+ jumpnrun_enemy_despawn(self);
+ self->base.flags &= ~JUMPNRUN_ENEMY_UNAVAILABLE;
+}
+
+static void enemy_bounce(jumpnrun_enemy *self) {
+ self->base.inertia.x = fixed_point_neg(self->base.inertia.x);
+}
+
+static inline vec2d enemy_pos_hitbox (jumpnrun_enemy const *self) { return self->base.hitbox.pos; }
+static inline vec2d enemy_pos_display(jumpnrun_enemy const *self) { return vec2d_sub(enemy_pos_hitbox(self), self->type->hitbox.pos); }
+static inline vec2d enemy_pos_desired(jumpnrun_enemy const *self) { return vec2d_add(enemy_pos_hitbox(self), self->base.inertia); }
+
+static inline void enemy_move_to(jumpnrun_enemy *self, vec2d new_pos) {
+ rectangle_move_to(&self->base.hitbox, new_pos);
+}
+
+static inline bool enemy_in_area(jumpnrun_enemy const *self, jumpnrun_game_state *state, int margin) {
+ return
+ fixed_point_gt(rectangle_left (enemy_hitbox(self)), FIXED_INT(jumpnrun_screen_left (state) - margin)) &&
+ fixed_point_lt(rectangle_right(enemy_hitbox(self)), FIXED_INT(jumpnrun_screen_right(state) + margin));
+}
+
+static inline bool enemy_on_screen(jumpnrun_enemy const *self, jumpnrun_game_state *state) {
+ return enemy_in_area(self, state, 0);
+}
+
+static inline bool enemy_in_spawn_area(jumpnrun_enemy const *self, jumpnrun_game_state *state) {
+ return enemy_in_area(self, state, JUMPNRUN_MAX_SPAWN_MARGIN);
+}
+
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,
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(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;
+ // Despawned enemies are reset to their spawn position, so enemy_in_spawn_area will determine whether the spawn point is in the spawn area.
+ if(self->base.flags & JUMPNRUN_ENEMY_SPAWNED) {
+ if(!enemy_in_spawn_area(self, state) || fixed_point_gt(rectangle_top (enemy_hitbox(self)), FIXED_INT(BADGE_DISPLAY_HEIGHT))) {
+ jumpnrun_enemy_despawn(self);
} else {
self->type->move_tick(self, state, lv, visible_tiles, player_inertia_mod);
self->type->collision_shots(self, state);
+ if (fixed_point_lt(self->base.inertia.x, FIXED_INT(0))) { self->base.flags &= ~JUMPNRUN_MOVEABLE_MIRRORED; }
+ else if(fixed_point_ne(self->base.inertia.x, FIXED_INT(0))) { self->base.flags |= JUMPNRUN_MOVEABLE_MIRRORED; }
if(fb) {
- badge_framebuffer_blt(fb,
- 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));
+ jumpnrun_render_enemy(fb, state, self);
}
}
- } else if(self->flags & JUMPNRUN_ENEMY_UNAVAILABLE) {
- if(state->left > fixed_point_cast_int(self->spawn_pos.x) + spawn_margin ||
- state->left + BADGE_DISPLAY_WIDTH + spawn_margin < fixed_point_cast_int(self->spawn_pos.x)) {
- self->flags &= ~JUMPNRUN_ENEMY_UNAVAILABLE;
+ } else if(self->base.flags & JUMPNRUN_ENEMY_UNAVAILABLE) {
+ if(!enemy_in_spawn_area(self, state)) {
+ self->base.flags &= ~JUMPNRUN_ENEMY_UNAVAILABLE;
}
- } else if(fixed_point_gt(self->spawn_pos.x, FIXED_POINT(state->left - spawn_margin, 0)) &&
- fixed_point_lt(self->spawn_pos.x, FIXED_POINT(state->left + BADGE_DISPLAY_WIDTH + spawn_margin, 0))) {
+ } else if(enemy_in_spawn_area(self, state)) {
// enemy unspawned, available and in spawn zone.
- 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;
+ enemy_spawn(self);
}
}
&inertia_mod);
if(killed) {
- self->flags &= ~JUMPNRUN_ENEMY_SPAWNED;
- }
-
- if(fixed_point_ne(inertia_mod.x, self->base.inertia.x)) {
- self->base.inertia.x = fixed_point_neg(self->base.inertia.x);
+ jumpnrun_enemy_despawn(self);
+ } else if(fixed_point_ne(inertia_mod.x, self->base.inertia.x)) {
+ enemy_bounce(self);
}
}
vec2d *player_inertia_mod) {
(void) player_inertia_mod;
- rectangle rect_self = enemy_hitbox(self);
-
- if(rectangle_intersect(&rect_self, &state->player.current_box)) {
- state->status = JUMPNRUN_DEAD;
+ if(rectangle_intersect(enemy_hitbox(self), &state->player.base.hitbox)) {
+ state->player.base.flags |= JUMPNRUN_PLAYER_DEAD;
}
}
jumpnrun_game_state *state,
vec2d *player_inertia_mod)
{
- rectangle rect_self = enemy_hitbox(self);
-
- if(rectangle_intersect(&rect_self, &state->player.current_box)) {
- if(fixed_point_lt(rectangle_top(&state->player.current_box), rectangle_top(&rect_self)) &&
- fixed_point_gt(state->player.inertia.y, FIXED_POINT(0, 0)))
+ if(rectangle_intersect(enemy_hitbox(self), &state->player.base.hitbox)) {
+ if(fixed_point_lt(rectangle_top(&state->player.base.hitbox), rectangle_top(enemy_hitbox(self))) &&
+ fixed_point_gt(state->player.base.inertia.y, FIXED_INT(0)))
{
- self->flags &= ~JUMPNRUN_ENEMY_SPAWNED;
+ jumpnrun_enemy_despawn(self);
player_inertia_mod->y = FIXED_POINT(0, -250);
- state->player.jumpable_frames = 12;
+ state->player.base.jumpable_frames = 12;
} else {
- state->status = JUMPNRUN_DEAD;
+ state->player.base.flags |= JUMPNRUN_PLAYER_DEAD;
}
}
}
void enemy_collision_shots_die(struct jumpnrun_enemy *self,
struct jumpnrun_game_state *state) {
- rectangle rect_self = enemy_hitbox(self);
-
for(uint8_t i = 0; i < JUMPNRUN_MAX_SHOTS; ++i) {
jumpnrun_shot *shot = &state->shots[i];
if(jumpnrun_shot_spawned(shot)) {
- if(rectangle_intersect(&rect_self, &shot->current_box)) {
- self->flags &= ~JUMPNRUN_ENEMY_SPAWNED;
+ if(rectangle_intersect(enemy_hitbox(self), &shot->current_box)) {
+ self->base.flags &= ~JUMPNRUN_ENEMY_SPAWNED;
jumpnrun_shot_despawn(shot);
}
}
void enemy_collision_shots_bounce(struct jumpnrun_enemy *self,
struct jumpnrun_game_state *state) {
- rectangle rect_self = enemy_hitbox(self);
-
for(uint8_t i = 0; i < JUMPNRUN_MAX_SHOTS; ++i) {
jumpnrun_shot *shot = &state->shots[i];
if(jumpnrun_shot_spawned(shot)) {
- if(rectangle_intersect(&rect_self, &shot->current_box)) {
+ if(rectangle_intersect(enemy_hitbox(self), &shot->current_box)) {
if(fixed_point_gt(shot->inertia.x, FIXED_INT(0))) {
- rectangle_move_to_x(&shot->current_box, fixed_point_sub(rectangle_left(&rect_self), rectangle_width(&shot->current_box)));
+ rectangle_move_to_x(&shot->current_box, fixed_point_sub(rectangle_left(enemy_hitbox(self)), rectangle_width(&shot->current_box)));
} else {
- rectangle_move_to_x(&shot->current_box, rectangle_right(&rect_self));
+ rectangle_move_to_x(&shot->current_box, rectangle_right(enemy_hitbox(self)));
}
shot->inertia.x = fixed_point_neg(shot->inertia.x);
(void) state;
}
+static void enemy_tick_common(jumpnrun_enemy *self,
+ jumpnrun_game_state *state,
+ jumpnrun_level *lv,
+ jumpnrun_tile_range const *visible_tiles,
+ vec2d *player_inertia_mod) {
+ vec2d new_pos = enemy_pos_desired(self);
+ self->type->collision_tiles (self, &new_pos, lv, visible_tiles);
+ self->type->collision_player(self, state, player_inertia_mod);
+ enemy_move_to(self, new_pos);
+}
+
void enemy_tick_straight_ahead(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->base.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, player_inertia_mod);
- rectangle_move_to(&self->base.current_box, new_pos);
-
+ enemy_tick_common(self, state, lv, visible_tiles, player_inertia_mod);
enemy_animation_advance(self);
}
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->base.inertia);
+ enemy_tick_common(self, state, lv, visible_tiles, player_inertia_mod);
- 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, player_inertia_mod);
- rectangle_move_to(&self->base.current_box, new_pos);
-
- if(fixed_point_lt(rectangle_right(&state->player.current_box), rectangle_left(enemy_box(self)))) {
+ if(fixed_point_lt(rectangle_right(&state->player.base.hitbox), rectangle_left(enemy_hitbox(self)))) {
self->base.inertia.x = self->type->spawn_inertia.x;
- } else if(fixed_point_gt(rectangle_left(&state->player.current_box), rectangle_right(enemy_box(self)))) {
+ } else if(fixed_point_gt(rectangle_left(&state->player.base.hitbox), rectangle_right(enemy_hitbox(self)))) {
self->base.inertia.x = fixed_point_neg(self->type->spawn_inertia.x);
}
struct jumpnrun_level *lv,
struct 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;
- }
-
- 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, player_inertia_mod);
- rectangle_move_to(&self->base.current_box, new_pos);
+ enemy_tick_common(self, state, lv, visible_tiles, player_inertia_mod);
self->base.inertia.y =
fixed_point_add(fixed_point_add(self->base.inertia.y,
fixed_point_div(self->type->spawn_inertia.y, FIXED_INT(3))),
fixed_point_mul(FIXED_POINT(0, 5),
fixed_point_sub(self->spawn_pos.y,
- enemy_position(self).y)));
+ enemy_pos_display(self).y)));
enemy_animation_advance(self);
}
struct jumpnrun_level *lv,
struct 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;
- }
-
- self->type->collision_tiles(self, &self->base.current_box.pos, lv, visible_tiles);
+ self->type->collision_tiles(self, &self->base.hitbox.pos, lv, visible_tiles);
self->type->collision_player(self, state, player_inertia_mod);
enemy_animation_advance(self);
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->base.inertia);
+ enemy_tick_common(self, state, lv, visible_tiles, player_inertia_mod);
- 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, player_inertia_mod);
- rectangle_move_to(&self->base.current_box, new_pos);
-
- if(self->base.touching_ground) {
+ if(jumpnrun_moveable_touching_ground(&self->base)) {
self->base.inertia.y = self->type->spawn_inertia.y;
}
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->base.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, player_inertia_mod);
- rectangle_move_to(&self->base.current_box, new_pos);
+ enemy_tick_common(self, state, lv, visible_tiles, player_inertia_mod);
if(self->base.tick_minor % self->type->animation_ticks_per_frame == 0) {
switch(self->base.tick_minor / self->type->animation_ticks_per_frame) {
case 4:
case 6:
self->base.anim_frame = 0;
- if(self->flags & JUMPNRUN_ENEMY_FACING_RIGHT) {
+ if(self->base.flags & JUMPNRUN_MOVEABLE_MIRRORED) {
self->base.inertia.x = fixed_point_neg(self->type->spawn_inertia.x);
} else {
self->base.inertia.x = self->type->spawn_inertia.x;
case 5:
case 7:
self->base.anim_frame = 1;
- if(self->flags & JUMPNRUN_ENEMY_FACING_RIGHT) {
+ if(self->base.flags & JUMPNRUN_MOVEABLE_MIRRORED) {
self->base.inertia.x = fixed_point_neg(self->type->spawn_inertia.x);
} else {
self->base.inertia.x = self->type->spawn_inertia.x;
}
++self->base.tick_minor;
- if (fixed_point_lt(self->base.inertia.x, FIXED_INT(0))) { self->flags &= ~JUMPNRUN_ENEMY_FACING_RIGHT; }
- else if(fixed_point_ne(self->base.inertia.x, FIXED_INT(0))) { self->flags |= JUMPNRUN_ENEMY_FACING_RIGHT; }
}
void enemy_tick_giraffe(jumpnrun_enemy *self,
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;
- }
-
- bool was_on_ground = self->base.touching_ground;
+ bool was_on_ground = jumpnrun_moveable_touching_ground(&self->base);
jumpnrun_passive_movement(&self->base.inertia);
+ enemy_tick_common(self, state, lv, visible_tiles, player_inertia_mod);
- 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, player_inertia_mod);
- rectangle_move_to(&self->base.current_box, new_pos);
-
- if(self->base.touching_ground) {
+ if(jumpnrun_moveable_touching_ground(&self->base)) {
if(was_on_ground) {
enemy_animation_advance(self);
if(self->base.anim_frame == 0) {
self->base.inertia = self->type->spawn_inertia;
- if(fixed_point_gt(rectangle_mid_x(&state->player.current_box), rectangle_mid_x(enemy_box(self)))) {
+ if(fixed_point_gt(rectangle_mid_x(&state->player.base.hitbox), rectangle_mid_x(enemy_hitbox(self)))) {
self->base.inertia.x = fixed_point_neg(self->base.inertia.x);
}
}
}
++self->base.tick_minor;
- if (fixed_point_lt(self->base.inertia.x, FIXED_INT(0))) { self->flags &= ~JUMPNRUN_ENEMY_FACING_RIGHT; }
- else if(fixed_point_ne(self->base.inertia.x, FIXED_INT(0))) { self->flags |= JUMPNRUN_ENEMY_FACING_RIGHT; }
}
void enemy_tick_fly_straight(struct jumpnrun_enemy *self,
struct jumpnrun_level *lv,
struct 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;
- }
-
- 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, player_inertia_mod);
- rectangle_move_to(&self->base.current_box, new_pos);
-
+ enemy_tick_common(self, state, lv, visible_tiles, player_inertia_mod);
enemy_animation_advance(self);
}
struct jumpnrun_level *lv,
struct 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;
- }
-
- if(fixed_point_lt(fixed_point_abs(fixed_point_sub(enemy_position(self).x,
- state->player.current_box.pos.x)),
+ if(fixed_point_lt(fixed_point_abs(fixed_point_sub(enemy_pos_hitbox(self).x,
+ state->player.base.hitbox.pos.x)),
FIXED_INT(20))) {
- self->flags |= JUMPNRUN_ENEMY_EVENT_TRIGGER1;
+ self->base.flags |= JUMPNRUN_ENEMY_EVENT_TRIGGER1;
}
- if(self->flags & JUMPNRUN_ENEMY_EVENT_TRIGGER1) {
+ if(self->base.flags & JUMPNRUN_ENEMY_EVENT_TRIGGER1) {
self->base.inertia.y =
fixed_point_add(fixed_point_add(self->base.inertia.y,
fixed_point_div(self->type->spawn_inertia.y, FIXED_INT(3))),
fixed_point_mul(FIXED_POINT(0, 5),
fixed_point_sub(self->spawn_pos.y,
- enemy_position(self).y)));
+ enemy_pos_hitbox(self).y)));
} else {
self->base.inertia.y = FIXED_INT(0);
}
- 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, player_inertia_mod);
- rectangle_move_to(&self->base.current_box, new_pos);
-
+ enemy_tick_common(self, state, lv, visible_tiles, player_inertia_mod);
enemy_animation_advance(self);
}
.animation_ticks_per_frame = 18,
.animation_length = ARRAY_SIZE(anim_cat),
.animation_frames = anim_cat,
- .extent = { FIXED_INT_I(8), FIXED_INT_I(5) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(2) },
{ FIXED_INT_I(6), FIXED_INT_I(3) } },
.spawn_inertia = { FIXED_POINT_I(0, -200), FIXED_INT_I(0) },
.animation_ticks_per_frame = 12,
.animation_length = ARRAY_SIZE(anim_mushroom),
.animation_frames = anim_mushroom,
- .extent = { FIXED_INT_I(7), FIXED_INT_I(7) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(1) },
{ FIXED_INT_I(5), FIXED_INT_I(4) } },
.spawn_inertia = { FIXED_POINT_I(0, -80), FIXED_INT_I(0) },
.animation_ticks_per_frame = 9,
.animation_length = ARRAY_SIZE(anim_bunny),
.animation_frames = anim_bunny,
- .extent = { FIXED_INT_I(7), FIXED_INT_I(5) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(2) },
{ FIXED_INT_I(5), FIXED_INT_I(3) } },
.spawn_inertia = { FIXED_POINT_I(0, -80), FIXED_POINT_I(0, -800) },
.animation_ticks_per_frame = 6,
.animation_length = ARRAY_SIZE(anim_snake),
.animation_frames = anim_snake,
- .extent = { FIXED_INT_I(10), FIXED_INT_I(6) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(4) },
{ FIXED_INT_I(8), FIXED_INT_I(2) } },
.spawn_inertia = { FIXED_POINT_I(0, -150), FIXED_INT_I(0) },
.animation_ticks_per_frame = 6,
.animation_length = ARRAY_SIZE(anim_spiral),
.animation_frames = anim_spiral,
- .extent = { FIXED_INT_I(10), FIXED_INT_I(10) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(1) },
{ FIXED_INT_I(8), FIXED_INT_I(8) } },
.spawn_inertia = { FIXED_INT_I(0), FIXED_POINT_I(0, -200) },
.animation_ticks_per_frame = 5,
.animation_length = ARRAY_SIZE(anim_rotor),
.animation_frames = anim_rotor,
- .extent = { FIXED_INT_I(9), FIXED_INT_I(9) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(1) },
{ FIXED_INT_I(7), FIXED_INT_I(7) } },
.spawn_inertia = { FIXED_INT_I(0), FIXED_POINT_I(0, 0) },
.animation_ticks_per_frame = 18,
.animation_length = ARRAY_SIZE(anim_dog),
.animation_frames = anim_dog,
- .extent = { FIXED_INT_I(8), FIXED_INT_I(5) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(1) },
{ FIXED_INT_I(6), FIXED_INT_I(4) } },
.spawn_inertia = { FIXED_POINT_I(0, -200), FIXED_POINT_I(0, 0) },
.animation_ticks_per_frame = 36,
.animation_length = ARRAY_SIZE(anim_giraffe),
.animation_frames = anim_giraffe,
- .extent = { FIXED_INT_I(7), FIXED_INT_I(10) },
.hitbox = { { FIXED_INT_I(2), FIXED_INT_I(1) },
{ FIXED_INT_I(4), FIXED_INT_I(9) } },
.spawn_inertia = { FIXED_POINT_I(0, -150), FIXED_POINT_I(-1, -200) },
.animation_ticks_per_frame = 24,
.animation_length = ARRAY_SIZE(anim_bird),
.animation_frames = anim_bird,
- .extent = { FIXED_INT_I(9), FIXED_INT_I(7) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(3) },
{ FIXED_INT_I(7), FIXED_INT_I(3) } },
.spawn_inertia = { FIXED_POINT_I(0, -400), FIXED_POINT_I(0, -150) },
.animation_ticks_per_frame = 24,
.animation_length = ARRAY_SIZE(anim_bird),
.animation_frames = anim_bird,
- .extent = { FIXED_INT_I(9), FIXED_INT_I(7) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(3) },
{ FIXED_INT_I(7), FIXED_INT_I(3) } },
.spawn_inertia = { FIXED_POINT_I(0, -400), FIXED_INT_I(0) },
.animation_ticks_per_frame = 24,
.animation_length = ARRAY_SIZE(anim_bird),
.animation_frames = anim_bird,
- .extent = { FIXED_INT_I(9), FIXED_INT_I(7) },
.hitbox = { { FIXED_INT_I(1), FIXED_INT_I(3) },
{ FIXED_INT_I(7), FIXED_INT_I(3) } },
.spawn_inertia = { FIXED_POINT_I(0, -400), FIXED_POINT_I(0, 200) },
size_t animation_length;
badge_sprite const *animation_frames;
- vec2d extent;
rectangle hitbox;
vec2d spawn_inertia;
typedef struct jumpnrun_enemy {
jumpnrun_moveable base;
vec2d spawn_pos;
- unsigned flags;
jumpnrun_enemy_type const *type;
} jumpnrun_enemy;
enum {
- JUMPNRUN_ENEMY_SPAWNED = 1,
- JUMPNRUN_ENEMY_UNAVAILABLE = 2,
- JUMPNRUN_ENEMY_FACING_RIGHT = 4,
+// Do not collide with JUMPNRUN_MOVEABLE_* flags
+ JUMPNRUN_ENEMY_SPAWNED = 4,
+ JUMPNRUN_ENEMY_UNAVAILABLE = 8,
JUMPNRUN_ENEMY_EVENT_TRIGGER1 = 128
};
-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 bool enemy_facing_right(jumpnrun_enemy const *enemy) { return (enemy->flags & JUMPNRUN_ENEMY_FACING_RIGHT) || fixed_point_gt(enemy->base.inertia.x, FIXED_INT(0)); }
-static inline uint8_t enemy_render_flags(jumpnrun_enemy const *enemy) { return enemy_facing_right(enemy) ? BADGE_BLT_MIRRORED : 0; }
+static inline rectangle const *enemy_hitbox(jumpnrun_enemy const *enemy) { return &enemy->base.hitbox; }
+void jumpnrun_enemy_despawn(jumpnrun_enemy *self);
+void jumpnrun_enemy_reset (jumpnrun_enemy *self);
enum {
JUMPNRUN_ENEMY_TYPE_CAT,
--- /dev/null
+#ifndef INCLUDED_BADGE_JUMPNRUN_GAME_STATE_H
+#define INCLUDED_BADGE_JUMPNRUN_GAME_STATE_H
+
+#include "player.h"
+#include "levels.h"
+#include "shots.h"
+#include "../ui/display.h"
+
+enum {
+ JUMPNRUN_MAX_SHOTS = 2,
+
+ JUMPNRUN_STATE_WON = 1
+};
+
+typedef struct jumpnrun_game_state {
+ jumpnrun_player player;
+ int screen_left;
+ uint8_t flags;
+ jumpnrun_shot shots[JUMPNRUN_MAX_SHOTS];
+} jumpnrun_game_state;
+
+static inline int jumpnrun_screen_left (jumpnrun_game_state const *state) { return state->screen_left; }
+static inline int jumpnrun_screen_right(jumpnrun_game_state const *state) { return jumpnrun_screen_left(state) + BADGE_DISPLAY_WIDTH; }
+
+void jumpnrun_game_state_init (jumpnrun_game_state *state, jumpnrun_level const *lv);
+void jumpnrun_game_state_respawn(jumpnrun_game_state *state, jumpnrun_level const *lv);
+
+void jumpnrun_shot_spawn(jumpnrun_shot *shot, jumpnrun_game_state const *state);
+
+#endif
#include "items.h"
#include "jumpnrun.h"
+#include "game_state.h"
static void on_collect_win(jumpnrun_item *self,
jumpnrun_game_state *state,
jumpnrun_level *lv) {
(void) lv;
self->flags |= JUMPNRUN_ITEM_COLLECTED;
- state->status = JUMPNRUN_WON;
+ state->flags |= JUMPNRUN_STATE_WON;
}
static void on_collect_checkpoint(jumpnrun_item *self,
(void) state;
self->flags |= JUMPNRUN_ITEM_COLLECTED;
lv->start_pos = (vec2d) { self->pos.x,
- fixed_point_sub(fixed_point_add(self->pos.y, FIXED_INT(self->type->sprite.height)), hacker_extents().y)
+ fixed_point_sub(fixed_point_add(self->pos.y, FIXED_INT(self->type->sprite.height)), jumpnrun_player_extents().y)
};
}
jumpnrun_level *lv) {
(void) lv;
self->flags |= JUMPNRUN_ITEM_COLLECTED;
- ++state->keys;
+ ++state->player.keys;
}
static void on_collect_encrypted(jumpnrun_item *self,
jumpnrun_game_state *state,
jumpnrun_level *lv) {
- if(state->keys != 0) {
+ if(state->player.keys != 0) {
on_collect_win(self, state, lv);
}
}
+#include "game_state.h"
#include "jumpnrun.h"
#include "collision.h"
#include "levels.h"
+#include "render.h"
#include "stats.h"
#include "../ui/display.h"
static fixed_point const drag_factor = FIXED_POINT_I(0, 854);
static fixed_point const speed_jump_x = FIXED_POINT_I(0, 600);
-vec2d hacker_extents(void) { return (vec2d) { FIXED_INT_I(5), FIXED_INT_I(8) }; }
-static vec2d const shot_spawn_inertia = { FIXED_POINT_I(0, 800), FIXED_POINT_I(0, -800) };
-
-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" },
- { 5, 8, (uint8_t const *) "\xdc\x3f\x1d\x24\xc4" },
- { 5, 8, (uint8_t const *) "\x1c\xff\x3d\xc4\x04" }
- /*
- { 5, 8, (uint8_t const *) "\x46\xfc\x73\x8c\x31" },
- { 5, 8, (uint8_t const *) "\x46\xfc\x73\x8c\x52" },
- { 5, 8, (uint8_t const *) "\x46\xfc\x73\x94\x8c" },
- { 5, 8, (uint8_t const *) "\x46\xfc\x73\x8c\x52" }
- */
- /*
- { 6, 8, (uint8_t const *) "\x0c\xe1\x3b\x0e\xc3\x30" },
- { 6, 8, (uint8_t const *) "\x0c\xe1\x3b\x0e\x43\x51" },
- { 6, 8, (uint8_t const *) "\x0c\xe1\x3b\x0e\x35\x82" },
- { 6, 8, (uint8_t const *) "\x0c\xe1\x3b\x0e\x43\x51" }
- */
- /*
- { 6, 8, (uint8_t const *) "\xff\xff\xff\xff\xff\xff" },
- { 6, 8, (uint8_t const *) "\xff\xff\xff\xff\xff\xff" },
- { 6, 8, (uint8_t const *) "\xff\xff\xff\xff\xff\xff" },
- { 6, 8, (uint8_t const *) "\xff\xff\xff\xff\xff\xff" }
- */
-};
-
-badge_sprite const *jumpnrun_hacker_symbol(void) {
- return &anim_hacker[0];
-}
-
-static badge_sprite const anim_sickle[] = {
- { 3, 3, (uint8_t const *) "\xab\x01" },
- { 3, 3, (uint8_t const *) "\xee\x00" }
-/*
- { 3, 3, (uint8_t const *) "\x8a\x01" },
- { 3, 3, (uint8_t const *) "\x6a" },
- { 3, 3, (uint8_t const *) "\xa3" },
- { 3, 3, (uint8_t const *) "\xac" }
-*/
-};
-
-enum {
- JUMPNRUN_SHOT_EXTENT = 3,
- JUMPNRUN_SHOT_TICKS_PER_FRAME = 36
-};
-
-static void jumpnrun_shot_spawn(jumpnrun_shot *shot, jumpnrun_game_state const *state) {
- shot->tick = 0;
- shot->inertia = shot_spawn_inertia;
-
- if(state->player.anim_direction == BADGE_BLT_MIRRORED) {
- shot->current_box = rectangle_new((vec2d) { fixed_point_sub(rectangle_left(&state->player.current_box), FIXED_INT(JUMPNRUN_SHOT_EXTENT)), rectangle_top(&state->player.current_box) },
- (vec2d) { FIXED_INT(JUMPNRUN_SHOT_EXTENT), FIXED_INT(JUMPNRUN_SHOT_EXTENT) });
- shot->inertia.x = fixed_point_neg(shot->inertia.x);
- } else {
- shot->current_box = rectangle_new((vec2d) { rectangle_right(&state->player.current_box), rectangle_top(&state->player.current_box) },
- (vec2d) { FIXED_INT(JUMPNRUN_SHOT_EXTENT), FIXED_INT(JUMPNRUN_SHOT_EXTENT) });
- }
-
- shot->old_box = shot->current_box;
- shot->inertia = vec2d_add(shot->inertia, state->player.inertia);
-}
-
static inline int imax(int x, int y) {
return x < y ? y : x;
}
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), hacker_extents().x); }
-static inline fixed_point hacker_bottom(vec2d const *pos, jumpnrun_game_state const *state) { return fixed_point_add(hacker_top (pos, state), hacker_extents().y); }
+static inline fixed_point hacker_right (vec2d const *pos, jumpnrun_game_state const *state) { return fixed_point_add(hacker_left(pos, state), jumpnrun_player_extents().x); }
+static inline fixed_point hacker_bottom(vec2d const *pos, jumpnrun_game_state const *state) { return fixed_point_add(hacker_top (pos, state), jumpnrun_player_extents().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->player.current_box.pos.x);
- int pos_rel = pos_cur - state->left;
+ int pos_cur = fixed_point_cast_int(state->player.base.hitbox.pos.x);
+ int pos_rel = pos_cur - state->screen_left;
if(pos_rel < lmargin) {
return imax(0, pos_cur - lmargin);
return pos_cur - (BADGE_DISPLAY_WIDTH - rmargin);
}
- return state->left;
+ return state->screen_left;
}
static int jumpnrun_bsearch_tile(jumpnrun_level const *lv, jumpnrun_game_state const *state) {
while(len > 0) {
int mid = front + len / 2;
- if(fixed_point_lt(tile_right(&lv->tiles[mid]), FIXED_INT(state->left - JUMPNRUN_MAX_SPAWN_MARGIN))) {
+ if(fixed_point_lt(tile_right(&lv->tiles[mid]), FIXED_INT(state->screen_left - JUMPNRUN_MAX_SPAWN_MARGIN))) {
front = mid + 1;
len -= len / 2 + 1;
} else {
r.first = jumpnrun_bsearch_tile(lv, state);
for(r.last = r.first;
- r.last < lv->header.tile_count && lv->tiles[r.last].pos.x * JUMPNRUN_TILE_PIXEL_WIDTH < state->left + BADGE_DISPLAY_WIDTH + JUMPNRUN_MAX_SPAWN_MARGIN;
+ r.last < lv->header.tile_count && lv->tiles[r.last].pos.x * JUMPNRUN_TILE_PIXEL_WIDTH < state->screen_left + BADGE_DISPLAY_WIDTH + JUMPNRUN_MAX_SPAWN_MARGIN;
++r.last)
;
return r;
}
+void jumpnrun_apply_gravity(vec2d *inertia) {
+ *inertia = vec2d_add(*inertia, gravity);
+}
+
void jumpnrun_passive_movement(vec2d *inertia)
{
- *inertia = vec2d_add(*inertia, gravity);
+ jumpnrun_apply_gravity(inertia);
inertia->x = fixed_point_min(fixed_point_max(fixed_point_neg(move_max.x), inertia->x), move_max.x);
inertia->y = fixed_point_min(fixed_point_max(fixed_point_neg(move_max.y), inertia->y), move_max.y);
(BADGE_EVENT_KEY_LEFT |
BADGE_EVENT_KEY_RIGHT)) {
case BADGE_EVENT_KEY_LEFT:
- // 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->player.anim_direction = BADGE_BLT_MIRRORED;
+ // state->player.base.inertia.x = state->player.touching_ground ? fixed_point_sub(state->player.base.inertia.x, accel_horiz) : fixed_point_neg(speed_jump_x);
+ state->player.base.inertia.x = fixed_point_sub(state->player.base.inertia.x, accel_horiz);
+ state->player.base.flags |= JUMPNRUN_MOVEABLE_MIRRORED;
break;
case BADGE_EVENT_KEY_RIGHT:
- // 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->player.anim_direction = 0;
+ // state->player.base.inertia.x = state->player.touching_ground ? fixed_point_add(state->player.base.inertia.x, accel_horiz) : speed_jump_x;
+ state->player.base.inertia.x = fixed_point_add(state->player.base.inertia.x, accel_horiz);
+ state->player.base.flags &= ~JUMPNRUN_MOVEABLE_MIRRORED;
break;
default:
- if(state->player.touching_ground) {
- state->player.inertia.x = fixed_point_mul(state->player.inertia.x, drag_factor);
+ if(jumpnrun_moveable_touching_ground(&state->player.base)) {
+ state->player.base.inertia.x = fixed_point_mul(state->player.base.inertia.x, drag_factor);
} //else {
- //state->player.inertia.x = FIXED_INT(0);
+ //state->player.base.inertia.x = FIXED_INT(0);
//}
break;
}
- if(state->player.jumpable_frames == 0) {
+ if(state->player.base.jumpable_frames == 0) {
// intentionally left blank.
} else if(badge_event_current_input_state() & BADGE_EVENT_KEY_BTN_A) {
- state->player.inertia.y = fixed_point_sub(state->player.inertia.y, accel_vert);
- --state->player.jumpable_frames;
+ state->player.base.inertia.y = fixed_point_sub(state->player.base.inertia.y, accel_vert);
+ --state->player.base.jumpable_frames;
} else {
- state->player.jumpable_frames = 0;
+ state->player.base.jumpable_frames = 0;
}
- jumpnrun_passive_movement(&state->player.inertia);
+ jumpnrun_passive_movement(&state->player.base.inertia);
- vec2d new_pos = vec2d_add(state->player.current_box.pos, state->player.inertia);
+ vec2d new_pos = vec2d_add(state->player.base.hitbox.pos, state->player.base.inertia);
- 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);
+ if(fixed_point_lt(new_pos.x, FIXED_INT(state->screen_left))) {
+ new_pos.x = FIXED_INT(state->screen_left);
+ state->player.base.inertia.x = FIXED_INT(0);
}
- *inertia_mod = state->player.inertia;
- bool killed = collisions_tiles_displace(&new_pos, &state->player, lv, tilerange, inertia_mod);
- state->player.inertia = *inertia_mod;
+ *inertia_mod = state->player.base.inertia;
+ bool killed = collisions_tiles_displace(&new_pos, &state->player.base, lv, tilerange, inertia_mod);
+ state->player.base.inertia = *inertia_mod;
- if(killed || fixed_point_gt(state->player.current_box.pos.y, FIXED_INT(BADGE_DISPLAY_HEIGHT))) {
- state->status = JUMPNRUN_DEAD;
+ if(killed || fixed_point_gt(state->player.base.hitbox.pos.y, FIXED_INT(BADGE_DISPLAY_HEIGHT))) {
+ state->player.base.flags |= JUMPNRUN_PLAYER_DEAD;
}
}
jumpnrun_game_state *state)
{
jumpnrun_tile_range tilerange = jumpnrun_visible_tiles(lv, state);
- vec2d inertia_mod = state->player.inertia;
+ vec2d inertia_mod = state->player.base.inertia;
jumpnrun_apply_movement(lv, &tilerange, state, &inertia_mod);
- state->left = jumpnrun_level_assert_left_side(state);
+ state->screen_left = jumpnrun_level_assert_left_side(state);
- if(state->player.tick_minor == 0) {
+ if(state->player.base.tick_minor == 0) {
badge_framebuffer fb;
badge_framebuffer_clear(&fb);
for(size_t tile = tilerange.first; tile < tilerange.last; ++tile) {
- badge_framebuffer_blt(&fb,
- fixed_point_cast_int(tile_left(&lv->tiles[tile])) - state->left,
- fixed_point_cast_int(tile_top (&lv->tiles[tile])),
- &tile_type(&lv->tiles[tile])->sprite,
- 0);
+ jumpnrun_render_tile(&fb, state, &lv->tiles[tile]);
}
for(size_t item = 0; item < lv->header.item_count; ++item) {
continue;
}
- int screenpos = fixed_point_cast_int(item_obj->pos.x) - state->left;
+ int screenpos = fixed_point_cast_int(item_obj->pos.x) - state->screen_left;
if(screenpos > -item_obj->type->sprite.width &&
screenpos < BADGE_DISPLAY_WIDTH) {
rectangle item_rect = rect_from_item(item_obj);
- if(rectangle_intersect(&state->player.current_box, &item_rect)) {
+ if(rectangle_intersect(&state->player.base.hitbox, &item_rect)) {
item_obj->type->on_collect(item_obj, state, lv);
}
- badge_framebuffer_blt(&fb,
- screenpos,
- fixed_point_cast_int(item_obj->pos.y),
- &item_obj->type->sprite,
- 0);
+ jumpnrun_render_item(&fb, state, item_obj);
}
}
for(size_t shot_ix = 0; shot_ix < JUMPNRUN_MAX_SHOTS; ++shot_ix) {
jumpnrun_shot *shot = &state->shots[shot_ix];
-
+ jumpnrun_shot_process(shot);
if(jumpnrun_shot_spawned(shot)) {
- rectangle_move_rel(&shot->current_box, shot->inertia);
- shot->inertia = vec2d_add(shot->inertia, gravity);
-
- if(fixed_point_gt(rectangle_top(&shot->current_box), FIXED_INT(BADGE_DISPLAY_HEIGHT))) {
- jumpnrun_shot_despawn(shot);
- }
-
- /* show every position twice, because LCD switching time. This makes the shots more
- * visible on the nokia lcds.
- */
- badge_framebuffer_blt(&fb,
- fixed_point_cast_int(shot->old_box.pos.x) - state->left,
- fixed_point_cast_int(shot->old_box.pos.y),
- &anim_sickle[shot->tick / JUMPNRUN_SHOT_TICKS_PER_FRAME],
- fixed_point_lt(shot->inertia.x, FIXED_INT(0)) ? BADGE_BLT_MIRRORED : 0);
- badge_framebuffer_blt(&fb,
- fixed_point_cast_int(shot->current_box.pos.x) - state->left,
- fixed_point_cast_int(shot->current_box.pos.y),
- &anim_sickle[shot->tick / JUMPNRUN_SHOT_TICKS_PER_FRAME],
- fixed_point_lt(shot->inertia.x, FIXED_INT(0)) ? BADGE_BLT_MIRRORED : 0);
-
- shot->old_box = shot->current_box;
-
- ++shot->tick;
- if(shot->tick == ARRAY_SIZE(anim_sickle) * JUMPNRUN_SHOT_TICKS_PER_FRAME) {
- shot->tick = 0;
- }
+ jumpnrun_render_shot(&fb, state, shot);
}
}
jumpnrun_process_enemy(enemy, &fb, state, lv, &tilerange, &inertia_mod);
}
- badge_framebuffer_blt(&fb,
- 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->player.anim_direction);
+ jumpnrun_render_player(&fb, state);
badge_framebuffer_flush(&fb);
- 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);
+ if(!jumpnrun_moveable_touching_ground(&state->player.base)) {
+ state->player.base.anim_frame = 2;
+ } else if(fixed_point_gt(fixed_point_abs(state->player.base.inertia.x), FIXED_POINT(0, 200))) {
+ state->player.base.anim_frame = (state->player.base.anim_frame + 1) % JUMPNRUN_PLAYER_FRAMES;
} else {
- state->player.anim_frame = 0;
+ state->player.base.anim_frame = 0;
}
} else {
for(size_t shot_ix = 0; shot_ix < JUMPNRUN_MAX_SHOTS; ++shot_ix) {
- jumpnrun_shot *shot = &state->shots[shot_ix];
-
- if(jumpnrun_shot_spawned(shot)) {
- rectangle_move_rel(&shot->current_box, shot->inertia);
- shot->inertia = vec2d_add(shot->inertia, gravity);
-
- if(fixed_point_gt(rectangle_top(&shot->current_box), FIXED_INT(BADGE_DISPLAY_HEIGHT))) {
- jumpnrun_shot_despawn(shot);
- }
-
- ++shot->tick;
- if(shot->tick == ARRAY_SIZE(anim_sickle) * JUMPNRUN_SHOT_TICKS_PER_FRAME) {
- shot->tick = 0;
- }
- }
+ jumpnrun_shot_process(&state->shots[shot_ix]);
}
for(size_t enemy_ix = 0; enemy_ix < lv->header.enemy_count; ++enemy_ix) {
}
}
- state->player.inertia = inertia_mod;
- ++state->player.tick_minor;
- if(state->player.tick_minor == 3) {
- state->player.tick_minor = 0;
+ state->player.base.inertia = inertia_mod;
+ ++state->player.base.tick_minor;
+ if(state->player.base.tick_minor == 3) {
+ state->player.base.tick_minor = 0;
}
}
JUMPNRUN_LEVEL_LOAD(lv, lvname);
jumpnrun_game_state gs;
- memset(&gs, 0, sizeof(gs));
- for(gs.lives = 99; gs.status != JUMPNRUN_WON && gs.lives != 0; --gs.lives) {
+ for(jumpnrun_game_state_init(&gs, &lv); (gs.flags & JUMPNRUN_STATE_WON) == 0 && gs.player.lives != 0; --gs.player.lives) {
jumpnrun_show_lives_screen(&gs);
+ jumpnrun_game_state_respawn(&gs, &lv);
- for(uint8_t i = 0; i < 75; ) {
- badge_event_t ev = badge_event_wait();
- if(badge_event_type(ev) == BADGE_EVENT_GAME_TICK) {
- ++i;
- } else if(i > 25) {
- uint8_t old_state = badge_event_old_input_state(ev);
- uint8_t new_state = badge_event_new_input_state(ev);
- uint8_t new_buttons = new_state & (old_state ^ new_state);
-
- if(new_buttons != 0) break;
- }
- }
-
- gs.status = JUMPNRUN_PLAYING;
- gs.left = 0;
- memset(&gs.player, 0, sizeof(gs.player));
- memset(&gs.shots , 0, sizeof(gs.shots ));
- gs.player.current_box = rectangle_new(lv.start_pos,
- hacker_extents());
-
- for(size_t i = 0; i < lv.header.enemy_count; ++i) {
- lv.enemies[i].flags = 0;
- }
-
- while(gs.status == JUMPNRUN_PLAYING) {
+ while((gs.player.base.flags & JUMPNRUN_PLAYER_DEAD) == 0 &&
+ (gs. flags & JUMPNRUN_STATE_WON ) == 0) {
badge_event_t ev = badge_event_wait();
switch(badge_event_type(ev)) {
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.player.touching_ground) {
- gs.player.jumpable_frames = 12;
+ if((new_buttons & BADGE_EVENT_KEY_BTN_A) && jumpnrun_moveable_touching_ground(&gs.player.base)) {
+ gs.player.base.jumpable_frames = 12;
}
if((new_buttons & BADGE_EVENT_KEY_BTN_B)) {
}
}
- return gs.status;
+ if(gs.flags & JUMPNRUN_STATE_WON) { return JUMPNRUN_WON; }
+ if(gs.player.lives == 0) return JUMPNRUN_LOST;
+ return JUMPNRUN_ERROR;
}
#include "enemies.h"
#include "items.h"
#include "levels.h"
+#include "shots.h"
#include "tiles.h"
#include "../ui/sprite.h"
enum {
JUMPNRUN_PLAYING,
- JUMPNRUN_DEAD,
JUMPNRUN_WON,
+ JUMPNRUN_LOST,
JUMPNRUN_ERROR
};
JUMPNRUN_MAX_SPAWNED_ENEMIES = 10
};
-typedef struct jumpnrun_shot {
- rectangle old_box;
- rectangle current_box;
- vec2d inertia;
- uint8_t tick;
-} jumpnrun_shot;
-
-static inline bool jumpnrun_shot_spawned(jumpnrun_shot const *shot) { return fixed_point_ne(shot->inertia.x, FIXED_INT(0)); }
-static inline void jumpnrun_shot_despawn(jumpnrun_shot *shot) { shot->inertia.x = FIXED_INT(0); }
-
-enum {
- JUMPNRUN_MAX_SHOTS = 2
-};
-
-typedef struct jumpnrun_game_state {
- jumpnrun_moveable player;
-
- uint8_t status;
- int left;
- uint8_t lives;
- uint8_t keys;
-
- jumpnrun_shot shots[JUMPNRUN_MAX_SHOTS];
-} jumpnrun_game_state;
-
-vec2d hacker_extents(void);
+vec2d jumpnrun_player_extents(void);
+void jumpnrun_apply_gravity(vec2d *inertia);
void jumpnrun_passive_movement(vec2d *inertia);
badge_sprite const *jumpnrun_hacker_symbol(void);
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 + 1) * JUMPNRUN_TILE_PIXEL_HEIGHT - dest->type->animation_frames[0].height, 0);
- dest->base.current_box = rectangle_new(dest->spawn_pos, dest->type->extent);
- dest->base.inertia = dest->type->spawn_inertia;
+ dest->spawn_pos.x = FIXED_POINT( thing.x * JUMPNRUN_TILE_PIXEL_WIDTH , 0);
+ dest->spawn_pos.y = FIXED_POINT((thing.y + 1) * JUMPNRUN_TILE_PIXEL_HEIGHT - dest->type->animation_frames[0].height, 0);
+ jumpnrun_enemy_despawn(dest);
}
#ifdef __linux__
#endif
return JUMPNRUN_LEVEL_LOAD_ERROR;
} else {
- dest->start_pos.x = fixed_point_sub(FIXED_INT((spos[0] + 1) * JUMPNRUN_TILE_PIXEL_WIDTH ), hacker_extents().x);
+ dest->start_pos.x = fixed_point_sub(FIXED_INT((spos[0] + 1) * JUMPNRUN_TILE_PIXEL_WIDTH ), jumpnrun_player_extents().x);
dest->start_pos.y = FIXED_INT( spos[1] * JUMPNRUN_TILE_PIXEL_HEIGHT);
}
+smb
lubiXOXO
lubilove
gnobbel
-smb
wrongturn
foo
mean
--- /dev/null
+#include "moveable.h"
#define INCLUDED_BADGE_JUMPNRUN_MOVEABLE_H
#include "../util/util.h"
+#include <stdint.h>
+
+enum {
+ // Do not collide with JUMPNRUN_ENEMY_* and JUMPNRUN_PLAYER_* flags.
+ JUMPNRUN_MOVEABLE_TOUCHING_GROUND = 1,
+ JUMPNRUN_MOVEABLE_MIRRORED = 2
+};
typedef struct jumpnrun_moveable {
- rectangle current_box;
+ rectangle hitbox;
vec2d inertia;
uint8_t tick_minor;
uint8_t anim_frame;
- uint8_t anim_direction;
- bool touching_ground;
+ uint8_t flags;
uint8_t jumpable_frames;
} jumpnrun_moveable;
+static inline bool jumpnrun_moveable_touching_ground(jumpnrun_moveable const *self) { return self->flags & JUMPNRUN_MOVEABLE_TOUCHING_GROUND; }
+static inline bool jumpnrun_moveable_mirrored (jumpnrun_moveable const *self) { return self->flags & JUMPNRUN_MOVEABLE_MIRRORED ; }
+
#endif
--- /dev/null
+#ifndef INCLUDED_BADGE_JUMPNRUN_PLAYER_H
+#define INCLUDED_BADGE_JUMPNRUN_PLAYER_H
+
+#include "moveable.h"
+#include "../ui/display.h"
+#include "../util/util.h"
+
+enum {
+ // Do not collide with JUMPNRUN_MOVEABLE_* flags
+ JUMPNRUN_PLAYER_DEAD = 4
+};
+
+enum {
+ JUMPNRUN_PLAYER_FRAMES = 4
+};
+
+typedef struct jumpnrun_player {
+ jumpnrun_moveable base;
+
+ uint8_t lives;
+ uint8_t keys;
+} jumpnrun_player;
+
+void jumpnrun_player_spawn (jumpnrun_player *self, vec2d spawn_pos, uint8_t lives);
+void jumpnrun_player_respawn (jumpnrun_player *self, vec2d spawn_pos);
+
+#endif
--- /dev/null
+#include "render.h"
+
+static badge_sprite const anim_sickle[JUMPNRUN_SHOT_FRAMES] = {
+ { 3, 3, (uint8_t const *) "\xab\x01" },
+ { 3, 3, (uint8_t const *) "\xee" }
+};
+
+static badge_sprite const anim_player[JUMPNRUN_PLAYER_FRAMES ] = {
+ { 5, 8, (uint8_t const *) "\x1c\xff\xfd\x04\x04" },
+ { 5, 8, (uint8_t const *) "\x1c\xff\x3d\xc4\x04" },
+ { 5, 8, (uint8_t const *) "\xdc\x3f\x1d\x24\xc4" },
+ { 5, 8, (uint8_t const *) "\x1c\xff\x3d\xc4\x04" }
+};
+
+vec2d jumpnrun_player_extents(void) { return (vec2d) { FIXED_INT_I(5), FIXED_INT_I(8) }; }
+
+void jumpnrun_render_moveable (badge_framebuffer *fb, jumpnrun_game_state const *state, jumpnrun_moveable const *moveable, badge_sprite const *animation, vec2d sprite_offset) {
+ vec2d render_pos = vec2d_sub(moveable->hitbox.pos, sprite_offset);
+ badge_framebuffer_blt(fb,
+ fixed_point_cast_int(render_pos.x) - jumpnrun_screen_left(state),
+ fixed_point_cast_int(render_pos.y),
+ &animation[moveable->anim_frame],
+ (moveable->flags & JUMPNRUN_MOVEABLE_MIRRORED) ? BADGE_BLT_MIRRORED : 0);
+}
+
+void jumpnrun_render_player (badge_framebuffer *fb, jumpnrun_game_state const *state) {
+ jumpnrun_render_moveable(fb, state, &state->player.base, anim_player, (vec2d) { FIXED_INT(0), FIXED_INT(0) });
+}
+
+void jumpnrun_render_shot (badge_framebuffer *fb, jumpnrun_game_state const *state, jumpnrun_shot *shot ) {
+ /* show every position twice, because LCD switching time. This makes the shots more
+ * visible on the nokia lcds.
+ */
+ badge_framebuffer_blt(fb,
+ fixed_point_cast_int(shot->old_box.pos.x) - jumpnrun_screen_left(state),
+ fixed_point_cast_int(shot->old_box.pos.y),
+ &anim_sickle[shot->tick / JUMPNRUN_SHOT_TICKS_PER_FRAME],
+ fixed_point_lt(shot->inertia.x, FIXED_INT(0)) ? BADGE_BLT_MIRRORED : 0);
+ badge_framebuffer_blt(fb,
+ fixed_point_cast_int(shot->current_box.pos.x) - jumpnrun_screen_left(state),
+ fixed_point_cast_int(shot->current_box.pos.y),
+ &anim_sickle[shot->tick / JUMPNRUN_SHOT_TICKS_PER_FRAME],
+ fixed_point_lt(shot->inertia.x, FIXED_INT(0)) ? BADGE_BLT_MIRRORED : 0);
+
+ shot->old_box = shot->current_box;
+}
+
+void jumpnrun_render_enemy (badge_framebuffer *fb, jumpnrun_game_state const *state, jumpnrun_enemy const *enemy ) {
+ jumpnrun_render_moveable(fb, state, &enemy->base, enemy->type->animation_frames, enemy->type->hitbox.pos);
+}
+
+void jumpnrun_render_tile (badge_framebuffer *fb, jumpnrun_game_state const *state, jumpnrun_tile const *tile ) {
+ badge_framebuffer_blt(fb,
+ tile->pos.x * JUMPNRUN_TILE_PIXEL_WIDTH - jumpnrun_screen_left(state),
+ tile->pos.y * JUMPNRUN_TILE_PIXEL_HEIGHT,
+ &tile_type(tile)->sprite,
+ 0);
+}
+
+void jumpnrun_render_item (badge_framebuffer *fb, jumpnrun_game_state const *state, jumpnrun_item const *item ) {
+ badge_framebuffer_blt(fb,
+ fixed_point_cast_int(item->pos.x) - jumpnrun_screen_left(state),
+ fixed_point_cast_int(item->pos.y),
+ &item->type->sprite,
+ 0);
+}
+
+void jumpnrun_render_player_symbol(badge_framebuffer *fb, int8_t x, int8_t y) {
+ badge_framebuffer_blt(fb, x, y, &anim_player[0], 0);
+}
+
+void jumpnrun_render_key_symbol (badge_framebuffer *fb, int8_t x, int8_t y) {
+ badge_framebuffer_blt(fb, x, y, &jumpnrun_item_type_data[JUMPNRUN_ITEM_TYPE_KEY].sprite, 0);
+}
--- /dev/null
+#include "shots.h"
+#include "jumpnrun.h"
+#include "render.h"
+
+void jumpnrun_shot_process(jumpnrun_shot *shot) {
+ if(jumpnrun_shot_spawned(shot)) {
+ rectangle_move_rel(&shot->current_box, shot->inertia);
+ jumpnrun_apply_gravity(&shot->inertia);
+
+ if(fixed_point_gt(rectangle_top(&shot->current_box), FIXED_INT(BADGE_DISPLAY_HEIGHT))) {
+ jumpnrun_shot_despawn(shot);
+ }
+
+ ++shot->tick;
+ if(shot->tick == JUMPNRUN_SHOT_FRAMES * JUMPNRUN_SHOT_TICKS_PER_FRAME) {
+ shot->tick = 0;
+ }
+ }
+}
--- /dev/null
+#ifndef INCLUDED_BADGE_JUMPNRUN_SHOTS_H
+#define INCLUDED_BADGE_JUMPNRUN_SHOTS_H
+
+#include "../ui/display.h"
+#include "../util/util.h"
+#include <stdbool.h>
+#include <stdint.h>
+
+typedef struct jumpnrun_shot {
+ rectangle old_box;
+ rectangle current_box;
+ vec2d inertia;
+ uint8_t tick;
+} jumpnrun_shot;
+
+enum {
+ JUMPNRUN_SHOT_EXTENT = 3,
+ JUMPNRUN_SHOT_TICKS_PER_FRAME = 36,
+ JUMPNRUN_SHOT_FRAMES = 2
+};
+
+static inline bool jumpnrun_shot_spawned(jumpnrun_shot const *shot) { return fixed_point_ne(shot->inertia.x, FIXED_INT(0)); }
+static inline void jumpnrun_shot_despawn(jumpnrun_shot *shot) { shot->inertia.x = FIXED_INT(0); }
+
+void jumpnrun_shot_process(jumpnrun_shot *shot);
+
+#endif
#include "stats.h"
-#include "jumpnrun.h"
+
#include "items.h"
+#include "jumpnrun.h"
+#include "render.h"
+
#include "../ui/display.h"
+#include "../ui/event.h"
#include "../ui/font.h"
void jumpnrun_show_lives_screen(jumpnrun_game_state const *state) {
badge_framebuffer fb = { { { 0 } } };
- badge_sprite const *hacker = jumpnrun_hacker_symbol();
- badge_sprite const *key = &jumpnrun_item_type_data[JUMPNRUN_ITEM_TYPE_KEY].sprite;
-
int8_t y_upper = BADGE_DISPLAY_HEIGHT / 2 - BADGE_FONT_HEIGHT;
int8_t y_lower = (BADGE_DISPLAY_HEIGHT + BADGE_FONT_HEIGHT) / 2;
- int8_t x_left = BADGE_DISPLAY_WIDTH / 2 - hacker->width - BADGE_FONT_WIDTH - 5;
+ int8_t x_left = BADGE_DISPLAY_WIDTH / 2 - fixed_point_cast_int(jumpnrun_player_extents().y) - BADGE_FONT_WIDTH - 5;
int8_t x_mid = (BADGE_DISPLAY_WIDTH - BADGE_FONT_WIDTH) / 2;
int8_t x_right = x_mid + BADGE_FONT_WIDTH + 5;
char buf[] = "x";
- if(state->keys != 0) {
+ if(state->player.keys != 0) {
y_upper -= BADGE_FONT_HEIGHT;
}
- badge_framebuffer_blt (&fb, x_left , y_upper, hacker, 0);
+ jumpnrun_render_player_symbol(&fb, x_left, y_upper);
badge_framebuffer_render_text (&fb, x_mid , y_upper, buf);
- badge_framebuffer_render_number(&fb, x_right, y_upper, state->lives);
+ badge_framebuffer_render_number(&fb, x_right, y_upper, state->player.lives);
- if(state->keys != 0) {
- badge_framebuffer_blt (&fb, x_left , y_lower, key, 0);
+ if(state->player.keys != 0) {
+ jumpnrun_render_key_symbol(&fb, x_left, y_lower);
badge_framebuffer_render_text (&fb, x_mid , y_lower, buf);
- badge_framebuffer_render_number(&fb, x_right, y_lower, state->keys);
+ badge_framebuffer_render_number(&fb, x_right, y_lower, state->player.keys);
}
badge_framebuffer_flush(&fb);
+
+ for(uint8_t i = 0; i < 75; ) {
+ badge_event_t ev = badge_event_wait();
+ if(badge_event_type(ev) == BADGE_EVENT_GAME_TICK) {
+ ++i;
+ } else if(i > 25) {
+ uint8_t old_state = badge_event_old_input_state(ev);
+ uint8_t new_state = badge_event_new_input_state(ev);
+ uint8_t new_buttons = new_state & (old_state ^ new_state);
+
+ if(new_buttons != 0) break;
+ }
+ }
}
#ifndef INCLUDED_BADGE_JUMPNRUN_STATS_H
#define INCLUDED_BADGE_JUMPNRUN_STATS_H
-#include "jumpnrun.h"
+#include "game_state.h"
void jumpnrun_show_lives_screen(jumpnrun_game_state const *state);
size_t last; // actually one past last.
} jumpnrun_tile_range;
-static inline fixed_point tile_left (jumpnrun_tile const *tile) { return FIXED_POINT(tile->pos.x * JUMPNRUN_TILE_PIXEL_WIDTH , 0); }
-static inline fixed_point tile_top (jumpnrun_tile const *tile) { return FIXED_POINT(tile->pos.y * JUMPNRUN_TILE_PIXEL_HEIGHT, 0); }
-static inline fixed_point tile_right (jumpnrun_tile const *tile) { return fixed_point_add(tile_left(tile), FIXED_POINT(JUMPNRUN_TILE_PIXEL_WIDTH , 0)); }
-static inline fixed_point tile_bottom(jumpnrun_tile const *tile) { return fixed_point_add(tile_top (tile), FIXED_POINT(JUMPNRUN_TILE_PIXEL_HEIGHT, 0)); }
+static inline fixed_point tile_left (jumpnrun_tile const *tile) { return FIXED_INT(tile->pos.x * JUMPNRUN_TILE_PIXEL_WIDTH ); }
+static inline fixed_point tile_top (jumpnrun_tile const *tile) { return FIXED_INT(tile->pos.y * JUMPNRUN_TILE_PIXEL_HEIGHT); }
+static inline fixed_point tile_right (jumpnrun_tile const *tile) { return fixed_point_add(tile_left(tile), FIXED_INT(JUMPNRUN_TILE_PIXEL_WIDTH )); }
+static inline fixed_point tile_bottom(jumpnrun_tile const *tile) { return fixed_point_add(tile_top (tile), FIXED_INT(JUMPNRUN_TILE_PIXEL_HEIGHT)); }
/************************************/
fixed_point_add(v1.x, v2.x),
fixed_point_add(v1.y, v2.y)
};
+ return r;
+}
+static inline vec2d vec2d_sub(vec2d v1, vec2d v2) {
+ vec2d r = {
+ fixed_point_sub(v1.x, v2.x),
+ fixed_point_sub(v1.y, v2.y)
+ };
return r;
}
ui/sprite.c \
jumpnrun/collision.c \
jumpnrun/enemies.c \
+ jumpnrun/game_state.c \
jumpnrun/items.c \
jumpnrun/jumpnrun.c \
- jumpnrun/tiles.c \
jumpnrun/level_load.c \
- jumpnrun/stats.c
+ jumpnrun/moveable.c \
+ jumpnrun/player.c \
+ jumpnrun/render.c \
+ jumpnrun/shots.c \
+ jumpnrun/stats.c \
+ jumpnrun/tiles.c
BADGE_CXXOBJS = $(BADGE_CXXSRCS:%.cc=%.o)
BADGE_COBJS = $(BADGE_CSRCS:%.c=%.o)