first commit

This commit is contained in:
dox
2023-02-11 23:18:45 -05:00
commit d723f08969
307 changed files with 38708 additions and 0 deletions

90
src/GAME.h Normal file
View File

@ -0,0 +1,90 @@
/*
* DESCRIPTION:
* Global variable and constants.
*/
#pragma once
#include "engine/event.h"
#include "engine/font.h"
#include "engine/io.h"
#include "engine/glyph.h"
#include "engine/keyboard.h"
#include "engine/mouse.h"
#include "engine/music.h"
#include "engine/renderer.h"
#include "engine/sound.h"
#include "engine/tick.h"
#include "engine/window.h"
#include "game/ecs/ECS_TYPES.h"
#include "game/state/STATE_TYPES.h"
#define TEXTURE_COUNT TEXTURE_LOGO + 1
enum TextureType
{
TEXTURE_PLAYER,
TEXTURE_FOLLOWER,
TEXTURE_ENEMY,
TEXTURE_PARTICLE,
TEXTURE_WARNING,
TEXTURE_LOGO
};
#define SOUND_COUNT SOUND_SELECT + 1
enum SoundType
{
SOUND_COLLIDE,
SOUND_HURT,
SOUND_LEVEL,
SOUND_WARNING,
SOUND_HOVER,
SOUND_SELECT
};
#define MUSIC_COUNT MUSIC_ETHNICA + 1
enum MusicType
{
MUSIC_ETHNICA
};
#define SHADER_COUNT SHADER_TEXTURE_QUAD + 1
enum ShaderType
{
SHADER_TEXTURE_QUAD
};
#define FONT_COUNT FONT_BIG + 1
enum FontType
{
FONT_SMALL,
FONT_BIG
};
struct Game
{
enum StateType state;
struct Camera camera;
struct ECS ecs;
struct Event event;
struct Keyboard keyboard;
struct Mouse mouse;
struct Renderer renderer;
struct Sound sounds[SOUND_COUNT];
struct Texture textures[TEXTURE_COUNT];
struct Music music[MUSIC_COUNT];
struct Shader shaders[SHADER_COUNT];
struct Font fonts[FONT_COUNT];
struct Tick tick;
struct Window window;
struct Play play;
struct Menu menu;
struct Results results;
u32 score;
vec4 bounds;
bool isQuit;
bool isPaused;
bool isMute;
};
extern struct Game game;

36
src/engine/atlas.c Normal file
View File

@ -0,0 +1,36 @@
/*
* DESCRIPTION:
* Texture atlas functions.
*/
#include "atlas.h"
/* Initializes an atlas. */
void
atlas_init(struct Atlas* self, struct Texture texture, s32 frameW, s32 frameH, s32 rows, s32 cols)
{
self->texture = texture;
self->frameW = frameW;
self->frameH = frameH;
self->rows = rows;
self->cols = cols;
self->index = 0;
}
/* Obtains the texture coordinates for an atlas frame. */
void
atlas_uv_get(struct Atlas* self, vec2 uvMin, vec2 uvMax)
{
vec2 pos;
s32 col;
s32 row;
pos[0] = (f32)(self->index / self->rows) * self->frameW;
pos[1] = (f32)(self->index % self->rows) * self->frameH;
uvMin[0] = (f32)pos[0] / self->texture.w;
uvMin[1] = (f32)pos[1] / self->texture.h;
uvMax[0] = (f32)(pos[0] + self->frameW) / self->texture.w;
uvMax[1] = (f32)(pos[1] + self->frameH) / self->texture.h;
}

19
src/engine/atlas.h Normal file
View File

@ -0,0 +1,19 @@
/*
* DESCRIPTION:
* atlas.c header.
*/
#include "texture.h"
struct Atlas
{
struct Texture texture;
s32 frameW;
s32 frameH;
s32 rows;
s32 cols;
s32 index;
};
void atlas_init(struct Atlas* atlas, struct Texture texture, s32 frameW, s32 frameH, s32 rows, s32 cols);
void atlas_uv_get(struct Atlas* atlas, vec2 uvMin, vec2 uvMax);

146
src/engine/camera.c Normal file
View File

@ -0,0 +1,146 @@
/*
* DESCRIPTION:
* Camera code.
*/
#include "camera.h"
/* Initialize perspective camera. */
void
camera_perspective_init(struct Camera* self, f32 fov, f32 aspect)
{
memset(self, '\0', sizeof(struct Camera));
self->type = CAMERA_PERSPECTIVE;
self->fov = fov;
self->yaw = CAMERA_PERSPECTIVE_YAW_DEFAULT;
self->pitch = 0;
self->aspect = aspect;
camera_update(self);
}
/* Initialize orthographic camera. */
void
camera_orthographic_init(struct Camera* self, vec2 size)
{
memset(self, '\0', sizeof(struct Camera));
self->type = CAMERA_ORTHOGRAPHIC;
glm_vec2_copy(size, self->size);
camera_update(self);
}
/* Returns view matrix of camera. */
void
camera_view_set(struct Camera* self)
{
vec3 positionFront;
glm_mat4_identity(self->view);
switch (self->type)
{
case CAMERA_PERSPECTIVE:
glm_vec3_add(self->position, self->front, positionFront);
glm_lookat(self->position, positionFront, self->up, self->view);
break;
case CAMERA_ORTHOGRAPHIC:
glm_mat4_identity(self->view);
break;
default:
break;
}
}
/* Gets projection of camera. */
void
camera_projection_set(struct Camera* self)
{
glm_mat4_identity(self->projection);
switch (self->type)
{
case CAMERA_PERSPECTIVE:
glm_perspective
(
self->fov,
self->aspect,
CAMERA_PERSPECTIVE_NEAR,
CAMERA_PERSPECTIVE_FAR,
self->projection
);
break;
case CAMERA_ORTHOGRAPHIC:
glm_ortho
(
0.0f,
self->size[0],
self->size[1],
0.0f,
CAMERA_ORTHOGRAPHIC_NEAR,
CAMERA_ORTHOGRAPHIC_FAR,
self->projection
);
break;
default:
break;
}
}
/* Sets the camera to a position. */
void
camera_position_set(struct Camera* self, vec3 position)
{
glm_vec3_copy(position, self->position);
}
/* Sets camera's vectors. */
void
camera_vector_set(struct Camera* self)
{
vec3 worldUp = {0.0f, 1.0f, 0.0f};
switch (self->type)
{
case CAMERA_PERSPECTIVE:
self->front[0] = cos(self->yaw) * cos(self->pitch);
self->front[1] = sin(self->pitch);
self->front[2] = sin(self->yaw) * cos(self->pitch);
glm_vec3_normalize(self->front);
glm_vec3_crossn(self->front, worldUp, self->right);
glm_vec3_crossn(self->right, self->front, self->up);
break;
case CAMERA_ORTHOGRAPHIC:
break;
default:
break;
}
}
/* Sets an orthographic camera's size. */
void
camera_orthographic_size_set(struct Camera* self, vec2 size)
{
glm_vec2_copy(size, self->size);
}
/* Sets an orthographic camera's size to a window's. */
void
camera_orthographic_window_set(struct Camera* self, struct Window* window)
{
camera_orthographic_size_set(self, window->size);
}
/* Updates camera. */
void
camera_update(struct Camera* self)
{
camera_vector_set(self);
camera_view_set(self);
camera_projection_set(self);
}

49
src/engine/camera.h Normal file
View File

@ -0,0 +1,49 @@
/*
* DESCRIPTION:
* camera.c header.
*/
#pragma once
#include <GL/glew.h>
#include <GL/gl.h>
#include "window.h"
#define CAMERA_ORTHOGRAPHIC_FAR -1.0f
#define CAMERA_ORTHOGRAPHIC_NEAR 1.0f
#define CAMERA_PERSPECTIVE_FAR 100.0f
#define CAMERA_PERSPECTIVE_NEAR 0.1f
#define CAMERA_PERSPECTIVE_YAW_DEFAULT (-M_PI / 2)
enum CameraType
{
CAMERA_PERSPECTIVE,
CAMERA_ORTHOGRAPHIC
};
struct Camera
{
enum CameraType type;
vec3 position;
f32 aspect;
f32 fov;
vec2 size;
vec3 front;
vec3 up;
vec3 right;
f32 yaw;
f32 pitch;
mat4 view;
mat4 projection;
};
void camera_perspective_init(struct Camera* self, f32 fov, f32 aspect);
void camera_orthographic_init(struct Camera* self, vec2 size);
void camera_orthographic_size_set(struct Camera* self, vec2 size);
void camera_orthographic_window_set(struct Camera* self, struct Window* window);
void camera_position_set(struct Camera* self, vec3 position);
void camera_projection_set(struct Camera* self);
void camera_view_set(struct Camera* self);
void camera_vector_set(struct Camera* self);
void camera_update(struct Camera* self);

65
src/engine/event.c Normal file
View File

@ -0,0 +1,65 @@
/*
* DESCRIPTION:
* Event handling.
*/
#include "event.h"
/* Updates events. */
void
event_update(struct Event* self)
{
SDL_Event event;
self->isWindowLeft = false;
self->isWindowResized = false;
memcpy(&self->prev, &self->curr, sizeof(bool) * EVENT_COUNT);
memset(&self->curr, '\0', sizeof(bool) * EVENT_COUNT);
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_WINDOWEVENT:
switch (event.window.event)
{
case SDL_WINDOWEVENT_LEAVE:
self->isWindowLeft = true;
break;
case SDL_WINDOWEVENT_RESIZED:
case SDL_WINDOWEVENT_SIZE_CHANGED:
self->isWindowResized = true;
default:
break;
}
break;
case SDL_QUIT:
self->curr[EVENT_QUIT] = true;
break;
default:
break;
}
}
}
/* Is a given event pressed? */
bool
event_press(struct Event* self, enum EventType type)
{
return (self->curr[type] && !self->prev[type]);
}
/* Is a given event held? */
bool
event_held(struct Event* self, enum EventType type)
{
return (self->curr[type] && self->prev[type]);
}
/* Is a given event released? */
bool
event_release(struct Event* self, enum EventType type)
{
return (!self->curr[type] && self->prev[type]);
}

29
src/engine/event.h Normal file
View File

@ -0,0 +1,29 @@
/*
* DESCRIPTION:
* event.c header.
*/
#pragma once
#include <SDL2/SDL.h>
#include "../util/UTIL.h"
#define EVENT_COUNT EVENT_QUIT + 1
enum EventType
{
EVENT_QUIT
};
struct Event
{
bool isWindowLeft;
bool isWindowResized;
bool curr[EVENT_COUNT];
bool prev[EVENT_COUNT];
};
void event_update(struct Event* self);
bool event_press(struct Event* self, enum EventType type);
bool event_held(struct Event* self, enum EventType type);
bool event_release(struct Event* self, enum EventType type);

46
src/engine/font.c Normal file
View File

@ -0,0 +1,46 @@
/*
* DESCRIPTION:
* TrueType font functions.
*/
#include "font.h"
/* Returns line skip of font. */
s32
font_line_skip_get(struct Font* self)
{
return TTF_FontLineSkip(self->ttf);
}
/* Returns height of font. */
s32
font_height_get(struct Font* self)
{
return TTF_FontHeight(self->ttf);
}
/* Inits a font. */
bool
font_init(struct Font* self, char* path, s32 size)
{
self->ttf = TTF_OpenFont(path, size);
if (!self->ttf)
return false;
self->size = size;
self->isInit = true;
return true;
}
/* Frees a font. */
void
font_free(struct Font* self)
{
if (self->isInit)
{
TTF_CloseFont(self->ttf);
self->isInit = false;
}
}

22
src/engine/font.h Normal file
View File

@ -0,0 +1,22 @@
/*
* DESCRIPTION:
* font.c header.
*/
#pragma once
#include "../util/UTIL.h"
#include <SDL2/SDL_ttf.h>
struct Font
{
TTF_Font* ttf;
s32 size;
bool isInit;
};
s32 font_height_get(struct Font* self);
s32 font_line_skip_get(struct Font* self);
bool font_init(struct Font* self, char* path, s32 size);
void font_free(struct Font* self);

13
src/engine/glew.c Normal file
View File

@ -0,0 +1,13 @@
/*
* DESCRIPTION:
* GLEW functions.
*/
#include "glew.h"
/* Inits GLEW. */
void
glew_init(void)
{
glewInit();
}

10
src/engine/glew.h Normal file
View File

@ -0,0 +1,10 @@
/*
* DESCRIPTION:
* glew.c header.
*/
#pragma once
#include <GL/glew.h>
void glew_init(void);

67
src/engine/glyph.c Normal file
View File

@ -0,0 +1,67 @@
/*
* DESCRIPTION:
* Glyph functions.
*/
#include "glyph.h"
/* Returns width of glyph. */
s32
glyph_width_get(struct Font* font, char glyph)
{
struct GlyphMetrics glyphMetrics;
glyph_metrics_get(&glyphMetrics, font, glyph);
return glyphMetrics.maxX - glyphMetrics.minX;
}
/* Determines the kerning between two glyphs. */
s32
glyph_kerning_get(struct Font* font, char glyph, char nextGlyph)
{
return TTF_GetFontKerningSizeGlyphs(font->ttf, glyph, nextGlyph);
}
/* Obtains glyph metrics, given a glyph and a font. */
void
glyph_metrics_get(struct GlyphMetrics* self, struct Font* font, char glyph)
{
TTF_GlyphMetrics
(
font->ttf,
glyph,
&self->minX,
&self->maxX,
&self->minY,
&self->maxY,
&self->advance
);
}
/* Creates a texture from a glyph. */
bool
glyph_texture_init(struct Texture* texture, struct Font* font, char glyph)
{
struct SDL_Surface* surface;
struct SDL_Surface* textSurface;
ivec2 size;
size[0] = glyph_width_get(font, glyph);
size[1] = font_height_get(font);
surface_rgba_init(&surface, size);
textSurface = TTF_RenderGlyph_Blended(font->ttf, glyph, GLYPH_COLOR);
SDL_BlitSurface(textSurface, NULL, surface, NULL);
SDL_FreeSurface(textSurface);
texture_surface_init(texture, surface);
SDL_FreeSurface(surface);
return true;
}

26
src/engine/glyph.h Normal file
View File

@ -0,0 +1,26 @@
/*
* DESCRIPTION:
* text.c header.
*/
#pragma once
#include "font.h"
#include "texture.h"
#include "surface.h"
struct GlyphMetrics
{
s32 minX;
s32 minY;
s32 maxX;
s32 maxY;
s32 advance;
};
static const SDL_Color GLYPH_COLOR = {255, 255, 255, 255};
s32 glyph_width_get(struct Font* font, char glyph);
s32 glyph_kerning_get(struct Font* font, char glyph, char nextGlyph);
bool glyph_texture_init(struct Texture* texture, struct Font* font, char glyph);
void glyph_metrics_get(struct GlyphMetrics* self, struct Font* font, char glyph);

46
src/engine/io.c Normal file
View File

@ -0,0 +1,46 @@
/*
* DESCRIPTION:
* File writing/reading.
*/
#include "io.h"
/* Opens a file for reading. */
bool
file_read(char* path, char* buffer, size_t size)
{
SDL_RWops* io;
if (!path || !buffer)
return false;
io = SDL_RWFromFile(path, "r");
if (!io)
return false;
SDL_RWread(io, buffer, size, 1);
SDL_RWclose(io);
return true;
}
/* Writes data to a file. */
bool
file_write(char* path, void* data, size_t size)
{
SDL_RWops* io;
if (!path || !data)
return false;
io = SDL_RWFromFile(path, "w");
if (!io)
return false;
SDL_RWwrite(io, data, size, 1);
return true;
}

13
src/engine/io.h Normal file
View File

@ -0,0 +1,13 @@
/*
* DESCRIPTION:
* io.c header.
*/
#pragma once
#include "../util/UTIL.h"
#include <SDL2/SDL.h>
bool file_read(char* path, char* buffer, size_t size);
bool file_write(char* path, void* data, size_t size);

36
src/engine/keyboard.c Normal file
View File

@ -0,0 +1,36 @@
#include "keyboard.h"
/* Updates the keyboard. */
void
keyboard_update(struct Keyboard* self)
{
const u8* state;
memcpy(&self->prev, &self->curr, sizeof(u8) * KEY_COUNT);
memset(&self->curr, '\0', sizeof(u8) * KEY_COUNT);
state = SDL_GetKeyboardState(NULL);
memcpy(&self->curr, state, KEY_COUNT);
}
/* Is the given key pressed? */
bool
keyboard_press(struct Keyboard* self, enum KeyType type)
{
return (self->curr[type] && !self->prev[type]);
}
/* Is the given key held? */
bool
keyboard_held(struct Keyboard* self, enum KeyType type)
{
return (self->curr[type] && self->prev[type]);
}
/* Is the given key released? */
bool
keyboard_release(struct Keyboard* self, enum KeyType type)
{
return (!self->curr[type] && self->prev[type]);
}

245
src/engine/keyboard.h Normal file
View File

@ -0,0 +1,245 @@
/*
* DESCRIPTION:
* keyboard.c header.
*/
#pragma once
#include <SDL2/SDL.h>
#include "../util/UTIL.h"
#define KEY_COUNT 255
enum KeyType
{
KEYBOARD_UNKNOWN = 0,
KEYBOARD_UNKNOWN_TWO = 1,
KEYBOARD_UNKNOWN_THREE = 2,
KEYBOARD_UNKNOWN_FOUR = 3,
KEYBOARD_A = 4,
KEYBOARD_B = 5,
KEYBOARD_C = 6,
KEYBOARD_D = 7,
KEYBOARD_E = 8,
KEYBOARD_F = 9,
KEYBOARD_G = 10,
KEYBOARD_H = 11,
KEYBOARD_I = 12,
KEYBOARD_J = 13,
KEYBOARD_K = 14,
KEYBOARD_L = 15,
KEYBOARD_M = 16,
KEYBOARD_N = 17,
KEYBOARD_O = 18,
KEYBOARD_P = 19,
KEYBOARD_Q = 20,
KEYBOARD_R = 21,
KEYBOARD_S = 22,
KEYBOARD_T = 23,
KEYBOARD_U = 24,
KEYBOARD_V = 25,
KEYBOARD_W = 26,
KEYBOARD_X = 27,
KEYBOARD_Y = 28,
KEYBOARD_Z = 29,
KEYBOARD_1 = 30,
KEYBOARD_2 = 31,
KEYBOARD_3 = 32,
KEYBOARD_4 = 33,
KEYBOARD_5 = 34,
KEYBOARD_6 = 35,
KEYBOARD_7 = 36,
KEYBOARD_8 = 37,
KEYBOARD_9 = 38,
KEYBOARD_0 = 39,
KEYBOARD_RETURN = 40,
KEYBOARD_ESCAPE = 41,
KEYBOARD_BACKSPACE = 42,
KEYBOARD_TAB = 43,
KEYBOARD_SPACE = 44,
KEYBOARD_MINUS = 45,
KEYBOARD_EQUALS = 46,
KEYBOARD_LEFTBRACKET = 47,
KEYBOARD_RIGHTBRACKET = 48,
KEYBOARD_BACKSLASH = 49,
KEYBOARD_NONUSHASH = 50,
KEYBOARD_SEMICOLON = 51,
KEYBOARD_APOSTROPHE = 52,
KEYBOARD_GRAVE = 53,
KEYBOARD_COMMA = 54,
KEYBOARD_PERIOD = 55,
KEYBOARD_SLASH = 56,
KEYBOARD_CAPSLOCK = 57,
KEYBOARD_F1 = 58,
KEYBOARD_F2 = 59,
KEYBOARD_F3 = 60,
KEYBOARD_F4 = 61,
KEYBOARD_F5 = 62,
KEYBOARD_F6 = 63,
KEYBOARD_F7 = 64,
KEYBOARD_F8 = 65,
KEYBOARD_F9 = 66,
KEYBOARD_F10 = 67,
KEYBOARD_F11 = 68,
KEYBOARD_F12 = 69,
KEYBOARD_PRINTSCREEN = 70,
KEYBOARD_SCROLLLOCK = 71,
KEYBOARD_PAUSE = 72,
KEYBOARD_INSERT = 73,
KEYBOARD_HOME = 74,
KEYBOARD_PAGEUP = 75,
KEYBOARD_DELETE = 76,
KEYBOARD_END = 77,
KEYBOARD_PAGEDOWN = 78,
KEYBOARD_RIGHT = 79,
KEYBOARD_LEFT = 80,
KEYBOARD_DOWN = 81,
KEYBOARD_UP = 82,
KEYBOARD_NUMLOCKCLEAR = 83,
KEYBOARD_KP_DIVIDE = 84,
KEYBOARD_KP_MULTIPLY = 85,
KEYBOARD_KP_MINUS = 86,
KEYBOARD_KP_PLUS = 87,
KEYBOARD_KP_ENTER = 88,
KEYBOARD_KP_1 = 89,
KEYBOARD_KP_2 = 90,
KEYBOARD_KP_3 = 91,
KEYBOARD_KP_4 = 92,
KEYBOARD_KP_5 = 93,
KEYBOARD_KP_6 = 94,
KEYBOARD_KP_7 = 95,
KEYBOARD_KP_8 = 96,
KEYBOARD_KP_9 = 97,
KEYBOARD_KP_0 = 98,
KEYBOARD_KP_PERIOD = 99,
KEYBOARD_NONUSBACKSLASH = 100,
KEYBOARD_APPLICATION = 101,
KEYBOARD_POWER = 102,
KEYBOARD_KP_EQUALS = 103,
KEYBOARD_F13 = 104,
KEYBOARD_F14 = 105,
KEYBOARD_F15 = 106,
KEYBOARD_F16 = 107,
KEYBOARD_F17 = 108,
KEYBOARD_F18 = 109,
KEYBOARD_F19 = 110,
KEYBOARD_F20 = 111,
KEYBOARD_F21 = 112,
KEYBOARD_F22 = 113,
KEYBOARD_F23 = 114,
KEYBOARD_F24 = 115,
KEYBOARD_EXECUTE = 116,
KEYBOARD_HELP = 117,
KEYBOARD_MENU = 118,
KEYBOARD_SELECT = 119,
KEYBOARD_STOP = 120,
KEYBOARD_AGAIN = 121,
KEYBOARD_UNDO = 122,
KEYBOARD_CUT = 123,
KEYBOARD_COPY = 124,
KEYBOARD_PASTE = 125,
KEYBOARD_FIND = 126,
KEYBOARD_MUTE = 127,
KEYBOARD_VOLUMEUP = 128,
KEYBOARD_VOLUMEDOWN = 129,
KEYBOARD_LOCKINGCAPSLOCK = 130,
KEYBOARD_LOCKINGNUMLOCK = 131,
KEYBOARD_LOCKINGSCROLLLOCK = 132,
KEYBOARD_KP_COMMA = 133,
KEYBOARD_KP_EQUALSAS400 = 134,
KEYBOARD_INTERNATIONAL1 = 135,
KEYBOARD_INTERNATIONAL2 = 136,
KEYBOARD_INTERNATIONAL3 = 137,
KEYBOARD_INTERNATIONAL4 = 138,
KEYBOARD_INTERNATIONAL5 = 139,
KEYBOARD_INTERNATIONAL6 = 140,
KEYBOARD_INTERNATIONAL7 = 141,
KEYBOARD_INTERNATIONAL8 = 142,
KEYBOARD_INTERNATIONAL9 = 143,
KEYBOARD_LANG1 = 144,
KEYBOARD_LANG2 = 145,
KEYBOARD_LANG3 = 146,
KEYBOARD_LANG4 = 147,
KEYBOARD_LANG5 = 148,
KEYBOARD_LANG6 = 149,
KEYBOARD_LANG7 = 150,
KEYBOARD_LANG8 = 151,
KEYBOARD_LANG9 = 152,
KEYBOARD_ALTERASE = 153,
KEYBOARD_SYSREQ = 154,
KEYBOARD_CANCEL = 155,
KEYBOARD_CLEAR = 156,
KEYBOARD_PRIOR = 157,
KEYBOARD_RETURN2 = 158,
KEYBOARD_SEPARATOR = 159,
KEYBOARD_OUT = 160,
KEYBOARD_OPER = 161,
KEYBOARD_CLEARAGAIN = 162,
KEYBOARD_CRSEL = 163,
KEYBOARD_EXSEL = 164,
KEYBOARD_KP_00 = 176,
KEYBOARD_KP_000 = 177,
KEYBOARD_THOUSANDSSEPARATOR = 178,
KEYBOARD_DECIMALSEPARATOR = 179,
KEYBOARD_CURRENCYUNIT = 180,
KEYBOARD_CURRENCYSUBUNIT = 181,
KEYBOARD_KP_LEFTPAREN = 182,
KEYBOARD_KP_RIGHTPAREN = 183,
KEYBOARD_KP_LEFTBRACE = 184,
KEYBOARD_KP_RIGHTBRACE = 185,
KEYBOARD_KP_TAB = 186,
KEYBOARD_KP_BACKSPACE = 187,
KEYBOARD_KP_A = 188,
KEYBOARD_KP_B = 189,
KEYBOARD_KP_C = 190,
KEYBOARD_KP_D = 191,
KEYBOARD_KP_E = 192,
KEYBOARD_KP_F = 193,
KEYBOARD_KP_XOR = 194,
KEYBOARD_KP_POWER = 195,
KEYBOARD_KP_PERCENT = 196,
KEYBOARD_KP_LESS = 197,
KEYBOARD_KP_GREATER = 198,
KEYBOARD_KP_AMPERSAND = 199,
KEYBOARD_KP_DBLAMPERSAND = 200,
KEYBOARD_KP_VERTICALBAR = 201,
KEYBOARD_KP_DBLVERTICALBAR = 202,
KEYBOARD_KP_COLON = 203,
KEYBOARD_KP_HASH = 204,
KEYBOARD_KP_SPACE = 205,
KEYBOARD_KP_AT = 206,
KEYBOARD_KP_EXCLAM = 207,
KEYBOARD_KP_MEMSTORE = 208,
KEYBOARD_KP_MEMRECALL = 209,
KEYBOARD_KP_MEMCLEAR = 210,
KEYBOARD_KP_MEMADD = 211,
KEYBOARD_KP_MEMSUBTRACT = 212,
KEYBOARD_KP_MEMMULTIPLY = 213,
KEYBOARD_KP_MEMDIVIDE = 214,
KEYBOARD_KP_PLUSMINUS = 215,
KEYBOARD_KP_CLEAR = 216,
KEYBOARD_KP_CLEARENTRY = 217,
KEYBOARD_KP_BINARY = 218,
KEYBOARD_KP_OCTAL = 219,
KEYBOARD_KP_DECIMAL = 220,
KEYBOARD_KP_HEXADECIMAL = 221,
KEYBOARD_LCTRL = 224,
KEYBOARD_LSHIFT = 225,
KEYBOARD_LALT = 226,
KEYBOARD_LGUI = 227,
KEYBOARD_RCTRL = 228,
KEYBOARD_RSHIFT = 229,
KEYBOARD_RALT = 230,
KEYBOARD_RGUI = 231
};
struct Keyboard
{
u8 curr[KEY_COUNT];
u8 prev[KEY_COUNT];
};
void keyboard_update(struct Keyboard* self);
bool keyboard_press(struct Keyboard* self, enum KeyType type);
bool keyboard_held(struct Keyboard* self, enum KeyType type);
bool keyboard_release(struct Keyboard* self, enum KeyType type);

55
src/engine/mouse.c Normal file
View File

@ -0,0 +1,55 @@
/*
* DESCRIPTION:
* Mouse functions.
*/
#include "mouse.h"
/* Updates the mouse. */
void
mouse_update(struct Mouse* self)
{
s32 state;
s32 x;
s32 y;
memcpy(&self->prev, &self->curr, sizeof(bool) * MOUSE_COUNT);
memset(&self->curr, '\0', sizeof(bool) * MOUSE_COUNT);
state = SDL_GetMouseState(NULL, NULL);
if ((state & SDL_BUTTON_LMASK) != 0)
self->curr[MOUSE_LEFT] = true;
if ((state & SDL_BUTTON_MMASK) != 0)
self->curr[MOUSE_MIDDLE] = true;
if ((state & SDL_BUTTON_RMASK) != 0)
self->curr[MOUSE_RIGHT] = true;
SDL_GetMouseState(&x, &y);
self->position[0] = (f32)x;
self->position[1] = (f32)y;
}
/* Is a given mouse button pressed? */
bool
mouse_press(struct Mouse* self, enum MouseType type)
{
return (self->curr[type] && !self->prev[type]);
}
/* Is a given mouse button held? */
bool
mouse_held(struct Mouse* self, enum MouseType type)
{
return (self->curr[type] && self->prev[type]);
}
/* Is a given mouse button released? */
bool
mouse_release(struct Mouse* self, enum MouseType type)
{
return (!self->curr[type] && self->prev[type]);
}

31
src/engine/mouse.h Normal file
View File

@ -0,0 +1,31 @@
/*
* DESCRIPTION:
* mouse.c header.
*/
#pragma once
#include <SDL2/SDL.h>
#include "../util/UTIL.h"
#define MOUSE_COUNT MOUSE_RIGHT + 1
enum MouseType
{
MOUSE_NONE,
MOUSE_LEFT,
MOUSE_MIDDLE,
MOUSE_RIGHT
};
struct Mouse
{
vec2 position;
bool curr[MOUSE_COUNT];
bool prev[MOUSE_COUNT];
};
void mouse_update(struct Mouse* self);
bool mouse_press(struct Mouse* self, enum MouseType type);
bool mouse_held(struct Mouse* self, enum MouseType type);
bool mouse_release(struct Mouse* self, enum MouseType type);

69
src/engine/music.c Normal file
View File

@ -0,0 +1,69 @@
/*
* DESCRIPTION:
* Music functions.
*/
#include "music.h"
/* Initializes music. */
bool
music_init(struct Music* self, char* path)
{
self->chunk = Mix_LoadMUS(path);
if (!self->chunk)
return false;
self->isInit = true;
return true;
}
/* Frees music. */
void
music_free(struct Music* self)
{
if (self->isInit)
{
Mix_FreeMusic(self->chunk);
self->isInit = false;
}
}
/* Plays music, specifying if it loops. */
void
music_play(struct Music* self, bool isLoop)
{
if (isLoop)
Mix_PlayMusic(self->chunk, -1);
else
Mix_PlayMusic(self->chunk, 0);
}
/* Resumes music, if it was paused before. */
void
music_resume(void)
{
Mix_ResumeMusic();
}
/* Pauses music. */
void
music_pause(void)
{
Mix_PauseMusic();
}
/* Stops music. */
void
music_stop(void)
{
Mix_HaltMusic();
}
/* Is music playing? */
bool
music_is_playing(void)
{
return Mix_PlayingMusic();
}

24
src/engine/music.h Normal file
View File

@ -0,0 +1,24 @@
/*
* DESCRIPTION:
* music.c header.
*/
#pragma once
#include <SDL2/SDL_mixer.h>
#include "../util/UTIL.h"
struct Music
{
Mix_Music* chunk;
bool isInit;
};
bool music_is_playing(void);
void music_free(struct Music* self);
bool music_init(struct Music* self, char* path);
void music_pause(void);
void music_play(struct Music* self, bool isLoop);
void music_resume(void);
void music_stop(void);

108
src/engine/renderer.c Normal file
View File

@ -0,0 +1,108 @@
/*
* DESCRIPTION:
* Basic rendering.
*/
#include "renderer.h"
/* Initializes renderer. */
void
renderer_init(struct Renderer* self, struct Window* window, enum CameraType type)
{
self->window = window;
self->glContext = SDL_GL_CreateContext(self->window->sdl);
glew_init();
vao_init(&self->vao);
vbo_init(&self->vbo, GL_ARRAY_BUFFER, true);
vbo_init(&self->ebo, GL_ELEMENT_ARRAY_BUFFER, true);
switch (type)
{
case CAMERA_PERSPECTIVE:
camera_perspective_init
(
&self->camera,
RENDERER_CAMERA_PERSPECTIVE_FOV_DEFAULT,
RENDERER_CAMERA_PERSPECTIVE_ASPECT_DEFAULT
);
break;
case CAMERA_ORTHOGRAPHIC:
camera_orthographic_init(&self->camera, self->window->size);
break;
default:
break;
}
}
/* Frees renderer. */
void
renderer_free(struct Renderer* self)
{
memset(self, '\0', sizeof(struct Renderer));
SDL_GL_DeleteContext(self->glContext);
}
/* Sets renderer's viewport. */
void
renderer_viewport_set(struct Renderer* self, ivec4 viewport)
{
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
}
/* Sets the renderer's viewport to its window. */
void
renderer_viewport_window_set(struct Renderer* self)
{
ivec4 viewport;
window_ivec4_get(self->window, viewport);
renderer_viewport_set(self, viewport);
}
/* Uses the specified shader. */
void
renderer_shader_use(struct Renderer* self, struct Shader* shader)
{
self->shader = shader;
shader_use(shader);
}
/* Sets the renderer clear color. */
void
renderer_clear_color_set(struct Renderer* self, vec4 color)
{
glClearColor(color[0], color[1], color[2], color[3]);
glm_vec4_copy(color, self->clearColor);
}
/* Clears the renderer. */
void
renderer_clear(struct Renderer* self)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
/* Presents renderer. */
void
renderer_present(struct Renderer* self)
{
SDL_GL_SwapWindow(self->window->sdl);
}
/* Updates renderer. */
void
renderer_update(struct Renderer* self)
{
renderer_viewport_window_set(self);
camera_update(&self->camera);
if (self->camera.type == CAMERA_ORTHOGRAPHIC)
camera_orthographic_window_set(&self->camera, self->window);
}

39
src/engine/renderer.h Normal file
View File

@ -0,0 +1,39 @@
/*
* DESCRIPTION:
* renderer.c header.
*/
#pragma once
#include "atlas.h"
#include "camera.h"
#include "glew.h"
#include "shader.h"
#include "vao.h"
#include "vbo.h"
#include "vertexattribute.h"
#define RENDERER_CAMERA_PERSPECTIVE_FOV_DEFAULT 90.0f
#define RENDERER_CAMERA_PERSPECTIVE_ASPECT_DEFAULT 1.0f
struct Renderer
{
SDL_GLContext glContext;
struct Camera camera;
struct Window* window;
struct Shader* shader;
struct VAO vao;
struct VBO ebo;
struct VBO vbo;
vec4 clearColor;
};
void renderer_init(struct Renderer* self, struct Window* window, enum CameraType type);
void renderer_clear_color_set(struct Renderer* self, vec4 color);
void renderer_viewport_window_set(struct Renderer* self);
void renderer_viewport_set(struct Renderer* self, ivec4 viewport);
void renderer_clear(struct Renderer* self);
void renderer_update(struct Renderer* self);
void renderer_free(struct Renderer* self);
void renderer_present(struct Renderer* self);
void renderer_shader_use(struct Renderer* self, struct Shader* shader);

65
src/engine/sdl.c Normal file
View File

@ -0,0 +1,65 @@
/*
* DESCRIPTION:
* Handles basic SDL functions.
*/
#include "sdl.h"
/* Initializes SDL. */
void
sdl_init(void)
{
if (SDL_INIT_VIDEO < 0)
{
printf("SDL2 ERROR: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
else
printf("SDL2 VIDEO LOADED\n");
if (SDL_INIT_TIMER < 0)
{
printf("SDL2 ERROR: %s\n", SDL_GetError());
exit(EXIT_FAILURE);
}
else
printf("SDL2 TIMER LOADED\n");
if (IMG_Init(IMG_FLAGS) < 0)
{
printf("SDL_image ERROR: %s\n", IMG_GetError());
exit(EXIT_FAILURE);
}
else
printf("SDL_image LOADED\n");
if (TTF_Init() < 0)
{
printf("SDL_ttf ERROR: %s\n", TTF_GetError());
exit(EXIT_FAILURE);
}
else
printf("SDL_ttf LOADED\n");
if (Mix_OpenAudio(MIX_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_CHANNELS, MIX_SAMPLE_SIZE) < 0)
{
printf("SDL_mixer ERROR: %s\n", TTF_GetError());
exit(EXIT_FAILURE);
}
else
printf("SDL_mixer LOADED\n");
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
}
/* Quits SDL. */
void
sdl_quit(void)
{
SDL_Quit();
Mix_CloseAudio();
IMG_Quit();
}

18
src/engine/sdl.h Normal file
View File

@ -0,0 +1,18 @@
/*
* DESCRIPTION:
* sdl.c header.
*/
#pragma once
#include <SDL2/SDL.h>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL_image.h>
#define MIX_FREQUENCY 44100
#define MIX_SAMPLE_SIZE 2048
#define IMG_FLAGS (IMG_INIT_PNG)
void sdl_init(void);
void sdl_quit(void);

125
src/engine/shader.c Normal file
View File

@ -0,0 +1,125 @@
/*
* DESCRIPTION:
* OpenGL shader abstraction.
*/
#include "shader.h"
/* Given two GLSL strings representing the vertex/fragment shaders,
* initializes and compiles shader program. */
bool
shader_init(struct Shader* self, char* vertex, char* fragment)
{
s32 success;
char log[SHADER_LOG_MAX];
GLuint vertexHandle;
GLuint fragmentHandle;
vertexHandle = glCreateShader(GL_VERTEX_SHADER);
fragmentHandle = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(vertexHandle, 1, (const char* const*)&vertex, NULL);
glShaderSource(fragmentHandle, 1, (const char* const*)&fragment, NULL);
glCompileShader(vertexHandle);
glCompileShader(fragmentHandle);
glGetShaderiv(vertexHandle, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(vertexHandle, SHADER_LOG_MAX, NULL, log);
printf("COMPILE ERROR: Shader #%i | %s\n", vertexHandle, log);
return false;
}
else
printf("COMPILE SUCCESS: Shader #%i\n", vertexHandle);
glGetShaderiv(fragmentHandle, GL_COMPILE_STATUS, &success);
if (!success)
{
glGetShaderInfoLog(fragmentHandle, SHADER_LOG_MAX, NULL, log);
printf("COMPILE ERROR: Shader #%i | %s\n", fragmentHandle, log);
return false;
}
else
printf("COMPILE SUCCESS: Shader #%i\n", fragmentHandle);
self->handle = glCreateProgram();
glAttachShader(self->handle, vertexHandle);
glAttachShader(self->handle, fragmentHandle);
glLinkProgram(self->handle);
glDeleteShader(vertexHandle);
glDeleteShader(fragmentHandle);
self->isInit = true;
return true;
}
/* Uses the specified shader program. */
void
shader_use(struct Shader* self)
{
glUseProgram(self->handle);
}
/* Frees a shader program. */
void
shader_free(struct Shader* self)
{
if (self->isInit)
{
glDeleteProgram(self->handle);
self->isInit = false;
}
}
/* Sets a s32 uniform. */
void
shader_uniform_s32_set(struct Shader* self, char* name, s32 value)
{
glUniform1i(glGetUniformLocation(self->handle, name), value);
}
/* Sets a f32 uniform. */
void
shader_uniform_f32_set(struct Shader* self, char* name, f32 value)
{
glUniform1i(glGetUniformLocation(self->handle, name), value);
}
/* Sets a vec3 uniform. */
void
shader_uniform_vec3_set(struct Shader* self, char* name, vec3 value)
{
glUniform3fv(glGetUniformLocation(self->handle, name), 1, value);
}
/* Sets a vec4 uniform. */
void
shader_uniform_vec4_set(struct Shader* self, char* name, vec4 value)
{
glUniform4fv(glGetUniformLocation(self->handle, name), 1, value);
}
/* Sets a mat4 uniform. */
void
shader_uniform_mat4_set(struct Shader* self, char* name, mat4 value)
{
glUniformMatrix4fv(glGetUniformLocation(self->handle, name), 1, GL_FALSE, (f32*)value);
}
/* Sets a texture uniform. */
void
shader_uniform_texture_set(struct Shader* self, char* name, struct Texture* texture, s32 index)
{
glActiveTexture(GL_TEXTURE0 + index);
texture_bind(texture);
glUniform1i(glGetUniformLocation(self->handle, name), index);
}

29
src/engine/shader.h Normal file
View File

@ -0,0 +1,29 @@
/*
* DESCRIPTION:
* shader.c header.
*/
#pragma once
#include <GL/glew.h>
#include <GL/gl.h>
#include "texture.h"
#define SHADER_LOG_MAX 1024
struct Shader
{
GLuint handle;
bool isInit;
};
bool shader_init(struct Shader* self, char* vertex, char* fragment);
void shader_use(struct Shader* self);
void shader_free(struct Shader* self);
void shader_uniform_f32_set(struct Shader* self, char* name, f32 value);
void shader_uniform_s32_set(struct Shader* self, char* name, s32 value);
void shader_uniform_mat4_set(struct Shader* self, char* name, mat4 value);
void shader_uniform_vec3_set(struct Shader* self, char* name, vec3 value);
void shader_uniform_vec4_set(struct Shader* self, char* name, vec4 value);
void shader_uniform_texture_set(struct Shader* self, char* name, struct Texture* texture, s32 index);

38
src/engine/sound.c Normal file
View File

@ -0,0 +1,38 @@
/*
* DESCRIPTION:
* Sound functions.
*/
#include "sound.h"
/* Initializes a sound. */
bool
sound_init(struct Sound* self, char* path)
{
self->chunk = Mix_LoadWAV(path);
if (!self->chunk)
return false;
self->isInit = true;
return true;
}
/* Frees a sound. */
void
sound_free(struct Sound* self)
{
if (self->isInit)
{
Mix_FreeChunk(self->chunk);
self->isInit = false;
}
}
/* Plays a sound, specifying a channel. */
void
sound_play(struct Sound* self, s32 channel)
{
Mix_PlayChannel(-1, self->chunk, 0);
}

20
src/engine/sound.h Normal file
View File

@ -0,0 +1,20 @@
/*
* DESCRIPTION:
* sound.c header.
*/
#pragma once
#include <SDL2/SDL_mixer.h>
#include "../util/UTIL.h"
struct Sound
{
struct Mix_Chunk* chunk;
bool isInit;
};
bool sound_init(struct Sound* self, char* path);
void sound_free(struct Sound* self);
void sound_play(struct Sound* self, s32 channel);

23
src/engine/surface.c Normal file
View File

@ -0,0 +1,23 @@
/*
* DESCRIPTION:
* SDL_Surface functions.
*/
#include "surface.h"
/* Initializes an RGBA8888 surface. */
void
surface_rgba_init(struct SDL_Surface** self, ivec2 size)
{
*self = SDL_CreateRGBSurface
(
0,
size[0],
size[1],
32,
0xFF000000,
0x00FF0000,
0x0000FF00,
0x000000FF
);
}

12
src/engine/surface.h Normal file
View File

@ -0,0 +1,12 @@
/*
* DESCRIPTION:
* surface.c header.
*/
#pragma once
#include <SDL2/SDL.h>
#include "../util/UTIL.h"
void surface_rgba_init(struct SDL_Surface** self, ivec2 size);

70
src/engine/texture.c Normal file
View File

@ -0,0 +1,70 @@
/*
* DESCRIPTION:
* OpenGL texture abstraction.
*/
#include "texture.h"
/* Given an SDL_Surface, creates a GL texture from it. */
/* NOTE: loading only supports RGBA */
bool
texture_surface_init(struct Texture* self, struct SDL_Surface* surface)
{
if (!self->isInit)
{
glGenTextures(1, &self->handle);
self->isInit = true;
}
if (!surface)
return false;
self->w = surface->w;
self->h = surface->h;
texture_bind(self);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->w, self->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, surface->pixels);
glGenerateMipmap(GL_TEXTURE_2D);
return true;
}
/* Initializes the OpenGL texture, given image data. */
bool
texture_init(struct Texture* self, char* path)
{
struct SDL_Surface* surface;
surface = IMG_Load(path);
if (!surface)
return false;
texture_surface_init(self, surface);
SDL_FreeSurface(surface);
return true;
}
/* Binds a texture. */
void
texture_bind(struct Texture* self)
{
glBindTexture(GL_TEXTURE_2D, self->handle);
}
/* Frees texture. */
void
texture_free(struct Texture* self)
{
glDeleteTextures(1, &self->handle);
memset(self, '\0', sizeof(struct Texture));
}

29
src/engine/texture.h Normal file
View File

@ -0,0 +1,29 @@
/*
* DESCRIPTION:
* texture.c header.
*/
#pragma once
#include <GL/glew.h>
#include <GL/gl.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL_ttf.h>
#include "../util/UTIL.h"
struct Texture
{
GLuint handle;
s32 w;
s32 h;
s32 channels;
bool isInit;
};
bool texture_init(struct Texture* self, char* path);
bool texture_surface_init(struct Texture* self, struct SDL_Surface* surface);
void texture_bind(struct Texture* self);
void texture_free(struct Texture* self);

16
src/engine/tick.c Normal file
View File

@ -0,0 +1,16 @@
/*
* DESCRIPTION:
* Handles ticks; game intervals.
*/
#include "tick.h"
/* Update ticks. */
void
tick_update(struct Tick* self)
{
self->prev = self->curr;
self->curr = SDL_GetTicks64();
self->delta = self->curr - self->prev;
self->cum += self->delta;
}

20
src/engine/tick.h Normal file
View File

@ -0,0 +1,20 @@
/*
* DESCRIPTION:
* tick.c header.
*/
#pragma once
#include <SDL2/SDL.h>
#include "../util/UTIL.h"
struct Tick
{
u64 curr;
u64 prev;
u64 delta;
u64 cum;
};
void tick_update(struct Tick* self);

35
src/engine/vao.c Normal file
View File

@ -0,0 +1,35 @@
/*
* DESCRIPTION:
* OpenGL Vertex Array Object (VAO) abstractions.
*/
#include "vao.h"
/* Initializes a VAO. */
void
vao_init(struct VAO* self)
{
glGenVertexArrays(1, &self->handle);
}
/* Binds VAO. */
void
vao_bind(struct VAO* self)
{
glBindVertexArray(self->handle);
}
/* Unbinds VAO. */
void
vao_unbind(void)
{
glBindVertexArray(0);
}
/* Frees VAO. */
void
vao_free(struct VAO* self)
{
glDeleteVertexArrays(1, &self->handle);
memset(self, '\0', sizeof(struct VAO));
}

21
src/engine/vao.h Normal file
View File

@ -0,0 +1,21 @@
/*
* DESCRIPTION:
* vao.c header.
*/
#pragma once
#include <GL/glew.h>
#include <GL/gl.h>
#include "../util/UTIL.h"
struct VAO
{
GLuint handle;
};
void vao_init(struct VAO* self);
void vao_bind(struct VAO* self);
void vao_unbind(void);
void vao_free(struct VAO* self);

38
src/engine/vbo.c Normal file
View File

@ -0,0 +1,38 @@
/*
* DESCRIPTION:
* OpenGL Vertex Buffer Object (VBO) abstractions.
*/
#include "vbo.h"
/* Initializes/generates a VBO. */
void
vbo_init(struct VBO* self, GLint type, bool isDynamic)
{
self->isDynamic = isDynamic;
self->type = type;
glGenBuffers(1, &self->handle);
}
/* Bind a VBO, specifying a type. */
void
vbo_bind(struct VBO* self)
{
glBindBuffer(self->type, self->handle);
}
/* Frees a given VBO. */
void
vbo_free(struct VBO* self)
{
glDeleteBuffers(1, &self->handle);
memset(self, '\0', sizeof(struct VBO));
}
/* Binds and sends data to a VBO. */
void
vbo_buffer(struct VBO* self, size_t size, void* data)
{
glBufferData(self->type, size, data, self->isDynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
}

23
src/engine/vbo.h Normal file
View File

@ -0,0 +1,23 @@
/*
* DESCRIPTION:
* vbo.c header.
*/
#pragma once
#include <GL/glew.h>
#include <GL/gl.h>
#include "../util/UTIL.h"
typedef struct VBO
{
GLuint handle;
GLint type;
bool isDynamic;
} VBO;
void vbo_buffer(struct VBO* self, size_t size, void* data);
void vbo_bind(struct VBO* self);
void vbo_free(struct VBO* self);
void vbo_init(struct VBO* self, GLint type, bool isDynamic);

View File

@ -0,0 +1,30 @@
/*
* DESCRIPTION:
* OpenGL Vertex attribute abstraction.
*/
#include "vertexattribute.h"
/* Sets and enables a vertex attribute. */
void
vertex_attribute_set(GLuint index, GLint size, GLenum type, GLsizei stride, size_t offset)
{
switch (type)
{
case GL_BYTE:
case GL_UNSIGNED_BYTE:
case GL_SHORT:
case GL_UNSIGNED_SHORT:
case GL_INT:
case GL_UNSIGNED_INT:
case GL_INT_2_10_10_10_REV:
case GL_UNSIGNED_INT_2_10_10_10_REV:
glVertexAttribIPointer(index, size, type, stride, (void*)offset);
break;
default:
glVertexAttribPointer(index, size, type, GL_FALSE, stride, (void*)offset);
break;
}
glEnableVertexAttribArray(index);
}

View File

@ -0,0 +1,13 @@
/*
* DESCRIPTION:
* vertexattribute.c header.
*/
#pragma once
#include <GL/glew.h>
#include <GL/gl.h>
#include "../util/UTIL.h"
void vertex_attribute_set(GLuint index, GLint size, GLenum type, GLsizei stride, size_t offset);

106
src/engine/window.c Normal file
View File

@ -0,0 +1,106 @@
/*
* DESCRIPTION:
* Window functionality.
*/
#include "window.h"
/* Initializes a window; needs menu, width, height, and flags. */
void
window_init(struct Window* self, char* name, vec2 size, u32 flags)
{
self->name = name;
self->flags = flags;
glm_vec2_copy(size, self->size);
self->isFullscreen = false;
self->sdl = SDL_CreateWindow
(
name,
SDL_WINDOWPOS_UNDEFINED,
SDL_WINDOWPOS_UNDEFINED,
(s32)self->size[0],
(s32)self->size[1],
flags
);
}
/* Frees a given window. */
void
window_free(struct Window* self)
{
SDL_DestroyWindow(self->sdl);
memset(self, '\0', sizeof(struct Window));
}
/* Returns window size. */
void
window_ivec4_get(struct Window* self, ivec4 vector)
{
vector[0] = 0;
vector[1] = 0;
vector[2] = self->size[0];
vector[3] = self->size[1];
}
/* Sets video mode to fullscreen. */
void
window_fullscreen_enter(struct Window* self)
{
SDL_DisplayMode dm;
s32 w;
s32 h;
SDL_GetCurrentDisplayMode(0, &dm);
w = dm.w;
h = dm.h;
SDL_SetWindowSize(self->sdl, w, h);
self->isFullscreen = true;
SDL_SetWindowFullscreen(self->sdl, SDL_WINDOW_FULLSCREEN);
}
/* Exit fullscreen.*/
void
window_fullscreen_exit(struct Window* self)
{
self->isFullscreen = false;
SDL_SetWindowFullscreen(self->sdl, 0);
}
void
window_fullscreen_toggle(struct Window* self)
{
if (!self->isFullscreen)
window_fullscreen_enter(self);
else
window_fullscreen_exit(self);
}
/* Updates window. */
void
window_update(struct Window* self)
{
s32 w;
s32 h;
SDL_GetWindowSize(self->sdl, &w, &h);
self->size[0] = (f32)w;
self->size[1] = (f32)h;
}
/* Window coords -> OpenGL coords. */
void
window_coords_to_gl(struct Window* self, vec2 position, vec2 dest)
{
dest[0] = ((position[0] / (f32)self->size[0]) * 2.0f) - 1.0f;
dest[1] = ((position[1] / (f32)self->size[1]) * 2.0f) - 1.0f;
}

28
src/engine/window.h Normal file
View File

@ -0,0 +1,28 @@
/*
* DESCRIPTION:
* window.c header.
*/
#pragma once
#include <SDL2/SDL.h>
#include "../util/UTIL.h"
struct Window
{
struct SDL_Window* sdl;
char* name;
u32 flags;
vec2 size;
bool isFullscreen;
};
void window_init(struct Window* self, char* name, vec2 size, u32 flags);
void window_free(struct Window* self);
void window_update(struct Window* self);
void window_fullscreen_enter(struct Window* self);
void window_fullscreen_exit(struct Window* self);
void window_fullscreen_toggle(struct Window* self);
void window_ivec4_get(struct Window* self, ivec4 vector);
void window_coords_to_gl(struct Window* self, vec2 position, vec2 dest);

73
src/game/ecs/ECS_TYPES.h Normal file
View File

@ -0,0 +1,73 @@
/*
* DESCRIPTION:
* ECS types.
*/
#pragma once
#include "../../util/UTIL.h"
#define ECS_FUNCTION_COUNT ECS_FUNCTION_DRAW + 1
enum ECSFunctionType
{
ECS_FUNCTION_ADD,
ECS_FUNCTION_DELETE,
ECS_FUNCTION_UPDATE_F,
ECS_FUNCTION_UPDATE_V,
ECS_FUNCTION_DRAW
};
#define ECS_C_COUNT ECS_C_UI_BUTTON + 1
enum ECSComponentType
{
ECS_C_CHASE,
ECS_C_CIRCLE,
ECS_C_CIRCLE_COLLIDE,
ECS_C_COLOR,
ECS_C_COLOR_CHANGE,
ECS_C_COLOR_COLLIDE_DELETE,
ECS_C_CONTACT_DAMAGE,
ECS_C_CONTROL,
ECS_C_DAMAGE,
ECS_C_FLASH,
ECS_C_GAME_OBJECT,
ECS_C_HEALTH,
ECS_C_MOVE,
ECS_C_ORBIT,
ECS_C_PARTICLE_SPAWN,
ECS_C_PHYSICS,
ECS_C_PLAYER_ATLAS_HEALTH,
ECS_C_PLAYER_DEATH,
ECS_C_PULSATE,
ECS_C_ROTATION,
ECS_C_SCALE,
ECS_C_SPIN,
ECS_C_SPRITE,
ECS_C_STUN,
ECS_C_TEXT,
ECS_C_TIME_DELETE,
ECS_C_UI_BUTTON
};
struct ECS;
typedef void (*ECSRegister)(void);
typedef void (*ECSFunction)(void*);
struct ECSSystem
{
ECSFunction functions[ECS_FUNCTION_COUNT];
};
struct ECSComponentList
{
struct ECSSystem system;
struct Vector components;
enum ECSComponentType type;
};
struct ECS
{
struct ECSComponentList lists[ECS_C_COUNT];
u32 nextID;
};

59
src/game/ecs/c_chase.c Normal file
View File

@ -0,0 +1,59 @@
/*
* DESCRIPTION:
* Chase component.
*/
#include "c_chase.h"
static void update_f(struct CChase* self);
/* Draws a chase component. */
static void
update_f(struct CChase* self)
{
struct CPhysics* physics;
struct CPhysics* targetPhysics;
f32 angle;
physics = ecs_get(self->id, ECS_C_PHYSICS);
targetPhysics = ecs_get(self->targetID, ECS_C_PHYSICS);
if (!physics || !targetPhysics)
return;
angle = ATAN
(
targetPhysics->position[0],
physics->position[0],
targetPhysics->position[1],
physics->position[1]
);
physics->velocity[0] -= (cos(angle) * self->speed);
physics->velocity[1] -= (sin(angle) * self->speed);
}
/* Sets chase component values. */
void
c_chase_set(struct CChase* self, u32 targetID, f32 speed)
{
self->targetID = targetID;
self->speed = speed;
}
/* Registers chase component. */
void
c_chase_register(void)
{
ecs_register
(
ECS_C_CHASE,
sizeof(struct CChase),
C_CHASE_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

20
src/game/ecs/c_chase.h Normal file
View File

@ -0,0 +1,20 @@
/*
* DESCRIPTION:
* c_chase.c header.
*/
#pragma once
#include "c_physics.h"
#define C_CHASE_LIMIT 0xFF
struct CChase
{
u32 id;
u32 targetID;
f32 speed;
};
void c_chase_set(struct CChase* self, u32 targetID, f32 speed);
void c_chase_register(void);

30
src/game/ecs/c_circle.c Normal file
View File

@ -0,0 +1,30 @@
/*
* DESCRIPTION:
* Circle component.
*/
#include "c_circle.h"
/* Sets circle component values. */
void
c_circle_set(struct CCircle* self, f32 radius)
{
self->radius = radius;
}
/* Registers circle component. */
void
c_circle_register(void)
{
ecs_register
(
ECS_C_CIRCLE,
sizeof(struct CCircle),
C_CIRCLE_LIMIT,
NULL,
NULL,
NULL,
NULL,
NULL
);
}

19
src/game/ecs/c_circle.h Normal file
View File

@ -0,0 +1,19 @@
/*
* DESCRIPTION:
* c_circle.c header.
*/
#pragma once
#include "entity.h"
#define C_CIRCLE_LIMIT 0xFF
struct CCircle
{
u32 id;
f32 radius;
};
void c_circle_set(struct CCircle* self, f32 radius);
void c_circle_register(void);

View File

@ -0,0 +1,100 @@
/*
* DESCRIPTION:
* Circle collide component.
*/
#include "c_circle_collide.h"
static bool collide(struct CCircle* a, struct CCircle* b);
static void add(struct CCircleCollide* self);
static void update_f(struct CCircleCollide* self);
static void delete(struct CCircleCollide* self);
/* Are two circle components colliding? */
static bool
collide(struct CCircle* a, struct CCircle* b)
{
struct CPhysics* aPhysics;
struct CPhysics* bPhysics;
f32 distance;
f32 sum;
aPhysics = ecs_get(a->id, ECS_C_PHYSICS);
bPhysics = ecs_get(b->id, ECS_C_PHYSICS);
if (!aPhysics || !bPhysics)
return false;
distance = DISTANCE_2D
(
aPhysics->position[0],
bPhysics->position[0],
aPhysics->position[1],
bPhysics->position[1]
);
sum = a->radius + b->radius;
if (distance < sum)
return true;
return false;
}
/* Adds circle collide component. */
static void
add(struct CCircleCollide* self)
{
vector_init(&self->collisions, sizeof(u32), C_CIRCLE_COLLIDE_COLLISIONS_LIMIT);
}
/* Deletes circle collide component. */
static void
delete(struct CCircleCollide* self)
{
vector_free(&self->collisions);
}
/* Draws a circle collide component. */
static void
update_f(struct CCircleCollide* self)
{
struct CCircle* circle;
circle = ecs_get(self->id, ECS_C_CIRCLE);
vector_clear(&self->collisions);
if (!circle)
return;
for (s32 i = 0; i < (s32)game.ecs.lists[ECS_C_CIRCLE].components.count; i++)
{
struct CCircle* collideCircle;
collideCircle = ecs_from_index_get(i, ECS_C_CIRCLE);
if (collideCircle->id == self->id)
continue;
if (collide(circle, collideCircle))
vector_push(&self->collisions, &collideCircle->id);
}
}
/* Registers circle collide component. */
void
c_circle_collide_register(void)
{
ecs_register
(
ECS_C_CIRCLE_COLLIDE,
sizeof(struct CCircleCollide),
C_CIRCLE_COLLIDE_LIMIT,
(ECSFunction)add,
(ECSFunction)delete,
(ECSFunction)update_f,
NULL,
NULL
);
}

View File

@ -0,0 +1,20 @@
/*
* DESCRIPTION:
* c_circle_collide.c header.
*/
#pragma once
#include "c_circle.h"
#include "c_physics.h"
#define C_CIRCLE_COLLIDE_LIMIT 0xFF
#define C_CIRCLE_COLLIDE_COLLISIONS_LIMIT C_CIRCLE_COLLIDE_LIMIT
struct CCircleCollide
{
u32 id;
struct Vector collisions; /* u32; CCircle ID */
};
void c_circle_collide_register(void);

30
src/game/ecs/c_color.c Normal file
View File

@ -0,0 +1,30 @@
/*
* DESCRIPTION:
* Color component.
*/
#include "c_color.h"
/* Sets color component. */
void
c_color_set(struct CColor* self, enum CColorType type)
{
self->type = type;
}
/* Registers color component. */
void
c_color_register(void)
{
ecs_register
(
ECS_C_COLOR,
sizeof(struct CColor),
C_COLOR_LIMIT,
NULL,
NULL,
NULL,
NULL,
NULL
);
}

40
src/game/ecs/c_color.h Normal file
View File

@ -0,0 +1,40 @@
/*
* DESCRIPTION:
* c_color.c header.
*/
#pragma once
#include "entity.h"
#define C_COLOR_LIMIT 0xFF
#define C_COLOR_COUNT C_COLOR_CYAN + 1
enum CColorType
{
C_COLOR_GREEN,
C_COLOR_BLUE,
C_COLOR_RED,
C_COLOR_YELLOW,
C_COLOR_MAGENTA,
C_COLOR_CYAN
};
struct CColor
{
u32 id;
enum CColorType type;
};
static const vec4 C_COLOR_VALUES[C_COLOR_COUNT] =
{
{0.30f, 1.00f, 0.30f, 1.00f},
{0.20f, 0.50f, 0.80f, 1.00f},
{1.00f, 0.20f, 0.20f, 1.00f},
{1.00f, 1.00f, 0.30f, 1.00f},
{1.00f, 0.20f, 0.90f, 1.00f},
{0.20f, 1.00f, 0.90f, 1.00f}
};
void c_color_set(struct CColor* self, enum CColorType type);
void c_color_register(void);

View File

@ -0,0 +1,116 @@
/*
* DESCRIPTION:
* Color change component.
*/
#include "c_color_change.h"
static void add(struct CColorChange* self);
static void update_f(struct CColorChange* self);
/* Adds a color change component. */
static void
add(struct CColorChange* self)
{
self->isFinished = true;
}
/* Updates an color change component. */
static void
update_f(struct CColorChange* self)
{
f32 progress;
struct CSprite* sprite;
struct CText* text;
vec4 current;
vec4 difference;
vec4 step;
vec4* color;
sprite = ecs_get(self->id, ECS_C_SPRITE);
text = ecs_get(self->id, ECS_C_TEXT);
if (self->isFinished)
return;
if (sprite)
color = &sprite->color;
else if (text)
color = &text->color;
else
return;
progress = (f32)self->timer / self->timerMax;
switch (self->type)
{
case C_COLOR_CHANGE_TO:
case C_COLOR_CHANGE_TO_STICK:
glm_vec4_copy(self->baseColor, current);
glm_vec4_sub(current, self->color, difference);
glm_vec4_scale(difference, (1.0f - progress), step);
glm_vec4_sub(current, step, current);
glm_vec4_copy(current, *color);
break;
case C_COLOR_CHANGE_FROM:
case C_COLOR_CHANGE_FROM_STICK:
glm_vec4_copy(self->color, current);
glm_vec4_sub(current, self->baseColor, difference);
glm_vec4_scale(difference, (1.0f - progress), step);
glm_vec4_sub(current, step, current);
glm_vec4_copy(current, *color);
break;
default:
break;
}
self->timer--;
if (self->timer <= 0)
{
switch (self->type)
{
case C_COLOR_CHANGE_TO:
case C_COLOR_CHANGE_FROM:
glm_vec4_copy(self->baseColor, *color);
break;
case C_COLOR_CHANGE_TO_STICK:
case C_COLOR_CHANGE_FROM_STICK:
default:
break;
}
self->isFinished = true;
}
}
/* Sets color_change component. */
void
c_color_change_set(struct CColorChange* self, vec4 baseColor, vec4 color, s32 timerMax, enum CColorChangeType type)
{
glm_vec4_copy(baseColor, self->baseColor);
glm_vec4_copy(color, self->color);
self->timerMax = timerMax;
self->type = type;
self->timer = self->timerMax;
self->isFinished = false;
}
/* Registers color_change component. */
void
c_color_change_register(void)
{
ecs_register
(
ECS_C_COLOR_CHANGE,
sizeof(struct CColorChange),
C_COLOR_CHANGE_LIMIT,
(ECSFunction)add,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

View File

@ -0,0 +1,34 @@
/*
* DESCRIPTION:
* c_color_change.c header.
*/
#pragma once
#include "c_sprite.h"
#include "c_text.h"
#define C_COLOR_CHANGE_LIMIT 0xFF
#define C_COLOR_CHANGE_COUNT C_COLOR_CHANGE_STICK + 1
enum CColorChangeType
{
C_COLOR_CHANGE_TO,
C_COLOR_CHANGE_FROM,
C_COLOR_CHANGE_TO_STICK,
C_COLOR_CHANGE_FROM_STICK
};
struct CColorChange
{
u32 id;
vec4 baseColor;
vec4 color;
s32 timer;
s32 timerMax;
bool isFinished;
enum CColorChangeType type;
};
void c_color_change_set(struct CColorChange* self, vec4 baseColor, vec4 color, s32 timerMax, enum CColorChangeType type);
void c_color_change_register(void);

View File

@ -0,0 +1,130 @@
/*
* DESCRIPTION:
* Color collide delete component.
* For when one of the player's colored orbs hits an enemy.
*/
#include "c_color_collide_delete.h"
static void delete_effect(struct CColorCollideDelete* self, u32 id);
static void delete_check(struct CColorCollideDelete* self, u32 id);
static void update_f(struct CColorCollideDelete* self);
/* Visual effect of color collide delete. */
static void
delete_effect(struct CColorCollideDelete* self, u32 id)
{
struct CColor* color;
struct CSprite* sprite;
struct CColorChange* colorChange;
struct CScale* scale;
struct CPhysics* collidePhysics;
struct CParticleSpawn* particleSpawn;
u32 particleID;
vec3 position;
sprite = ecs_get(self->id, ECS_C_SPRITE);
colorChange = ecs_get(self->id, ECS_C_COLOR_CHANGE);
color = ecs_get(self->id, ECS_C_COLOR);
scale = ecs_get(self->id, ECS_C_SCALE);
collidePhysics = ecs_get(id, ECS_C_PHYSICS);
particleSpawn = ecs_get(id, ECS_C_PARTICLE_SPAWN);
if (!sprite || !colorChange || !scale || !color || !collidePhysics || !particleSpawn)
return;
c_color_change_set
(
colorChange,
C_COLOR_VALUES[color->type],
COLOR_OPAQUE,
C_COLOR_COLLIDE_DELETE_COLOR_CHANGE_TIMER_MAX,
C_COLOR_CHANGE_FROM
);
c_scale_set
(
scale,
C_COLOR_COLLIDE_DELETE_SCALE_BASE_VALUE,
C_COLOR_COLLIDE_DELETE_SCALE_VALUE,
C_COLOR_COLLIDE_DELETE_SCALE_TIMER_MAX,
C_COLOR_COLLIDE_DELETE_SCALE_TYPE
);
glm_vec3_copy(collidePhysics->position, position);
c_particle_spawn(particleSpawn, position);
sound_play(&game.sounds[SOUND_COLLIDE], -1);
}
/*
* Checks if the color of the collision is the same as this.
* If so, removes it.
*/
static void
delete_check(struct CColorCollideDelete* self, u32 id)
{
struct CColor* color;
struct CColor* collideColor;
color = ecs_get(self->id, ECS_C_COLOR);
collideColor = ecs_get(id, ECS_C_COLOR);
if (!color || !collideColor)
return;
if (collideColor->type == color->type)
{
delete_effect(self, id);
self->isCollided = true;
self->collideID = id;
entity_delete(id);
}
}
/* Draws a color collide delete component. */
static void
update_f(struct CColorCollideDelete* self)
{
struct CCircleCollide* circleCollide;
if (self->isDisabled)
return;
circleCollide = ecs_get(self->id, ECS_C_CIRCLE_COLLIDE);
self->isCollided = false;
if (!circleCollide)
return;
if (circleCollide->collisions.count == 0)
return;
for (s32 i = 0; i < (s32)circleCollide->collisions.count; i++)
{
u32* id;
id = (u32*)vector_get(&circleCollide->collisions, i);
delete_check(self, *id);
}
}
/* Registers color collide delete component. */
void
c_color_collide_delete_register(void)
{
ecs_register
(
ECS_C_COLOR_COLLIDE_DELETE,
sizeof(struct CColorCollideDelete),
C_COLOR_COLLIDE_DELETE_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

View File

@ -0,0 +1,28 @@
/*
* DESCRIPTION:
* c_color_collide_delete.c header.
*/
#pragma once
#include "c_circle_collide.h"
#include "c_color.h"
#include "c_particle_spawn.h"
#define C_COLOR_COLLIDE_DELETE_LIMIT 0xFF
#define C_COLOR_COLLIDE_DELETE_COLOR_CHANGE_TIMER_MAX 30
#define C_COLOR_COLLIDE_DELETE_SCALE_TIMER_MAX 30
#define C_COLOR_COLLIDE_DELETE_SCALE_VALUE -1.0f
#define C_COLOR_COLLIDE_DELETE_SCALE_BASE_VALUE 1.0f
#define C_COLOR_COLLIDE_DELETE_SCALE_TYPE C_SCALE_FROM
struct CColorCollideDelete
{
u32 id;
bool isDisabled;
bool isCollided;
u32 collideID;
};
void c_color_collide_delete_register(void);

View File

@ -0,0 +1,53 @@
/*
* DESCRIPTION:
* Contact damage component.
*/
#include "c_contact_damage.h"
static void update_f(struct CContactDamage* self);
/* Draws a contact damage component. */
static void
update_f(struct CContactDamage* self)
{
struct CCircleCollide* circleCollide;
circleCollide = ecs_get(self->id, ECS_C_CIRCLE_COLLIDE);
if (!circleCollide)
return;
for (s32 i = 0; i < (s32)circleCollide->collisions.count; i++)
{
struct CDamage* damage;
u32* id;
id = (u32*)vector_get(&circleCollide->collisions, i);
damage = ecs_get(*id, ECS_C_DAMAGE);
if (!damage || damage->isDisabled)
continue;
damage->isDamaged = true;
break;
}
}
/* Registers contact damage component. */
void
c_contact_damage_register(void)
{
ecs_register
(
ECS_C_CONTACT_DAMAGE,
sizeof(struct CContactDamage),
C_CONTACT_DAMAGE_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

View File

@ -0,0 +1,18 @@
/*
* DESCRIPTION:
* c_contact_damage.c header.
*/
#pragma once
#include "c_circle_collide.h"
#include "c_damage.h"
#define C_CONTACT_DAMAGE_LIMIT 0xFF
struct CContactDamage
{
u32 id;
};
void c_contact_damage_register(void);

65
src/game/ecs/c_control.c Normal file
View File

@ -0,0 +1,65 @@
/*
* DESCRIPTION:
* Physics component.
*/
#include "c_control.h"
static void update_f(struct CControl* self);
/* Draws a control component. */
static void
update_f(struct CControl* self)
{
struct CPhysics* physics;
vec2 glMouse;
vec2 glPosition;
f32 distance;
f32 angle;
f32 travel;
physics = ecs_get(self->id, ECS_C_PHYSICS);
if (!physics || self->isDisabled)
return;
window_coords_to_gl(&game.window, game.mouse.position, glMouse);
window_coords_to_gl(&game.window, physics->position, glPosition);
distance = DISTANCE_2D(glPosition[0], glMouse[0], glPosition[1], glMouse[1]);
if (distance < self->moveMinimum)
return;
travel = distance / self->speed;
angle = ATAN(glPosition[0], glMouse[0], glPosition[1], glMouse[1]);
physics->velocity[0] += cos(angle) * travel;
physics->velocity[1] += sin(angle) * travel;
}
/* Sets control component values. */
void
c_control_set(struct CControl* self, f32 speed, f32 moveMinimum)
{
self->speed = speed;
self->moveMinimum = moveMinimum;
}
/* Registers control component. */
void
c_control_register(void)
{
ecs_register
(
ECS_C_CONTROL,
sizeof(struct CControl),
C_CONTROL_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

21
src/game/ecs/c_control.h Normal file
View File

@ -0,0 +1,21 @@
/*
* DESCRIPTION:
* c_control.c header.
*/
#pragma once
#include "c_physics.h"
#define C_CONTROL_LIMIT 0xFF
struct CControl
{
u32 id;
bool isDisabled;
f32 speed;
f32 moveMinimum;
};
void c_control_set(struct CControl* self, f32 speed, f32 moveMinimum);
void c_control_register(void);

71
src/game/ecs/c_damage.c Normal file
View File

@ -0,0 +1,71 @@
/*
* DESCRIPTION:
* Damage component.
*/
#include "c_damage.h"
static void update_f(struct CDamage* self);
/* Updates a damage component. */
static void
update_f(struct CDamage* self)
{
struct CHealth* health;
struct CFlash* flash;
struct CStun* stun;
health = ecs_get(self->id, ECS_C_HEALTH);
self->isDamageUpdate = false;
if (!health)
return;
if (self->timer > 0)
{
self->timer--;
self->isDamaged = false;
return;
}
if (!self->isDamaged || health->isDead)
return;
self->timer = C_DAMAGE_TIMER;
flash = ecs_get(self->id, ECS_C_FLASH);
stun = ecs_get(self->id, ECS_C_STUN);
if (!flash || !stun)
return;
self->isDamageUpdate = true;
c_flash_set(flash, game.renderer.clearColor, C_DAMAGE_FLASH_COLOR, C_DAMAGE_TIMER, C_FLASH_STROBE);
c_stun_set(stun, C_DAMAGE_TIMER);
health->current--;
self->isDamaged = false;
sound_play(&game.sounds[SOUND_HURT], -1);
}
/* Registers damage component. */
void
c_damage_register(void)
{
ecs_register
(
ECS_C_DAMAGE,
sizeof(struct CDamage),
C_DAMAGE_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

26
src/game/ecs/c_damage.h Normal file
View File

@ -0,0 +1,26 @@
/*
* DESCRIPTION:
* c_damage.c header.
*/
#pragma once
#include "c_health.h"
#include "c_flash.h"
#include "c_stun.h"
#define C_DAMAGE_LIMIT 0xFF
#define C_DAMAGE_TIMER 18
struct CDamage
{
u32 id;
u32 timer;
bool isDisabled;
bool isDamaged;
bool isDamageUpdate;
};
static const vec4 C_DAMAGE_FLASH_COLOR = {1.0f, 0.0f, 0.0f, 1.0f};
void c_damage_register(void);

81
src/game/ecs/c_flash.c Normal file
View File

@ -0,0 +1,81 @@
/*
* DESCRIPTION:
* Flash component.
*/
#include "c_flash.h"
static void update_f(struct CFlash* self);
/* Updates flash component. */
static void
update_f(struct CFlash* self)
{
vec4 color;
f32 progress;
if (self->isFinished)
return;
progress = (f32)self->timer / self->timerMax;
glm_vec4_copy(self->color, color);
switch (self->type)
{
case C_FLASH_VANISH:
glm_vec4_scale(color, progress, color);
break;
case C_FLASH_APPEAR:
glm_vec4_scale(color, (1.0f - progress), color);
break;
case C_FLASH_STROBE:
glm_vec4_scale(color, sin((M_PI * 2) * (progress * 2.0f)), color);
break;
case C_FLASH_CONSTANT:
glm_vec4_copy(self->color, color);
break;
default:
break;
}
renderer_clear_color_set(&game.renderer, color);
if (self->timer <= 0)
{
renderer_clear_color_set(&game.renderer, self->baseColor);
self->timer = 0;
self->isFinished = true;
}
else
self->timer--;
}
/* Sets flash component info. */
void
c_flash_set(struct CFlash* self, vec4 baseColor, vec4 color, s32 timerMax, enum CFlashType type)
{
self->timerMax = timerMax;
self->type = type;
glm_vec4_copy(baseColor, self->baseColor);
glm_vec4_copy(color, self->color);
self->timer = self->timerMax;
self->isFinished = false;
}
/* Registers flash component. */
void
c_flash_register(void)
{
ecs_register
(
ECS_C_FLASH,
sizeof(struct CFlash),
C_FLASH_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

33
src/game/ecs/c_flash.h Normal file
View File

@ -0,0 +1,33 @@
/*
* DESCRIPTION:
* c_flash.c header.
*/
#pragma once
#include "entity.h"
#define C_FLASH_LIMIT 0xFF
#define C_FLASH_COUNT C_FLASH_STROBE + 1
enum CFlashType
{
C_FLASH_VANISH,
C_FLASH_APPEAR,
C_FLASH_STROBE,
C_FLASH_CONSTANT
};
struct CFlash
{
u32 id;
bool isFinished;
enum CFlashType type;
s32 timer;
s32 timerMax;
vec4 baseColor;
vec4 color;
};
void c_flash_set(struct CFlash* self, vec4 baseColor, vec4 color, s32 timerMax, enum CFlashType type);
void c_flash_register(void);

View File

@ -0,0 +1,107 @@
/*
* DESCRIPTION:
* Game object component.
*/
#include "c_game_object.h"
static void update_f(struct CGameObject* self);
/* Draws a game object component. */
static void
update_f(struct CGameObject* self)
{
struct CPhysics* physics;
struct CSprite* sprite;
physics = ecs_get(self->id, ECS_C_PHYSICS);
sprite = ecs_get(self->id, ECS_C_SPRITE);
if (!physics || !sprite)
return;
glm_vec3_copy(physics->position, sprite->position);
}
/* Sets game object component to specified values. */
void
c_game_object_set
(
struct CGameObject* self,
struct Texture texture,
enum ShaderType shader,
enum OriginType origin,
vec2 size,
vec3 position,
vec4 color,
f32 friction,
f32 velocityMax,
f32 radius
)
{
struct CPhysics* physics;
struct CSprite* sprite;
struct CCircle* circle;
physics = ecs_add(self->id, ECS_C_PHYSICS);
sprite = ecs_add(self->id, ECS_C_SPRITE);
circle = ecs_add(self->id, ECS_C_CIRCLE);
ecs_add(self->id, ECS_C_CIRCLE_COLLIDE);
c_sprite_set(sprite, texture, shader, origin, size, color, position);
c_physics_set(physics, position, friction, velocityMax);
c_circle_set(circle, radius);
}
/* Sets game object component to specified values, plus additional texture atlas info. */
void
c_game_object_atlas_set
(
struct CGameObject* self,
struct Texture texture,
enum ShaderType shader,
enum OriginType origin,
s32 frameW,
s32 frameH,
s32 rows,
s32 cols,
vec2 size,
vec3 position,
vec4 color,
f32 friction,
f32 velocityMax,
f32 radius
)
{
struct CPhysics* physics;
struct CSprite* sprite;
struct CCircle* circle;
physics = ecs_add(self->id, ECS_C_PHYSICS);
sprite = ecs_add(self->id, ECS_C_SPRITE);
circle = ecs_add(self->id, ECS_C_CIRCLE);
ecs_add(self->id, ECS_C_CIRCLE_COLLIDE);
c_sprite_atlas_set(sprite, texture, shader, origin, frameW, frameH, rows, cols, size, color, position);
c_physics_set(physics, position, friction, velocityMax);
c_circle_set(circle, radius);
}
/* Registers game_object component. */
void
c_game_object_register(void)
{
ecs_register
(
ECS_C_GAME_OBJECT,
sizeof(struct CGameObject),
C_GAME_OBJECT_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

View File

@ -0,0 +1,51 @@
/*
* DESCRIPTION:
* c_game_object.c header.
*/
#pragma once
#include "c_circle.h"
#include "c_physics.h"
#include "c_sprite.h"
#define C_GAME_OBJECT_LIMIT 0xFF
struct CGameObject
{
u32 id;
};
void c_game_object_register(void);
void c_game_object_set
(
struct CGameObject* self,
struct Texture texture,
enum ShaderType shader,
enum OriginType origin,
vec2 size,
vec3 position,
vec4 color,
f32 friction,
f32 velocityMax,
f32 radius
);
void c_game_object_atlas_set
(
struct CGameObject* self,
struct Texture texture,
enum ShaderType shader,
enum OriginType origin,
s32 frameW,
s32 frameH,
s32 rows,
s32 cols,
vec2 size,
vec3 position,
vec4 color,
f32 friction,
f32 velocityMax,
f32 radius
);

47
src/game/ecs/c_health.c Normal file
View File

@ -0,0 +1,47 @@
/*
* DESCRIPTION:
* Health component.
*/
#include "c_health.h"
static void update_f(struct CHealth* self);
/* Draws a health component. */
static void
update_f(struct CHealth* self)
{
if (self->current <= 0)
{
self->current = 0;
self->isDead = true;
}
else
self->isDead = false;
}
/* Sets health component. */
void
c_health_set(struct CHealth* self, s32 max)
{
self->max = max;
self->current = self->max;
self->isDead = false;
}
/* Registers health component. */
void
c_health_register(void)
{
ecs_register
(
ECS_C_HEALTH,
sizeof(struct CHealth),
C_HEALTH_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

21
src/game/ecs/c_health.h Normal file
View File

@ -0,0 +1,21 @@
/*
* DESCRIPTION:
* c_health.c header.
*/
#pragma once
#include "entity.h"
#define C_HEALTH_LIMIT 0xFF
struct CHealth
{
u32 id;
s32 current;
s32 max;
bool isDead;
};
void c_health_set(struct CHealth* self, s32 max);
void c_health_register(void);

116
src/game/ecs/c_move.c Normal file
View File

@ -0,0 +1,116 @@
/*
* DESCRIPTION:
* Move component.
*/
#include "c_move.h"
static void add(struct CMove* self);
static void update_f(struct CMove* self);
static void
add(struct CMove* self)
{
self->isFinished = true;
}
/* Updates an move component. */
static void
update_f(struct CMove* self)
{
struct CSprite* sprite;
struct CText* text;
f32 progress;
f32 distance;
vec3* position;
vec3 difference;
vec3 step;
vec3 current;
sprite = ecs_get(self->id, ECS_C_SPRITE);
text = ecs_get(self->id, ECS_C_TEXT);
if (self->isFinished)
return;
if (sprite)
position = &sprite->position;
else if (text)
position = &text->position;
else
return;
progress = (f32)self->timer / self->timerMax;
switch (self->type)
{
case C_MOVE_TO:
case C_MOVE_TO_STICK:
glm_vec3_copy(self->start, current);
glm_vec3_sub(current, self->end, difference);
glm_vec3_scale(difference, (1.0f - progress), step);
glm_vec3_sub(current, step, current);
glm_vec3_copy(current, *position);
break;
case C_MOVE_FROM:
case C_MOVE_FROM_STICK:
glm_vec3_copy(self->end, current);
glm_vec3_sub(current, self->start, difference);
glm_vec3_scale(difference, (1.0f - progress), step);
glm_vec3_sub(current, step, current);
glm_vec3_copy(current, *position);
break;
default:
break;
}
self->timer--;
if (self->timer <= 0)
{
switch (self->type)
{
case C_MOVE_TO:
case C_MOVE_FROM:
glm_vec3_copy(self->start, *position);
break;
case C_MOVE_TO_STICK:
case C_MOVE_FROM_STICK:
default:
break;
}
self->isFinished = true;
}
}
/* Sets move component. */
void
c_move_set(struct CMove* self, vec3 start, vec3 end, s32 timerMax, enum CMoveType type)
{
glm_vec3_copy(start, self->start);
glm_vec3_copy(end, self->end);
self->timerMax = timerMax;
self->type = type;
self->timer = self->timerMax;
self->isFinished = false;
}
/* Registers move component. */
void
c_move_register(void)
{
ecs_register
(
ECS_C_MOVE,
sizeof(struct CMove),
C_MOVE_LIMIT,
(ECSFunction)add,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

34
src/game/ecs/c_move.h Normal file
View File

@ -0,0 +1,34 @@
/*
* DESCRIPTION:
* c_move.c header.
*/
#pragma once
#include "c_sprite.h"
#include "c_text.h"
#define C_MOVE_LIMIT 0xFF
#define C_MOVE_COUNT C_MOVE_FROM_STICK + 1
enum CMoveType
{
C_MOVE_TO,
C_MOVE_FROM,
C_MOVE_TO_STICK,
C_MOVE_FROM_STICK,
};
struct CMove
{
u32 id;
vec3 start;
vec3 end;
s32 timer;
s32 timerMax;
bool isFinished;
enum CMoveType type;
};
void c_move_set(struct CMove* self, vec3 start, vec3 end, s32 timerMax, enum CMoveType type);
void c_move_register(void);

125
src/game/ecs/c_orbit.c Normal file
View File

@ -0,0 +1,125 @@
/*
* DESCRIPTION:
* Orbit component; for the follower orbs of the player.
*/
#include "c_orbit.h"
static void object_position_set(struct COrbit* self, u32 id, s32 index);
static void add(struct COrbit* self);
static void delete(struct COrbit* self);
static void update_f(struct COrbit* self);
/* Sets the position of a object in orbit. */
static void
object_position_set(struct COrbit* self, u32 id, s32 index)
{
struct CPhysics* physics;
struct CRotation* rotation;
struct CPhysics* objectPhysics;
f32 offset;
vec3 position;
physics = ecs_get(self->id, ECS_C_PHYSICS);
rotation = ecs_get(self->id, ECS_C_ROTATION);
objectPhysics = ecs_get(id, ECS_C_PHYSICS);
if (!physics || !rotation || !objectPhysics)
return;
offset = (f32)(RADIANS_MAX / self->objects.count) * index;
glm_vec3_copy(physics->position, position);
position[0] -= physics->velocity[0];
position[1] -= physics->velocity[1];
objectPhysics->position[0] = position[0] + (-cos(rotation->angle + offset)) * self->offset;
objectPhysics->position[1] = position[1] + (sin(rotation->angle + offset)) * self->offset;
}
/* Adds orbit component. */
static void
add(struct COrbit* self)
{
vector_init(&self->objects, sizeof(u32), C_ORBIT_GAME_OBJECT_LIMIT);
}
/* Deletes orbit component. */
static void
delete(struct COrbit* self)
{
for (s32 i = 0; i < (s32)self->objects.count; i++)
{
u32* id;
id = (u32*)vector_get(&self->objects, i);
entity_delete(*id);
}
vector_free(&self->objects);
}
/* Draws a orbit component. */
static void
update_f(struct COrbit* self)
{
if (self->objects.count == 0)
return;
for (s32 i = 0; i < (s32)self->objects.count; i++)
{
u32* id;
id = (u32*)vector_get(&self->objects, i);
object_position_set(self, *id, i);
}
}
/* Given a GameObject id, adds it to the orbit. */
void
c_orbit_object_add(struct COrbit* self, u32 id)
{
vector_push(&self->objects, &id);
}
/* Given a GameObjct id, removes it from orbit. */
void
c_orbit_object_delete(struct COrbit* self, u32 id)
{
vector_remove_from_data(&self->objects, &id);
}
/* Removes all objects from COrbit. */
void
c_orbit_object_clear(struct COrbit* self, u32 id)
{
vector_clear(&self->objects);
}
/* Sets orbit component. */
void
c_orbit_set(struct COrbit* self, f32 offset)
{
self->offset = offset;
}
/* Registers orbit component. */
void
c_orbit_register(void)
{
ecs_register
(
ECS_C_ORBIT,
sizeof(struct COrbit),
C_ORBIT_LIMIT,
(ECSFunction)add,
(ECSFunction)delete,
(ECSFunction)update_f,
NULL,
NULL
);
}

25
src/game/ecs/c_orbit.h Normal file
View File

@ -0,0 +1,25 @@
/*
* DESCRIPTION:
* c_orbit.c header.
*/
#pragma once
#include "c_game_object.h"
#include "c_rotation.h"
#define C_ORBIT_LIMIT 0xFF
#define C_ORBIT_GAME_OBJECT_LIMIT 0xFF
struct COrbit
{
u32 id;
struct Vector objects; /* u32; GameObject ID */
f32 offset;
};
void c_orbit_set(struct COrbit* self, f32 offset);
void c_orbit_object_add(struct COrbit* self, u32 id);
void c_orbit_object_delete(struct COrbit* self, u32 id);
void c_orbit_object_clear(struct COrbit* self, u32 id);
void c_orbit_register(void);

View File

@ -0,0 +1,71 @@
/*
* DESCRIPTION:
* ParticleSpawn component.
*/
#include "c_particle_spawn.h"
static f32 spin_speed_get(void);
static f32
spin_speed_get(void)
{
return (RANDOM * (PARTICLE_SPAWN_SPIN_SPEED_MAX - PARTICLE_SPAWN_SPIN_SPEED_MIN) + PARTICLE_SPAWN_SPIN_SPEED_MIN);
}
/* Spawns a particle at a given location. */
void
c_particle_spawn(struct CParticleSpawn* self, vec3 position)
{
u32 lilParticleID;
u32 bigParticleID;
f32 lilParticleSpinSpeed;
f32 bigParticleSpinSpeed;
lilParticleID = entity_add();
bigParticleID = entity_add();
lilParticleSpinSpeed = spin_speed_get();
bigParticleSpinSpeed = spin_speed_get();
particle_init
(
lilParticleID,
position,
PARTICLE_SPAWN_LIL_PARTICLE_BASE_COLOR,
COLOR_TRANSPARENT,
PARTICLE_SPAWN_LIL_PARTICLE_SIZE,
PARTICLE_SPAWN_SCALE,
lilParticleSpinSpeed,
PARTICLE_SPAWN_TIMER
);
particle_init
(
bigParticleID,
position,
PARTICLE_SPAWN_BIG_PARTICLE_BASE_COLOR,
COLOR_TRANSPARENT,
PARTICLE_SPAWN_BIG_PARTICLE_SIZE,
PARTICLE_SPAWN_SCALE,
bigParticleSpinSpeed,
PARTICLE_SPAWN_TIMER
);
}
/* Registers particle_spawn component. */
void
c_particle_spawn_register(void)
{
ecs_register
(
ECS_C_PARTICLE_SPAWN,
sizeof(struct CParticleSpawn),
C_PARTICLE_SPAWN_LIMIT,
NULL,
NULL,
NULL,
NULL,
NULL
);
}

View File

@ -0,0 +1,28 @@
/*
* DESCRIPTION:
* c_particle_spawn.c header.
*/
#pragma once
#include "e_particle.h"
#define C_PARTICLE_SPAWN_LIMIT 0xFF
#define PARTICLE_SPAWN_SCALE 2.0f
#define PARTICLE_SPAWN_SPIN_SPEED_MIN -0.01f
#define PARTICLE_SPAWN_SPIN_SPEED_MAX 0.01f
#define PARTICLE_SPAWN_TIMER 20
static const vec4 PARTICLE_SPAWN_BIG_PARTICLE_BASE_COLOR = {1.0f, 1.0f, 1.0f, 0.5f};
static const vec4 PARTICLE_SPAWN_LIL_PARTICLE_BASE_COLOR = {1.0f, 1.0f, 1.0f, 1.0f};
static const vec2 PARTICLE_SPAWN_BIG_PARTICLE_SIZE = {30.0f, 30.0f};
static const vec2 PARTICLE_SPAWN_LIL_PARTICLE_SIZE = {15.0f, 15.0f};
struct CParticleSpawn
{
u32 id;
};
void c_particle_spawn(struct CParticleSpawn* self, vec3 position);
void c_particle_spawn_register(void);

47
src/game/ecs/c_physics.c Normal file
View File

@ -0,0 +1,47 @@
/*
* DESCRIPTION:
* Physics component.
*/
#include "c_physics.h"
static void update_f(struct CPhysics* self);
/* Draws a physics component. */
static void
update_f(struct CPhysics* self)
{
glm_vec3_add(self->position, self->velocity, self->position);
glm_vec3_scale(self->velocity, self->friction, self->velocity);
self->velocity[0] = CLAMP(self->velocity[0], -self->velocityMax, self->velocityMax);
self->velocity[1] = CLAMP(self->velocity[1], -self->velocityMax, self->velocityMax);
self->velocity[2] = CLAMP(self->velocity[2], -self->velocityMax, self->velocityMax);
}
/* Sets physics component. */
void
c_physics_set(struct CPhysics* self, vec3 position, f32 friction, f32 velocityMax)
{
glm_vec3_copy(position, self->position);
self->friction = friction;
self->velocityMax = velocityMax;
}
/* Registers physics component. */
void
c_physics_register(void)
{
ecs_register
(
ECS_C_PHYSICS,
sizeof(struct CPhysics),
C_PHYSICS_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

22
src/game/ecs/c_physics.h Normal file
View File

@ -0,0 +1,22 @@
/*
* DESCRIPTION:
* c_physics.c header.
*/
#pragma once
#include "entity.h"
#define C_PHYSICS_LIMIT 0xFF
struct CPhysics
{
u32 id;
f32 velocityMax;
f32 friction;
vec3 position;
vec3 velocity;
};
void c_physics_set(struct CPhysics* self, vec3 position, f32 friction, f32 velocityMax);
void c_physics_register(void);

View File

@ -0,0 +1,42 @@
/*
* DESCRIPTION:
* Player atlas health component.
* Changes the player's atlas frame in conjunction with its health.
*/
#include "c_player_atlas_health.h"
static void update_f(struct CPlayerAtlasHealth* self);
/* Draws a player_atlas_health component. */
static void
update_f(struct CPlayerAtlasHealth* self)
{
struct CSprite* sprite;
struct CHealth* health;
sprite = ecs_get(self->id, ECS_C_SPRITE);
health = ecs_get(self->id, ECS_C_HEALTH);
if (!sprite || !health)
return;
sprite->atlas.index = health->max - health->current;
}
/* Registers player_atlas_health component. */
void
c_player_atlas_health_register(void)
{
ecs_register
(
ECS_C_PLAYER_ATLAS_HEALTH,
sizeof(struct CPlayerAtlasHealth),
C_PLAYER_ATLAS_HEALTH_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

View File

@ -0,0 +1,18 @@
/*
* DESCRIPTION:
* c_player_atlas_health.c header.
*/
#pragma once
#include "c_health.h"
#include "c_sprite.h"
#define C_PLAYER_ATLAS_HEALTH_LIMIT 0xFF
struct CPlayerAtlasHealth
{
u32 id;
};
void c_player_atlas_health_register(void);

View File

@ -0,0 +1,188 @@
/*
* DESCRIPTION:
* Player death component.
*/
#include "c_player_death.h"
static void state_set(struct CPlayerDeath* self, enum CPlayerDeathState state);
static void add(struct CPlayerDeath* self);
static void begin(struct CPlayerDeath* self);
static void update_f(struct CPlayerDeath* self);
/* Sets death state. */
static void
state_set(struct CPlayerDeath* self, enum CPlayerDeathState state)
{
struct CScale* scale;
struct CColorChange* colorChange;
scale = ecs_get(self->id, ECS_C_SCALE);
colorChange = ecs_get(self->id, ECS_C_COLOR_CHANGE);
self->state = state;
switch (self->state)
{
case C_PLAYER_DEATH_PULSATE:
self->timer = C_PLAYER_DEATH_PULSATE_TIME;
break;
case C_PLAYER_DEATH_GROW:
c_scale_set
(
scale,
C_PLAYER_DEATH_GROW_SCALE_BASE_VALUE,
C_PLAYER_DEATH_GROW_SCALE_VALUE,
C_PLAYER_DEATH_GROW_TIME,
C_SCALE_TO_STICK
);
c_color_change_set
(
colorChange,
C_PLAYER_DEATH_GROW_COLOR_CHANGE_BASE_COLOR,
C_PLAYER_DEATH_GROW_COLOR_CHANGE_COLOR,
C_PLAYER_DEATH_GROW_TIME,
C_COLOR_CHANGE_TO_STICK
);
self->timer = C_PLAYER_DEATH_GROW_TIME;
break;
case C_PLAYER_DEATH_VANISH:
c_scale_set
(
scale,
C_PLAYER_DEATH_VANISH_SCALE_BASE_VALUE,
C_PLAYER_DEATH_VANISH_SCALE_VALUE,
C_PLAYER_DEATH_VANISH_TIME,
C_SCALE_TO_STICK
);
c_color_change_set
(
colorChange,
C_PLAYER_DEATH_VANISH_COLOR_CHANGE_BASE_COLOR,
C_PLAYER_DEATH_VANISH_COLOR_CHANGE_COLOR,
C_PLAYER_DEATH_VANISH_TIME,
C_COLOR_CHANGE_TO_STICK
);
self->timer = C_PLAYER_DEATH_VANISH_TIME;
break;
case C_PLAYER_DEATH_NONE:
case C_PLAYER_DEATH_END:
default:
break;
}
}
/* Begins death process. */
static void
begin(struct CPlayerDeath* self)
{
struct CRotation* rotation;
struct CControl* control;
struct COrbit* orbit;
struct CPulsate* pulsate;
control = ecs_get(self->id, ECS_C_CONTROL);
rotation = ecs_get(self->id, ECS_C_ROTATION);
orbit = ecs_get(self->id, ECS_C_ORBIT);
pulsate = ecs_get(self->id, ECS_C_PULSATE);
if (!control || !rotation || !orbit)
return;
control->isDisabled = true;
rotation->isDisabled = true;
pulsate->isDisabled = true;
for (s32 i = 0; i < (s32)orbit->objects.count; i++)
{
struct CTimeDelete* timeDelete;
struct CScale* scale;
struct CColorChange* colorChange;
struct CColorCollideDelete* colorCollideDelete;
struct CSprite* sprite;
u32* id;
id = (u32*)vector_get(&orbit->objects, i);
timeDelete = ecs_get(*id, ECS_C_TIME_DELETE);
scale = ecs_get(*id, ECS_C_SCALE);
colorChange = ecs_get(*id, ECS_C_COLOR_CHANGE);
sprite = ecs_get(*id, ECS_C_SPRITE);
colorCollideDelete = ecs_get(*id, ECS_C_COLOR_COLLIDE_DELETE);
if (!timeDelete || !scale || !colorChange || !sprite || !colorCollideDelete)
continue;
colorCollideDelete->isDisabled = true;
c_scale_set
(
scale,
C_PLAYER_DEATH_FOLLOWER_BASE_SCALE,
C_PLAYER_DEATH_FOLLOWER_SCALE,
C_PLAYER_DEATH_FOLLOWER_TIMER,
C_SCALE_TO
);
c_color_change_set
(
colorChange,
sprite->color,
C_PLAYER_DEATH_FOLLOWER_COLOR,
C_PLAYER_DEATH_FOLLOWER_TIMER,
C_COLOR_CHANGE_TO
);
c_time_delete_set(timeDelete, C_PLAYER_DEATH_FOLLOWER_TIMER);
}
state_set(self, C_PLAYER_DEATH_PULSATE);
}
/* Adds a CPlayerDeath component. */
static void
add(struct CPlayerDeath* self)
{
state_set(self, C_PLAYER_DEATH_NONE);
}
/* Draws a player_death component. */
static void
update_f(struct CPlayerDeath* self)
{
struct CHealth* health;
health = ecs_get(self->id, ECS_C_HEALTH);
if (!health || !health->isDead || self->state == C_PLAYER_DEATH_END)
return;
if (self->state == C_PLAYER_DEATH_NONE)
begin(self);
self->timer--;
if (self->timer <= 0)
state_set(self, self->state + 1);
}
/* Registers player_death component. */
void
c_player_death_register(void)
{
ecs_register
(
ECS_C_PLAYER_DEATH,
sizeof(struct CPlayerDeath),
C_PLAYER_DEATH_LIMIT,
(ECSFunction)add,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

View File

@ -0,0 +1,52 @@
/*
* DESCRIPTION:
* c_player_death.c header.
*/
#pragma once
#include "c_color_change.h"
#include "c_color_collide_delete.h"
#include "c_control.h"
#include "c_health.h"
#include "c_orbit.h"
#include "c_pulsate.h"
#include "c_scale.h"
#include "c_time_delete.h"
#define C_PLAYER_DEATH_LIMIT 0xFF
#define C_PLAYER_DEATH_PULSATE_TIME 20
#define C_PLAYER_DEATH_GROW_TIME 80
#define C_PLAYER_DEATH_VANISH_TIME 80
#define C_PLAYER_DEATH_GROW_SCALE_BASE_VALUE 1.0f
#define C_PLAYER_DEATH_GROW_SCALE_VALUE 3.0f
#define C_PLAYER_DEATH_VANISH_SCALE_BASE_VALUE 3.0f
#define C_PLAYER_DEATH_VANISH_SCALE_VALUE -3.0f
#define C_PLAYER_DEATH_FOLLOWER_SCALE 2.0f
#define C_PLAYER_DEATH_FOLLOWER_BASE_SCALE 1.0f
#define C_PLAYER_DEATH_FOLLOWER_TIMER 30
static const vec4 C_PLAYER_DEATH_FOLLOWER_COLOR = {1.0f, 1.0f, 1.0f, 0.0f};
static const vec4 C_PLAYER_DEATH_GROW_COLOR_CHANGE_BASE_COLOR = {1.0f, 1.0f, 1.0f, 1.0f};
static const vec4 C_PLAYER_DEATH_GROW_COLOR_CHANGE_COLOR = {1.0f, 0.0f, 0.0f, 0.5f};
static const vec4 C_PLAYER_DEATH_VANISH_COLOR_CHANGE_BASE_COLOR = {1.0f, 0.0f, 0.0f, 0.5f};
static const vec4 C_PLAYER_DEATH_VANISH_COLOR_CHANGE_COLOR = {0.0f, 0.0f, 0.0f, 0.0f};
#define C_PLAYER_DEATH_STATE_COUNT C_PLAYER_DEATH_END + 1
enum CPlayerDeathState
{
C_PLAYER_DEATH_NONE,
C_PLAYER_DEATH_PULSATE,
C_PLAYER_DEATH_GROW,
C_PLAYER_DEATH_VANISH,
C_PLAYER_DEATH_END
};
struct CPlayerDeath
{
u32 id;
enum CPlayerDeathState state;
s32 timer;
};
void c_player_death_register(void);

62
src/game/ecs/c_pulsate.c Normal file
View File

@ -0,0 +1,62 @@
/*
* DESCRIPTION:
* Pulsate component.
*/
#include "c_pulsate.h"
static void update_f(struct CPulsate* self);
/* Updates an pulsate component. */
static void
update_f(struct CPulsate* self)
{
struct CSprite* sprite;
f32 progress;
f32 scale;
sprite = ecs_get(self->id, ECS_C_SPRITE);
if (!sprite || self->isDisabled)
return;
progress = (f32)self->timer / self->timerMax;
sprite->scale = (sin(TAU * progress) * self->value) + self->baseScale;
self->timer--;
if (self->timer <= 0)
{
sprite->scale = self->baseScale;
self->timer = self->timerMax;
}
}
/* Sets pulsate component. */
void
c_pulsate_set(struct CPulsate* self, f32 baseScale, f32 value, s32 timerMax)
{
self->baseScale = baseScale;
self->timerMax = timerMax;
self->value = value;
self->timer = self->timerMax;
}
/* Registers pulsate component. */
void
c_pulsate_register(void)
{
ecs_register
(
ECS_C_PULSATE,
sizeof(struct CPulsate),
C_PULSATE_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

23
src/game/ecs/c_pulsate.h Normal file
View File

@ -0,0 +1,23 @@
/*
* DESCRIPTION:
* c_pulsate.c header.
*/
#pragma once
#include "c_sprite.h"
#define C_PULSATE_LIMIT 0xFF
struct CPulsate
{
u32 id;
f32 baseScale;
f32 value;
s32 timer;
s32 timerMax;
bool isDisabled;
};
void c_pulsate_set(struct CPulsate* self, f32 baseScale, f32 value, s32 timerMax);
void c_pulsate_register(void);

74
src/game/ecs/c_rotation.c Normal file
View File

@ -0,0 +1,74 @@
/*
* DESCRIPTION:
* Rotation component.
*/
#include "c_rotation.h"
static void update_f(struct CRotation* self);
/* Adds a rotation component. */
static void
add(struct CRotation* self)
{
self->angle = C_ROTATION_ANGLE_DEFAULT;
self->velocity = C_ROTATION_VELOCITY_DEFAULT;
}
/* Draws a rotation component. */
static void
update_f(struct CRotation* self)
{
if (self->isDisabled)
return;
if
(
keyboard_held(&game.keyboard, KEYBOARD_LEFT) ||
keyboard_held(&game.keyboard, KEYBOARD_A)
)
self->velocity += self->speed;
if
(
keyboard_held(&game.keyboard, KEYBOARD_RIGHT) ||
keyboard_held(&game.keyboard, KEYBOARD_D)
)
self->velocity -= self->speed;
self->velocity *= self->friction;
self->velocity = self->velocity > self->velocityMax ? self->velocityMax : self->velocity;
self->velocity = self->velocity < -self->velocityMax ? -self->velocityMax : self->velocity;
self->angle += self->velocity;
self->angle = self->angle > RADIANS_MAX ? RADIANS_MIN : self->angle;
self->angle = self->angle < RADIANS_MIN ? RADIANS_MAX : self->angle;
}
/* Sets rotation component values. */
void
c_rotation_set(struct CRotation* self, f32 speed, f32 velocityMax, f32 friction)
{
self->speed = speed;
self->velocityMax = velocityMax;
self->friction = friction;
}
/* Registers rotation component. */
void
c_rotation_register(void)
{
ecs_register
(
ECS_C_ROTATION,
sizeof(struct CRotation),
C_ROTATION_LIMIT,
(ECSFunction)add,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

27
src/game/ecs/c_rotation.h Normal file
View File

@ -0,0 +1,27 @@
/*
* DESCRIPTION:
* c_rotation.c header.
*/
#pragma once
#include "entity.h"
#define C_ROTATION_ANGLE_DEFAULT (PI / 2)
#define C_ROTATION_VELOCITY_DEFAULT -2.5f
#define C_ROTATION_LIMIT 0xFF
struct CRotation
{
u32 id;
bool isDisabled;
f32 velocity;
f32 friction;
f32 angle;
f32 speed;
f32 velocityMax;
};
void c_rotation_set(struct CRotation* self, f32 speed, f32 speedMax, f32 friction);
void c_rotation_register(void);

103
src/game/ecs/c_scale.c Normal file
View File

@ -0,0 +1,103 @@
/*
* DESCRIPTION:
* Scale component.
*/
#include "c_scale.h"
static void add(struct CScale* self);
static void update_f(struct CScale* self);
static void
add(struct CScale* self)
{
self->isFinished = true;
}
/* Updates an scale component. */
static void
update_f(struct CScale* self)
{
struct CSprite* sprite;
struct CText* text;
f32 progress;
f32* scale;
sprite = ecs_get(self->id, ECS_C_SPRITE);
text = ecs_get(self->id, ECS_C_TEXT);
if (self->isFinished)
return;
if (sprite)
scale = &sprite->scale;
else if (text)
scale = &text->scale;
else
return;
progress = (f32)self->timer / self->timerMax;
switch (self->type)
{
case C_SCALE_TO:
case C_SCALE_TO_STICK:
*scale = self->baseValue + (self->value * (1.0f - progress));
break;
case C_SCALE_FROM:
case C_SCALE_FROM_STICK:
*scale = self->baseValue + (self->value * progress);
break;
default:
break;
}
self->timer--;
if (self->timer <= 0)
{
switch (self->type)
{
case C_SCALE_TO:
case C_SCALE_FROM:
*scale = self->baseValue;
break;
case C_SCALE_TO_STICK:
case C_SCALE_FROM_STICK:
default:
break;
}
self->isFinished = true;
}
}
/* Sets scale component. */
void
c_scale_set(struct CScale* self, f32 baseValue, f32 value, s32 timerMax, enum CScaleType type)
{
self->value = value;
self->baseValue = baseValue;
self->timerMax = timerMax;
self->type = type;
self->timer = self->timerMax;
self->isFinished = false;
}
/* Registers scale component. */
void
c_scale_register(void)
{
ecs_register
(
ECS_C_SCALE,
sizeof(struct CScale),
C_SCALE_LIMIT,
(ECSFunction)add,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

35
src/game/ecs/c_scale.h Normal file
View File

@ -0,0 +1,35 @@
/*
* DESCRIPTION:
* c_scale.c header.
*/
#pragma once
#include "c_sprite.h"
#include "c_text.h"
#define C_SCALE_LIMIT 0xFF
#define C_SCALE_DEFAULT 1.0f
#define C_SCALE_COUNT C_SCALE_FROM_STICK + 1
enum CScaleType
{
C_SCALE_TO,
C_SCALE_FROM,
C_SCALE_TO_STICK,
C_SCALE_FROM_STICK,
};
struct CScale
{
u32 id;
f32 value;
f32 baseValue;
s32 timer;
s32 timerMax;
bool isFinished;
enum CScaleType type;
};
void c_scale_set(struct CScale* self, f32 baseValue, f32 value, s32 timerMax, enum CScaleType type);
void c_scale_register(void);

46
src/game/ecs/c_spin.c Normal file
View File

@ -0,0 +1,46 @@
/*
* DESCRIPTION:
* Spin component.
*/
#include "c_spin.h"
static void update_f(struct CSpin* self);
/* Updates an spin component. */
static void
update_f(struct CSpin* self)
{
struct CSprite* sprite;
sprite = ecs_get(self->id, ECS_C_SPRITE);
if (!sprite)
return;
sprite->rotation += self->speed;
}
/* Sets spin component. */
void
c_spin_set(struct CSpin* self, f32 speed)
{
self->speed = speed;
}
/* Registers spin component. */
void
c_spin_register(void)
{
ecs_register
(
ECS_C_SPIN,
sizeof(struct CSpin),
C_SPIN_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

19
src/game/ecs/c_spin.h Normal file
View File

@ -0,0 +1,19 @@
/*
* DESCRIPTION:
* c_spin.c header.
*/
#pragma once
#include "c_sprite.h"
#define C_SPIN_LIMIT 0xFF
struct CSpin
{
u32 id;
f32 speed;
};
void c_spin_set(struct CSpin* self, f32 speed);
void c_spin_register(void);

153
src/game/ecs/c_sprite.c Normal file
View File

@ -0,0 +1,153 @@
/*
* DESCRIPTION:
* Sprite component.
*/
#include "c_sprite.h"
static void c_sprite_size_get(struct CSprite* self, vec2 size);
static void add(struct CSprite* self);
static void draw(struct CSprite* self);
static void update_f(struct CSprite* self);
/* Obtains sprite draw size. */
static void
c_sprite_size_get(struct CSprite* self, vec2 size)
{
glm_vec2_copy(self->size, size);
glm_vec2_scale(size, self->scale, size);
}
/* Adds sprite component. */
static void
add(struct CSprite* self)
{
glm_vec4_copy(COLOR_OPAQUE, self->color);
self->scale = C_SPRITE_SCALE_DEFAULT;
}
/* Updates (fixed) sprite component. */
static void
update_f(struct CSprite* self)
{
self->rotation = self->rotation > RADIANS_MAX ? RADIANS_MIN : self->rotation;
self->rotation = self->rotation < RADIANS_MIN ? RADIANS_MAX : self->rotation;
}
/* Draws a sprite component. */
static void
draw(struct CSprite* self)
{
mat4 model;
vec2 size;
vec2 origin;
vec3 position;
vec3 modelOrigin;
c_sprite_size_get(self, size);
origin_2d_get(self->origin, size, origin);
position[0] = self->position[0] - origin[0];
position[1] = self->position[1] - origin[1];
position[2] = self->position[2];
modelOrigin[0] = origin[0];
modelOrigin[1] = origin[1];
modelOrigin[2] = 0.0f;
glm_mat4_identity(model);
glm_translate(model, position);
glm_rotate_at(model, modelOrigin, self->rotation, C_SPRITE_ROTATION_AXIS);
shader_texture_quad_draw(&self->atlas, self->shader, model, size, self->color);
}
/* Returns the sprite's containing rectangle. */
void
c_sprite_rectangle_get(struct CSprite* self, vec4 rectangle)
{
vec2 size;
vec2 origin;
c_sprite_size_get(self, size);
origin_2d_get(self->origin, size, origin);
rectangle[0] = self->position[0] - origin[0];
rectangle[1] = self->position[1] - origin[1];
rectangle[2] = rectangle[0] + self->size[0];
rectangle[3] = rectangle[1] + self->size[1];
}
/* Sets sprite component info. */
void
c_sprite_set
(
struct CSprite* self,
struct Texture texture,
enum ShaderType shader,
enum OriginType origin,
vec2 size,
vec4 color,
vec3 position
)
{
c_sprite_atlas_set
(
self,
texture,
shader,
origin,
texture.w,
texture.h,
1,
1,
size,
color,
position
);
}
/* Sets sprite component info, additionally given atlas rows/columns. */
void
c_sprite_atlas_set
(
struct CSprite* self,
struct Texture texture,
enum ShaderType shader,
enum OriginType origin,
s32 frameW,
s32 frameH,
s32 rows,
s32 cols,
vec2 size,
vec4 color,
vec3 position
)
{
self->shader = shader;
self->origin = origin;
atlas_init(&self->atlas, texture, frameW, frameH, rows, cols);
glm_vec2_copy(size, self->size);
glm_vec3_copy(position, self->position);
glm_vec4_copy(color, self->color);
}
/* Registers sprite component. */
void
c_sprite_register(void)
{
ecs_register
(
ECS_C_SPRITE,
sizeof(struct CSprite),
C_SPRITE_LIMIT,
(ECSFunction)add,
NULL,
(ECSFunction)update_f,
NULL,
(ECSFunction)draw
);
}

58
src/game/ecs/c_sprite.h Normal file
View File

@ -0,0 +1,58 @@
/*
* DESCRIPTION:
* c_sprite.c header.
*/
#pragma once
#include "../shader/shader_texture_quad.h"
#include "entity.h"
#define C_SPRITE_LIMIT 0xFF
#define C_SPRITE_SCALE_DEFAULT 1.0f
struct CSprite
{
u32 id;
struct Atlas atlas;
enum ShaderType shader;
enum OriginType origin;
vec2 size;
vec3 position;
vec4 color;
f32 scale;
f32 rotation;
};
static const vec3 C_SPRITE_ROTATION_AXIS = {0.0f, 0.0f, 1.0f};
void c_sprite_rectangle_get(struct CSprite* self, vec4 rectangle);
void c_sprite_set
(
struct CSprite* self,
struct Texture texture,
enum ShaderType shader,
enum OriginType origin,
vec2 size,
vec4 color,
vec3 position
);
void c_sprite_atlas_set
(
struct CSprite* self,
struct Texture texture,
enum ShaderType shader,
enum OriginType origin,
s32 frameW,
s32 frameH,
s32 rows,
s32 cols,
vec2 size,
vec4 color,
vec3 position
);
void c_sprite_register(void);

66
src/game/ecs/c_stun.c Normal file
View File

@ -0,0 +1,66 @@
/*
* DESCRIPTION:
* Stun component.
*/
#include "c_stun.h"
static void update_f(struct CStun* self);
/* Draws a stun component. */
static void
update_f(struct CStun* self)
{
struct CPhysics* physics;
struct CControl* control;
struct CRotation* rotation;
struct CHealth* health;
physics = ecs_get(self->id, ECS_C_PHYSICS);
control = ecs_get(self->id, ECS_C_CONTROL);
rotation = ecs_get(self->id, ECS_C_ROTATION);
health = ecs_get(self->id, ECS_C_HEALTH);
if (health->isDead || !control || !rotation || !physics || !self->isStun)
return;
control->isDisabled = true;
rotation->isDisabled = true;
glm_vec3_zero(physics->velocity);
self->timer--;
if (self->timer <= 0)
{
control->isDisabled = false;
rotation->isDisabled = false;
self->isStun = false;
}
}
/* Sets stun component. */
void
c_stun_set(struct CStun* self, s32 timerMax)
{
self->timerMax = timerMax;
self->timer = self->timerMax;
self->isStun = true;
}
/* Registers stun component. */
void
c_stun_register(void)
{
ecs_register
(
ECS_C_STUN,
sizeof(struct CStun),
C_STUN_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

24
src/game/ecs/c_stun.h Normal file
View File

@ -0,0 +1,24 @@
/*
* DESCRIPTION:
* c_stun.c header.
*/
#pragma once
#include "c_control.h"
#include "c_health.h"
#include "c_physics.h"
#include "c_rotation.h"
#define C_STUN_LIMIT 0xFF
struct CStun
{
u32 id;
s32 timer;
s32 timerMax;
bool isStun;
};
void c_stun_set(struct CStun* self, s32 timerMax);
void c_stun_register(void);

284
src/game/ecs/c_text.c Normal file
View File

@ -0,0 +1,284 @@
/*
* DESCRIPTION:
* Text component.
*/
#include "c_text.h"
static void c_text_free(struct CText* self);
static void c_text_glyph_draw(struct CText* self, struct Texture, vec3 position);
static void add(struct CText* self);
static void draw(struct CText* self);
/* Obtains the size of the glyph. */
static void
c_text_glyph_size_get(struct CText* self, struct Texture texture, vec2 size)
{
size[0] = texture.w;
size[1] = texture.h;
glm_vec2_scale(size, self->scale, size);
}
/* Frees glyph textures. */
static void
c_text_free(struct CText* self)
{
for (s32 i = 0; i < self->length; i++)
{
struct Texture* texture;
texture = &self->glyphTextures[i];
if (texture->isInit)
texture_free(texture);
}
memset(&self->glyphTextures, '\0', sizeof(self->glyphTextures));
}
/* Draws a glyph. */
static void
c_text_glyph_draw(struct CText* self, struct Texture texture, vec3 position)
{
struct Atlas atlas;
mat4 model;
vec2 size;
c_text_glyph_size_get(self, texture, size);
glm_mat4_identity(model);
glm_translate(model, position);
atlas_init(&atlas, texture, texture.w, texture.h, 1, 1);
shader_texture_quad_draw(&atlas, self->shader, model, size, self->color);
}
/* Adds text component. */
static void
add(struct CText* self)
{
glm_vec4_copy(COLOR_OPAQUE, self->color);
self->scale = C_TEXT_SCALE_DEFAULT;
}
/* Deletes text component. */
static void
delete(struct CText* self)
{
c_text_free(self);
}
/* Draws a text component. */
static void
draw(struct CText* self)
{
char glyph;
char nextGlyph;
f32 advance;
f32 lineW;
f32 offsetX;
f32 kerning;
struct GlyphMetrics glyphMetrics;
vec3 position;
vec4 rectangle;
vec2 origin;
vec2 size;
f32 lineSkip;
f32 lineBegin;
c_text_rectangle_get(self, rectangle);
size[0] = rectangle[2] - rectangle[0];
size[1] = rectangle[3] - rectangle[1];
origin_2d_get(self->origin, size, origin);
position[0] = self->position[0] - origin[0];
position[1] = self->position[1] - origin[1];
position[2] = self->position[2];
offsetX = 0.0f;
lineW = 0.0f;
lineBegin = position[0];
lineSkip = font_line_skip_get(&self->font) * self->scale;
for (s32 i = 0; i < self->length; i++)
{
glyph = self->string[i];
if
(
glyph == '\n' ||
(glyph == ' ' && (lineW > self->wrap && self->wrap != -1))
)
{
position[0] = lineBegin;
position[1] += lineSkip;
lineW = 0.0f;
if (glyph == '\n')
continue;
}
if (i < self->length)
{
nextGlyph = self->string[i + 1];
kerning = (f32)glyph_kerning_get(&self->font, glyph, nextGlyph);
}
else
kerning = 0.0;
glyph_metrics_get(&glyphMetrics, &self->font, glyph);
c_text_glyph_draw(self, self->glyphTextures[i], position);
advance = glyphMetrics.advance;
offsetX = advance + kerning;
offsetX *= self->scale;
position[0] += offsetX;
lineW += offsetX;
}
}
/* Gets a rectangle the size of all glyphs. */
void
c_text_rectangle_get(struct CText* self, vec4 rectangle)
{
char glyph;
char nextGlyph;
f32 lineW;
f32 offsetX;
f32 prevY;
struct GlyphMetrics glyphMetrics;
vec2 origin;
vec2 size;
f32 lineSkip;
f32 kerning;
f32 advance;
if (self->length <= 0 || self->length > 255)
return;
lineSkip = font_line_skip_get(&self->font);
lineSkip *= self->scale;
glyph_metrics_get(&glyphMetrics, &self->font, self->string[0]);
lineW = 0.0f;
size[0] = 0.0f;
size[1] = (f32)glyphMetrics.maxY - glyphMetrics.minY;
for (s32 i = 0; i < self->length; i++)
{
glyph = self->string[i];
if
(
glyph == '\n' ||
(glyph == ' ' && (lineW > self->wrap && self->wrap != -1))
)
{
size[1] += lineSkip;
lineW = 0.0f;
if (glyph == '\n')
continue;
}
if (i < self->length)
{
nextGlyph = self->string[i + 1];
kerning = (f32)glyph_kerning_get(&self->font, glyph, nextGlyph);
}
else
kerning = 0.0;
glyph_metrics_get(&glyphMetrics, &self->font, glyph);
advance = glyphMetrics.advance;
offsetX = advance + kerning;
offsetX *= self->scale;
lineW += offsetX;
if (lineW > size[0])
size[0] = lineW;
}
origin_2d_get(self->origin, size, origin);
rectangle[0] = self->position[0] - origin[0];
rectangle[1] = self->position[1] - origin[1];
rectangle[2] = rectangle[0] + size[0];
rectangle[3] = rectangle[1] + size[1];
}
/* Given a string and its length, generates textures for the string. */
void
c_text_string_set(struct CText* self, char* string, s32 length)
{
c_text_free(self);
if (length > C_TEXT_STRING_LIMIT)
return;
self->length = length;
memset(self->string, '\0', sizeof(char) * C_TEXT_STRING_LIMIT);
memcpy(self->string, string, sizeof(char) * self->length);
for (s32 i = 0; i < self->length; i++)
glyph_texture_init(&self->glyphTextures[i], &self->font, (char)string[i]);
}
/* Sets text component info. */
void
c_text_set
(
struct CText* self,
enum ShaderType shader,
enum OriginType origin,
struct Font font,
char* string,
s32 length,
s32 wrap,
vec4 color,
vec3 position
)
{
self->font = font;
self->shader = shader;
self->wrap = wrap;
self->origin = origin;
glm_vec3_copy(position, self->position);
glm_vec4_copy(color, self->color);
c_text_string_set(self, string, length);
}
/* Registers text component. */
void
c_text_register(void)
{
ecs_register
(
ECS_C_TEXT,
sizeof(struct CText),
C_TEXT_LIMIT,
(ECSFunction)add,
(ECSFunction)delete,
NULL,
NULL,
(ECSFunction)draw
);
}

47
src/game/ecs/c_text.h Normal file
View File

@ -0,0 +1,47 @@
/*
* DESCRIPTION:
* c_text.c header.
*/
#pragma once
#include "../shader/shader_texture_quad.h"
#include "entity.h"
#define C_TEXT_LIMIT 0xFF
#define C_TEXT_STRING_LIMIT 0xFF
#define C_TEXT_SCALE_DEFAULT 1.0f
struct CText
{
u32 id;
struct Font font;
struct Texture glyphTextures[C_TEXT_STRING_LIMIT];
char string[C_TEXT_STRING_LIMIT];
enum ShaderType shader;
enum OriginType origin;
s32 length;
s32 wrap;
vec3 position;
vec4 color;
f32 scale;
};
void c_text_rectangle_get(struct CText* self, vec4 rectangle);
void c_text_string_set(struct CText* self, char* string, s32 length);
void c_text_set
(
struct CText* self,
enum ShaderType shader,
enum OriginType origin,
struct Font font,
char* string,
s32 length,
s32 wrap,
vec4 color,
vec3 position
);
void c_text_register(void);

View File

@ -0,0 +1,55 @@
/*
* DESCRIPTION:
* Time delete component.
* Deletes an entity when the timer elapses.
*/
#include "c_time_delete.h"
static void add(struct CTimeDelete* self);
static void update_f(struct CTimeDelete* self);
/* Adds a time_delete component. */
static void
add(struct CTimeDelete* self)
{
self->isDisabled = true;
}
/* Draws a time_delete component. */
static void
update_f(struct CTimeDelete* self)
{
if (self->isDisabled)
return;
self->timer--;
if (self->timer <= 0)
entity_delete(self->id);
}
/* Sets TimeDelete component. */
void
c_time_delete_set(struct CTimeDelete* self, s32 timer)
{
self->timer = timer;
self->isDisabled = false;
}
/* Registers time_delete component. */
void
c_time_delete_register(void)
{
ecs_register
(
ECS_C_TIME_DELETE,
sizeof(struct CTimeDelete),
C_TIME_DELETE_LIMIT,
(ECSFunction)add,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

View File

@ -0,0 +1,20 @@
/*
* DESCRIPTION:
* c_time_delete.c header.
*/
#pragma once
#include "entity.h"
#define C_TIME_DELETE_LIMIT 0xFF
struct CTimeDelete
{
u32 id;
s32 timer;
bool isDisabled;
};
void c_time_delete_set(struct CTimeDelete* self, s32 timer);
void c_time_delete_register(void);

106
src/game/ecs/c_ui_button.c Normal file
View File

@ -0,0 +1,106 @@
/*
* DESCRIPTION:
* UI button component.
*/
#include "c_ui_button.h"
static void update_f(struct CUIButton* self);
/* Draws a ui_button component. */
static void
update_f(struct CUIButton* self)
{
struct CSprite* sprite;
struct CText* text;
struct CColorChange* colorChange;
vec4 rectangle;
sprite = ecs_get(self->id, ECS_C_SPRITE);
text = ecs_get(self->id, ECS_C_TEXT);
colorChange = ecs_get(self->id, ECS_C_COLOR_CHANGE);
if (self->isDisabled)
return;
if (sprite)
c_sprite_rectangle_get(sprite, rectangle);
else if (text)
c_text_rectangle_get(text, rectangle);
else
return;
if (rectangle_has_point(rectangle, game.mouse.position))
{
if (self->state != C_UI_BUTTON_HOVER)
{
c_color_change_set
(
colorChange,
self->selectColor,
self->baseColor,
1,
C_COLOR_CHANGE_TO_STICK
);
if (self->state != C_UI_BUTTON_HELD)
sound_play(&game.sounds[SOUND_HOVER], -1);
}
self->state = C_UI_BUTTON_HOVER;
if (mouse_held(&game.mouse, MOUSE_LEFT))
{
if (!self->isPressed)
{
sound_play(&game.sounds[SOUND_SELECT], -1);
self->isPressed = true;
}
self->state = C_UI_BUTTON_HELD;
}
}
else
{
if (self->state != C_UI_BUTTON_IDLE)
{
c_color_change_set
(
colorChange,
self->baseColor,
self->selectColor,
1,
C_COLOR_CHANGE_TO_STICK
);
self->isPressed = false;
}
self->state = C_UI_BUTTON_IDLE;
}
}
/* Sets ui button component. */
void
c_ui_button_set(struct CUIButton* self, vec4 baseColor, vec4 selectColor)
{
glm_vec4_copy(baseColor, self->baseColor);
glm_vec4_copy(selectColor, self->selectColor);
}
/* Registers ui_button component. */
void
c_ui_button_register(void)
{
ecs_register
(
ECS_C_UI_BUTTON,
sizeof(struct CUIButton),
C_UI_BUTTON_LIMIT,
NULL,
NULL,
(ECSFunction)update_f,
NULL,
NULL
);
}

View File

@ -0,0 +1,30 @@
/*
* DESCRIPTION:
* c_ui_button.c header.
*/
#pragma once
#include "c_color_change.h"
#define C_UI_BUTTON_LIMIT 0xFF
enum CUIButtonState
{
C_UI_BUTTON_IDLE,
C_UI_BUTTON_HOVER,
C_UI_BUTTON_HELD
};
struct CUIButton
{
u32 id;
vec4 baseColor;
vec4 selectColor;
bool isDisabled;
bool isPressed;
enum CUIButtonState state;
};
void c_ui_button_set(struct CUIButton* self, vec4 baseColor, vec4 selectColor);
void c_ui_button_register(void);

43
src/game/ecs/e_enemy.c Normal file
View File

@ -0,0 +1,43 @@
/*
* DESCRIPTION:
* Enemy code.
*/
#include "e_enemy.h"
/* Initializes an enemy. */
void
enemy_init(u32 id, u32 targetID, enum CColorType colorType, vec3 position, f32 speed)
{
struct CGameObject* object;
struct CChase* chase;
struct CSpin* spin;
struct CColor* color;
object = ecs_add(id, ECS_C_GAME_OBJECT);
chase = ecs_add(id, ECS_C_CHASE);
spin = ecs_add(id, ECS_C_SPIN);
color = ecs_add(id, ECS_C_COLOR);
ecs_add(id, ECS_C_CONTACT_DAMAGE);
ecs_add(id, ECS_C_PARTICLE_SPAWN);
c_game_object_set
(
object,
game.textures[TEXTURE_ENEMY],
ENEMY_SHADER,
ENEMY_ORIGIN,
ENEMY_SIZE,
position,
C_COLOR_VALUES[colorType],
ENEMY_FRICTION,
ENEMY_VELOCITY_MAX,
ENEMY_RADIUS
);
c_chase_set(chase, targetID, speed);
c_spin_set(spin, ENEMY_SPIN_SPEED);
c_color_set(color, colorType);
}

24
src/game/ecs/e_enemy.h Normal file
View File

@ -0,0 +1,24 @@
/*
* DESCRIPTION:
* e_enemy.c header.
*/
#pragma once
#include "c_chase.h"
#include "c_color.h"
#include "c_game_object.h"
#include "c_spin.h"
#define ENEMY_FRICTION 0.95f
#define ENEMY_ALPHA_TIMER_MAX 60
#define ENEMY_RADIUS 16.0f
#define ENEMY_SPIN_SPEED 0.05f
#define ENEMY_VELOCITY_MAX 20.0f
#define ENEMY_CHASE_SPEED 0.015f
#define ENEMY_SHADER SHADER_TEXTURE_QUAD
#define ENEMY_ORIGIN ORIGIN_CENTER
static const vec2 ENEMY_SIZE = {25.0f, 25.0f};
void enemy_init(u32 id, u32 targetID, enum CColorType colorType, vec3 position, f32 speed);

Some files were not shown because too many files have changed in this diff Show More