Compare commits

..

8 Commits

12 changed files with 444 additions and 131 deletions

View File

@@ -16,3 +16,10 @@ make all
```
the gameboy rom will be output to `obj/untitled2dshooter.gb`
## credits
### art
a cool guy named louie - drew mike

210
res/sprite_metadata.c Normal file
View File

@@ -0,0 +1,210 @@
#include <gb/gb.h>
#include "../src/sprite.h"
#include "../src/flags.h"
Sprite sprites_info[] = {
{
.frames_since_last_dash = 0,
.frames_since_last_jump = 0,
.name = "arrow",
.has_diag_sprites = 0,
.bitmap_index = SI_LEFT,
.has_joypad = 0,
.pos = { .x = 0, .y = 0},
.vel = { .x = 0, .y = 0},
.acc = { .x = 0, .y = 0},
.bitmap_indexes[SI_UP] = 12, .bitmap_prop[SI_UP] = 0,
.collision_offset[SI_UP] = {
.itl = { .x = 3, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 3, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_DOWN] = 12, .bitmap_prop[SI_DOWN] = S_FLIPY,
.collision_offset[SI_DOWN] = {
.itl = { .x = 3, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 3, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_LEFT] = 11, .bitmap_prop[SI_LEFT] = 0,
.collision_offset[SI_LEFT] = {
.itl = { .x = 8, .y = 3},
.itr = { .x = 1, .y = 3},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_RIGHT] = 11, .bitmap_prop[SI_RIGHT] = S_FLIPX,
.collision_offset[SI_RIGHT] = {
.itl = { .x = 8, .y = 3},
.itr = { .x = 1, .y = 3},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_UP_RIGHT] = 13, .bitmap_prop[SI_UP_RIGHT] = 0,
.collision_offset[SI_UP_RIGHT] = {
.itl = { .x = 7, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 7, .y = 2},
.ibr = { .x = 1, .y = 2},
},
.bitmap_indexes[SI_UP_LEFT] = 13, .bitmap_prop[SI_UP_LEFT] = S_FLIPX,
.collision_offset[SI_UP_LEFT] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 2, .y = 8},
.ibl = { .x = 8, .y = 2},
.ibr = { .x = 2, .y = 2},
},
.bitmap_indexes[SI_DOWN_LEFT] = 13, .bitmap_prop[SI_DOWN_LEFT] = S_FLIPX | S_FLIPY,
.collision_offset[SI_DOWN_LEFT] = {
.itl = { .x = 8, .y = 7},
.itr = { .x = 2, .y = 7},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 2, .y = 1},
},
.bitmap_indexes[SI_DOWN_RIGHT] = 13, .bitmap_prop[SI_DOWN_RIGHT] = S_FLIPY,
.collision_offset[SI_DOWN_RIGHT] = {
.itl = { .x = 7, .y = 7},
.itr = { .x = 1, .y = 7},
.ibl = { .x = 7, .y = 1},
.ibr = { .x = 1, .y = 1},
}
},
{
.frames_since_last_dash = 0,
.frames_since_last_jump = 0,
.name = "dodgy_hat_guy",
.has_diag_sprites = 0,
.bitmap_index = SI_LEFT,
.has_joypad = 0,
.pos = { .x = 0, .y = 0},
.vel = { .x = 0, .y = 0},
.acc = { .x = 0, .y = 0},
.bitmap_indexes[SI_UP] = 14, .bitmap_prop[SI_UP] = 0,
.collision_offset[SI_UP] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_DOWN] = 15, .bitmap_prop[SI_DOWN] = 0,
.collision_offset[SI_DOWN] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_LEFT] = 14, .bitmap_prop[SI_LEFT] = 0,
.collision_offset[SI_LEFT] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_RIGHT] = 14, .bitmap_prop[SI_RIGHT] = S_FLIPX,
.collision_offset[SI_RIGHT] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_UP_RIGHT] = 14, .bitmap_prop[SI_UP_RIGHT] = 0,
.collision_offset[SI_UP_RIGHT] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_UP_LEFT] = 14, .bitmap_prop[SI_UP_LEFT] = S_FLIPX,
.collision_offset[SI_UP_LEFT] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_DOWN_LEFT] = 15, .bitmap_prop[SI_DOWN_LEFT] = 0,
.collision_offset[SI_DOWN_LEFT] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_DOWN_RIGHT] = 15, .bitmap_prop[SI_DOWN_RIGHT] = S_FLIPX,
.collision_offset[SI_DOWN_RIGHT] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
}
},
{
.frames_since_last_dash = 0,
.frames_since_last_jump = 0,
.name = "mike",
.has_diag_sprites = 0,
.bitmap_index = SI_LEFT,
.has_joypad = 0,
.pos = { .x = 0, .y = 0},
.vel = { .x = 0, .y = 0},
.acc = { .x = 0, .y = 0},
.bitmap_indexes[SI_UP] = 25, .bitmap_prop[SI_UP] = 0,
.collision_offset[SI_UP] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_DOWN] = 22, .bitmap_prop[SI_DOWN] = 0,
.collision_offset[SI_DOWN] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_LEFT] = 21, .bitmap_prop[SI_LEFT] = 0,
.collision_offset[SI_LEFT] = {
.itl = { .x = 8, .y = 5},
.itr = { .x = 1, .y = 5},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_RIGHT] = 21, .bitmap_prop[SI_RIGHT] = S_FLIPX,
.collision_offset[SI_RIGHT] = {
.itl = { .x = 8, .y = 5},
.itr = { .x = 1, .y = 5},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_UP_RIGHT] = 23, .bitmap_prop[SI_UP_RIGHT] = 0,
.collision_offset[SI_UP_RIGHT] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_UP_LEFT] = 23, .bitmap_prop[SI_UP_LEFT] = S_FLIPX,
.collision_offset[SI_UP_LEFT] = {
.itl = { .x = 8, .y = 8},
.itr = { .x = 1, .y = 8},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_DOWN_LEFT] = 24, .bitmap_prop[SI_DOWN_LEFT] = S_FLIPX,
.collision_offset[SI_DOWN_LEFT] = {
.itl = { .x = 8, .y = 7},
.itr = { .x = 1, .y = 7},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
},
.bitmap_indexes[SI_DOWN_RIGHT] = 24, .bitmap_prop[SI_DOWN_RIGHT] = 0,
.collision_offset[SI_DOWN_RIGHT] = {
.itl = { .x = 8, .y = 7},
.itr = { .x = 1, .y = 7},
.ibl = { .x = 8, .y = 1},
.ibr = { .x = 1, .y = 1},
}
}
};

3
res/sprite_metadata.h Normal file
View File

@@ -0,0 +1,3 @@
#include "../src/sprite.h"
extern Sprite sprites_info[];

View File

@@ -10,7 +10,7 @@
Compression : None.
Counter : None.
Tile size : 8 x 8
Tiles : 0 to 10
Tiles : 0 to 25
Palette colors : None.
SGB Palette : None.
@@ -25,8 +25,8 @@
/* Start of tile array. */
unsigned char sprites[] =
{
0xF7,0x08,0xED,0x12,0xFE,0x11,0xFF,0x38,
0xFE,0x39,0xFE,0x39,0xFF,0x7E,0xFF,0x6E,
0xFF,0x19,0xEF,0x17,0xFF,0x11,0xFF,0x3B,
0xFE,0x3F,0xFE,0x3D,0xFF,0x7E,0xFF,0x6E,
0xFF,0x00,0xC3,0x42,0x81,0x00,0x81,0x00,
0x81,0x00,0x81,0x00,0xC3,0x42,0xFF,0x00,
0xC3,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E,
@@ -46,7 +46,37 @@ unsigned char sprites[] =
0xC3,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E,
0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0x42,0xC3,
0x43,0xC3,0xDB,0xDB,0x3C,0x3C,0x7E,0x7E,
0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0x43,0xC3
0x7E,0x7E,0x3C,0x3C,0xDB,0xDB,0x43,0xC3,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x43,0x38,0xC6,0x00,0x43,
0x00,0x02,0x00,0x07,0x02,0x00,0x02,0x00,
0x02,0x00,0x00,0x02,0x00,0x07,0x00,0x05,
0x00,0x03,0x02,0x01,0x04,0x00,0x08,0x00,
0x00,0x30,0x00,0x50,0x00,0x20,0x00,0x00,
0x38,0x38,0x7C,0x7C,0x7C,0x44,0x38,0x00,
0x18,0x00,0x18,0x18,0xBD,0xBD,0xBD,0xBD,
0x38,0x38,0x7C,0x7C,0x7C,0x44,0x39,0x01,
0x99,0x81,0x98,0x98,0x3C,0x3C,0x3C,0x3C,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,
0x25,0xFE,0x18,0xE7,0x7E,0xFF,0x00,0xDB,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,
0x38,0xEE,0x52,0xAD,0x7C,0xFF,0x01,0xD7,
0x00,0x38,0x10,0x6E,0x2C,0x77,0x22,0xDD,
0x7E,0xFF,0x12,0xC9,0x18,0xE7,0x00,0x7E,
0x00,0x38,0x10,0x6C,0x3C,0xC6,0x60,0xBF,
0x0E,0xFF,0x78,0xF3,0x00,0xDE,0x00,0x70,
0x00,0x00,0x30,0x4C,0x70,0x9E,0x06,0xFB,
0x7C,0xF3,0x0E,0x5F,0x00,0x7B,0x00,0x1E,
0x00,0x7E,0x18,0xE7,0x36,0xED,0x02,0xFD,
0x7E,0xFF,0x08,0x53,0x10,0x6E,0x00,0x38
};
/* End of SPRITES.C */

Binary file not shown.

View File

@@ -10,7 +10,7 @@
Compression : None.
Counter : None.
Tile size : 8 x 8
Tiles : 0 to 10
Tiles : 0 to 25
Palette colors : None.
SGB Palette : None.

View File

@@ -25,8 +25,8 @@
/* Start of tile array. */
unsigned char tiles[] =
{
0x10,0x00,0x00,0x00,0x08,0x00,0x10,0x00,
0x30,0x00,0x20,0x00,0x60,0x00,0x50,0x20,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0xFF,0xFF,0xFF,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,
0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,

Binary file not shown.

View File

@@ -24,6 +24,15 @@
#define SC_IBL 0b0010
#define SC_IBR 0b0001
#define SI_UP 0
#define SI_DOWN 1
#define SI_LEFT 2
#define SI_RIGHT 3
#define SI_UP_RIGHT 4
#define SI_DOWN_RIGHT 5
#define SI_UP_LEFT 6
#define SI_DOWN_LEFT 7
/* Sprite Collision point diagram:
* x TL LT x
* ------------

View File

@@ -1,22 +1,25 @@
#include <gb/gb.h>
#include <gb/drawing.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "../res/tiles.h"
#include "../res/map.h"
#include"../res/sprites.h"
#include"../res/sprite_metadata.h"
#include "./flags.h"
#include "./constants.h"
#include "./sprite.h"
#include "./vec.h"
#define NO_SCREEN_SPRITES 3
void init_gfx()
{
// Load Background tiles and then map
set_bkg_data(0, 23, tiles);
set_bkg_tiles(0, 0, map.width, map.height, map.data);
set_sprite_data(0, 11, sprites);
set_sprite_tile(0, 2);
set_sprite_prop(0, 0);
set_sprite_data(0, 26, sprites);
// Turn the background map on to make it visible
SHOW_BKG;
@@ -25,25 +28,33 @@ void init_gfx()
void main(void)
{
unsigned int fc = 0;
struct Sprites sprite;
init_gfx();
sprite.pos.x = 72;
sprite.pos.y = 36;
sprite.vel.x = 0;
sprite.vel.y = 0;
sprite.acc.x = 0;
sprite.acc.y = 0;
move_sprite(0, sprite.pos.x, sprite.pos.y);
unsigned int i, jp, fc = 0;
struct Sprites screen_sprites[NO_SCREEN_SPRITES];
memcpy(&(screen_sprites[0]), &(sprites_info[2]), sizeof(Sprite));
memcpy(&(screen_sprites[1]), &(sprites_info[1]), sizeof(Sprite));
memcpy(&(screen_sprites[2]), &(sprites_info[0]), sizeof(Sprite));
screen_sprites[0].has_joypad = 1;
for (i = 0; i < NO_SCREEN_SPRITES; i++) {
screen_sprites[i].bitmap_index_prev = -1;
screen_sprites[i].gb_sprite_index = i;
screen_sprites[i].pos.x = 72+(8*i);
screen_sprites[i].pos.y = 36+(8*i);
sprite_draw_to_screen(&(screen_sprites[i]));
}
// Loop forever
while(1) {
fc++;
sprite_iter_frame(&sprite, &map, joypad(), &fc);
move_sprite(0, sprite.pos.x, sprite.pos.y);
jp = joypad();
for (i = 0; i < NO_SCREEN_SPRITES; i++) {
sprite_iter_frame(&(screen_sprites[i]), &map, screen_sprites[i].has_joypad ? jp : 0, &fc);
}
// Done processing, yield CPU and wait for start of next frame
wait_vbl_done();

View File

@@ -5,15 +5,17 @@
#include "./flags.h"
#include "./map.h"
#define GET_TILE_INDEX_BY_COORD(x, y) ((((y) / PIXELS_PER_TILE) * 20) + ((x) / PIXELS_PER_TILE))
typedef struct Sprites {
int frames_since_last_dash;
int frames_since_last_jump;
int size;
UVec pos;
Vec vel;
Vec acc;
} Sprite;
#define GET_SPRITE_CORNERS(sprite, sc) \
sc.itl.x = sprite->pos.x - sprite->collision_offset[sprite->bitmap_index].itl.x; \
sc.itl.y = sprite->pos.y - sprite->collision_offset[sprite->bitmap_index].itl.y - 8; \
sc.itr.x = sprite->pos.x - sprite->collision_offset[sprite->bitmap_index].itr.x; \
sc.itr.y = sprite->pos.y - sprite->collision_offset[sprite->bitmap_index].itr.y - 8; \
sc.ibl.x = sprite->pos.x - sprite->collision_offset[sprite->bitmap_index].ibl.x; \
sc.ibl.y = sprite->pos.y - sprite->collision_offset[sprite->bitmap_index].ibl.y - 8; \
sc.ibr.x = sprite->pos.x - sprite->collision_offset[sprite->bitmap_index].ibr.x; \
sc.ibr.y = sprite->pos.y - sprite->collision_offset[sprite->bitmap_index].ibr.y - 8;
typedef struct SpriteCorners {
@@ -24,36 +26,39 @@ typedef struct SpriteCorners {
} SpriteCorners;
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];
SpriteCorners collision_offset[8];
UVec pos;
Vec vel;
Vec acc;
} Sprite;
int get_tile_index_by_coord(unsigned int x, unsigned int y);
void getSpriteCorners(Sprite *sprite, SpriteCorners *r);
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);
int get_tile_index_by_coord(unsigned int x, unsigned int y)
{
return ((y / PIXELS_PER_TILE) * 20) + (x / PIXELS_PER_TILE);
}
void getSpriteCorners(Sprite *sprite, SpriteCorners *sc)
{
sc->itl.x = sprite->pos.x-8;
sc->itl.y = sprite->pos.y-16;
sc->itr.x = sprite->pos.x-1;
sc->itr.y = sprite->pos.y-16;
sc->ibl.x = sprite->pos.x-8;
sc->ibl.y = sprite->pos.y-9 ;
sc->ibr.x = sprite->pos.x-1;
sc->ibr.y = sprite->pos.y-9;
}
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)
{
int c, collision_check_steps;
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};
@@ -68,68 +73,92 @@ 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;
else sprite->acc.x = -sprite->vel.x/abs(sprite->vel.x);
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 -= (abs(sprite->vel.y)-TERM_VELY)/TERM_VELY_DIVISOR;
if (sprite->vel.y < -TERM_VELY) sprite->vel.y += (abs(sprite->vel.y)-TERM_VELY)/TERM_VELY_DIVISOR;
if (sprite->vel.x > TERM_VELX) sprite->vel.x -= (abs(sprite->vel.x)-TERM_VELX)/TERM_VELX_DIVISOR;
if (sprite->vel.x < -TERM_VELX) sprite->vel.x += (abs(sprite->vel.x)-TERM_VELX)/TERM_VELX_DIVISOR;
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;
c = sprite_collision(map, sprite);
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;
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;
}
else 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.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 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 (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);
int absvelx = abs(sprite->vel.x);
int absvely = abs(sprite->vel.y);
collision_check_steps = (absvelx > absvely) ? absvelx : absvely;
original_position.x = sprite->pos.x;
@@ -139,43 +168,41 @@ 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_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)
// set new sprite bitmap
void sprite_update_bitmap(Sprite *sprite)
{
unsigned int rv = 0;
SpriteCorners sc;
getSpriteCorners(sprite, &sc);
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;
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;
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;
}
// check for external collisions (if rectangle is at least touchign something)
unsigned int sprite_collision(Map *map, Sprite *sprite)
void sprite_draw_to_screen(Sprite *sprite)
{
unsigned int rv = 0;
SpriteCorners sc;
getSpriteCorners(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;
// 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]);
}
move_sprite(sprite->gb_sprite_index, sprite->pos.x, sprite->pos.y);
}

View File

@@ -4,10 +4,25 @@
#include "./vec.h"
#include "./map.h"
typedef struct SpriteCorners {
UVec itl;
UVec itr;
UVec ibl;
UVec ibr;
} SpriteCorners;
typedef struct Sprites {
int gb_sprite_index;
int frames_since_last_dash;
int frames_since_last_jump;
int size;
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];
SpriteCorners collision_offset[8];
UVec pos;
Vec vel;
Vec acc;
@@ -16,5 +31,6 @@ typedef struct Sprites {
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);
#endif