Implement terrain collisions
This commit is contained in:
parent
f17530af4a
commit
c24cd75360
56
app/main.c
56
app/main.c
@ -34,11 +34,17 @@
|
||||
#define PWIDTH 48
|
||||
#define PHEIGHT 64
|
||||
#define PANIMLEN 8
|
||||
#define PFBWIDTH 12
|
||||
#define PFBHEIGHT 6
|
||||
#define PFBOFFX -6
|
||||
#define PFBOFFY 6
|
||||
|
||||
#define WALKSPEED 72 // pixels per second
|
||||
|
||||
#define BASEANIMPERIOD 100
|
||||
|
||||
#define NELEMS(a) (sizeof(a) / sizeof(a[0]))
|
||||
|
||||
typedef enum {
|
||||
SPRITE_DIR_DOWN = 0,
|
||||
SPRITE_DIR_LEFT_DOWN = 1,
|
||||
@ -61,12 +67,34 @@ static SDL_Renderer *renderer;
|
||||
static unsigned map[MAPWIDTH][MAPHEIGHT];
|
||||
static SDL_Texture *tstex, *pidle, *pwalk, *ptex;
|
||||
static input_state_t input;
|
||||
static dvec_t vpos = { 512, 0 };
|
||||
static const unsigned passable[] = { 118, 178 };
|
||||
|
||||
static inline double mag(dvec_t v)
|
||||
{
|
||||
return sqrt(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
static inline unsigned tileat(double x, double y)
|
||||
{
|
||||
const unsigned row = (unsigned)floor(x / TILESIZE) + MAPSHIFTX;
|
||||
const unsigned col = (unsigned)floor(y / TILESIZE) + MAPSHIFTY;
|
||||
if (row >= MAPWIDTH || col >= MAPHEIGHT)
|
||||
return 0;
|
||||
else
|
||||
return map[row][col];
|
||||
}
|
||||
|
||||
static inline bool tilepassable(int x, int y)
|
||||
{
|
||||
const unsigned id = tileat(x, y);
|
||||
for (unsigned i = 0; i < NELEMS(passable); ++i) {
|
||||
if (passable[i] == id)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char path[MAX_PATH_LEN];
|
||||
@ -176,8 +204,7 @@ int main(int argc, char *argv[])
|
||||
pwalk = IMG_LoadTexture(renderer, path);
|
||||
assert(NULL != pwalk);
|
||||
|
||||
// Initialize view and player
|
||||
dvec_t vpos = { 512, 0 };
|
||||
// Initialize player
|
||||
SDL_Rect psrc = { .y = 0, .w = PWIDTH, .h = PHEIGHT };
|
||||
SDL_Rect pdest = { .w = SCALE * PWIDTH, .h = SCALE * PHEIGHT };
|
||||
dvec_t pvel = { 0, 0 }, ppos = { 640, 96 };
|
||||
@ -247,8 +274,21 @@ int main(int argc, char *argv[])
|
||||
if (pspeed != 0) {
|
||||
pvel.x *= WALKSPEED / pspeed;
|
||||
pvel.y *= WALKSPEED / pspeed;
|
||||
ppos.x += (double)dt / 1000.0 * pvel.x;
|
||||
ppos.y += (double)dt / 1000.0 * pvel.y;
|
||||
|
||||
// Check for terrain collision, update position if none
|
||||
const double nextx = ppos.x + (double)dt / 1000.0 * pvel.x;
|
||||
const double nexty = ppos.y + (double)dt / 1000.0 * pvel.y;
|
||||
const dvec_t pfb
|
||||
= { .x = nextx + PFBOFFX, .y = nexty + PFBOFFY };
|
||||
bool valid = true;
|
||||
valid &= tilepassable(pfb.x, pfb.y);
|
||||
valid &= tilepassable(pfb.x + PFBWIDTH, pfb.y);
|
||||
valid &= tilepassable(pfb.x, pfb.y + PFBHEIGHT);
|
||||
valid &= tilepassable(pfb.x + PFBWIDTH, pfb.y + PFBHEIGHT);
|
||||
if (valid) {
|
||||
ppos.x = nextx;
|
||||
ppos.y = nexty;
|
||||
}
|
||||
|
||||
// Update direction
|
||||
if (pvel.y >= 0) {
|
||||
@ -267,7 +307,6 @@ int main(int argc, char *argv[])
|
||||
pdir = SPRITE_DIR_UP;
|
||||
}
|
||||
|
||||
// Set walkikng texture
|
||||
ptex = pwalk;
|
||||
} else {
|
||||
ptex = pidle;
|
||||
@ -290,11 +329,7 @@ int main(int argc, char *argv[])
|
||||
const int starty = TILESIZE * floor(vpos.y / TILESIZE);
|
||||
for (int y = starty; y < vpos.y + VIEWHEIGHT; y += TILESIZE) {
|
||||
for (int x = startx; x < vpos.x + VIEWWIDTH; x += TILESIZE) {
|
||||
const unsigned row = x / TILESIZE + MAPSHIFTX;
|
||||
const unsigned col = y / TILESIZE + MAPSHIFTY;
|
||||
if (row >= MAPWIDTH || col >= MAPHEIGHT)
|
||||
continue;
|
||||
const unsigned tileid = map[row][col];
|
||||
const unsigned tileid = tileat(x, y);
|
||||
if (0 == tileid)
|
||||
continue;
|
||||
const SDL_Rect src = {
|
||||
@ -320,6 +355,7 @@ int main(int argc, char *argv[])
|
||||
pdest.x = SCALE * (int)(ppos.x - vpos.x - PWIDTH / 2);
|
||||
pdest.y = SCALE * (int)(ppos.y - vpos.y - PHEIGHT / 2);
|
||||
SDL_RenderCopy(renderer, ptex, &psrc, &pdest);
|
||||
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user