Skip to content

Instantly share code, notes, and snippets.

@jweinst1
Last active July 14, 2026 23:46
Show Gist options
  • Select an option

  • Save jweinst1/00d99f834bad36a2677e2d7bea4eda64 to your computer and use it in GitHub Desktop.

Select an option

Save jweinst1/00d99f834bad36a2677e2d7bea4eda64 to your computer and use it in GitHub Desktop.
Chess in SDL3 with C++
#include <SDL3/SDL.h>
#include <iostream>
#include <cstdint>
#include <cassert>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <utility>
#include <algorithm>
#include <string>
static constexpr uint8_t PAWN_WHITE[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 3, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 3, 2, 3, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 2, 2, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t KNIGHT_WHITE[] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 1, 0, 0, 0, 0,
0, 0, 0, 3, 3, 1, 1, 3, 3, 3, 2, 3, 1, 0, 0, 0,
0, 0, 3, 4, 4, 4, 4, 2, 2, 2, 3, 3, 3, 1, 0, 0,
0, 1, 4, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 3, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 0, 0, 1, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 2, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t ROOK_WHITE[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 3, 3, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0,
0, 0, 3, 4, 4, 1, 1, 4, 4, 1, 1, 4, 4, 1, 0, 0,
0, 0, 3, 4, 2, 3, 2, 4, 2, 3, 3, 4, 3, 1, 0, 0,
0, 0, 1, 4, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 3, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t BISHOP_WHITE[] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3, 4, 2, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
0, 0, 0, 1, 4, 2, 2, 3, 2, 2, 2, 3, 1, 0, 0, 0,
0, 0, 0, 1, 2, 2, 3, 3, 3, 2, 2, 3, 1, 0, 0, 0,
0, 0, 0, 1, 2, 2, 2, 3, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t QUEEN_WHITE[] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 3, 3, 4, 4, 2, 2, 2, 3, 1, 1, 0, 0, 0,
0, 0, 1, 4, 4, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 4, 2, 2, 3, 3, 3, 3, 3, 3, 3, 1, 0, 0,
0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t KING_WHITE[] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 3, 4, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 4, 3, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3, 4, 4, 4, 2, 1, 0, 0, 0, 0, 0,
0, 0, 0, 1, 3, 4, 4, 3, 1, 2, 3, 1, 1, 0, 0, 0,
0, 0, 1, 4, 4, 3, 3, 4, 2, 1, 1, 3, 3, 1, 0, 0,
0, 0, 1, 4, 2, 3, 4, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr SDL_Color WHITE_PIECE_PAL[5] = {
{ 0, 0, 0, 0 },
{ 31, 31, 41, 255 },
{ 150, 162, 179, 255 },
{ 89, 96, 112, 255 },
{ 234, 240, 216, 255 }
};
static constexpr uint8_t PAWN_BLACK[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3, 3, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 3, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 3, 2, 3, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 2, 2, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t KNIGHT_BLACK[] = {
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 1, 1, 0, 0, 0, 0,
0, 0, 0, 3, 3, 1, 1, 3, 3, 3, 2, 3, 1, 0, 0, 0,
0, 0, 3, 4, 4, 4, 4, 2, 2, 2, 3, 3, 3, 1, 0, 0,
0, 1, 4, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 3, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 3, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 0, 0, 1, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 2, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t ROOK_BLACK[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 3, 3, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0,
0, 0, 3, 4, 4, 1, 1, 4, 4, 1, 1, 4, 4, 1, 0, 0,
0, 0, 3, 4, 2, 3, 2, 4, 2, 3, 3, 4, 3, 1, 0, 0,
0, 0, 1, 4, 2, 2, 2, 2, 2, 2, 2, 2, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 3, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 1, 2, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 2, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t BISHOP_BLACK[] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3, 4, 2, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3, 4, 2, 2, 2, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0,
0, 0, 0, 1, 4, 2, 2, 3, 2, 2, 2, 3, 1, 0, 0, 0,
0, 0, 0, 1, 2, 2, 3, 3, 3, 2, 2, 3, 1, 0, 0, 0,
0, 0, 0, 1, 2, 2, 2, 3, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t QUEEN_BLACK[] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 4, 4, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 3, 3, 4, 4, 2, 2, 2, 3, 1, 1, 0, 0, 0,
0, 0, 1, 4, 4, 2, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 4, 2, 2, 3, 3, 3, 3, 3, 3, 3, 1, 0, 0,
0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 2, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr uint8_t KING_BLACK[] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 3, 4, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 4, 3, 1, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 3, 4, 4, 4, 2, 1, 0, 0, 0, 0, 0,
0, 0, 0, 1, 3, 4, 4, 3, 1, 2, 3, 1, 1, 0, 0, 0,
0, 0, 1, 4, 4, 3, 3, 4, 2, 1, 1, 3, 3, 1, 0, 0,
0, 0, 1, 4, 2, 3, 4, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 0, 1, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0,
0, 0, 0, 0, 1, 2, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 3, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 1, 2, 2, 2, 3, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 3, 4, 2, 2, 2, 3, 3, 1, 0, 0, 0, 0,
0, 0, 0, 3, 4, 2, 2, 3, 3, 3, 3, 3, 1, 0, 0, 0,
0, 0, 1, 4, 4, 4, 2, 2, 2, 2, 2, 3, 3, 1, 0, 0,
0, 0, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 1, 0, 0,
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0
};
static constexpr SDL_Color BLACK_PIECE_PAL[5] = {
{ 0, 0, 0, 0 },
{ 31, 31, 41, 255 },
{ 89, 96, 112, 255 },
{ 65, 58, 66, 255},
{150, 162, 179, 255}
};
//static constexpr const uint8_t* TOTAL_TEXT_PICS[] = { textchtxt_0, textchtxt_1, textchtxt_2, textchtxt_3, textchtxt_4, textchtxt_5, textchtxt_6, textchtxt_7, textchtxt_8, textchtxt_9, textchtxt_10, textchtxt_11, textchtxt_12, textchtxt_13, textchtxt_14, textchtxt_15, textchtxt_16, textchtxt_17, textchtxt_18, textchtxt_19, textchtxt_20, textchtxt_21, textchtxt_22, textchtxt_23, textchtxt_24, textchtxt_25, textchtxt_26, textchtxt_27, textchtxt_28, textchtxt_29, textchtxt_30, textchtxt_31, textchtxt_32, textchtxt_33, textchtxt_34, textchtxt_35, textchtxt_36, textchtxt_37, textchtxt_38, textchtxt_39, textchtxt_40, textchtxt_41, textchtxt_42, textchtxt_43, textchtxt_44, textchtxt_45, textchtxt_46, textchtxt_47, textchtxt_48, textchtxt_49, textchtxt_50, textchtxt_51, textchtxt_52, textchtxt_53, textchtxt_54, textchtxt_55, textchtxt_56, textchtxt_57, textchtxt_58, textchtxt_59, textchtxt_60, textchtxt_61, textchtxt_62, textchtxt_63 };
//static constexpr size_t TOTAL_TEXT_PIC_SIZE = sizeof(TOTAL_TEXT_PICS) / sizeof(TOTAL_TEXT_PICS[0]);
enum class ChessPieceMarker {
OffBoard,
Empty,
PawnW1,
PawnW2,
PawnW3,
PawnW4,
PawnW5,
PawnW6,
PawnW7,
PawnW8,
RookW1,
RookW2,
KnightW1,
KnightW2,
BishopW1,
BishopW2,
QueenW,
KingW,
PawnB1,
PawnB2,
PawnB3,
PawnB4,
PawnB5,
PawnB6,
PawnB7,
PawnB8,
RookB1,
RookB2,
KnightB1,
KnightB2,
BishopB1,
BishopB2,
QueenB,
KingB
};
struct ChessSprites {
static constexpr int SPRITE_BOX_SIZE = 16;
SDL_Palette* whitePalette = nullptr;
SDL_Palette* blackPalette = nullptr;
SDL_Texture* whitePawnTexture = nullptr;
SDL_Texture* whiteKnightTexture = nullptr;
SDL_Texture* whiteRookTexture = nullptr;
SDL_Texture* whiteBishopTexture = nullptr;
SDL_Texture* whiteQueenTexture = nullptr;
SDL_Texture* whiteKingTexture = nullptr;
SDL_Texture* blackPawnTexture = nullptr;
SDL_Texture* blackKnightTexture = nullptr;
SDL_Texture* blackRookTexture = nullptr;
SDL_Texture* blackBishopTexture = nullptr;
SDL_Texture* blackQueenTexture = nullptr;
SDL_Texture* blackKingTexture = nullptr;
void initAll(SDL_Renderer* rend) {
whitePalette = SDL_CreatePalette(5);
blackPalette = SDL_CreatePalette(5);
SDL_SetPaletteColors(whitePalette, WHITE_PIECE_PAL, 0, 5);
SDL_SetPaletteColors(blackPalette, BLACK_PIECE_PAL, 0, 5);
whitePawnTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(whitePawnTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(whitePawnTexture, whitePalette);
SDL_UpdateTexture(whitePawnTexture, nullptr, PAWN_WHITE, 16);
whiteKnightTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(whiteKnightTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(whiteKnightTexture, whitePalette);
SDL_UpdateTexture(whiteKnightTexture, nullptr, KNIGHT_WHITE, 16);
whiteRookTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(whiteRookTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(whiteRookTexture, whitePalette);
SDL_UpdateTexture(whiteRookTexture, nullptr, ROOK_WHITE, 16);
whiteBishopTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(whiteBishopTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(whiteBishopTexture, whitePalette);
SDL_UpdateTexture(whiteBishopTexture, nullptr, BISHOP_WHITE, 16);
whiteQueenTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(whiteQueenTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(whiteQueenTexture, whitePalette);
SDL_UpdateTexture(whiteQueenTexture, nullptr, QUEEN_WHITE, 16);
whiteKingTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(whiteKingTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(whiteKingTexture, whitePalette);
SDL_UpdateTexture(whiteKingTexture, nullptr, KING_WHITE, 16);
blackPawnTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(blackPawnTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(blackPawnTexture, blackPalette);
SDL_UpdateTexture(blackPawnTexture, nullptr, PAWN_BLACK, 16);
blackKnightTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(blackKnightTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(blackKnightTexture, blackPalette);
SDL_UpdateTexture(blackKnightTexture, nullptr, KNIGHT_BLACK, 16);
blackRookTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(blackRookTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(blackRookTexture, blackPalette);
SDL_UpdateTexture(blackRookTexture, nullptr, ROOK_BLACK, 16);
blackBishopTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(blackBishopTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(blackBishopTexture, blackPalette);
SDL_UpdateTexture(blackBishopTexture, nullptr, BISHOP_BLACK, 16);
blackQueenTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(blackQueenTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(blackQueenTexture, blackPalette);
SDL_UpdateTexture(blackQueenTexture, nullptr, QUEEN_BLACK, 16);
blackKingTexture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_INDEX8, SDL_TEXTUREACCESS_STATIC, SPRITE_BOX_SIZE, SPRITE_BOX_SIZE);
SDL_SetTextureBlendMode(blackKingTexture, SDL_BLENDMODE_BLEND);
SDL_SetTexturePalette(blackKingTexture, blackPalette);
SDL_UpdateTexture(blackKingTexture, nullptr, KING_BLACK, 16);
}
void deinitAll() {}
static const char* getString(ChessPieceMarker mark) {
switch (mark) {
// White Pieces
case ChessPieceMarker::PawnW1:
case ChessPieceMarker::PawnW2:
case ChessPieceMarker::PawnW3:
case ChessPieceMarker::PawnW4:
case ChessPieceMarker::PawnW5:
case ChessPieceMarker::PawnW6:
case ChessPieceMarker::PawnW7:
case ChessPieceMarker::PawnW8:
return "White Pawn";
case ChessPieceMarker::RookW1:
case ChessPieceMarker::RookW2:
return "White Rook";
case ChessPieceMarker::KnightW1:
case ChessPieceMarker::KnightW2:
return "White Knight";
case ChessPieceMarker::BishopW1:
case ChessPieceMarker::BishopW2:
return "White Bishop";
case ChessPieceMarker::QueenW:
return "White Queen";
case ChessPieceMarker::KingW:
return "White King";
// Black Pieces
case ChessPieceMarker::PawnB1:
case ChessPieceMarker::PawnB2:
case ChessPieceMarker::PawnB3:
case ChessPieceMarker::PawnB4:
case ChessPieceMarker::PawnB5:
case ChessPieceMarker::PawnB6:
case ChessPieceMarker::PawnB7:
case ChessPieceMarker::PawnB8:
return "Black Pawn";
case ChessPieceMarker::RookB1:
case ChessPieceMarker::RookB2:
return "Black Rook";
case ChessPieceMarker::KnightB1:
case ChessPieceMarker::KnightB2:
return "Black Knight";
case ChessPieceMarker::BishopB1:
case ChessPieceMarker::BishopB2:
return "Black Bishop";
case ChessPieceMarker::QueenB:
return "Black Queen";
case ChessPieceMarker::KingB:
return "Black King";
case ChessPieceMarker::Empty:
return "Empty";
case ChessPieceMarker::OffBoard:
return "Off Board";
default:
return "";
}
}
SDL_Texture* getSprite(ChessPieceMarker mark) {
switch (mark) {
// White Pieces
case ChessPieceMarker::PawnW1:
case ChessPieceMarker::PawnW2:
case ChessPieceMarker::PawnW3:
case ChessPieceMarker::PawnW4:
case ChessPieceMarker::PawnW5:
case ChessPieceMarker::PawnW6:
case ChessPieceMarker::PawnW7:
case ChessPieceMarker::PawnW8:
return whitePawnTexture;
case ChessPieceMarker::RookW1:
case ChessPieceMarker::RookW2:
return whiteRookTexture;
case ChessPieceMarker::KnightW1:
case ChessPieceMarker::KnightW2:
return whiteKnightTexture;
case ChessPieceMarker::BishopW1:
case ChessPieceMarker::BishopW2:
return whiteBishopTexture;
case ChessPieceMarker::QueenW:
return whiteQueenTexture;
case ChessPieceMarker::KingW:
return whiteKingTexture;
// Black Pieces
case ChessPieceMarker::PawnB1:
case ChessPieceMarker::PawnB2:
case ChessPieceMarker::PawnB3:
case ChessPieceMarker::PawnB4:
case ChessPieceMarker::PawnB5:
case ChessPieceMarker::PawnB6:
case ChessPieceMarker::PawnB7:
case ChessPieceMarker::PawnB8:
return blackPawnTexture;
case ChessPieceMarker::RookB1:
case ChessPieceMarker::RookB2:
return blackRookTexture;
case ChessPieceMarker::KnightB1:
case ChessPieceMarker::KnightB2:
return blackKnightTexture;
case ChessPieceMarker::BishopB1:
case ChessPieceMarker::BishopB2:
return blackBishopTexture;
case ChessPieceMarker::QueenB:
return blackQueenTexture;
case ChessPieceMarker::KingB:
return blackKingTexture;
case ChessPieceMarker::Empty:
return nullptr;
default:
return nullptr;
}
}
};
struct ChessBoard {
static constexpr size_t SQUARE_SIZE_I = 16;
static constexpr float SQUARE_SIZE_F = 16.0f;
static constexpr float BOARD_SIDE_SIZE = 8.0f;
static constexpr float BOARD_SIDE_SIZE_PX = SQUARE_SIZE_F * BOARD_SIDE_SIZE;
static constexpr uint8_t BOARD_SQ_R = 122;
static constexpr uint8_t BOARD_SQ_G = 56;
static constexpr uint8_t BOARD_SQ_B = 14;
float posX = 0.0f;
float posY = 0.0f;
ChessPieceMarker theBoard[8][8] = {
// Row 0: Black Back Rank
{
ChessPieceMarker::RookB1, ChessPieceMarker::KnightB1, ChessPieceMarker::BishopB1, ChessPieceMarker::QueenB,
ChessPieceMarker::KingB, ChessPieceMarker::BishopB2, ChessPieceMarker::KnightB2, ChessPieceMarker::RookB2
},
// Row 1: Black Pawns
{
ChessPieceMarker::PawnB1, ChessPieceMarker::PawnB2, ChessPieceMarker::PawnB3, ChessPieceMarker::PawnB4,
ChessPieceMarker::PawnB5, ChessPieceMarker::PawnB6, ChessPieceMarker::PawnB7, ChessPieceMarker::PawnB8
},
// Rows 2 to 5: Empty Squares
{ ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty },
{ ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty },
{ ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty },
{ ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty, ChessPieceMarker::Empty },
// Row 6: White Pawns
{
ChessPieceMarker::PawnW1, ChessPieceMarker::PawnW2, ChessPieceMarker::PawnW3, ChessPieceMarker::PawnW4,
ChessPieceMarker::PawnW5, ChessPieceMarker::PawnW6, ChessPieceMarker::PawnW7, ChessPieceMarker::PawnW8
},
// Row 7: White Back Rank
{
ChessPieceMarker::RookW1, ChessPieceMarker::KnightW1, ChessPieceMarker::BishopW1, ChessPieceMarker::QueenW,
ChessPieceMarker::KingW, ChessPieceMarker::BishopW2, ChessPieceMarker::KnightW2, ChessPieceMarker::RookW2
}
};
ChessPieceMarker getPieceAtSpot(float x, float y) {
int spotX = static_cast<int>(x - posX) / SQUARE_SIZE_I;
int spotY = static_cast<int>(y - posY) / SQUARE_SIZE_I;
int maxX = posX + BOARD_SIDE_SIZE_PX;
int maxY = posY + BOARD_SIDE_SIZE_PX;
if (x > maxX || y > maxY || x < posX || y < posY) {
return ChessPieceMarker::OffBoard;
}
return theBoard[spotY][spotX];
}
void setPieceAtSpot(float x, float y, ChessPieceMarker mark) {
int spotX = static_cast<int>(x - posX) / SQUARE_SIZE_I;
int spotY = static_cast<int>(y - posY) / SQUARE_SIZE_I;
int maxX = posX + BOARD_SIDE_SIZE_PX;
int maxY = posY + BOARD_SIDE_SIZE_PX;
if (x > maxX || y > maxY || x < posX || y < posY) {
return;
}
theBoard[spotY][spotX] = mark;
}
void drawBackground(SDL_Renderer* rend) {
uint8_t byteOdd = 0;
SDL_SetRenderDrawColor(rend, BOARD_SQ_R, BOARD_SQ_G, BOARD_SQ_B, 255);
for (float i = posY; i < BOARD_SIDE_SIZE_PX; i += SQUARE_SIZE_F)
{
for (float j = posX; j < BOARD_SIDE_SIZE_PX; j += SQUARE_SIZE_F)
{
byteOdd ^= 1;
if (byteOdd) {
continue;
}
SDL_FRect pecrect = { j, i, SQUARE_SIZE_F, SQUARE_SIZE_F };
SDL_RenderFillRect(rend, &pecrect);
}
byteOdd ^= 1; // extra flip to create board appearance
}
}
void drawPieces(SDL_Renderer* rend, ChessSprites* sprites) {
for (int i = 0; i < 8; ++i)
{
float drawY = posY + (static_cast<float>(i) * SQUARE_SIZE_F);
for (int j = 0; j < 8; ++j)
{
SDL_Texture* pieceText = sprites->getSprite(theBoard[i][j]);
if (pieceText == nullptr)
continue;
float drawX = posX + (static_cast<float>(j) * SQUARE_SIZE_F);
SDL_FRect pecrect = { drawX, drawY, SQUARE_SIZE_F, SQUARE_SIZE_F };
SDL_RenderTexture(rend, pieceText , nullptr, &pecrect);
}
}
}
};
static constexpr size_t SCREEN_X_PX = 256;
static constexpr size_t SCREEN_Y_PX = 256;
int main(int argc, char const *argv[])
{
if (!SDL_Init(SDL_INIT_VIDEO)) {
std::cerr << "Initialization failed: " << SDL_GetError() << "\n";
return -1;
}
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
if (!SDL_CreateWindowAndRenderer("The Chess Game", SCREEN_X_PX, SCREEN_Y_PX, 0, &window, &renderer)) {
std::cerr << "Failed to create window/renderer: " << SDL_GetError() << "\n";
return -1;
}
bool running = true;
// Fixed timestep setup (60 updates per second)
const Uint64 FIXED_DELTA_TIME_NS = 1000000000 / 60;
Uint64 current_time_ns = SDL_GetTicksNS();
Uint64 previous_time_ns = current_time_ns;
Uint64 accumulator_ns = 0;
ChessBoard cb;
ChessSprites csps;
csps.initAll(renderer);
bool isMousePressed = false;
float lastPressedX = 0.0f, lastPressedY = 0.0f;
float curPressedX = 0.0f, curPressedY = 0.0f;
SDL_Texture* pickedUpChessPiece = nullptr;
ChessPieceMarker pickedUpChessMark = ChessPieceMarker::OffBoard;
while (running) {
current_time_ns = SDL_GetTicksNS();
Uint64 elapsed_ns = current_time_ns - previous_time_ns;
previous_time_ns = current_time_ns;
if (elapsed_ns > 250000000) elapsed_ns = 250000000;
accumulator_ns += elapsed_ns;
// ==========================================
// 1. INPUT DETECTION (OS Events & Mouse)
// ==========================================
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_EVENT_QUIT) {
running = false;
}
// Detect Mouse Clicks in SDL3
else if (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN) {
if (event.button.button == SDL_BUTTON_LEFT) {
// SDL3 provides mouse coordinates as clean floats
float mousepre_x = event.button.x;
float mousepre_y = event.button.y;
isMousePressed = true;
curPressedX = event.button.x;
curPressedY = event.button.y;
auto piece = cb.getPieceAtSpot(mousepre_x, mousepre_y);
std::cout << "Clicked x=" << mousepre_x << ", y=" << mousepre_y
<<", board=" << ChessSprites::getString(piece) << "\n";
if (piece != ChessPieceMarker::OffBoard && piece != ChessPieceMarker::Empty) {
cb.setPieceAtSpot(mousepre_x, mousepre_y, ChessPieceMarker::Empty);
pickedUpChessPiece = csps.getSprite(piece);
pickedUpChessMark = piece;
lastPressedX = mousepre_x;
lastPressedY = mousepre_y;
}
}
}
else if (event.type == SDL_EVENT_MOUSE_MOTION) {
if (isMousePressed) {
curPressedX = event.motion.x;
curPressedY = event.motion.y;
std::cout << "Dragging to x=" << curPressedX << ", y=" << curPressedY << "\n";
}
}
else if (event.type == SDL_EVENT_MOUSE_BUTTON_UP) {
if (event.button.button == SDL_BUTTON_LEFT) {
isMousePressed = false;
std::cout << "Mouse Released.\n";
if (pickedUpChessPiece != nullptr) {
auto piece = cb.getPieceAtSpot(curPressedX, curPressedY);
if (piece == ChessPieceMarker::Empty) {
cb.setPieceAtSpot(curPressedX, curPressedY, pickedUpChessMark);
} else {
cb.setPieceAtSpot(lastPressedX, lastPressedY, pickedUpChessMark);
}
}
pickedUpChessPiece = nullptr;
pickedUpChessMark = ChessPieceMarker::OffBoard;
curPressedX = 0.0f;
curPressedY = 0.0f;
}
}
}
// ==========================================
// 2. FIXED PHYSICS / LOGIC TIMESTEP
// ==========================================
while (accumulator_ns >= FIXED_DELTA_TIME_NS) {
// Update item animations, physics, and skilling timers here
//playerPathMover.moveSprite();
// based on path, change target.
accumulator_ns -= FIXED_DELTA_TIME_NS;
}
// ==========================================
// 3. PAINT / RENDERING THE WINDOW
// ==========================================
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
cb.drawBackground(renderer);
cb.drawPieces(renderer, &csps);
if (pickedUpChessPiece != nullptr) {
SDL_FRect pecrect = { curPressedX - 8.0f, curPressedY - 8.0f, ChessBoard::SQUARE_SIZE_F, ChessBoard::SQUARE_SIZE_F };
SDL_RenderTexture(renderer, pickedUpChessPiece , nullptr, &pecrect);
}
//SDL_RenderFillRect(renderer, &specrect);
//myBoard.draw(renderer);
//myTextBox.draw(renderer);
// C. Command the GPU to push the backbuffer into the visible monitor frame
SDL_RenderPresent(renderer);
}
//myBoard.deinitAll();
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment