#include #include #include #include #include "draw.h" #include "collide.h" #include "levels.h" #include "player.h" #define MAX_HSPD 2.5 #define ACCELERATION 1.0 #define DECELERATION 0.5 #define MIN_VSPD -12.0 #define MAX_VSPD 6.0 #define JUMP_SPD -3.99 #define GRAV 0.4 #define JUMP_SCALE 8 #define JUMP_REDUCTION -0.41 #define DRAW_LEVEL() draw_level(level, step, polarity, &start_x, &start_y) 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; 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 char in_water = 0; int player_x = 0; int player_y = 0; int start_x = 18*16 + 2; int start_y = 9*16 + 4; char spawn_buffer = 0; unsigned int step = 0; char pswap_held = 0; char polarity = 0; //0 -> blue, 1 -> red set_level(level_id, level); DRAW_LEVEL(); player_x = start_x; player_y = start_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(); draw_player(player_x, player_y); draw_timer(step); dupdate(); //END DRAW clearevents(); //polarity swap first if (keydown(KEY_OPTN)) { if (!pswap_held) { pswap_held = 1; polarity = !polarity; } } else pswap_held = 0; //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 (1) //glue was here { if (!collide_solid(player_x + trunc_hspd, player_y, level, polarity)) { player_x += trunc_hspd; } else { int sign_hspd = sgn(trunc_hspd); while (!collide_solid(player_x + sign_hspd, player_y, level, polarity)) { player_x += sign_hspd; } hspd = 0; } } } //ground detection if (vspd >= 0 && collide_solid(player_x, player_y + 1, level, polarity)) { 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 / (1 + in_water); if (on_ground) on_ground--; } //in water? in_water = collide(player_x, player_y, level, 'w'); //vertical movement jump_test(&jump_pressed, &jump_buffer, &jump_hold); //jump if (jump_buffer && (on_ground || in_water)) { 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; if (in_water) trunc_vspd = vspd / 2; else trunc_vspd = vspd; //bouncer if (collide(player_x, player_y + trunc_vspd, level, '*')) { vspd = -vspd - 2; trunc_vspd = vspd; } if (trunc_vspd) { if (!collide_solid(player_x, player_y + trunc_vspd, level, polarity)) { player_y += trunc_vspd; } else { int sign_vspd = sgn(trunc_vspd); while (!collide_solid(player_x, player_y + sign_vspd, level, polarity)) { 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; polarity = 0; vspd = 0; } //border warp if (player_x <= 22) player_x = 414; else if (player_x >= 416) player_x = 24; else if (player_y <= 8) player_y = 246; else if (player_y >= 248) player_y = 10; //secret way/hidden passage collide_and_erase(player_x, player_y, level, 's'); //next level (exit) if (collide(player_x, player_y, level, 'E')) { level_id++; set_level(level_id, level); DRAW_LEVEL(); dprint(100, 0, C_WHITE, C_BLACK, "%d", level_id); player_x = start_x; player_y = start_y; polarity = 0; vspd = 0; } //exit if (keydown(KEY_EXIT)) return 0; } } int sgn(int number) { if (number < 0) return -1; else return 1; }