.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, -50), FIXED_INT_I(0) },
+ .spawn_inertia = { FIXED_POINT_I(0, -80), FIXED_INT_I(0) },
.collision_tiles = enemy_collision_tiles_bounce_horiz,
.collision_player = enemy_collision_player_jumpable,
.collision_shots = enemy_collision_shots_die,
#include "items.h"
#include "jumpnrun.h"
-static void on_collect_win(jumpnrun_game_state *state) {
+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;
}
+static void on_collect_checkpoint(jumpnrun_item *self,
+ jumpnrun_game_state *state,
+ jumpnrun_level *lv) {
+ (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)
+ };
+}
+
jumpnrun_item_type const jumpnrun_item_type_data[JUMPNRUN_ITEM_TYPE_COUNT] = {
- { { 6, 7, (uint8_t const *) "\x7c\x61\xb5\x1a\xfc\x03" }, on_collect_win }
+ { { 6, 7, (uint8_t const *) "\x7c\x61\xb5\x1a\xfc\x03" }, on_collect_win },
+ { { 9, 12, (uint8_t const *) "\xff\x1f\x04\x49\x10\x05\x49\x50\x04\x51\x10\x04\x7f" }, on_collect_checkpoint }
};
#include "../util/rectangle.h"
struct jumpnrun_game_state;
+struct jumpnrun_level;
+struct jumpnrun_item;
+
+enum {
+ JUMPNRUN_ITEM_COLLECTED = 1
+};
typedef struct jumpnrun_item_type {
badge_sprite sprite;
- void (*on_collect)(struct jumpnrun_game_state *state);
+ void (*on_collect)(struct jumpnrun_item *item,
+ struct jumpnrun_game_state *state,
+ struct jumpnrun_level *lv);
} jumpnrun_item_type;
typedef struct jumpnrun_item {
- vec2d pos;
+ vec2d pos;
+ uint8_t flags;
jumpnrun_item_type const *type;
} jumpnrun_item;
enum {
JUMPNRUN_ITEM_TYPE_DOCUMENT,
+ JUMPNRUN_ITEM_TYPE_CHECKPOINT,
JUMPNRUN_ITEM_TYPE_COUNT
};
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) };
+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[] = {
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_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); }
+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); }
int jumpnrun_level_assert_left_side(jumpnrun_game_state const *state) {
static int const lmargin = 20;
}
for(size_t item = 0; item < lv->header.item_count; ++item) {
- int screenpos = fixed_point_cast_int(lv->items[item].pos.x) - state->left;
- if(screenpos > -lv->items[item].type->sprite.width &&
+ jumpnrun_item *item_obj = &lv->items[item];
+
+ if(item_obj->flags & JUMPNRUN_ITEM_COLLECTED) {
+ continue;
+ }
+
+ int screenpos = fixed_point_cast_int(item_obj->pos.x) - state->left;
+ if(screenpos > -item_obj->type->sprite.width &&
screenpos < BADGE_DISPLAY_WIDTH) {
- rectangle item_rect = rect_from_item(&lv->items[item]);
+ rectangle item_rect = rect_from_item(item_obj);
if(rectangle_intersect(&state->player.current_box, &item_rect)) {
- lv->items[item].type->on_collect(state);
+ item_obj->type->on_collect(item_obj, state, lv);
}
badge_framebuffer_blt(&fb,
screenpos,
- fixed_point_cast_int(lv->items[item].pos.y),
- &lv->items[item].type->sprite,
+ fixed_point_cast_int(item_obj->pos.y),
+ &item_obj->type->sprite,
0);
}
}
jumpnrun_game_state gs;
memset(&gs, 0, sizeof(gs));
- gs.player.current_box = rectangle_new(lv.start_pos, hacker_extent);
+ for(gs.lives = 3; gs.lives != 0; --gs.lives) {
+ gs.status = JUMPNRUN_PLAYING;
+ gs.player.current_box = rectangle_new(lv.start_pos,
+ hacker_extents());
- while(gs.status == JUMPNRUN_PLAYING) {
- badge_event_t ev = badge_event_wait();
+ while(gs.status == JUMPNRUN_PLAYING) {
+ badge_event_t ev = badge_event_wait();
- switch(badge_event_type(ev)) {
- case BADGE_EVENT_USER_INPUT:
+ switch(badge_event_type(ev)) {
+ case BADGE_EVENT_USER_INPUT:
{
uint8_t old_state = badge_event_old_input_state(ev);
uint8_t new_state = badge_event_new_input_state(ev);
break;
}
- case BADGE_EVENT_GAME_TICK:
+ case BADGE_EVENT_GAME_TICK:
{
jumpnrun_level_tick(&lv, &gs);
break;
}
+ }
}
}
uint8_t status;
int left;
+ uint8_t lives;
jumpnrun_shot shots[JUMPNRUN_MAX_SHOTS];
} jumpnrun_game_state;
-rectangle hacker_rect_current(jumpnrun_game_state const *state);
-
+vec2d hacker_extents(void);
void jumpnrun_passive_movement(vec2d *inertia);
uint8_t jumpnrun_play(char const *lvname);
#include "tiles.h"
#include "items.h"
#include "enemies.h"
+#include "jumpnrun.h"
#ifndef __linux__
#include <drivers/fatfs/ff.h>
}
static void jumpnrun_level_make_tile(jumpnrun_tile *dest, level_thing thing) {
+ memset(dest, 0, sizeof(*dest));
+
dest->type = thing.type;
dest->pos.x = thing.x;
dest->pos.y = thing.y;
}
static void jumpnrun_level_make_item(jumpnrun_item *dest, level_thing thing) {
+ memset(dest, 0, sizeof(*dest));
+
dest->type = &jumpnrun_item_type_data[thing.type];
- dest->pos.x = FIXED_POINT(thing.x * JUMPNRUN_TILE_PIXEL_WIDTH , 0);
- dest->pos.y = FIXED_POINT(thing.y * JUMPNRUN_TILE_PIXEL_WIDTH , 0);
+ dest->pos.x = FIXED_POINT( thing.x * JUMPNRUN_TILE_PIXEL_WIDTH , 0);
+ dest->pos.y = FIXED_POINT((thing.y + 1) * JUMPNRUN_TILE_PIXEL_WIDTH - dest->type->sprite.height, 0);
}
static void jumpnrun_level_make_enemy(jumpnrun_enemy *dest, level_thing thing) {
+ memset(dest, 0, sizeof(*dest));
+
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->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->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__
#endif
return JUMPNRUN_LEVEL_LOAD_ERROR;
} else {
- dest->start_pos.x = FIXED_POINT(spos[0] * JUMPNRUN_TILE_PIXEL_WIDTH , 0);
- dest->start_pos.y = FIXED_POINT(spos[1] * JUMPNRUN_TILE_PIXEL_HEIGHT, 0);
+ dest->start_pos.x = fixed_point_sub(FIXED_INT((spos[0] + 1) * JUMPNRUN_TILE_PIXEL_WIDTH ), hacker_extents().x);
+ dest->start_pos.y = FIXED_INT( spos[1] * JUMPNRUN_TILE_PIXEL_HEIGHT);
}
for(i = 0; i < dest->header.tile_count; ++i) {
? vv###### ###? W ? ### #??# ## #
### #
V #### # #
- ##### V # ###
- ? #?#?# 01 01 #?# # ## ? ? ? # ## # # ## # ##?# ###### # ###
+ c ##### # ###
+ ? #?#?# 01 01 #?# # ## ? ? ? # ## # # ## # ##?# ###### V # ###
01 23 23 @ R R ## ## ### ## ####### # #####
- P 01 23 23 23 G M ### ### #### ### 01 01 ######## D # #####
- S 23 23B 23 H H 23 C C S S C C H H #### #### ##### #### 23 H H 23######### # #####
+ 01 23 23 23 G M ### ### #### ### 01 01 ######## d # #####
+ P S 23 23B 23 H H 23 C C S S C C H H #### #### ##### #### 23 H H 23######### # #####
#################################################################### ############### ################################################################ ############################################^^^######
[tiles]
< spike_left
[items]
-D doc
+d doc
+c checkpoint
[enemies]
C cat
;
items.add
- ("doc", JUMPNRUN_ITEM_TYPE_DOCUMENT)
+ ("doc" , JUMPNRUN_ITEM_TYPE_DOCUMENT )
+ ("checkpoint", JUMPNRUN_ITEM_TYPE_CHECKPOINT)
;
enemies.add