diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index f75e8a4..3f5fc9d 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -5,6 +5,7 @@ set_default_target_options(game) target_include_directories(game PUBLIC include) target_link_libraries(game PRIVATE + m LibXml2::LibXml2 SDL2::SDL2 SDL2::SDL2main diff --git a/app/main.c b/app/main.c index 2b60e71..05973cb 100644 --- a/app/main.c +++ b/app/main.c @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #define SCALE 4 @@ -32,12 +34,28 @@ #define PIHEIGHT 64 #define PIANIMLEN 8 +#define WALKSPEED 72 // pixels per second + #define BASEANIMPERIOD 200 +typedef struct { + bool left, right, up, down; +} input_state_t; + +typedef struct { + double x, y; +} dvec_t; + static SDL_Window *window; static SDL_Renderer *renderer; static unsigned map[MAPWIDTH][MAPHEIGHT]; static SDL_Texture *tstex, *pitex; +static input_state_t input; + +static inline double mag(dvec_t v) +{ + return sqrt(v.x * v.x + v.y * v.y); +} int main(int argc, char *argv[]) { @@ -144,25 +162,77 @@ int main(int argc, char *argv[]) assert(NULL != pitex); int offx = 16, offy = 0; - const SDL_Rect pdest = { - .x = SCALE * 80, - .y = SCALE * 80, - .w = SCALE * PIWIDTH, - .h = SCALE * PIHEIGHT, - }; + SDL_Rect psrc = { .y = 0, .w = PIWIDTH, .h = PIHEIGHT }; + SDL_Rect pdest = { .w = SCALE * PIWIDTH, .h = SCALE * PIHEIGHT }; + dvec_t pvel = { 0, 0 }, ppos = { 80, 80 }; SDL_Event event; + uint64_t prevt = SDL_GetTicks64(); while (1) { + // Calculate dt + const uint64_t t = SDL_GetTicks64(); + const uint64_t dt = t - prevt; + prevt = t; + // Handle events SDL_PollEvent(&event); switch (event.type) { case SDL_QUIT: goto quit; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_LEFT: + input.left = true; + break; + case SDLK_RIGHT: + input.right = true; + break; + case SDLK_UP: + input.up = true; + break; + case SDLK_DOWN: + input.down = true; + break; + default: + break; + } + break; + + case SDL_KEYUP: + switch (event.key.keysym.sym) { + case SDLK_LEFT: + input.left = false; + break; + case SDLK_RIGHT: + input.right = false; + break; + case SDLK_UP: + input.up = false; + break; + case SDLK_DOWN: + input.down = false; + break; + default: + break; + } + break; + default: break; } + // Calculate and apply velocity + pvel.x = (input.left ? -1 : 0) + (input.right ? 1 : 0); + pvel.y = (input.up ? -1 : 0) + (input.down ? 1 : 0); + const double pspeed = mag(pvel); + 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; + } + SDL_RenderClear(renderer); // Draw map @@ -189,14 +259,10 @@ int main(int argc, char *argv[]) } // Draw player - const unsigned piframe - = (SDL_GetTicks64() / BASEANIMPERIOD) % PIANIMLEN; - const SDL_Rect psrc = { - .x = PIWIDTH * piframe, - .y = 0, - .w = PIWIDTH, - .h = PIHEIGHT, - }; + const unsigned piframe = (t / BASEANIMPERIOD) % PIANIMLEN; + psrc.x = PIWIDTH * piframe; + pdest.x = SCALE * (int)ppos.x; + pdest.y = SCALE * (int)ppos.y; SDL_RenderCopy(renderer, pitex, &psrc, &pdest); SDL_RenderPresent(renderer);