#include #include #include #include "draw.h" #include "collide.h" #include "levels.h" #include "player.h" #define MAX_HSPD 2.5 #define ACCELERATION 1 #define DECELERATION 0.5 #define MIN_VSPD -12.0 #define MAX_VSPD 12 #define JUMP_SPD -3.99 #define GRAV 0.4 #define JUMP_SCALE 12 #define JUMP_REDUCTION -0.41 #define UG_CAN_JUMP upgrades[0] char coins[256]; #define DRAW_LEVEL() draw_level(level, upgrades, coins[coin_id]) void dupdate(); //gint function //test if jump pressed int sgn(int number); //return the sign of input double int callback(volatile void *arg) { volatile int *has_ticked = arg; *has_ticked = 1; return 0; } int main(void) { volatile int has_ticked = 1; //fps cap char level[477]; int level_id = 5050; //START UPGRADES char upgrades[] = { 0 //jump }; //END UPGRADES unsigned int coin_id = 0; unsigned int coin_count = 0; char jump_pressed = 1; //avoid holding jump char jump_buffer = 0; //jump buffer, last 3 frames unsigned int jump_hold = 0; //number of consecutive frames jump has been held double vspd = 0.0; //player vertical speed double hspd = 0; //player horizontal speed int move = 0; int direction = 0; int on_ground = 6; //remember if player is on solid int player_x = 0; int player_y = 0; int start_x = 18*16 + 2; int start_y = 9*16 + 4; int old_x, old_y; char spawn_buffer = 0; unsigned int step = 0; set_level(level_id, level, &coin_id); DRAW_LEVEL(); draw_level_anims(level, upgrades, step); player_x = start_x; player_y = start_y; old_x = player_x + 1; //offset to draw it on first cycle old_y = player_y; //fps cap timer timer_setup(0, timer_delay(0, 16667), 0, callback, &has_ticked); timer_start(0); while (1) { while(!has_ticked) sleep(); has_ticked = 0; //START DRAW step++; draw_level_anims(level, upgrades, step); draw_player(old_x, old_y, player_x, player_y); draw_timer(step); dupdate(); old_y = player_y; old_x = player_x; //END DRAW clearevents(); //horizontal movement & collision { move = 0; double friction = 1; int trunc_hspd; //ice if (collide(player_x, player_y + 1, level, '~')) friction = 0.2; move = keydown(KEY_RIGHT) + 0 - keydown(KEY_LEFT); if (move) { if (hspd < MAX_HSPD) { hspd += ACCELERATION * friction; if (hspd > MAX_HSPD) hspd = MAX_HSPD; } direction = move; } else if (hspd > 0) { if (friction != 0.2) hspd -= DECELERATION * friction; else hspd -= DECELERATION / 4 * friction; if (hspd < 0) hspd = 0; } trunc_hspd = hspd * direction; if (!collide(player_x, player_y + 1, level, '#')) { if (!collide_solid(player_x + trunc_hspd, player_y, level)) { player_x += trunc_hspd; } else { int sign_hspd = sgn(trunc_hspd); while (!collide_solid(player_x + sign_hspd, player_y, level)) { player_x += sign_hspd; } hspd = 0; } } } //ground detection if (vspd >= 0 && collide_solid(player_x, player_y + 1, level)) { on_ground = 6; vspd = 0; if (spawn_buffer) { spawn_buffer = 0; set_start_pos(&start_x, &start_y, player_x, player_y); } } else { if (on_ground != 6 && vspd < MAX_VSPD) vspd += GRAV; if (on_ground) on_ground--; } //vertical movement if (UG_CAN_JUMP) jump_test(&jump_pressed, &jump_buffer, &jump_hold); //jump if (jump_buffer && on_ground) { vspd = JUMP_SPD; on_ground = 0; jump_hold = JUMP_SCALE; } else if (jump_hold && keydown(KEY_SHIFT)) { jump_hold--; vspd += JUMP_REDUCTION; } else jump_hold = 0; //elevator collision and raise if ((collide(player_x - 1, player_y, level, '^') || collide(player_x + 1, player_y, level, '^')) && vspd > MIN_VSPD) { if (vspd > -2) { vspd -= GRAV; } vspd -= GRAV; } //vertical collision { int trunc_vspd = vspd; //truncate vspd if (trunc_vspd) { if (!collide_solid(player_x, player_y + trunc_vspd, level)) { player_y += trunc_vspd; } else { int sign_vspd = sgn(trunc_vspd); while (!collide_solid(player_x, player_y + sign_vspd, level)) { player_y += sign_vspd; } vspd = 0; jump_hold = 0; } } } //spike collision and death if (collide(player_x, player_y, level, 'v')) { player_x = start_x; player_y = start_y; vspd = 0; } //borders collision if (player_x <= 22) { level_id -= 1; player_x = 414 + (move * (int) hspd); set_start_pos(&start_x, &start_y, player_x, player_y); set_level(level_id, level, &coin_id); DRAW_LEVEL(); reset_old_pos(&old_x, &old_y); } else if (player_x >= 416) { level_id += 1; player_x = 24 + (move * (int) hspd); set_start_pos(&start_x, &start_y, player_x, player_y); set_level(level_id, level, &coin_id); DRAW_LEVEL(); reset_old_pos(&old_x, &old_y); } else if (player_y <= 8) { level_id -= 100; player_y = 246; spawn_buffer = 1; set_start_pos(&start_x, &start_y, player_x, player_y); set_level(level_id, level, &coin_id); DRAW_LEVEL(); reset_old_pos(&old_x, &old_y); } else if (player_y >= 248) { level_id += 100; player_y = 10; set_start_pos(&start_x, &start_y, player_x, player_y); set_level(level_id, level, &coin_id); DRAW_LEVEL(); reset_old_pos(&old_x, &old_y); } //item get if (collide(player_x, player_y, level, 'j')) { UG_CAN_JUMP = 1; collide_and_erase(player_x, player_y, level, 'j'); draw_upgrade_message('j'); } //coin get if (collide(player_x, player_y, level, 'c')) { coins[coin_id] = 1; coin_count++; collide_and_erase(player_x, player_y, level, 'c'); } //secret way/hidden passage collide_and_erase(player_x, player_y, level, 's'); //exit if (keydown(KEY_EXIT)) return 0; } } int sgn(int number) { if (number < 0) return -1; else return 1; }