Skip to content

Instantly share code, notes, and snippets.

@t-mat
Last active October 15, 2023 07:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save t-mat/2d77ee3813945ffd59ea95c56ead98cc to your computer and use it in GitHub Desktop.
Save t-mat/2d77ee3813945ffd59ea95c56ead98cc to your computer and use it in GitHub Desktop.
My SDL2 template
// My template code for SDL2. Press ESC to exit.
// Copyright (C) 2021, Takayuki Matsuoka.
// SPDX-License-Identifier: CC0-1.0
#include <vector>
#define SDL_MAIN_HANDLED
#include <SDL.h>
#if defined(_MSC_VER)
//#pragma comment(lib, "SDL2.lib")
#pragma comment(lib, "SDL2-static.lib")
#pragma comment(lib, "winmm.lib")
#pragma comment(lib, "Version.lib")
#pragma comment(lib, "imm32.lib")
#pragma comment(lib, "Setupapi.lib")
#endif
std::vector<uint8_t> loadFile(const char* filename) {
std::vector<uint8_t> file;
if(SDL_RWops* rw = SDL_RWFromFile(filename, "rb")) {
file.resize(SDL_RWsize(rw));
SDL_RWread(rw, file.data(), 1, file.size());
SDL_RWclose(rw);
}
return file;
}
struct GameControllers : std::vector<SDL_GameController*> {
GameControllers() {
for(int i = 0, n = SDL_NumJoysticks(); i < n; ++i) {
auto* g = SDL_GameControllerOpen(i);
if(g) { push_back(g); }
}
}
};
struct Screen : std::vector<uint32_t> {
Screen(int w, int h) : width{w}, height{h} { resize(w * h); }
void setPixel(int x, int y, int r, int g, int b) {
if(x < 0 || x >= width || y < 0 || y >= height) { return; }
const uint32_t c = ((r & 0xff) << 24) | ((g & 0xff) << 16) | ((b & 0xff) << 8);
(*this)[y * width + x] = c;
}
int width = 0;
int height = 0;
};
//
bool update(uint64_t microsecondsSinceStartup, Screen& screen, const uint8_t* sdlKeyboardState, GameControllers& gameControllers) {
double secondsSinceStartup = microsecondsSinceStartup * (1.0 / 1000 / 1000);
const int t = (int) secondsSinceStartup;
for(int y = 0; y < screen.height; y++) {
for(int x = 0; x < screen.width; x++) {
const int c = (1 + t + y / 32 + x / 32) % 8;
int r = ((c>>0) & 1) * 0xff;
int g = ((c>>1) & 1) * 0xff;
int b = ((c>>2) & 1) * 0xff;
screen.setPixel(x, y, r, g, b);
}
}
if(sdlKeyboardState[SDL_SCANCODE_ESCAPE] != 0) {
return false;
}
return true;
}
int main(int argc, const char* argv[]) {
uint32_t sdlInitFlag = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK;
const int width = 320; // in pixels
const int height = 240; // in pixels
const int scale = 4; // magnifier
const int FrameRate = 60; // frames / sec
if(SDL_Init(sdlInitFlag) < 0) {
return SDL_Log("FAIL: SDL_Init() - %s\n", SDL_GetError()), EXIT_FAILURE;
}
SDL_Window* window = SDL_CreateWindow("My app", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
width*scale, height*scale, SDL_WINDOW_SHOWN);
if(! window) {
return SDL_Log("FAIL: SDL_CreateWindow() - %s\n", SDL_GetError()), EXIT_FAILURE;
}
SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(0, width, height, 32, SDL_PIXELFORMAT_RGBX8888);
GameControllers gameControllers;
Screen screen(width, height);
const uint64_t pcOrig = SDL_GetPerformanceCounter();
const uint64_t pcFreq = SDL_GetPerformanceFrequency();
uint64_t pcPrev = SDL_GetPerformanceCounter();
for(bool running = true; running; ) {
for(SDL_Event e; SDL_PollEvent(&e); ) {
running &= (e.type != SDL_QUIT);
}
{ // Update app logic
const uint64_t microsecondsSinceStartup = (SDL_GetPerformanceCounter() - pcOrig) * 1000000 / pcFreq;
const uint8_t* keyboardState = SDL_GetKeyboardState(nullptr);
running &= update(microsecondsSinceStartup, screen, keyboardState, gameControllers);
}
{ // Copy screen to the surface
SDL_LockSurface(surface);
for(int y = 0; y < height; ++y) {
auto* dst = reinterpret_cast<uint32_t*>(surface->pixels) + y * width;
for(int x = 0; x < width; ++x) {
dst[x] = screen[y * width + x];
}
}
SDL_UnlockSurface(surface);
SDL_BlitScaled(surface, nullptr, SDL_GetWindowSurface(window), nullptr);
}
{ // Delay for constant frame rate
const uint64_t pcNext = pcPrev + pcFreq / FrameRate;
const int64_t pcDiff = pcNext - SDL_GetPerformanceCounter();
if(pcDiff > 0) {
SDL_Delay(static_cast<uint32_t>((pcDiff * 1000) / pcFreq));
}
pcPrev = SDL_GetPerformanceCounter();
}
SDL_UpdateWindowSurface(window);
}
SDL_FreeSurface(surface);
SDL_DestroyWindow(window);
SDL_Quit();
return EXIT_SUCCESS;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment