Textdateiankuckdingviech.
[hackover2013-badge-firmware.git] / badge / jumpnrun / jumpnrun.c
index 7dc2c22..c91aac1 100644 (file)
@@ -2,6 +2,7 @@
 #include "jumpnrun.h"
 #include "collision.h"
 #include "levels.h"
+#include "player.h"
 #include "render.h"
 #include "stats.h"
 
 #include <stddef.h>
 #include <stdio.h>
 
-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 accel_vert   =   FIXED_POINT_I(0, 167);
-static fixed_point const drag_factor  =   FIXED_POINT_I(0, 854);
-static fixed_point const speed_jump_x =   FIXED_POINT_I(0, 600);
+static vec2d       gravity     () { return (vec2d) { FIXED_POINT(0,   0), FIXED_POINT(0,  56) }; }
+static vec2d       move_max    () { return (vec2d) { FIXED_POINT(0, 600), FIXED_POINT(1, 300) }; }
+static fixed_point accel_horiz () { return           FIXED_POINT(0,  50); }
+static fixed_point accel_vert  () { return           FIXED_POINT(0, 167); }
+static fixed_point drag_factor () { return           FIXED_POINT(0, 854); }
 
 static inline int imax(int x, int y) {
   return x < y ? y : x;
@@ -80,15 +80,15 @@ jumpnrun_tile_range jumpnrun_visible_tiles(jumpnrun_level const *lv,
 }
 
 void jumpnrun_apply_gravity(vec2d *inertia) {
-  *inertia = vec2d_add(*inertia, gravity);
+  *inertia = vec2d_add(*inertia, gravity());
 }
 
 void jumpnrun_passive_movement(vec2d *inertia)
 {
   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);
+  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);
 }
 
 static void jumpnrun_apply_movement(jumpnrun_level      const *lv,
@@ -99,18 +99,18 @@ static void jumpnrun_apply_movement(jumpnrun_level      const *lv,
          (BADGE_EVENT_KEY_LEFT |
           BADGE_EVENT_KEY_RIGHT)) {
   case BADGE_EVENT_KEY_LEFT:
-    //    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.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.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.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(jumpnrun_moveable_touching_ground(&state->player.base)) {
-      state->player.base.inertia.x = fixed_point_mul(state->player.base.inertia.x, drag_factor);
+      state->player.base.inertia.x = fixed_point_mul(state->player.base.inertia.x, drag_factor());
     } //else {
       //state->player.base.inertia.x = FIXED_INT(0);
     //}
@@ -121,7 +121,7 @@ static void jumpnrun_apply_movement(jumpnrun_level      const *lv,
   if(state->player.base.jumpable_frames == 0) {
     // intentionally left blank.
   } else if(badge_event_current_input_state() & BADGE_EVENT_KEY_BTN_A) {
-    state->player.base.inertia.y = fixed_point_sub(state->player.base.inertia.y, accel_vert);
+    state->player.base.inertia.y = fixed_point_sub(state->player.base.inertia.y, accel_vert());
     --state->player.base.jumpable_frames;
   } else {
     state->player.base.jumpable_frames = 0;
@@ -140,8 +140,10 @@ static void jumpnrun_apply_movement(jumpnrun_level      const *lv,
   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.base.hitbox.pos.y, FIXED_INT(BADGE_DISPLAY_HEIGHT))) {
-    state->player.base.flags |= JUMPNRUN_PLAYER_DEAD;
+  if(fixed_point_gt(rectangle_top(&state->player.base.hitbox), FIXED_INT(BADGE_DISPLAY_HEIGHT))) {
+    jumpnrun_player_despawn(&state->player);
+  } else if(killed) {
+    jumpnrun_player_kill   (&state->player);
   }
 }
 
@@ -151,18 +153,20 @@ void jumpnrun_level_tick(jumpnrun_level      *lv,
   jumpnrun_tile_range tilerange = jumpnrun_visible_tiles(lv, state);
   vec2d inertia_mod = state->player.base.inertia;
 
-  jumpnrun_apply_movement(lv, &tilerange, state, &inertia_mod);
+  if(jumpnrun_player_alive(&state->player)) {
+    jumpnrun_apply_movement(lv, &tilerange, state, &inertia_mod);
+  }
+
   state->screen_left = jumpnrun_level_assert_left_side(state);
 
-  if(state->player.base.tick_minor == 0) {
-    badge_framebuffer fb;
-    badge_framebuffer_clear(&fb);
+  if(state->tick == 0) {
+    badge_framebuffer fb = { { { 0 } } };
 
-    for(size_t tile = tilerange.first; tile < tilerange.last; ++tile) {
+    for(uint16_t tile = tilerange.first; tile < tilerange.last; ++tile) {
       jumpnrun_render_tile(&fb, state, &lv->tiles[tile]);
     }
 
-    for(size_t item = 0; item < lv->header.item_count; ++item) {
+    for(uint16_t item = 0; item < lv->header.item_count; ++item) {
       jumpnrun_item *item_obj = &lv->items[item];
 
       if(item_obj->flags & JUMPNRUN_ITEM_COLLECTED) {
@@ -182,7 +186,7 @@ void jumpnrun_level_tick(jumpnrun_level      *lv,
       }
     }
 
-    for(size_t shot_ix = 0; shot_ix < JUMPNRUN_MAX_SHOTS; ++shot_ix) {
+    for(uint16_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)) {
@@ -190,12 +194,20 @@ void jumpnrun_level_tick(jumpnrun_level      *lv,
       }
     }
 
-    for(size_t enemy_ix = 0; enemy_ix < lv->header.enemy_count; ++enemy_ix) {
+    for(uint16_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, &inertia_mod);
     }
 
-    jumpnrun_render_player(&fb, state);
+    if(jumpnrun_player_alive(&state->player)) {
+      jumpnrun_render_player(&fb, state);
+      jumpnrun_player_advance_animation(&state->player);
+    } else if(jumpnrun_moveable_finished_dying(&state->player.base)) {
+      jumpnrun_player_despawn(&state->player);
+    } else if(jumpnrun_moveable_dying(&state->player.base)) {
+      jumpnrun_render_splosion(&fb, state, &state->player.base);
+      state->player.base.tick_minor += JUMPNRUN_STATE_TICKS_PER_FRAME;
+    }
 
     badge_framebuffer_flush(&fb);
 
@@ -207,31 +219,33 @@ void jumpnrun_level_tick(jumpnrun_level      *lv,
       state->player.base.anim_frame = 0;
     }
   } else {
-    for(size_t shot_ix = 0; shot_ix < JUMPNRUN_MAX_SHOTS; ++shot_ix) {
+    for(uint16_t shot_ix = 0; shot_ix < JUMPNRUN_MAX_SHOTS; ++shot_ix) {
       jumpnrun_shot_process(&state->shots[shot_ix]);
     }
 
-    for(size_t enemy_ix = 0; enemy_ix < lv->header.enemy_count; ++enemy_ix) {
+    for(uint16_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, &inertia_mod);
     }
   }
 
   state->player.base.inertia = inertia_mod;
-  ++state->player.base.tick_minor;
-  if(state->player.base.tick_minor == 3) {
-    state->player.base.tick_minor = 0;
+  ++state->tick;
+  if(state->tick == JUMPNRUN_STATE_TICKS_PER_FRAME) {
+    state->tick = 0;
   }
 }
 
-uint8_t jumpnrun_play(char const *lvname) {
+uint8_t jumpnrun_play_level(char const *lvname) {
   jumpnrun_level lv;
 
   JUMPNRUN_LEVEL_LOAD(lv, lvname);
 
   jumpnrun_game_state gs;
 
-  for(jumpnrun_game_state_init(&gs, &lv); (gs.flags & JUMPNRUN_STATE_WON) == 0 && gs.player.lives != 0; --gs.player.lives) {
+  jumpnrun_game_state_init(&gs, &lv);
+
+  do {
     jumpnrun_show_lives_screen(&gs);
     jumpnrun_game_state_respawn(&gs, &lv);
 
@@ -269,9 +283,17 @@ uint8_t jumpnrun_play(char const *lvname) {
       }
       }
     }
+  } while((gs.flags & JUMPNRUN_STATE_WON) == 0 && gs.player.lives-- != 0);
+
+  if(gs.flags & JUMPNRUN_STATE_WON) {
+    jumpnrun_show_you_rock();
+    return JUMPNRUN_WON;
+  }
+
+  if(++gs.player.lives == 0) {
+    jumpnrun_show_game_over();
+    return JUMPNRUN_LOST;
   }
 
-  if(gs.flags & JUMPNRUN_STATE_WON) { return JUMPNRUN_WON; }
-  if(gs.player.lives == 0) return JUMPNRUN_LOST;
   return JUMPNRUN_ERROR;
 }
This page took 0.034644 seconds and 4 git commands to generate.