#include "art/game_player.h" #include "art/game_tiles.h" #include "device/device.h" #include "map/game_map.h" #include "game.h" #include "sys/sys.h" game_bbox game_player_bbox = { .x_origin=0x0500, .y_origin=0x0c00, .x=0x9000, .y=0x1000, .w=0x0a00, .h=0x0c00, }; bool game_player_grounded = false; sys_i32 game_player_jump_frames = 0; sys_i32 game_player_coyote_frames = 0; sys_i32 game_player_dx = 0; sys_i32 game_player_dy = 0; bool game_player_faceleft = false; typedef enum { GAME_PLAYER_ANIM_STANDING, GAME_PLAYER_ANIM_WALKING, GAME_PLAYER_ANIM_FLOATING, } game_player_anim; game_player_anim game_player_anim_state = GAME_PLAYER_ANIM_STANDING; uint8_t game_player_anim_progress = 0; void game_player_anim_transition(game_player_anim anim); void game_player_anim_add_progress(uint8_t amt); void game_player_init() { game_player_bbox.x = game_map_player_start_x; game_player_bbox.y = game_map_player_start_y; } void game_player_update(bool* allow_input) { game_collision collision = game_collision_move_to_contact( &game_player_bbox, game_player_dx, game_player_dy ); if (collision.collided_x) { game_player_dx = 0; } if (collision.collided_y) { game_player_dy = 0; } game_player_grounded = !game_collision_can_move( game_player_bbox, 0, 1 ); { sys_i32 fric_numerator = game_player_grounded ? 0x70 : 0x7f; game_player_dx = ( game_player_dx * fric_numerator + // round up 0x7f * sys_sgn_i32(game_player_dx) ) / 0x80; if (sys_abs_i32(game_player_dx) > 0x140) { game_player_dx = sys_sgn_i32(game_player_dx) * 0x140; } int wanted_dx = game_player_dx; if (*allow_input && sys_btn(DEVICE_BUTTON_L)) { wanted_dx -= 0x50; } if (*allow_input && sys_btn(DEVICE_BUTTON_R)) { wanted_dx += 0x50; } // allow this if grounded or if it's not a change of direction if ( /* game_player_grounded || (sys_sgn_i32(wanted_dx) == sys_sgn_i32(game_player_dx)) */ true ) { game_player_dx = wanted_dx; } else { // the smallest possible amount of movement without changing sign game_player_dx = sys_sgn_i32(game_player_dx); } } if (game_player_grounded || game_player_coyote_frames > 0) { if (*allow_input && sys_btnp(DEVICE_BUTTON_U, false)) { game_player_dy = -0x200; game_player_jump_frames = 13; game_player_grounded = false; } } if (game_player_dx < 0) { game_player_faceleft = true; } if (game_player_dx > 0) { game_player_faceleft = false; } bool wants_to_go_higher = false; if (game_player_grounded) { game_player_coyote_frames = 5; if (game_player_dy > 0) { game_player_dy = 0; } if (sys_abs_i32(game_player_dx) < 0x20) { game_player_dx = 0; } } else { game_player_coyote_frames = sys_max_i32(0, game_player_coyote_frames - 1); wants_to_go_higher = sys_btn(DEVICE_BUTTON_U); bool is_going_higher = wants_to_go_higher && game_player_jump_frames > 0; if (game_player_dy >= 0 || !is_going_higher) { game_player_dy += 48; } else { game_player_jump_frames -= 1; } } // deduce animation state if (game_player_grounded) { if (game_player_dx == 0) { game_player_anim_transition(GAME_PLAYER_ANIM_STANDING); } else { game_player_anim_transition(GAME_PLAYER_ANIM_WALKING); game_player_anim_add_progress( sys_min_i32(sys_abs_i32(game_player_dx) / 0x10, 0x20) ); } } else { if (wants_to_go_higher) { game_player_anim_transition(GAME_PLAYER_ANIM_FLOATING); } else { game_player_anim_transition(GAME_PLAYER_ANIM_STANDING); } } } void game_player_set_camera() { sys_i32 x = game_player_bbox.x; sys_i32 y = game_player_bbox.y; // TODO: Use round_down et al sys_i32 x_pixel = x / PIXEL_SZ_MICROPIXEL; sys_i32 y_pixel = y / PIXEL_SZ_MICROPIXEL; sys_i32 x_topcorner = x_pixel - x_pixel % DEVICE_W; sys_i32 y_topcorner = y_pixel - y_pixel % DEVICE_H; sys_camera_set(x_topcorner, y_topcorner); } void game_player_draw() { int game_player_image; switch (game_player_anim_state) { case GAME_PLAYER_ANIM_WALKING: game_player_image = 2 + (game_player_anim_progress / 0x80) * 2; break; case GAME_PLAYER_ANIM_FLOATING: game_player_image = 6; break; default: case GAME_PLAYER_ANIM_STANDING: game_player_image = 0; break; } sys_sprite_draw_ext( spr_game_player, game_player_image, game_player_bbox.x / 0x100 - 8, game_player_bbox.y / 0x100 - 16, 2, 2, game_player_faceleft, false ); } void game_player_anim_transition(game_player_anim anim) { if (game_player_anim_state == anim) { return ;} game_player_anim_state = anim; game_player_anim_progress = 0; } void game_player_anim_add_progress(uint8_t amt) { game_player_anim_progress = ( (uint32_t) game_player_anim_progress + (uint32_t) amt ) & 0xff; } void game_player_get_center(sys_i32* x, sys_i32* y) { *x = game_player_bbox.x; // center on me, not on feet *y = game_player_bbox.y - 8 * PIXEL_SZ_MICROPIXEL; }