diff --git a/src/main.c b/src/main.c index a162d82..31999db 100644 --- a/src/main.c +++ b/src/main.c @@ -12,7 +12,7 @@ #include "./sprite.h" #include "./vec.h" -#define NO_SCREEN_SPRITES 6 +#define NO_SCREEN_SPRITES 3 void init_gfx() { @@ -35,12 +35,9 @@ void main(void) memcpy(&(screen_sprites[0]), &(sprites_info[2]), sizeof(Sprite)); - memcpy(&(screen_sprites[1]), &(sprites_info[0]), sizeof(Sprite)); + memcpy(&(screen_sprites[1]), &(sprites_info[1]), sizeof(Sprite)); memcpy(&(screen_sprites[2]), &(sprites_info[0]), sizeof(Sprite)); - memcpy(&(screen_sprites[3]), &(sprites_info[0]), sizeof(Sprite)); - memcpy(&(screen_sprites[4]), &(sprites_info[0]), sizeof(Sprite)); - memcpy(&(screen_sprites[5]), &(sprites_info[0]), sizeof(Sprite)); - screen_sprites[1].has_joypad = 1; + screen_sprites[0].has_joypad = 1; for (i = 0; i < NO_SCREEN_SPRITES; i++) { screen_sprites[i].bitmap_index_prev = -1; diff --git a/src/sprite.c b/src/sprite.c index f238686..84b4bdf 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -46,8 +46,6 @@ typedef struct Sprites { int get_tile_index_by_coord(unsigned int x, unsigned int y); void sprite_iter_frame(Sprite *sprite, Map *map, int joypad, unsigned int *fc); -unsigned int sprite_internal_collision(Map *map, Sprite *sprite); -unsigned int sprite_collision(Map *map, Sprite *sprite); void sprite_draw_to_screen(Sprite *sprite); void sprite_update_bitmap(Sprite *sprite); @@ -55,7 +53,12 @@ void sprite_update_bitmap(Sprite *sprite); // update a sprite for stuff that changes every frame void sprite_iter_frame(Sprite *sprite, Map *map, int joypad, unsigned int *fc) { - int c, collision_check_steps, absvelx = abs(sprite->vel.x), absvely = abs(sprite->vel.y); + SpriteCorners sc; + int c, collision_check_steps, sprite_internal_collision, + absvelx = abs(sprite->vel.x), absvely = abs(sprite->vel.y); + int b_right = joypad & J_RIGHT, b_left = joypad & J_LEFT, b_up = joypad & J_UP, + b_down = joypad & J_DOWN, b_a = joypad & J_A, b_b = joypad & J_B; + int tl, tr, bl, br, lt, lb, rt, rb; // target displacement is sprite->vel but may collide, giving actual displacment Vec displacement = {.x = 0, .y = 0}; @@ -70,71 +73,91 @@ void sprite_iter_frame(Sprite *sprite, Map *map, int joypad, unsigned int *fc) } // player move left/right - if ((joypad & J_RIGHT) && (sprite->vel.x < TERM_VELX)) sprite->acc.x = 1; - else if ((joypad & J_LEFT) && (sprite->vel.x > -TERM_VELX)) sprite->acc.x = -1; + if ((joypad & b_right) && (sprite->vel.x < TERM_VELX)) sprite->acc.x = 1; + else if ((joypad & b_left) && (sprite->vel.x > -TERM_VELX)) sprite->acc.x = -1; else sprite->acc.x = -sprite->vel.x/absvelx; sprite->vel.x += sprite->acc.x; // player dash - if ((joypad & J_B) && (sprite->frames_since_last_dash > DASH_TIMEOUT_FRAMES)) { + if (b_b && (sprite->frames_since_last_dash > DASH_TIMEOUT_FRAMES)) { int frames_since_last_dash_copy = sprite->frames_since_last_dash; sprite->frames_since_last_dash = 0; - if ((joypad & J_LEFT) && !(joypad & (J_UP | J_RIGHT | J_DOWN))) { - sprite->vel.x = -DASH_VELL; - } else if ((joypad & J_RIGHT) && !(joypad & (J_UP | J_LEFT | J_DOWN))) { - sprite->vel.x = DASH_VELL; - } else if ((joypad & J_UP) && !(joypad & (J_RIGHT | J_LEFT | J_DOWN))) { - sprite->vel.y = -DASH_VELL; - } else if ((joypad & J_DOWN) && !(joypad & (J_UP | J_LEFT | J_RIGHT))) { - sprite->vel.y = DASH_VELL; - } else if ((joypad & J_RIGHT) && (joypad & J_UP)) { - sprite->vel.x = DASH_VELD; - sprite->vel.y = -DASH_VELD; - } else if ((joypad & J_LEFT) && (joypad & J_UP)) { - sprite->vel.x = -DASH_VELD; - sprite->vel.y = -DASH_VELD; - } else if ((joypad & J_LEFT) && (joypad & J_DOWN)) { - sprite->vel.x = -DASH_VELD; - sprite->vel.y = DASH_VELD; - } else if ((joypad & J_RIGHT) && (joypad & J_DOWN)) { - sprite->vel.x = DASH_VELD; - sprite->vel.y = DASH_VELD; - } else { - // if player doesn't hold the right buttons to dash, don't dash and set the - // frames_since_last_dash counter back to what it was before - sprite->frames_since_last_dash = frames_since_last_dash_copy; + if (b_left) { + if (b_up) { + sprite->vel.x = -DASH_VELD; + sprite->vel.y = -DASH_VELD; + } else if (b_down) { + sprite->vel.x = -DASH_VELD; + sprite->vel.y = DASH_VELD; + } else { + sprite->vel.x = -DASH_VELL; + } + } else if (b_right) { + if (b_up) { + sprite->vel.x = DASH_VELD; + sprite->vel.y = -DASH_VELD; + } else if (b_down) { + sprite->vel.x = DASH_VELD; + sprite->vel.y = DASH_VELD; + } else { + sprite->vel.x = DASH_VELL; + } } + else if (b_up) sprite->vel.y = -DASH_VELL; + else if (b_down) sprite->vel.y = DASH_VELL; + // if player doesn't hold the right buttons to dash, don't dash and set the + // frames_since_last_dash counter back to what it was before + else sprite->frames_since_last_dash = frames_since_last_dash_copy; } // slow down sprite in kind of realistic way // (in real life i think it's drag is proportional to sprite->vel square but not // sure if that is worth the compute yet cause everythign else is shit) - //if (sprite->vel.y > TERM_VELY) sprite->vel.y -= (absvely-TERM_VELY)/TERM_VELY_DIVISOR; - //if (sprite->vel.y < -TERM_VELY) sprite->vel.y += (absvely-TERM_VELY)/TERM_VELY_DIVISOR; - //if (sprite->vel.x > TERM_VELX) sprite->vel.x -= (absvelx-TERM_VELX)/TERM_VELX_DIVISOR; - //if (sprite->vel.x < -TERM_VELX) sprite->vel.x += (absvelx-TERM_VELX)/TERM_VELX_DIVISOR; - // - //absvelx = abs(sprite->vel.x); - //absvely = abs(sprite->vel.y); + if (sprite->vel.y > TERM_VELY) sprite->vel.y -= (absvely-TERM_VELY)/TERM_VELY_DIVISOR; + if (sprite->vel.y < -TERM_VELY) sprite->vel.y += (absvely-TERM_VELY)/TERM_VELY_DIVISOR; + if (sprite->vel.x > TERM_VELX) sprite->vel.x -= (absvelx-TERM_VELX)/TERM_VELX_DIVISOR; + if (sprite->vel.x < -TERM_VELX) sprite->vel.x += (absvelx-TERM_VELX)/TERM_VELX_DIVISOR; + + absvelx = abs(sprite->vel.x); + absvely = abs(sprite->vel.y); // if sprite not moving, no more logic needs to be done --- right? if ((absvelx == 0) && (absvely == 0)) return; - c = sprite_collision(map, sprite); + GET_SPRITE_CORNERS(sprite, sc); // don't let player move in a direction which they are already touching something - if (((c & SC_TL) | (c & SC_TR)) && (sprite->vel.y < 0)) { sprite->vel.y = 0; } - if (((c & SC_BL) | (c & SC_BR)) && (sprite->vel.y > 0)) { - // player jump - if ((joypad & J_A) && (sprite->frames_since_last_jump > JUMP_TIMEOUT_FRAMES)) { - sprite->vel.y = -JUMP_VEL; - sprite->frames_since_last_jump = 0; + if (sprite->vel.y > 0) { + br = map->data[GET_TILE_INDEX_BY_COORD(sc.ibl.x, sc.ibl.y+1)]; + bl = map->data[GET_TILE_INDEX_BY_COORD(sc.ibr.x, sc.ibr.y+1)]; + + if (bl | br) { + sprite->vel.y = 0; + // player jump + if (b_a && (sprite->frames_since_last_jump > JUMP_TIMEOUT_FRAMES)) { + sprite->vel.y = -JUMP_VEL; + sprite->frames_since_last_jump = 0; + } } - else sprite->vel.y = 0; + } else if (sprite->vel.y < 0) { + tl = map->data[GET_TILE_INDEX_BY_COORD(sc.itl.x, sc.itl.y-1)]; + tr = map->data[GET_TILE_INDEX_BY_COORD(sc.itr.x, sc.itr.y-1)]; + if (tl | tr) sprite->vel.y = 0; } - if (((c & SC_RT) | (c & SC_RB)) && (sprite->vel.x > 0)) { sprite->vel.x = 0; } - if (((c & SC_LT) | (c & SC_LB)) && (sprite->vel.x < 0)) { sprite->vel.x = 0; } + + if (sprite->vel.x > 0) { + rt = map->data[GET_TILE_INDEX_BY_COORD(sc.itr.x+1, sc.itr.y)]; + rb = map->data[GET_TILE_INDEX_BY_COORD(sc.ibr.x+1, sc.ibr.y)]; + if (rt | rb) sprite->vel.x = 0; + } else if (sprite->vel.x < 0) { + lt = map->data[GET_TILE_INDEX_BY_COORD(sc.itl.x-1, sc.itl.y)]; + lb = map->data[GET_TILE_INDEX_BY_COORD(sc.ibl.x-1, sc.ibl.y)]; + if (lt | lb) sprite->vel.x = 0; + } + + absvelx = abs(sprite->vel.x); + absvely = abs(sprite->vel.y); collision_check_steps = (absvelx > absvely) ? absvelx : absvely; @@ -145,57 +168,24 @@ void sprite_iter_frame(Sprite *sprite, Map *map, int joypad, unsigned int *fc) sprite->pos.x = original_position.x + ((step * sprite->vel.x)/collision_check_steps); sprite->pos.y = original_position.y + ((step * sprite->vel.y)/collision_check_steps); - if (!sprite_internal_collision(map, sprite)) break; + sprite_internal_collision = 0; + if (map->data[GET_TILE_INDEX_BY_COORD(sc.itl.x, sc.itl.y)]) sprite_internal_collision++; + if (map->data[GET_TILE_INDEX_BY_COORD(sc.itr.x, sc.itr.y)]) sprite_internal_collision++; + if (map->data[GET_TILE_INDEX_BY_COORD(sc.ibl.x, sc.ibl.y)]) sprite_internal_collision++; + if (map->data[GET_TILE_INDEX_BY_COORD(sc.ibr.x, sc.ibr.y)]) sprite_internal_collision++; + if (sprite_internal_collision == 0) break; } - sprite_update_bitmap(sprite); sprite_draw_to_screen(sprite); move_sprite(sprite->gb_sprite_index, sprite->pos.x, sprite->pos.y); } -// calculate internal collisions -unsigned int sprite_internal_collision(Map *map, Sprite *sprite) -{ - unsigned int rv = 0; - SpriteCorners sc; - GET_SPRITE_CORNERS(sprite, sc); - // (((y / PIXELS_PER_TILE) * 20) + (x / PIXELS_PER_TILE)) - if (map->data[GET_TILE_INDEX_BY_COORD(sc.itl.x, sc.itl.y)]) rv = rv | SC_ITL; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.itr.x, sc.itr.y)]) rv = rv | SC_ITR; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.ibl.x, sc.ibl.y)]) rv = rv | SC_IBL; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.ibr.x, sc.ibr.y)]) rv = rv | SC_IBR; - - return rv; -} - - -// check for external collisions (if rectangle is at least touchign something) -unsigned int sprite_collision(Map *map, Sprite *sprite) -{ - unsigned int rv = 0; - SpriteCorners sc; - GET_SPRITE_CORNERS(sprite, sc); - - // check if corners are in a non 0 tile - if (map->data[GET_TILE_INDEX_BY_COORD(sc.itl.x, sc.itl.y-1)]) rv = rv | SC_TL; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.itr.x, sc.itr.y-1)]) rv = rv | SC_TR; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.ibl.x, sc.ibl.y+1)]) rv = rv | SC_BL; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.ibr.x, sc.ibr.y+1)]) rv = rv | SC_BR; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.itl.x-1, sc.itl.y )]) rv = rv | SC_LT; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.ibl.x-1, sc.ibl.y )]) rv = rv | SC_LB; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.itr.x+1, sc.itr.y )]) rv = rv | SC_RT; - if (map->data[GET_TILE_INDEX_BY_COORD(sc.ibr.x+1, sc.ibr.y )]) rv = rv | SC_RB; - - return rv; -} - +// set new sprite bitmap void sprite_update_bitmap(Sprite *sprite) { - sprite->bitmap_index_prev = sprite->bitmap_index; - - if ((sprite->vel.y > 0) && (sprite->vel.x > 0)) sprite->bitmap_index = SI_DOWN_RIGHT; + if ((sprite->vel.y > 0) && (sprite->vel.x > 0)) sprite->bitmap_index = SI_DOWN_RIGHT; else if ((sprite->vel.y < 0) && (sprite->vel.x > 0)) sprite->bitmap_index = SI_UP_RIGHT; else if ((sprite->vel.y > 0) && (sprite->vel.x < 0)) sprite->bitmap_index = SI_DOWN_LEFT; else if ((sprite->vel.y < 0) && (sprite->vel.x < 0)) sprite->bitmap_index = SI_UP_LEFT; @@ -208,6 +198,8 @@ void sprite_update_bitmap(Sprite *sprite) void sprite_draw_to_screen(Sprite *sprite) { + // only set sprite if sprite to be used has changed + sprite_update_bitmap(sprite); if (sprite->bitmap_index_prev != sprite->bitmap_index) { set_sprite_tile(sprite->gb_sprite_index, sprite->bitmap_indexes[sprite->bitmap_index]); set_sprite_prop(sprite->gb_sprite_index, sprite->bitmap_prop[sprite->bitmap_index]);