Continue SDL frontend

This commit is contained in:
Miloslav Ciz 2023-09-10 14:43:20 +02:00
parent 7503a5dc2b
commit afecda260e
4 changed files with 169 additions and 70 deletions

View file

@ -1 +1,100 @@
#include <stdio.h>
#include <SDL2/SDL.h>
#include "game.h" #include "game.h"
#include "debug.h"
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture;
SDL_Surface *screenSurface;
uint16_t screen[LCR_SETTING_RESOLUTION_X * LCR_SETTING_RESOLUTION_Y];
const uint8_t *keyboardState;
uint8_t LCR_keyPressed(uint8_t key)
{
switch (key)
{
case LCR_KEY_UP: return
keyboardState[SDL_SCANCODE_W] | keyboardState[SDL_SCANCODE_UP]; break;
case LCR_KEY_RIGHT: return
keyboardState[SDL_SCANCODE_D] | keyboardState[SDL_SCANCODE_RIGHT]; break;
case LCR_KEY_DOWN: return
keyboardState[SDL_SCANCODE_S] | keyboardState[SDL_SCANCODE_DOWN]; break;
case LCR_KEY_LEFT: return
keyboardState[SDL_SCANCODE_A] | keyboardState[SDL_SCANCODE_LEFT]; break;
case LCR_KEY_A: return
keyboardState[SDL_SCANCODE_K] | keyboardState[SDL_SCANCODE_RETURN]; break;
case LCR_KEY_B: return
keyboardState[SDL_SCANCODE_L] | keyboardState[SDL_SCANCODE_ESCAPE]; break;
default: break;
}
return 0;
}
void LCR_sleep(uint16_t timeMs)
{
}
void LCR_drawPixel(unsigned int x, unsigned int y, uint_fast16_t color)
{
screen[y * LCR_SETTING_RESOLUTION_X + x] = color;
}
int main(int argc, char *argv[])
{
uint8_t running = 1;
LCR_gameInit();
SDL_Init(0);
window =
SDL_CreateWindow("Licar", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, LCR_SETTING_RESOLUTION_X, LCR_SETTING_RESOLUTION_Y,
SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window,-1,0);
texture =
SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGB565,SDL_TEXTUREACCESS_STATIC,
LCR_SETTING_RESOLUTION_X,LCR_SETTING_RESOLUTION_Y);
screenSurface = SDL_GetWindowSurface(window);
SDL_ShowCursor(0);
SDL_PumpEvents();
keyboardState = SDL_GetKeyboardState(NULL);
while (running)
{
SDL_PumpEvents();
keyboardState = SDL_GetKeyboardState(NULL);
running = !keyboardState[SDL_SCANCODE_Q];
running &= LCR_gameStep(SDL_GetTicks());
SDL_UpdateTexture(texture,NULL,screen,
LCR_SETTING_RESOLUTION_X * sizeof(uint16_t));
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer,texture,NULL,NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
LCR_gameEnd();
return 0;
}

79
game.h
View file

@ -1,42 +1,91 @@
/**
Licar game: this file implements the backend of a complete, actually playable
licar game, and is meant to be included and used by specific frontends (which
will handle each platform's hardware details and I/O).
*/
#ifndef _LCR_GAME_H #ifndef _LCR_GAME_H
#define _LCR_GAME_H #define _LCR_GAME_H
#include "map.h" #include "map.h"
#define LCR_KEY_UP 0x00 #define LCR_KEY_UP 0x00
#define LCR_KEY_RIGHT 0x01 #define LCR_KEY_RIGHT 0x01
#define LCR_KEY_DOWN 0x02 #define LCR_KEY_DOWN 0x02
#define LCR_KEY_LEFT 0x03 #define LCR_KEY_LEFT 0x03
#define LCR_KEY_A 0x04 ///< confirm, restart race #define LCR_KEY_A 0x04 ///< confirm, restart race
#define LCR_KEY_B 0x05 ///< cancel, open menu #define LCR_KEY_B 0x05 ///< cancel, open menu
#define LCR_KEYS_TOTAL 6
/*
FOR FRONTENDS:
- Implement the below described functions according to their description.
- Implement the main program and game loop.
- Call the below described functions as described.
*/
/**
Implement this in your frontend. Returns 1 if given key is pressed or 0
otherwise.
*/
uint8_t LCR_keyPressed(uint8_t key); uint8_t LCR_keyPressed(uint8_t key);
/**
Implement this in your frontend. This function pauses program execution for
given amount of milliseconds and relieves the CPU usage. On platforms that
don't support this the function may simply do nothing.
*/
void LCR_sleep(uint16_t timeMs); void LCR_sleep(uint16_t timeMs);
/**
Implement this in your frontend. This function draws a pixel of given color
to the screen back buffer (i.e. NOT directly to screen, back buffer shall
only be copied to front buffer once the LCR_gameStep function finishes all
rendering). This function should NOT check for out-of-screen coordinates, this
is handled by the game internals and out-of-screen pixels will never be drawn.
The color value depends on game settings but is normally an RGB565 value.
*/
void LCR_drawPixel(unsigned int x, unsigned int y, uint_fast16_t color); void LCR_drawPixel(unsigned int x, unsigned int y, uint_fast16_t color);
/** /**
Call at the start of the program. Call this function in your frontend at the start of the program.
*/ */
void LCR_gameInit(void); void LCR_gameInit(void);
/** /**
Call right before program end. Call this function in your frontend right before program end.
*/ */
void LCR_gameEnd(void); void LCR_gameEnd(void);
/** /**
Call this repeatedly in your main loop, pass the current time as the number Call this function in your frontend repeatedly inside the main loop, pass the
of milliseconds since program start. Returns 0 if program should end, current time as the number of milliseconds since program start. This function
otherwise 1. will perform the game step AND other things such as checking the input states,
rendering or sleeping (all using the above functions you should implement).
Returns 0 if program should end, otherwise 1.
*/ */
uint8_t LCR_gameStep(uint32_t timeMs); uint8_t LCR_gameStep(uint32_t timeMs);
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
uint8_t _LCR_keyStates[LCR_KEYS_TOTAL]; /**< Assures unchanging key states
during a single frame. */
/**
Internal pixel drawing function that checks for out-of-screen coordinates.
*/
static inline void _LCR_drawPixel(unsigned int x, unsigned int y,
uint_fast16_t color)
{
if (x < LCR_SETTING_RESOLUTION_X && y < LCR_SETTING_RESOLUTION_Y)
LCR_drawPixel(x,y,color);
}
void LCR_gameInit(void) void LCR_gameInit(void)
{ {
for (int i = 0; i < LCR_KEYS_TOTAL; ++i)
_LCR_keyStates[i] = 0;
} }
void LCR_gameEnd(void) void LCR_gameEnd(void)
@ -45,6 +94,14 @@ void LCR_gameEnd(void)
uint8_t LCR_gameStep(uint32_t time) uint8_t LCR_gameStep(uint32_t time)
{ {
for (int i = 0; i < LCR_KEYS_TOTAL; ++i)
_LCR_keyStates[i] = LCR_keyPressed(i);
for (int i = 0; i < 100; ++i)
for (int j = 0; j < 50; ++j)
_LCR_drawPixel(i,j,0x00ff);
return 1;
} }
#endif // guard #endif // guard

View file

@ -1,57 +0,0 @@
#include <stdio.h>
#include <SDL2/SDL.h>
#include "game.h"
#include "debug.h"
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture;
SDL_Surface *screenSurface;
const uint8_t *sdlKeyboardState;
int main(int argc, char *argv[])
{
uint8_t running = 1;
LCR_gameInit();
SDL_Init(SDL_INIT_AUDIO | SDL_INIT_JOYSTICK);
window =
SDL_CreateWindow("Licar", SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED, LCR_SETTING_RESOLUTION_X, LCR_SETTING_RESOLUTION_Y,
SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window,-1,0);
texture =
SDL_CreateTexture(renderer,SDL_PIXELFORMAT_RGB565,SDL_TEXTUREACCESS_STATIC,
LCR_SETTING_RESOLUTION_X,LCR_SETTING_RESOLUTION_Y);
screenSurface = SDL_GetWindowSurface(window);
SDL_ShowCursor(0);
SDL_PumpEvents();
sdlKeyboardState = SDL_GetKeyboardState(NULL);
while (running)
{
SDL_PumpEvents();
sdlKeyboardState = SDL_GetKeyboardState(NULL);
running = !sdlKeyboardState[SDL_SCANCODE_Q];
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer,texture,NULL,NULL);
SDL_RenderPresent(renderer);
}
SDL_DestroyTexture(texture);
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
LCR_gameEnd();
return 0;
}

View file

@ -2,11 +2,11 @@
#define _LCR_SETTINGS_H #define _LCR_SETTINGS_H
#ifndef LCR_SETTING_RESOLUTION_X #ifndef LCR_SETTING_RESOLUTION_X
#define LCR_SETTING_RESOLUTION_X 800 #define LCR_SETTING_RESOLUTION_X 1024
#endif #endif
#ifndef LCR_SETTING_RESOLUTION_Y #ifndef LCR_SETTING_RESOLUTION_Y
#define LCR_SETTING_RESOLUTION_Y 600 #define LCR_SETTING_RESOLUTION_Y 768
#endif #endif
#ifndef LCR_SETTING_MAP_MAX_SIZE #ifndef LCR_SETTING_MAP_MAX_SIZE