commit
2007fb7edc
200 files changed
+27710
No files matched your search
+217
@@ -0,0 +1,217 @@
|
||||
#pragma once
|
||||
|
||||
#include "dmath.h"
|
||||
#include <SDL3/SDL_filesystem.h>
|
||||
#include <SDL3/SDL_stdinc.h>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
constexpr const char* GAME_ID = "smack-a-brother";
|
||||
constexpr const char* GAME_NAME = "Smack a Brother";
|
||||
constexpr int CANVAS_HEIGHT = 360;
|
||||
constexpr int CANVAS_WIDTH = 640;
|
||||
constexpr int TILE_SIZE = 16;
|
||||
constexpr float GRAVITY = 1000.0f;
|
||||
constexpr float PI = 3.14159265f;
|
||||
constexpr float TICK = 1.0f / 60.0f;
|
||||
|
||||
struct Vec2
|
||||
{
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
};
|
||||
|
||||
struct Rect
|
||||
{
|
||||
float x = 0;
|
||||
float y = 0;
|
||||
float w = 0;
|
||||
float h = 0;
|
||||
};
|
||||
|
||||
struct Color
|
||||
{
|
||||
float r = 1;
|
||||
float g = 1;
|
||||
float b = 1;
|
||||
float a = 1;
|
||||
};
|
||||
|
||||
constexpr Color BLACK = {0, 0, 0, 1};
|
||||
constexpr Color GRAY = {128 / 255.0f, 128 / 255.0f, 128 / 255.0f, 1};
|
||||
constexpr Color WHITE = {1, 1, 1, 1};
|
||||
|
||||
inline Vec2 operator+(Vec2 a, Vec2 b)
|
||||
{
|
||||
return {a.x + b.x, a.y + b.y};
|
||||
}
|
||||
|
||||
inline Vec2 operator-(Vec2 a, Vec2 b)
|
||||
{
|
||||
return {a.x - b.x, a.y - b.y};
|
||||
}
|
||||
|
||||
inline Vec2 operator*(Vec2 v, float scale)
|
||||
{
|
||||
return {v.x * scale, v.y * scale};
|
||||
}
|
||||
|
||||
inline float vec2_dot(Vec2 a, Vec2 b)
|
||||
{
|
||||
return a.x * b.x + a.y * b.y;
|
||||
}
|
||||
|
||||
inline float vec2_length(Vec2 v)
|
||||
{
|
||||
return std::sqrt(v.x * v.x + v.y * v.y);
|
||||
}
|
||||
|
||||
inline Vec2 vec2_normalize(Vec2 v)
|
||||
{
|
||||
float length = vec2_length(v);
|
||||
return length > 0 ? v * (1 / length) : Vec2{1, 0};
|
||||
}
|
||||
|
||||
inline float vec2_angle(Vec2 v)
|
||||
{
|
||||
return math_atan2(v.y, v.x);
|
||||
}
|
||||
|
||||
inline Vec2 vec2_polar(float angle, float length)
|
||||
{
|
||||
return {math_cos(angle) * length, math_sin(angle) * length};
|
||||
}
|
||||
|
||||
inline Vec2 vec2_lerp(Vec2 from, Vec2 to, float t)
|
||||
{
|
||||
return from + (to - from) * t;
|
||||
}
|
||||
|
||||
// A 2D affine transform taking x to (a·x + c·y + x0, b·x + d·y + y0).
|
||||
struct Affine
|
||||
{
|
||||
float a = 1;
|
||||
float b = 0;
|
||||
float c = 0;
|
||||
float d = 1;
|
||||
float x0 = 0;
|
||||
float y0 = 0;
|
||||
};
|
||||
|
||||
inline Affine operator*(Affine m, Affine n)
|
||||
{
|
||||
return {m.a * n.a + m.c * n.b, m.b * n.a + m.d * n.b, m.a * n.c + m.c * n.d,
|
||||
m.b * n.c + m.d * n.d, m.a * n.x0 + m.c * n.y0 + m.x0, m.b * n.x0 + m.d * n.y0 + m.y0};
|
||||
}
|
||||
|
||||
inline Vec2 operator*(Affine m, Vec2 v)
|
||||
{
|
||||
return {m.a * v.x + m.c * v.y + m.x0, m.b * v.x + m.d * v.y + m.y0};
|
||||
}
|
||||
|
||||
// Moves to position, turns by angle and scales, about origin.
|
||||
inline Affine affine_get(Vec2 position, float angle, Vec2 scale, Vec2 origin)
|
||||
{
|
||||
float cosine = math_cos(angle);
|
||||
float sine = math_sin(angle);
|
||||
Affine m = {cosine * scale.x, sine * scale.x, -sine * scale.y, cosine * scale.y, position.x, position.y};
|
||||
return m * Affine{1, 0, 0, 1, -origin.x, -origin.y};
|
||||
}
|
||||
|
||||
// Blends angles the short way round.
|
||||
inline float angle_lerp(float from, float to, float t)
|
||||
{
|
||||
return from + std::remainder(to - from, 2 * PI) * t;
|
||||
}
|
||||
|
||||
// Cosmetic randomness: particles, flicker, shake. Gameplay draws from Rng instead.
|
||||
inline float random_get(float min, float max)
|
||||
{
|
||||
return min + SDL_randf() * (max - min);
|
||||
}
|
||||
|
||||
constexpr int RNG_FRACTION_BITS = 24;
|
||||
constexpr int RNG_SHIFT_A = 13;
|
||||
constexpr int RNG_SHIFT_B = 17;
|
||||
constexpr int RNG_SHIFT_C = 5;
|
||||
constexpr Uint32 RNG_SEED = 0x9E3779B9;
|
||||
|
||||
// A small seeded xorshift generator for gameplay, saved with the simulation so a replay draws the same numbers.
|
||||
struct Rng
|
||||
{
|
||||
Uint32 state = RNG_SEED;
|
||||
|
||||
float random_get(float min, float max)
|
||||
{
|
||||
state ^= state << RNG_SHIFT_A;
|
||||
state ^= state >> RNG_SHIFT_B;
|
||||
state ^= state << RNG_SHIFT_C;
|
||||
float unit = (state >> (32 - RNG_FRACTION_BITS)) / (float)(1 << RNG_FRACTION_BITS);
|
||||
return min + unit * (max - min);
|
||||
}
|
||||
};
|
||||
|
||||
inline bool is_point_in_rect(Vec2 point, Rect rect)
|
||||
{
|
||||
return point.x >= rect.x && point.y >= rect.y && point.x < rect.x + rect.w && point.y < rect.y + rect.h;
|
||||
}
|
||||
|
||||
inline bool is_rect_overlapping(Rect a, Rect b)
|
||||
{
|
||||
return a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h;
|
||||
}
|
||||
|
||||
// Darkens a colour by amount, keeping its alpha.
|
||||
inline Color color_shade(Color color, float amount)
|
||||
{
|
||||
return {color.r * amount, color.g * amount, color.b * amount, color.a};
|
||||
}
|
||||
|
||||
inline Color color_fade(Color color, float alpha)
|
||||
{
|
||||
return {color.r, color.g, color.b, color.a * alpha};
|
||||
}
|
||||
|
||||
// A list of up to N items held in place, without the heap: game state kept in one, unlike in a std::vector, is plain
|
||||
// bytes that mean the same on every platform (see Fighter). Pushing past N drops the item.
|
||||
template <class T, int N> struct FixedList
|
||||
{
|
||||
T items[N] = {};
|
||||
int count = 0;
|
||||
|
||||
void clear()
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
void push_back(const T& item)
|
||||
{
|
||||
if (count < N)
|
||||
items[count++] = item;
|
||||
}
|
||||
T* begin()
|
||||
{
|
||||
return items;
|
||||
}
|
||||
T* end()
|
||||
{
|
||||
return items + count;
|
||||
}
|
||||
int size() const
|
||||
{
|
||||
return count;
|
||||
}
|
||||
template <class Predicate> void erase_if(Predicate predicate)
|
||||
{
|
||||
int kept = 0;
|
||||
for (int i = 0; i < count; i++)
|
||||
if (!predicate(items[i]))
|
||||
items[kept++] = items[i];
|
||||
count = kept;
|
||||
}
|
||||
};
|
||||
|
||||
// Absolute path to a file inside the resources folder next to the executable.
|
||||
inline std::string path_get(const char* relative)
|
||||
{
|
||||
return std::string(SDL_GetBasePath()) + "resources/" + relative;
|
||||
}
|
||||
Reference in new issue
Block a user