first commit - a kind of working thingy

This commit is contained in:
2022-06-06 22:19:34 +01:00
commit c78bc5e88b
19 changed files with 652 additions and 0 deletions

224
src/main.c Normal file
View File

@@ -0,0 +1,224 @@
#include <gb/gb.h>
#include <stdlib.h>
#include "../res/tiles.h"
#include "../res/map.h"
#include"../res/sprites.h"
#include "./flags.h"
#include "./constants.h"
#include "./vec.c"
int getTileIndexByCoord(unsigned int x, unsigned int y)
{
return ((y / PIXELS_PER_TILE) * 20) + (x / PIXELS_PER_TILE);
}
// check for external collisions (if rectangle is at least touchign something)
unsigned int collision(unsigned char map[], struct UVec *sprite_pos, struct UVec *sprite_size)
{
unsigned int rv = 0;
struct UVec itl, itr, ibl, ibr;
itl.x = sprite_pos->x-8; itl.y = sprite_pos->y-16;
itr.x = sprite_pos->x-1; itr.y = sprite_pos->y-16;
ibl.x = sprite_pos->x-8; ibl.y = sprite_pos->y-9;
ibr.x = sprite_pos->x-1; ibr.y = sprite_pos->y-9;
// check if corners are in a non 0 tile
if (map[getTileIndexByCoord(itl.x, itl.y-1)]) rv = rv | SC_TL;
if (map[getTileIndexByCoord(itr.x, itr.y-1)]) rv = rv | SC_TR;
if (map[getTileIndexByCoord(ibl.x, ibl.y+1)]) rv = rv | SC_BL;
if (map[getTileIndexByCoord(ibr.x, ibr.y+1)]) rv = rv | SC_BR;
if (map[getTileIndexByCoord(itl.x-1, itl.y)]) rv = rv | SC_LT;
if (map[getTileIndexByCoord(ibl.x-1, ibl.y)]) rv = rv | SC_LB;
if (map[getTileIndexByCoord(itr.x+1, itr.y)]) rv = rv | SC_RT;
if (map[getTileIndexByCoord(ibr.x+1, ibr.y)]) rv = rv | SC_RB;
return rv;
}
// calculate internal collisions from external collisions
unsigned int icollision(unsigned char map[], struct UVec *sprite_pos, struct UVec *sprite_size)
{
unsigned int c, rv = 0;
struct UVec itl, itr, ibl, ibr;
itl.x = sprite_pos->x-8; itl.y = sprite_pos->y-16;
itr.x = sprite_pos->x-1; itr.y = sprite_pos->y-16;
ibl.x = sprite_pos->x-8; ibl.y = sprite_pos->y-9;
ibr.x = sprite_pos->x-1; ibr.y = sprite_pos->y-9;
if (map[getTileIndexByCoord(itl.x, itl.y)]) rv = rv | SC_ITL;
if (map[getTileIndexByCoord(itr.x, itr.y)]) rv = rv | SC_ITR;
if (map[getTileIndexByCoord(ibl.x, ibl.y)]) rv = rv | SC_IBL;
if (map[getTileIndexByCoord(ibr.x, ibr.y)]) rv = rv | SC_IBR;
return rv;
}
void init_gfx()
{
// Load Background tiles and then map
set_bkg_data(0, 23, tiles);
set_bkg_tiles(0, 0, mapWidth, mapHeight, map);
set_sprite_data(0, 11, sprites);
set_sprite_tile(0, 2);
set_sprite_prop(0, 0);
// Turn the background map on to make it visible
SHOW_BKG;
SHOW_SPRITES;
}
void main(void)
{
unsigned int c, search_found, frames_since_last_jump, frames_since_last_dash, fc = 0;
int xsearch, ysearch;
struct UVec sprite_pos, search_pos, sprite_size;
struct Vec velocity, acceleration;
init_gfx();
sprite_pos.x = 72;
sprite_pos.y = 35;
sprite_size.x = 8;
sprite_size.y = 8;
frames_since_last_jump = JUMP_TIMEOUT_FRAMES;
frames_since_last_dash = DASH_TIMEOUT_FRAMES;
velocity.x = 0;
velocity.y = 0;
acceleration.x = 0;
acceleration.y = 0;
move_sprite(0, sprite_pos.x, sprite_pos.y);
// Loop forever
while(1) {
// the gameboy simulates physics too quickly to have good control over the speeds of things
// so draw them less often and move them more
if (frames_since_last_jump <= JUMP_TIMEOUT_FRAMES) frames_since_last_jump++;
if (frames_since_last_dash <= DASH_TIMEOUT_FRAMES) frames_since_last_dash++;
if (++fc % 2 == 0) {
velocity.y += GRAV_ACC;
fc = 0;
}
// player move left/right
if ((joypad() & J_RIGHT) && (velocity.x < TERM_VELX)) acceleration.x = 1;
else if ((joypad() & J_LEFT) && (velocity.x > -TERM_VELX)) acceleration.x = -1;
else acceleration.x = -velocity.x/abs(velocity.x);
velocity.x += acceleration.x;
// player dash
if ((joypad() & J_B) && (frames_since_last_dash > DASH_TIMEOUT_FRAMES)) {
int frames_since_last_dash_copy = frames_since_last_dash;
frames_since_last_dash = 0;
if ((joypad() & J_LEFT) && !(joypad() & (J_UP | J_RIGHT | J_DOWN))) {
velocity.x = -DASH_VELL;
} else if ((joypad() & J_RIGHT) && !(joypad() & (J_UP | J_LEFT | J_DOWN))) {
velocity.x = DASH_VELL;
} else if ((joypad() & J_UP) && !(joypad() & (J_RIGHT | J_LEFT | J_DOWN))) {
velocity.y = -DASH_VELL;
} else if ((joypad() & J_DOWN) && !(joypad() & (J_UP | J_LEFT | J_RIGHT))) {
velocity.y = DASH_VELL;
} else if ((joypad() & J_RIGHT) && (joypad() & J_UP)) {
velocity.x = DASH_VELD;
velocity.y = -DASH_VELD;
} else if ((joypad() & J_LEFT) && (joypad() & J_UP)) {
velocity.x = -DASH_VELD;
velocity.y = -DASH_VELD;
} else if ((joypad() & J_LEFT) && (joypad() & J_DOWN)) {
velocity.x = -DASH_VELD;
velocity.y = DASH_VELD;
} else if ((joypad() & J_RIGHT) && (joypad() & J_DOWN)) {
velocity.x = DASH_VELD;
velocity.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
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 velocity square but not
// sure if that is worth the compute yet)
if (velocity.y > TERM_VELY) velocity.y -= (abs(velocity.y)-TERM_VELY)/TERM_VELY_DIVISOR;
if (velocity.y < -TERM_VELY) velocity.y += (abs(velocity.y)-TERM_VELY)/TERM_VELY_DIVISOR;
if (velocity.x > TERM_VELX) velocity.x -= (abs(velocity.x)-TERM_VELX)/TERM_VELX_DIVISOR;
if (velocity.x < -TERM_VELX) velocity.x += (abs(velocity.x)-TERM_VELX)/TERM_VELX_DIVISOR;
// don't let player move in a direction which they are already touching something
if (((c & SC_TL) | (c & SC_TR)) && (velocity.y < 0)) { velocity.y = 0; }
if (((c & SC_BL) | (c & SC_BR)) && (velocity.y > 0)) {
// player jump
if ((joypad() & J_A) && (frames_since_last_jump > JUMP_TIMEOUT_FRAMES)) {
velocity.y = -JUMP_VEL;
frames_since_last_jump = 0;
}
else velocity.y = 0;
}
if (((c & SC_RT) | (c & SC_RB)) && (velocity.x > 0)) { velocity.x = 0; }
if (((c & SC_LT) | (c & SC_LB)) && (velocity.x < 0)) { velocity.x = 0; }
sprite_pos.x += velocity.x;
sprite_pos.y += velocity.y;
c = collision(map, &sprite_pos, &sprite_size);
// move player out of tiles by brute force searching :eyes:
// TODO this is really stupid and bad and i think it will have to be changed when there
// are more players moving around
search_found = 0;
for (ysearch = 0; ysearch <= SPRITE_HEIGHT; ysearch++) {
for (xsearch = 0; xsearch <= SPRITE_WIDTH; xsearch++) {
search_pos.x = sprite_pos.x + xsearch;
search_pos.y = sprite_pos.y + ysearch;
if(icollision(map, &search_pos, &sprite_size) == 0) {
sprite_pos.x = search_pos.x;
sprite_pos.y = search_pos.y;
search_found = 1;
break;
}
search_pos.x = sprite_pos.x - xsearch;
search_pos.y = sprite_pos.y + ysearch;
if(icollision(map, &search_pos, &sprite_size) == 0) {
sprite_pos.x = search_pos.x;
sprite_pos.y = search_pos.y;
search_found = 1;
break;
}
search_pos.x = sprite_pos.x - xsearch;
search_pos.y = sprite_pos.y - ysearch;
if(icollision(map, &search_pos, &sprite_size) == 0) {
sprite_pos.x = search_pos.x;
sprite_pos.y = search_pos.y;
search_found = 1;
break;
}
search_pos.x = sprite_pos.x + xsearch;
search_pos.y = sprite_pos.y - ysearch;
if(icollision(map, &search_pos, &sprite_size) == 0) {
sprite_pos.x = search_pos.x;
sprite_pos.y = search_pos.y;
search_found = 1;
break;
}
}
if (search_found) break;
}
// finally move the sprite
move_sprite(0, sprite_pos.x, sprite_pos.y);
// Done processing, yield CPU and wait for start of next frame
wait_vbl_done();
}
}