#include #include "keyb.h" #include "vga.h" #include "map.h" #include "data.h" #include "game.h" #include "player.h" #define DIR_RIGHT 0 #define DIR_LEFT 1 #define FRAME_STANDING 0 #define FRAME_JUMPING 4 #define FRAME_DYING 5 #define WALK_CYCLE_FRAMES 4 #define WALK_DELAY 8 #define GRAVITY_OFF 0 /* XXX: subtract 1 to get the value from gravity_seq */ #define GRAVITY_DOWN 14 #define GRAVITY_UP 1 #define GRAVITY_SEQ_LEN 24 #define IS_NOT_GOING_UP(x) (gravity == GRAVITY_OFF || (x)>=GRAVITY_DOWN) static uint16_t x, y; static uint8_t dir, frame, delay, gravity, jump; const uint8_t gravity_seq[GRAVITY_SEQ_LEN] = { 6, 4, 4, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 4 }; static uint8_t bg[256]; static const Rect frames[2][6] = { { /* walk cycle */ { 0, 0, 144, 144 }, { 16, 0, 144, 144 }, { 0, 0, 144, 144 }, { 32, 0, 144, 144 }, /* jump */ { 48, 0, 144, 144 }, /* dying */ { 128, 0, 144, 144 }, }, { /* walk cycle */ { 64, 0, 144, 144 }, { 80, 0, 144, 144 }, { 64, 0, 144, 144 }, { 96, 0, 144, 144 }, /* jump */ { 112, 0, 144, 144 }, /* dying */ { 128, 0, 144, 144 }, }, }; void player_init(uint16_t start_x, uint8_t start_y) { dir = DIR_RIGHT; frame = FRAME_STANDING; delay = 0; jump = 0; x = start_x; y = start_y; gravity = GRAVITY_OFF; } void player_update() { uint8_t moved = 0; if (gravity == GRAVITY_OFF && !map_is_blocked(x + 4, y + 16) && !map_is_blocked(x + 11, y + 16)) { gravity = GRAVITY_DOWN; frame = FRAME_JUMPING; moved = 1; } if (keys[KEY_UP]) { if (gravity == GRAVITY_OFF && !jump) { jump = 1; frame = FRAME_JUMPING; gravity = GRAVITY_UP; } } else jump = 0; if (keys[KEY_RIGHT] && !keys[KEY_LEFT]) { moved = 1; dir = DIR_RIGHT; /* XXX: off limits */ if (x < MAP_W * MAP_TILE_W - 16) { if ((IS_NOT_GOING_UP(gravity) && !map_is_blocked(x + 16, y + 15)) || (!IS_NOT_GOING_UP(gravity) && !(map_is_blocked(x + 16, y + 15) && map_is_blocked(x + 16, y + 7)))) x++; } } if (keys[KEY_LEFT] && !keys[KEY_RIGHT]) { moved = 1; dir = DIR_LEFT; /* XXX: off limits */ if (x) { if ((IS_NOT_GOING_UP(gravity) && !map_is_blocked(x - 1, y + 15)) || (!IS_NOT_GOING_UP(gravity) && !(map_is_blocked(x - 1, y + 15) && map_is_blocked(x - 1, y + 7)))) x--; } } if (gravity != GRAVITY_OFF) { uint8_t steps = gravity_seq[gravity - 1]; moved = 1; if (gravity > GRAVITY_DOWN) { /* going down! */ for (uint8_t i = 0; i < steps; i++) { /* hit the floor */ if ((map_is_blocked(x + 11, y + 16) || map_is_blocked(x + 4, y + 16)) && !map_is_blocked(x + 4, y + 15) && !map_is_blocked(x + 11, y + 15)) { gravity = GRAVITY_OFF; frame = FRAME_STANDING; break; } y++; } } else { /* going up! */ if (y < steps) y = 0; else y -= steps; } if (gravity != GRAVITY_OFF && gravity != GRAVITY_SEQ_LEN) gravity++; } if (moved) { if (delay++ == WALK_DELAY) { delay = 0; if (frame != FRAME_JUMPING) { frame++; if (frame == WALK_CYCLE_FRAMES) frame = FRAME_STANDING; } } } else { delay = 0; frame = FRAME_STANDING; } if (map_update_gold(x + (dir == DIR_LEFT ? 7 : 8), y + 15)) add_score(10); } void player_erase() { Rect dst = { x, y + MAP_OFFS_Y, 16, 16 }; blit(bg, &dst); } void player_draw() { Rect dst = { x, y + MAP_OFFS_Y, 16, 16 }; read_buffer(bg, &dst); blitrc(binary_sprites_start, &frames[dir][frame], &dst); }