Squashed commit of the following: commit 053c06ea29702728e2605899a2b47edac647c459 Author: Alvie Rahman <alvierahman90@gmail.com> Date: Sat Dec 3 16:09:51 2022 +0000 begin documentation on codebase: sprite metadata commit 435f0c62743112818594f4b1a902d90d1f60823a Author: Alvie Rahman <alvierahman90@gmail.com> Date: Sat Dec 3 16:05:37 2022 +0000 formatting, mostly commit f338476aaf4c33081969b18b2a6d13a3639571cd Author: Alvie Rahman <alvierahman90@gmail.com> Date: Fri Dec 2 23:18:27 2022 +0000 way faster collisions
174 lines
6.4 KiB
C
174 lines
6.4 KiB
C
#include <gb/gb.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include "./vec.h"
|
|
#include "./constants.h"
|
|
#include "./flags.h"
|
|
#include "./map.h"
|
|
|
|
|
|
#define LYO 8
|
|
#define GET_TILE_INDEX_BY_COORD(x, y) ((((y) / PIXELS_PER_TILE) * 20) + ((x) / PIXELS_PER_TILE))
|
|
|
|
typedef struct Sprites {
|
|
int gb_sprite_index;
|
|
int frames_since_last_dash;
|
|
int frames_since_last_jump;
|
|
int bitmap_index_prev;
|
|
int bitmap_index;
|
|
int bitmap_indexes[8];
|
|
int bitmap_prop[8];
|
|
int has_diag_sprites;
|
|
int has_joypad;
|
|
char name[20];
|
|
int collision_offset[8][12];
|
|
UVec pos;
|
|
Vec vel;
|
|
Vec acc;
|
|
} Sprite;
|
|
|
|
|
|
void sprite_iter_frame(Sprite *sprite, Map *map, int joypad, unsigned int *fc);
|
|
void sprite_draw_to_screen(Sprite *sprite);
|
|
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)
|
|
{
|
|
unsigned int colx, coly;
|
|
UVec original_position;
|
|
|
|
// target displacement is sprite->vel but may collide, giving actual displacment
|
|
|
|
if (sprite->frames_since_last_jump <= JUMP_TIMEOUT_FRAMES) sprite->frames_since_last_jump++;
|
|
if (sprite->frames_since_last_dash <= DASH_TIMEOUT_FRAMES) sprite->frames_since_last_dash++;
|
|
|
|
if (*fc % 2 == 0) {
|
|
sprite->vel.y += GRAV_ACC;
|
|
*fc = 0;
|
|
}
|
|
|
|
// 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;
|
|
else sprite->acc.x = -sprite->vel.x/abs(sprite->vel.x);
|
|
sprite->vel.x += sprite->acc.x;
|
|
|
|
// player dash
|
|
if ((joypad & J_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;
|
|
}
|
|
}
|
|
|
|
// 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 = TERM_VELY;
|
|
if (sprite->vel.y < -TERM_VELY) sprite->vel.y += (abs(sprite->vel.y)-TERM_VELY)/TERM_VELY_DIVISOR;
|
|
|
|
int *offsets = sprite->collision_offset[sprite->bitmap_index];
|
|
// jump if on platform
|
|
if ((joypad & J_A) && (sprite->frames_since_last_jump > JUMP_TIMEOUT_FRAMES)) {
|
|
coly = map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[0], sprite->pos.y - offsets[3]-LYO+1)];
|
|
if (!coly) coly += map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[2], sprite->pos.y - offsets[3]-LYO+1)];
|
|
if(coly) {
|
|
sprite->vel.y = -JUMP_VEL;
|
|
sprite->frames_since_last_jump = 0;
|
|
}
|
|
}
|
|
|
|
original_position.x = sprite->pos.x;
|
|
original_position.y = sprite->pos.y;
|
|
// check if following the path by the velocity will lead to a collision
|
|
|
|
// if no velocity component, pretend sprite has already collided
|
|
colx = sprite->vel.x == 0;
|
|
coly = sprite->vel.y == 0;
|
|
|
|
//for (int step = collision_check_steps; step >= 0; step--) {
|
|
if(sprite->vel.y != 0){
|
|
sprite->pos.y = original_position.y + sprite->vel.y;
|
|
|
|
if (sprite->vel.y < 0) {
|
|
coly += map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[0], sprite->pos.y - offsets[1]-LYO)];
|
|
if (!coly) coly += map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[2], sprite->pos.y - offsets[1]-LYO)];
|
|
} else if (sprite->vel.y > 0) {
|
|
coly += map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[0], sprite->pos.y - offsets[3]-LYO)];
|
|
if (!coly) coly += map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[2], sprite->pos.y - offsets[3]-LYO)];
|
|
}
|
|
|
|
if (coly) sprite->pos.y = original_position.y;
|
|
}
|
|
|
|
if(sprite->vel.x != 0) {
|
|
sprite->pos.x = original_position.x + sprite->vel.x;
|
|
|
|
if (sprite->vel.x < 0) {
|
|
colx += map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[0], sprite->pos.y - offsets[1]-LYO)];
|
|
if(!colx) colx += map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[0], sprite->pos.y - offsets[3]-LYO)];
|
|
} else if (sprite->vel.x > 0) {
|
|
colx += map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[2], sprite->pos.y - offsets[1]-LYO)];
|
|
if(!colx) colx += map->data[GET_TILE_INDEX_BY_COORD(sprite->pos.x - offsets[2], sprite->pos.y - offsets[3]-LYO)];
|
|
}
|
|
|
|
if (colx) sprite->pos.x = original_position.x;
|
|
}
|
|
|
|
sprite_update_bitmap(sprite);
|
|
sprite_draw_to_screen(sprite);
|
|
}
|
|
|
|
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;
|
|
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;
|
|
|
|
else if ( sprite->vel.y < 0) sprite->bitmap_index = SI_UP;
|
|
else if ( sprite->vel.y > 0) sprite->bitmap_index = SI_DOWN;
|
|
else if ( sprite->vel.x > 0) sprite->bitmap_index = SI_RIGHT;
|
|
else if ( sprite->vel.x < 0) sprite->bitmap_index = SI_LEFT;
|
|
}
|
|
|
|
void sprite_draw_to_screen(Sprite *sprite)
|
|
{
|
|
int bmi = sprite->bitmap_index;
|
|
|
|
if (sprite->bitmap_index_prev != bmi) {
|
|
set_sprite_tile(sprite->gb_sprite_index, sprite->bitmap_indexes[bmi]);
|
|
set_sprite_prop(sprite->gb_sprite_index, sprite->bitmap_prop[bmi]);
|
|
}
|
|
move_sprite(sprite->gb_sprite_index, sprite->pos.x, sprite->pos.y);
|
|
}
|