first commit
This commit is contained in:
68
src/COMMON.h
Normal file
68
src/COMMON.h
Normal file
@ -0,0 +1,68 @@
|
||||
#pragma once
|
||||
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define CGLM_DEFINE_PRINTS
|
||||
|
||||
#include <cglm/cglm.h>
|
||||
|
||||
#define PI (GLM_PI)
|
||||
#define PI_FOURTH (PI / 4)
|
||||
#define PI_EIGHTH (PI / 8)
|
||||
#define PI_HALF (PI / 2)
|
||||
#define TAU (PI * 2)
|
||||
#define RADIANS(x) (x * (PI / 180))
|
||||
#define RADIANS_MIN (0)
|
||||
#define RADIANS_MAX (TAU)
|
||||
|
||||
#define MIN(x, min) (x < min ? min : x)
|
||||
#define MAX(x, max) (x > max ? max : x)
|
||||
#define CLAMP(x, min, max) (MIN(MAX(x, max), min))
|
||||
|
||||
#define RANDOM_SEED_SET(seed) (srand(seed))
|
||||
#define RANDOM ((f32)rand() / (f32)RAND_MAX)
|
||||
#define RANDOM_F32(min, max) ((f32)((RANDOM * (max - min + 1)) + min)) /* [min, max] */
|
||||
#define RANDOM_S32(min, max) ((s32)((RANDOM * (max - min + 1)) + min)) /* [min, max] */
|
||||
#define RANDOM_BOOL() (RANDOM_S32(0, 2))
|
||||
|
||||
#define DISTANCE_2D(x1, x2, y1, y2) (sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2)))
|
||||
#define ATAN(x1, x2, y1, y2) (fmod((atan2(y2 - y1, x2 - x1) + TAU), TAU)) /* [0, 2PI] */
|
||||
|
||||
#define MILLISECOND_TICK 600
|
||||
#define SECOND_TICK 60
|
||||
#define MINUTE_TICK 3600
|
||||
#define HOUR_TICK 216000
|
||||
|
||||
typedef uint8_t u8;
|
||||
typedef uint16_t u16;
|
||||
typedef uint32_t u32;
|
||||
typedef uint64_t u64;
|
||||
|
||||
typedef int8_t s8;
|
||||
typedef int16_t s16;
|
||||
typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
|
||||
typedef float f32;
|
||||
typedef double f64;
|
||||
|
||||
typedef s32 (*SortCompareFunction)(const void*, const void*);
|
||||
|
||||
#define DIRECTION_COUNT 4
|
||||
typedef enum Direction
|
||||
{
|
||||
DIRECTION_LEFT,
|
||||
DIRECTION_RIGHT,
|
||||
DIRECTION_UP,
|
||||
DIRECTION_DOWN
|
||||
} Direction;
|
||||
|
||||
static const vec4 OPAQUE = {1.0f, 1.0f, 1.0f, 1.0f};
|
||||
static const vec4 BLACK = {0.0f, 0.0f, 0.0f, 1.0f};
|
||||
static const vec4 TRANSPARENT = {0.0f, 0.0f, 0.0f, 0.0f};
|
83
src/engine/camera.c
Normal file
83
src/engine/camera.c
Normal file
@ -0,0 +1,83 @@
|
||||
#include "camera.h"
|
||||
|
||||
void
|
||||
camera_orthographic_init(Camera* self, vec2 size)
|
||||
{
|
||||
memset(self, '\0', sizeof(Camera));
|
||||
|
||||
self->type = CAMERA_ORTHOGRAPHIC;
|
||||
|
||||
glm_vec2_copy(size, self->orthographic.size);
|
||||
|
||||
self->zoom = 1.0f;
|
||||
}
|
||||
|
||||
void
|
||||
camera_view_get(Camera* self, mat4 view)
|
||||
{
|
||||
vec3 glPosition;
|
||||
vec3 zoom;
|
||||
vec3 center;
|
||||
|
||||
glm_mat4_identity(view);
|
||||
|
||||
glPosition[0] = -self->position[0] / (f32)self->orthographic.size[0];
|
||||
glPosition[1] = self->position[1] / (f32)self->orthographic.size[1];
|
||||
glPosition[2] = 0.0f;
|
||||
|
||||
zoom[0] = self->zoom;
|
||||
zoom[1] = self->zoom;
|
||||
zoom[2] = 0.0f;
|
||||
|
||||
switch (self->type)
|
||||
{
|
||||
case CAMERA_ORTHOGRAPHIC:
|
||||
glm_mat4_identity(view);
|
||||
glm_translate(view, glPosition);
|
||||
glm_scale(view, zoom);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
camera_projection_get(Camera* self, mat4 projection)
|
||||
{
|
||||
glm_mat4_identity(projection);
|
||||
|
||||
switch (self->type)
|
||||
{
|
||||
case CAMERA_ORTHOGRAPHIC:
|
||||
glm_ortho
|
||||
(
|
||||
0.0f,
|
||||
self->orthographic.size[0],
|
||||
self->orthographic.size[1],
|
||||
0.0f,
|
||||
CAMERA_ORTHOGRAPHIC_NEAR,
|
||||
CAMERA_ORTHOGRAPHIC_FAR,
|
||||
projection
|
||||
);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
camera_position_set(Camera* self, vec3 position)
|
||||
{
|
||||
glm_vec3_copy(position, self->position);
|
||||
}
|
||||
|
||||
void
|
||||
camera_orthographic_window_set(Camera* self, Window* window)
|
||||
{
|
||||
ivec2 size;
|
||||
|
||||
window_size_get(window, size);
|
||||
|
||||
self->orthographic.size[0] = (f32)size[0];
|
||||
self->orthographic.size[1] = (f32)size[1];
|
||||
}
|
42
src/engine/camera.h
Normal file
42
src/engine/camera.h
Normal file
@ -0,0 +1,42 @@
|
||||
#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
|
||||
|
||||
typedef enum CameraType
|
||||
{
|
||||
CAMERA_PERSPECTIVE, // unsupported
|
||||
CAMERA_ORTHOGRAPHIC
|
||||
} CameraType;
|
||||
|
||||
typedef struct Camera
|
||||
{
|
||||
CameraType type;
|
||||
vec3 position;
|
||||
f32 yaw;
|
||||
f32 pitch;
|
||||
f32 zoom;
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
vec2 size;
|
||||
} orthographic;
|
||||
struct
|
||||
{
|
||||
f32 fov;
|
||||
f32 aspect;
|
||||
} perspective;
|
||||
};
|
||||
} Camera;
|
||||
|
||||
void camera_orthographic_init(Camera* self, vec2 size);
|
||||
void camera_orthographic_window_set(Camera* self, Window* window);
|
||||
void camera_position_set(Camera* self, vec3 position);
|
||||
void camera_projection_get(Camera* self, mat4 projection);
|
||||
void camera_view_get(Camera* self, mat4 view);
|
42
src/engine/circle.c
Normal file
42
src/engine/circle.c
Normal file
@ -0,0 +1,42 @@
|
||||
#include "circle.h"
|
||||
|
||||
bool
|
||||
circle_collide_check(Circle* a, Circle* b)
|
||||
{
|
||||
f32 sum;
|
||||
f32 distance;
|
||||
|
||||
distance = DISTANCE_2D
|
||||
(
|
||||
a->position[0],
|
||||
b->position[0],
|
||||
a->position[1],
|
||||
b->position[1]
|
||||
);
|
||||
|
||||
sum = a->radius + b->radius;
|
||||
|
||||
if (distance < sum)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
circle_has_point_check(Circle* self, vec2 point)
|
||||
{
|
||||
f32 distance;
|
||||
|
||||
distance = DISTANCE_2D
|
||||
(
|
||||
point[0],
|
||||
self->position[0],
|
||||
point[1],
|
||||
self->position[1]
|
||||
);
|
||||
|
||||
if (distance <= self->radius)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
12
src/engine/circle.h
Normal file
12
src/engine/circle.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
typedef struct Circle
|
||||
{
|
||||
f32 radius;
|
||||
vec2 position;
|
||||
} Circle;
|
||||
|
||||
bool circle_collide_check(Circle* a, Circle* b);
|
||||
bool circle_has_point_check(Circle* self, vec2 point);
|
44
src/engine/event.c
Normal file
44
src/engine/event.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include "event.h"
|
||||
|
||||
/* Updates events. */
|
||||
void
|
||||
event_update(Event* self)
|
||||
{
|
||||
SDL_Event event;
|
||||
|
||||
memcpy(&self->previous, &self->current, sizeof(bool) * EVENT_COUNT);
|
||||
memset(&self->current, '\0', sizeof(bool) * EVENT_COUNT);
|
||||
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
{
|
||||
case SDL_QUIT:
|
||||
self->current[EVENT_QUIT] = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Is a given event pressed? */
|
||||
bool
|
||||
event_press(Event* self, EventType type)
|
||||
{
|
||||
return (self->current[type] && !self->previous[type]);
|
||||
}
|
||||
|
||||
/* Is a given event held? */
|
||||
bool
|
||||
event_held(Event* self, EventType type)
|
||||
{
|
||||
return (self->current[type] && self->previous[type]);
|
||||
}
|
||||
|
||||
/* Is a given event released? */
|
||||
bool
|
||||
event_release(Event* self, EventType type)
|
||||
{
|
||||
return (!self->current[type] && self->previous[type]);
|
||||
}
|
22
src/engine/event.h
Normal file
22
src/engine/event.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
#define EVENT_COUNT (EVENT_QUIT + 1)
|
||||
typedef enum EventType
|
||||
{
|
||||
EVENT_QUIT
|
||||
} EventType;
|
||||
|
||||
typedef struct Event
|
||||
{
|
||||
bool current[EVENT_COUNT];
|
||||
bool previous[EVENT_COUNT];
|
||||
} Event;
|
||||
|
||||
void event_update(Event* self);
|
||||
bool event_press(Event* self, EventType type);
|
||||
bool event_held(Event* self, EventType type);
|
||||
bool event_release(Event* self, EventType type);
|
38
src/engine/fbo.c
Normal file
38
src/engine/fbo.c
Normal file
@ -0,0 +1,38 @@
|
||||
#include "fbo.h"
|
||||
|
||||
void
|
||||
fbo_init(FBO* self)
|
||||
{
|
||||
glGenFramebuffers(1, &self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
fbo_bind(FBO* self)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
fbo_unbind(void)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void
|
||||
fbo_rbo_set(RBO* rbo)
|
||||
{
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo->handle);
|
||||
}
|
||||
|
||||
void
|
||||
fbo_texture_set(Texture* texture)
|
||||
{
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture->handle, 0);
|
||||
}
|
||||
|
||||
void
|
||||
fbo_free(FBO* self)
|
||||
{
|
||||
glDeleteFramebuffers(1, &self->handle);
|
||||
memset(self, '\0', sizeof(FBO));
|
||||
}
|
16
src/engine/fbo.h
Normal file
16
src/engine/fbo.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "rbo.h"
|
||||
#include "texture.h"
|
||||
|
||||
typedef struct FBO
|
||||
{
|
||||
GLuint handle;
|
||||
} FBO;
|
||||
|
||||
void fbo_init(FBO* self);
|
||||
void fbo_bind(FBO* self);
|
||||
void fbo_unbind(void);
|
||||
void fbo_free(FBO* self);
|
||||
void fbo_rbo_set(RBO* rbo);
|
||||
void fbo_texture_set(Texture* texture);
|
53
src/engine/file.c
Normal file
53
src/engine/file.c
Normal file
@ -0,0 +1,53 @@
|
||||
#include "file.h"
|
||||
|
||||
bool
|
||||
file_read(const char* path, void* buffer, size_t size, const char* mode)
|
||||
{
|
||||
SDL_RWops* io;
|
||||
|
||||
printf(STRING_FILE_READ_OPEN, path);
|
||||
|
||||
io = SDL_RWFromFile(path, mode);
|
||||
|
||||
if (!io)
|
||||
{
|
||||
printf(STRING_FILE_READ_ERROR, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_RWread(io, buffer, size, 1);
|
||||
|
||||
printf(STRING_FILE_READ_SUCCESS, path);
|
||||
|
||||
SDL_RWclose(io);
|
||||
|
||||
printf(STRING_FILE_CLOSED, path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
file_write(const char* path, void* data, size_t size, const char* mode)
|
||||
{
|
||||
SDL_RWops* io;
|
||||
|
||||
printf(STRING_FILE_WRITE_OPEN, path);
|
||||
|
||||
io = SDL_RWFromFile(path, mode);
|
||||
|
||||
if (!io)
|
||||
{
|
||||
printf(STRING_FILE_WRITE_ERROR, path);
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_RWwrite(io, data, size, 1);
|
||||
|
||||
printf(STRING_FILE_WRITE_SUCCESS, path);
|
||||
|
||||
SDL_RWclose(io);
|
||||
|
||||
printf(STRING_FILE_CLOSED, path);
|
||||
|
||||
return true;
|
||||
}
|
15
src/engine/file.h
Normal file
15
src/engine/file.h
Normal file
@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include "../COMMON.h"
|
||||
|
||||
#define STRING_FILE_READ_OPEN "[INFO] Opened file to read: %s\n"
|
||||
#define STRING_FILE_CLOSED "[INFO] Closed file: %s\n"
|
||||
#define STRING_FILE_READ_SUCCESS "[INFO] Read from file: %s\n"
|
||||
#define STRING_FILE_READ_ERROR "[ERROR] Unable to read from file: %s\n"
|
||||
#define STRING_FILE_WRITE_OPEN "[INFO] Opened file to write: %s\n"
|
||||
#define STRING_FILE_WRITE_ERROR "[ERROR] Unable to write to file: %s\n"
|
||||
#define STRING_FILE_WRITE_SUCCESS "[INFO] Wrote to file: %s\n"
|
||||
|
||||
bool file_read(const char* path, void* buffer, size_t size, const char* mode);
|
||||
bool file_write(const char* path, void* data, size_t size, const char* mode);
|
104
src/engine/font.c
Normal file
104
src/engine/font.c
Normal file
@ -0,0 +1,104 @@
|
||||
#include "font.h"
|
||||
|
||||
void
|
||||
font_glyph_metrics_init(Font* self, GlyphMetrics* glyphMetrics, char glyph)
|
||||
{
|
||||
TTF_GlyphMetrics
|
||||
(
|
||||
self->ttf,
|
||||
glyph,
|
||||
&glyphMetrics->minX,
|
||||
&glyphMetrics->maxX,
|
||||
&glyphMetrics->minY,
|
||||
&glyphMetrics->maxY,
|
||||
&glyphMetrics->advance
|
||||
);
|
||||
}
|
||||
|
||||
s32
|
||||
font_glyph_width_get(Font* self, char glyph)
|
||||
{
|
||||
GlyphMetrics glyphMetrics;
|
||||
|
||||
font_glyph_metrics_init(self, &glyphMetrics, glyph);
|
||||
|
||||
return glyphMetrics.maxX - glyphMetrics.minX;
|
||||
}
|
||||
|
||||
s32
|
||||
font_glyph_kerning_get(Font* self, char glyph, char nextGlyph)
|
||||
{
|
||||
return TTF_GetFontKerningSizeGlyphs(self->ttf, glyph, nextGlyph);
|
||||
}
|
||||
|
||||
void
|
||||
font_glyph_texture_init(Font* self, Texture* texture, char glyph)
|
||||
{
|
||||
SDL_Surface* surface;
|
||||
SDL_Surface* textSurface;
|
||||
ivec2 size;
|
||||
|
||||
size[0] = font_glyph_width_get(self, glyph);
|
||||
|
||||
size[1] = font_height_get(self);
|
||||
|
||||
surface_rgba_init(&surface, size);
|
||||
|
||||
textSurface = TTF_RenderGlyph_Blended(self->ttf, glyph, GLYPH_COLOR);
|
||||
|
||||
SDL_BlitSurface(textSurface, NULL, surface, NULL);
|
||||
|
||||
SDL_FreeSurface(textSurface);
|
||||
|
||||
texture_surface_init(texture, surface);
|
||||
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
|
||||
s32
|
||||
font_line_skip_get(Font* self)
|
||||
{
|
||||
return TTF_FontLineSkip(self->ttf);
|
||||
}
|
||||
|
||||
s32
|
||||
font_height_get(Font* self)
|
||||
{
|
||||
return TTF_FontHeight(self->ttf);
|
||||
}
|
||||
|
||||
bool
|
||||
font_init(Font* self, const char* path, u32 size)
|
||||
{
|
||||
self->ttf = TTF_OpenFont(path, size);
|
||||
|
||||
if (!self->ttf)
|
||||
{
|
||||
printf(STRING_SDL_TTF_FONT_ERROR, path, TTF_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
printf(STRING_SDL_TTF_FONT_SUCCESS, path);
|
||||
|
||||
self->size = size;
|
||||
self->isInit = true;
|
||||
|
||||
for (s32 i = 0; i < FONT_GLYPH_MAX; i++)
|
||||
font_glyph_texture_init(self, &self->glyphTextures[i], (char)i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
font_free(Font* self)
|
||||
{
|
||||
if (self->isInit)
|
||||
{
|
||||
TTF_CloseFont(self->ttf);
|
||||
|
||||
for (s32 i = 0; i < FONT_GLYPH_MAX; i++)
|
||||
texture_free(&self->glyphTextures[i]);
|
||||
|
||||
self->isInit = false;
|
||||
}
|
||||
}
|
39
src/engine/font.h
Normal file
39
src/engine/font.h
Normal file
@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
|
||||
#include "texture.h"
|
||||
#include "surface.h"
|
||||
|
||||
#define FONT_GLYPH_MAX 128
|
||||
|
||||
#define STRING_SDL_TTF_FONT_SUCCESS "[INFO] Loaded font: %s\n"
|
||||
#define STRING_SDL_TTF_FONT_ERROR "[ERROR] Unable to load font: %s | %s\n"
|
||||
|
||||
typedef struct Font
|
||||
{
|
||||
TTF_Font* ttf;
|
||||
Texture glyphTextures[FONT_GLYPH_MAX];
|
||||
u32 size;
|
||||
bool isInit;
|
||||
} Font;
|
||||
|
||||
typedef struct GlyphMetrics
|
||||
{
|
||||
s32 minX;
|
||||
s32 minY;
|
||||
s32 maxX;
|
||||
s32 maxY;
|
||||
s32 advance;
|
||||
} GlyphMetrics;
|
||||
|
||||
bool font_init(Font* self, const char* path, u32 size);
|
||||
s32 font_glyph_kerning_get(Font* self, char glyph, char nextGlyph);
|
||||
s32 font_glyph_width_get(Font* self, char glyph);
|
||||
s32 font_height_get(Font* self);
|
||||
s32 font_line_skip_get(Font* self);
|
||||
void font_free(Font* self);
|
||||
void font_glyph_metrics_init(Font* self, GlyphMetrics* glyphMetrics, char glyph);
|
||||
void font_glyph_texture_init(Font* self, Texture* texture, char glyph);
|
||||
|
||||
static const SDL_Color GLYPH_COLOR = {255, 255, 255, 255};
|
22
src/engine/fullscreen.c
Normal file
22
src/engine/fullscreen.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "fullscreen.h"
|
||||
|
||||
/* Sets window to fullscreen. */
|
||||
void
|
||||
fullscreen_set(Window* self, Renderer* renderer)
|
||||
{
|
||||
SDL_SetWindowSize(self->sdl, self->expectedSize[0], self->expectedSize[1]);
|
||||
|
||||
renderer_update(renderer);
|
||||
|
||||
SDL_SetWindowFullscreen(self->sdl, SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||
}
|
||||
|
||||
/* Exits fullscreen. */
|
||||
void
|
||||
fullscreen_exit(Window* self, Renderer* renderer)
|
||||
{
|
||||
SDL_SetWindowFullscreen(self->sdl, 0);
|
||||
SDL_SetWindowSize(self->sdl, self->expectedSize[0], self->expectedSize[1]);
|
||||
renderer_update(renderer);
|
||||
}
|
||||
|
7
src/engine/fullscreen.h
Normal file
7
src/engine/fullscreen.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "window.h"
|
||||
#include "renderer.h"
|
||||
|
||||
void fullscreen_set(Window* window, Renderer* renderer);
|
||||
void fullscreen_exit(Window* window, Renderer* renderer);
|
9
src/engine/glew.c
Normal file
9
src/engine/glew.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include "glew.h"
|
||||
|
||||
void
|
||||
glew_init(void)
|
||||
{
|
||||
glewInit();
|
||||
|
||||
printf(STRING_GLEW_INIT);
|
||||
}
|
9
src/engine/glew.h
Normal file
9
src/engine/glew.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
#define STRING_GLEW_INIT "[INFO] Initialized GLEW\n"
|
||||
|
||||
void glew_init(void);
|
32
src/engine/keyboard.c
Normal file
32
src/engine/keyboard.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include "keyboard.h"
|
||||
|
||||
void
|
||||
keyboard_update(Keyboard* self)
|
||||
{
|
||||
const u8* state;
|
||||
|
||||
memcpy(&self->previous, &self->current, sizeof(u8) * KEYBOARD_KEY_COUNT);
|
||||
memset(&self->current, '\0', sizeof(u8) * KEYBOARD_KEY_COUNT);
|
||||
|
||||
state = SDL_GetKeyboardState(NULL);
|
||||
|
||||
memcpy(&self->current, state, KEYBOARD_KEY_COUNT);
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_press(Keyboard* self, KeyboardKeyType type)
|
||||
{
|
||||
return (self->current[type] && !self->previous[type]);
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_held(Keyboard* self, KeyboardKeyType type)
|
||||
{
|
||||
return (self->current[type] && self->previous[type]);
|
||||
}
|
||||
|
||||
bool
|
||||
keyboard_release(Keyboard* self, KeyboardKeyType type)
|
||||
{
|
||||
return (!self->current[type] && self->previous[type]);
|
||||
}
|
240
src/engine/keyboard.h
Normal file
240
src/engine/keyboard.h
Normal file
@ -0,0 +1,240 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
#define KEYBOARD_KEY_COUNT (255)
|
||||
typedef enum KeyboardKeyType
|
||||
{
|
||||
KEYBOARD_KEY_UNKNOWN = 0,
|
||||
KEYBOARD_KEY_UNKNOWN_TWO = 1,
|
||||
KEYBOARD_KEY_UNKNOWN_THREE = 2,
|
||||
KEYBOARD_KEY_UNKNOWN_FOUR = 3,
|
||||
KEYBOARD_KEY_A = 4,
|
||||
KEYBOARD_KEY_B = 5,
|
||||
KEYBOARD_KEY_C = 6,
|
||||
KEYBOARD_KEY_D = 7,
|
||||
KEYBOARD_KEY_E = 8,
|
||||
KEYBOARD_KEY_F = 9,
|
||||
KEYBOARD_KEY_G = 10,
|
||||
KEYBOARD_KEY_H = 11,
|
||||
KEYBOARD_KEY_I = 12,
|
||||
KEYBOARD_KEY_J = 13,
|
||||
KEYBOARD_KEY_K = 14,
|
||||
KEYBOARD_KEY_L = 15,
|
||||
KEYBOARD_KEY_M = 16,
|
||||
KEYBOARD_KEY_N = 17,
|
||||
KEYBOARD_KEY_O = 18,
|
||||
KEYBOARD_KEY_P = 19,
|
||||
KEYBOARD_KEY_Q = 20,
|
||||
KEYBOARD_KEY_R = 21,
|
||||
KEYBOARD_KEY_S = 22,
|
||||
KEYBOARD_KEY_T = 23,
|
||||
KEYBOARD_KEY_U = 24,
|
||||
KEYBOARD_KEY_V = 25,
|
||||
KEYBOARD_KEY_W = 26,
|
||||
KEYBOARD_KEY_X = 27,
|
||||
KEYBOARD_KEY_Y = 28,
|
||||
KEYBOARD_KEY_Z = 29,
|
||||
KEYBOARD_KEY_1 = 30,
|
||||
KEYBOARD_KEY_2 = 31,
|
||||
KEYBOARD_KEY_3 = 32,
|
||||
KEYBOARD_KEY_4 = 33,
|
||||
KEYBOARD_KEY_5 = 34,
|
||||
KEYBOARD_KEY_6 = 35,
|
||||
KEYBOARD_KEY_7 = 36,
|
||||
KEYBOARD_KEY_8 = 37,
|
||||
KEYBOARD_KEY_9 = 38,
|
||||
KEYBOARD_KEY_0 = 39,
|
||||
KEYBOARD_KEY_RETURN = 40,
|
||||
KEYBOARD_KEY_ESCAPE = 41,
|
||||
KEYBOARD_KEY_BACKSPACE = 42,
|
||||
KEYBOARD_KEY_TAB = 43,
|
||||
KEYBOARD_KEY_SPACE = 44,
|
||||
KEYBOARD_KEY_MINUS = 45,
|
||||
KEYBOARD_KEY_EQUALS = 46,
|
||||
KEYBOARD_KEY_LEFTBRACKET = 47,
|
||||
KEYBOARD_KEY_RIGHTBRACKET = 48,
|
||||
KEYBOARD_KEY_BACKSLASH = 49,
|
||||
KEYBOARD_KEY_NONUSHASH = 50,
|
||||
KEYBOARD_KEY_SEMICOLON = 51,
|
||||
KEYBOARD_KEY_APOSTROPHE = 52,
|
||||
KEYBOARD_KEY_GRAVE = 53,
|
||||
KEYBOARD_KEY_COMMA = 54,
|
||||
KEYBOARD_KEY_PERIOD = 55,
|
||||
KEYBOARD_KEY_SLASH = 56,
|
||||
KEYBOARD_KEY_CAPSLOCK = 57,
|
||||
KEYBOARD_KEY_F1 = 58,
|
||||
KEYBOARD_KEY_F2 = 59,
|
||||
KEYBOARD_KEY_F3 = 60,
|
||||
KEYBOARD_KEY_F4 = 61,
|
||||
KEYBOARD_KEY_F5 = 62,
|
||||
KEYBOARD_KEY_F6 = 63,
|
||||
KEYBOARD_KEY_F7 = 64,
|
||||
KEYBOARD_KEY_F8 = 65,
|
||||
KEYBOARD_KEY_F9 = 66,
|
||||
KEYBOARD_KEY_F10 = 67,
|
||||
KEYBOARD_KEY_F11 = 68,
|
||||
KEYBOARD_KEY_F12 = 69,
|
||||
KEYBOARD_KEY_PRINTSCREEN = 70,
|
||||
KEYBOARD_KEY_SCROLLLOCK = 71,
|
||||
KEYBOARD_KEY_PAUSE = 72,
|
||||
KEYBOARD_KEY_INSERT = 73,
|
||||
KEYBOARD_KEY_HOME = 74,
|
||||
KEYBOARD_KEY_PAGEUP = 75,
|
||||
KEYBOARD_KEY_DELETE = 76,
|
||||
KEYBOARD_KEY_END = 77,
|
||||
KEYBOARD_KEY_PAGEDOWN = 78,
|
||||
KEYBOARD_KEY_RIGHT = 79,
|
||||
KEYBOARD_KEY_LEFT = 80,
|
||||
KEYBOARD_KEY_DOWN = 81,
|
||||
KEYBOARD_KEY_UP = 82,
|
||||
KEYBOARD_KEY_NUMLOCKCLEAR = 83,
|
||||
KEYBOARD_KEY_KP_DIVIDE = 84,
|
||||
KEYBOARD_KEY_KP_MULTIPLY = 85,
|
||||
KEYBOARD_KEY_KP_MINUS = 86,
|
||||
KEYBOARD_KEY_KP_PLUS = 87,
|
||||
KEYBOARD_KEY_KP_ENTER = 88,
|
||||
KEYBOARD_KEY_KP_1 = 89,
|
||||
KEYBOARD_KEY_KP_2 = 90,
|
||||
KEYBOARD_KEY_KP_3 = 91,
|
||||
KEYBOARD_KEY_KP_4 = 92,
|
||||
KEYBOARD_KEY_KP_5 = 93,
|
||||
KEYBOARD_KEY_KP_6 = 94,
|
||||
KEYBOARD_KEY_KP_7 = 95,
|
||||
KEYBOARD_KEY_KP_8 = 96,
|
||||
KEYBOARD_KEY_KP_9 = 97,
|
||||
KEYBOARD_KEY_KP_0 = 98,
|
||||
KEYBOARD_KEY_KP_PERIOD = 99,
|
||||
KEYBOARD_KEY_NONUSBACKSLASH = 100,
|
||||
KEYBOARD_KEY_APPLICATION = 101,
|
||||
KEYBOARD_KEY_POWER = 102,
|
||||
KEYBOARD_KEY_KP_EQUALS = 103,
|
||||
KEYBOARD_KEY_F13 = 104,
|
||||
KEYBOARD_KEY_F14 = 105,
|
||||
KEYBOARD_KEY_F15 = 106,
|
||||
KEYBOARD_KEY_F16 = 107,
|
||||
KEYBOARD_KEY_F17 = 108,
|
||||
KEYBOARD_KEY_F18 = 109,
|
||||
KEYBOARD_KEY_F19 = 110,
|
||||
KEYBOARD_KEY_F20 = 111,
|
||||
KEYBOARD_KEY_F21 = 112,
|
||||
KEYBOARD_KEY_F22 = 113,
|
||||
KEYBOARD_KEY_F23 = 114,
|
||||
KEYBOARD_KEY_F24 = 115,
|
||||
KEYBOARD_KEY_EXECUTE = 116,
|
||||
KEYBOARD_KEY_HELP = 117,
|
||||
KEYBOARD_KEY_MENU = 118,
|
||||
KEYBOARD_KEY_SELECT = 119,
|
||||
KEYBOARD_KEY_STOP = 120,
|
||||
KEYBOARD_KEY_AGAIN = 121,
|
||||
KEYBOARD_KEY_UNDO = 122,
|
||||
KEYBOARD_KEY_CUT = 123,
|
||||
KEYBOARD_KEY_COPY = 124,
|
||||
KEYBOARD_KEY_PASTE = 125,
|
||||
KEYBOARD_KEY_FIND = 126,
|
||||
KEYBOARD_KEY_MUTE = 127,
|
||||
KEYBOARD_KEY_VOLUMEUP = 128,
|
||||
KEYBOARD_KEY_VOLUMEDOWN = 129,
|
||||
KEYBOARD_KEY_LOCKINGCAPSLOCK = 130,
|
||||
KEYBOARD_KEY_LOCKINGNUMLOCK = 131,
|
||||
KEYBOARD_KEY_LOCKINGSCROLLLOCK = 132,
|
||||
KEYBOARD_KEY_KP_COMMA = 133,
|
||||
KEYBOARD_KEY_KP_EQUALSAS400 = 134,
|
||||
KEYBOARD_KEY_INTERNATIONAL1 = 135,
|
||||
KEYBOARD_KEY_INTERNATIONAL2 = 136,
|
||||
KEYBOARD_KEY_INTERNATIONAL3 = 137,
|
||||
KEYBOARD_KEY_INTERNATIONAL4 = 138,
|
||||
KEYBOARD_KEY_INTERNATIONAL5 = 139,
|
||||
KEYBOARD_KEY_INTERNATIONAL6 = 140,
|
||||
KEYBOARD_KEY_INTERNATIONAL7 = 141,
|
||||
KEYBOARD_KEY_INTERNATIONAL8 = 142,
|
||||
KEYBOARD_KEY_INTERNATIONAL9 = 143,
|
||||
KEYBOARD_KEY_LANG1 = 144,
|
||||
KEYBOARD_KEY_LANG2 = 145,
|
||||
KEYBOARD_KEY_LANG3 = 146,
|
||||
KEYBOARD_KEY_LANG4 = 147,
|
||||
KEYBOARD_KEY_LANG5 = 148,
|
||||
KEYBOARD_KEY_LANG6 = 149,
|
||||
KEYBOARD_KEY_LANG7 = 150,
|
||||
KEYBOARD_KEY_LANG8 = 151,
|
||||
KEYBOARD_KEY_LANG9 = 152,
|
||||
KEYBOARD_KEY_ALTERASE = 153,
|
||||
KEYBOARD_KEY_SYSREQ = 154,
|
||||
KEYBOARD_KEY_CANCEL = 155,
|
||||
KEYBOARD_KEY_CLEAR = 156,
|
||||
KEYBOARD_KEY_PRIOR = 157,
|
||||
KEYBOARD_KEY_RETURN2 = 158,
|
||||
KEYBOARD_KEY_SEPARATOR = 159,
|
||||
KEYBOARD_KEY_OUT = 160,
|
||||
KEYBOARD_KEY_OPER = 161,
|
||||
KEYBOARD_KEY_CLEARAGAIN = 162,
|
||||
KEYBOARD_KEY_CRSEL = 163,
|
||||
KEYBOARD_KEY_EXSEL = 164,
|
||||
KEYBOARD_KEY_KP_00 = 176,
|
||||
KEYBOARD_KEY_KP_000 = 177,
|
||||
KEYBOARD_KEY_THOUSANDSSEPARATOR = 178,
|
||||
KEYBOARD_KEY_DECIMALSEPARATOR = 179,
|
||||
KEYBOARD_KEY_CURRENCYUNIT = 180,
|
||||
KEYBOARD_KEY_CURRENCYSUBUNIT = 181,
|
||||
KEYBOARD_KEY_KP_LEFTPAREN = 182,
|
||||
KEYBOARD_KEY_KP_RIGHTPAREN = 183,
|
||||
KEYBOARD_KEY_KP_LEFTBRACE = 184,
|
||||
KEYBOARD_KEY_KP_RIGHTBRACE = 185,
|
||||
KEYBOARD_KEY_KP_TAB = 186,
|
||||
KEYBOARD_KEY_KP_BACKSPACE = 187,
|
||||
KEYBOARD_KEY_KP_A = 188,
|
||||
KEYBOARD_KEY_KP_B = 189,
|
||||
KEYBOARD_KEY_KP_C = 190,
|
||||
KEYBOARD_KEY_KP_D = 191,
|
||||
KEYBOARD_KEY_KP_E = 192,
|
||||
KEYBOARD_KEY_KP_F = 193,
|
||||
KEYBOARD_KEY_KP_XOR = 194,
|
||||
KEYBOARD_KEY_KP_POWER = 195,
|
||||
KEYBOARD_KEY_KP_PERCENT = 196,
|
||||
KEYBOARD_KEY_KP_LESS = 197,
|
||||
KEYBOARD_KEY_KP_GREATER = 198,
|
||||
KEYBOARD_KEY_KP_AMPERSAND = 199,
|
||||
KEYBOARD_KEY_KP_DBLAMPERSAND = 200,
|
||||
KEYBOARD_KEY_KP_VERTICALBAR = 201,
|
||||
KEYBOARD_KEY_KP_DBLVERTICALBAR = 202,
|
||||
KEYBOARD_KEY_KP_COLON = 203,
|
||||
KEYBOARD_KEY_KP_HASH = 204,
|
||||
KEYBOARD_KEY_KP_SPACE = 205,
|
||||
KEYBOARD_KEY_KP_AT = 206,
|
||||
KEYBOARD_KEY_KP_EXCLAM = 207,
|
||||
KEYBOARD_KEY_KP_MEMSTORE = 208,
|
||||
KEYBOARD_KEY_KP_MEMRECALL = 209,
|
||||
KEYBOARD_KEY_KP_MEMCLEAR = 210,
|
||||
KEYBOARD_KEY_KP_MEMADD = 211,
|
||||
KEYBOARD_KEY_KP_MEMSUBTRACT = 212,
|
||||
KEYBOARD_KEY_KP_MEMMULTIPLY = 213,
|
||||
KEYBOARD_KEY_KP_MEMDIVIDE = 214,
|
||||
KEYBOARD_KEY_KP_PLUSMINUS = 215,
|
||||
KEYBOARD_KEY_KP_CLEAR = 216,
|
||||
KEYBOARD_KEY_KP_CLEARENTRY = 217,
|
||||
KEYBOARD_KEY_KP_BINARY = 218,
|
||||
KEYBOARD_KEY_KP_OCTAL = 219,
|
||||
KEYBOARD_KEY_KP_DECIMAL = 220,
|
||||
KEYBOARD_KEY_KP_HEXADECIMAL = 221,
|
||||
KEYBOARD_KEY_LCTRL = 224,
|
||||
KEYBOARD_KEY_LSHIFT = 225,
|
||||
KEYBOARD_KEY_LALT = 226,
|
||||
KEYBOARD_KEY_LGUI = 227,
|
||||
KEYBOARD_KEY_RCTRL = 228,
|
||||
KEYBOARD_KEY_RSHIFT = 229,
|
||||
KEYBOARD_KEY_RALT = 230,
|
||||
KEYBOARD_KEY_RGUI = 231
|
||||
} KeyboardKeyType;
|
||||
|
||||
typedef struct Keyboard
|
||||
{
|
||||
u8 current[KEYBOARD_KEY_COUNT];
|
||||
u8 previous[KEYBOARD_KEY_COUNT];
|
||||
} Keyboard;
|
||||
|
||||
void keyboard_update(Keyboard* self);
|
||||
bool keyboard_press(Keyboard* self, KeyboardKeyType type);
|
||||
bool keyboard_held(Keyboard* self, KeyboardKeyType type);
|
||||
bool keyboard_release(Keyboard* self, KeyboardKeyType type);
|
74
src/engine/mouse.c
Normal file
74
src/engine/mouse.c
Normal file
@ -0,0 +1,74 @@
|
||||
#include "mouse.h"
|
||||
|
||||
void
|
||||
mouse_update(Mouse* self)
|
||||
{
|
||||
s32 state;
|
||||
s32 x;
|
||||
s32 y;
|
||||
|
||||
memcpy(&self->previous, &self->current, sizeof(bool) * MOUSE_BUTTON_COUNT);
|
||||
memset(&self->current, '\0', sizeof(bool) * MOUSE_BUTTON_COUNT);
|
||||
|
||||
state = SDL_GetMouseState(NULL, NULL);
|
||||
|
||||
if ((state & SDL_BUTTON_LMASK) != 0)
|
||||
self->current[MOUSE_BUTTON_LEFT] = true;
|
||||
|
||||
if ((state & SDL_BUTTON_MMASK) != 0)
|
||||
self->current[MOUSE_BUTTON_MIDDLE] = true;
|
||||
|
||||
if ((state & SDL_BUTTON_RMASK) != 0)
|
||||
self->current[MOUSE_BUTTON_RIGHT] = true;
|
||||
|
||||
if ((state & SDL_BUTTON_X1) != 0)
|
||||
self->current[MOUSE_BUTTON_X1] = true;
|
||||
|
||||
if ((state & SDL_BUTTON_X2) != 0)
|
||||
self->current[MOUSE_BUTTON_X2] = true;
|
||||
|
||||
SDL_GetMouseState(&x, &y);
|
||||
|
||||
self->position[0] = x;
|
||||
self->position[1] = y;
|
||||
}
|
||||
|
||||
bool
|
||||
mouse_press(Mouse* self, MouseButtonType type)
|
||||
{
|
||||
return (self->current[type] && !self->previous[type]);
|
||||
}
|
||||
|
||||
bool
|
||||
mouse_held(Mouse* self, MouseButtonType type)
|
||||
{
|
||||
return (self->current[type] && self->previous[type]);
|
||||
}
|
||||
|
||||
bool
|
||||
mouse_release(Mouse* self, MouseButtonType type)
|
||||
{
|
||||
return (!self->current[type] && self->previous[type]);
|
||||
}
|
||||
|
||||
void
|
||||
mouse_buffer_position_get(Mouse* self, RendererBuffer buffer, Renderer* renderer, vec2 position)
|
||||
{
|
||||
vec2 mousePosition;
|
||||
|
||||
mousePosition[0] = (f32)self->position[0];
|
||||
mousePosition[1] = (f32)self->position[1];
|
||||
|
||||
renderer_buffer_position_from_window_position(renderer, buffer, mousePosition, position);
|
||||
}
|
||||
|
||||
f32
|
||||
mouse_angle_from_buffer_position_get(Mouse* self, RendererBuffer buffer, Renderer* renderer, vec2 position)
|
||||
{
|
||||
vec2 mousePosition;
|
||||
f32 angle;
|
||||
|
||||
mouse_buffer_position_get(self, buffer, renderer, mousePosition);
|
||||
|
||||
return ATAN(position[0], mousePosition[0], position[1], mousePosition[1]);
|
||||
}
|
30
src/engine/mouse.h
Normal file
30
src/engine/mouse.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "renderer.h"
|
||||
|
||||
#define MOUSE_BUTTON_COUNT (MOUSE_BUTTON_X2 + 1)
|
||||
typedef enum MouseButtonType
|
||||
{
|
||||
MOUSE_BUTTON_NONE,
|
||||
MOUSE_BUTTON_LEFT,
|
||||
MOUSE_BUTTON_MIDDLE,
|
||||
MOUSE_BUTTON_RIGHT,
|
||||
MOUSE_BUTTON_X1,
|
||||
MOUSE_BUTTON_X2
|
||||
} MouseButtonType;
|
||||
|
||||
typedef struct Mouse
|
||||
{
|
||||
ivec2 position;
|
||||
bool current[MOUSE_BUTTON_COUNT];
|
||||
bool previous[MOUSE_BUTTON_COUNT];
|
||||
} Mouse;
|
||||
|
||||
void mouse_update(Mouse* self);
|
||||
bool mouse_press(Mouse* self, MouseButtonType type);
|
||||
bool mouse_held(Mouse* self, MouseButtonType type);
|
||||
bool mouse_release(Mouse* self, MouseButtonType type);
|
||||
void mouse_buffer_position_get(Mouse* mouse, RendererBuffer buffer, Renderer* renderer, vec2 position);
|
||||
f32 mouse_angle_from_buffer_position_get(Mouse* self, RendererBuffer buffer, Renderer* renderer, vec2 position);
|
62
src/engine/music.c
Normal file
62
src/engine/music.c
Normal file
@ -0,0 +1,62 @@
|
||||
#include "music.h"
|
||||
|
||||
bool
|
||||
music_init(Music* self, const char* path)
|
||||
{
|
||||
self->chunk = Mix_LoadMUS(path);
|
||||
|
||||
if (!self->chunk)
|
||||
{
|
||||
printf(STRING_SDL_MIXER_MUSIC_ERROR, path, Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
printf(STRING_SDL_MIXER_MUSIC_SUCCESS, path);
|
||||
|
||||
self->isInit = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
music_free(Music* self)
|
||||
{
|
||||
if (self->isInit)
|
||||
{
|
||||
Mix_FreeMusic(self->chunk);
|
||||
self->isInit = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
music_play(Music* self, bool isLoop)
|
||||
{
|
||||
if (isLoop)
|
||||
Mix_PlayMusic(self->chunk, -1);
|
||||
else
|
||||
Mix_PlayMusic(self->chunk, 0);
|
||||
}
|
||||
|
||||
void
|
||||
music_resume(void)
|
||||
{
|
||||
Mix_ResumeMusic();
|
||||
}
|
||||
|
||||
void
|
||||
music_pause(void)
|
||||
{
|
||||
Mix_PauseMusic();
|
||||
}
|
||||
|
||||
void
|
||||
music_stop(void)
|
||||
{
|
||||
Mix_HaltMusic();
|
||||
}
|
||||
|
||||
bool
|
||||
music_is_playing_check(void)
|
||||
{
|
||||
return Mix_PlayingMusic();
|
||||
}
|
22
src/engine/music.h
Normal file
22
src/engine/music.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
#define STRING_SDL_MIXER_MUSIC_SUCCESS "[INFO] Loaded music: %s\n"
|
||||
#define STRING_SDL_MIXER_MUSIC_ERROR "[ERROR] Unable to load music: %s | %s\n"
|
||||
|
||||
typedef struct Music
|
||||
{
|
||||
Mix_Music* chunk;
|
||||
bool isInit;
|
||||
} Music;
|
||||
|
||||
bool music_is_playing_check(void);
|
||||
void music_free(Music* self);
|
||||
bool music_init(Music* self, const char* path);
|
||||
void music_pause(void);
|
||||
void music_play(Music* self, bool isLoop);
|
||||
void music_resume(void);
|
||||
void music_stop(void);
|
32
src/engine/rbo.c
Normal file
32
src/engine/rbo.c
Normal file
@ -0,0 +1,32 @@
|
||||
#include "rbo.h"
|
||||
|
||||
void
|
||||
rbo_init(RBO* self)
|
||||
{
|
||||
glGenRenderbuffers(1, &self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
rbo_bind(RBO* self)
|
||||
{
|
||||
glBindRenderbuffer(GL_FRAMEBUFFER, self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
rbo_unbind(void)
|
||||
{
|
||||
glBindRenderbuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
void
|
||||
rbo_storage_set(RBO* self, ivec2 size)
|
||||
{
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, size[0], size[1]);
|
||||
}
|
||||
|
||||
void
|
||||
rbo_free(RBO* self)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &self->handle);
|
||||
memset(self, '\0', sizeof(RBO));
|
||||
}
|
17
src/engine/rbo.h
Normal file
17
src/engine/rbo.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
typedef struct RBO
|
||||
{
|
||||
GLuint handle;
|
||||
} RBO;
|
||||
|
||||
void rbo_init(RBO* self);
|
||||
void rbo_bind(RBO* self);
|
||||
void rbo_unbind(void);
|
||||
void rbo_free(RBO* self);
|
||||
void rbo_storage_set(RBO* self, ivec2 size);
|
24
src/engine/rectangle.c
Normal file
24
src/engine/rectangle.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include "rectangle.h"
|
||||
|
||||
bool
|
||||
rectangle_collide_intersection(Rectangle* a, Rectangle* b, Rectangle* intersection)
|
||||
{
|
||||
return SDL_IntersectFRect(a, b, intersection);
|
||||
}
|
||||
|
||||
bool
|
||||
rectangle_collide(Rectangle* a, Rectangle* b)
|
||||
{
|
||||
return SDL_HasIntersectionF(a, b);
|
||||
}
|
||||
|
||||
bool
|
||||
rectangle_has_point(Rectangle* self, vec2 point)
|
||||
{
|
||||
SDL_FPoint sdlPoint;
|
||||
|
||||
sdlPoint.x = point[0];
|
||||
sdlPoint.y = point[1];
|
||||
|
||||
return SDL_PointInFRect(&sdlPoint, self);
|
||||
}
|
11
src/engine/rectangle.h
Normal file
11
src/engine/rectangle.h
Normal file
@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
typedef SDL_FRect Rectangle;
|
||||
|
||||
bool rectangle_collide(Rectangle* a, Rectangle* b);
|
||||
bool rectangle_collide_intersection(Rectangle* a, Rectangle* b, Rectangle* intersection);
|
||||
bool rectangle_has_point(Rectangle* self, vec2 point);
|
174
src/engine/renderer.c
Normal file
174
src/engine/renderer.c
Normal file
@ -0,0 +1,174 @@
|
||||
#include "renderer.h"
|
||||
|
||||
static void _renderer_viewport_window_set(Renderer* self);
|
||||
|
||||
void
|
||||
renderer_buffer_init(Renderer* self, RendererBuffer buffer)
|
||||
{
|
||||
ivec2 size;
|
||||
|
||||
window_size_get(self->window, size);
|
||||
|
||||
fbo_init(&self->fbos[buffer]);
|
||||
|
||||
fbo_bind(&self->fbos[buffer]);
|
||||
|
||||
texture_init(&self->fboTextures[buffer], size, NULL);
|
||||
|
||||
texture_bind(&self->fboTextures[buffer]);
|
||||
|
||||
fbo_texture_set(&self->fboTextures[buffer]);
|
||||
|
||||
rbo_init(&self->rbos[buffer]);
|
||||
|
||||
rbo_bind(&self->rbos[buffer]);
|
||||
|
||||
rbo_storage_set(&self->rbos[buffer], size);
|
||||
|
||||
fbo_rbo_set(&self->rbos[buffer]);
|
||||
|
||||
rbo_unbind();
|
||||
fbo_unbind();
|
||||
}
|
||||
|
||||
void
|
||||
renderer_buffer_free(Renderer* self, RendererBuffer buffer)
|
||||
{
|
||||
texture_free(&self->fboTextures[buffer]);
|
||||
rbo_free(&self->rbos[buffer]);
|
||||
fbo_free(&self->fbos[buffer]);
|
||||
}
|
||||
|
||||
static void
|
||||
_renderer_viewport_window_set(Renderer* self)
|
||||
{
|
||||
ivec4 viewport;
|
||||
|
||||
window_ivec4_get(self->window, viewport);
|
||||
|
||||
glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||
}
|
||||
|
||||
void
|
||||
renderer_init(Renderer* self, Window* window, CameraType type, const ivec2* bufferSizes)
|
||||
{
|
||||
|
||||
memset(self, '\0', sizeof(Renderer));
|
||||
|
||||
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);
|
||||
|
||||
for (s32 i = 0; i < RENDERER_BUFFER_COUNT; i++)
|
||||
{
|
||||
vec2 cameraSize;
|
||||
|
||||
renderer_buffer_init(self, (RendererBuffer)i);
|
||||
|
||||
glm_ivec2_copy((s32*)bufferSizes[i], self->bufferSizes[i]);
|
||||
|
||||
cameraSize[0] = bufferSizes[i][0];
|
||||
cameraSize[1] = bufferSizes[i][1];
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case CAMERA_ORTHOGRAPHIC:
|
||||
camera_orthographic_init(&self->camera[i], cameraSize);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void
|
||||
renderer_free(Renderer* self)
|
||||
{
|
||||
for (s32 i = 0; i < RENDERER_BUFFER_COUNT; i++)
|
||||
renderer_buffer_free(self, (RendererBuffer)i);
|
||||
|
||||
vao_free(&self->vao);
|
||||
vbo_free(&self->vbo);
|
||||
vbo_free(&self->ebo);
|
||||
|
||||
memset(self, '\0', sizeof(Renderer));
|
||||
SDL_GL_DeleteContext(self->glContext);
|
||||
}
|
||||
|
||||
void
|
||||
renderer_shader_use(Renderer* self, Shader* shader)
|
||||
{
|
||||
shader_use(shader);
|
||||
}
|
||||
|
||||
void
|
||||
renderer_clear_color_set(Renderer* self, vec4 color)
|
||||
{
|
||||
glClearColor(color[0], color[1], color[2], color[3]);
|
||||
}
|
||||
|
||||
void
|
||||
renderer_clear(Renderer* self)
|
||||
{
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void
|
||||
renderer_present(Renderer* self)
|
||||
{
|
||||
SDL_GL_SwapWindow(self->window->sdl);
|
||||
}
|
||||
|
||||
void
|
||||
renderer_update(Renderer* self)
|
||||
{
|
||||
_renderer_viewport_window_set(self);
|
||||
}
|
||||
|
||||
void
|
||||
renderer_buffer_use(Renderer* self, RendererBuffer buffer)
|
||||
{
|
||||
fbo_bind(&self->fbos[buffer]);
|
||||
}
|
||||
|
||||
void
|
||||
renderer_buffer_unbind(void)
|
||||
{
|
||||
fbo_unbind();
|
||||
}
|
||||
|
||||
void
|
||||
renderer_buffer_position_from_window_position
|
||||
(
|
||||
Renderer* self,
|
||||
RendererBuffer buffer,
|
||||
vec2 windowPosition,
|
||||
vec2 rendererPosition
|
||||
)
|
||||
{
|
||||
ivec2 windowSize;
|
||||
|
||||
window_size_get(self->window, windowSize);
|
||||
|
||||
rendererPosition[0] = windowPosition[0] / windowSize[0];
|
||||
rendererPosition[1] = windowPosition[1] / windowSize[1];
|
||||
|
||||
rendererPosition[0] *= self->camera[buffer].orthographic.size[0];
|
||||
rendererPosition[1] *= self->camera[buffer].orthographic.size[1];
|
||||
|
||||
rendererPosition[0] += (self->camera[buffer].orthographic.size[0] / 2) * (1 - self->camera[buffer].zoom);
|
||||
rendererPosition[1] += (self->camera[buffer].orthographic.size[1] / 2) * (1 - self->camera[buffer].zoom);
|
||||
|
||||
rendererPosition[0] += self->camera[buffer].position[0];
|
||||
rendererPosition[1] += self->camera[buffer].position[1];
|
||||
|
||||
}
|
55
src/engine/renderer.h
Normal file
55
src/engine/renderer.h
Normal file
@ -0,0 +1,55 @@
|
||||
#pragma once
|
||||
|
||||
#include "camera.h"
|
||||
#include "glew.h"
|
||||
#include "window.h"
|
||||
#include "shader.h"
|
||||
#include "vao.h"
|
||||
#include "fbo.h"
|
||||
#include "rbo.h"
|
||||
#include "vbo.h"
|
||||
#include "vertexattribute.h"
|
||||
|
||||
#define RENDERER_BUFFER_COUNT RENDERER_BUFFER_CURSOR + 1
|
||||
typedef enum RendererBuffer
|
||||
{
|
||||
RENDERER_BUFFER_BACKGROUND,
|
||||
RENDERER_BUFFER_WORLD,
|
||||
RENDERER_BUFFER_UI,
|
||||
RENDERER_BUFFER_META,
|
||||
RENDERER_BUFFER_CURSOR
|
||||
} RendererBuffer;
|
||||
|
||||
typedef struct Renderer
|
||||
{
|
||||
SDL_GLContext glContext;
|
||||
Window* window;
|
||||
Camera camera[RENDERER_BUFFER_COUNT];
|
||||
ivec2 bufferSizes[RENDERER_BUFFER_COUNT];
|
||||
Texture fboTextures[RENDERER_BUFFER_COUNT];
|
||||
FBO fbos[RENDERER_BUFFER_COUNT];
|
||||
RBO rbos[RENDERER_BUFFER_COUNT];
|
||||
VBO vbo;
|
||||
VBO ebo;
|
||||
VAO vao;
|
||||
} Renderer;
|
||||
|
||||
void renderer_init(Renderer* self, Window* window, CameraType type, const ivec2* bufferSizes);
|
||||
void renderer_clear_color_set(Renderer* self, vec4 color);
|
||||
void renderer_clear(Renderer* self);
|
||||
void renderer_shader_use(Renderer* self, Shader* shader);
|
||||
void renderer_buffer_use(Renderer* self, RendererBuffer buffer);
|
||||
void renderer_buffer_init(Renderer* self, RendererBuffer buffer);
|
||||
void renderer_buffer_free(Renderer* self, RendererBuffer buffer);
|
||||
void renderer_free(Renderer* self);
|
||||
void renderer_update(Renderer* self);
|
||||
void renderer_present(Renderer* self);
|
||||
void renderer_buffer_unbind(void);
|
||||
|
||||
void renderer_buffer_position_from_window_position
|
||||
(
|
||||
Renderer* self,
|
||||
RendererBuffer buffer,
|
||||
vec2 windowPosition,
|
||||
vec2 rendererPosition
|
||||
);
|
63
src/engine/sdl.c
Normal file
63
src/engine/sdl.c
Normal file
@ -0,0 +1,63 @@
|
||||
#include "sdl.h"
|
||||
|
||||
/* Initializes SDL. */
|
||||
void
|
||||
sdl_init(void)
|
||||
{
|
||||
if (SDL_INIT_VIDEO < 0)
|
||||
{
|
||||
printf(STRING_SDL2_VIDEO_ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
printf(STRING_SDL2_VIDEO_INIT);
|
||||
|
||||
if (SDL_INIT_TIMER < 0)
|
||||
{
|
||||
printf(STRING_SDL2_TIMER_ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
printf(STRING_SDL2_TIMER_INIT);
|
||||
|
||||
if (IMG_Init(IMG_FLAGS) < 0)
|
||||
{
|
||||
printf(STRING_SDL_IMAGE_ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
printf(STRING_SDL_IMAGE_INIT);
|
||||
|
||||
if (TTF_Init() < 0)
|
||||
{
|
||||
printf(STRING_SDL_TTF_ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
printf(STRING_SDL_TTF_INIT);
|
||||
|
||||
if (Mix_OpenAudio(MIX_FREQUENCY, MIX_DEFAULT_FORMAT, MIX_CHANNELS, MIX_SAMPLE_SIZE) < 0)
|
||||
{
|
||||
printf(STRING_SDL_MIXER_ERROR);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
else
|
||||
printf(STRING_SDL_MIXER_INIT);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
|
||||
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
}
|
||||
|
||||
/* Quits SDL. */
|
||||
void
|
||||
sdl_quit(void)
|
||||
{
|
||||
printf(STRING_SDL2_QUIT);
|
||||
SDL_Quit();
|
||||
}
|
29
src/engine/sdl.h
Normal file
29
src/engine/sdl.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#define SDL_MAIN_HANDLED
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include "../COMMON.h"
|
||||
|
||||
#define STRING_SDL2_VIDEO_ERROR "[ERROR] Unable to initialize SDL2 (Video): %s\n", SDL_GetError()
|
||||
#define STRING_SDL2_VIDEO_INIT "[INFO] Initialized SDL2 (Video)\n"
|
||||
#define STRING_SDL2_TIMER_ERROR "[ERROR] Unable to initialize SDL2 (Timer): %s\n", SDL_GetError()
|
||||
#define STRING_SDL2_TIMER_INIT "[INFO] Initialized SDL2 (Timer)\n"
|
||||
#define STRING_SDL_IMAGE_ERROR "[ERROR] Unable to initialize SDL_image: %s\n", IMG_GetError()
|
||||
#define STRING_SDL_IMAGE_INIT "[INFO] Initialized SDL_image\n"
|
||||
#define STRING_SDL_MIXER_ERROR "[ERROR] Unable to initialize SDL_mixer: %s\n", Mix_GetError()
|
||||
#define STRING_SDL_MIXER_INIT "[INFO] Initialized SDL_mixer\n"
|
||||
#define STRING_SDL_TTF_ERROR "[ERROR] Unable to initialize SDL_ttf: %s\n", TTF_GetError()
|
||||
#define STRING_SDL_TTF_INIT "[INFO] Initialized SDL_ttf\n"
|
||||
#define STRING_SDL2_QUIT "[INFO] Quitting SDL2\n"
|
||||
|
||||
#define MIX_FREQUENCY 44100
|
||||
#define MIX_SAMPLE_SIZE 2048
|
||||
|
||||
#define IMG_FLAGS (IMG_INIT_PNG)
|
||||
|
||||
void sdl_init(void);
|
||||
void sdl_quit(void);
|
128
src/engine/shader.c
Normal file
128
src/engine/shader.c
Normal file
@ -0,0 +1,128 @@
|
||||
#include "shader.h"
|
||||
|
||||
static bool _shader_compile(u32 handle);
|
||||
|
||||
static bool
|
||||
_shader_compile(u32 handle)
|
||||
{
|
||||
s32 success;
|
||||
char log[SHADER_LOG_BUFFER_SIZE];
|
||||
|
||||
glCompileShader(handle);
|
||||
glGetShaderiv(handle, GL_COMPILE_STATUS, &success);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
glGetShaderInfoLog(handle, SHADER_LOG_BUFFER_SIZE, NULL, log);
|
||||
printf(STRING_SHADER_COMPILE_ERROR, handle, log);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
printf(STRING_SHADER_COMPILE_SUCCESS, handle);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
shader_init(Shader* self, const char* vertex, const char* fragment)
|
||||
{
|
||||
GLuint vertexHandle;
|
||||
GLuint fragmentHandle;
|
||||
|
||||
memset(self, '\0', sizeof(struct Shader));
|
||||
|
||||
vertexHandle = glCreateShader(GL_VERTEX_SHADER);
|
||||
fragmentHandle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
glShaderSource(vertexHandle, 1, &vertex, NULL);
|
||||
glShaderSource(fragmentHandle, 1, &fragment, NULL);
|
||||
|
||||
if (!_shader_compile(vertexHandle) || !_shader_compile(fragmentHandle))
|
||||
return false;
|
||||
|
||||
self->handle = glCreateProgram();
|
||||
|
||||
glAttachShader(self->handle, vertexHandle);
|
||||
glAttachShader(self->handle, fragmentHandle);
|
||||
|
||||
glLinkProgram(self->handle);
|
||||
|
||||
glDeleteShader(vertexHandle);
|
||||
glDeleteShader(fragmentHandle);
|
||||
|
||||
self->isInit = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
shader_use(Shader* self)
|
||||
{
|
||||
glUseProgram(self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
shader_free(Shader* self)
|
||||
{
|
||||
if (self->isInit)
|
||||
{
|
||||
glDeleteProgram(self->handle);
|
||||
self->isInit = false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
shader_uniform_s32_set(Shader* self, const char* name, s32 value)
|
||||
{
|
||||
glUniform1i(glGetUniformLocation(self->handle, name), value);
|
||||
}
|
||||
|
||||
void
|
||||
shader_uniform_u32_set(Shader* self, const char* name, u32 value)
|
||||
{
|
||||
glUniform1ui(glGetUniformLocation(self->handle, name), value);
|
||||
}
|
||||
|
||||
void
|
||||
shader_uniform_bool_set(Shader* self, const char* name, bool value)
|
||||
{
|
||||
glUniform1i(glGetUniformLocation(self->handle, name), value);
|
||||
}
|
||||
|
||||
void
|
||||
shader_uniform_f32_set(Shader* self, const char* name, f32 value)
|
||||
{
|
||||
glUniform1f(glGetUniformLocation(self->handle, name), value);
|
||||
}
|
||||
|
||||
void
|
||||
shader_uniform_vec2_set(Shader* self, const char* name, vec2 value)
|
||||
{
|
||||
glUniform2fv(glGetUniformLocation(self->handle, name), 1, value);
|
||||
}
|
||||
|
||||
void
|
||||
shader_uniform_vec3_set(Shader* self, const char* name, vec3 value)
|
||||
{
|
||||
glUniform3fv(glGetUniformLocation(self->handle, name), 1, value);
|
||||
}
|
||||
|
||||
void
|
||||
shader_uniform_vec4_set(Shader* self, const char* name, vec4 value)
|
||||
{
|
||||
glUniform4fv(glGetUniformLocation(self->handle, name), 1, value);
|
||||
}
|
||||
|
||||
void
|
||||
shader_uniform_mat4_set(Shader* self, const char* name, mat4 value)
|
||||
{
|
||||
glUniformMatrix4fv(glGetUniformLocation(self->handle, name), 1, GL_FALSE, (f32*)value);
|
||||
}
|
||||
|
||||
void
|
||||
shader_uniform_texture_set(Shader* self, const char* name, Texture* texture, s32 index)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + index);
|
||||
texture_bind(texture);
|
||||
glUniform1i(glGetUniformLocation(self->handle, name), index);
|
||||
}
|
30
src/engine/shader.h
Normal file
30
src/engine/shader.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "texture.h"
|
||||
|
||||
#define SHADER_LOG_BUFFER_SIZE 1024
|
||||
|
||||
#define STRING_SHADER_COMPILE_SUCCESS "[INFO] Compiled shader: #%i\n"
|
||||
#define STRING_SHADER_COMPILE_ERROR "[ERROR] Unable to compile shader: #%i, %s\n"
|
||||
|
||||
typedef struct Shader
|
||||
{
|
||||
GLuint handle;
|
||||
bool isInit;
|
||||
} Shader;
|
||||
|
||||
bool shader_init(struct Shader* self, const char* vertex, const char* fragment);
|
||||
void shader_use(struct Shader* self);
|
||||
void shader_free(struct Shader* self);
|
||||
void shader_uniform_f32_set(struct Shader* self, const char* name, f32 value);
|
||||
void shader_uniform_s32_set(struct Shader* self, const char* name, s32 value);
|
||||
void shader_uniform_u32_set(struct Shader* self, const char* name, u32 value);
|
||||
void shader_uniform_bool_set(struct Shader* self, const char* name, bool value);
|
||||
void shader_uniform_mat4_set(struct Shader* self, const char* name, mat4 value);
|
||||
void shader_uniform_vec2_set(struct Shader* self, const char* name, vec2 value);
|
||||
void shader_uniform_vec3_set(struct Shader* self, const char* name, vec3 value);
|
||||
void shader_uniform_vec4_set(struct Shader* self, const char* name, vec4 value);
|
||||
void shader_uniform_texture_set(struct Shader* self, const char* name, Texture* texture, s32 index);
|
45
src/engine/sound.c
Normal file
45
src/engine/sound.c
Normal file
@ -0,0 +1,45 @@
|
||||
#include "sound.h"
|
||||
|
||||
/* Initializes a sound. */
|
||||
bool
|
||||
sound_init(Sound* self, const char* path)
|
||||
{
|
||||
self->chunk = Mix_LoadWAV(path);
|
||||
|
||||
if (!self->chunk)
|
||||
{
|
||||
printf(STRING_SDL_MIXER_SOUND_ERROR, path, Mix_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
printf(STRING_SDL_MIXER_SOUND_SUCCESS, path);
|
||||
|
||||
self->isInit = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Frees a sound. */
|
||||
void
|
||||
sound_free(Sound* self)
|
||||
{
|
||||
if (self->isInit)
|
||||
{
|
||||
Mix_FreeChunk(self->chunk);
|
||||
self->isInit = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Plays a sound, specifying a channel. */
|
||||
void
|
||||
sound_play(Sound* self)
|
||||
{
|
||||
Mix_PlayChannel(-1, self->chunk, 0);
|
||||
}
|
||||
|
||||
/* Stops a channel. */
|
||||
void
|
||||
sound_channel_stop(s32 channel)
|
||||
{
|
||||
Mix_HaltChannel(channel);
|
||||
}
|
21
src/engine/sound.h
Normal file
21
src/engine/sound.h
Normal file
@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL_mixer.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
#define SOUND_NO_PRIORITY -1
|
||||
|
||||
#define STRING_SDL_MIXER_SOUND_SUCCESS "[INFO] Loaded sound: %s\n"
|
||||
#define STRING_SDL_MIXER_SOUND_ERROR "[ERROR] Unable to load sound: %s | %s\n"
|
||||
|
||||
typedef struct Sound
|
||||
{
|
||||
Mix_Chunk* chunk;
|
||||
bool isInit;
|
||||
} Sound;
|
||||
|
||||
bool sound_init(Sound* self, const char* path);
|
||||
void sound_free(Sound* self);
|
||||
void sound_play(Sound* self);
|
||||
void sound_channel_stop(s32 channel);
|
17
src/engine/surface.c
Normal file
17
src/engine/surface.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include "surface.h"
|
||||
|
||||
void
|
||||
surface_rgba_init(SDL_Surface** self, ivec2 size)
|
||||
{
|
||||
*self = SDL_CreateRGBSurface
|
||||
(
|
||||
0,
|
||||
size[0],
|
||||
size[1],
|
||||
32,
|
||||
0xFF000000,
|
||||
0x00FF0000,
|
||||
0x0000FF00,
|
||||
0x000000FF
|
||||
);
|
||||
}
|
7
src/engine/surface.h
Normal file
7
src/engine/surface.h
Normal file
@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
void surface_rgba_init(SDL_Surface** self, ivec2 size);
|
84
src/engine/texture.c
Normal file
84
src/engine/texture.c
Normal file
@ -0,0 +1,84 @@
|
||||
#include "texture.h"
|
||||
|
||||
void
|
||||
texture_surface_init(Texture* self, SDL_Surface* surface)
|
||||
{
|
||||
ivec2 size;
|
||||
|
||||
size[0] = surface->w;
|
||||
size[1] = surface->h;
|
||||
|
||||
texture_init(self, size, surface->pixels);
|
||||
}
|
||||
|
||||
bool
|
||||
texture_from_path_init(Texture* self, const char* path)
|
||||
{
|
||||
SDL_Surface* surface;
|
||||
|
||||
memset(self, '\0', sizeof(Texture));
|
||||
|
||||
surface = IMG_Load(path);
|
||||
|
||||
if (!surface)
|
||||
{
|
||||
printf(STRING_SDL_IMAGE_LOAD_ERROR, path, IMG_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
printf(STRING_SDL_IMAGE_LOAD_SUCCESS, path);
|
||||
|
||||
texture_surface_init(self, surface);
|
||||
|
||||
SDL_FreeSurface(surface);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
texture_init(Texture* self, ivec2 size, void* data)
|
||||
{
|
||||
glGenTextures(1, &self->handle);
|
||||
|
||||
texture_bind(self);
|
||||
|
||||
glm_ivec2_copy(size, self->size);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, self->size[0], self->size[1], 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||
|
||||
texture_parameter_set(GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
texture_parameter_set(GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
texture_parameter_set(GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
texture_parameter_set(GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
self->isInit = true;
|
||||
|
||||
texture_unbind();
|
||||
}
|
||||
|
||||
void
|
||||
texture_bind(Texture* self)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
texture_parameter_set(GLenum pname, GLint parameter)
|
||||
{
|
||||
glTexParameteri(GL_TEXTURE_2D, pname, parameter);
|
||||
}
|
||||
|
||||
void
|
||||
texture_unbind(void)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
void
|
||||
texture_free(Texture* self)
|
||||
{
|
||||
glDeleteTextures(1, &self->handle);
|
||||
memset(self, '\0', sizeof(Texture));
|
||||
}
|
26
src/engine/texture.h
Normal file
26
src/engine/texture.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_image.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
#define STRING_SDL_IMAGE_LOAD_ERROR "[ERROR] Unable to load image: %s | %s\n"
|
||||
#define STRING_SDL_IMAGE_LOAD_SUCCESS "[INFO] Loaded image: %s\n"
|
||||
|
||||
typedef struct Texture
|
||||
{
|
||||
GLuint handle;
|
||||
ivec2 size;
|
||||
bool isInit;
|
||||
} Texture;
|
||||
|
||||
bool texture_from_path_init(Texture* self, const char* path);
|
||||
void texture_init(Texture* self, ivec2 size, void* data);
|
||||
void texture_surface_init(Texture* self, SDL_Surface* surface);
|
||||
void texture_parameter_set(GLenum pname, GLint parameter);
|
||||
void texture_bind(Texture* self);
|
||||
void texture_unbind(void);
|
||||
void texture_free(Texture* self);
|
10
src/engine/tick.c
Normal file
10
src/engine/tick.c
Normal file
@ -0,0 +1,10 @@
|
||||
#include "tick.h"
|
||||
|
||||
void
|
||||
tick_update(Tick* self)
|
||||
{
|
||||
self->previous = self->current;
|
||||
self->current = SDL_GetTicks64();
|
||||
self->delta = self->current - self->previous;
|
||||
self->cumulative += self->delta;
|
||||
}
|
14
src/engine/tick.h
Normal file
14
src/engine/tick.h
Normal file
@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include "../COMMON.h"
|
||||
|
||||
typedef struct Tick
|
||||
{
|
||||
u64 current;
|
||||
u64 previous;
|
||||
u64 delta;
|
||||
u64 cumulative;
|
||||
} Tick;
|
||||
|
||||
void tick_update(Tick* self);
|
9
src/engine/time.c
Normal file
9
src/engine/time.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include "time.h"
|
||||
|
||||
void
|
||||
time_formatted_get(u32 value, u32* minutes, u32* seconds, u32* milliseconds)
|
||||
{
|
||||
*minutes = (u32)((f32)value / MINUTE_TICK);
|
||||
*seconds = (u32)((f32)value / SECOND_TICK) % SECOND_TICK;
|
||||
*milliseconds = (((f32)value - ((*minutes * MINUTE_TICK) + (*seconds * SECOND_TICK))) / SECOND_TICK) * 100;
|
||||
}
|
5
src/engine/time.h
Normal file
5
src/engine/time.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
void time_formatted_get(u32 value, u32* minutes, u32* seconds, u32* milliseconds);
|
26
src/engine/vao.c
Normal file
26
src/engine/vao.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include "vao.h"
|
||||
|
||||
void
|
||||
vao_init(VAO* self)
|
||||
{
|
||||
glGenVertexArrays(1, &self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
vao_bind(VAO* self)
|
||||
{
|
||||
glBindVertexArray(self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
vao_unbind(void)
|
||||
{
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void
|
||||
vao_free(VAO* self)
|
||||
{
|
||||
glDeleteVertexArrays(1, &self->handle);
|
||||
memset(self, '\0', sizeof(VAO));
|
||||
}
|
16
src/engine/vao.h
Normal file
16
src/engine/vao.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
typedef struct VAO
|
||||
{
|
||||
GLuint handle;
|
||||
} VAO;
|
||||
|
||||
void vao_init(VAO* self);
|
||||
void vao_bind(VAO* self);
|
||||
void vao_unbind(void);
|
||||
void vao_free(VAO* self);
|
29
src/engine/vbo.c
Normal file
29
src/engine/vbo.c
Normal file
@ -0,0 +1,29 @@
|
||||
#include "vbo.h"
|
||||
|
||||
void
|
||||
vbo_init(VBO* self, GLint type, bool isDynamic)
|
||||
{
|
||||
self->isDynamic = isDynamic;
|
||||
self->type = type;
|
||||
|
||||
glGenBuffers(1, &self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
vbo_bind(VBO* self)
|
||||
{
|
||||
glBindBuffer(self->type, self->handle);
|
||||
}
|
||||
|
||||
void
|
||||
vbo_free(VBO* self)
|
||||
{
|
||||
glDeleteBuffers(1, &self->handle);
|
||||
memset(self, '\0', sizeof(VBO));
|
||||
}
|
||||
|
||||
void
|
||||
vbo_buffer(VBO* self, size_t size, void* data)
|
||||
{
|
||||
glBufferData(self->type, size, data, self->isDynamic ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW);
|
||||
}
|
18
src/engine/vbo.h
Normal file
18
src/engine/vbo.h
Normal file
@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
typedef struct VBO
|
||||
{
|
||||
GLuint handle;
|
||||
GLint type;
|
||||
bool isDynamic;
|
||||
} VBO;
|
||||
|
||||
void vbo_buffer(VBO* self, size_t size, void* data);
|
||||
void vbo_bind(VBO* self);
|
||||
void vbo_free(VBO* self);
|
||||
void vbo_init(VBO* self, GLint type, bool isDynamic);
|
192
src/engine/vector.c
Normal file
192
src/engine/vector.c
Normal file
@ -0,0 +1,192 @@
|
||||
#include "vector.h"
|
||||
|
||||
static void _vector_realloc(Vector* self);
|
||||
static void _vector_forward(Vector* self, s32 index);
|
||||
static void _vector_backward(Vector* self, s32 index);
|
||||
|
||||
static void
|
||||
_vector_realloc(Vector* self)
|
||||
{
|
||||
if (self->count == 0)
|
||||
{
|
||||
self->data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
self->data = realloc(self->data, vector_size_get(self));
|
||||
}
|
||||
|
||||
static void
|
||||
_vector_forward(Vector* self, s32 index)
|
||||
{
|
||||
s32 length;
|
||||
|
||||
length = ((self->count - 1) - index);
|
||||
|
||||
for (s32 i = 0; i < length; i++)
|
||||
{
|
||||
u8* data;
|
||||
u8* nextData;
|
||||
s32 currentIndex;
|
||||
|
||||
currentIndex = index + i;
|
||||
|
||||
data = (u8*)self->data + (currentIndex * self->itemSize);
|
||||
nextData = data + self->itemSize;
|
||||
|
||||
memcpy((void*)data, (void*)nextData, self->itemSize);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
_vector_backward(Vector* self, s32 index)
|
||||
{
|
||||
s32 length;
|
||||
|
||||
if (self->count == 0)
|
||||
return;
|
||||
|
||||
length = ((self->count - 1) - index);
|
||||
|
||||
for (s32 i = 0; i < length; i++)
|
||||
{
|
||||
u8* data;
|
||||
u8* prevData;
|
||||
s32 index;
|
||||
|
||||
index = (self->count - 1) - i;
|
||||
|
||||
data = (u8*)self->data + (index * self->itemSize);
|
||||
prevData = (u8*)data - self->itemSize;
|
||||
|
||||
memcpy((void*)data, (void*)prevData, self->itemSize);
|
||||
}
|
||||
}
|
||||
|
||||
size_t
|
||||
vector_size_get(Vector* self)
|
||||
{
|
||||
return self->count * self->itemSize;
|
||||
}
|
||||
|
||||
void
|
||||
vector_init(Vector* self, size_t size)
|
||||
{
|
||||
memset(self, '\0', sizeof(Vector));
|
||||
|
||||
self->itemSize = size;
|
||||
|
||||
_vector_realloc(self);
|
||||
|
||||
memset(self->data, '\0', vector_size_get(self));
|
||||
}
|
||||
|
||||
void
|
||||
vector_free(Vector* self)
|
||||
{
|
||||
if (self->data)
|
||||
free(self->data);
|
||||
|
||||
self->count = 0;
|
||||
}
|
||||
|
||||
void*
|
||||
vector_push(Vector* self, void* data)
|
||||
{
|
||||
u8* pointer;
|
||||
|
||||
self->count++;
|
||||
|
||||
_vector_realloc(self);
|
||||
|
||||
pointer = (u8*)self->data + (vector_size_get(self) - self->itemSize);
|
||||
|
||||
if (data)
|
||||
memcpy((void*)pointer, data, self->itemSize);
|
||||
else
|
||||
memset((void*)pointer, '\0', self->itemSize);
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
void
|
||||
vector_pop(Vector* self)
|
||||
{
|
||||
self->count--;
|
||||
|
||||
_vector_realloc(self);
|
||||
}
|
||||
|
||||
void
|
||||
vector_clear(Vector* self)
|
||||
{
|
||||
self->count = 0;
|
||||
|
||||
_vector_realloc(self);
|
||||
}
|
||||
|
||||
void*
|
||||
vector_insert(Vector* self, void* data, s32 index)
|
||||
{
|
||||
u8* pointer;
|
||||
|
||||
_vector_backward(self, index);
|
||||
|
||||
self->count++;
|
||||
|
||||
_vector_realloc(self);
|
||||
|
||||
pointer = (u8*)self->data + (index * self->itemSize);
|
||||
|
||||
memcpy((void*)pointer, data, self->itemSize);
|
||||
|
||||
return pointer;
|
||||
}
|
||||
|
||||
void
|
||||
vector_remove(Vector* self, s32 index)
|
||||
{
|
||||
_vector_forward(self, index);
|
||||
|
||||
vector_pop(self);
|
||||
}
|
||||
|
||||
void*
|
||||
vector_get(Vector* self, s32 index)
|
||||
{
|
||||
return (void*)((u8*)self->data + (index * self->itemSize));
|
||||
}
|
||||
|
||||
s32
|
||||
vector_index_get(Vector* self, void* data)
|
||||
{
|
||||
s32 index;
|
||||
|
||||
index = ((u8*)data - (u8*)self->data) / self->itemSize;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void
|
||||
vector_remove_from_data(Vector* self, void* data)
|
||||
{
|
||||
for (s32 i = 0; i < (s32)self->count; i++)
|
||||
{
|
||||
void* pointer;
|
||||
s32 result;
|
||||
|
||||
pointer = vector_get(self, i);
|
||||
|
||||
result = memcmp(pointer, data, self->itemSize);
|
||||
|
||||
if (result == 0)
|
||||
vector_remove(self, i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
vector_sort(Vector* self, SortCompareFunction function)
|
||||
{
|
||||
qsort(self->data, self->count, self->itemSize, function);
|
||||
}
|
26
src/engine/vector.h
Normal file
26
src/engine/vector.h
Normal file
@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
typedef struct Vector
|
||||
{
|
||||
u32 count;
|
||||
u32 limit;
|
||||
size_t itemSize;
|
||||
void* data;
|
||||
} Vector;
|
||||
|
||||
s32 vector_index_get(Vector* self, void* data);
|
||||
size_t vector_size_get(Vector* self);
|
||||
void vector_free(Vector* self);
|
||||
void vector_init(Vector* self, size_t size);
|
||||
void vector_pop(Vector* self);
|
||||
void vector_remove(Vector* self, s32 index);
|
||||
void vector_clear(Vector* self);
|
||||
void vector_remove_from_data(Vector* self, void* data);
|
||||
void* vector_get(Vector* self, s32 index);
|
||||
void* vector_insert(Vector* self, void* data, s32 index);
|
||||
void* vector_push(Vector* self, void* data);
|
||||
void vector_print(Vector* self);
|
||||
void vector_sort(Vector* self, SortCompareFunction function);
|
||||
void vector_remove_from_data(Vector* self, void* data);
|
24
src/engine/vertexattribute.c
Normal file
24
src/engine/vertexattribute.c
Normal file
@ -0,0 +1,24 @@
|
||||
#include "vertexattribute.h"
|
||||
|
||||
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);
|
||||
}
|
8
src/engine/vertexattribute.h
Normal file
8
src/engine/vertexattribute.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GL/gl.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
void vertex_attribute_set(GLuint index, GLint size, GLenum type, GLsizei stride, size_t offset);
|
49
src/engine/window.c
Normal file
49
src/engine/window.c
Normal file
@ -0,0 +1,49 @@
|
||||
#include "window.h"
|
||||
|
||||
void
|
||||
window_init(Window* self, char* name, ivec2 size, u32 flags)
|
||||
{
|
||||
memset(self, '\0', sizeof(Window));
|
||||
|
||||
glm_ivec2_copy(size, self->expectedSize);
|
||||
|
||||
self->sdl = SDL_CreateWindow
|
||||
(
|
||||
name,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
SDL_WINDOWPOS_UNDEFINED,
|
||||
size[0],
|
||||
size[1],
|
||||
flags
|
||||
);
|
||||
|
||||
SDL_ShowCursor(SDL_DISABLE);
|
||||
}
|
||||
|
||||
void
|
||||
window_ivec4_get(struct Window* self, ivec4 value)
|
||||
{
|
||||
ivec2 size;
|
||||
|
||||
window_size_get(self, size);
|
||||
|
||||
value[0] = 0;
|
||||
value[1] = 0;
|
||||
value[2] = size[0];
|
||||
value[3] = size[1];
|
||||
}
|
||||
|
||||
void
|
||||
window_size_get(Window* self, ivec2 size)
|
||||
{
|
||||
SDL_GetWindowSize(self->sdl, &size[0], &size[1]);
|
||||
}
|
||||
|
||||
void
|
||||
window_free(Window* self)
|
||||
{
|
||||
SDL_DestroyWindow(self->sdl);
|
||||
|
||||
memset(self, '\0', sizeof(Window));
|
||||
}
|
||||
|
17
src/engine/window.h
Normal file
17
src/engine/window.h
Normal file
@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "../COMMON.h"
|
||||
|
||||
typedef struct Window
|
||||
{
|
||||
SDL_Window* sdl;
|
||||
ivec2 expectedSize;
|
||||
} Window;
|
||||
|
||||
void window_init(Window* self, char* name, ivec2 size, u32 flags);
|
||||
void window_free(Window* self);
|
||||
void window_ivec4_get(Window* self, ivec4 size);
|
||||
void window_size_get(Window* self, ivec2 size);
|
||||
|
22
src/game/GAME_COMMON.h
Normal file
22
src/game/GAME_COMMON.h
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "state/state.h"
|
||||
|
||||
#include "../engine/tick.h"
|
||||
#include "../engine/sdl.h"
|
||||
|
||||
#include "render/buffer.h"
|
||||
|
||||
typedef struct Game
|
||||
{
|
||||
ECS ecs;
|
||||
Input input;
|
||||
Control control;
|
||||
Renderer renderer;
|
||||
Resources resources;
|
||||
State state;
|
||||
Tick tick;
|
||||
Window window;
|
||||
Postprocessing postprocessing[RENDERER_BUFFER_COUNT];
|
||||
bool isPaused;
|
||||
} Game;
|
66
src/game/ecs/ECS_COMMON.h
Normal file
66
src/game/ecs/ECS_COMMON.h
Normal file
@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include "component/COMPONENT_COMMON.h"
|
||||
|
||||
#include "../../engine/vector.h"
|
||||
|
||||
#define ECS_FUNCTION_COUNT ECS_FUNCTION_DRAW + 1
|
||||
typedef enum ECSFunctionType
|
||||
{
|
||||
ECS_FUNCTION_ADD,
|
||||
ECS_FUNCTION_DELETE,
|
||||
ECS_FUNCTION_TICK,
|
||||
ECS_FUNCTION_UPDATE,
|
||||
ECS_FUNCTION_DRAW
|
||||
} ECSFunctionType;
|
||||
|
||||
typedef struct ECS ECS;
|
||||
typedef struct Control Control;
|
||||
typedef struct Input Input;
|
||||
typedef struct Renderer Renderer;
|
||||
typedef struct Postprocessing Postprocessing;
|
||||
typedef struct Resources Resources;
|
||||
typedef u32 EntityID;
|
||||
|
||||
typedef void (*ECSFunction)(void*, ECS*);
|
||||
|
||||
typedef struct ECSSystem
|
||||
{
|
||||
ECSFunction functions[ECS_FUNCTION_COUNT];
|
||||
} ECSSystem;
|
||||
|
||||
typedef struct Component
|
||||
{
|
||||
EntityID id;
|
||||
bool isDisabled;
|
||||
bool isFunctionDisabled[ECS_FUNCTION_COUNT];
|
||||
} Component;
|
||||
|
||||
typedef struct ComponentInfo
|
||||
{
|
||||
ECSSystem system;
|
||||
ComponentType type;
|
||||
size_t size;
|
||||
} ComponentInfo;
|
||||
|
||||
typedef struct ComponentList
|
||||
{
|
||||
ECS* ecs;
|
||||
ECSSystem system;
|
||||
ComponentType type;
|
||||
Vector components;
|
||||
} ComponentList;
|
||||
|
||||
typedef struct ECS
|
||||
{
|
||||
Input* input;
|
||||
Control* control;
|
||||
Renderer* renderer;
|
||||
Resources* resources;
|
||||
Postprocessing* postprocessing;
|
||||
ComponentList lists[COMPONENT_COUNT];
|
||||
bool isFunctionDisabled[ECS_FUNCTION_COUNT];
|
||||
bool isLog;
|
||||
EntityID nextID;
|
||||
} ECS;
|
||||
|
52
src/game/ecs/component/COMPONENT_COMMON.h
Normal file
52
src/game/ecs/component/COMPONENT_COMMON.h
Normal file
@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../../COMMON.h"
|
||||
|
||||
#define COMPONENT_COUNT COMPONENT_PULSATE + 1
|
||||
typedef enum ComponentType
|
||||
{
|
||||
/* Utility */
|
||||
COMPONENT_TIMER,
|
||||
COMPONENT_COUNTER,
|
||||
COMPONENT_DELETE_ON_TIMER,
|
||||
/* Physics */
|
||||
COMPONENT_PHYSICS,
|
||||
COMPONENT_COPY_MOUSE_POSITION,
|
||||
COMPONENT_CIRCLE_COLLIDER,
|
||||
/* Game */
|
||||
COMPONENT_GAME_OBJECT,
|
||||
COMPONENT_PLANE_OBJECT,
|
||||
COMPONENT_WORLD_OBJECT,
|
||||
COMPONENT_SOLID,
|
||||
COMPONENT_LEVITATE,
|
||||
COMPONENT_COLLIDE_SLOW,
|
||||
COMPONENT_COLLECTIBLE,
|
||||
COMPONENT_COLLECT,
|
||||
COMPONENT_HOMING,
|
||||
COMPONENT_FOOD,
|
||||
COMPONENT_THRESHOLD,
|
||||
COMPONENT_TAKE_FOOD,
|
||||
COMPONENT_STAGE,
|
||||
COMPONENT_STAMINA,
|
||||
COMPONENT_POWER,
|
||||
COMPONENT_PLAYER_CONTROL,
|
||||
/* Animation */
|
||||
COMPONENT_ANIMATION,
|
||||
COMPONENT_ANIMATION_PLAYER,
|
||||
COMPONENT_ANIMATION_TARGET,
|
||||
/* UI */
|
||||
COMPONENT_BUTTON,
|
||||
/* Visual */
|
||||
COMPONENT_DROP_SHADOW,
|
||||
COMPONENT_TEXTURE_QUAD,
|
||||
COMPONENT_TEXT,
|
||||
COMPONENT_DIALOGUE,
|
||||
COMPONENT_VALUE_TEXT,
|
||||
COMPONENT_ATLAS,
|
||||
COMPONENT_CAMERA_FOCUS,
|
||||
COMPONENT_COLOR_CHANGE,
|
||||
COMPONENT_COLOR_MATCH,
|
||||
COMPONENT_SCALE_VALUE,
|
||||
COMPONENT_ROTATE,
|
||||
COMPONENT_PULSATE
|
||||
} ComponentType;
|
87
src/game/ecs/component/animation/component_animation.c
Normal file
87
src/game/ecs/component/animation/component_animation.c
Normal file
@ -0,0 +1,87 @@
|
||||
#include "component_animation.h"
|
||||
|
||||
void _component_animation_frame_set(ComponentAnimation* self, ECS* ecs);
|
||||
|
||||
void
|
||||
_component_animation_frame_set(ComponentAnimation* self, ECS* ecs)
|
||||
{
|
||||
ComponentTimer* timer;
|
||||
|
||||
if (self->isFinished)
|
||||
return;
|
||||
|
||||
timer = ecs_component_get(ecs, COMPONENT_TIMER, self->timer);
|
||||
|
||||
if (timer->isFinished)
|
||||
{
|
||||
ComponentAtlas* atlas;
|
||||
|
||||
if (self->frame >= self->animation.count)
|
||||
{
|
||||
if (!self->animation.isLoop)
|
||||
{
|
||||
self->isFinished = true;
|
||||
return;
|
||||
}
|
||||
|
||||
self->frame = 0;
|
||||
}
|
||||
|
||||
atlas = ecs_component_get(ecs, COMPONENT_ATLAS, self->component.id);
|
||||
|
||||
atlas->index = self->animation.frameIndices[self->frame];
|
||||
|
||||
component_timer_init(timer, ecs, self->animation.length);
|
||||
|
||||
self->frame++;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
component_animation_add(ComponentAnimation* self, ECS* ecs)
|
||||
{
|
||||
ComponentTimer* timer;
|
||||
|
||||
self->timer = entity_timer_add(ecs, -1);
|
||||
|
||||
timer = ecs_component_get(ecs, COMPONENT_TIMER, self->timer);
|
||||
|
||||
timer->component.isDisabled = true;
|
||||
}
|
||||
|
||||
void
|
||||
component_animation_delete(ComponentAnimation* self, ECS* ecs)
|
||||
{
|
||||
ecs_entity_delete(ecs, self->timer);
|
||||
}
|
||||
|
||||
void
|
||||
component_animation_set(ComponentAnimation* self, ECS* ecs, Animation* animation)
|
||||
{
|
||||
ComponentTimer* timer;
|
||||
|
||||
timer = ecs_component_get(ecs, COMPONENT_TIMER, self->timer);
|
||||
|
||||
memcpy(&self->animation, animation, sizeof(Animation));
|
||||
|
||||
self->frame = 0;
|
||||
self->isFinished = false;
|
||||
|
||||
component_timer_init(timer, ecs, self->animation.length);
|
||||
timer->component.isDisabled = false;
|
||||
timer->isFinished = true;
|
||||
|
||||
_component_animation_frame_set(self, ecs);
|
||||
}
|
||||
|
||||
void
|
||||
component_animation_init(ComponentAnimation* self, ECS* ecs, Animation* animation)
|
||||
{
|
||||
component_animation_set(self, ecs, animation);
|
||||
}
|
||||
|
||||
void
|
||||
component_animation_tick(ComponentAnimation* self, ECS* ecs)
|
||||
{
|
||||
_component_animation_frame_set(self, ecs);
|
||||
}
|
44
src/game/ecs/component/animation/component_animation.h
Normal file
44
src/game/ecs/component/animation/component_animation.h
Normal file
@ -0,0 +1,44 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../entity/utility/entity_timer.h"
|
||||
#include "../../component/visual/component_atlas.h"
|
||||
|
||||
typedef struct Animation
|
||||
{
|
||||
u32* frameIndices;
|
||||
u32 count;
|
||||
u32 length;
|
||||
bool isLoop;
|
||||
} Animation;
|
||||
|
||||
typedef struct ComponentAnimation
|
||||
{
|
||||
Component component;
|
||||
EntityID timer;
|
||||
u32 frame;
|
||||
bool isFinished;
|
||||
Animation animation;
|
||||
} ComponentAnimation;
|
||||
|
||||
void component_animation_add(ComponentAnimation* self, ECS* ecs);
|
||||
void component_animation_delete(ComponentAnimation* self, ECS* ecs);
|
||||
void component_animation_tick(ComponentAnimation* self, ECS* ecs);
|
||||
void component_animation_set(ComponentAnimation* self, ECS* ecs, Animation* animation);
|
||||
void component_animation_init(ComponentAnimation* self, ECS* ecs, Animation* animation);
|
||||
|
||||
static const ComponentInfo COMPONENT_ANIMATION_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
(ECSFunction)component_animation_add,
|
||||
(ECSFunction)component_animation_delete,
|
||||
(ECSFunction)component_animation_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_ANIMATION,
|
||||
.size = sizeof(ComponentAnimation)
|
||||
};
|
@ -0,0 +1,87 @@
|
||||
#include "component_animation_player.h"
|
||||
|
||||
void _component_animation_player_set(ComponentAnimationPlayer* self, ECS* ecs, AnimationPlayerType type);
|
||||
void _component_animation_player_determine(ComponentAnimationPlayer* self, ECS* ecs);
|
||||
|
||||
void
|
||||
_component_animation_player_set(ComponentAnimationPlayer* self, ECS* ecs, AnimationPlayerType type)
|
||||
{
|
||||
ComponentAnimation* animation;
|
||||
|
||||
if (type == self->type)
|
||||
return;
|
||||
|
||||
self->type = type;
|
||||
|
||||
animation = ecs_component_get(ecs, COMPONENT_ANIMATION, self->component.id);
|
||||
|
||||
component_animation_set(animation, ecs, &ANIMATION_PLAYER_STRUCTS[type]);
|
||||
}
|
||||
|
||||
void
|
||||
_component_animation_player_determine(ComponentAnimationPlayer* self, ECS* ecs)
|
||||
{
|
||||
AnimationPlayerType type;
|
||||
ComponentWorldObject* worldObject;
|
||||
|
||||
worldObject = ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, self->component.id);
|
||||
|
||||
type = (AnimationPlayerType)(self->action + ((ANIMATION_PLAYER_ACTION_COUNT) * worldObject->direction));
|
||||
|
||||
_component_animation_player_set(self, ecs, type);
|
||||
}
|
||||
|
||||
void
|
||||
component_animation_player_init(ComponentAnimationPlayer* self, ECS* ecs, AnimationPlayerType type)
|
||||
{
|
||||
self->type = -1;
|
||||
self->action = ANIMATION_PLAYER_ACTION_IDLE;
|
||||
|
||||
_component_animation_player_set(self, ecs, type);
|
||||
}
|
||||
|
||||
void
|
||||
component_animation_player_tick(ComponentAnimationPlayer* self, ECS* ecs)
|
||||
{
|
||||
ComponentWorldObject* worldObject;
|
||||
ComponentPlayerControl* playerControl;
|
||||
ComponentPhysics* physics;
|
||||
ComponentAnimation* animation;
|
||||
ComponentTimer* animationTimer;
|
||||
f32 nextPositionDistance;
|
||||
s32 newTimer;
|
||||
|
||||
worldObject = ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, self->component.id);
|
||||
|
||||
if (worldObject->isAirborne && self->action == ANIMATION_PLAYER_ACTION_LUNGE)
|
||||
return;
|
||||
|
||||
playerControl = ecs_component_get(ecs, COMPONENT_PLAYER_CONTROL, self->component.id);
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
|
||||
self->action = ANIMATION_PLAYER_ACTION_IDLE;
|
||||
|
||||
if (playerControl->isLunge)
|
||||
{
|
||||
self->action = ANIMATION_PLAYER_ACTION_LUNGE;
|
||||
sound_play(&ecs->resources->sounds[SOUND_LUNGE + RANDOM_S32(0, SOUND_LUNGE_COUNT - 1)]);
|
||||
}
|
||||
else if (physics->isMoving)
|
||||
{
|
||||
self->action = ANIMATION_PLAYER_ACTION_RUN;
|
||||
|
||||
animation = ecs_component_get(ecs, COMPONENT_ANIMATION, self->component.id);
|
||||
animationTimer = ecs_component_get(ecs, COMPONENT_TIMER, animation->timer);
|
||||
|
||||
nextPositionDistance = component_physics_next_position_distance_get(physics, ecs);
|
||||
|
||||
newTimer = ANIMATION_PLAYER_RUN_TIMER - (s32)((nextPositionDistance / ANIMATION_PLAYER_RUN_DISTANCE_MAX) * ANIMATION_PLAYER_RUN_TIMER);
|
||||
|
||||
newTimer = MIN(newTimer, (s32)ANIMATION_PLAYER_RUN_TIMER_MIN);
|
||||
|
||||
if (animationTimer->value > (s32)ANIMATION_PLAYER_RUN_TIMER_MIN)
|
||||
animationTimer->value = (s32)(CLAMP((s32)animationTimer->value, (s32)ANIMATION_PLAYER_RUN_TIMER_MIN, (s32)newTimer));
|
||||
}
|
||||
|
||||
_component_animation_player_determine(self, ecs);
|
||||
}
|
199
src/game/ecs/component/animation/component_animation_player.h
Normal file
199
src/game/ecs/component/animation/component_animation_player.h
Normal file
@ -0,0 +1,199 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_animation.h"
|
||||
#include "../game/component_world_object.h"
|
||||
#include "../game/component_player_control.h"
|
||||
|
||||
static const f32 ANIMATION_PLAYER_RUN_DISTANCE_MAX = 50.0f;
|
||||
static const u32 ANIMATION_PLAYER_RUN_TIMER = 20;
|
||||
static const u32 ANIMATION_PLAYER_RUN_TIMER_MIN = 5;
|
||||
|
||||
#define ANIMATION_PLAYER_COUNT ANIMATION_PLAYER_LUNGE_DOWN + 1
|
||||
typedef enum AnimationPlayerType
|
||||
{
|
||||
ANIMATION_PLAYER_IDLE_LEFT,
|
||||
ANIMATION_PLAYER_RUN_LEFT,
|
||||
ANIMATION_PLAYER_LUNGE_LEFT,
|
||||
ANIMATION_PLAYER_IDLE_RIGHT,
|
||||
ANIMATION_PLAYER_RUN_RIGHT,
|
||||
ANIMATION_PLAYER_LUNGE_RIGHT,
|
||||
ANIMATION_PLAYER_IDLE_UP,
|
||||
ANIMATION_PLAYER_RUN_UP,
|
||||
ANIMATION_PLAYER_LUNGE_UP,
|
||||
ANIMATION_PLAYER_IDLE_DOWN,
|
||||
ANIMATION_PLAYER_RUN_DOWN,
|
||||
ANIMATION_PLAYER_LUNGE_DOWN
|
||||
} AnimationPlayerType;
|
||||
|
||||
#define ANIMATION_PLAYER_ACTION_COUNT (ANIMATION_PLAYER_ACTION_LUNGE + 1)
|
||||
typedef enum AnimationPlayerActionType
|
||||
{
|
||||
ANIMATION_PLAYER_ACTION_IDLE,
|
||||
ANIMATION_PLAYER_ACTION_RUN,
|
||||
ANIMATION_PLAYER_ACTION_LUNGE
|
||||
} AnimationPlayerActionType;
|
||||
|
||||
#define ANIMATION_PLAYER_IDLE_LEFT_COUNT 1
|
||||
static const u32 ANIMATION_PLAYER_IDLE_LEFT_FRAME_INDICES[ANIMATION_PLAYER_IDLE_LEFT_COUNT] = {0};
|
||||
static const struct Animation ANIMATION_PLAYER_IDLE_LEFT_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_IDLE_LEFT_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_IDLE_LEFT_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_PLAYER_RUN_LEFT_COUNT 3
|
||||
static const u32 ANIMATION_PLAYER_RUN_LEFT_FRAME_INDICES[ANIMATION_PLAYER_RUN_LEFT_COUNT] = {1, 2, 3};
|
||||
static const struct Animation ANIMATION_PLAYER_RUN_LEFT_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_RUN_LEFT_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_RUN_LEFT_COUNT,
|
||||
.length = 20,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
|
||||
#define ANIMATION_PLAYER_LUNGE_LEFT_COUNT 1
|
||||
static const u32 ANIMATION_PLAYER_LUNGE_LEFT_FRAME_INDICES[ANIMATION_PLAYER_LUNGE_LEFT_COUNT] = {4};
|
||||
static const struct Animation ANIMATION_PLAYER_LUNGE_LEFT_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_LUNGE_LEFT_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_LUNGE_LEFT_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_PLAYER_IDLE_RIGHT_COUNT 1
|
||||
static const u32 ANIMATION_PLAYER_IDLE_RIGHT_FRAME_INDICES[ANIMATION_PLAYER_IDLE_RIGHT_COUNT] = {5};
|
||||
static const struct Animation ANIMATION_PLAYER_IDLE_RIGHT_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_IDLE_RIGHT_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_IDLE_RIGHT_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_PLAYER_RUN_RIGHT_COUNT 3
|
||||
static const u32 ANIMATION_PLAYER_RUN_RIGHT_FRAME_INDICES[ANIMATION_PLAYER_RUN_RIGHT_COUNT] = {6, 7, 8};
|
||||
static const struct Animation ANIMATION_PLAYER_RUN_RIGHT_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_RUN_RIGHT_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_RUN_RIGHT_COUNT,
|
||||
.length = 20,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_PLAYER_LUNGE_RIGHT_COUNT 1
|
||||
static const u32 ANIMATION_PLAYER_LUNGE_RIGHT_FRAME_INDICES[ANIMATION_PLAYER_LUNGE_RIGHT_COUNT] = {9};
|
||||
static const struct Animation ANIMATION_PLAYER_LUNGE_RIGHT_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_LUNGE_RIGHT_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_LUNGE_RIGHT_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
|
||||
#define ANIMATION_PLAYER_IDLE_UP_COUNT 1
|
||||
static const u32 ANIMATION_PLAYER_IDLE_UP_FRAME_INDICES[ANIMATION_PLAYER_IDLE_UP_COUNT] = {10};
|
||||
static const struct Animation ANIMATION_PLAYER_IDLE_UP_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_IDLE_UP_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_IDLE_UP_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_PLAYER_RUN_UP_COUNT 3
|
||||
static const u32 ANIMATION_PLAYER_RUN_UP_FRAME_INDICES[ANIMATION_PLAYER_RUN_UP_COUNT] = {11, 12, 13};
|
||||
static const struct Animation ANIMATION_PLAYER_RUN_UP_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_RUN_UP_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_RUN_UP_COUNT,
|
||||
.length = 20,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_PLAYER_LUNGE_UP_COUNT 1
|
||||
static const u32 ANIMATION_PLAYER_LUNGE_UP_FRAME_INDICES[ANIMATION_PLAYER_LUNGE_UP_COUNT] = {14};
|
||||
static const struct Animation ANIMATION_PLAYER_LUNGE_UP_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_LUNGE_UP_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_LUNGE_UP_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_PLAYER_IDLE_DOWN_COUNT 1
|
||||
static const u32 ANIMATION_PLAYER_IDLE_DOWN_FRAME_INDICES[ANIMATION_PLAYER_IDLE_DOWN_COUNT] = {15};
|
||||
static const struct Animation ANIMATION_PLAYER_IDLE_DOWN_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_IDLE_DOWN_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_IDLE_DOWN_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_PLAYER_RUN_DOWN_COUNT 3
|
||||
static const u32 ANIMATION_PLAYER_RUN_DOWN_FRAME_INDICES[ANIMATION_PLAYER_RUN_DOWN_COUNT] = {16, 17, 18};
|
||||
static const struct Animation ANIMATION_PLAYER_RUN_DOWN_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_RUN_DOWN_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_RUN_DOWN_COUNT,
|
||||
.length = 20,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_PLAYER_LUNGE_DOWN_COUNT 1
|
||||
static const u32 ANIMATION_PLAYER_LUNGE_DOWN_FRAME_INDICES[ANIMATION_PLAYER_LUNGE_DOWN_COUNT] = {19};
|
||||
static const struct Animation ANIMATION_PLAYER_LUNGE_DOWN_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_PLAYER_LUNGE_DOWN_FRAME_INDICES,
|
||||
.count = ANIMATION_PLAYER_LUNGE_DOWN_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
static const struct Animation ANIMATION_PLAYER_STRUCTS[ANIMATION_PLAYER_COUNT] =
|
||||
{
|
||||
ANIMATION_PLAYER_IDLE_LEFT_STRUCT,
|
||||
ANIMATION_PLAYER_RUN_LEFT_STRUCT,
|
||||
ANIMATION_PLAYER_LUNGE_LEFT_STRUCT,
|
||||
ANIMATION_PLAYER_IDLE_RIGHT_STRUCT,
|
||||
ANIMATION_PLAYER_RUN_RIGHT_STRUCT,
|
||||
ANIMATION_PLAYER_LUNGE_RIGHT_STRUCT,
|
||||
ANIMATION_PLAYER_IDLE_UP_STRUCT,
|
||||
ANIMATION_PLAYER_RUN_UP_STRUCT,
|
||||
ANIMATION_PLAYER_LUNGE_UP_STRUCT,
|
||||
ANIMATION_PLAYER_IDLE_DOWN_STRUCT,
|
||||
ANIMATION_PLAYER_RUN_DOWN_STRUCT,
|
||||
ANIMATION_PLAYER_LUNGE_DOWN_STRUCT
|
||||
};
|
||||
|
||||
typedef struct ComponentAnimationPlayer
|
||||
{
|
||||
Component component;
|
||||
AnimationPlayerType type;
|
||||
AnimationPlayerActionType action;
|
||||
} ComponentAnimationPlayer;
|
||||
|
||||
void component_animation_player_init(ComponentAnimationPlayer* self, ECS* ecs, AnimationPlayerType type);
|
||||
void component_animation_player_tick(ComponentAnimationPlayer* self, ECS* ecs);
|
||||
|
||||
static const ComponentInfo COMPONENT_ANIMATION_PLAYER_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_animation_player_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_ANIMATION_PLAYER,
|
||||
.size = sizeof(ComponentAnimationPlayer)
|
||||
};
|
107
src/game/ecs/component/animation/component_animation_target.c
Normal file
107
src/game/ecs/component/animation/component_animation_target.c
Normal file
@ -0,0 +1,107 @@
|
||||
#include "component_animation_target.h"
|
||||
|
||||
void _component_animation_target_set(ComponentAnimationTarget* self, ECS* ecs, AnimationTargetType type);
|
||||
void _component_animation_target_determine(ComponentAnimationTarget* self, ECS* ecs);
|
||||
|
||||
void
|
||||
_component_animation_target_set(ComponentAnimationTarget* self, ECS* ecs, AnimationTargetType type)
|
||||
{
|
||||
ComponentAnimation* animation;
|
||||
|
||||
if (type == self->type)
|
||||
return;
|
||||
|
||||
self->type = type;
|
||||
|
||||
animation = ecs_component_get(ecs, COMPONENT_ANIMATION, self->component.id);
|
||||
|
||||
component_animation_set(animation, ecs, &ANIMATION_TARGET_STRUCTS[type]);
|
||||
}
|
||||
|
||||
void
|
||||
_component_animation_target_determine(ComponentAnimationTarget* self, ECS* ecs)
|
||||
{
|
||||
ComponentStage* stage;
|
||||
AnimationTargetType type;
|
||||
|
||||
stage = ecs_component_get(ecs, COMPONENT_STAGE, self->component.id);
|
||||
|
||||
type = (AnimationTargetType)(self->action + ((ANIMATION_TARGET_ACTION_COUNT) * stage->value));
|
||||
|
||||
_component_animation_target_set(self, ecs, type);
|
||||
}
|
||||
|
||||
void
|
||||
component_animation_target_init(ComponentAnimationTarget* self, ECS* ecs, AnimationTargetType type, EntityID playerID)
|
||||
{
|
||||
self->type = -1;
|
||||
self->action = ANIMATION_TARGET_ACTION_IDLE;
|
||||
self->playerID = playerID;
|
||||
|
||||
_component_animation_target_set(self, ecs, type);
|
||||
}
|
||||
|
||||
void
|
||||
component_animation_target_tick(ComponentAnimationTarget* self, ECS* ecs)
|
||||
{
|
||||
ComponentFood* playerFood;
|
||||
ComponentTakeFood* takeFood;
|
||||
ComponentAnimation* animation;
|
||||
|
||||
animation = ecs_component_get(ecs, COMPONENT_ANIMATION, self->component.id);
|
||||
|
||||
if
|
||||
(
|
||||
(self->action == ANIMATION_TARGET_ACTION_GULP || self->action == ANIMATION_TARGET_ACTION_BURP) &&
|
||||
!animation->isFinished
|
||||
)
|
||||
return;
|
||||
|
||||
if (self->action == ANIMATION_TARGET_ACTION_GULP && animation->isFinished)
|
||||
{
|
||||
self->action = ANIMATION_TARGET_ACTION_BURP;
|
||||
|
||||
sound_play(&ecs->resources->sounds[SOUND_BURP + RANDOM_S32(0, SOUND_BURP_COUNT - 1)]);
|
||||
|
||||
_component_animation_target_determine(self, ecs);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
playerFood = ecs_component_get(ecs, COMPONENT_FOOD, self->playerID);
|
||||
takeFood = ecs_component_get(ecs, COMPONENT_TAKE_FOOD, self->component.id);
|
||||
|
||||
if (self->action == ANIMATION_TARGET_ACTION_BURP && animation->isFinished)
|
||||
{
|
||||
sound_play(&ecs->resources->sounds[SOUND_GURGLE + RANDOM_S32(0, SOUND_GURGLE_COUNT - 1)]);
|
||||
takeFood->component.isDisabled = false;
|
||||
}
|
||||
|
||||
self->action = ANIMATION_TARGET_ACTION_IDLE;
|
||||
|
||||
if (takeFood->isTakeFood)
|
||||
{
|
||||
self->action = ANIMATION_TARGET_ACTION_GULP;
|
||||
|
||||
takeFood->isTakeFood = false;
|
||||
takeFood->component.isDisabled = true;
|
||||
|
||||
sound_play(&ecs->resources->sounds[SOUND_GULP + RANDOM_S32(0, SOUND_GULP_COUNT - 1)]);
|
||||
}
|
||||
else if (playerFood->value > 0)
|
||||
{
|
||||
ComponentPhysics* playerPhysics;
|
||||
ComponentPhysics* physics;
|
||||
f32 distance;
|
||||
|
||||
playerPhysics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->playerID);
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
|
||||
distance = DISTANCE_2D(playerPhysics->position[0], physics->position[0], playerPhysics->position[1], physics->position[1]);
|
||||
|
||||
if (distance <= ANIMATION_TARGET_POINT_RADIUS && !self->isPointDisabled)
|
||||
self->action = ANIMATION_TARGET_ACTION_POINT;
|
||||
}
|
||||
|
||||
_component_animation_target_determine(self, ecs);
|
||||
}
|
296
src/game/ecs/component/animation/component_animation_target.h
Normal file
296
src/game/ecs/component/animation/component_animation_target.h
Normal file
@ -0,0 +1,296 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_animation.h"
|
||||
#include "../game/component_food.h"
|
||||
#include "../game/component_take_food.h"
|
||||
#include "../game/component_stage.h"
|
||||
#include "../game/component_world_object.h"
|
||||
|
||||
static const f32 ANIMATION_TARGET_POINT_RADIUS = 1500.0f;
|
||||
|
||||
#define ANIMATION_TARGET_COUNT (ANIMATION_TARGET_BURP_STAGE_FIVE + 1)
|
||||
typedef enum AnimationTargetType
|
||||
{
|
||||
ANIMATION_TARGET_IDLE_STAGE_ONE,
|
||||
ANIMATION_TARGET_POINT_STAGE_ONE,
|
||||
ANIMATION_TARGET_GULP_STAGE_ONE,
|
||||
ANIMATION_TARGET_BURP_STAGE_ONE,
|
||||
ANIMATION_TARGET_IDLE_STAGE_TWO,
|
||||
ANIMATION_TARGET_POINT_STAGE_TWO,
|
||||
ANIMATION_TARGET_GULP_STAGE_TWO,
|
||||
ANIMATION_TARGET_BURP_STAGE_TWO,
|
||||
ANIMATION_TARGET_IDLE_STAGE_THREE,
|
||||
ANIMATION_TARGET_POINT_STAGE_THREE,
|
||||
ANIMATION_TARGET_GULP_STAGE_THREE,
|
||||
ANIMATION_TARGET_BURP_STAGE_THREE,
|
||||
ANIMATION_TARGET_IDLE_STAGE_FOUR,
|
||||
ANIMATION_TARGET_POINT_STAGE_FOUR,
|
||||
ANIMATION_TARGET_GULP_STAGE_FOUR,
|
||||
ANIMATION_TARGET_BURP_STAGE_FOUR,
|
||||
ANIMATION_TARGET_IDLE_STAGE_FIVE,
|
||||
ANIMATION_TARGET_POINT_STAGE_FIVE,
|
||||
ANIMATION_TARGET_GULP_STAGE_FIVE,
|
||||
ANIMATION_TARGET_BURP_STAGE_FIVE
|
||||
} AnimationTargetType;
|
||||
|
||||
#define ANIMATION_TARGET_ACTION_COUNT (ANIMATION_TARGET_ACTION_BURP + 1)
|
||||
typedef enum AnimationTargetActionType
|
||||
{
|
||||
ANIMATION_TARGET_ACTION_IDLE,
|
||||
ANIMATION_TARGET_ACTION_POINT,
|
||||
ANIMATION_TARGET_ACTION_GULP,
|
||||
ANIMATION_TARGET_ACTION_BURP
|
||||
} AnimationTargetActionType;
|
||||
|
||||
#define ANIMATION_TARGET_IDLE_STAGE_ONE_COUNT 2
|
||||
static const u32 ANIMATION_TARGET_IDLE_STAGE_ONE_FRAME_INDICES[ANIMATION_TARGET_IDLE_STAGE_ONE_COUNT] = {0, 1};
|
||||
static const struct Animation ANIMATION_TARGET_IDLE_STAGE_ONE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_IDLE_STAGE_ONE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_IDLE_STAGE_ONE_COUNT,
|
||||
.length = 30,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_POINT_STAGE_ONE_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_POINT_STAGE_ONE_FRAME_INDICES[ANIMATION_TARGET_POINT_STAGE_ONE_COUNT] = {2};
|
||||
static const struct Animation ANIMATION_TARGET_POINT_STAGE_ONE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_POINT_STAGE_ONE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_POINT_STAGE_ONE_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_GULP_STAGE_ONE_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_GULP_STAGE_ONE_FRAME_INDICES[ANIMATION_TARGET_GULP_STAGE_ONE_COUNT] = {3};
|
||||
static const struct Animation ANIMATION_TARGET_GULP_STAGE_ONE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_GULP_STAGE_ONE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_GULP_STAGE_ONE_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_BURP_STAGE_ONE_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_BURP_STAGE_ONE_FRAME_INDICES[ANIMATION_TARGET_BURP_STAGE_ONE_COUNT] = {4};
|
||||
static const struct Animation ANIMATION_TARGET_BURP_STAGE_ONE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_BURP_STAGE_ONE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_BURP_STAGE_ONE_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_IDLE_STAGE_TWO_COUNT 2
|
||||
static const u32 ANIMATION_TARGET_IDLE_STAGE_TWO_FRAME_INDICES[ANIMATION_TARGET_IDLE_STAGE_TWO_COUNT] = {5, 6};
|
||||
static const struct Animation ANIMATION_TARGET_IDLE_STAGE_TWO_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_IDLE_STAGE_TWO_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_IDLE_STAGE_TWO_COUNT,
|
||||
.length = 30,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_POINT_STAGE_TWO_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_POINT_STAGE_TWO_FRAME_INDICES[ANIMATION_TARGET_POINT_STAGE_TWO_COUNT] = {7};
|
||||
static const struct Animation ANIMATION_TARGET_POINT_STAGE_TWO_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_POINT_STAGE_TWO_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_POINT_STAGE_TWO_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_GULP_STAGE_TWO_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_GULP_STAGE_TWO_FRAME_INDICES[ANIMATION_TARGET_GULP_STAGE_TWO_COUNT] = {8};
|
||||
static const struct Animation ANIMATION_TARGET_GULP_STAGE_TWO_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_GULP_STAGE_TWO_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_GULP_STAGE_TWO_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_BURP_STAGE_TWO_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_BURP_STAGE_TWO_FRAME_INDICES[ANIMATION_TARGET_BURP_STAGE_TWO_COUNT] = {9};
|
||||
static const struct Animation ANIMATION_TARGET_BURP_STAGE_TWO_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_BURP_STAGE_TWO_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_BURP_STAGE_TWO_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_IDLE_STAGE_THREE_COUNT 2
|
||||
static const u32 ANIMATION_TARGET_IDLE_STAGE_THREE_FRAME_INDICES[ANIMATION_TARGET_IDLE_STAGE_THREE_COUNT] = {10, 11};
|
||||
static const struct Animation ANIMATION_TARGET_IDLE_STAGE_THREE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_IDLE_STAGE_THREE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_IDLE_STAGE_THREE_COUNT,
|
||||
.length = 30,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_POINT_STAGE_THREE_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_POINT_STAGE_THREE_FRAME_INDICES[ANIMATION_TARGET_POINT_STAGE_THREE_COUNT] = {12};
|
||||
static const struct Animation ANIMATION_TARGET_POINT_STAGE_THREE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_POINT_STAGE_THREE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_POINT_STAGE_THREE_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_GULP_STAGE_THREE_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_GULP_STAGE_THREE_FRAME_INDICES[ANIMATION_TARGET_GULP_STAGE_THREE_COUNT] = {13};
|
||||
static const struct Animation ANIMATION_TARGET_GULP_STAGE_THREE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_GULP_STAGE_THREE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_GULP_STAGE_THREE_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_BURP_STAGE_THREE_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_BURP_STAGE_THREE_FRAME_INDICES[ANIMATION_TARGET_BURP_STAGE_THREE_COUNT] = {14};
|
||||
static const struct Animation ANIMATION_TARGET_BURP_STAGE_THREE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_BURP_STAGE_THREE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_BURP_STAGE_THREE_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_IDLE_STAGE_FOUR_COUNT 2
|
||||
static const u32 ANIMATION_TARGET_IDLE_STAGE_FOUR_FRAME_INDICES[ANIMATION_TARGET_IDLE_STAGE_FOUR_COUNT] = {15, 16};
|
||||
static const struct Animation ANIMATION_TARGET_IDLE_STAGE_FOUR_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_IDLE_STAGE_FOUR_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_IDLE_STAGE_FOUR_COUNT,
|
||||
.length = 30,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_POINT_STAGE_FOUR_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_POINT_STAGE_FOUR_FRAME_INDICES[ANIMATION_TARGET_POINT_STAGE_FOUR_COUNT] = {17};
|
||||
static const struct Animation ANIMATION_TARGET_POINT_STAGE_FOUR_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_POINT_STAGE_FOUR_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_POINT_STAGE_FOUR_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_GULP_STAGE_FOUR_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_GULP_STAGE_FOUR_FRAME_INDICES[ANIMATION_TARGET_GULP_STAGE_FOUR_COUNT] = {18};
|
||||
static const struct Animation ANIMATION_TARGET_GULP_STAGE_FOUR_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_GULP_STAGE_FOUR_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_GULP_STAGE_FOUR_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_BURP_STAGE_FOUR_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_BURP_STAGE_FOUR_FRAME_INDICES[ANIMATION_TARGET_BURP_STAGE_FOUR_COUNT] = {19};
|
||||
static const struct Animation ANIMATION_TARGET_BURP_STAGE_FOUR_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_BURP_STAGE_FOUR_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_BURP_STAGE_FOUR_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_IDLE_STAGE_FIVE_COUNT 2
|
||||
static const u32 ANIMATION_TARGET_IDLE_STAGE_FIVE_FRAME_INDICES[ANIMATION_TARGET_IDLE_STAGE_FIVE_COUNT] = {20, 21};
|
||||
static const struct Animation ANIMATION_TARGET_IDLE_STAGE_FIVE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_IDLE_STAGE_FIVE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_IDLE_STAGE_FIVE_COUNT,
|
||||
.length = 30,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_POINT_STAGE_FIVE_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_POINT_STAGE_FIVE_FRAME_INDICES[ANIMATION_TARGET_POINT_STAGE_FIVE_COUNT] = {22};
|
||||
static const struct Animation ANIMATION_TARGET_POINT_STAGE_FIVE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_POINT_STAGE_FIVE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_POINT_STAGE_FIVE_COUNT,
|
||||
.length = 0,
|
||||
.isLoop = true
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_GULP_STAGE_FIVE_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_GULP_STAGE_FIVE_FRAME_INDICES[ANIMATION_TARGET_GULP_STAGE_FIVE_COUNT] = {23};
|
||||
static const struct Animation ANIMATION_TARGET_GULP_STAGE_FIVE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_GULP_STAGE_FIVE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_GULP_STAGE_FIVE_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
#define ANIMATION_TARGET_BURP_STAGE_FIVE_COUNT 1
|
||||
static const u32 ANIMATION_TARGET_BURP_STAGE_FIVE_FRAME_INDICES[ANIMATION_TARGET_BURP_STAGE_FIVE_COUNT] = {24};
|
||||
static const struct Animation ANIMATION_TARGET_BURP_STAGE_FIVE_STRUCT =
|
||||
{
|
||||
.frameIndices = (u32*)ANIMATION_TARGET_BURP_STAGE_FIVE_FRAME_INDICES,
|
||||
.count = ANIMATION_TARGET_BURP_STAGE_FIVE_COUNT,
|
||||
.length = 60,
|
||||
.isLoop = false
|
||||
};
|
||||
|
||||
static const struct Animation ANIMATION_TARGET_STRUCTS[ANIMATION_TARGET_COUNT] =
|
||||
{
|
||||
ANIMATION_TARGET_IDLE_STAGE_ONE_STRUCT,
|
||||
ANIMATION_TARGET_POINT_STAGE_ONE_STRUCT,
|
||||
ANIMATION_TARGET_GULP_STAGE_ONE_STRUCT,
|
||||
ANIMATION_TARGET_BURP_STAGE_ONE_STRUCT,
|
||||
ANIMATION_TARGET_IDLE_STAGE_TWO_STRUCT,
|
||||
ANIMATION_TARGET_POINT_STAGE_TWO_STRUCT,
|
||||
ANIMATION_TARGET_GULP_STAGE_TWO_STRUCT,
|
||||
ANIMATION_TARGET_BURP_STAGE_TWO_STRUCT,
|
||||
ANIMATION_TARGET_IDLE_STAGE_THREE_STRUCT,
|
||||
ANIMATION_TARGET_POINT_STAGE_THREE_STRUCT,
|
||||
ANIMATION_TARGET_GULP_STAGE_THREE_STRUCT,
|
||||
ANIMATION_TARGET_BURP_STAGE_THREE_STRUCT,
|
||||
ANIMATION_TARGET_IDLE_STAGE_FOUR_STRUCT,
|
||||
ANIMATION_TARGET_POINT_STAGE_FOUR_STRUCT,
|
||||
ANIMATION_TARGET_GULP_STAGE_FOUR_STRUCT,
|
||||
ANIMATION_TARGET_BURP_STAGE_FOUR_STRUCT,
|
||||
ANIMATION_TARGET_IDLE_STAGE_FIVE_STRUCT,
|
||||
ANIMATION_TARGET_POINT_STAGE_FIVE_STRUCT,
|
||||
ANIMATION_TARGET_GULP_STAGE_FIVE_STRUCT,
|
||||
ANIMATION_TARGET_BURP_STAGE_FIVE_STRUCT
|
||||
};
|
||||
|
||||
typedef struct ComponentAnimationTarget
|
||||
{
|
||||
Component component;
|
||||
AnimationTargetType type;
|
||||
AnimationTargetActionType action;
|
||||
EntityID playerID;
|
||||
bool isPointDisabled;
|
||||
} ComponentAnimationTarget;
|
||||
|
||||
void component_animation_target_init(ComponentAnimationTarget* self, ECS* ecs, AnimationTargetType type, EntityID playerID);
|
||||
void component_animation_target_tick(ComponentAnimationTarget* self, ECS* ecs);
|
||||
|
||||
static const ComponentInfo COMPONENT_ANIMATION_TARGET_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_animation_target_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_ANIMATION_TARGET,
|
||||
.size = sizeof(ComponentAnimationTarget)
|
||||
};
|
26
src/game/ecs/component/game/component_collect.c
Normal file
26
src/game/ecs/component/game/component_collect.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include "component_collect.h"
|
||||
|
||||
void _component_collect_circle_set(ComponentCollect* self, ECS* ecs);
|
||||
|
||||
void
|
||||
_component_collect_circle_set(ComponentCollect* self, ECS* ecs)
|
||||
{
|
||||
ComponentCircleCollider* circleCollider;
|
||||
|
||||
circleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id);
|
||||
|
||||
self->circle.position[0] = circleCollider->circle.position[0];
|
||||
self->circle.position[1] = circleCollider->circle.position[1];
|
||||
}
|
||||
|
||||
void
|
||||
component_collect_init(ComponentCollect* self, ECS* ecs, f32 radius)
|
||||
{
|
||||
self->circle.radius = radius;
|
||||
}
|
||||
|
||||
void
|
||||
component_collect_tick(ComponentCollect* self, ECS* ecs)
|
||||
{
|
||||
_component_collect_circle_set(self, ecs);
|
||||
}
|
29
src/game/ecs/component/game/component_collect.h
Normal file
29
src/game/ecs/component/game/component_collect.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_world_object.h"
|
||||
|
||||
typedef struct ComponentCollect
|
||||
{
|
||||
Component component;
|
||||
Circle circle;
|
||||
} ComponentCollect;
|
||||
|
||||
void component_collect_tick(ComponentCollect* self, ECS* ecs);
|
||||
void component_collect_init(ComponentCollect* self, ECS* ecs, f32 radius);
|
||||
|
||||
static const ComponentInfo COMPONENT_COLLECT_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_collect_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_COLLECT,
|
||||
.size = sizeof(ComponentCollect)
|
||||
};
|
169
src/game/ecs/component/game/component_collectible.c
Normal file
169
src/game/ecs/component/game/component_collectible.c
Normal file
@ -0,0 +1,169 @@
|
||||
#include "component_collectible.h"
|
||||
|
||||
void _component_collectible_increment(ComponentCollectible* self, ECS* ecs, EntityID id);
|
||||
void _component_collectible_collect(ComponentCollectible* self, ECS* ecs, EntityID id);
|
||||
|
||||
void
|
||||
_component_collectible_increment(ComponentCollectible* self, ECS* ecs, EntityID id)
|
||||
{
|
||||
ComponentFood* food;
|
||||
ComponentPower* power;
|
||||
ComponentStamina* stamina;
|
||||
ComponentColorChange* colorChange;
|
||||
|
||||
switch (self->type)
|
||||
{
|
||||
case COLLECTIBLE_FOOD:
|
||||
food = ecs_component_get(ecs, COMPONENT_FOOD, id);
|
||||
if (!food)
|
||||
return;
|
||||
food->value += COMPONENT_COLLECTIBLE_FOOD_VALUE * food->multiplier;
|
||||
sound_play(&ecs->resources->sounds[SOUND_FOOD_COLLECT]);
|
||||
break;
|
||||
case COLLECTIBLE_POWER:
|
||||
colorChange = ecs_component_get(ecs, COMPONENT_COLOR_CHANGE, id);
|
||||
power = ecs_component_get(ecs, COMPONENT_POWER, id);
|
||||
if (!power)
|
||||
return;
|
||||
power->value += COMPONENT_COLLECTIBLE_POWER_VALUE;
|
||||
sound_play(&ecs->resources->sounds[SOUND_POWER]);
|
||||
|
||||
if (!colorChange)
|
||||
return;
|
||||
|
||||
component_color_change_init(colorChange, ecs, COMPONENT_COLLECTIBLE_POWER_COLOR,TRANSPARENT, COMPONENT_COLLECTIBLE_POWER_COLOR_CHANGE_TIME, true, false);
|
||||
break;
|
||||
case COLLECTIBLE_STAMINA:
|
||||
stamina = ecs_component_get(ecs, COMPONENT_STAMINA, id);
|
||||
colorChange = ecs_component_get(ecs, COMPONENT_COLOR_CHANGE, id);
|
||||
if (!stamina)
|
||||
return;
|
||||
stamina->value += COMPONENT_COLLECTIBLE_STAMINA_VALUE;
|
||||
sound_play(&ecs->resources->sounds[SOUND_STAMINA]);
|
||||
|
||||
if (!colorChange)
|
||||
return;
|
||||
|
||||
component_color_change_init(colorChange, ecs, COMPONENT_COLLECTIBLE_STAMINA_COLOR,TRANSPARENT, COMPONENT_COLLECTIBLE_STAMINA_COLOR_CHANGE_TIME, true, false);
|
||||
break;
|
||||
case COLLECTIBLE_ROTTEN_FOOD:
|
||||
food = ecs_component_get(ecs, COMPONENT_FOOD, id);
|
||||
if (!food)
|
||||
return;
|
||||
food->value -= COMPONENT_COLLECTIBLE_FOOD_VALUE;
|
||||
sound_play(&ecs->resources->sounds[SOUND_BLEH]);
|
||||
break;
|
||||
case COLLECTIBLE_AMULET:
|
||||
sound_play(&ecs->resources->sounds[SOUND_POWER]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_component_collectible_collect(ComponentCollectible* self, ECS* ecs, EntityID id)
|
||||
{
|
||||
_component_collectible_increment(self, ecs, id);
|
||||
ecs_entity_delete(ecs, self->component.id);
|
||||
}
|
||||
|
||||
void
|
||||
component_collectible_add(ComponentCollectible* self, ECS* ecs)
|
||||
{
|
||||
ecs_components_add
|
||||
(
|
||||
ecs,
|
||||
COMPONENT_COLLECTIBLE_DEPENDENCIES,
|
||||
COMPONENT_COLLECTIBLE_DEPENDENCY_COUNT,
|
||||
self->component.id
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
component_collectible_init
|
||||
(
|
||||
ComponentCollectible* self,
|
||||
ECS* ecs,
|
||||
Texture* texture,
|
||||
const vec2 size,
|
||||
const vec3 position,
|
||||
CollectibleType type
|
||||
)
|
||||
{
|
||||
component_world_object_init
|
||||
(
|
||||
ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, self->component.id),
|
||||
ecs,
|
||||
texture,
|
||||
size,
|
||||
position,
|
||||
COMPONENT_COLLECTIBLE_HEIGHT_OFFSET,
|
||||
COMPONENT_COLLECTIBLE_RADIUS
|
||||
);
|
||||
|
||||
component_levitate_init
|
||||
(
|
||||
ecs_component_get(ecs, COMPONENT_LEVITATE, self->component.id),
|
||||
ecs,
|
||||
COMPONENT_COLLECTIBLE_LEVITATE_DISTANCE,
|
||||
COMPONENT_COLLECTIBLE_LEVITATE_FREQUENCY
|
||||
);
|
||||
|
||||
self->type = type;
|
||||
}
|
||||
|
||||
void
|
||||
component_collectible_tick(ComponentCollectible* self, ECS* ecs)
|
||||
{
|
||||
ComponentCircleCollider* circleCollider;
|
||||
ComponentHoming* homing;
|
||||
bool isTarget;
|
||||
bool isAbleToBeCollected;
|
||||
EntityID target;
|
||||
|
||||
circleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id);
|
||||
homing = ecs_component_get(ecs, COMPONENT_HOMING, self->component.id);
|
||||
|
||||
isTarget = false;
|
||||
isAbleToBeCollected = true;
|
||||
|
||||
for (s32 i = 0; i < (s32)ecs->lists[COMPONENT_COLLECT].components.count; i++)
|
||||
{
|
||||
ComponentCollect* collect;
|
||||
|
||||
collect = ecs_component_from_index_get(ecs, COMPONENT_COLLECT, i);
|
||||
|
||||
if (circle_collide_check(&collect->circle, &circleCollider->circle))
|
||||
{
|
||||
target = collect->component.id;
|
||||
isTarget = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isTarget)
|
||||
return;
|
||||
|
||||
if (self->type == COLLECTIBLE_FOOD)
|
||||
{
|
||||
ComponentFood* food;
|
||||
|
||||
food = ecs_component_get(ecs, COMPONENT_FOOD, target);
|
||||
|
||||
if (food->value >= food->max)
|
||||
{
|
||||
homing->isHoming = false;
|
||||
isAbleToBeCollected = false;
|
||||
//sound_play(&ecs->resources->sounds[SOUND_CANT_CARRY]);
|
||||
}
|
||||
}
|
||||
|
||||
if (isAbleToBeCollected)
|
||||
{
|
||||
if (!homing->isHoming)
|
||||
component_homing_init(homing, ecs, target, COMPONENT_COLLECTIBLE_HOMING_SPEED);
|
||||
|
||||
if (component_circle_collider_collide_check(circleCollider, ecs, target))
|
||||
_component_collectible_collect(self, ecs, target);
|
||||
}
|
||||
}
|
85
src/game/ecs/component/game/component_collectible.h
Normal file
85
src/game/ecs/component/game/component_collectible.h
Normal file
@ -0,0 +1,85 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_homing.h"
|
||||
#include "component_collect.h"
|
||||
#include "component_world_object.h"
|
||||
#include "component_levitate.h"
|
||||
#include "component_food.h"
|
||||
#include "component_power.h"
|
||||
#include "component_stamina.h"
|
||||
|
||||
#include "../visual/component_color_change.h"
|
||||
|
||||
static const f32 COMPONENT_COLLECTIBLE_HEIGHT_OFFSET = 1000.0f;
|
||||
static const f32 COMPONENT_COLLECTIBLE_RADIUS = 64.0f;
|
||||
static const u32 COMPONENT_COLLECTIBLE_FOOD_VALUE = 1;
|
||||
static const f32 COMPONENT_COLLECTIBLE_POWER_VALUE = 10.0f;
|
||||
static const f32 COMPONENT_COLLECTIBLE_STAMINA_VALUE = 50.0f;
|
||||
static const u32 COMPONENT_COLLECTIBLE_HOMING_SPEED = 3.0f;
|
||||
|
||||
static const f32 COMPONENT_COLLECTIBLE_LEVITATE_DISTANCE = 32.0f;
|
||||
static const f32 COMPONENT_COLLECTIBLE_LEVITATE_FREQUENCY = 10.0f;
|
||||
|
||||
static const u32 COMPONENT_COLLECTIBLE_STAMINA_COLOR_CHANGE_TIME = 30;
|
||||
static const u32 COMPONENT_COLLECTIBLE_POWER_COLOR_CHANGE_TIME = 30;
|
||||
|
||||
static const vec4 COMPONENT_COLLECTIBLE_POWER_COLOR = {0.60f, 1.0f, 0.80f, 0.0f};
|
||||
static const vec4 COMPONENT_COLLECTIBLE_STAMINA_COLOR = {1.0f, 0.2f, 0.40f, 0.0f};
|
||||
|
||||
typedef struct Vector Vector;
|
||||
|
||||
#define COLLECTIBLE_TYPE_COUNT COLLECTIBLE_ROTTEN_FOOD + 1
|
||||
typedef enum CollectibleType
|
||||
{
|
||||
COLLECTIBLE_FOOD,
|
||||
COLLECTIBLE_STAMINA,
|
||||
COLLECTIBLE_POWER,
|
||||
COLLECTIBLE_LOREBOOK,
|
||||
COLLECTIBLE_AMULET,
|
||||
COLLECTIBLE_ROTTEN_FOOD
|
||||
} CollectibleType;
|
||||
|
||||
typedef struct ComponentCollectible
|
||||
{
|
||||
Component component;
|
||||
CollectibleType type;
|
||||
} ComponentCollectible;
|
||||
|
||||
void
|
||||
component_collectible_init
|
||||
(
|
||||
ComponentCollectible* self,
|
||||
ECS* ecs,
|
||||
Texture* texture,
|
||||
const vec2 size,
|
||||
const vec3 position,
|
||||
CollectibleType type
|
||||
);
|
||||
|
||||
void component_collectible_add(ComponentCollectible* self, ECS* ecs);
|
||||
void component_collectible_tick(ComponentCollectible* self, ECS* ecs);
|
||||
|
||||
#define COMPONENT_COLLECTIBLE_DEPENDENCY_COUNT 3
|
||||
static const ComponentType COMPONENT_COLLECTIBLE_DEPENDENCIES[COMPONENT_COLLECTIBLE_DEPENDENCY_COUNT] =
|
||||
{
|
||||
COMPONENT_WORLD_OBJECT,
|
||||
COMPONENT_HOMING,
|
||||
COMPONENT_LEVITATE
|
||||
};
|
||||
|
||||
static const ComponentInfo COMPONENT_COLLECTIBLE_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
(ECSFunction)component_collectible_add,
|
||||
NULL,
|
||||
(ECSFunction)component_collectible_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_COLLECTIBLE,
|
||||
.size = sizeof(ComponentCollectible)
|
||||
};
|
52
src/game/ecs/component/game/component_collide_slow.c
Normal file
52
src/game/ecs/component/game/component_collide_slow.c
Normal file
@ -0,0 +1,52 @@
|
||||
#include "component_collide_slow.h"
|
||||
|
||||
void _component_collide_slow_collisions_tick(ComponentCollideSlow* self, ECS* ecs);
|
||||
|
||||
void
|
||||
_component_collide_slow_collisions_tick(ComponentCollideSlow* self, ECS* ecs)
|
||||
{
|
||||
ComponentCircleCollider* circleCollider;
|
||||
|
||||
circleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id);
|
||||
|
||||
self->isPreviousColliding = self->isColliding;
|
||||
self->isColliding = false;
|
||||
|
||||
ecs->isLog = false;
|
||||
|
||||
for (s32 i = 0; i < (s32)circleCollider->collisions.count; i++)
|
||||
{
|
||||
ComponentPhysics* collidePhysics;
|
||||
ComponentWorldObject* collideWorldObject;
|
||||
EntityID* id;
|
||||
f32 angle;
|
||||
f32 distance;
|
||||
|
||||
id = vector_get(&circleCollider->collisions, i);
|
||||
|
||||
collidePhysics = ecs_component_get(ecs, COMPONENT_PHYSICS, *id);
|
||||
collideWorldObject = ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, *id);
|
||||
|
||||
if (!collideWorldObject || !collidePhysics)
|
||||
continue;
|
||||
|
||||
if (!collideWorldObject->isAirborne)
|
||||
{
|
||||
collidePhysics->velocity[0] *= COMPONENT_COLLIDE_SLOW_VELOCITY_MULTIPLIER;
|
||||
collidePhysics->velocity[1] *= COMPONENT_COLLIDE_SLOW_VELOCITY_MULTIPLIER;
|
||||
|
||||
self->isColliding = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->isPreviousColliding != self->isColliding)
|
||||
sound_play(&ecs->resources->sounds[SOUND_STICKY]);
|
||||
|
||||
ecs->isLog = true;
|
||||
}
|
||||
|
||||
void
|
||||
component_collide_slow_tick(ComponentCollideSlow* self, ECS* ecs)
|
||||
{
|
||||
_component_collide_slow_collisions_tick(self, ecs);
|
||||
}
|
31
src/game/ecs/component/game/component_collide_slow.h
Normal file
31
src/game/ecs/component/game/component_collide_slow.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_world_object.h"
|
||||
|
||||
typedef struct ComponentCollideSlow
|
||||
{
|
||||
Component component;
|
||||
bool isColliding;
|
||||
bool isPreviousColliding;
|
||||
} ComponentCollideSlow;
|
||||
|
||||
static const f32 COMPONENT_COLLIDE_SLOW_VELOCITY_MULTIPLIER = 0.5f;
|
||||
|
||||
void component_collide_slow_tick(ComponentCollideSlow* self, ECS* ecs);
|
||||
|
||||
static const ComponentInfo COMPONENT_COLLIDE_SLOW_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_collide_slow_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_COLLIDE_SLOW,
|
||||
.size = sizeof(ComponentCollideSlow)
|
||||
};
|
26
src/game/ecs/component/game/component_food.c
Normal file
26
src/game/ecs/component/game/component_food.c
Normal file
@ -0,0 +1,26 @@
|
||||
#include "component_food.h"
|
||||
|
||||
void
|
||||
component_food_tick(ComponentFood* self, ECS* ecs)
|
||||
{
|
||||
self->value = CLAMP(self->value, 0, self->max);
|
||||
|
||||
if (self->value == self->max)
|
||||
{
|
||||
if (!self->isJustFull)
|
||||
{
|
||||
sound_play(&ecs->resources->sounds[SOUND_CANT_CARRY]);
|
||||
self->isJustFull = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
self->isJustFull = false;
|
||||
}
|
||||
|
||||
void
|
||||
component_food_init(ComponentFood* self, ECS* ecs, s32 value, s32 max, s32 multiplier)
|
||||
{
|
||||
self->value = value;
|
||||
self->max = max;
|
||||
self->multiplier = multiplier;
|
||||
}
|
32
src/game/ecs/component/game/component_food.h
Normal file
32
src/game/ecs/component/game/component_food.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_world_object.h"
|
||||
|
||||
typedef struct ComponentFood
|
||||
{
|
||||
Component component;
|
||||
s32 value;
|
||||
s32 max;
|
||||
s32 multiplier;
|
||||
bool isJustFull;
|
||||
} ComponentFood;
|
||||
|
||||
void component_food_tick(ComponentFood* self, ECS* ecs);
|
||||
void component_food_init(ComponentFood* self, ECS* ecs, s32 value, s32 max, s32 multiplier);
|
||||
|
||||
static const ComponentInfo COMPONENT_FOOD_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_food_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_FOOD,
|
||||
.size = sizeof(ComponentFood)
|
||||
};
|
62
src/game/ecs/component/game/component_game_object.c
Normal file
62
src/game/ecs/component/game/component_game_object.c
Normal file
@ -0,0 +1,62 @@
|
||||
#include "component_game_object.h"
|
||||
|
||||
void
|
||||
component_game_object_init
|
||||
(
|
||||
ComponentGameObject* self,
|
||||
ECS* ecs,
|
||||
Texture* texture,
|
||||
RendererBuffer buffer,
|
||||
Origin origin,
|
||||
vec2 size,
|
||||
vec3 position
|
||||
)
|
||||
{
|
||||
ComponentPhysics* physics;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
|
||||
component_texture_quad_init
|
||||
(
|
||||
ecs_component_get(ecs, COMPONENT_TEXTURE_QUAD, self->component.id),
|
||||
ecs,
|
||||
texture,
|
||||
COMPONENT_TEXTURE_QUAD_FLIP_DEFAULT,
|
||||
origin,
|
||||
buffer,
|
||||
COMPONENT_TEXTURE_QUAD_ROTATION_DEFAULT,
|
||||
size,
|
||||
COMPONENT_TEXTURE_QUAD_SCALE_DEFAULT,
|
||||
COMPONENT_TEXTURE_QUAD_UV_MIN_DEFAULT,
|
||||
COMPONENT_TEXTURE_QUAD_UV_MAX_DEFAULT,
|
||||
COMPONENT_TEXTURE_QUAD_OFFSET_DEFAULT,
|
||||
position,
|
||||
COMPONENT_TEXTURE_QUAD_COLOR_DEFAULT
|
||||
);
|
||||
|
||||
glm_vec3_copy(position, physics->position);
|
||||
}
|
||||
|
||||
void
|
||||
component_game_object_add(ComponentGameObject* self, ECS* ecs)
|
||||
{
|
||||
ecs_components_add
|
||||
(
|
||||
ecs,
|
||||
COMPONENT_GAME_OBJECT_DEPENDENCIES,
|
||||
COMPONENT_GAME_OBJECT_DEPENDENCY_COUNT,
|
||||
self->component.id
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
component_game_object_tick(ComponentGameObject* self, ECS* ecs)
|
||||
{
|
||||
ComponentTextureQuad* textureQuad;
|
||||
ComponentPhysics* physics;
|
||||
|
||||
textureQuad = ecs_component_get(ecs, COMPONENT_TEXTURE_QUAD, self->component.id);
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
|
||||
glm_vec3_copy(physics->position, textureQuad->position);
|
||||
}
|
48
src/game/ecs/component/game/component_game_object.h
Normal file
48
src/game/ecs/component/game/component_game_object.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "../visual/component_texture_quad.h"
|
||||
#include "../physics/component_physics.h"
|
||||
|
||||
typedef struct ComponentGameObject
|
||||
{
|
||||
Component component;
|
||||
} ComponentGameObject;
|
||||
|
||||
void
|
||||
component_game_object_init
|
||||
(
|
||||
ComponentGameObject* self,
|
||||
ECS* ecs,
|
||||
Texture* texture,
|
||||
RendererBuffer buffer,
|
||||
Origin origin,
|
||||
vec2 size,
|
||||
vec3 position
|
||||
);
|
||||
|
||||
void component_game_object_add(ComponentGameObject* self, ECS* ecs);
|
||||
void component_game_object_tick(ComponentGameObject* self, ECS* ecs);
|
||||
|
||||
#define COMPONENT_GAME_OBJECT_DEPENDENCY_COUNT 2
|
||||
static const ComponentType COMPONENT_GAME_OBJECT_DEPENDENCIES[COMPONENT_GAME_OBJECT_DEPENDENCY_COUNT] =
|
||||
{
|
||||
COMPONENT_PHYSICS,
|
||||
COMPONENT_TEXTURE_QUAD,
|
||||
};
|
||||
|
||||
static const ComponentInfo COMPONENT_GAME_OBJECT_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
(ECSFunction)component_game_object_add,
|
||||
NULL,
|
||||
(ECSFunction)component_game_object_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_GAME_OBJECT,
|
||||
.size = sizeof(ComponentGameObject)
|
||||
};
|
31
src/game/ecs/component/game/component_homing.c
Normal file
31
src/game/ecs/component/game/component_homing.c
Normal file
@ -0,0 +1,31 @@
|
||||
#include "component_homing.h"
|
||||
|
||||
void
|
||||
component_homing_init(ComponentHoming* self, ECS* ecs, EntityID targetID, f32 speed)
|
||||
{
|
||||
self->targetID = targetID;
|
||||
self->speed = speed;
|
||||
self->isHoming = true;
|
||||
}
|
||||
|
||||
void
|
||||
component_homing_tick(ComponentHoming* self, ECS* ecs)
|
||||
{
|
||||
if (!self->isHoming)
|
||||
return;
|
||||
|
||||
ComponentPhysics* physics;
|
||||
ComponentPhysics* targetPhysics;
|
||||
f32 angle;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
targetPhysics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->targetID);
|
||||
|
||||
if (!targetPhysics)
|
||||
return;
|
||||
|
||||
angle = ATAN(physics->position[0], targetPhysics->position[0], physics->position[1], targetPhysics->position[1]);
|
||||
|
||||
physics->velocity[0] += self->speed * cos(angle);
|
||||
physics->velocity[1] += self->speed * sin(angle);
|
||||
}
|
31
src/game/ecs/component/game/component_homing.h
Normal file
31
src/game/ecs/component/game/component_homing.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "../physics/component_physics.h"
|
||||
|
||||
typedef struct ComponentHoming
|
||||
{
|
||||
Component component;
|
||||
EntityID targetID;
|
||||
f32 speed;
|
||||
bool isHoming;
|
||||
} ComponentHoming;
|
||||
|
||||
void component_homing_tick(ComponentHoming* self, ECS* ecs);
|
||||
void component_homing_init(ComponentHoming* self, ECS* ecs, EntityID targetID, f32 speed);
|
||||
|
||||
static const ComponentInfo COMPONENT_HOMING_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_homing_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_HOMING,
|
||||
.size = sizeof(ComponentHoming)
|
||||
};
|
44
src/game/ecs/component/game/component_levitate.c
Normal file
44
src/game/ecs/component/game/component_levitate.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include "component_levitate.h"
|
||||
|
||||
void
|
||||
component_levitate_add(ComponentLevitate* self, ECS* ecs)
|
||||
{
|
||||
self->counterID = entity_counter_add(ecs);
|
||||
}
|
||||
|
||||
void
|
||||
component_levitate_delete(ComponentLevitate* self, ECS* ecs)
|
||||
{
|
||||
ecs_entity_delete(ecs, self->counterID);
|
||||
}
|
||||
|
||||
void
|
||||
component_levitate_tick(ComponentLevitate* self, ECS* ecs)
|
||||
{
|
||||
ComponentCounter* counter;
|
||||
ComponentWorldObject* worldObject;
|
||||
|
||||
counter = ecs_component_get(ecs, COMPONENT_COUNTER, self->counterID);
|
||||
worldObject = ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, self->component.id);
|
||||
|
||||
worldObject->heightOffset = self->distance + ((self->distance / 2.0f) * cos((f32)counter->value / self->frequency));
|
||||
}
|
||||
|
||||
void
|
||||
component_levitate_init
|
||||
(
|
||||
ComponentLevitate* self,
|
||||
ECS* ecs,
|
||||
f32 distance,
|
||||
f32 frequency
|
||||
)
|
||||
{
|
||||
ComponentWorldObject* worldObject;
|
||||
|
||||
worldObject = ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, self->component.id);
|
||||
|
||||
self->frequency = frequency;
|
||||
self->distance = distance;
|
||||
|
||||
worldObject->isGravityAffected = false;
|
||||
}
|
42
src/game/ecs/component/game/component_levitate.h
Normal file
42
src/game/ecs/component/game/component_levitate.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_world_object.h"
|
||||
#include "../../entity/utility/entity_counter.h"
|
||||
|
||||
typedef struct ComponentLevitate
|
||||
{
|
||||
Component component;
|
||||
f32 distance;
|
||||
f32 frequency;
|
||||
EntityID counterID;
|
||||
} ComponentLevitate;
|
||||
|
||||
void component_levitate_add(ComponentLevitate* self, ECS* ecs);
|
||||
void component_levitate_delete(ComponentLevitate* self, ECS* ecs);
|
||||
void component_levitate_tick(ComponentLevitate* self, ECS* ecs);
|
||||
|
||||
void
|
||||
component_levitate_init
|
||||
(
|
||||
ComponentLevitate* self,
|
||||
ECS* ecs,
|
||||
f32 distance,
|
||||
f32 frequency
|
||||
);
|
||||
|
||||
static const ComponentInfo COMPONENT_LEVITATE_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
(ECSFunction)component_levitate_add,
|
||||
(ECSFunction)component_levitate_delete,
|
||||
(ECSFunction)component_levitate_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_LEVITATE,
|
||||
.size = sizeof(ComponentLevitate)
|
||||
};
|
111
src/game/ecs/component/game/component_plane_object.c
Normal file
111
src/game/ecs/component/game/component_plane_object.c
Normal file
@ -0,0 +1,111 @@
|
||||
#include "component_plane_object.h"
|
||||
|
||||
void _component_plane_object_depth_set(ComponentPlaneObject* self, ECS* ecs);
|
||||
void _component_plane_object_circle_collider_set(ComponentPlaneObject* self, ECS* ecs);
|
||||
|
||||
void
|
||||
_component_plane_object_circle_collider_set(ComponentPlaneObject* self, ECS* ecs)
|
||||
{
|
||||
ComponentCircleCollider* circleCollider;
|
||||
ComponentTextureQuad* textureQuad;
|
||||
ComponentPhysics* physics;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
textureQuad = ecs_component_get(ecs, COMPONENT_TEXTURE_QUAD, self->component.id);
|
||||
circleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id);
|
||||
|
||||
circleCollider->circle.position[0] = physics->position[0];
|
||||
circleCollider->circle.position[1] = physics->position[1] + (textureQuad->size[1] / 2.0f);
|
||||
}
|
||||
|
||||
void
|
||||
_component_plane_object_depth_set(ComponentPlaneObject* self, ECS* ecs)
|
||||
{
|
||||
ComponentPhysics* physics;
|
||||
ComponentTextureQuad* textureQuad;
|
||||
f32 depth;
|
||||
f32 yOffset;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
textureQuad = ecs_component_get(ecs, COMPONENT_TEXTURE_QUAD, self->component.id);
|
||||
|
||||
yOffset = COMPONENT_PLANE_OBJECT_DEPTH_Y_OFFSET_MULTIPLIER * ((physics->position[1] + textureQuad->size[1]) / COMPONENT_PLANE_OBJECT_BOUNDS[3]);
|
||||
|
||||
depth = COMPONENT_PLANE_OBJECT_DEPTH_MAX - yOffset;
|
||||
depth += COMPONENT_PLANE_OBJECT_DEPTH_MIN;
|
||||
|
||||
physics->position[2] = depth;
|
||||
}
|
||||
|
||||
void
|
||||
_component_plane_object_bounds_set(ComponentPlaneObject* self, ECS* ecs)
|
||||
{
|
||||
ComponentPhysics* physics;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
|
||||
physics->position[0] = CLAMP(physics->position[0], COMPONENT_PLANE_OBJECT_BOUNDS[0], COMPONENT_PLANE_OBJECT_BOUNDS[2]);
|
||||
physics->position[1] = CLAMP(physics->position[1], COMPONENT_PLANE_OBJECT_BOUNDS[1], COMPONENT_PLANE_OBJECT_BOUNDS[3]);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
component_plane_object_init
|
||||
(
|
||||
ComponentPlaneObject* self,
|
||||
ECS* ecs,
|
||||
Texture* texture,
|
||||
vec2 size,
|
||||
vec3 position,
|
||||
f32 radius
|
||||
)
|
||||
{
|
||||
component_game_object_init
|
||||
(
|
||||
ecs_component_get(ecs, COMPONENT_GAME_OBJECT, self->component.id),
|
||||
ecs,
|
||||
texture,
|
||||
COMPONENT_PLANE_OBJECT_BUFFER,
|
||||
COMPONENT_PLANE_OBJECT_ORIGIN,
|
||||
size,
|
||||
position
|
||||
);
|
||||
|
||||
component_circle_collider_init
|
||||
(
|
||||
ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id),
|
||||
(f32*)position,
|
||||
radius
|
||||
);
|
||||
|
||||
component_physics_init
|
||||
(
|
||||
ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id),
|
||||
ecs,
|
||||
position,
|
||||
COMPONENT_PLANE_OBJECT_VELOCITY_MAX,
|
||||
COMPONENT_PLANE_OBJECT_FRICTION
|
||||
);
|
||||
|
||||
_component_plane_object_circle_collider_set(self, ecs);
|
||||
}
|
||||
|
||||
void
|
||||
component_plane_object_add(ComponentPlaneObject* self, ECS* ecs)
|
||||
{
|
||||
ecs_components_add
|
||||
(
|
||||
ecs,
|
||||
COMPONENT_PLANE_OBJECT_DEPENDENCIES,
|
||||
COMPONENT_PLANE_OBJECT_DEPENDENCY_COUNT,
|
||||
self->component.id
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
component_plane_object_tick(ComponentPlaneObject* self, ECS* ecs)
|
||||
{
|
||||
_component_plane_object_bounds_set(self, ecs);
|
||||
_component_plane_object_depth_set(self, ecs);
|
||||
_component_plane_object_circle_collider_set(self, ecs);
|
||||
}
|
58
src/game/ecs/component/game/component_plane_object.h
Normal file
58
src/game/ecs/component/game/component_plane_object.h
Normal file
@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_game_object.h"
|
||||
#include "../physics/component_circle_collider.h"
|
||||
|
||||
static const RendererBuffer COMPONENT_PLANE_OBJECT_BUFFER = RENDERER_BUFFER_WORLD;
|
||||
static const f32 COMPONENT_PLANE_OBJECT_FRICTION = 0.985f;
|
||||
static const f32 COMPONENT_PLANE_OBJECT_DEPTH_Y_OFFSET_MULTIPLIER = 0.1f;
|
||||
static const f32 COMPONENT_PLANE_OBJECT_DEPTH_MIN = 0.3f;
|
||||
static const f32 COMPONENT_PLANE_OBJECT_DEPTH_MAX = 0.4f;
|
||||
static const vec3 COMPONENT_PLANE_OBJECT_VELOCITY_MAX = {0.0f, 0.0f, 0.0f};
|
||||
static const vec4 COMPONENT_PLANE_OBJECT_BOUNDS = {250.0f, 250.0f, 6300.0f, 3100.0f};
|
||||
|
||||
#define COMPONENT_PLANE_OBJECT_ORIGIN ORIGIN_CENTER
|
||||
|
||||
typedef struct ComponentPlaneObject
|
||||
{
|
||||
Component component;
|
||||
} ComponentPlaneObject;
|
||||
|
||||
void
|
||||
component_plane_object_init
|
||||
(
|
||||
ComponentPlaneObject* self,
|
||||
ECS* ecs,
|
||||
Texture* texture,
|
||||
vec2 size,
|
||||
vec3 position,
|
||||
f32 radius
|
||||
);
|
||||
|
||||
void component_plane_object_add(ComponentPlaneObject* self, ECS* ecs);
|
||||
void component_plane_object_delete(ComponentPlaneObject* self, ECS* ecs);
|
||||
void component_plane_object_tick(ComponentPlaneObject* self, ECS* ecs);
|
||||
|
||||
#define COMPONENT_PLANE_OBJECT_DEPENDENCY_COUNT 2
|
||||
static const ComponentType COMPONENT_PLANE_OBJECT_DEPENDENCIES[COMPONENT_PLANE_OBJECT_DEPENDENCY_COUNT] =
|
||||
{
|
||||
COMPONENT_GAME_OBJECT,
|
||||
COMPONENT_CIRCLE_COLLIDER
|
||||
};
|
||||
|
||||
static const ComponentInfo COMPONENT_PLANE_OBJECT_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
(ECSFunction)component_plane_object_add,
|
||||
NULL,
|
||||
(ECSFunction)component_plane_object_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_PLANE_OBJECT,
|
||||
.size = sizeof(ComponentPlaneObject)
|
||||
};
|
148
src/game/ecs/component/game/component_player_control.c
Normal file
148
src/game/ecs/component/game/component_player_control.c
Normal file
@ -0,0 +1,148 @@
|
||||
#include "component_player_control.h"
|
||||
|
||||
void _component_player_control_movement_tick(ComponentPlayerControl* self, ECS* ecs);
|
||||
void _component_player_control_movement(ComponentPlayerControl* self, ECS* ecs);
|
||||
void _component_player_control_lunge(ComponentPlayerControl* self, ECS* ecs);
|
||||
void _component_player_control_lunge_tick(ComponentPlayerControl* self, ECS* ecs);
|
||||
|
||||
static vec2 SIZE = {64.0f, 64.0f};
|
||||
static vec3 POSITION = {0.0f, 0.0f, 0.0f};
|
||||
|
||||
void
|
||||
component_player_control_add(ComponentPlayerControl* self, ECS* ecs)
|
||||
{
|
||||
ecs_components_add(ecs, COMPONENT_PLAYER_CONTROL_DEPENDENCIES, COMPONENT_PLAYER_CONTROL_DEPENDENCY_COUNT, self->component.id);
|
||||
|
||||
self->lungeTimerID = entity_timer_add(ecs, COMPONENT_PLAYER_CONTROL_LUNGE_TIMER_MAX);
|
||||
}
|
||||
|
||||
void
|
||||
component_player_control_delete(ComponentPlayerControl* self, ECS* ecs)
|
||||
{
|
||||
ecs_entity_delete(ecs, self->lungeTimerID);
|
||||
}
|
||||
|
||||
void
|
||||
_component_player_control_movement(ComponentPlayerControl* self, ECS* ecs)
|
||||
{
|
||||
ComponentPhysics* physics;
|
||||
ComponentWorldObject* worldObject;
|
||||
vec2 mousePosition;
|
||||
vec2 physicsPosition;
|
||||
f32 velocityGain;
|
||||
f32 distanceFromMouse;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
worldObject = ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, self->component.id);
|
||||
|
||||
physicsPosition[0] = physics->position[0];
|
||||
physicsPosition[1] = physics->position[1];
|
||||
|
||||
mouse_buffer_position_get(&ecs->input->mouse, RENDERER_BUFFER_WORLD, ecs->renderer, mousePosition);
|
||||
|
||||
worldObject->angle = mouse_angle_from_buffer_position_get(&ecs->input->mouse, RENDERER_BUFFER_WORLD, ecs->renderer, physicsPosition);
|
||||
|
||||
velocityGain = COMPONENT_PLAYER_CONTROL_VELOCITY_DEFAULT;
|
||||
|
||||
distanceFromMouse = DISTANCE_2D
|
||||
(
|
||||
physicsPosition[0],
|
||||
mousePosition[0],
|
||||
physicsPosition[1],
|
||||
mousePosition[1]
|
||||
);
|
||||
|
||||
if (distanceFromMouse < COMPONENT_PLAYER_CONTROL_VELOCITY_DISTANCE_MAX)
|
||||
{
|
||||
f32 nextPositionDistance;
|
||||
velocityGain *= (distanceFromMouse / COMPONENT_PLAYER_CONTROL_VELOCITY_DISTANCE_MAX);
|
||||
|
||||
nextPositionDistance = component_physics_next_position_distance_get(physics, ecs);
|
||||
|
||||
if (nextPositionDistance < COMPONENT_PLAYER_CONTROL_VELOCITY_STOP_THRESHOLD)
|
||||
{
|
||||
velocityGain = 0.0f;
|
||||
glm_vec2_zero(physics->velocity);
|
||||
}
|
||||
}
|
||||
|
||||
physics->velocity[0] += velocityGain * cos(worldObject->angle);
|
||||
physics->velocity[1] += velocityGain * sin(worldObject->angle);
|
||||
}
|
||||
|
||||
void
|
||||
_component_player_control_movement_tick(ComponentPlayerControl* self, ECS* ecs)
|
||||
{
|
||||
ComponentWorldObject* worldObject;
|
||||
|
||||
worldObject = ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, self->component.id);
|
||||
|
||||
if (!worldObject->isAirborne)
|
||||
_component_player_control_movement(self, ecs);
|
||||
}
|
||||
|
||||
void
|
||||
_component_player_control_lunge(ComponentPlayerControl* self, ECS* ecs)
|
||||
{
|
||||
ComponentPhysics* physics;
|
||||
ComponentWorldObject* worldObject;
|
||||
vec2 physicsPosition;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
worldObject = ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, self->component.id);
|
||||
|
||||
physicsPosition[0] = physics->position[0];
|
||||
physicsPosition[1] = physics->position[1];
|
||||
|
||||
worldObject->angle = mouse_angle_from_buffer_position_get(&ecs->input->mouse, RENDERER_BUFFER_WORLD, ecs->renderer, physicsPosition);
|
||||
|
||||
physics->velocity[0] = COMPONENT_PLAYER_CONTROL_LUNGE_VELOCITY * cos(worldObject->angle);
|
||||
physics->velocity[1] = COMPONENT_PLAYER_CONTROL_LUNGE_VELOCITY * sin(worldObject->angle);
|
||||
|
||||
worldObject->heightOffsetVelocity += COMPONENT_PLAYER_CONTROL_LUNGE_HEIGHT_OFFSET_VELOCITY;
|
||||
|
||||
worldObject->isAirborne = true;
|
||||
|
||||
worldObject->heightOffset += COMPONENT_PLAYER_CONTROL_LUNGE_HEIGHT_OFFSET_VELOCITY;
|
||||
}
|
||||
|
||||
void
|
||||
_component_player_control_lunge_tick(ComponentPlayerControl* self, ECS* ecs)
|
||||
{
|
||||
self->isLunge = false;
|
||||
|
||||
if (control_pressed(ecs->control, CONTROL_ACTION_SECONDARY))
|
||||
{
|
||||
ComponentTimer* lungeTimer;
|
||||
ComponentStamina* stamina;
|
||||
ComponentWorldObject* worldObject;
|
||||
|
||||
lungeTimer = ecs_component_get(ecs, COMPONENT_TIMER, self->lungeTimerID);
|
||||
stamina = ecs_component_get(ecs, COMPONENT_STAMINA, self->component.id);
|
||||
worldObject = ecs_component_get(ecs, COMPONENT_WORLD_OBJECT, self->component.id);
|
||||
|
||||
if
|
||||
(
|
||||
lungeTimer->isFinished &&
|
||||
stamina->value >= COMPONENT_PLAYER_CONTROL_LUNGE_STAMINA_COST &&
|
||||
!worldObject->isAirborne
|
||||
)
|
||||
{
|
||||
component_timer_init(lungeTimer, ecs, COMPONENT_PLAYER_CONTROL_LUNGE_TIMER_MAX);
|
||||
|
||||
stamina->value -= COMPONENT_PLAYER_CONTROL_LUNGE_STAMINA_COST;
|
||||
self->isLunge = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (self->isLunge)
|
||||
_component_player_control_lunge(self, ecs);
|
||||
}
|
||||
|
||||
void
|
||||
component_player_control_tick(ComponentPlayerControl* self, ECS* ecs)
|
||||
{
|
||||
_component_player_control_movement_tick(self, ecs);
|
||||
_component_player_control_lunge_tick(self, ecs);
|
||||
}
|
50
src/game/ecs/component/game/component_player_control.h
Normal file
50
src/game/ecs/component/game/component_player_control.h
Normal file
@ -0,0 +1,50 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_world_object.h"
|
||||
#include "component_stamina.h"
|
||||
|
||||
#include "../../entity/visual/entity_sprite.h"
|
||||
#include "../../entity/utility/entity_timer.h"
|
||||
|
||||
static const f32 COMPONENT_PLAYER_CONTROL_VELOCITY_DEFAULT = 1.0f;
|
||||
static const f32 COMPONENT_PLAYER_CONTROL_VELOCITY_DISTANCE_MAX = 500.0f;
|
||||
static const f32 COMPONENT_PLAYER_CONTROL_VELOCITY_IN_CIRCLE_MULTIPLIER = 0.9f;
|
||||
static const f32 COMPONENT_PLAYER_CONTROL_VELOCITY_STOP_THRESHOLD = 3.0f;
|
||||
static const f32 COMPONENT_PLAYER_CONTROL_LUNGE_VELOCITY = 50.0f;
|
||||
static const f32 COMPONENT_PLAYER_CONTROL_LUNGE_HEIGHT_OFFSET_VELOCITY = 10.0f;
|
||||
static const s32 COMPONENT_PLAYER_CONTROL_LUNGE_STAMINA_COST = 25;
|
||||
static const s32 COMPONENT_PLAYER_CONTROL_LUNGE_TIMER_MAX = 10;
|
||||
|
||||
typedef struct ComponentPlayerControl
|
||||
{
|
||||
Component component;
|
||||
bool isLunge;
|
||||
EntityID lungeTimerID;
|
||||
} ComponentPlayerControl;
|
||||
|
||||
void component_player_control_add(ComponentPlayerControl* self, ECS* ecs);
|
||||
void component_player_control_tick(ComponentPlayerControl* self, ECS* ecs);
|
||||
|
||||
#define COMPONENT_PLAYER_CONTROL_DEPENDENCY_COUNT 2
|
||||
static const ComponentType COMPONENT_PLAYER_CONTROL_DEPENDENCIES[COMPONENT_PLAYER_CONTROL_DEPENDENCY_COUNT] =
|
||||
{
|
||||
COMPONENT_WORLD_OBJECT,
|
||||
COMPONENT_STAMINA,
|
||||
};
|
||||
|
||||
static const ComponentInfo COMPONENT_PLAYER_CONTROL_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
(ECSFunction)component_player_control_add,
|
||||
NULL,
|
||||
(ECSFunction)component_player_control_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_PLAYER_CONTROL,
|
||||
.size = sizeof(ComponentPlayerControl)
|
||||
};
|
16
src/game/ecs/component/game/component_power.c
Normal file
16
src/game/ecs/component/game/component_power.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "component_power.h"
|
||||
|
||||
void
|
||||
component_power_init(ComponentPower* self, ECS* ecs, f32 max, f32 gain)
|
||||
{
|
||||
self->value = max;
|
||||
self->max = max;
|
||||
self->gain = gain;
|
||||
}
|
||||
|
||||
void
|
||||
component_power_tick(ComponentPower* self, ECS* ecs)
|
||||
{
|
||||
self->value += self->gain;
|
||||
self->value = MAX(self->value, self->max);
|
||||
}
|
31
src/game/ecs/component/game/component_power.h
Normal file
31
src/game/ecs/component/game/component_power.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../ecs_entity.h"
|
||||
|
||||
typedef struct ComponentPower
|
||||
{
|
||||
Component component;
|
||||
f32 value;
|
||||
f32 max;
|
||||
f32 gain;
|
||||
} ComponentPower;
|
||||
|
||||
void component_power_tick(ComponentPower* self, ECS* ecs);
|
||||
void component_power_init(ComponentPower* self, ECS* ecs, f32 max, f32 gain);
|
||||
|
||||
static const ComponentInfo COMPONENT_POWER_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_power_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_POWER,
|
||||
.size = sizeof(ComponentPower)
|
||||
};
|
46
src/game/ecs/component/game/component_solid.c
Normal file
46
src/game/ecs/component/game/component_solid.c
Normal file
@ -0,0 +1,46 @@
|
||||
#include "component_solid.h"
|
||||
|
||||
void _component_solid_collisions_tick(ComponentSolid* self, ECS* ecs);
|
||||
|
||||
void
|
||||
_component_solid_collisions_tick(ComponentSolid* self, ECS* ecs)
|
||||
{
|
||||
ComponentCircleCollider* circleCollider;
|
||||
ComponentPhysics* physics;
|
||||
|
||||
circleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id);
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
|
||||
for (s32 i = 0; i < (s32)circleCollider->collisions.count; i++)
|
||||
{
|
||||
ComponentPhysics* collidePhysics;
|
||||
ComponentCircleCollider* collideCircleCollider;
|
||||
EntityID* id;
|
||||
f32 angle;
|
||||
|
||||
id = vector_get(&circleCollider->collisions, i);
|
||||
|
||||
collidePhysics = ecs_component_get(ecs, COMPONENT_PHYSICS, *id);
|
||||
collideCircleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, *id);
|
||||
|
||||
angle = ATAN
|
||||
(
|
||||
physics->position[0],
|
||||
collidePhysics->position[0],
|
||||
physics->position[1],
|
||||
collidePhysics->position[1]
|
||||
);
|
||||
|
||||
collidePhysics->position[0] = physics->position[0] + ((circleCollider->circle.radius * 2) * cos(angle));
|
||||
collidePhysics->position[1] = physics->position[1] + ((circleCollider->circle.radius * 2) * sin(angle));
|
||||
|
||||
collidePhysics->position[0] += (collideCircleCollider->circle.radius * 2) * cos(angle);
|
||||
collidePhysics->position[1] += (collideCircleCollider->circle.radius * 2) * sin(angle);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
component_solid_tick(ComponentSolid* self, ECS* ecs)
|
||||
{
|
||||
_component_solid_collisions_tick(self, ecs);
|
||||
}
|
27
src/game/ecs/component/game/component_solid.h
Normal file
27
src/game/ecs/component/game/component_solid.h
Normal file
@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_world_object.h"
|
||||
|
||||
typedef struct ComponentSolid
|
||||
{
|
||||
Component component;
|
||||
} ComponentSolid;
|
||||
|
||||
void component_solid_tick(ComponentSolid* self, ECS* ecs);
|
||||
|
||||
static const ComponentInfo COMPONENT_SOLID_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_solid_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_SOLID,
|
||||
.size = sizeof(ComponentSolid)
|
||||
};
|
13
src/game/ecs/component/game/component_stage.c
Normal file
13
src/game/ecs/component/game/component_stage.c
Normal file
@ -0,0 +1,13 @@
|
||||
#include "component_stage.h"
|
||||
|
||||
void
|
||||
component_stage_init(ComponentStage* self, ECS* ecs, u32 value)
|
||||
{
|
||||
self->value = value;
|
||||
}
|
||||
|
||||
void
|
||||
component_stage_tick(ComponentStage* self, ECS* ecs)
|
||||
{
|
||||
|
||||
}
|
29
src/game/ecs/component/game/component_stage.h
Normal file
29
src/game/ecs/component/game/component_stage.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../ecs_entity.h"
|
||||
|
||||
typedef struct ComponentStage
|
||||
{
|
||||
Component component;
|
||||
u32 value;
|
||||
} ComponentStage;
|
||||
|
||||
void component_stage_tick(ComponentStage* self, ECS* ecs);
|
||||
void component_stage_init(ComponentStage* self, ECS* ecs, u32 value);
|
||||
|
||||
static const ComponentInfo COMPONENT_STAGE_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_stage_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_STAGE,
|
||||
.size = sizeof(ComponentStage)
|
||||
};
|
16
src/game/ecs/component/game/component_stamina.c
Normal file
16
src/game/ecs/component/game/component_stamina.c
Normal file
@ -0,0 +1,16 @@
|
||||
#include "component_stamina.h"
|
||||
|
||||
void
|
||||
component_stamina_init(ComponentStamina* self, ECS* ecs, f32 max, f32 gain)
|
||||
{
|
||||
self->value = max;
|
||||
self->max = max;
|
||||
self->gain = gain;
|
||||
}
|
||||
|
||||
void
|
||||
component_stamina_tick(ComponentStamina* self, ECS* ecs)
|
||||
{
|
||||
self->value += self->gain;
|
||||
self->value = MAX(self->value, self->max);
|
||||
}
|
31
src/game/ecs/component/game/component_stamina.h
Normal file
31
src/game/ecs/component/game/component_stamina.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../ecs_entity.h"
|
||||
|
||||
typedef struct ComponentStamina
|
||||
{
|
||||
Component component;
|
||||
f32 value;
|
||||
f32 max;
|
||||
f32 gain;
|
||||
} ComponentStamina;
|
||||
|
||||
void component_stamina_tick(ComponentStamina* self, ECS* ecs);
|
||||
void component_stamina_init(ComponentStamina* self, ECS* ecs, f32 max, f32 gain);
|
||||
|
||||
static const ComponentInfo COMPONENT_STAMINA_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_stamina_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_STAMINA,
|
||||
.size = sizeof(ComponentStamina)
|
||||
};
|
37
src/game/ecs/component/game/component_take_food.c
Normal file
37
src/game/ecs/component/game/component_take_food.c
Normal file
@ -0,0 +1,37 @@
|
||||
#include "component_take_food.h"
|
||||
|
||||
void
|
||||
component_take_food_tick(ComponentTakeFood* self, ECS* ecs)
|
||||
{
|
||||
ComponentCircleCollider* circleCollider;
|
||||
|
||||
circleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id);
|
||||
|
||||
self->isTakeFood = false;
|
||||
|
||||
ecs->isLog = false;
|
||||
|
||||
for (s32 i = 0; i < (s32)circleCollider->collisions.count; i++)
|
||||
{
|
||||
ComponentFood* collideFood;
|
||||
ComponentFood* food;
|
||||
EntityID* id;
|
||||
|
||||
id = vector_get(&circleCollider->collisions, i);
|
||||
|
||||
collideFood = ecs_component_get(ecs, COMPONENT_FOOD, *id);
|
||||
food = ecs_component_get(ecs, COMPONENT_FOOD, self->component.id);
|
||||
|
||||
if (!collideFood)
|
||||
continue;
|
||||
|
||||
if (collideFood->value > 0)
|
||||
{
|
||||
food->value += (collideFood->value * food->multiplier);
|
||||
collideFood->value = 0;
|
||||
self->isTakeFood = true;
|
||||
}
|
||||
}
|
||||
|
||||
ecs->isLog = true;
|
||||
}
|
29
src/game/ecs/component/game/component_take_food.h
Normal file
29
src/game/ecs/component/game/component_take_food.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_world_object.h"
|
||||
#include "component_food.h"
|
||||
|
||||
typedef struct ComponentTakeFood
|
||||
{
|
||||
Component component;
|
||||
bool isTakeFood;
|
||||
} ComponentTakeFood;
|
||||
|
||||
void component_take_food_tick(ComponentTakeFood* self, ECS* ecs);
|
||||
|
||||
static const ComponentInfo COMPONENT_TAKE_FOOD_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_take_food_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_TAKE_FOOD,
|
||||
.size = sizeof(ComponentTakeFood)
|
||||
};
|
12
src/game/ecs/component/game/component_threshold.c
Normal file
12
src/game/ecs/component/game/component_threshold.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include "component_threshold.h"
|
||||
|
||||
void
|
||||
component_threshold_tick(ComponentThreshold* self, ECS* ecs)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
component_threshold_init(ComponentThreshold* self, ECS* ecs, u32 value)
|
||||
{
|
||||
self->value = value;
|
||||
}
|
30
src/game/ecs/component/game/component_threshold.h
Normal file
30
src/game/ecs/component/game/component_threshold.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../ecs_entity.h"
|
||||
|
||||
typedef struct ComponentThreshold
|
||||
{
|
||||
Component component;
|
||||
s32 value;
|
||||
s32 max;
|
||||
} ComponentThreshold;
|
||||
|
||||
void component_threshold_tick(ComponentThreshold* self, ECS* ecs);
|
||||
void component_threshold_init(ComponentThreshold* self, ECS* ecs, u32 value);
|
||||
|
||||
static const ComponentInfo COMPONENT_THRESHOLD_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_threshold_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_THRESHOLD,
|
||||
.size = sizeof(ComponentThreshold)
|
||||
};
|
213
src/game/ecs/component/game/component_world_object.c
Normal file
213
src/game/ecs/component/game/component_world_object.c
Normal file
@ -0,0 +1,213 @@
|
||||
#include "component_world_object.h"
|
||||
|
||||
void _component_world_object_shadow_set(ComponentWorldObject* self, ECS* ecs);
|
||||
void _component_world_object_height_offset_set(ComponentWorldObject* self, ECS* ecs);
|
||||
void _component_world_object_depth_set(ComponentWorldObject* self, ECS* ecs);
|
||||
void _component_world_object_circle_collider_set(ComponentWorldObject* self, ECS* ecs);
|
||||
void _component_world_object_direction_set(ComponentWorldObject* self, ECS* ecs);
|
||||
|
||||
void
|
||||
_component_world_object_shadow_set(ComponentWorldObject* self, ECS* ecs)
|
||||
{
|
||||
ComponentTextureQuad* shadowTextureQuad;
|
||||
ComponentTextureQuad* textureQuad;
|
||||
ComponentCircleCollider* circleCollider;
|
||||
ComponentPhysics* physics;
|
||||
f32 shadowScale;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
circleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id);
|
||||
textureQuad = ecs_component_get(ecs, COMPONENT_TEXTURE_QUAD, self->component.id);
|
||||
shadowTextureQuad = ecs_component_get(ecs, COMPONENT_TEXTURE_QUAD, self->shadowID);
|
||||
|
||||
shadowTextureQuad->size[0] = circleCollider->circle.radius;
|
||||
shadowTextureQuad->size[1] = COMPONENT_WORLD_OBJECT_SHADOW_HEIGHT;
|
||||
|
||||
shadowTextureQuad->position[0] = physics->position[0];
|
||||
shadowTextureQuad->position[1] = physics->position[1] + (textureQuad->size[1] / 2.0f);
|
||||
shadowTextureQuad->position[2] = physics->position[2] + COMPONENT_WORLD_OBJECT_SHADOW_Z_OFFSET;
|
||||
|
||||
shadowScale = 1 - (self->heightOffset * COMPONENT_WORLD_OBJECT_HEIGHT_OFFSET_SHADOW_SCALE_MULTIPLIER);
|
||||
|
||||
shadowTextureQuad->scale[0] = shadowScale;
|
||||
shadowTextureQuad->scale[1] = shadowScale;
|
||||
|
||||
shadowTextureQuad->scale[0] = MIN(shadowTextureQuad->scale[0], 0);
|
||||
shadowTextureQuad->scale[1] = MIN(shadowTextureQuad->scale[1], 0);
|
||||
}
|
||||
|
||||
void
|
||||
_component_world_object_height_offset_set(ComponentWorldObject* self, ECS* ecs)
|
||||
{
|
||||
ComponentTextureQuad* textureQuad;
|
||||
|
||||
textureQuad = ecs_component_get(ecs, COMPONENT_TEXTURE_QUAD, self->component.id);
|
||||
|
||||
if (self->isGravityAffected)
|
||||
self->heightOffsetVelocity -= COMPONENT_WORLD_OBJECT_GRAVITY;
|
||||
|
||||
self->heightOffset += self->heightOffsetVelocity;
|
||||
|
||||
if (self->heightOffset <= 0.0f)
|
||||
{
|
||||
self->isAirborne = false;
|
||||
self->heightOffset = 0.0f;
|
||||
self->heightOffsetVelocity = 0.0f;
|
||||
}
|
||||
else
|
||||
self->isAirborne = true;
|
||||
|
||||
textureQuad->offset[1] = -self->heightOffset;
|
||||
}
|
||||
|
||||
void
|
||||
_component_world_object_circle_collider_set(ComponentWorldObject* self, ECS* ecs)
|
||||
{
|
||||
ComponentCircleCollider* circleCollider;
|
||||
ComponentTextureQuad* textureQuad;
|
||||
ComponentPhysics* physics;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
textureQuad = ecs_component_get(ecs, COMPONENT_TEXTURE_QUAD, self->component.id);
|
||||
circleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id);
|
||||
|
||||
circleCollider->circle.position[0] = physics->position[0];
|
||||
circleCollider->circle.position[1] = physics->position[1] + (textureQuad->size[1] / 2.0f);
|
||||
}
|
||||
|
||||
void
|
||||
_component_world_object_depth_set(ComponentWorldObject* self, ECS* ecs)
|
||||
{
|
||||
ComponentPhysics* physics;
|
||||
ComponentTextureQuad* textureQuad;
|
||||
f32 depth;
|
||||
f32 yOffset;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
textureQuad = ecs_component_get(ecs, COMPONENT_TEXTURE_QUAD, self->component.id);
|
||||
|
||||
yOffset = COMPONENT_WORLD_OBJECT_DEPTH_Y_OFFSET_MULTIPLIER * ((physics->position[1] + textureQuad->size[1]) / COMPONENT_WORLD_OBJECT_BOUNDS[3]);
|
||||
|
||||
depth = COMPONENT_WORLD_OBJECT_DEPTH_MAX - yOffset;
|
||||
depth += COMPONENT_WORLD_OBJECT_DEPTH_MIN;
|
||||
|
||||
physics->position[2] = depth;
|
||||
}
|
||||
|
||||
void
|
||||
_component_world_object_bounds_set(ComponentWorldObject* self, ECS* ecs)
|
||||
{
|
||||
ComponentPhysics* physics;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
|
||||
physics->position[0] = CLAMP(physics->position[0], COMPONENT_WORLD_OBJECT_BOUNDS[0], COMPONENT_WORLD_OBJECT_BOUNDS[2]);
|
||||
physics->position[1] = CLAMP(physics->position[1], COMPONENT_WORLD_OBJECT_BOUNDS[1], COMPONENT_WORLD_OBJECT_BOUNDS[3]);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
_component_world_object_direction_set(ComponentWorldObject* self, ECS* ecs)
|
||||
{
|
||||
if
|
||||
(
|
||||
(self->angle >= 0.0f && self->angle < PI_FOURTH) ||
|
||||
(self->angle >= PI + PI_HALF + PI_FOURTH && self->angle < TAU)
|
||||
)
|
||||
self->direction = DIRECTION_RIGHT;
|
||||
|
||||
if (self->angle >= PI_FOURTH && self->angle < PI_HALF + PI_FOURTH)
|
||||
self->direction = DIRECTION_DOWN;
|
||||
|
||||
if (self->angle >= PI_HALF + PI_FOURTH && self->angle < PI + PI_FOURTH)
|
||||
self->direction = DIRECTION_LEFT;
|
||||
|
||||
if (self->angle >= PI + PI_FOURTH && self->angle < PI + PI_HALF + PI_FOURTH)
|
||||
self->direction = DIRECTION_UP;
|
||||
}
|
||||
|
||||
void
|
||||
component_world_object_init
|
||||
(
|
||||
ComponentWorldObject* self,
|
||||
ECS* ecs,
|
||||
Texture* texture,
|
||||
vec2 size,
|
||||
vec3 position,
|
||||
f32 heightOffset,
|
||||
f32 radius
|
||||
)
|
||||
{
|
||||
component_game_object_init
|
||||
(
|
||||
ecs_component_get(ecs, COMPONENT_GAME_OBJECT, self->component.id),
|
||||
ecs,
|
||||
texture,
|
||||
COMPONENT_WORLD_OBJECT_BUFFER,
|
||||
COMPONENT_WORLD_OBJECT_ORIGIN,
|
||||
size,
|
||||
position
|
||||
);
|
||||
|
||||
component_circle_collider_init
|
||||
(
|
||||
ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, self->component.id),
|
||||
(f32*)position,
|
||||
radius
|
||||
);
|
||||
|
||||
component_physics_init
|
||||
(
|
||||
ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id),
|
||||
ecs,
|
||||
position,
|
||||
COMPONENT_WORLD_OBJECT_VELOCITY_MAX,
|
||||
COMPONENT_WORLD_OBJECT_FRICTION
|
||||
);
|
||||
|
||||
self->shadowID = entity_sprite_add
|
||||
(
|
||||
ecs,
|
||||
&ecs->resources->textures[TEXTURE_SHADOW],
|
||||
COMPONENT_WORLD_OBJECT_BUFFER,
|
||||
COMPONENT_WORLD_OBJECT_ORIGIN,
|
||||
(f32*)size,
|
||||
(f32*)position
|
||||
);
|
||||
|
||||
self->heightOffset = heightOffset;
|
||||
self->isGravityAffected = true;
|
||||
|
||||
_component_world_object_shadow_set(self, ecs);
|
||||
_component_world_object_height_offset_set(self, ecs);
|
||||
_component_world_object_circle_collider_set(self, ecs);
|
||||
}
|
||||
|
||||
void
|
||||
component_world_object_add(ComponentWorldObject* self, ECS* ecs)
|
||||
{
|
||||
ecs_components_add
|
||||
(
|
||||
ecs,
|
||||
COMPONENT_WORLD_OBJECT_DEPENDENCIES,
|
||||
COMPONENT_WORLD_OBJECT_DEPENDENCY_COUNT,
|
||||
self->component.id
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
component_world_object_delete(ComponentWorldObject* self, ECS* ecs)
|
||||
{
|
||||
ecs_entity_delete(ecs, self->shadowID);
|
||||
}
|
||||
|
||||
void
|
||||
component_world_object_tick(ComponentWorldObject* self, ECS* ecs)
|
||||
{
|
||||
_component_world_object_depth_set(self, ecs);
|
||||
_component_world_object_shadow_set(self, ecs);
|
||||
_component_world_object_height_offset_set(self, ecs);
|
||||
_component_world_object_bounds_set(self, ecs);
|
||||
_component_world_object_direction_set(self, ecs);
|
||||
_component_world_object_circle_collider_set(self, ecs);
|
||||
}
|
72
src/game/ecs/component/game/component_world_object.h
Normal file
72
src/game/ecs/component/game/component_world_object.h
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_game_object.h"
|
||||
#include "../physics/component_circle_collider.h"
|
||||
|
||||
#include "../../entity/visual/entity_sprite.h"
|
||||
|
||||
static const RendererBuffer COMPONENT_WORLD_OBJECT_BUFFER = RENDERER_BUFFER_WORLD;
|
||||
static const f32 COMPONENT_WORLD_OBJECT_SHADOW_Z_OFFSET = 0.001f;
|
||||
static const f32 COMPONENT_WORLD_OBJECT_HEIGHT_OFFSET_SHADOW_SCALE_MULTIPLIER = 0.005f;
|
||||
static const f32 COMPONENT_WORLD_OBJECT_FRICTION = 0.985f;
|
||||
static const f32 COMPONENT_WORLD_OBJECT_SHADOW_HEIGHT = 32.0f;
|
||||
static const f32 COMPONENT_WORLD_OBJECT_DEPTH_Y_OFFSET_MULTIPLIER = 0.1f;
|
||||
static const f32 COMPONENT_WORLD_OBJECT_DEPTH_MIN = 0.1f;
|
||||
static const f32 COMPONENT_WORLD_OBJECT_DEPTH_MAX = 0.2f;
|
||||
static const f32 COMPONENT_WORLD_OBJECT_GRAVITY = 1.0f;
|
||||
static const vec3 COMPONENT_WORLD_OBJECT_VELOCITY_MAX = {100.0f, 100.0f, 100.0f};
|
||||
static const vec4 COMPONENT_WORLD_OBJECT_BOUNDS = {250.0f, 250.0f, 6300.0f, 3100.0f};
|
||||
|
||||
#define COMPONENT_WORLD_OBJECT_ORIGIN ORIGIN_CENTER
|
||||
|
||||
typedef struct ComponentWorldObject
|
||||
{
|
||||
Component component;
|
||||
EntityID shadowID;
|
||||
f32 heightOffset;
|
||||
f32 heightOffsetVelocity;
|
||||
f32 angle;
|
||||
Direction direction;
|
||||
bool isAirborne;
|
||||
bool isGravityAffected;
|
||||
} ComponentWorldObject;
|
||||
|
||||
void
|
||||
component_world_object_init
|
||||
(
|
||||
ComponentWorldObject* self,
|
||||
ECS* ecs,
|
||||
Texture* texture,
|
||||
vec2 size,
|
||||
vec3 position,
|
||||
f32 heightOffset,
|
||||
f32 radius
|
||||
);
|
||||
|
||||
void component_world_object_add(ComponentWorldObject* self, ECS* ecs);
|
||||
void component_world_object_delete(ComponentWorldObject* self, ECS* ecs);
|
||||
void component_world_object_tick(ComponentWorldObject* self, ECS* ecs);
|
||||
|
||||
#define COMPONENT_WORLD_OBJECT_DEPENDENCY_COUNT 2
|
||||
static const ComponentType COMPONENT_WORLD_OBJECT_DEPENDENCIES[COMPONENT_WORLD_OBJECT_DEPENDENCY_COUNT] =
|
||||
{
|
||||
COMPONENT_GAME_OBJECT,
|
||||
COMPONENT_CIRCLE_COLLIDER
|
||||
};
|
||||
|
||||
static const ComponentInfo COMPONENT_WORLD_OBJECT_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
(ECSFunction)component_world_object_add,
|
||||
(ECSFunction)component_world_object_delete,
|
||||
(ECSFunction)component_world_object_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_WORLD_OBJECT,
|
||||
.size = sizeof(ComponentWorldObject)
|
||||
};
|
66
src/game/ecs/component/physics/component_circle_collider.c
Normal file
66
src/game/ecs/component/physics/component_circle_collider.c
Normal file
@ -0,0 +1,66 @@
|
||||
#include "component_circle_collider.h"
|
||||
|
||||
void _component_circle_collider_collisions_tick(ComponentCircleCollider* self, ECS* ecs);
|
||||
|
||||
void
|
||||
_component_circle_collider_collisions_tick(ComponentCircleCollider* self, ECS* ecs)
|
||||
{
|
||||
vector_clear(&self->collisions);
|
||||
|
||||
for (s32 i = 0; i < (s32)ecs->lists[COMPONENT_CIRCLE_COLLIDER].components.count; i++)
|
||||
{
|
||||
EntityID* id;
|
||||
ComponentCircleCollider* circleCollider;
|
||||
|
||||
id = vector_get(&ecs->lists[COMPONENT_CIRCLE_COLLIDER].components, i);
|
||||
|
||||
if (*id == self->component.id)
|
||||
continue;
|
||||
|
||||
circleCollider = ecs_component_get(ecs, COMPONENT_CIRCLE_COLLIDER, *id);
|
||||
|
||||
if (circle_collide_check(&self->circle, &circleCollider->circle))
|
||||
vector_push(&self->collisions, id);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
component_circle_collider_collide_check(ComponentCircleCollider* self, ECS* ecs, EntityID id)
|
||||
{
|
||||
for (s32 i = 0; i < (s32)self->collisions.count; i++)
|
||||
{
|
||||
EntityID* checkID;
|
||||
|
||||
checkID = vector_get(&self->collisions, i);
|
||||
|
||||
if (*checkID == id)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
component_circle_collider_add(ComponentCircleCollider* self, ECS* ecs)
|
||||
{
|
||||
vector_init(&self->collisions, sizeof(EntityID));
|
||||
}
|
||||
|
||||
void
|
||||
component_circle_collider_delete(ComponentCircleCollider* self, ECS* ecs)
|
||||
{
|
||||
vector_free(&self->collisions);
|
||||
}
|
||||
|
||||
void
|
||||
component_circle_collider_tick(ComponentCircleCollider* self, ECS* ecs)
|
||||
{
|
||||
_component_circle_collider_collisions_tick(self, ecs);
|
||||
}
|
||||
|
||||
void
|
||||
component_circle_collider_init(ComponentCircleCollider* self, vec2 position, f32 radius)
|
||||
{
|
||||
glm_vec2_copy(position, self->circle.position);
|
||||
self->circle.radius = radius;
|
||||
}
|
42
src/game/ecs/component/physics/component_circle_collider.h
Normal file
42
src/game/ecs/component/physics/component_circle_collider.h
Normal file
@ -0,0 +1,42 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../ecs_entity.h"
|
||||
|
||||
#include "../../../../engine/circle.h"
|
||||
|
||||
typedef struct ComponentCircleCollider
|
||||
{
|
||||
Component component;
|
||||
Circle circle;
|
||||
Vector collisions; /* EntityID */
|
||||
} ComponentCircleCollider;
|
||||
|
||||
void component_circle_collider_add(ComponentCircleCollider* self, ECS* ecs);
|
||||
void component_circle_collider_delete(ComponentCircleCollider* self, ECS* ecs);
|
||||
void component_circle_collider_tick(ComponentCircleCollider* self, ECS* ecs);
|
||||
bool component_circle_collider_collide_check(ComponentCircleCollider* self, ECS* ecs, EntityID id);
|
||||
|
||||
void component_circle_collider_init
|
||||
(
|
||||
ComponentCircleCollider* self,
|
||||
vec2 position,
|
||||
f32 radius
|
||||
);
|
||||
|
||||
static const ComponentInfo COMPONENT_CIRCLE_COLLIDER_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
|
||||
(ECSFunction)component_circle_collider_add,
|
||||
(ECSFunction)component_circle_collider_delete,
|
||||
(ECSFunction)component_circle_collider_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_CIRCLE_COLLIDER,
|
||||
.size = sizeof(ComponentCircleCollider)
|
||||
};
|
@ -0,0 +1,21 @@
|
||||
#include "component_copy_mouse_position.h"
|
||||
|
||||
void
|
||||
component_copy_mouse_position_add(ComponentCopyMousePosition* self, ECS* ecs)
|
||||
{
|
||||
component_copy_mouse_position_tick(self, ecs);
|
||||
}
|
||||
|
||||
void
|
||||
component_copy_mouse_position_tick(ComponentCopyMousePosition* self, ECS* ecs)
|
||||
{
|
||||
ComponentPhysics* physics;
|
||||
vec2 mousePosition;
|
||||
|
||||
physics = ecs_component_get(ecs, COMPONENT_PHYSICS, self->component.id);
|
||||
|
||||
mouse_buffer_position_get(&ecs->input->mouse, RENDERER_BUFFER_CURSOR, ecs->renderer, mousePosition);
|
||||
|
||||
physics->position[0] = mousePosition[0];
|
||||
physics->position[1] = mousePosition[1];
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include "component_physics.h"
|
||||
|
||||
#include "../../../input/input.h"
|
||||
|
||||
typedef struct ComponentCopyMousePosition
|
||||
{
|
||||
Component component;
|
||||
} ComponentCopyMousePosition;
|
||||
|
||||
void component_copy_mouse_position_add(ComponentCopyMousePosition* self, ECS* ecs);
|
||||
void component_copy_mouse_position_tick(ComponentCopyMousePosition* self, ECS* ecs);
|
||||
|
||||
static const ComponentInfo COMPONENT_COPY_MOUSE_POSITION_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
(ECSFunction)component_copy_mouse_position_add,
|
||||
NULL,
|
||||
(ECSFunction)component_copy_mouse_position_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_COPY_MOUSE_POSITION,
|
||||
.size = sizeof(ComponentCopyMousePosition)
|
||||
};
|
67
src/game/ecs/component/physics/component_physics.c
Normal file
67
src/game/ecs/component/physics/component_physics.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "component_physics.h"
|
||||
|
||||
void
|
||||
component_physics_tick(ComponentPhysics* self, ECS* ecs)
|
||||
{
|
||||
glm_vec3_add(self->velocity, self->position, self->position);
|
||||
|
||||
glm_vec3_scale(self->velocity, self->friction, self->velocity);
|
||||
|
||||
self->velocity[0] = MAX(self->velocity[0], self->velocityMax[0]);
|
||||
self->velocity[1] = MAX(self->velocity[1], self->velocityMax[1]);
|
||||
self->velocity[2] = MAX(self->velocity[2], self->velocityMax[2]);
|
||||
|
||||
if
|
||||
(
|
||||
self->velocity[0] != 0.0f ||
|
||||
self->velocity[1] != 0.0f
|
||||
)
|
||||
self->isMoving = true;
|
||||
else
|
||||
self->isMoving = false;
|
||||
}
|
||||
|
||||
void
|
||||
component_physics_next_position_get(ComponentPhysics* self, ECS* ecs, vec2 position)
|
||||
{
|
||||
position[0] = self->position[0] + self->velocity[0];
|
||||
position[1] = self->position[1] + self->velocity[1];
|
||||
}
|
||||
|
||||
f32
|
||||
component_physics_next_position_distance_get(ComponentPhysics* self, ECS* ecs)
|
||||
{
|
||||
vec2 position;
|
||||
|
||||
component_physics_next_position_get(self, ecs, position);
|
||||
|
||||
return DISTANCE_2D
|
||||
(
|
||||
position[0],
|
||||
self->position[0],
|
||||
position[1],
|
||||
self->position[1]
|
||||
);
|
||||
}
|
||||
|
||||
void
|
||||
component_physics_add(ComponentPhysics* self, ECS* ecs)
|
||||
{
|
||||
self->friction = COMPONENT_PHYSICS_FRICTION_DEFAULT;
|
||||
glm_vec3_copy((f32*)COMPONENT_PHYSICS_VELOCITY_MAX_DEFAULT, self->velocityMax);
|
||||
}
|
||||
|
||||
void
|
||||
component_physics_init
|
||||
(
|
||||
ComponentPhysics* self,
|
||||
ECS* ecs,
|
||||
const vec3 position,
|
||||
const vec3 velocityMax,
|
||||
f32 friction
|
||||
)
|
||||
{
|
||||
glm_vec3_copy((f32*)position, self->position);
|
||||
glm_vec3_copy((f32*)velocityMax, self->velocityMax);
|
||||
self->friction = friction;
|
||||
}
|
48
src/game/ecs/component/physics/component_physics.h
Normal file
48
src/game/ecs/component/physics/component_physics.h
Normal file
@ -0,0 +1,48 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../ecs_entity.h"
|
||||
|
||||
#include "../../../input/control.h"
|
||||
|
||||
static const f32 COMPONENT_PHYSICS_FRICTION_DEFAULT = 1.0f;
|
||||
static const vec3 COMPONENT_PHYSICS_VELOCITY_MAX_DEFAULT = {1000.0f, 1000.0f, 1000.0f};
|
||||
|
||||
typedef struct ComponentPhysics
|
||||
{
|
||||
Component component;
|
||||
vec3 position;
|
||||
vec3 velocity;
|
||||
vec3 velocityMax;
|
||||
f32 friction;
|
||||
bool isMoving;
|
||||
} ComponentPhysics;
|
||||
|
||||
void component_physics_tick(ComponentPhysics* self, ECS* ecs);
|
||||
void component_physics_next_position_get(ComponentPhysics* self, ECS* ecs, vec2 position);
|
||||
f32 component_physics_next_position_distance_get(ComponentPhysics* self, ECS* ecs);
|
||||
|
||||
void component_physics_init
|
||||
(
|
||||
ComponentPhysics* self,
|
||||
ECS* ecs,
|
||||
const vec3 position,
|
||||
const vec3 velocityMax,
|
||||
f32 friction
|
||||
);
|
||||
|
||||
static const ComponentInfo COMPONENT_PHYSICS_INFO =
|
||||
{
|
||||
.system =
|
||||
{
|
||||
.functions =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
(ECSFunction)component_physics_tick,
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
},
|
||||
.type = COMPONENT_PHYSICS,
|
||||
.size = sizeof(ComponentPhysics)
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user