#include #include #include #include "draw.h" #include "collide.h" #include "levels.h" #include "player.h" #define WALK_SPD 2 #define MIN_VSPD -12.0 #define MAX_VSPD 12 #define JUMP_SPD -4.2 #define GRAV 0.4 #define JUMP_SCALE 12 #define JUMP_REDUCTION -0.4 #define UG_CAN_JUMP upgrades[0] void dupdate(); //gint function //test if jump pressed void jump_test(char *jump_pressed, char *jump_buffer, unsigned int *jump_hold); 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 (mostly bools) char upgrades[] = { 0 //can jump }; //end upgrades 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; //player vertical speed char hspd = 0; //player horizontal speed 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; set_level(level_id, level); draw_level(level, upgrades); 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; draw_player(old_x, old_y, player_x, player_y); dupdate(); old_x = player_x; old_y = player_y; clearevents(); //horizontal movement hspd = 0; if (keydown(KEY_LEFT)) hspd -= WALK_SPD; if (keydown(KEY_RIGHT)) hspd += WALK_SPD; if (!collide_solid(player_x + hspd, player_y, level)) { player_x += hspd; } //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 = 416 + hspd; set_start_pos(&start_x, &start_y, player_x, player_y); set_level(level_id, level); draw_level(level, upgrades); reset_old_pos(&old_x, &old_y); } else if (player_x >= 416) { level_id += 1; player_x = 22 + hspd; set_start_pos(&start_x, &start_y, player_x, player_y); set_level(level_id, level); draw_level(level, upgrades); reset_old_pos(&old_x, &old_y); } else if (player_y <= 8) { level_id -= 100; player_y = 246; spawn_buffer = 1; set_level(level_id, level); draw_level(level, upgrades); 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); draw_level(level, upgrades); reset_old_pos(&old_x, &old_y); } //item get if (collide(player_x, player_y, level, 'j')) { UG_CAN_JUMP = 1; erase_tile(player_x, player_y, level); draw_upgrade_message('j'); } //exit if (keydown(KEY_EXIT)) return 0; } } int sgn(int number) { if (number < 0) return -1; else return 1; }