Compare commits
No commits in common. "master" and "v0.0.1.1" have entirely different histories.
156 changed files with 8118 additions and 15233 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -32,7 +32,6 @@ bld/
|
||||||
[Oo]ut/
|
[Oo]ut/
|
||||||
[Ll]og/
|
[Ll]og/
|
||||||
[Ll]ogs/
|
[Ll]ogs/
|
||||||
[Bb]uild/
|
|
||||||
|
|
||||||
# Visual Studio 2015/2017 cache/options directory
|
# Visual Studio 2015/2017 cache/options directory
|
||||||
.vs/
|
.vs/
|
||||||
|
|
@ -365,5 +364,3 @@ FodyWeavers.xsd
|
||||||
/Resources/weapons/.bubblegun.xml.swp
|
/Resources/weapons/.bubblegun.xml.swp
|
||||||
*.swp
|
*.swp
|
||||||
/Resources/scenes/.debugScene.xml.swp
|
/Resources/scenes/.debugScene.xml.swp
|
||||||
compile_commands.json
|
|
||||||
compile_flags.txt
|
|
||||||
|
|
|
||||||
|
|
@ -12,23 +12,10 @@ endif()
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
SET(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
SET(CMAKE_EXPORT_COMPILE_COMMANDS 1)
|
||||||
#SET(SOL_LUAJIT 1)
|
|
||||||
|
|
||||||
#SET(TRACY_ENABLE 1)
|
SET(TRACY_ENABLE 1)
|
||||||
#SET(TRACY_ON_DEMAND 1)
|
SET(TRACY_ON_DEMAND 1)
|
||||||
#SET(TRACY_ONLY_LOCALHOST 1)
|
SET(TRACY_ONLY_LOCALHOST 1)
|
||||||
|
|
||||||
SET(FT_DISABLE_BROTLI 1)
|
|
||||||
SET(FT_DISABLE_BZIP2 1)
|
|
||||||
SET(FT_DISABLE_HARFBUZZ 1)
|
|
||||||
SET(FT_DISABLE_PNG 1)
|
|
||||||
SET(FT_DISABLE_ZLIB 1)
|
|
||||||
|
|
||||||
option(GLM_ENABLE_FAST_MATH OFF)
|
|
||||||
|
|
||||||
# -fsanitize=address I will forget, renable this flag no more leaks allowed!
|
|
||||||
|
|
||||||
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -ffloat-store -fexcess-precision=standard -ffp-contract=off")
|
|
||||||
|
|
||||||
FetchContent_Declare(
|
FetchContent_Declare(
|
||||||
tracy
|
tracy
|
||||||
|
|
@ -38,6 +25,8 @@ FetchContent_Declare(
|
||||||
GIT_PROGRESS TRUE
|
GIT_PROGRESS TRUE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
FetchContent_MakeAvailable(tracy)
|
||||||
|
|
||||||
project ("YuppleMayham")
|
project ("YuppleMayham")
|
||||||
|
|
||||||
# Include sub-projects.
|
# Include sub-projects.
|
||||||
|
|
|
||||||
66
README.md
66
README.md
|
|
@ -1,66 +0,0 @@
|
||||||
# Personal Game Engine
|
|
||||||
|
|
||||||
A modular, event driven 2D game engine, built from scratch to learn engine architecture and low-level graphics programming.
|
|
||||||
|
|
||||||
Supports sprite-based animation, Lua scripting, XML-driven definitions and Tiled map creation.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
- Event-based animation and sound system
|
|
||||||
- Animation and tile-sets supported by texture atlases
|
|
||||||
- Map creation and collision map support in Tiled map editor
|
|
||||||
- Component-based entity structure
|
|
||||||
- Basic audio engine integration via OpenAL (XML definitions)
|
|
||||||
- Basic physics system
|
|
||||||
- Lua scripted enemy and weapon behavior
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Current Status
|
|
||||||
|
|
||||||
**Work in Progress** - This project is still under active development, I am currently cleaning up my resource management system for better ease of use for future users of this engine.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Dependencies
|
|
||||||
|
|
||||||
- SDL2, SDL2_image
|
|
||||||
- OpenGL 3.3
|
|
||||||
- sol2 (Lua binding)
|
|
||||||
- TinyXML2
|
|
||||||
- OpenAL
|
|
||||||
- Freetype
|
|
||||||
- GLM
|
|
||||||
- pkg-config
|
|
||||||
- CMake
|
|
||||||
|
|
||||||
## Build Instructions
|
|
||||||
|
|
||||||
1. Clone the repo (git.wienermeister.net/snakert12345/yupplemayham.git)
|
|
||||||
2. Install list of dependencies. Ensure they're available via pkg-config
|
|
||||||
3. Build with CMake
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone https://git.wienermeister.net/snakert12345/yupplemayham.git
|
|
||||||
cd yupplemayham
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake ..
|
|
||||||
make
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Screenshot
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Roadmap
|
|
||||||
|
|
||||||
- Save/Load system
|
|
||||||
- Modular and scalable menu system
|
|
||||||
- In-game dialog and conversation systems
|
|
||||||
- Expanded combat system
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
<!--
|
|
||||||
<animations>
|
<animations>
|
||||||
<animation name="bubble_idle_anim" type="idle">
|
<animation name="bubble_idle_anim" type="idle">
|
||||||
<FPS>2</FPS>
|
<FPS>2</FPS>
|
||||||
<sprite path="sprites/bubbleoAtlas64.png" frameSize="64.0"/>
|
<sprite path="sprites/bubbleoAtlas64.png" frameSize="64.0"/>
|
||||||
</animation>
|
</animation>
|
||||||
</animations>
|
</animations>
|
||||||
-->
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
|
|
||||||
<!-- Player Animations -->
|
|
||||||
<animation id="character/player/idle" directional="true" FPS="5" frameSize="64.0" atlas="sprites/player3AtlasIdle64.png"/>
|
|
||||||
<animation id="character/player/move" directional="true" FPS="7" frameSize="64.0" atlas="sprites/player3AtlasMove64.png"/>
|
|
||||||
|
|
||||||
<!-- Fallback animations -->
|
|
||||||
<animation id="character/tmp/move" directional="false" FPS="7" frameSize="128.0" atlas="sprites/player2Atlas.png"/>
|
|
||||||
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<animations directional="true">
|
|
||||||
<animation name="player_move_anim" type="move">
|
|
||||||
<FPS>7</FPS>
|
|
||||||
<sprite path="sprites/player3AtlasMove64.png" frameSize="64.0"/>
|
|
||||||
</animation>
|
|
||||||
|
|
||||||
<animation name="player_idle_anim" type="idle">
|
|
||||||
<FPS>5</FPS>
|
|
||||||
<sprite path="sprites/player3AtlasIdle64.png" frameSize="64.0"/>
|
|
||||||
</animation>
|
|
||||||
</animations>
|
|
||||||
-->
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
<!--
|
|
||||||
<animations>
|
<animations>
|
||||||
<animation name="machine_gun_idle_anim" type="idle">
|
<animation name="machine_gun_idle_anim" type="idle">
|
||||||
<FPS>4</FPS>
|
<FPS>4</FPS>
|
||||||
|
|
@ -9,4 +8,3 @@
|
||||||
<sprite path="sprites/machineGunAtlasReload256.png" frameSize="256.0"/>
|
<sprite path="sprites/machineGunAtlasReload256.png" frameSize="256.0"/>
|
||||||
</animation>
|
</animation>
|
||||||
</animations>
|
</animations>
|
||||||
-->
|
|
||||||
|
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
<!-- Bubble -->
|
|
||||||
<animation id="obj/bubble/idle" FPS="2" frameSize="64.0" atlas="sprites/bubbleoAtlas64.png"/>
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
<!--
|
|
||||||
<animations>
|
<animations>
|
||||||
<animation name="pistol_idle_anim" type="idle">
|
<animation name="pistol_idle_anim" type="idle">
|
||||||
<FPS>4</FPS>
|
<FPS>4</FPS>
|
||||||
|
|
@ -9,4 +8,3 @@
|
||||||
<sprite path="sprites/pistolAtlasReload256.png" frameSize="256.0"/>
|
<sprite path="sprites/pistolAtlasReload256.png" frameSize="256.0"/>
|
||||||
</animation>
|
</animation>
|
||||||
</animations>
|
</animations>
|
||||||
-->
|
|
||||||
|
|
|
||||||
11
Resources/animations/player_anim.xml
Normal file
11
Resources/animations/player_anim.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<animations directional="true">
|
||||||
|
<animation name="player_move_anim" type="move">
|
||||||
|
<FPS>7</FPS>
|
||||||
|
<sprite path="sprites/player3AtlasMove64.png" frameSize="64.0"/>
|
||||||
|
</animation>
|
||||||
|
|
||||||
|
<animation name="player_idle_anim" type="idle">
|
||||||
|
<FPS>5</FPS>
|
||||||
|
<sprite path="sprites/player3AtlasIdle64.png" frameSize="64.0"/>
|
||||||
|
</animation>
|
||||||
|
</animations>
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
<!--
|
|
||||||
<animations>
|
<animations>
|
||||||
<animation name="shot_gun_idle_anim" type="idle">
|
<animation name="shot_gun_idle_anim" type="idle">
|
||||||
<FPS>4</FPS>
|
<FPS>4</FPS>
|
||||||
|
|
@ -13,4 +12,3 @@
|
||||||
<sprite path="sprites/shotGunReload128.png" frameSize="128.0"/>
|
<sprite path="sprites/shotGunReload128.png" frameSize="128.0"/>
|
||||||
</animation>
|
</animation>
|
||||||
</animations>
|
</animations>
|
||||||
-->
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
<!--
|
|
||||||
<animations>
|
<animations>
|
||||||
<animation name="tmp_enemy_move_anim" type="move">
|
<animation name="tmp_enemy_move_anim" type="move">
|
||||||
<FPS>7</FPS>
|
<FPS>7</FPS>
|
||||||
<sprite path="sprites/player2Atlas.png" frameSize="128.0"/>
|
<sprite path="sprites/player2Atlas.png" frameSize="128.0"/>
|
||||||
</animation>
|
</animation>
|
||||||
</animations>
|
</animations>
|
||||||
-->
|
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
<!-- Machine Gun -->
|
|
||||||
<animation id="gun/machine/idle" FPS="4" frameSize="256.0" atlas="sprites/machineGunAtlas256.png"/>
|
|
||||||
<animation id="gun/machine/reload" FPS="6" frameSize="256.0" atlas="sprites/machineGunAtlasReload256.png"/>
|
|
||||||
|
|
||||||
<!-- Pistol -->
|
|
||||||
<animation id="gun/pistol/idle" FPS="4" frameSize="256.0" atlas="sprites/pistolAtlas256.png"/>
|
|
||||||
<animation id="gun/pistol/reload" FPS="8" frameSize="256.0" atlas="sprites/pistolAtlasReload256.png"/>
|
|
||||||
|
|
||||||
<!-- Shotgun -->
|
|
||||||
<animation id="gun/shotgun/idle" FPS="4" frameSize="128.0" atlas="sprites/shotGunIdle128.png"/>
|
|
||||||
<animation id="gun/shotgun/fire" FPS="8" frameSize="128.0" atlas="sprites/shotGunFire128.png"/>
|
|
||||||
<animation id="gun/shotgun/reload" FPS="8" frameSize="128.0" atlas="sprites/shotGunReload128.png"/>
|
|
||||||
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
<monster id="monster/shooty/bighead" anim="character/tmp" weapon="gun/pistol" aggressive="true" behaviour="script/behaviour/grunt" hp="10.0"/>
|
|
||||||
<monster id="monster/shooty/clone" anim="character/player" weapon="gun/shotgun" aggressive="true" behaviour="script/behaviour/grunt" hp="15.0"/>
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -3,17 +3,20 @@
|
||||||
<scene type="shooter" id="000" bg="backgrounds/blue_sky.png">
|
<scene type="shooter" id="000" bg="backgrounds/blue_sky.png">
|
||||||
<map name="newmap"/>
|
<map name="newmap"/>
|
||||||
<entities>
|
<entities>
|
||||||
<player x="7" y="5" weapon="gun/shotgun">
|
<player x="7" y="5" weapon="shotGun">
|
||||||
<animation id="character/player"/>
|
<animation name="player_anim"/>
|
||||||
</player>
|
</player>
|
||||||
<entity x="10" y="3" weapon="gun/pistol">
|
<entity x="10" y="3" weapon="pistolGun">
|
||||||
<animation id="character/player"/>
|
<animation name="player_anim"/>
|
||||||
<script id="script/behaviour/grunt"/>
|
<script file="scripts/ai/grunt_behaviour.lua"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity x="6" y="3" weapon="gun/pistol">
|
<entity x="6" y="3" weapon="pistolGun">
|
||||||
<animation id="character/tmp"/>
|
<animation name="tmp_enemy_anim"/>
|
||||||
<script id="script/behaviour/grunt"/>
|
<script file="scripts/ai/grunt_behaviour.lua"/>
|
||||||
|
</entity>
|
||||||
|
<entity x="5" y="3" weapon="pistolGun">
|
||||||
|
<animation name="tmp_enemy_anim"/>
|
||||||
|
<script file="scripts/ai/grunt_behaviour.lua"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity x="5" y="3" weapon="gun/pistol" monster_id="monster/shooty/bighead"/>
|
|
||||||
</entities>
|
</entities>
|
||||||
</scene>
|
</scene>
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,31 @@
|
||||||
-- global vars
|
-- global vars
|
||||||
MoveLeft = true
|
patrolDestination = { x=500.0, y=500.0, z=0.0 }
|
||||||
|
moveLeft = true
|
||||||
-- helper functions
|
-- helper functions
|
||||||
local function watchPosition(actor, pos)
|
function watchPosition(actor, pos)
|
||||||
local y = pos.y - actor.position.y
|
local y = pos.y - actor.position.y
|
||||||
local x = pos.x - actor.position.x
|
local x = pos.x - actor.position.x
|
||||||
local rotation = math.atan2(y, x)
|
local rotation = math.atan(y, x)
|
||||||
actor.rotation = math.deg(rotation)
|
actor.rotation = math.deg(rotation)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function distance(a, b)
|
function distance(a, b)
|
||||||
local dx = a.x - b.x
|
local dx = a.x - b.x
|
||||||
local dy = a.y - b.y
|
local dy = a.y - b.y
|
||||||
return math.sqrt(dx * dx + dy * dy)
|
return math.sqrt(dx * dx + dy * dy)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function moveTo(actor, pos)
|
||||||
|
local a = actor
|
||||||
|
local p = pos
|
||||||
|
watchPosition(a, p)
|
||||||
|
if distance(a.position, p) < 50 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
a:moveForward()
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
-- Behaviour Functions called on AI
|
-- Behaviour Functions called on AI
|
||||||
|
|
||||||
-- These functions are ai behaviour functions called in the game
|
-- These functions are ai behaviour functions called in the game
|
||||||
|
|
@ -36,12 +48,24 @@ end
|
||||||
function patrol(actor, target)
|
function patrol(actor, target)
|
||||||
local a = actor
|
local a = actor
|
||||||
local t = target
|
local t = target
|
||||||
|
if t ~= nil then
|
||||||
|
-- print("target is at " .. target.position.x)
|
||||||
|
end
|
||||||
|
--if moveTo(actor, patrolDestination) == true then
|
||||||
|
-- patrolDestination = { x=math.random(400.0, 750.0), y=math.random(400.0, 750.0), z=0.0 }
|
||||||
|
--end
|
||||||
|
-- performRaycast returns if true if the raycast hits the target position it also sets the getter function
|
||||||
|
-- distFromWall, at bot creation distFromWall is and infinite float value.
|
||||||
|
-- This performRaycast function is highly discourage due to slow down
|
||||||
|
--if raycaster:performRaycast(actor.position, actor.rotation, target.position) == true then
|
||||||
|
--ai.state = AIState.Alert
|
||||||
|
--end
|
||||||
if raycaster:bresenhamRaycast(a.position, a.rotation, t.position) == true then
|
if raycaster:bresenhamRaycast(a.position, a.rotation, t.position) == true then
|
||||||
--target hit!
|
--target hit!
|
||||||
ai.state = AIState.Alert
|
ai.state = AIState.Alert
|
||||||
end
|
end
|
||||||
if raycaster:distFromWall() < 3 then
|
if raycaster:distFromWall() < 3 then
|
||||||
local upOrDown = math.random(2)
|
upOrDown = math.random(2)
|
||||||
if moveLeft == true then
|
if moveLeft == true then
|
||||||
if upOrDown == 1 then
|
if upOrDown == 1 then
|
||||||
a.rotation = 180
|
a.rotation = 180
|
||||||
|
|
@ -66,8 +90,10 @@ function alert(actor, target)
|
||||||
local a = actor
|
local a = actor
|
||||||
local t = target
|
local t = target
|
||||||
if target ~= nil then
|
if target ~= nil then
|
||||||
|
-- print("target is at " .. target.position.x)
|
||||||
watchPosition(a, t.position)
|
watchPosition(a, t.position)
|
||||||
end
|
end
|
||||||
|
--print("actor is alert at " .. actor.position.x)
|
||||||
if distance(a.position, t.position) > 300 then
|
if distance(a.position, t.position) > 300 then
|
||||||
a:moveForward()
|
a:moveForward()
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
-- helper functions
|
-- helper functions
|
||||||
|
|
||||||
local function lookAway(actor, pos)
|
function lookAway(actor, pos)
|
||||||
local y = actor.position.y - pos.y
|
y = actor.position.y - pos.y
|
||||||
local x = actor.position.x - pos.x
|
x = actor.position.x - pos.x
|
||||||
local rotation = math.atan(y, x)
|
rotation = math.atan(y, x)
|
||||||
actor.rotation = math.deg(rotation)
|
actor.rotation = math.deg(rotation)
|
||||||
end
|
end
|
||||||
|
|
||||||
local function distance(a, b)
|
function distance(a, b)
|
||||||
return math.sqrt((math.abs(a.x - b.x) ^ 2) + (math.abs(a.y - b.y) ^ 2))
|
return math.sqrt((math.abs(a.x - b.x)^2) + (math.abs(a.y - b.y)^2))
|
||||||
end
|
end
|
||||||
|
|
||||||
function idle(actor, target)
|
function idle(actor, target)
|
||||||
|
|
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
<!-- Shooter Scripts -->
|
|
||||||
<script id="script/behaviour/grunt" file="scripts/ai/grunt_behaviour.lua"/>
|
|
||||||
<script id="script/behaviour/scared" file="scripts/ai/scared_behaviour.lua"/>
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
|
|
||||||
<!-- Ranged weapon scripts -->
|
|
||||||
<script id="script/weapon/shotgun" file="scripts/weapons/shotgun_script.lua"/>
|
|
||||||
|
|
@ -17,5 +17,5 @@ end
|
||||||
|
|
||||||
-- How the bullet, target or wielder respond when the bullet hits a target.
|
-- How the bullet, target or wielder respond when the bullet hits a target.
|
||||||
function onHit(target, bullet, normal)
|
function onHit(target, bullet, normal)
|
||||||
target.physics.rigidBody:applyForce(normal, 5000.0);
|
target.physics.rigidBody:applyForce(vec3.new(normal.x, normal.y, 0.0), 5000.0);
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,14 @@
|
||||||
#version 330 core
|
#version 330 core
|
||||||
layout (location = 0) in vec3 aPos;
|
layout (location = 0) in vec3 aPos;
|
||||||
layout (location = 1) in vec2 aTexCoord;
|
layout (location = 1) in vec2 aTexCoord;
|
||||||
layout (std140) uniform Matrices
|
|
||||||
{
|
|
||||||
mat4 projection;
|
|
||||||
mat4 view;
|
|
||||||
};
|
|
||||||
|
|
||||||
out vec2 texCoord;
|
out vec2 texCoord;
|
||||||
|
|
||||||
|
uniform mat4 MVP;
|
||||||
|
|
||||||
uniform mat4 model;
|
uniform mat4 model;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 view;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,12 @@
|
||||||
#version 330 core
|
#version 330 core
|
||||||
layout (location = 0) in vec3 aPos;
|
layout (location = 0) in vec3 aPos;
|
||||||
layout (location = 1) in vec2 aTexCoord;
|
layout (location = 1) in vec2 aTexCoord;
|
||||||
layout (std140) uniform Matrices
|
|
||||||
{
|
|
||||||
mat4 projection;
|
|
||||||
mat4 view;
|
|
||||||
};
|
|
||||||
|
|
||||||
out vec2 texCoord;
|
out vec2 texCoord;
|
||||||
|
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 view;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
texCoord = aTexCoord;
|
texCoord = aTexCoord;
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
#version 330 core
|
#version 330 core
|
||||||
layout (location = 0) in vec3 aPos;
|
layout (location = 0) in vec3 aPos;
|
||||||
layout (location = 1) in vec2 aTexCoord;
|
layout (location = 1) in vec2 aTexCoord;
|
||||||
layout (std140) uniform Matrices
|
|
||||||
{
|
|
||||||
mat4 projection;
|
|
||||||
mat4 view;
|
|
||||||
};
|
|
||||||
|
|
||||||
out vec2 texCoord;
|
out vec2 texCoord;
|
||||||
|
|
||||||
|
uniform mat4 MVP;
|
||||||
|
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 view;
|
||||||
uniform mat4 model;
|
uniform mat4 model;
|
||||||
uniform bool flip;
|
uniform bool flip;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,15 @@
|
||||||
#version 330 core
|
#version 330 core
|
||||||
layout (location = 0) in vec3 aPos;
|
layout (location = 0) in vec3 aPos;
|
||||||
layout (location = 1) in vec2 aTexPos;
|
layout (location = 1) in vec2 aTexPos;
|
||||||
layout (std140) uniform Matrices
|
|
||||||
{
|
|
||||||
mat4 projection;
|
|
||||||
mat4 view;
|
|
||||||
};
|
|
||||||
|
|
||||||
out vec3 pos;
|
out vec3 pos;
|
||||||
out vec2 texPos;
|
out vec2 texPos;
|
||||||
|
|
||||||
|
uniform mat4 MVP;
|
||||||
|
|
||||||
uniform mat4 model;
|
uniform mat4 model;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 view;
|
||||||
|
|
||||||
void main()
|
void main()
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,10 @@ layout (location = 4) in int aTilesPerRow;
|
||||||
layout (location = 5) in int aStartIndex;
|
layout (location = 5) in int aStartIndex;
|
||||||
layout (location = 6) in vec2 aOriginalSize;
|
layout (location = 6) in vec2 aOriginalSize;
|
||||||
layout (location = 7) in mat4 aModel;
|
layout (location = 7) in mat4 aModel;
|
||||||
layout (std140) uniform Matrices
|
|
||||||
{
|
|
||||||
mat4 projection;
|
|
||||||
mat4 view;
|
|
||||||
};
|
|
||||||
|
|
||||||
uniform vec2 uCanvasSize;
|
uniform vec2 uCanvasSize;
|
||||||
|
uniform mat4 projection;
|
||||||
|
uniform mat4 view;
|
||||||
|
|
||||||
out vec2 texCoord;
|
out vec2 texCoord;
|
||||||
flat out int textureIndex;
|
flat out int textureIndex;
|
||||||
|
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<!-- Shotgun Sounds -->
|
|
||||||
<sound id="gun/shotgun/shoot" spatial="true" path="sounds/gun/big_boom.ogg"/>
|
|
||||||
|
|
||||||
<!-- Pistol Sounds -->
|
|
||||||
<sound id="gun/pistol/shoot" spatial="true" path="sounds/gun/small_pew.ogg"/>
|
|
||||||
|
|
||||||
<!-- Machine Gun Sounds -->
|
|
||||||
<sound id="gun/machine/shoot" spatial="true" path="sounds/gun/mach_pew.ogg"/>
|
|
||||||
|
|
||||||
<!-- Generic Sounds -->
|
|
||||||
<sound id="gun/generic/shoot" spatial="true" path="sounds/gun/small_pew.ogg"/>
|
|
||||||
<sound id="gun/generic/reload" spatial="true" path="sounds/gun/reload.ogg"/>
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<weapons>
|
<weapons>
|
||||||
<weapon id="gun/machine" fireSpeed="100.0" maxAmmo="40000" clipSize="1000">
|
<weapon name="bubbleGun" fireSpeed="100.0" maxAmmo="40000" clipSize="1000">
|
||||||
<bullet anim="obj/bubble">
|
<bullet anim="bubble_anim">
|
||||||
<spread>60</spread>
|
<spread>60</spread>
|
||||||
<speed>20.0</speed>
|
<speed>20.0</speed>
|
||||||
<drop>250.0</drop>
|
<drop>250.0</drop>
|
||||||
|
|
@ -11,9 +11,9 @@
|
||||||
</bullet>
|
</bullet>
|
||||||
</weapon>
|
</weapon>
|
||||||
|
|
||||||
<weapon id="gun/shotgun" fireSpeed="1750.0" maxAmmo="64" clipSize="4">
|
<weapon name="shotGun" fireSpeed="1750.0" maxAmmo="64" clipSize="4">
|
||||||
<script id="script/weapon/shotgun"/>
|
<script file="scripts/weapons/shotgun_script.lua"/>
|
||||||
<animation>
|
<animation name="shot_gun_anim">
|
||||||
<size x="55.0" y="55.0"/>
|
<size x="55.0" y="55.0"/>
|
||||||
<offset x="-30.0" y="0.0"/>
|
<offset x="-30.0" y="0.0"/>
|
||||||
</animation>
|
</animation>
|
||||||
|
|
@ -26,8 +26,8 @@
|
||||||
</bullet>
|
</bullet>
|
||||||
</weapon>
|
</weapon>
|
||||||
|
|
||||||
<weapon id="gun/machine" fireSpeed="50.0" maxAmmo="512" clipSize="64">
|
<weapon name="machineGun" fireSpeed="50.0" maxAmmo="512" clipSize="64">
|
||||||
<animation>
|
<animation name="machine_gun_anim">
|
||||||
<size x="55.0" y="55.0"/>
|
<size x="55.0" y="55.0"/>
|
||||||
<offset x="-30.0" y="0.0"/>
|
<offset x="-30.0" y="0.0"/>
|
||||||
</animation>
|
</animation>
|
||||||
|
|
@ -40,8 +40,8 @@
|
||||||
</bullet>
|
</bullet>
|
||||||
</weapon>
|
</weapon>
|
||||||
|
|
||||||
<weapon id="gun/pistol" fireSpeed="750.0" maxAmmo="512" clipSize="21">
|
<weapon name="pistolGun" fireSpeed="750.0" maxAmmo="512" clipSize="21">
|
||||||
<animation>
|
<animation name="pistol_anim">
|
||||||
<size x="55.0" y="55.0"/>
|
<size x="55.0" y="55.0"/>
|
||||||
<offset x="-30.0" y="0.0"/>
|
<offset x="-30.0" y="0.0"/>
|
||||||
</animation>
|
</animation>
|
||||||
|
|
@ -2,47 +2,32 @@
|
||||||
# project specific logic here.
|
# project specific logic here.
|
||||||
#
|
#
|
||||||
|
|
||||||
find_package(SDL2 2.30.2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
find_package(SDL2_image 2.8.2 REQUIRED)
|
find_package(SDL2_IMAGE REQUIRED)
|
||||||
find_package(PkgConfig REQUIRED)
|
|
||||||
pkg_check_modules(LuaJIT REQUIRED IMPORTED_TARGET GLOBAL luajit)
|
|
||||||
find_package(sol2 REQUIRED)
|
|
||||||
find_package(tinyxml2 REQUIRED)
|
|
||||||
find_package(Freetype REQUIRED)
|
|
||||||
find_package(OpenAL REQUIRED)
|
|
||||||
find_package(glm CONFIG REQUIRED)
|
|
||||||
|
|
||||||
|
include_directories(SYSTEM "${PROJECT_SOURCE_DIR}/YuppleMayham/include")
|
||||||
|
include_directories(SYSTEM "c:/sdks/glad/include")
|
||||||
|
include_directories(SYSTEM "c:/sdks/tinyxml2-10.0.0/debug/include")
|
||||||
|
include_directories(SYSTEM "c:/sdks/glm")
|
||||||
|
include_directories(SYSTEM "C:/sdks/sol2-3.3.0/single/single/include")
|
||||||
|
include_directories(SYSTEM "c:/sdks/lua-5.4.6/include")
|
||||||
|
include_directories(SYSTEM "C:/sdks/freetype-2.13.2/include")
|
||||||
|
link_directories(SYSTEM "C:/sdks/freetype-2.13.2/objs")
|
||||||
|
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
link_directories(SYSTEM "c:/sdks/tinyxml2-10.0.0/debug/lib")
|
||||||
|
else()
|
||||||
|
link_directories(SYSTEM "c:/sdks/tinyxml2-10.0.0/release/lib")
|
||||||
|
endif()
|
||||||
|
link_directories(SYSTEM "c:/sdks/lua-5.4.6/lib")
|
||||||
|
|
||||||
#include_directories(SYSTEM "c:/sdks/glad/include")
|
include_directories("${PROJECT_SOURCE_DIR}/YuppleMayham/include")
|
||||||
#include_directories(SYSTEM "c:/sdks/tinyxml2-10.0.0/debug/include")
|
|
||||||
#include_directories(SYSTEM "c:/sdks/glm")
|
|
||||||
#include_directories(SYSTEM "C:/sdks/sol2-3.3.0/single/single/include")
|
|
||||||
#include_directories(SYSTEM "c:/sdks/lua-5.4.6/include")
|
|
||||||
#include_directories(SYSTEM "C:/sdks/freetype-2.13.2/include")
|
|
||||||
#link_directories(SYSTEM "C:/sdks/freetype-2.13.2/objs")
|
|
||||||
#if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
||||||
# link_directories(SYSTEM "c:/sdks/tinyxml2-10.0.0/debug/lib")
|
|
||||||
#else()
|
|
||||||
# link_directories(SYSTEM "c:/sdks/tinyxml2-10.0.0/release/lib")
|
|
||||||
#endif()
|
|
||||||
#link_directories(SYSTEM "c:/sdks/lua-5.4.6/lib")
|
|
||||||
|
|
||||||
#include_directories("${PROJECT_SOURCE_DIR}/YuppleMayham/include")
|
|
||||||
|
|
||||||
# Add source to this project's executable.
|
# Add source to this project's executable.
|
||||||
add_executable (YuppleMayham
|
add_executable (YuppleMayham
|
||||||
"src/main.cpp"
|
"src/main.cpp"
|
||||||
"src/thirdparty/glad.c"
|
"c:/sdks/glad/src/glad.c"
|
||||||
"src/sound/engine.cpp"
|
|
||||||
"src/sound/audiostream.cpp"
|
|
||||||
"src/sound/soundeffect.cpp"
|
|
||||||
"src/sound/soundmanager.cpp"
|
|
||||||
"include/thirdparty/stb_vorbis.c"
|
|
||||||
"src/utility/data/font_data.c"
|
|
||||||
"src/utility/ftfont.cpp"
|
|
||||||
"src/graphics/sprite.cpp"
|
"src/graphics/sprite.cpp"
|
||||||
"src/graphics/mesh.cpp"
|
"src/graphics/mesh.cpp"
|
||||||
"src/graphics/glwindow.cpp"
|
|
||||||
"src/gameplay/entity.cpp"
|
"src/gameplay/entity.cpp"
|
||||||
"src/gameplay/gameactor.cpp"
|
"src/gameplay/gameactor.cpp"
|
||||||
"src/graphics/shader.cpp"
|
"src/graphics/shader.cpp"
|
||||||
|
|
@ -54,7 +39,6 @@ add_executable (YuppleMayham
|
||||||
"src/gameplay/weapons/bulletmanager.cpp"
|
"src/gameplay/weapons/bulletmanager.cpp"
|
||||||
"src/gameplay/scene.cpp"
|
"src/gameplay/scene.cpp"
|
||||||
"src/graphics/texture.cpp"
|
"src/graphics/texture.cpp"
|
||||||
"src/graphics/background.cpp"
|
|
||||||
|
|
||||||
"src/utility/resourcemanager.cpp"
|
"src/utility/resourcemanager.cpp"
|
||||||
"src/utility/xmlloader.cpp"
|
"src/utility/xmlloader.cpp"
|
||||||
|
|
@ -66,6 +50,7 @@ add_executable (YuppleMayham
|
||||||
"src/utility/debugdraw.cpp"
|
"src/utility/debugdraw.cpp"
|
||||||
"src/utility/script.cpp"
|
"src/utility/script.cpp"
|
||||||
"src/gameplay/ai.cpp"
|
"src/gameplay/ai.cpp"
|
||||||
|
"src/utility/ftfont.cpp"
|
||||||
"include/graphics/glwindow.h"
|
"include/graphics/glwindow.h"
|
||||||
"include/gameplay/camera.h"
|
"include/gameplay/camera.h"
|
||||||
"include/utility/mousestate.h"
|
"include/utility/mousestate.h"
|
||||||
|
|
@ -100,11 +85,8 @@ add_custom_command(TARGET YuppleMayham PRE_BUILD COMMAND ${CMAKE_COMMAND} -E cop
|
||||||
|
|
||||||
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
if (CMAKE_VERSION VERSION_GREATER 3.12)
|
||||||
set_property(TARGET YuppleMayham PROPERTY CXX_STANDARD 20)
|
set_property(TARGET YuppleMayham PROPERTY CXX_STANDARD 20)
|
||||||
message("this is freetype include dirs: ${FREETYPE_INCLUDE_DIR_ft2build}")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_include_directories(YuppleMayham PRIVATE "${PROJECT_SOURCE_DIR}/YuppleMayham/include" ${LuaJIT_INCLUDE_DIRS} ${FREETYPE_INCLUDE_DIR_ft2build})
|
target_link_libraries(YuppleMayham SDL2::SDL2main SDL2::SDL2 SDL2_image::SDL2_image tinyxml2 lua_static freetype Tracy::TracyClient)
|
||||||
|
|
||||||
target_link_libraries(YuppleMayham SDL2::SDL2main SDL2::SDL2 SDL2_image::SDL2_image openal glm::glm tinyxml2 freetype ${LuaJIT_LINK_LIBRARIES})
|
|
||||||
|
|
||||||
# TODO: Add tests and install targets if needed.
|
# TODO: Add tests and install targets if needed.
|
||||||
|
|
|
||||||
|
|
@ -17,25 +17,25 @@ enum class AIState {
|
||||||
Patrol
|
Patrol
|
||||||
};
|
};
|
||||||
|
|
||||||
class AI {
|
class AI : public std::enable_shared_from_this<AI> {
|
||||||
public:
|
public:
|
||||||
AI(GameActor* actor, std::unique_ptr<Raycaster> raycaster);
|
AI(const std::shared_ptr<GameActor>& actor, const std::shared_ptr<Raycaster>& raycaster);
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
void setTarget(GameActor* target) { this->target = target; }
|
void setTarget(const std::shared_ptr<GameActor>& target) { this->target = target; }
|
||||||
void attachBehaviourScript(std::unique_ptr<AIScript> behaviour);
|
void attachBehaviourScript(const std::shared_ptr<AIScript>& behaviour);
|
||||||
|
|
||||||
AIState getState() const { return state; }
|
AIState getState() const { return state; }
|
||||||
void setState(AIState state) { this->state = state; }
|
void setState(AIState state) { this->state = state; }
|
||||||
|
|
||||||
~AI();
|
~AI() {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AIState state;
|
AIState state;
|
||||||
std::unique_ptr<Raycaster> raycaster;
|
std::shared_ptr<Raycaster> raycaster;
|
||||||
std::unique_ptr<AIScript> behaviour;
|
std::shared_ptr<AIScript> behaviour;
|
||||||
GameActor* actor;
|
std::shared_ptr<GameActor> actor;
|
||||||
GameActor* target;
|
std::shared_ptr<GameActor> target;
|
||||||
|
|
||||||
// cache our lua function calls
|
// cache our lua function calls
|
||||||
sol::function idleFunc;
|
sol::function idleFunc;
|
||||||
|
|
|
||||||
|
|
@ -3,35 +3,34 @@
|
||||||
|
|
||||||
#include "gameplay/entity.h"
|
#include "gameplay/entity.h"
|
||||||
|
|
||||||
class Camera {
|
class Camera
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Camera(float viewPortW, float viewPortH)
|
Camera(float viewPortW, float viewPortH) :
|
||||||
: position(glm::vec3(0.0f, 0.0f, 0.0f)),
|
position(glm::vec3(0.0f, 0.0f, 0.0f)),
|
||||||
front(glm::vec3(0.0f, 0.0f, -1.0f)), up(glm::vec3(0.0f, 1.0f, 0.0f)),
|
front(glm::vec3(0.0f, 0.0f, -1.0f)),
|
||||||
viewPortW(viewPortW), viewPortH(viewPortH) {};
|
up(glm::vec3(0.0f, 1.0f, 0.0f)),
|
||||||
|
viewPortW(viewPortW),
|
||||||
|
viewPortH(viewPortH)
|
||||||
|
{};
|
||||||
|
|
||||||
void setPosition(const glm::vec3 &position) { this->position = position; }
|
void setPosition(const glm::vec3& position) { this->position = position; }
|
||||||
|
|
||||||
const Entity *getTarget() const { return target; }
|
const Entity* getTarget() const { return target; }
|
||||||
const glm::vec3 getCenterPos() const {
|
const glm::vec3 getCenterPos() const { return glm::vec3(position.x + (viewPortW / 2.f), position.y + (viewPortH / 2.f), 0.0f); }
|
||||||
return glm::vec3(position.x + (viewPortW / 2.f),
|
void setTarget(Entity* target) { this->target = target; }
|
||||||
position.y + (viewPortH / 2.f), 0.0f);
|
|
||||||
}
|
|
||||||
void setTarget(Entity *target) { this->target = target; }
|
|
||||||
void unsetTarget() { target = nullptr; }
|
void unsetTarget() { target = nullptr; }
|
||||||
bool isTargeting() { return (target != nullptr); }
|
bool isTargeting() { return (target != nullptr); }
|
||||||
|
|
||||||
void update(double deltaTime);
|
void update(double deltaTime);
|
||||||
void setViewportSize(float width, float height);
|
|
||||||
|
|
||||||
const glm::vec3 worldToLocal(const glm::vec3 &worldCoordinates);
|
const glm::vec3 worldToLocal(const glm::vec3& worldCoordinates);
|
||||||
|
|
||||||
glm::mat4 getViewMatrix();
|
glm::mat4 getViewMatrix();
|
||||||
glm::mat4 getProjectionMatrix();
|
glm::mat4 getProjectionMatrix();
|
||||||
const glm::vec3 getPosition() const { return position; }
|
const glm::vec3 getPosition() const { return position; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Entity *target = nullptr;
|
Entity* target = nullptr;
|
||||||
|
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
glm::vec3 front;
|
glm::vec3 front;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
|
|
||||||
#include "graphics/renderer.h"
|
#include "graphics/renderer.h"
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
class Camera;
|
class Camera;
|
||||||
struct PhysicsComponent;
|
struct PhysicsComponent;
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,33 @@
|
||||||
#ifndef _H_GAME_H
|
#ifndef _H_GAME_H
|
||||||
#define _H_GAME_H
|
#define _H_GAME_H
|
||||||
|
|
||||||
#include <SDL_events.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <SDL_events.h>
|
||||||
#include <utility/events.h>
|
#include <utility/events.h>
|
||||||
|
|
||||||
#include "gameplay/camera.h"
|
|
||||||
|
|
||||||
class InputHandler;
|
class InputHandler;
|
||||||
class Scene;
|
class Scene;
|
||||||
class Text;
|
class Text;
|
||||||
class ResourceManager;
|
class ResourceManager;
|
||||||
class Renderer;
|
class Renderer;
|
||||||
class AudioEngine;
|
|
||||||
class GLWindow;
|
class GLWindow;
|
||||||
|
|
||||||
enum { GAME_QUITTING = 0, GAME_RUNNING = 1, GAME_MENU = 2, GAME_PLAYING = 4 };
|
enum {
|
||||||
|
GAME_QUITTING = 0,
|
||||||
|
GAME_RUNNING = 1,
|
||||||
|
GAME_MENU = 2,
|
||||||
|
GAME_PLAYING = 4
|
||||||
|
};
|
||||||
|
|
||||||
class Game {
|
class Game
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Game() {}
|
Game() {}
|
||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
bool loadDebugScene();
|
bool loadDebugScene();
|
||||||
|
|
||||||
void captureInput(SDL_Event &e);
|
void handleInput(SDL_Event& e);
|
||||||
void executeInputs();
|
|
||||||
|
|
||||||
void update(double deltaTime);
|
void update(double deltaTime);
|
||||||
void render();
|
void render();
|
||||||
|
|
@ -35,21 +37,18 @@ public:
|
||||||
const unsigned getWindowWidth() const;
|
const unsigned getWindowWidth() const;
|
||||||
const unsigned getWindowHeight() const;
|
const unsigned getWindowHeight() const;
|
||||||
|
|
||||||
void quit();
|
void quit() { game_state = GAME_QUITTING; }
|
||||||
~Game();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
unsigned game_state = GAME_QUITTING;
|
unsigned game_state = GAME_QUITTING;
|
||||||
|
|
||||||
std::shared_ptr<GLWindow> window;
|
std::shared_ptr<GLWindow> window;
|
||||||
|
|
||||||
std::unique_ptr<Camera> camera;
|
|
||||||
std::shared_ptr<Scene> currentScene;
|
std::shared_ptr<Scene> currentScene;
|
||||||
std::shared_ptr<InputHandler> inputHandler;
|
std::shared_ptr<InputHandler> inputHandler;
|
||||||
std::shared_ptr<ResourceManager> resourceManager;
|
std::shared_ptr<ResourceManager> resourceManager;
|
||||||
std::shared_ptr<Renderer> renderer;
|
std::shared_ptr<Renderer> renderer;
|
||||||
std::shared_ptr<Text> textHandler;
|
std::shared_ptr<Text> textHandler;
|
||||||
std::shared_ptr<AudioEngine> audioEngine;
|
|
||||||
std::shared_ptr<EventManager> globalEventManager;
|
std::shared_ptr<EventManager> globalEventManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,17 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <span>
|
|
||||||
|
|
||||||
#include "gameplay/entity.h"
|
#include "gameplay/entity.h"
|
||||||
#include "gameplay/weapons/weapon.h"
|
|
||||||
#include "utility/mousestate.h"
|
#include "utility/mousestate.h"
|
||||||
|
|
||||||
#include <utility/component.h>
|
#include <utility/component.h>
|
||||||
|
|
||||||
class AI;
|
class AI;
|
||||||
|
class Weapon;
|
||||||
class ISceneContext;
|
class ISceneContext;
|
||||||
|
|
||||||
|
// TODO: Finish weapon cycling code and add default weapon to every actor
|
||||||
// TODO: Add ammo system, then work on some basic UI design
|
// TODO: Add ammo system, then work on some basic UI design
|
||||||
|
|
||||||
class GameActor : public Entity
|
class GameActor : public Entity
|
||||||
|
|
@ -25,12 +25,11 @@ public:
|
||||||
~GameActor();
|
~GameActor();
|
||||||
|
|
||||||
void addComponent(std::unique_ptr<Component> component);
|
void addComponent(std::unique_ptr<Component> component);
|
||||||
void pickupWeapon(std::unique_ptr<Weapon> weapon);
|
void pickupWeapon(std::shared_ptr<Weapon> weapon);
|
||||||
void update(double deltaTime) override;
|
void update(double deltaTime) override;
|
||||||
void draw() override;
|
void draw() override;
|
||||||
|
|
||||||
Weapon* getHeldWeapon() const;
|
const std::shared_ptr<Weapon> getHeldWeapon() const;
|
||||||
std::span<Weapon*> getAllWeapons();
|
|
||||||
|
|
||||||
void setRotation(const float& rotation) override;
|
void setRotation(const float& rotation) override;
|
||||||
|
|
||||||
|
|
@ -50,9 +49,11 @@ public:
|
||||||
void cycleWeapons(const MouseState&);
|
void cycleWeapons(const MouseState&);
|
||||||
void followMouse(const MouseState&);
|
void followMouse(const MouseState&);
|
||||||
private:
|
private:
|
||||||
std::vector<std::unique_ptr<Component>> components;
|
using component_vector_t = std::vector<std::unique_ptr<Component>>;
|
||||||
std::vector<std::unique_ptr<Weapon>> weapons;
|
using weapon_vector_t = std::vector<std::shared_ptr<Weapon>>;
|
||||||
std::vector<Weapon*> weaponCache;
|
|
||||||
|
component_vector_t components;
|
||||||
|
weapon_vector_t weapons;
|
||||||
size_t currentWeaponIndex = 0;
|
size_t currentWeaponIndex = 0;
|
||||||
|
|
||||||
ISceneContext* sceneContext;
|
ISceneContext* sceneContext;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
#ifndef _H_INPUT_H
|
#ifndef _H_INPUT_H
|
||||||
#define _H_INPUT_H
|
#define _H_INPUT_H
|
||||||
|
|
||||||
#include "utility/logger.h"
|
|
||||||
#include <SDL_mouse.h>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <SDL_keycode.h>
|
#include <SDL_keycode.h>
|
||||||
#include <SDL_events.h>
|
#include <SDL_events.h>
|
||||||
|
|
@ -47,12 +45,13 @@ protected:
|
||||||
mouseButtons[MOUSE_BUTTON_LEFT] = true;
|
mouseButtons[MOUSE_BUTTON_LEFT] = true;
|
||||||
if (e.type == SDL_MOUSEBUTTONUP)
|
if (e.type == SDL_MOUSEBUTTONUP)
|
||||||
mouseButtons[MOUSE_BUTTON_LEFT] = false;
|
mouseButtons[MOUSE_BUTTON_LEFT] = false;
|
||||||
if (e.type == SDL_MOUSEWHEEL)
|
if (e.type == SDL_MOUSEMOTION)
|
||||||
mouse_state.scroll = e.wheel.preciseY;
|
{
|
||||||
if (e.type == SDL_MOUSEMOTION) {
|
|
||||||
mouse_state.x = static_cast<float>(e.motion.x);
|
mouse_state.x = static_cast<float>(e.motion.x);
|
||||||
mouse_state.y = static_cast<float>(e.motion.y);
|
mouse_state.y = static_cast<float>(e.motion.y);
|
||||||
}
|
}
|
||||||
|
if (e.type == SDL_MOUSEWHEEL)
|
||||||
|
mouse_state.scroll = e.wheel.preciseY;
|
||||||
}
|
}
|
||||||
MouseState mouse_state;
|
MouseState mouse_state;
|
||||||
std::unordered_map<Uint8, bool> mouseButtons;
|
std::unordered_map<Uint8, bool> mouseButtons;
|
||||||
|
|
@ -62,12 +61,12 @@ class InputHandler : public Keyboard, public Mouse
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
struct CommandWithDelay{
|
struct CommandWithDelay{
|
||||||
std::unique_ptr<Command> cmd;
|
Command* cmd;
|
||||||
Uint32 lastExecution;
|
Uint32 lastExecution;
|
||||||
Uint32 delay;
|
Uint32 delay;
|
||||||
};
|
};
|
||||||
struct MouseCommandWithDelay{
|
struct MouseCommandWithDelay{
|
||||||
std::unique_ptr<MouseCommand> cmd;
|
MouseCommand* cmd;
|
||||||
Uint32 lastExecution;
|
Uint32 lastExecution;
|
||||||
Uint32 delay;
|
Uint32 delay;
|
||||||
};
|
};
|
||||||
|
|
@ -80,31 +79,26 @@ public:
|
||||||
this->actor = actor;
|
this->actor = actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bindKeyCommand(SDL_Keycode key, Uint32 delay, std::unique_ptr<Command> command) {
|
void bindKeyCommand(SDL_Keycode key, Uint32 delay, Command* command) {
|
||||||
keyCommands[key] = { std::move(command), 0, delay };
|
keyCommands[key] = { command, 0, delay };
|
||||||
}
|
}
|
||||||
void bindMouseCommand(Uint8 mouse, Uint32 delay, std::unique_ptr<MouseCommand> command) {
|
void bindMouseCommand(Uint8 mouse, Uint32 delay, MouseCommand* command) {
|
||||||
mouseCommands[mouse] = { std::move(command), 0, delay };
|
mouseCommands[mouse] = { command, 0, delay };
|
||||||
}
|
}
|
||||||
void bindMouseMotion(std::unique_ptr<MouseCommand> command) {
|
void bindMouseMotion(MouseCommand* command) {
|
||||||
mouseMotionCommand = std::move(command);
|
mouseMotionCommand = command;
|
||||||
}
|
}
|
||||||
void bindMouseScroll(std::unique_ptr<MouseCommand> command) {
|
void bindMouseScroll(MouseCommand* command) {
|
||||||
mouseScrollCommand = std::move(command);
|
mouseScrollCommand = command;
|
||||||
}
|
}
|
||||||
void handleInput();
|
void handleInput();
|
||||||
void executeCommands();
|
|
||||||
|
|
||||||
~InputHandler();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GameActor* actor = nullptr;
|
GameActor* actor = nullptr;
|
||||||
std::unordered_map<SDL_Keycode, CommandWithDelay> keyCommands;
|
std::unordered_map<SDL_Keycode, CommandWithDelay> keyCommands;
|
||||||
std::unordered_map<Uint8, MouseCommandWithDelay> mouseCommands;
|
std::unordered_map<Uint8, MouseCommandWithDelay> mouseCommands;
|
||||||
std::vector<Command*> commandQueue;
|
MouseCommand* mouseMotionCommand = nullptr;
|
||||||
std::vector<MouseCommand*> mouseQueue;
|
MouseCommand* mouseScrollCommand = nullptr;
|
||||||
std::unique_ptr<MouseCommand> mouseMotionCommand = nullptr;
|
|
||||||
std::unique_ptr<MouseCommand> mouseScrollCommand = nullptr;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _H_INPUT_H
|
#endif // _H_INPUT_H
|
||||||
|
|
@ -16,7 +16,7 @@ struct TileSetData;
|
||||||
class Map : public Drawable
|
class Map : public Drawable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Map(const MapData* mapData, const unsigned shaderID, std::shared_ptr<ResourceManager> resourceManager);
|
Map(std::shared_ptr<MapData> mapData, const unsigned shaderID, std::shared_ptr<ResourceManager> resourceManager);
|
||||||
|
|
||||||
const std::vector<std::vector<int>> getCollisionMap() const { return collisionMap; }
|
const std::vector<std::vector<int>> getCollisionMap() const { return collisionMap; }
|
||||||
|
|
||||||
|
|
@ -26,10 +26,10 @@ private:
|
||||||
void loadMap();
|
void loadMap();
|
||||||
void createCollisionMap();
|
void createCollisionMap();
|
||||||
|
|
||||||
size_t getTileSetIndex(int id) const;
|
int getTileSetIndex(int id) const;
|
||||||
|
|
||||||
const MapData* mapData;
|
std::shared_ptr<MapData> mapData;
|
||||||
std::vector<const TileSetData*> tileSetData;
|
std::vector<std::shared_ptr<TileSetData>> tileSetData;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<TileTextureInstance>> instanceHandles;
|
std::vector<std::shared_ptr<TileTextureInstance>> instanceHandles;
|
||||||
std::vector<std::vector<std::vector<int>>> tileIds;
|
std::vector<std::vector<std::vector<int>>> tileIds;
|
||||||
|
|
|
||||||
|
|
@ -12,20 +12,20 @@ struct PhysicsComponent {
|
||||||
// This ID holds the ID of the gameactor that owns this object, that being themselves or a bullet.
|
// This ID holds the ID of the gameactor that owns this object, that being themselves or a bullet.
|
||||||
unsigned int ID = 0; // If the ID stays 0 then that object has no owner and will be uncollidable
|
unsigned int ID = 0; // If the ID stays 0 then that object has no owner and will be uncollidable
|
||||||
struct RigidBody {
|
struct RigidBody {
|
||||||
glm::vec2 position;
|
glm::vec3 position;
|
||||||
glm::vec2 velocity = glm::vec2(0.f);
|
glm::vec3 velocity;
|
||||||
glm::vec2 acceleration = glm::vec2(0.f);
|
glm::vec3 acceleration;
|
||||||
float elasticity = 0.7f;
|
float elasticity = 0.7f;
|
||||||
float mass = 1.0f;
|
float mass = 1.0f;
|
||||||
void applyForce(glm::vec2 dir, float mag) {
|
void applyForce(glm::vec3 dir, float mag) {
|
||||||
acceleration += ((dir * mag) / mass);
|
acceleration += ((dir * mag) / mass);
|
||||||
}
|
}
|
||||||
}rigidBody;
|
}rigidBody;
|
||||||
|
|
||||||
struct Collider {
|
struct Collider {
|
||||||
enum class Shape { Square, Circle } shape = Shape::Circle;
|
enum class Shape { Square, Circle } shape = Shape::Circle;
|
||||||
glm::vec2 offset = glm::vec2(0.f);
|
glm::vec3 offset = glm::vec3(0.f);
|
||||||
glm::vec2 dimensions;
|
glm::vec3 dimensions;
|
||||||
}collider;
|
}collider;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ public:
|
||||||
p.ID = ID;
|
p.ID = ID;
|
||||||
p.rigidBody.position = pos;
|
p.rigidBody.position = pos;
|
||||||
p.rigidBody.mass = mass;
|
p.rigidBody.mass = mass;
|
||||||
p.collider = { PhysicsComponent::Collider::Shape::Circle, glm::vec2(0.f, 0.f), glm::vec2(radius) };
|
p.collider = { PhysicsComponent::Collider::Shape::Circle, glm::vec3(radius, radius, 0.f), glm::vec3(radius) };
|
||||||
p.isBullet = true;
|
p.isBullet = true;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
@ -59,7 +59,7 @@ private:
|
||||||
void resolveWorldCollision(const std::shared_ptr<PhysicsComponent>&);
|
void resolveWorldCollision(const std::shared_ptr<PhysicsComponent>&);
|
||||||
void resolvePossibleCollisions();
|
void resolvePossibleCollisions();
|
||||||
void getPossibleCollisions();
|
void getPossibleCollisions();
|
||||||
int getTileCollider(const glm::vec2& position);
|
int getTileCollider(const glm::vec3& position);
|
||||||
std::vector<std::shared_ptr<PhysicsComponent>> objects;
|
std::vector<std::shared_ptr<PhysicsComponent>> objects;
|
||||||
std::vector<CollisionPair> objCollisions;
|
std::vector<CollisionPair> objCollisions;
|
||||||
std::vector<std::vector<int>> collisionMap;
|
std::vector<std::vector<int>> collisionMap;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
#include <gameplay/gameactor.h>
|
#include <gameplay/gameactor.h>
|
||||||
|
|
||||||
class Background;
|
|
||||||
class Entity;
|
class Entity;
|
||||||
class Camera;
|
class Camera;
|
||||||
class Map;
|
class Map;
|
||||||
|
|
@ -62,9 +61,6 @@ private:
|
||||||
void hookSceneEvents();
|
void hookSceneEvents();
|
||||||
GameActor* getGameActorByID(const unsigned int ID);
|
GameActor* getGameActorByID(const unsigned int ID);
|
||||||
|
|
||||||
// Non-owning pointer DO NOT DELETE, resource manager will handle that!
|
|
||||||
Background *background;
|
|
||||||
|
|
||||||
SceneType type;
|
SceneType type;
|
||||||
std::shared_ptr<Map> map;
|
std::shared_ptr<Map> map;
|
||||||
//std::shared_ptr<TileSet> tileSet;
|
//std::shared_ptr<TileSet> tileSet;
|
||||||
|
|
@ -78,7 +74,7 @@ private:
|
||||||
std::shared_ptr<ResourceManager> resourceManager;
|
std::shared_ptr<ResourceManager> resourceManager;
|
||||||
std::weak_ptr<EventManager> globalEventManager;
|
std::weak_ptr<EventManager> globalEventManager;
|
||||||
std::shared_ptr<EventManager> eventManager;
|
std::shared_ptr<EventManager> eventManager;
|
||||||
const SceneData* sceneData;
|
std::shared_ptr<SceneData> sceneData;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_H_SCENE_H
|
#endif //_H_SCENE_H
|
||||||
|
|
@ -24,10 +24,10 @@ class WeaponScript;
|
||||||
struct PhysicsComponent;
|
struct PhysicsComponent;
|
||||||
struct WeaponData;
|
struct WeaponData;
|
||||||
|
|
||||||
class Weapon : public Entity
|
class Weapon : public Entity, public std::enable_shared_from_this<Weapon>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Weapon(const WeaponData* data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager);
|
Weapon(std::shared_ptr<WeaponData> data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager);
|
||||||
|
|
||||||
void setWielder(GameActor* wielder) { this->wielder = wielder; }
|
void setWielder(GameActor* wielder) { this->wielder = wielder; }
|
||||||
void toggleInfiniteAmmo() { infiniteAmmo = !infiniteAmmo; }
|
void toggleInfiniteAmmo() { infiniteAmmo = !infiniteAmmo; }
|
||||||
|
|
@ -35,15 +35,13 @@ public:
|
||||||
void putaway() { wielded = false; }
|
void putaway() { wielded = false; }
|
||||||
|
|
||||||
void addComponent(std::unique_ptr<Component> component);
|
void addComponent(std::unique_ptr<Component> component);
|
||||||
void attachScript(std::unique_ptr<WeaponScript> script);
|
void attachScript(const std::shared_ptr<WeaponScript>& script);
|
||||||
void hookEventManager(std::weak_ptr<EventManager> eventManager);
|
void hookEventManager(std::weak_ptr<EventManager> eventManager);
|
||||||
bool shoot();
|
bool shoot();
|
||||||
void reload();
|
void reload();
|
||||||
void update(double deltaTime);
|
void update(double deltaTime);
|
||||||
void draw();
|
void draw();
|
||||||
|
|
||||||
const std::string getType() const { return weaponType; }
|
|
||||||
|
|
||||||
struct BulletData {
|
struct BulletData {
|
||||||
glm::vec3 origin;
|
glm::vec3 origin;
|
||||||
glm::vec2 direction;
|
glm::vec2 direction;
|
||||||
|
|
@ -69,13 +67,9 @@ public:
|
||||||
|
|
||||||
const BulletManager* getBulletManager() { return bulletManager.get(); }
|
const BulletManager* getBulletManager() { return bulletManager.get(); }
|
||||||
|
|
||||||
~Weapon();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void adjustWeapon();
|
void adjustWeapon();
|
||||||
|
|
||||||
std::string weaponType;
|
|
||||||
|
|
||||||
glm::vec2 weaponSize;
|
glm::vec2 weaponSize;
|
||||||
glm::vec2 weaponOffset;
|
glm::vec2 weaponOffset;
|
||||||
// TODO: Add reloading
|
// TODO: Add reloading
|
||||||
|
|
@ -106,7 +100,7 @@ private:
|
||||||
Direction lastDir;
|
Direction lastDir;
|
||||||
|
|
||||||
std::vector <std::unique_ptr<Component>> components;
|
std::vector <std::unique_ptr<Component>> components;
|
||||||
std::unique_ptr<WeaponScript> weaponScript;
|
std::shared_ptr<WeaponScript> weaponScript;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
|
|
@ -23,11 +22,10 @@ struct AnimationData;
|
||||||
class Animation
|
class Animation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Animation(const AnimationData* animData, ResourceManager* resourceManager);
|
Animation(const std::shared_ptr<AnimationData>& animData, ResourceManager* resourceManager);
|
||||||
|
|
||||||
std::string getPrefix() const { return prefix; }
|
std::string getName() const { return animName; }
|
||||||
std::string getType() const { return type; }
|
std::string getType() const { return animType; }
|
||||||
std::string getID() const { return prefix + "/" + type; }
|
|
||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
void draw();
|
void draw();
|
||||||
|
|
@ -35,7 +33,7 @@ public:
|
||||||
|
|
||||||
void play() { isPlaying = true; }
|
void play() { isPlaying = true; }
|
||||||
void stop() { isPlaying = false; }
|
void stop() { isPlaying = false; }
|
||||||
void reset() { currentFrame = 0; lastFrameTick = 0; elapsedTime = 0; }
|
void reset() { currentFrame = 0; }
|
||||||
|
|
||||||
const bool getPlaying() const { return isPlaying; }
|
const bool getPlaying() const { return isPlaying; }
|
||||||
const bool getDirectional() const { return isDirectional; }
|
const bool getDirectional() const { return isDirectional; }
|
||||||
|
|
@ -44,8 +42,8 @@ public:
|
||||||
void setFPS(const float fps) { FPS = fps; }
|
void setFPS(const float fps) { FPS = fps; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string prefix;
|
std::string animName;
|
||||||
std::string type;
|
std::string animType;
|
||||||
|
|
||||||
SpriteAtlas* spriteAtlas;
|
SpriteAtlas* spriteAtlas;
|
||||||
|
|
||||||
|
|
@ -71,7 +69,7 @@ class AnimationSet : public std::enable_shared_from_this<AnimationSet>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AnimationSet(const int& entityid);
|
AnimationSet(const int& entityid);
|
||||||
AnimationSet(const int& entityid, ResourceManager* resourceManager, std::vector<AnimationData*> animSet);
|
AnimationSet(const int& entityid, ResourceManager* resourceManager, std::vector<std::shared_ptr<AnimationData>> animSet);
|
||||||
AnimationSet(const int& entityid, std::unordered_map<std::string, std::unique_ptr<Animation>> animations);
|
AnimationSet(const int& entityid, std::unordered_map<std::string, std::unique_ptr<Animation>> animations);
|
||||||
|
|
||||||
Animation* operator [](std::string animType) { return anims[animType].get(); }
|
Animation* operator [](std::string animType) { return anims[animType].get(); }
|
||||||
|
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
#ifndef _H_BACKGROUND_H
|
|
||||||
#define _H_BACKGROUND_H
|
|
||||||
|
|
||||||
#include "graphics/quad.h"
|
|
||||||
#include "graphics/drawable.h"
|
|
||||||
#include "graphics/texture.h"
|
|
||||||
|
|
||||||
#include "utility/logger.h"
|
|
||||||
|
|
||||||
class Background : public Drawable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Background(const std::string& fileName);
|
|
||||||
|
|
||||||
void draw() override;
|
|
||||||
|
|
||||||
~Background();
|
|
||||||
|
|
||||||
private:
|
|
||||||
ScreenQuad *quad;
|
|
||||||
Texture *texture;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _H_BACKGROUND_H
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
#ifndef _H_DRAWABLE_H
|
|
||||||
#define _H_DRAWABLE_H
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <variant>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
using UniformValue = std::variant<
|
|
||||||
int,
|
|
||||||
bool,
|
|
||||||
float,
|
|
||||||
double,
|
|
||||||
glm::mat4,
|
|
||||||
glm::vec2
|
|
||||||
>;
|
|
||||||
|
|
||||||
struct Uniform {
|
|
||||||
std::string name;
|
|
||||||
UniformValue value;
|
|
||||||
};
|
|
||||||
|
|
||||||
class Drawable
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
virtual void draw() = 0;
|
|
||||||
const unsigned getShaderID() const { return shaderID; }
|
|
||||||
const std::vector<Uniform>& getUniforms() { return uniforms; }
|
|
||||||
const std::vector<Uniform>& getOneShotUniforms() { return oneShotUniforms; }
|
|
||||||
void clearOneShot() { oneShotUniforms.clear(); }
|
|
||||||
void clearUniforms() { uniforms.clear(); }
|
|
||||||
protected:
|
|
||||||
unsigned shaderID;
|
|
||||||
template <typename T>
|
|
||||||
void editUniform(const std::string& name, T value)
|
|
||||||
{
|
|
||||||
uniforms.emplace_back(Uniform {name, value});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void editUniformOnce(const std::string& name, T value)
|
|
||||||
{
|
|
||||||
oneShotUniforms.emplace_back(Uniform {name, value});
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
std::vector<Uniform> uniforms;
|
|
||||||
std::vector<Uniform> oneShotUniforms;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _H_DRAWABLE_H
|
|
||||||
|
|
@ -2,14 +2,17 @@
|
||||||
#define _H_GLWINDOW_H
|
#define _H_GLWINDOW_H
|
||||||
|
|
||||||
#include <SDL_video.h>
|
#include <SDL_video.h>
|
||||||
#include <thirdparty/glad/glad.h>
|
//#include <SDL_opengl.h>
|
||||||
|
|
||||||
#include "utility/logger.h"
|
#include <glad/glad.h>
|
||||||
|
|
||||||
class GLWindow {
|
class GLWindow
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
GLWindow(const char *windowName, int width, int height)
|
GLWindow(const char* windowName, int width, int height) :
|
||||||
: w(width), h(height), name(windowName) {};
|
name(windowName),
|
||||||
|
w(width),
|
||||||
|
h(height) {};
|
||||||
~GLWindow();
|
~GLWindow();
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
|
|
@ -17,20 +20,34 @@ public:
|
||||||
void swap() { SDL_GL_SwapWindow(window); }
|
void swap() { SDL_GL_SwapWindow(window); }
|
||||||
void makeCurrent() { SDL_GL_MakeCurrent(window, glContext); }
|
void makeCurrent() { SDL_GL_MakeCurrent(window, glContext); }
|
||||||
|
|
||||||
unsigned Width() const { return w; }
|
unsigned width() const { return w; }
|
||||||
unsigned Height() const { return h; }
|
unsigned height() const { return h; }
|
||||||
|
|
||||||
void resizeWindow(size_t w, size_t h);
|
|
||||||
|
|
||||||
SDL_Window *getWindow() const { return window; }
|
|
||||||
const SDL_GLContext &getContext() const { return glContext; }
|
|
||||||
|
|
||||||
|
SDL_Window* getWindow() const { return window; }
|
||||||
|
const SDL_GLContext& getContext() const { return glContext; }
|
||||||
private:
|
private:
|
||||||
SDL_Window *window = nullptr;
|
SDL_Window* window = nullptr;
|
||||||
SDL_GLContext glContext = NULL;
|
SDL_GLContext glContext = NULL;
|
||||||
|
|
||||||
unsigned w, h;
|
unsigned w, h;
|
||||||
const char *name;
|
const char* name;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
bool GLWindow::Init()
|
||||||
|
{
|
||||||
|
window = SDL_CreateWindow(name, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_OPENGL);
|
||||||
|
if (!window)
|
||||||
|
return false;
|
||||||
|
glContext = SDL_GL_CreateContext(window);
|
||||||
|
if (!glContext)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLWindow::~GLWindow()
|
||||||
|
{
|
||||||
|
SDL_GL_DeleteContext(glContext);
|
||||||
|
SDL_DestroyWindow(window);
|
||||||
|
}
|
||||||
|
|
||||||
#endif // _H_GLWINDOW_H
|
#endif // _H_GLWINDOW_H
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <thirdparty/glad/glad.h>
|
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
#define MAX_INSTANCES 1000
|
#define MAX_INSTANCES 1000
|
||||||
#define MAX_TEXTURES 31
|
#define MAX_TEXTURES 31
|
||||||
|
|
@ -52,8 +50,6 @@ public:
|
||||||
const TextureArray* getTextureArray() { return textures; }
|
const TextureArray* getTextureArray() { return textures; }
|
||||||
const Texture* getTexture() { return texture; }
|
const Texture* getTexture() { return texture; }
|
||||||
|
|
||||||
~TileTextureInstance();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setup() override;
|
void setup() override;
|
||||||
TextureArray* textures = nullptr;
|
TextureArray* textures = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <thirdparty/glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef _H_POSTPROCESS_H
|
#ifndef _H_POSTPROCESS_H
|
||||||
#define _H_POSTPROCESS_H
|
#define _H_POSTPROCESS_H
|
||||||
|
|
||||||
#include <SDL_timer.h>
|
#include <SDL_Timer.h>
|
||||||
#include <thirdparty/glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
#ifndef _H_QUAD_H
|
#ifndef _H_QUAD_H
|
||||||
#define _H_QUAD_H
|
#define _H_QUAD_H
|
||||||
|
|
||||||
#include <thirdparty/glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <cstring>
|
|
||||||
|
|
||||||
class Quad
|
class Quad
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void draw();
|
void draw();
|
||||||
virtual ~Quad();
|
~Quad();
|
||||||
protected:
|
protected:
|
||||||
Quad(const float* vertexData);
|
Quad(const float* vertexData);
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -1,67 +1,116 @@
|
||||||
#ifndef _H_RENDERER_H
|
#ifndef _H_RENDERER_H
|
||||||
#define _H_RENDERER_H
|
#define _H_RENDERER_H
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <memory>
|
||||||
|
#include <variant>
|
||||||
|
#include <string>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
#include <memory>
|
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "graphics/drawable.h"
|
|
||||||
#include "graphics/glwindow.h"
|
|
||||||
#include "graphics/postprocess.h"
|
|
||||||
#include "graphics/quad.h"
|
#include "graphics/quad.h"
|
||||||
|
#include "graphics/postprocess.h"
|
||||||
|
|
||||||
class ResourceManager;
|
class ResourceManager;
|
||||||
class Shader;
|
class Shader;
|
||||||
|
|
||||||
enum class RenderLayer { Background, Map, GameObjects, Effects, HUD, Menu };
|
enum class RenderLayer {
|
||||||
|
Background,
|
||||||
|
Map,
|
||||||
|
GameObjects,
|
||||||
|
Effects,
|
||||||
|
HUD,
|
||||||
|
Menu
|
||||||
|
};
|
||||||
|
|
||||||
class Renderer {
|
using UniformValue = std::variant<
|
||||||
|
int,
|
||||||
|
bool,
|
||||||
|
float,
|
||||||
|
double,
|
||||||
|
glm::mat4,
|
||||||
|
glm::vec2
|
||||||
|
>;
|
||||||
|
|
||||||
|
struct Uniform {
|
||||||
|
std::string name;
|
||||||
|
UniformValue value;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Drawable
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
Renderer(const std::shared_ptr<ResourceManager> &,
|
virtual void draw() = 0;
|
||||||
const std::shared_ptr<GLWindow> &);
|
const unsigned getShaderID() const { return shaderID; }
|
||||||
|
const std::vector<Uniform>& getUniforms() { return uniforms; }
|
||||||
|
const std::vector<Uniform>& getOneShotUniforms() { return oneShotUniforms; }
|
||||||
|
void clearOneShot() { oneShotUniforms.clear(); }
|
||||||
|
void clearUniforms() { uniforms.clear(); }
|
||||||
|
protected:
|
||||||
|
unsigned shaderID;
|
||||||
|
template <typename T>
|
||||||
|
void editUniform(const std::string& name, T value)
|
||||||
|
{
|
||||||
|
uniforms.emplace_back(Uniform {name, value});
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void editUniformOnce(const std::string& name, T value)
|
||||||
|
{
|
||||||
|
oneShotUniforms.emplace_back(Uniform {name, value});
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::vector<Uniform> uniforms;
|
||||||
|
std::vector<Uniform> oneShotUniforms;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Renderer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Renderer(const std::shared_ptr<ResourceManager>&);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
void hookEventManager(const std::weak_ptr<EventManager> eventManager);
|
void hookEventManager(const std::weak_ptr<EventManager> eventManager);
|
||||||
|
|
||||||
void setProjAndViewMatrix(const glm::mat4 &proj, const glm::mat4 &view);
|
void setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view);
|
||||||
void addDrawable(RenderLayer renderLayer, Drawable *drawable);
|
void addDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable);
|
||||||
void removeDrawable(RenderLayer renderLayer, Drawable *drawable);
|
void removeDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable);
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<RenderLayer, std::vector<Drawable *>> worldLayerPool;
|
std::unordered_map<RenderLayer, std::vector<std::shared_ptr<Drawable>>> worldLayerPool;
|
||||||
std::unordered_map<RenderLayer, std::vector<Drawable *>> HUDLayerPool;
|
std::unordered_map<RenderLayer, std::vector<std::shared_ptr<Drawable>>> HUDLayerPool;
|
||||||
std::vector<RenderLayer> renderingOrder = {
|
std::vector<RenderLayer> renderingOrder = {
|
||||||
RenderLayer::Background, RenderLayer::Map, RenderLayer::GameObjects,
|
RenderLayer::Background,
|
||||||
RenderLayer::Effects, RenderLayer::HUD, RenderLayer::Menu};
|
RenderLayer::Map,
|
||||||
|
RenderLayer::GameObjects,
|
||||||
|
RenderLayer::Effects,
|
||||||
|
RenderLayer::HUD,
|
||||||
|
RenderLayer::Menu
|
||||||
|
};
|
||||||
|
|
||||||
void uploadUniforms(const unsigned shaderID,
|
void uploadUniforms(const unsigned shaderID, const std::vector<Uniform>& uniforms);
|
||||||
const std::vector<Uniform> &uniforms);
|
|
||||||
|
|
||||||
unsigned uboMatrices;
|
glm::mat4 projMat;
|
||||||
|
glm::mat4 viewMat;
|
||||||
|
|
||||||
union FrameBuffer {
|
union FrameBuffer {
|
||||||
unsigned int frame;
|
unsigned int frame;
|
||||||
unsigned int texture;
|
unsigned int texture;
|
||||||
} worldBuffer, hudBuffer;
|
}worldBuffer, hudBuffer;
|
||||||
|
|
||||||
std::unique_ptr<ScreenQuad> screenQuad;
|
std::unique_ptr<ScreenQuad> screenQuad;
|
||||||
|
|
||||||
std::shared_ptr<ResourceManager> resourceManager;
|
std::shared_ptr<ResourceManager> resourceManager;
|
||||||
std::shared_ptr<GLWindow> glWindow;
|
|
||||||
|
|
||||||
void initFrameBuffers();
|
void initFrameBuffers();
|
||||||
void initUniformBuffers();
|
|
||||||
|
|
||||||
void resizeFrameBuffers();
|
|
||||||
|
|
||||||
std::unique_ptr<Postprocessor> postProcessor;
|
std::unique_ptr<Postprocessor> postProcessor;
|
||||||
|
|
||||||
void sortLayerPool(auto &layerPool);
|
void sortLayerPool(auto& layerPool);
|
||||||
void renderPool(auto &layerPool);
|
void renderPool(auto& layerPool);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -1,21 +1,16 @@
|
||||||
#ifndef _H_SHADER_H
|
#ifndef _H_SHADER_H
|
||||||
#define _H_SHADER_H
|
#define _H_SHADER_H
|
||||||
|
|
||||||
#include <thirdparty/glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class Shader
|
class Shader
|
||||||
{
|
{
|
||||||
protected:
|
private:
|
||||||
bool compileAndLink(const char *vSource, const char *fSource);
|
|
||||||
std::string vertexPath;
|
|
||||||
std::string fragmentPath;
|
|
||||||
bool valid;
|
|
||||||
Shader();
|
|
||||||
public:
|
public:
|
||||||
unsigned int ID;
|
unsigned int ID;
|
||||||
Shader(const char* vertPath, const char* fragPath);
|
Shader(const char* vertexPath, const char* fragmentPath);
|
||||||
|
|
||||||
void use() { glUseProgram(ID); }
|
void use() { glUseProgram(ID); }
|
||||||
void setFloat(const std::string& name, float value);
|
void setFloat(const std::string& name, float value);
|
||||||
|
|
@ -26,15 +21,7 @@ public:
|
||||||
void setVec2(const std::string& name, const float* value);
|
void setVec2(const std::string& name, const float* value);
|
||||||
void setMatrix4f(const std::string& name, const float* value);
|
void setMatrix4f(const std::string& name, const float* value);
|
||||||
|
|
||||||
bool isValid() { return valid; }
|
~Shader();
|
||||||
|
|
||||||
virtual ~Shader();
|
|
||||||
};
|
|
||||||
|
|
||||||
class GenericShader : public Shader
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
GenericShader() : Shader() {};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _H_SHADER_H
|
#endif // _H_SHADER_H
|
||||||
|
|
@ -2,14 +2,13 @@
|
||||||
#define _H_SPRITE_H
|
#define _H_SPRITE_H
|
||||||
|
|
||||||
#include <SDL_image.h>
|
#include <SDL_image.h>
|
||||||
#include <thirdparty/glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
#include "utility/direction.h"
|
#include "utility/direction.h"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,6 @@
|
||||||
#define _H_TEXTURE_H
|
#define _H_TEXTURE_H
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <thirdparty/glad/glad.h>
|
|
||||||
#include <SDL_image.h>
|
|
||||||
|
|
||||||
struct SDL_Surface;
|
struct SDL_Surface;
|
||||||
|
|
||||||
|
|
@ -38,14 +36,14 @@ public:
|
||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
|
|
||||||
TextureData operator[](const size_t index) {
|
TextureData* operator[](const size_t index) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return textures.at(index);
|
return textures.at(index);
|
||||||
}
|
}
|
||||||
catch (std::exception&)
|
catch (std::exception&)
|
||||||
{
|
{
|
||||||
return { 0, 0 };
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -59,7 +57,7 @@ private:
|
||||||
|
|
||||||
size_t numOfLayers;
|
size_t numOfLayers;
|
||||||
unsigned ID = 0;
|
unsigned ID = 0;
|
||||||
std::vector<TextureData> textures;
|
std::vector<TextureData*> textures;
|
||||||
int canvasWidth = 0;
|
int canvasWidth = 0;
|
||||||
int canvasHeight = 0;
|
int canvasHeight = 0;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,59 +0,0 @@
|
||||||
#ifndef _H_AUDIO_STREAM_H
|
|
||||||
#define _H_AUDIO_STREAM_H
|
|
||||||
|
|
||||||
#define STB_VORBIS_HEADER_ONLY
|
|
||||||
#include "thirdparty/stb_vorbis.c"
|
|
||||||
|
|
||||||
#include "utility/logger.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#include <string>
|
|
||||||
#include <queue>
|
|
||||||
#include <mutex>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
class AudioStream
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AudioStream();
|
|
||||||
|
|
||||||
bool PlayStream();
|
|
||||||
void AddToQueue(std::string songName);
|
|
||||||
void PauseStream() { paused = !paused; }
|
|
||||||
|
|
||||||
void kill() { stopThread = true; }
|
|
||||||
~AudioStream();
|
|
||||||
private:
|
|
||||||
std::queue<std::string> songNames;
|
|
||||||
std::mutex mutex;
|
|
||||||
std::atomic<bool> stopThread;
|
|
||||||
std::atomic<bool> paused;
|
|
||||||
std::string CurStreamName();
|
|
||||||
bool eof;
|
|
||||||
std::thread streamThread;
|
|
||||||
|
|
||||||
int loadInitalChunk();
|
|
||||||
int loadNextChunk();
|
|
||||||
|
|
||||||
int loadChunk(ALuint buffer);
|
|
||||||
|
|
||||||
void popQueue();
|
|
||||||
void cycleQueue();
|
|
||||||
|
|
||||||
bool openFile(std::string fileName);
|
|
||||||
|
|
||||||
void stream();
|
|
||||||
|
|
||||||
short *data;
|
|
||||||
stb_vorbis *file;
|
|
||||||
stb_vorbis_info info;
|
|
||||||
ALuint buffers[4];
|
|
||||||
ALuint source;
|
|
||||||
ALint state;
|
|
||||||
ALint format;
|
|
||||||
size_t last_buffer;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _H_AUDIO_STREAM_H
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
||||||
#ifndef _H_AUDIO_ENGINE_H
|
|
||||||
#define _H_AUDIO_ENGINE_H
|
|
||||||
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#include <memory>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
#include "utility/events.h"
|
|
||||||
#include "sound/audiostream.h"
|
|
||||||
#include "sound/soundmanager.h"
|
|
||||||
#include "utility/resourcemanager.h"
|
|
||||||
#include "utility/logger.h"
|
|
||||||
|
|
||||||
class AudioEngine : public std::enable_shared_from_this<AudioEngine>
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AudioEngine(std::weak_ptr<ResourceManager> _resource);
|
|
||||||
|
|
||||||
void hookEventManager(std::weak_ptr<EventManager> _events);
|
|
||||||
void hookSceneManager(std::weak_ptr<EventManager> _events);
|
|
||||||
void pushMusic(std::string _songName);
|
|
||||||
void playMusic();
|
|
||||||
void pauseMusic();
|
|
||||||
void killMusic();
|
|
||||||
|
|
||||||
void poll();
|
|
||||||
void updateListener(const glm::vec3& pos);
|
|
||||||
|
|
||||||
~AudioEngine();
|
|
||||||
private:
|
|
||||||
std::unique_ptr<AudioStream> musicPlayer;
|
|
||||||
std::unique_ptr<SoundManager> soundManager;
|
|
||||||
std::weak_ptr<EventManager> globalEventManager;
|
|
||||||
std::weak_ptr<EventManager> sceneEventManager;
|
|
||||||
std::weak_ptr<ResourceManager> resourceManager;
|
|
||||||
ALCdevice *device;
|
|
||||||
ALCcontext *context;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
#endif // _H_AUDIO_ENGINE_H
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
/* Resource manager is going to hold a list of soundeffects for each item and the state that item is in.
|
|
||||||
* ie. A shotgun is reloading, so the shotgun is the item, and the state (reloading) has a list of different reloading sounds
|
|
||||||
* this is so we don't have annoying repeats.
|
|
||||||
*
|
|
||||||
* The sound engine is going to handle global events that are passed from these objects which will contain their entity ID
|
|
||||||
* and event specific information, such as event location and in special cases the type of item that is triggering the event
|
|
||||||
* such as my shotgun has fired so I will have my audio engine look through a list of shotgun firing sound effects to play,
|
|
||||||
* Once the engine knows what sound to play, it will look for the next available source, load the buffer onto that source and play.
|
|
||||||
* Every frame the engine is responsible for checking every source and pull off buffers that are no longer in use
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef _H_SOUNDEFFECT_H
|
|
||||||
#define _H_SOUNDEFFECT_H
|
|
||||||
|
|
||||||
#define STB_VORBIS_HEADER_ONLY
|
|
||||||
#include "thirdparty/stb_vorbis.c"
|
|
||||||
|
|
||||||
#include "utility/logger.h"
|
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class SoundEffect
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SoundEffect(const std::string& filename);
|
|
||||||
|
|
||||||
ALuint getBuffer() const { return buffer; }
|
|
||||||
bool isValid() const { return valid; }
|
|
||||||
|
|
||||||
~SoundEffect();
|
|
||||||
private:
|
|
||||||
bool loadFile(const std::string &filename);
|
|
||||||
|
|
||||||
ALuint buffer;
|
|
||||||
bool valid;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _H_SOUNDEFFECT_H
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
#ifndef _H_SOUNDMANAGER_H
|
|
||||||
#define _H_SOUNDMANAGER_H
|
|
||||||
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <array>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
|
|
||||||
class SoundManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SoundManager();
|
|
||||||
void playSound(ALuint buffer, int priority=10, const glm::vec3& pos = glm::vec3(0));
|
|
||||||
void pollSources();
|
|
||||||
~SoundManager();
|
|
||||||
private:
|
|
||||||
struct AudioSource {
|
|
||||||
ALuint source;
|
|
||||||
ALuint buffer;
|
|
||||||
bool inUse;
|
|
||||||
int priority;
|
|
||||||
};
|
|
||||||
std::array<AudioSource, 10> sources;
|
|
||||||
std::size_t lastUsed = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // _H_SOUNDMANAGER_H
|
|
||||||
311
YuppleMayham/include/thirdparty/KHR/khrplatform.h
vendored
311
YuppleMayham/include/thirdparty/KHR/khrplatform.h
vendored
|
|
@ -1,311 +0,0 @@
|
||||||
#ifndef __khrplatform_h_
|
|
||||||
#define __khrplatform_h_
|
|
||||||
|
|
||||||
/*
|
|
||||||
** Copyright (c) 2008-2018 The Khronos Group Inc.
|
|
||||||
**
|
|
||||||
** Permission is hereby granted, free of charge, to any person obtaining a
|
|
||||||
** copy of this software and/or associated documentation files (the
|
|
||||||
** "Materials"), to deal in the Materials without restriction, including
|
|
||||||
** without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
** distribute, sublicense, and/or sell copies of the Materials, and to
|
|
||||||
** permit persons to whom the Materials are furnished to do so, subject to
|
|
||||||
** the following conditions:
|
|
||||||
**
|
|
||||||
** The above copyright notice and this permission notice shall be included
|
|
||||||
** in all copies or substantial portions of the Materials.
|
|
||||||
**
|
|
||||||
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
||||||
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
||||||
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Khronos platform-specific types and definitions.
|
|
||||||
*
|
|
||||||
* The master copy of khrplatform.h is maintained in the Khronos EGL
|
|
||||||
* Registry repository at https://github.com/KhronosGroup/EGL-Registry
|
|
||||||
* The last semantic modification to khrplatform.h was at commit ID:
|
|
||||||
* 67a3e0864c2d75ea5287b9f3d2eb74a745936692
|
|
||||||
*
|
|
||||||
* Adopters may modify this file to suit their platform. Adopters are
|
|
||||||
* encouraged to submit platform specific modifications to the Khronos
|
|
||||||
* group so that they can be included in future versions of this file.
|
|
||||||
* Please submit changes by filing pull requests or issues on
|
|
||||||
* the EGL Registry repository linked above.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* See the Implementer's Guidelines for information about where this file
|
|
||||||
* should be located on your system and for more details of its use:
|
|
||||||
* http://www.khronos.org/registry/implementers_guide.pdf
|
|
||||||
*
|
|
||||||
* This file should be included as
|
|
||||||
* #include <KHR/khrplatform.h>
|
|
||||||
* by Khronos client API header files that use its types and defines.
|
|
||||||
*
|
|
||||||
* The types in khrplatform.h should only be used to define API-specific types.
|
|
||||||
*
|
|
||||||
* Types defined in khrplatform.h:
|
|
||||||
* khronos_int8_t signed 8 bit
|
|
||||||
* khronos_uint8_t unsigned 8 bit
|
|
||||||
* khronos_int16_t signed 16 bit
|
|
||||||
* khronos_uint16_t unsigned 16 bit
|
|
||||||
* khronos_int32_t signed 32 bit
|
|
||||||
* khronos_uint32_t unsigned 32 bit
|
|
||||||
* khronos_int64_t signed 64 bit
|
|
||||||
* khronos_uint64_t unsigned 64 bit
|
|
||||||
* khronos_intptr_t signed same number of bits as a pointer
|
|
||||||
* khronos_uintptr_t unsigned same number of bits as a pointer
|
|
||||||
* khronos_ssize_t signed size
|
|
||||||
* khronos_usize_t unsigned size
|
|
||||||
* khronos_float_t signed 32 bit floating point
|
|
||||||
* khronos_time_ns_t unsigned 64 bit time in nanoseconds
|
|
||||||
* khronos_utime_nanoseconds_t unsigned time interval or absolute time in
|
|
||||||
* nanoseconds
|
|
||||||
* khronos_stime_nanoseconds_t signed time interval in nanoseconds
|
|
||||||
* khronos_boolean_enum_t enumerated boolean type. This should
|
|
||||||
* only be used as a base type when a client API's boolean type is
|
|
||||||
* an enum. Client APIs which use an integer or other type for
|
|
||||||
* booleans cannot use this as the base type for their boolean.
|
|
||||||
*
|
|
||||||
* Tokens defined in khrplatform.h:
|
|
||||||
*
|
|
||||||
* KHRONOS_FALSE, KHRONOS_TRUE Enumerated boolean false/true values.
|
|
||||||
*
|
|
||||||
* KHRONOS_SUPPORT_INT64 is 1 if 64 bit integers are supported; otherwise 0.
|
|
||||||
* KHRONOS_SUPPORT_FLOAT is 1 if floats are supported; otherwise 0.
|
|
||||||
*
|
|
||||||
* Calling convention macros defined in this file:
|
|
||||||
* KHRONOS_APICALL
|
|
||||||
* KHRONOS_APIENTRY
|
|
||||||
* KHRONOS_APIATTRIBUTES
|
|
||||||
*
|
|
||||||
* These may be used in function prototypes as:
|
|
||||||
*
|
|
||||||
* KHRONOS_APICALL void KHRONOS_APIENTRY funcname(
|
|
||||||
* int arg1,
|
|
||||||
* int arg2) KHRONOS_APIATTRIBUTES;
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__SCITECH_SNAP__) && !defined(KHRONOS_STATIC)
|
|
||||||
# define KHRONOS_STATIC 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* Definition of KHRONOS_APICALL
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
* This precedes the return type of the function in the function prototype.
|
|
||||||
*/
|
|
||||||
#if defined(KHRONOS_STATIC)
|
|
||||||
/* If the preprocessor constant KHRONOS_STATIC is defined, make the
|
|
||||||
* header compatible with static linking. */
|
|
||||||
# define KHRONOS_APICALL
|
|
||||||
#elif defined(_WIN32)
|
|
||||||
# define KHRONOS_APICALL __declspec(dllimport)
|
|
||||||
#elif defined (__SYMBIAN32__)
|
|
||||||
# define KHRONOS_APICALL IMPORT_C
|
|
||||||
#elif defined(__ANDROID__)
|
|
||||||
# define KHRONOS_APICALL __attribute__((visibility("default")))
|
|
||||||
#else
|
|
||||||
# define KHRONOS_APICALL
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* Definition of KHRONOS_APIENTRY
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
* This follows the return type of the function and precedes the function
|
|
||||||
* name in the function prototype.
|
|
||||||
*/
|
|
||||||
#if defined(_WIN32) && !defined(_WIN32_WCE) && !defined(__SCITECH_SNAP__)
|
|
||||||
/* Win32 but not WinCE */
|
|
||||||
# define KHRONOS_APIENTRY __stdcall
|
|
||||||
#else
|
|
||||||
# define KHRONOS_APIENTRY
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* Definition of KHRONOS_APIATTRIBUTES
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
* This follows the closing parenthesis of the function prototype arguments.
|
|
||||||
*/
|
|
||||||
#if defined (__ARMCC_2__)
|
|
||||||
#define KHRONOS_APIATTRIBUTES __softfp
|
|
||||||
#else
|
|
||||||
#define KHRONOS_APIATTRIBUTES
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
* basic type definitions
|
|
||||||
*-----------------------------------------------------------------------*/
|
|
||||||
#if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__GNUC__) || defined(__SCO__) || defined(__USLC__)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Using <stdint.h>
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef int32_t khronos_int32_t;
|
|
||||||
typedef uint32_t khronos_uint32_t;
|
|
||||||
typedef int64_t khronos_int64_t;
|
|
||||||
typedef uint64_t khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
/*
|
|
||||||
* To support platform where unsigned long cannot be used interchangeably with
|
|
||||||
* inptr_t (e.g. CHERI-extended ISAs), we can use the stdint.h intptr_t.
|
|
||||||
* Ideally, we could just use (u)intptr_t everywhere, but this could result in
|
|
||||||
* ABI breakage if khronos_uintptr_t is changed from unsigned long to
|
|
||||||
* unsigned long long or similar (this results in different C++ name mangling).
|
|
||||||
* To avoid changes for existing platforms, we restrict usage of intptr_t to
|
|
||||||
* platforms where the size of a pointer is larger than the size of long.
|
|
||||||
*/
|
|
||||||
#if defined(__SIZEOF_LONG__) && defined(__SIZEOF_POINTER__)
|
|
||||||
#if __SIZEOF_POINTER__ > __SIZEOF_LONG__
|
|
||||||
#define KHRONOS_USE_INTPTR_T
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#elif defined(__VMS ) || defined(__sgi)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Using <inttypes.h>
|
|
||||||
*/
|
|
||||||
#include <inttypes.h>
|
|
||||||
typedef int32_t khronos_int32_t;
|
|
||||||
typedef uint32_t khronos_uint32_t;
|
|
||||||
typedef int64_t khronos_int64_t;
|
|
||||||
typedef uint64_t khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#elif defined(_WIN32) && !defined(__SCITECH_SNAP__)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Win32
|
|
||||||
*/
|
|
||||||
typedef __int32 khronos_int32_t;
|
|
||||||
typedef unsigned __int32 khronos_uint32_t;
|
|
||||||
typedef __int64 khronos_int64_t;
|
|
||||||
typedef unsigned __int64 khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#elif defined(__sun__) || defined(__digital__)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Sun or Digital
|
|
||||||
*/
|
|
||||||
typedef int khronos_int32_t;
|
|
||||||
typedef unsigned int khronos_uint32_t;
|
|
||||||
#if defined(__arch64__) || defined(_LP64)
|
|
||||||
typedef long int khronos_int64_t;
|
|
||||||
typedef unsigned long int khronos_uint64_t;
|
|
||||||
#else
|
|
||||||
typedef long long int khronos_int64_t;
|
|
||||||
typedef unsigned long long int khronos_uint64_t;
|
|
||||||
#endif /* __arch64__ */
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#elif 0
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Hypothetical platform with no float or int64 support
|
|
||||||
*/
|
|
||||||
typedef int khronos_int32_t;
|
|
||||||
typedef unsigned int khronos_uint32_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 0
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 0
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Generic fallback
|
|
||||||
*/
|
|
||||||
#include <stdint.h>
|
|
||||||
typedef int32_t khronos_int32_t;
|
|
||||||
typedef uint32_t khronos_uint32_t;
|
|
||||||
typedef int64_t khronos_int64_t;
|
|
||||||
typedef uint64_t khronos_uint64_t;
|
|
||||||
#define KHRONOS_SUPPORT_INT64 1
|
|
||||||
#define KHRONOS_SUPPORT_FLOAT 1
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Types that are (so far) the same on all platforms
|
|
||||||
*/
|
|
||||||
typedef signed char khronos_int8_t;
|
|
||||||
typedef unsigned char khronos_uint8_t;
|
|
||||||
typedef signed short int khronos_int16_t;
|
|
||||||
typedef unsigned short int khronos_uint16_t;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Types that differ between LLP64 and LP64 architectures - in LLP64,
|
|
||||||
* pointers are 64 bits, but 'long' is still 32 bits. Win64 appears
|
|
||||||
* to be the only LLP64 architecture in current use.
|
|
||||||
*/
|
|
||||||
#ifdef KHRONOS_USE_INTPTR_T
|
|
||||||
typedef intptr_t khronos_intptr_t;
|
|
||||||
typedef uintptr_t khronos_uintptr_t;
|
|
||||||
#elif defined(_WIN64)
|
|
||||||
typedef signed long long int khronos_intptr_t;
|
|
||||||
typedef unsigned long long int khronos_uintptr_t;
|
|
||||||
#else
|
|
||||||
typedef signed long int khronos_intptr_t;
|
|
||||||
typedef unsigned long int khronos_uintptr_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN64)
|
|
||||||
typedef signed long long int khronos_ssize_t;
|
|
||||||
typedef unsigned long long int khronos_usize_t;
|
|
||||||
#else
|
|
||||||
typedef signed long int khronos_ssize_t;
|
|
||||||
typedef unsigned long int khronos_usize_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if KHRONOS_SUPPORT_FLOAT
|
|
||||||
/*
|
|
||||||
* Float type
|
|
||||||
*/
|
|
||||||
typedef float khronos_float_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if KHRONOS_SUPPORT_INT64
|
|
||||||
/* Time types
|
|
||||||
*
|
|
||||||
* These types can be used to represent a time interval in nanoseconds or
|
|
||||||
* an absolute Unadjusted System Time. Unadjusted System Time is the number
|
|
||||||
* of nanoseconds since some arbitrary system event (e.g. since the last
|
|
||||||
* time the system booted). The Unadjusted System Time is an unsigned
|
|
||||||
* 64 bit value that wraps back to 0 every 584 years. Time intervals
|
|
||||||
* may be either signed or unsigned.
|
|
||||||
*/
|
|
||||||
typedef khronos_uint64_t khronos_utime_nanoseconds_t;
|
|
||||||
typedef khronos_int64_t khronos_stime_nanoseconds_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Dummy value used to pad enum types to 32 bits.
|
|
||||||
*/
|
|
||||||
#ifndef KHRONOS_MAX_ENUM
|
|
||||||
#define KHRONOS_MAX_ENUM 0x7FFFFFFF
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Enumerated boolean type
|
|
||||||
*
|
|
||||||
* Values other than zero should be considered to be true. Therefore
|
|
||||||
* comparisons should not be made against KHRONOS_TRUE.
|
|
||||||
*/
|
|
||||||
typedef enum {
|
|
||||||
KHRONOS_FALSE = 0,
|
|
||||||
KHRONOS_TRUE = 1,
|
|
||||||
KHRONOS_BOOLEAN_ENUM_FORCE_SIZE = KHRONOS_MAX_ENUM
|
|
||||||
} khronos_boolean_enum_t;
|
|
||||||
|
|
||||||
#endif /* __khrplatform_h_ */
|
|
||||||
2129
YuppleMayham/include/thirdparty/glad/glad.h
vendored
2129
YuppleMayham/include/thirdparty/glad/glad.h
vendored
File diff suppressed because it is too large
Load diff
5584
YuppleMayham/include/thirdparty/stb_vorbis.c
vendored
5584
YuppleMayham/include/thirdparty/stb_vorbis.c
vendored
File diff suppressed because it is too large
Load diff
|
|
@ -6,40 +6,9 @@
|
||||||
|
|
||||||
namespace UTIL
|
namespace UTIL
|
||||||
{
|
{
|
||||||
namespace AUDIO {
|
|
||||||
constexpr size_t CHUNK_SIZE = 4096;
|
|
||||||
constexpr int SAMPLE_RATE = 44100;
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr float INF_TIME = -99.6875f;
|
constexpr float INF_TIME = -99.6875f;
|
||||||
constexpr auto split = [](const std::string& s, size_t *left, size_t *right, std::string *out) {
|
|
||||||
if ((*right = s.find("/", *left)) != std::string::npos) {
|
|
||||||
if (out) {
|
|
||||||
*out = s.substr(*left, *right - *left);
|
|
||||||
}
|
|
||||||
*left = *right + 1;
|
|
||||||
} else {
|
|
||||||
if (out) {
|
|
||||||
out->append(s.substr(*left));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr auto get_type = [](const std::string& id) {
|
|
||||||
auto pos = id.find_last_of("/");
|
|
||||||
return (pos != std::string::npos) ? id.substr(pos + 1) : id;
|
|
||||||
};
|
|
||||||
|
|
||||||
constexpr auto get_generic = [](const std::string& id) {
|
|
||||||
size_t left = 0;
|
|
||||||
size_t right = 0;
|
|
||||||
std::string out;
|
|
||||||
split(id, &left, &right, &out);
|
|
||||||
return (out + "/generic/" + get_type(id));
|
|
||||||
};
|
|
||||||
|
|
||||||
void flip_surface(SDL_Surface* surface);
|
void flip_surface(SDL_Surface* surface);
|
||||||
std::string parsePrefix(const std::string& id);
|
|
||||||
|
|
||||||
class RandomGenerator
|
class RandomGenerator
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -145,8 +145,6 @@ public:
|
||||||
void idle() override { /*unused*/ }
|
void idle() override { /*unused*/ }
|
||||||
TYPE getType() const override { return TYPE::AI; }
|
TYPE getType() const override { return TYPE::AI; }
|
||||||
|
|
||||||
~AIComponent() { }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<AI> ai;
|
std::shared_ptr<AI> ai;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
/* C array of file 'Px437_IBM_VGA_9x8.ttf' */
|
|
||||||
|
|
||||||
#ifndef _H_FONT_DATA_H
|
|
||||||
#define _H_FONT_DATA_H
|
|
||||||
|
|
||||||
extern const unsigned char debug_font_data[];
|
|
||||||
extern const unsigned int debug_font_len;
|
|
||||||
|
|
||||||
#endif // _H_FONT_DATA_H
|
|
||||||
|
|
@ -1,13 +1,12 @@
|
||||||
#ifndef _H_DEBUGDRAW_H
|
#ifndef _H_DEBUGDRAW_H
|
||||||
#define _H_DEBUGDRAW_H
|
#define _H_DEBUGDRAW_H
|
||||||
|
|
||||||
#include <thirdparty/glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
#include <utility/ftfont.h>
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
struct ShaderSource {
|
struct ShaderSource {
|
||||||
const char* vertexShader;
|
const char* vertexShader;
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
#ifndef _H_EVENTS_H
|
#ifndef _H_EVENTS_H
|
||||||
#define _H_EVENTS_H
|
#define _H_EVENTS_H
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <typeindex>
|
#include <memory>
|
||||||
|
#include <functional>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "utility/direction.h"
|
#include "utility/direction.h"
|
||||||
|
|
@ -13,91 +12,124 @@
|
||||||
class Bullet;
|
class Bullet;
|
||||||
struct PhysicsComponent;
|
struct PhysicsComponent;
|
||||||
|
|
||||||
struct BulletFiredEvent {
|
class Event {
|
||||||
std::weak_ptr<Bullet> bullet;
|
public:
|
||||||
|
virtual ~Event() { };
|
||||||
|
virtual std::string getType() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BulletDiedEvent {
|
class BulletFiredEvent : public Event {
|
||||||
|
public:
|
||||||
|
BulletFiredEvent(const std::shared_ptr<Bullet>& bullet) : bullet(bullet) {};
|
||||||
|
std::string getType() const override { return "OnBulletFired"; }
|
||||||
|
std::shared_ptr<Bullet> bullet;
|
||||||
|
};
|
||||||
|
|
||||||
|
class BulletDiedEvent : public Event {
|
||||||
|
public:
|
||||||
|
BulletDiedEvent(const std::shared_ptr<PhysicsComponent>& physObj) : physObj(physObj) {};
|
||||||
|
std::string getType() const override { return "OnBulletDied"; }
|
||||||
std::shared_ptr<PhysicsComponent> physObj;
|
std::shared_ptr<PhysicsComponent> physObj;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct BulletCollideEvent {
|
class BulletCollideEvent : public Event {
|
||||||
|
public:
|
||||||
|
BulletCollideEvent(const unsigned int ownerID, const unsigned int victimID, const std::shared_ptr<PhysicsComponent>& bullet, const glm::vec2& normal)
|
||||||
|
: ownerID(ownerID), victimID(victimID), bullet(bullet), normal(normal){}
|
||||||
|
std::string getType() const override { return "OnBulletCollide"; }
|
||||||
unsigned int ownerID;
|
unsigned int ownerID;
|
||||||
unsigned int victimID;
|
unsigned int victimID;
|
||||||
std::shared_ptr<PhysicsComponent> bullet;
|
std::shared_ptr<PhysicsComponent> bullet;
|
||||||
glm::vec2 normal;
|
glm::vec2 normal;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DirectionChangeEvent {
|
class DirectionChangeEvent : public Event {
|
||||||
int entityid;
|
public:
|
||||||
|
DirectionChangeEvent(const int entityid, Direction direction) : direction(direction), entityid(entityid) {}
|
||||||
|
std::string getType() const override { return "OnDirectionChange"; }
|
||||||
Direction direction;
|
Direction direction;
|
||||||
};
|
|
||||||
|
|
||||||
struct EntityMoveEvent {
|
|
||||||
int entityid;
|
int entityid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EntityStopEvent {
|
class EntityMoveEvent : public Event {
|
||||||
|
public:
|
||||||
|
EntityMoveEvent(const int entityid) : entityid(entityid) {}
|
||||||
|
std::string getType() const override { return "OnEntityMove"; }
|
||||||
int entityid;
|
int entityid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EntityReloadEvent {
|
class EntityStopEvent : public Event {
|
||||||
int entityid;
|
public:
|
||||||
glm::vec3 position;
|
EntityStopEvent(const int entityid) : entityid(entityid) {}
|
||||||
std::string weaponType;
|
std::string getType() const override { return "OnEntityStop"; }
|
||||||
};
|
|
||||||
|
|
||||||
struct EntityFinishReloadEvent {
|
|
||||||
int entityid;
|
int entityid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EntityFireEvent {
|
class EntityReloadEvent : public Event {
|
||||||
|
public:
|
||||||
|
EntityReloadEvent(const int entityid) : entityid(entityid) {}
|
||||||
|
std::string getType() const override { return "OnEntityReload"; }
|
||||||
|
int entityid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntityFinishReloadEvent : public Event {
|
||||||
|
public:
|
||||||
|
EntityFinishReloadEvent(const int entityid) : entityid(entityid) {}
|
||||||
|
std::string getType() const override { return "OnEntityFinishReload"; }
|
||||||
|
int entityid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntityFireEvent : public Event {
|
||||||
|
public:
|
||||||
|
EntityFireEvent(const int entityid, const float fireDelay) : entityid(entityid), fireDelay(fireDelay) {}
|
||||||
|
std::string getType() const override { return "OnEntityFire"; }
|
||||||
int entityid;
|
int entityid;
|
||||||
float fireDelay;
|
float fireDelay;
|
||||||
glm::vec3 firePosition;
|
|
||||||
std::string weaponType;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AnimationFinishedEvent {
|
class AnimationFinishedEvent : public Event {
|
||||||
int entityid;
|
public:
|
||||||
|
AnimationFinishedEvent(const int entityid, const std::string animType) : animType(animType), entityid(entityid) {}
|
||||||
|
std::string getType() const override { return "OnAnimationFinished"; }
|
||||||
std::string animType;
|
std::string animType;
|
||||||
|
int entityid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScreenShakeEvent {
|
class ScreenShakeEvent : public Event {
|
||||||
|
public:
|
||||||
|
ScreenShakeEvent(float intensity, float duration) : intensity(intensity), duration(duration) {}
|
||||||
|
std::string getType() const override { return "OnScreenShake"; }
|
||||||
float intensity;
|
float intensity;
|
||||||
float duration;
|
float duration;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScreenBlurEvent {
|
class ScreenBlurEvent : public Event {
|
||||||
|
public:
|
||||||
|
ScreenBlurEvent(float intensity, float duration) : intensity(intensity), duration(duration) {}
|
||||||
|
std::string getType() const override { return "OnScreenBlur"; }
|
||||||
float intensity;
|
float intensity;
|
||||||
float duration;
|
float duration;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct WindowResizeEvent {
|
|
||||||
size_t width;
|
|
||||||
size_t height;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EventManager {
|
class EventManager {
|
||||||
public:
|
public:
|
||||||
template <typename T> using EventCallback = std::function<void(const T &)>;
|
using EventCallback = std::function<void(std::shared_ptr<Event>)>;
|
||||||
|
|
||||||
template <typename T> void subscribe(EventCallback<T> cb) {
|
void subscribe(std::string eventType, EventCallback callback) {
|
||||||
auto wrapper = [cb](void *ev) { cb(*static_cast<T *>(ev)); };
|
listeners[eventType].push_back(callback);
|
||||||
callbacks[typeid(T)].push_back(wrapper);
|
|
||||||
}
|
}
|
||||||
template <typename T> void notify(const T &event) {
|
void notify(const std::shared_ptr<Event>& event) {
|
||||||
auto iterator = callbacks.find(typeid(T));
|
auto iterator = listeners.find(event->getType());
|
||||||
if (iterator != callbacks.end()) {
|
if (iterator != listeners.end())
|
||||||
for (auto &cb : iterator->second) {
|
{
|
||||||
cb((void *)&event);
|
for (auto& callback : iterator->second)
|
||||||
|
{
|
||||||
|
callback(event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::type_index, std::vector<std::function<void(void *)>>>
|
std::unordered_map <std::string, std::vector <EventCallback>> listeners;
|
||||||
callbacks;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //_H_EVENTS_H
|
#endif //_H_EVENTS_H
|
||||||
|
|
@ -4,19 +4,14 @@
|
||||||
#include <ft2build.h>
|
#include <ft2build.h>
|
||||||
#include FT_FREETYPE_H
|
#include FT_FREETYPE_H
|
||||||
|
|
||||||
#include <thirdparty/glad/glad.h>
|
#include <iostream>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <format>
|
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <mutex>
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
#define DEBUG_TEXT(pos_vec2, col_vec4, scale, text, ...) DebugText::getInstance()->DrawDebugText(pos_vec2, col_vec4, scale, text, __VA_ARGS__)
|
|
||||||
|
|
||||||
class Text {
|
class Text {
|
||||||
protected:
|
private:
|
||||||
struct Font {
|
struct Font {
|
||||||
struct Character {
|
struct Character {
|
||||||
unsigned int TextureID;
|
unsigned int TextureID;
|
||||||
|
|
@ -31,11 +26,15 @@ protected:
|
||||||
unsigned int programID = 0;
|
unsigned int programID = 0;
|
||||||
unsigned int VAO = 0, VBO = 0;
|
unsigned int VAO = 0, VBO = 0;
|
||||||
unsigned int colorPos = 0;
|
unsigned int colorPos = 0;
|
||||||
|
unsigned int projPos = 0;
|
||||||
|
glm::mat4 projMatrix = glm::mat4(1.f);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Text();
|
Text();
|
||||||
bool loadFonts(const std::string& font_folder);
|
bool loadFonts(const std::string& font_folder);
|
||||||
|
|
||||||
|
void setProjectionMatrix(const glm::mat4& proj) { projMatrix = proj; }
|
||||||
|
|
||||||
void DrawText(
|
void DrawText(
|
||||||
const std::string& fontName,
|
const std::string& fontName,
|
||||||
const std::string& text,
|
const std::string& text,
|
||||||
|
|
@ -50,45 +49,6 @@ public:
|
||||||
float scale,
|
float scale,
|
||||||
const glm::vec4& color = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)
|
const glm::vec4& color = glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)
|
||||||
);
|
);
|
||||||
~Text() { };
|
|
||||||
};
|
|
||||||
|
|
||||||
class DebugText : public Text {
|
|
||||||
public:
|
|
||||||
static DebugText* getInstance();
|
|
||||||
bool loadFonts(const std::string &font_folder) = delete;
|
|
||||||
DebugText(DebugText const&) = delete;
|
|
||||||
void operator=(DebugText const&) = delete;
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
void DrawDebugText(const glm::vec2& pos,
|
|
||||||
const glm::vec4& color,
|
|
||||||
const float scale,
|
|
||||||
const std::string& text,
|
|
||||||
Args... args)
|
|
||||||
{
|
|
||||||
DrawText(pos, color, scale, formatString(text, args...));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
static std::mutex mutex;
|
|
||||||
static DebugText *instance;
|
|
||||||
Font font;
|
|
||||||
DebugText();
|
|
||||||
void loadDebugFont();
|
|
||||||
~DebugText();
|
|
||||||
|
|
||||||
template <typename... Args>
|
|
||||||
std::string formatString(const std::string& str, Args... args) const
|
|
||||||
{
|
|
||||||
return std::vformat(str, std::make_format_args(args...));
|
|
||||||
}
|
|
||||||
void DrawText(const glm::vec2& pos,
|
|
||||||
const glm::vec4& color,
|
|
||||||
const float scale,
|
|
||||||
const std::string& text);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _H_FTFONT_H
|
#endif // _H_FTFONT_H
|
||||||
|
|
|
||||||
|
|
@ -1,60 +1,48 @@
|
||||||
#ifndef _H_RESOURCEMANAGER_H
|
#ifndef _H_RESOURCEMANAGER_H
|
||||||
#define _H_RESOURCEMANAGER_H
|
#define _H_RESOURCEMANAGER_H
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
#include "graphics/background.h"
|
#include "utility/xmlloader.h"
|
||||||
#include "graphics/shader.h"
|
#include "graphics/shader.h"
|
||||||
#include "graphics/sprite.h"
|
#include "graphics/sprite.h"
|
||||||
#include "sound/soundeffect.h"
|
|
||||||
#include "utility/script.h"
|
|
||||||
#include "utility/xmlloader.h"
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
class Weapon;
|
class Weapon;
|
||||||
|
class Script;
|
||||||
class AnimationSet;
|
class AnimationSet;
|
||||||
|
class AIScript;
|
||||||
|
class WeaponScript;
|
||||||
|
class TileSetData;
|
||||||
class SpriteComponent;
|
class SpriteComponent;
|
||||||
|
|
||||||
class ResourceManager {
|
class ResourceManager
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
ResourceManager() : xmlLoader(std::make_shared<XMLLoader>()) {
|
ResourceManager() :
|
||||||
|
xmlLoader(std::make_shared<XMLLoader>())
|
||||||
|
{
|
||||||
xmlLoader->loadWeapons("weapons");
|
xmlLoader->loadWeapons("weapons");
|
||||||
xmlLoader->loadAnimations("animations");
|
xmlLoader->loadAnimations("animations");
|
||||||
xmlLoader->loadMonsters("monsters");
|
|
||||||
xmlLoader->loadTileSets("maps/tilesets");
|
xmlLoader->loadTileSets("maps/tilesets");
|
||||||
xmlLoader->loadMaps("maps");
|
xmlLoader->loadMaps("maps");
|
||||||
xmlLoader->loadScripts("scripts", loadLuaString);
|
|
||||||
xmlLoader->loadScenes("scenes");
|
xmlLoader->loadScenes("scenes");
|
||||||
xmlLoader->loadSoundEffects("sounds");
|
|
||||||
shaders["__fallback__"] = std::make_unique<GenericShader>();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns a NON-OWNING pointer to a sprite atlas
|
SpriteAtlas* loadSpriteAtlas (const std::string& path, float frameSize, bool isDirectional = false);
|
||||||
SpriteAtlas *loadSpriteAtlas(const std::string &path, float frameSize,
|
Sprite* loadSpriteStatic (const std::string& path);
|
||||||
bool isDirectional = false);
|
std::shared_ptr<AIScript> loadAIScript (const std::string& path);
|
||||||
// Returns a NON-OWNING pointer to a static sprite
|
std::shared_ptr<WeaponScript> loadWeaponScript (const std::string& path);
|
||||||
Sprite *loadSpriteStatic(const std::string &path);
|
|
||||||
// Returns a NON-OWNING pointer to a background
|
|
||||||
Background *loadBackground(const std::string &path);
|
|
||||||
const unsigned loadSoundEffect(const std::string &id);
|
|
||||||
template <typename T = Script>
|
|
||||||
std::unique_ptr<T> loadScript(const std::string &id);
|
|
||||||
std::unique_ptr<Weapon> loadWeapon(const std::string &name,
|
|
||||||
const unsigned weaponShaderID,
|
|
||||||
const unsigned bulletShaderID);
|
|
||||||
std::shared_ptr<AnimationSet> loadAnimationSet(const std::string &name,
|
|
||||||
int entityid = 0);
|
|
||||||
|
|
||||||
const unsigned loadShader(const std::string &name,
|
const unsigned loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath);
|
||||||
const std::string &vertexPath,
|
std::shared_ptr<Weapon> loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID);
|
||||||
const std::string &fragPath);
|
std::shared_ptr<SceneData> loadScene (const std::string& id);
|
||||||
const SceneData *loadScene(const std::string &id);
|
std::shared_ptr<AnimationSet> loadAnimationSet(const std::string& name, int entityid = 0);
|
||||||
const TileSetData *loadTileSet(const std::string &name);
|
std::shared_ptr<TileSetData> loadTileSet (const std::string& name);
|
||||||
|
|
||||||
// Returns a NON-OWNING pointer to a shader by ID
|
Shader* getShaderByID(unsigned int ID);
|
||||||
Shader *getShaderByID(unsigned int ID);
|
|
||||||
|
|
||||||
void clearResources();
|
void clearResources();
|
||||||
|
|
||||||
|
|
@ -62,29 +50,17 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, std::unique_ptr<Shader>> shaders;
|
std::unordered_map<std::string, std::unique_ptr<Shader>> shaders;
|
||||||
std::unordered_map<unsigned, Shader *> shaderIDs;
|
std::unordered_map<unsigned, Shader*> shaderIDs;
|
||||||
std::unordered_map<std::string, std::unique_ptr<SoundEffect>> sounds;
|
|
||||||
std::unordered_map<std::string, std::unique_ptr<Sprite>> sprites;
|
std::unordered_map<std::string, std::unique_ptr<Sprite>> sprites;
|
||||||
std::unordered_map<std::string, std::unique_ptr<Background>> backgrounds;
|
std::unordered_map<std::string, std::shared_ptr<Weapon>> weapons;
|
||||||
std::unordered_map<std::string, std::shared_ptr<TileSetData>> tileSets;
|
std::unordered_map<std::string, std::shared_ptr<Script>> scripts;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<TileSetData>>tileSets;
|
||||||
|
//std::unordered_map<std::string, std::shared_ptr<EntityData>> entityData;
|
||||||
|
//std::unordered_map<std::string, std::shared_ptr<SceneData>> scenes;
|
||||||
|
//std::unordered_map<std::string, std::shared_ptr<MapData>> maps;
|
||||||
|
//std::unordered_map<std::string, std::shared_ptr<TileType>> tiles;
|
||||||
|
|
||||||
std::shared_ptr<XMLLoader> xmlLoader;
|
std::shared_ptr<XMLLoader> xmlLoader;
|
||||||
|
|
||||||
static bool loadLuaString(ScriptData *script);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
std::unique_ptr<T> ResourceManager::loadScript(const std::string &id) {
|
|
||||||
const ScriptData *data = xmlLoader->getScriptData(id);
|
|
||||||
if (data == nullptr)
|
|
||||||
return nullptr;
|
|
||||||
try {
|
|
||||||
std::unique_ptr<T> script = std::make_unique<T>(data->script);
|
|
||||||
return std::move(script);
|
|
||||||
} catch (std::exception &e) {
|
|
||||||
LOG(ERROR, "Failed to load script '{}'", data->fileName);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // _H_RESOURCEMANAGER_H
|
#endif // _H_RESOURCEMANAGER_H
|
||||||
|
|
@ -3,22 +3,22 @@
|
||||||
|
|
||||||
#define SOL_ALL_SAFETIES_ON 1
|
#define SOL_ALL_SAFETIES_ON 1
|
||||||
|
|
||||||
|
#include <sol/sol.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sol/sol.hpp>
|
|
||||||
|
|
||||||
class Script {
|
class Script {
|
||||||
public:
|
public:
|
||||||
sol::state lua;
|
sol::state lua;
|
||||||
Script(const std::string &str);
|
Script(const std::string& path);
|
||||||
~Script();
|
virtual ~Script() {};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool loadScript(const std::string &str) {
|
bool loadScript(const std::string& path) {
|
||||||
auto result = lua.script(str);
|
auto result = lua.script_file(path);
|
||||||
if (!result.valid()) {
|
if (!result.valid())
|
||||||
|
{
|
||||||
sol::error err = result;
|
sol::error err = result;
|
||||||
std::cerr << "Failed to load script. Error: " << err.what() << std::endl;
|
std::cerr << "Failed to load script ( " << path << " ) Error: " << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
return result.valid();
|
return result.valid();
|
||||||
}
|
}
|
||||||
|
|
@ -27,21 +27,18 @@ private:
|
||||||
|
|
||||||
class AIScript : public Script {
|
class AIScript : public Script {
|
||||||
public:
|
public:
|
||||||
AIScript(const std::string &str) : Script(str) { registerUserTypes(); }
|
AIScript(const std::string& path) : Script(path) { registerUserTypes(); }
|
||||||
|
|
||||||
~AIScript();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void registerUserTypes();
|
|
||||||
|
void registerUserTypes() ;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WeaponScript : public Script {
|
class WeaponScript : public Script {
|
||||||
public:
|
public:
|
||||||
WeaponScript(const std::string &str) : Script(str) { registerUserTypes(); }
|
WeaponScript(const std::string& path) : Script(path) { registerUserTypes(); }
|
||||||
~WeaponScript();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void registerUserTypes();
|
void registerUserTypes() ;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _H_SCRIPT_H
|
#endif // _H_SCRIPT_H
|
||||||
|
|
@ -1,30 +1,25 @@
|
||||||
#ifndef _H_XMLLOADER_H
|
#ifndef _H_XMLLOADER_H
|
||||||
#define _H_XMLLOADER_H
|
#define _H_XMLLOADER_H
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <memory>
|
|
||||||
#include <string>
|
|
||||||
#include <unordered_map>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <memory>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <filesystem>
|
||||||
#include <tinyxml2.h>
|
#include <tinyxml2.h>
|
||||||
|
|
||||||
struct Tile;
|
struct Tile;
|
||||||
|
|
||||||
// Except for the player, these definitions are mostly overrides of the monster
|
|
||||||
// data
|
|
||||||
struct EntityData {
|
struct EntityData {
|
||||||
bool isPlayer;
|
bool isPlayer;
|
||||||
bool animated;
|
bool animated;
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
float hp;
|
|
||||||
std::string monsterDef;
|
|
||||||
std::string graphic;
|
std::string graphic;
|
||||||
std::string weapon = "gun/pistol";
|
std::string weapon = "pistolGun";
|
||||||
std::string script;
|
std::string script;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -72,24 +67,18 @@ struct SceneData {
|
||||||
std::string type;
|
std::string type;
|
||||||
std::string bgFile;
|
std::string bgFile;
|
||||||
|
|
||||||
const MapData *map;
|
std::shared_ptr<MapData> map;
|
||||||
std::vector<EntityData> entities;
|
std::vector<EntityData> entities;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Store our script as a string so we only need to read the file at boot
|
|
||||||
struct ScriptData {
|
|
||||||
std::string id;
|
|
||||||
std::string fileName;
|
|
||||||
std::string script;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct WeaponData {
|
struct WeaponData {
|
||||||
std::string id;
|
std::string name;
|
||||||
float fireSpeed = 250.0f;
|
float fireSpeed = 250.0f;
|
||||||
int clipSize = 21;
|
int clipSize = 21;
|
||||||
int maxAmmo = 512;
|
int maxAmmo = 512;
|
||||||
std::string script = "";
|
std::string script = "";
|
||||||
std::string graphic;
|
std::string graphic;
|
||||||
|
std::string animSet;
|
||||||
bool animated = false;
|
bool animated = false;
|
||||||
float sizeX = 50.f, sizeY = 50.f;
|
float sizeX = 50.f, sizeY = 50.f;
|
||||||
float offsetX = 0.f, offsetY = 0.f;
|
float offsetX = 0.f, offsetY = 0.f;
|
||||||
|
|
@ -100,147 +89,102 @@ struct WeaponData {
|
||||||
float modMin = 0.5f, modMax = 1.0f;
|
float modMin = 0.5f, modMax = 1.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ID is the new tactic I've decided on.
|
|
||||||
// Each animationable object will be given a prefix
|
|
||||||
// denoting their type and object so <type>/<object>
|
|
||||||
// This prefix will be used to look up the animation on
|
|
||||||
// the animation map
|
|
||||||
struct AnimationData {
|
struct AnimationData {
|
||||||
std::string id;
|
std::string name;
|
||||||
|
std::string type;
|
||||||
std::string spriteAtlas;
|
std::string spriteAtlas;
|
||||||
|
// Each entity will have a set of animations,
|
||||||
|
// this animation set is meant to keep each group
|
||||||
|
// of animations within their set.
|
||||||
|
// The actual set name is based on the file the animation
|
||||||
|
// is held in.
|
||||||
|
std::string animSet;
|
||||||
bool directional = false;
|
bool directional = false;
|
||||||
bool oneShot;
|
bool oneShot;
|
||||||
float FPS = 1.f;
|
float FPS = 1.f;
|
||||||
float frameSize;
|
float frameSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
// This holds a lot of defaults, but the scene can
|
class XMLLoader
|
||||||
// override a large portion of the definitions here
|
{
|
||||||
struct MonsterData {
|
|
||||||
std::string id;
|
|
||||||
std::string anim;
|
|
||||||
std::string weapon;
|
|
||||||
bool aggressive = false;
|
|
||||||
std::string behaviour;
|
|
||||||
float hp;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SoundData {
|
|
||||||
std::string id; // <type>/<object>/<state>
|
|
||||||
std::string path;
|
|
||||||
bool spatial;
|
|
||||||
};
|
|
||||||
|
|
||||||
class XMLLoader {
|
|
||||||
public:
|
public:
|
||||||
XMLLoader() {}
|
XMLLoader() {}
|
||||||
bool loadScenes(const char *sceneFolder);
|
bool loadScenes(const char* sceneFolder);
|
||||||
bool loadWeapons(const char *weaponFolder);
|
bool loadWeapons(const char* weaponFolder);
|
||||||
bool loadAnimations(const char *animationFolder);
|
bool loadAnimations(const char* animationFolder);
|
||||||
bool loadTileSets(const char *tileSetFolder);
|
bool loadTileSets(const char* tileSetFolder);
|
||||||
bool loadMaps(const char *mapFolder);
|
bool loadMaps(const char* mapFolder);
|
||||||
bool loadMonsters(const char *monsterFolder);
|
|
||||||
// luaLoader is the function we use to load the lua file.
|
|
||||||
// This will be defined in our resource manager
|
|
||||||
bool loadScripts(const char *scriptFolder,
|
|
||||||
std::function<bool(ScriptData *)> luaLoader);
|
|
||||||
bool loadSoundEffects(const char *soundFolder);
|
|
||||||
|
|
||||||
const SceneData *getSceneData(const std::string &id) const {
|
const std::shared_ptr<SceneData> getSceneData(const std::string& id) const {
|
||||||
try {
|
try {
|
||||||
return scenes.at(id).get();
|
return scenes.at(id);
|
||||||
} catch (std::exception &) {
|
}
|
||||||
|
catch (std::exception&) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ScriptData *getScriptData(const std::string &id) const {
|
const std::shared_ptr<MapData> getMapData(const std::string& name) const {
|
||||||
try {
|
try {
|
||||||
return scripts.at(id).get();
|
return maps.at(name);
|
||||||
} catch (std::exception &) {
|
}
|
||||||
|
catch (std::exception&) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MapData *getMapData(const std::string &name) const {
|
const std::shared_ptr<WeaponData> getWeaponData(const std::string& name) const {
|
||||||
try {
|
try {
|
||||||
return maps.at(name).get();
|
return weapons.at(name);
|
||||||
} catch (std::exception &) {
|
}
|
||||||
|
catch (std::exception&) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const WeaponData *getWeaponData(const std::string &id) const {
|
const std::shared_ptr<AnimationData> getAnimationData(const std::string& name) const {
|
||||||
try {
|
try {
|
||||||
return weapons.at(id).get();
|
return animations.at(name);
|
||||||
} catch (std::exception &) {
|
}
|
||||||
|
catch (std::exception&) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const AnimationData *getAnimationData(const std::string &id) const {
|
const std::shared_ptr<TileSetData> getTileSetData(const std::string& name) const {
|
||||||
try {
|
try {
|
||||||
return animations.at(id).get();
|
return tileSets.at(name);
|
||||||
} catch (std::exception &) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
}
|
catch (std::exception&) {
|
||||||
|
|
||||||
const TileSetData *getTileSetData(const std::string &name) const {
|
|
||||||
try {
|
|
||||||
return tileSets.at(name).get();
|
|
||||||
} catch (std::exception &) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const SoundData *getSoundData(const std::string &id) const {
|
|
||||||
try {
|
|
||||||
return sounds.at(id).get();
|
|
||||||
} catch (std::exception &) {
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// return a full set of animations, may need further optimization.
|
// return a full set of animations, may need further optimization.
|
||||||
// one idea is when loading animations we create a seperate map that holds
|
// one idea is when loading animations we create a seperate map that holds each set by their reference, so we can just do a simple,
|
||||||
// each set by their reference, so we can just do a simple, hash table lookup.
|
// hash table lookup.
|
||||||
std::vector<AnimationData *>
|
std::vector<std::shared_ptr<AnimationData>> getAnimationSet(const std::string& set) const {
|
||||||
getAnimationSet(const std::string &prefix) const {
|
std::vector<std::shared_ptr<AnimationData>> animSet;
|
||||||
std::vector<AnimationData *> animSet;
|
|
||||||
animSet.reserve(animations.size());
|
animSet.reserve(animations.size());
|
||||||
for (const auto &[id, anim] : animations) {
|
for (const auto& [name, anim] : animations) {
|
||||||
if (id.starts_with(prefix))
|
if (anim->animSet == set) animSet.push_back(anim);
|
||||||
animSet.push_back(anim.get());
|
|
||||||
}
|
}
|
||||||
animSet.shrink_to_fit();
|
animSet.shrink_to_fit();
|
||||||
return animSet;
|
return animSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clearData() {
|
void clearData() { scenes.clear(); weapons.clear(); animations.clear(); maps.clear(); tileSets.clear(); }
|
||||||
scenes.clear();
|
|
||||||
weapons.clear();
|
|
||||||
animations.clear();
|
|
||||||
maps.clear();
|
|
||||||
tileSets.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool loadXmlScene(const char *xmlFile, SceneData *out);
|
bool loadXmlScene(const char* xmlFile, SceneData* out);
|
||||||
bool loadEntityData(const char *xmlFile, SceneData *out);
|
bool loadEntityData(const char* xmlFile, SceneData* out);
|
||||||
bool loadTile(tinyxml2::XMLElement *tileElement, TileSetData::TileData *out);
|
bool loadTile(tinyxml2::XMLElement* tileElement, TileSetData::TileData* out);
|
||||||
bool loadObject(tinyxml2::XMLElement *objectElement,
|
bool loadObject(tinyxml2::XMLElement* objectElement, TileSetData::TileData::ObjectData* out);
|
||||||
TileSetData::TileData::ObjectData *out);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, std::unique_ptr<SceneData>> scenes;
|
std::unordered_map<std::string, std::shared_ptr<SceneData>> scenes;
|
||||||
std::unordered_map<std::string, std::unique_ptr<ScriptData>> scripts;
|
std::unordered_map<std::string, std::shared_ptr<WeaponData>> weapons;
|
||||||
std::unordered_map<std::string, std::unique_ptr<WeaponData>> weapons;
|
std::unordered_map<std::string, std::shared_ptr<AnimationData>> animations;
|
||||||
std::unordered_map<std::string, std::unique_ptr<AnimationData>> animations;
|
std::unordered_map<std::string, std::shared_ptr<MapData>> maps;
|
||||||
std::unordered_map<std::string, std::unique_ptr<MonsterData>> monsters;
|
std::unordered_map<std::string, std::shared_ptr<TileSetData>> tileSets;
|
||||||
std::unordered_map<std::string, std::unique_ptr<MapData>> maps;
|
|
||||||
std::unordered_map<std::string, std::unique_ptr<TileSetData>> tileSets;
|
|
||||||
std::unordered_map<std::string, std::unique_ptr<SoundData>> sounds;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _H_XMLLOADER_H
|
#endif // _H_XMLLOADER_H
|
||||||
|
|
@ -4,91 +4,78 @@
|
||||||
#include "utility/raycaster.h"
|
#include "utility/raycaster.h"
|
||||||
#include "utility/script.h"
|
#include "utility/script.h"
|
||||||
|
|
||||||
AI::AI(GameActor *actor, std::unique_ptr<Raycaster> raycaster)
|
#include <tracy/Tracy.hpp>
|
||||||
: state(AIState::Idle), raycaster(std::move(raycaster)), actor(actor),
|
|
||||||
lastGCTime(std::chrono::high_resolution_clock::now()), GCTimeout(3) {}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The behavior script works off of three different states, idle, patrol and
|
AI::AI(const std::shared_ptr<GameActor>& actor, const std::shared_ptr<Raycaster>& raycaster)
|
||||||
* alert. When the script is idle, this is */
|
: actor(actor), raycaster(raycaster), state(AIState::Idle),
|
||||||
void AI::attachBehaviourScript(std::unique_ptr<AIScript> behaviour) {
|
lastGCTime(std::chrono::high_resolution_clock::now()), GCTimeout(3)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void AI::attachBehaviourScript(const std::shared_ptr<AIScript>& behaviour)
|
||||||
|
{
|
||||||
// passing out instance of raycaster and this AI into our scripting api
|
// passing out instance of raycaster and this AI into our scripting api
|
||||||
// pay special attention each ai script has control of only their own instance
|
// pay special attention each ai script has control of only their own instance of ai!
|
||||||
// of ai!
|
this->behaviour = behaviour;
|
||||||
this->behaviour = std::move(behaviour);
|
this->behaviour->lua["raycaster"] = raycaster;
|
||||||
this->behaviour->lua["raycaster"] =
|
this->behaviour->lua["ai"] = shared_from_this();
|
||||||
sol::make_reference(this->behaviour->lua, raycaster.get());
|
|
||||||
this->behaviour->lua["ai"] = sol::make_reference(this->behaviour->lua, this);
|
|
||||||
|
|
||||||
|
if (this->behaviour->lua["idle"].valid())
|
||||||
idleFunc = this->behaviour->lua["idle"];
|
idleFunc = this->behaviour->lua["idle"];
|
||||||
|
if (this->behaviour->lua["patrol"].valid())
|
||||||
patrolFunc = this->behaviour->lua["patrol"];
|
patrolFunc = this->behaviour->lua["patrol"];
|
||||||
|
if (this->behaviour->lua["alert"].valid())
|
||||||
alertFunc = this->behaviour->lua["alert"];
|
alertFunc = this->behaviour->lua["alert"];
|
||||||
}
|
}
|
||||||
|
|
||||||
void AI::update() {
|
void AI::update()
|
||||||
|
{
|
||||||
try {
|
try {
|
||||||
// If our ai doesn't have a reference to the actor it's controlling it will
|
switch (state)
|
||||||
// do nothing. If our ai script does have an actor but no target, it will
|
{
|
||||||
// default to its idle state.
|
|
||||||
if (actor && target) {
|
|
||||||
switch (state) {
|
|
||||||
case AIState::Idle:
|
case AIState::Idle:
|
||||||
if (idleFunc.valid()) {
|
if (idleFunc.valid())
|
||||||
|
{
|
||||||
auto result = idleFunc(actor, target);
|
auto result = idleFunc(actor, target);
|
||||||
if (!result.valid()) {
|
if (!result.valid())
|
||||||
|
{
|
||||||
sol::error err = result;
|
sol::error err = result;
|
||||||
LOG(ERROR, "Lua error: {}", err.what(), NULL);
|
std::cerr << "lua error: " << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AIState::Patrol:
|
case AIState::Patrol:
|
||||||
if (patrolFunc.valid()) {
|
if (patrolFunc.valid())
|
||||||
|
{
|
||||||
auto result = patrolFunc(actor, target);
|
auto result = patrolFunc(actor, target);
|
||||||
if (!result.valid()) {
|
if (!result.valid())
|
||||||
|
{
|
||||||
sol::error err = result;
|
sol::error err = result;
|
||||||
LOG(ERROR, "Lua error: {}", err.what(), NULL);
|
std::cerr << "lua error: " << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case AIState::Alert:
|
case AIState::Alert:
|
||||||
if (alertFunc.valid()) {
|
if (alertFunc.valid())
|
||||||
|
{
|
||||||
auto result = alertFunc(actor, target);
|
auto result = alertFunc(actor, target);
|
||||||
if (!result.valid()) {
|
if (!result.valid())
|
||||||
|
{
|
||||||
sol::error err = result;
|
sol::error err = result;
|
||||||
LOG(ERROR, "Lua error: {}", err.what(), NULL);
|
std::cerr << "lua error: " << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (actor) {
|
std::chrono::high_resolution_clock::time_point curTime = std::chrono::high_resolution_clock::now();
|
||||||
if (idleFunc.valid()) {
|
if (curTime - lastGCTime >= GCTimeout)
|
||||||
auto result = idleFunc(actor, nullptr);
|
{
|
||||||
if (!result.valid()) {
|
|
||||||
sol::error err = result;
|
|
||||||
LOG(ERROR, "Lua Error: {}", err.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Collect garbage just to be sure.
|
|
||||||
std::chrono::high_resolution_clock::time_point curTime =
|
|
||||||
std::chrono::high_resolution_clock::now();
|
|
||||||
if (curTime - lastGCTime >= GCTimeout) {
|
|
||||||
behaviour->lua.collect_gc();
|
behaviour->lua.collect_gc();
|
||||||
lastGCTime = curTime;
|
lastGCTime = curTime;
|
||||||
}
|
}
|
||||||
} catch (const std::exception &e) {
|
}
|
||||||
LOG(ERROR, "Problem occured during AI update: {}", e.what());
|
catch (const std::exception& e) {
|
||||||
|
std::cerr << "Error during AI update: " << e.what() << std::endl;
|
||||||
state = AIState::Idle;
|
state = AIState::Idle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AI::~AI() {
|
|
||||||
// Just set all of the references to null, given they are smart pointers, they
|
|
||||||
// are freed when no longer used.
|
|
||||||
behaviour->lua["raycaster"] = sol::nil;
|
|
||||||
behaviour->lua["ai"] = sol::nil;
|
|
||||||
behaviour->lua["idle"] = sol::nil;
|
|
||||||
behaviour->lua["patrol"] = sol::nil;
|
|
||||||
behaviour->lua["alert"] = sol::nil;
|
|
||||||
behaviour->lua.collect_gc();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,26 @@
|
||||||
#include "gameplay/camera.h"
|
#include "gameplay/camera.h"
|
||||||
|
|
||||||
// follow our target set using the setTarget. If there is no target set the
|
void Camera::update(double deltaTime)
|
||||||
// camera will not move.
|
{
|
||||||
void Camera::update(double deltaTime) {
|
|
||||||
if (target == nullptr)
|
if (target == nullptr)
|
||||||
return;
|
return;
|
||||||
float smoothingFactor = 5.0f;
|
float smoothingFactor = 5.0f;
|
||||||
// if (glm::distance(target->getCenter(), getCenterPos()) > 20.f)
|
//if (glm::distance(target->getCenter(), getCenterPos()) > 20.f)
|
||||||
position += (target->getCenter() - getCenterPos()) * smoothingFactor *
|
position += (target->getCenter() - getCenterPos()) * smoothingFactor * static_cast<float>(deltaTime);
|
||||||
static_cast<float>(deltaTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 Camera::getViewMatrix() {
|
glm::mat4 Camera::getViewMatrix()
|
||||||
|
{
|
||||||
return glm::lookAt(position, position + front, up);
|
return glm::lookAt(position, position + front, up);
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 Camera::getProjectionMatrix() {
|
glm::mat4 Camera::getProjectionMatrix()
|
||||||
|
{
|
||||||
return glm::ortho(0.f, viewPortW, viewPortH, 0.f);
|
return glm::ortho(0.f, viewPortW, viewPortH, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::setViewportSize(float width, float height) {
|
const glm::vec3 Camera::worldToLocal(const glm::vec3& worldCoordinates)
|
||||||
viewPortW = width;
|
{
|
||||||
viewPortH = height;
|
//return worldCoordinates - position;
|
||||||
}
|
|
||||||
|
|
||||||
// The local coordinates are the corrdinates relative to the camera.
|
|
||||||
const glm::vec3 Camera::worldToLocal(const glm::vec3 &worldCoordinates) {
|
|
||||||
// return worldCoordinates - position;
|
|
||||||
return glm::vec3(getViewMatrix() * glm::vec4(worldCoordinates, 1.0f));
|
return glm::vec3(getViewMatrix() * glm::vec4(worldCoordinates, 1.0f));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "gameplay/entity.h"
|
#include "gameplay/entity.h"
|
||||||
|
#include "gameplay/camera.h"
|
||||||
#include "gameplay/physics.h"
|
#include "gameplay/physics.h"
|
||||||
|
|
||||||
void Entity::setPosition(const glm::vec3& position)
|
void Entity::setPosition(const glm::vec3& position)
|
||||||
|
|
@ -32,7 +33,6 @@ void Entity::flip()
|
||||||
flipped = !flipped;
|
flipped = !flipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add physics component implies more than one can be attached to an entity...
|
|
||||||
void Entity::addPhysicsComponent(const std::shared_ptr<PhysicsComponent>& physics)
|
void Entity::addPhysicsComponent(const std::shared_ptr<PhysicsComponent>& physics)
|
||||||
{
|
{
|
||||||
this->physics = physics;
|
this->physics = physics;
|
||||||
|
|
@ -40,35 +40,29 @@ void Entity::addPhysicsComponent(const std::shared_ptr<PhysicsComponent>& physic
|
||||||
|
|
||||||
void Entity::update(double deltaTime)
|
void Entity::update(double deltaTime)
|
||||||
{
|
{
|
||||||
// If our entity has a physics component attached and that they're moving,
|
if (physics && physics->rigidBody.velocity != glm::vec3(0.0f))
|
||||||
// we will update the entity position to match the rigidBody position.
|
|
||||||
if (physics && physics->rigidBody.velocity != glm::vec2(0.0f))
|
|
||||||
{
|
{
|
||||||
position = glm::vec3(physics->rigidBody.position, 0.f);
|
position = physics->rigidBody.position;
|
||||||
updateModelMatrix();
|
updateModelMatrix();
|
||||||
deltaPosition = glm::vec3(0.0f);
|
deltaPosition = glm::vec3(0.0f);
|
||||||
}
|
}
|
||||||
else if (!physics)
|
else if (!physics)
|
||||||
{
|
{
|
||||||
// In the case that the entity does not have a physics component we will handle movement on the entity itself.
|
|
||||||
position += deltaPosition * 1.f;
|
position += deltaPosition * 1.f;
|
||||||
updateModelMatrix();
|
updateModelMatrix();
|
||||||
deltaPosition = glm::vec3(0.f);
|
deltaPosition = glm::vec3(0.f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The entity will only need to update its model matrix and the flipped flag on its attached shader.
|
|
||||||
// The shader and sprite component will handle the drawing.
|
|
||||||
void Entity::draw()
|
void Entity::draw()
|
||||||
{
|
{
|
||||||
|
//glm::mat4 mvp = camera->getProjectionMatrix() * camera->getViewMatrix() * modelMatrix;
|
||||||
editUniform("model", modelMatrix);
|
editUniform("model", modelMatrix);
|
||||||
editUniform("flip", flipped);
|
editUniform("flip", flipped);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Entity::updateModelMatrix()
|
void Entity::updateModelMatrix()
|
||||||
{
|
{
|
||||||
// Quick sanity check to make sure our Z position is zero. Since we are in 2D
|
|
||||||
position.z = 0.f;
|
|
||||||
glm::mat4 rotationMat = (isRotatable) ? glm::rotate(glm::mat4(1.f), glm::radians(rotation), glm::vec3(0.0f, 0.0f, 1.0f)) : glm::mat4(1.0f);
|
glm::mat4 rotationMat = (isRotatable) ? glm::rotate(glm::mat4(1.f), glm::radians(rotation), glm::vec3(0.0f, 0.0f, 1.0f)) : glm::mat4(1.0f);
|
||||||
glm::mat4 translation = glm::translate(glm::mat4(1.f), position);
|
glm::mat4 translation = glm::translate(glm::mat4(1.f), position);
|
||||||
modelMatrix =
|
modelMatrix =
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,32 @@
|
||||||
#include "gameplay/game.h"
|
#include "gameplay/game.h"
|
||||||
#include "gameplay/input.h"
|
#include "gameplay/input.h"
|
||||||
#include "gameplay/scene.h"
|
#include "gameplay/scene.h"
|
||||||
|
/*due for possible removal!*/
|
||||||
|
#include "gameplay/gameactor.h"
|
||||||
|
#include "gameplay/weapons/weapon.h"
|
||||||
|
/*-------------------------*/
|
||||||
|
|
||||||
#include "utility/command.h"
|
#include "utility/command.h"
|
||||||
|
#include "utility/resourcemanager.h"
|
||||||
#include "utility/ftfont.h"
|
#include "utility/ftfont.h"
|
||||||
#include "utility/logger.h"
|
#include "utility/logger.h"
|
||||||
#include "utility/resourcemanager.h"
|
|
||||||
|
|
||||||
#include "graphics/glwindow.h"
|
#include "graphics/glwindow.h"
|
||||||
|
|
||||||
#include "sound/engine.h"
|
#include <iostream>
|
||||||
|
|
||||||
#include <SDL_video.h>
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <utility/events.h>
|
#include <utility/events.h>
|
||||||
|
|
||||||
bool Game::init() {
|
bool Game::init()
|
||||||
window = std::make_shared<GLWindow>("Yupple Mayham", 1024, 768);
|
{
|
||||||
|
window = std::make_shared<GLWindow>("Yupple Mayham", 800, 600);
|
||||||
|
|
||||||
if (!window->Init())
|
if (!window->Init())
|
||||||
ERROR_LOG("Failed to init GLWindow: {}", SDL_GetError());
|
ERROR_LOG("Failed to init GLWindow: {}", SDL_GetError());
|
||||||
|
|
||||||
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
|
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
|
||||||
ERROR_LOG("Failed to load GLLoader", NULL);
|
ERROR_LOG("Failed to load GLLoader");
|
||||||
|
|
||||||
#if _DEBUG
|
#if _DEBUG
|
||||||
LOG_LEVEL(DEBUG);
|
LOG_LEVEL(DEBUG);
|
||||||
|
|
@ -32,107 +35,71 @@ bool Game::init() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SDL_GL_SetSwapInterval(1);
|
SDL_GL_SetSwapInterval(1);
|
||||||
glViewport(0, 0, window->Width(), window->Height());
|
glViewport(0, 0, window->width(), window->height());
|
||||||
glDisable(GL_DEPTH_TEST);
|
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
// For now we'll init default bindings, but as we move forward controls will
|
// For now we'll init default bindings, but as we move forward controls will be set by the player and saved in controls.xml
|
||||||
// be set by the player and saved in controls.xml
|
|
||||||
inputHandler = std::make_shared<InputHandler>();
|
inputHandler = std::make_shared<InputHandler>();
|
||||||
inputHandler->bindKeyCommand(SDLK_w, 0, std::make_unique<MoveUpCommand>());
|
inputHandler->bindKeyCommand(SDLK_w, 0, new MoveUpCommand());
|
||||||
inputHandler->bindKeyCommand(SDLK_a, 0, std::make_unique<MoveLeftCommand>());
|
inputHandler->bindKeyCommand(SDLK_a, 0, new MoveLeftCommand());
|
||||||
inputHandler->bindKeyCommand(SDLK_s, 0, std::make_unique<MoveDownCommand>());
|
inputHandler->bindKeyCommand(SDLK_s, 0, new MoveDownCommand());
|
||||||
inputHandler->bindKeyCommand(SDLK_d, 0, std::make_unique<MoveRightCommand>());
|
inputHandler->bindKeyCommand(SDLK_d, 0, new MoveRightCommand());
|
||||||
|
|
||||||
inputHandler->bindMouseCommand(MOUSE_BUTTON_LEFT, 100,
|
inputHandler->bindMouseCommand(MOUSE_BUTTON_LEFT, 100, new ShootCommand());
|
||||||
std::make_unique<ShootCommand>());
|
inputHandler->bindMouseMotion(new FollowMouseCommand());
|
||||||
inputHandler->bindMouseMotion(std::make_unique<FollowMouseCommand>());
|
inputHandler->bindMouseScroll(new CycleCommand());
|
||||||
inputHandler->bindMouseScroll(std::make_unique<CycleCommand>());
|
|
||||||
|
|
||||||
game_state |= GAME_RUNNING;
|
game_state |= GAME_RUNNING;
|
||||||
globalEventManager = std::make_shared<EventManager>();
|
globalEventManager = std::make_shared<EventManager>();
|
||||||
resourceManager = std::make_shared<ResourceManager>();
|
resourceManager = std::make_shared<ResourceManager>();
|
||||||
renderer = std::make_shared<Renderer>(resourceManager, window);
|
renderer = std::make_shared<Renderer>(resourceManager);
|
||||||
audioEngine = std::make_shared<AudioEngine>(resourceManager);
|
|
||||||
camera = std::make_unique<Camera>(static_cast<float>(window->Width()),
|
|
||||||
static_cast<float>(window->Height()));
|
|
||||||
audioEngine->hookEventManager(globalEventManager);
|
|
||||||
/* Testing */
|
|
||||||
audioEngine->pushMusic("music/short_song.ogg");
|
|
||||||
audioEngine->pushMusic("music/bright.ogg");
|
|
||||||
audioEngine->pushMusic("music/main_song.ogg");
|
|
||||||
audioEngine->playMusic();
|
|
||||||
/* */
|
|
||||||
renderer->hookEventManager(globalEventManager);
|
renderer->hookEventManager(globalEventManager);
|
||||||
textHandler = std::make_shared<Text>();
|
textHandler = std::make_shared<Text>();
|
||||||
if (!textHandler->loadFonts("fonts"))
|
if (!textHandler->loadFonts("fonts"))
|
||||||
return false;
|
return false;
|
||||||
|
textHandler->setProjectionMatrix(glm::ortho(0.f, static_cast<float>(window->width()), 0.f, static_cast<float>(window->height())));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned Game::getWindowWidth() const { return window->Width(); }
|
const unsigned Game::getWindowWidth() const { return window->width(); }
|
||||||
const unsigned Game::getWindowHeight() const { return window->Height(); }
|
const unsigned Game::getWindowHeight() const { return window->height(); }
|
||||||
|
|
||||||
bool Game::loadDebugScene() {
|
bool Game::loadDebugScene()
|
||||||
currentScene = std::make_shared<Scene>(SCENE_SHOOTER, resourceManager,
|
{
|
||||||
globalEventManager);
|
currentScene = std::make_shared<Scene>(SCENE_SHOOTER, resourceManager, globalEventManager);
|
||||||
currentScene->init();
|
currentScene->init();
|
||||||
audioEngine->hookSceneManager(currentScene->getEventManager());
|
|
||||||
if (currentScene->getPlayer() == nullptr)
|
if (currentScene->getPlayer() == nullptr)
|
||||||
return false;
|
return false;
|
||||||
inputHandler->setActor(currentScene->getPlayer().get());
|
inputHandler->setActor(currentScene->getPlayer().get());
|
||||||
camera->setTarget(currentScene->getPlayer().get());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::captureInput(SDL_Event &e) {
|
void Game::handleInput(SDL_Event& e)
|
||||||
|
{
|
||||||
inputHandler->captureInput(e);
|
inputHandler->captureInput(e);
|
||||||
if (e.type == SDL_WINDOWEVENT_RESIZED) {
|
|
||||||
size_t width = static_cast<size_t>(e.window.data1);
|
|
||||||
size_t height = static_cast<size_t>(e.window.data2);
|
|
||||||
globalEventManager->notify<WindowResizeEvent>({width, height});
|
|
||||||
window->resizeWindow(width, height);
|
|
||||||
camera->setViewportSize(static_cast<float>(e.window.data1),
|
|
||||||
static_cast<float>(e.window.data2));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Game::executeInputs() {
|
|
||||||
inputHandler->handleInput();
|
inputHandler->handleInput();
|
||||||
inputHandler->executeCommands();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::update(double deltaTime) {
|
void Game::update(double deltaTime)
|
||||||
if (currentScene) {
|
{
|
||||||
|
if (currentScene)
|
||||||
currentScene->update(deltaTime);
|
currentScene->update(deltaTime);
|
||||||
if (auto player = currentScene->getPlayer()) {
|
|
||||||
audioEngine->updateListener(player->getPosition());
|
|
||||||
player->setLocalPosition(camera->worldToLocal(player->getPosition()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
camera->update(deltaTime);
|
|
||||||
audioEngine->poll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::render() {
|
void Game::render()
|
||||||
|
{
|
||||||
glClearColor(0.05f, 0.25f, 0.05f, 1.0f);
|
glClearColor(0.05f, 0.25f, 0.05f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
renderer->setProjAndViewMatrix(camera->getProjectionMatrix(),
|
|
||||||
camera->getViewMatrix());
|
|
||||||
|
|
||||||
if (currentScene)
|
if (currentScene)
|
||||||
|
{
|
||||||
currentScene->render(renderer);
|
currentScene->render(renderer);
|
||||||
|
/*Debug ammo indicator*/
|
||||||
|
textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->getMagazine()), glm::vec2(10, 10), 0.5f);
|
||||||
|
textHandler->DrawText("comic.ttf", "/", glm::vec2(50, 10), 0.5f);
|
||||||
|
textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->getAmmo()), glm::vec2(90, 10), 0.5f);
|
||||||
|
}
|
||||||
|
|
||||||
window->swap();
|
window->swap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::quit() { game_state = GAME_QUITTING; }
|
|
||||||
|
|
||||||
Game::~Game() {
|
|
||||||
if (audioEngine) {
|
|
||||||
audioEngine->killMusic();
|
|
||||||
}
|
|
||||||
resourceManager->clearResources();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -3,122 +3,104 @@
|
||||||
#include "gameplay/physics.h"
|
#include "gameplay/physics.h"
|
||||||
#include "gameplay/scene.h"
|
#include "gameplay/scene.h"
|
||||||
#include "gameplay/weapons/weapon.h"
|
#include "gameplay/weapons/weapon.h"
|
||||||
#include "utility/component.h"
|
|
||||||
#include "utility/direction.h"
|
|
||||||
#include "utility/events.h"
|
#include "utility/events.h"
|
||||||
|
#include "utility/direction.h"
|
||||||
|
#include "utility/component.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
// The components are smart pointer references to resources owned by the
|
GameActor::~GameActor() { }
|
||||||
// resource manager. So the GameActor is not responsible for cleaning resources.
|
|
||||||
GameActor::~GameActor() {}
|
|
||||||
|
|
||||||
// Adding a component also means attaching the id of the entity to the
|
void GameActor::addComponent(std::unique_ptr<Component> component)
|
||||||
// component, so it's aware of who owns it. This is important for event handling
|
{
|
||||||
void GameActor::addComponent(std::unique_ptr<Component> component) {
|
|
||||||
component->ownerid = entityid;
|
component->ownerid = entityid;
|
||||||
components.push_back(std::move(component));
|
components.push_back(std::move(component));
|
||||||
}
|
}
|
||||||
|
|
||||||
Weapon *GameActor::getHeldWeapon() const {
|
const std::shared_ptr<Weapon> GameActor::getHeldWeapon() const
|
||||||
return (weapons.empty() || currentWeaponIndex >= weapons.size())
|
{
|
||||||
? nullptr
|
return (weapons.empty() || currentWeaponIndex >= weapons.size()) ? nullptr : weapons[currentWeaponIndex];
|
||||||
: weapons[currentWeaponIndex].get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::span<Weapon *> GameActor::getAllWeapons() { return weaponCache; }
|
void GameActor::pickupWeapon(std::shared_ptr<Weapon> weapon)
|
||||||
|
{
|
||||||
// Keep a seperate vector that is used as the cache for external calls to
|
|
||||||
// getAllWeapons()
|
|
||||||
void GameActor::pickupWeapon(std::unique_ptr<Weapon> weapon) {
|
|
||||||
weapon->setWielder(this);
|
weapon->setWielder(this);
|
||||||
if (auto eventManager = sceneContext->getEventManager().lock()) {
|
if (auto eventManager = sceneContext->getEventManager().lock()) {
|
||||||
weapon->hookEventManager(eventManager);
|
weapon->hookEventManager(eventManager);
|
||||||
}
|
}
|
||||||
weaponCache.push_back(weapon.get());
|
weapons.push_back(weapon);
|
||||||
weapons.push_back(std::move(weapon));
|
|
||||||
// wield the newly picked up weapon.
|
// wield the newly picked up weapon.
|
||||||
getHeldWeapon()->putaway();
|
getHeldWeapon()->putaway();
|
||||||
currentWeaponIndex = weapons.size() - 1;
|
currentWeaponIndex = weapons.size() - 1;
|
||||||
getHeldWeapon()->wield();
|
getHeldWeapon()->wield();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameActor::setRotation(const float &rotation) {
|
void GameActor::setRotation(const float& rotation)
|
||||||
// Any attached animation component would be interested if their owner needs
|
{
|
||||||
// their sprite swapped
|
|
||||||
if (!isRotatable) {
|
if (!isRotatable) {
|
||||||
if (auto eventManager = sceneContext->getEventManager().lock()) {
|
if (auto eventManager = sceneContext->getEventManager().lock()) {
|
||||||
Direction newDir = getDirectionFromRotation(rotation);
|
Direction newDir = getDirectionFromRotation(rotation);
|
||||||
if (getDirectionFromRotation(this->rotation) != newDir)
|
if (getDirectionFromRotation(this->rotation) != newDir)
|
||||||
eventManager->notify<DirectionChangeEvent>({entityid, newDir});
|
eventManager->notify(std::make_shared<DirectionChangeEvent>(entityid, newDir));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->rotation = rotation;
|
this->rotation = rotation;
|
||||||
updateModelMatrix();
|
updateModelMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameActor::update(double deltaTime) {
|
void GameActor::update(double deltaTime)
|
||||||
|
{
|
||||||
Entity::update(deltaTime);
|
Entity::update(deltaTime);
|
||||||
|
|
||||||
for (const auto &component : components)
|
for (const auto& component : components)
|
||||||
component->update();
|
component->update();
|
||||||
for (const auto &weapon : weapons)
|
for (const auto& weapon : weapons)
|
||||||
weapon->update(deltaTime);
|
weapon->update(deltaTime);
|
||||||
|
|
||||||
// Not the cleanest solution, but this is to make sure the animation isn't
|
if (isMoving && !wasMoving)
|
||||||
// starting to move over and over.
|
{
|
||||||
if (isMoving && !wasMoving) {
|
|
||||||
if (auto event = sceneContext->getEventManager().lock()) {
|
if (auto event = sceneContext->getEventManager().lock()) {
|
||||||
event->notify<EntityMoveEvent>({entityid});
|
event->notify(std::make_shared<EntityMoveEvent>(entityid));
|
||||||
}
|
}
|
||||||
wasMoving = true;
|
wasMoving = true;
|
||||||
} else if (!isMoving && wasMoving) {
|
}
|
||||||
|
else if (!isMoving && wasMoving)
|
||||||
|
{
|
||||||
if (auto event = sceneContext->getEventManager().lock()) {
|
if (auto event = sceneContext->getEventManager().lock()) {
|
||||||
event->notify<EntityStopEvent>({entityid});
|
event->notify(std::make_shared<EntityStopEvent>(entityid));
|
||||||
}
|
}
|
||||||
wasMoving = false;
|
wasMoving = false;
|
||||||
}
|
}
|
||||||
isMoving = false;
|
isMoving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameActor::draw() {
|
void GameActor::draw()
|
||||||
|
{
|
||||||
Entity::draw();
|
Entity::draw();
|
||||||
for (const auto &component : components) {
|
|
||||||
|
// regular loop through components, but if the component returns true to kill, we erase it.
|
||||||
|
// Components are always assumed to be smart pointers!
|
||||||
|
for (const auto& component : components)
|
||||||
|
{
|
||||||
component->bind();
|
component->bind();
|
||||||
component->render();
|
component->render();
|
||||||
}
|
}
|
||||||
|
//for (auto& weapon : weapons)
|
||||||
|
// weapon->draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameActor::moveUp() {
|
void GameActor::moveUp() { if (physics) physics->rigidBody.applyForce(glm::vec3( 0.f,-1.f, 0.f), 1500.25f); isMoving = true; }
|
||||||
if (physics)
|
void GameActor::moveDown() { if (physics) physics->rigidBody.applyForce(glm::vec3( 0.f, 1.f, 0.f), 1500.25f); isMoving = true; }
|
||||||
physics->rigidBody.applyForce(glm::vec3(0.f, -1.f, 0.f), 1500.25f);
|
void GameActor::moveLeft() { if (physics) physics->rigidBody.applyForce(glm::vec3(-1.f, 0.f, 0.f), 1500.25f); isMoving = true; }
|
||||||
isMoving = true;
|
void GameActor::moveRight(){ if (physics) physics->rigidBody.applyForce(glm::vec3( 1.f, 0.f, 0.f), 1500.25f); isMoving = true; }
|
||||||
}
|
|
||||||
void GameActor::moveDown() {
|
|
||||||
if (physics)
|
|
||||||
physics->rigidBody.applyForce(glm::vec3(0.f, 1.f, 0.f), 1500.25f);
|
|
||||||
isMoving = true;
|
|
||||||
}
|
|
||||||
void GameActor::moveLeft() {
|
|
||||||
if (physics)
|
|
||||||
physics->rigidBody.applyForce(glm::vec3(-1.f, 0.f, 0.f), 1500.25f);
|
|
||||||
isMoving = true;
|
|
||||||
}
|
|
||||||
void GameActor::moveRight() {
|
|
||||||
if (physics)
|
|
||||||
physics->rigidBody.applyForce(glm::vec3(1.f, 0.f, 0.f), 1500.25f);
|
|
||||||
isMoving = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// top-down shooter mode controls
|
// top-down shooter mode controls
|
||||||
void GameActor::fireWeapon() const {
|
void GameActor::fireWeapon()const {
|
||||||
if (auto weapon = getHeldWeapon()) {
|
if (auto& weapon = getHeldWeapon()) {
|
||||||
if (weapon->shoot()) {
|
if (weapon->shoot()) {
|
||||||
// If it's the player that is shooting apply a shake and blur effect to
|
|
||||||
// give the shots some weight
|
|
||||||
if (sceneContext->getPlayerID() == entityid) {
|
if (sceneContext->getPlayerID() == entityid) {
|
||||||
if (auto gEvent = sceneContext->getGlobalEventManager().lock()) {
|
if (auto gEvent = sceneContext->getGlobalEventManager().lock()) {
|
||||||
gEvent->notify<ScreenShakeEvent>({0.01f, 0.8f});
|
gEvent->notify(std::make_shared<ScreenShakeEvent>(0.01f, 0.8f));
|
||||||
gEvent->notify<ScreenBlurEvent>({1.f, 0.8f});
|
gEvent->notify(std::make_shared<ScreenBlurEvent>(1.f, 0.8f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -135,46 +117,33 @@ void GameActor::cycleUpWeapons() {
|
||||||
void GameActor::cycleDownWeapons() {
|
void GameActor::cycleDownWeapons() {
|
||||||
if (!weapons.empty()) {
|
if (!weapons.empty()) {
|
||||||
weapons[currentWeaponIndex]->putaway();
|
weapons[currentWeaponIndex]->putaway();
|
||||||
currentWeaponIndex =
|
currentWeaponIndex = (currentWeaponIndex + weapons.size() - 1) % weapons.size();
|
||||||
(currentWeaponIndex + weapons.size() - 1) % weapons.size();
|
|
||||||
weapons[currentWeaponIndex]->wield();
|
weapons[currentWeaponIndex]->wield();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void GameActor::cycleWeapons(const MouseState &mouse_state) {
|
void GameActor::cycleWeapons(const MouseState& mouse_state)
|
||||||
|
{
|
||||||
if (mouse_state.scroll < 0)
|
if (mouse_state.scroll < 0)
|
||||||
cycleUpWeapons();
|
cycleUpWeapons();
|
||||||
else if (mouse_state.scroll > 0)
|
else if (mouse_state.scroll > 0)
|
||||||
cycleDownWeapons();
|
cycleDownWeapons();
|
||||||
}
|
}
|
||||||
void GameActor::followMouse(const MouseState &mouse_state) {
|
void GameActor::followMouse(const MouseState& mouse_state)
|
||||||
glm::vec2 direction = glm::vec2(mouse_state.x, mouse_state.y) -
|
{
|
||||||
glm::vec2(localPosition.x, localPosition.y);
|
glm::vec2 direction = glm::vec2(mouse_state.x, mouse_state.y) - glm::vec2(localPosition.x + 0.5f * scale.x, localPosition.y + 0.5f * scale.y);
|
||||||
float newRotation = glm::degrees(glm::atan(direction.y, direction.x));
|
float newRotation = glm::degrees(glm::atan(direction.y, direction.x));
|
||||||
if (getDirectionFromRotation(rotation) !=
|
if (getDirectionFromRotation(rotation) != getDirectionFromRotation(newRotation)) {
|
||||||
getDirectionFromRotation(newRotation)) {
|
|
||||||
if (auto event = sceneContext->getEventManager().lock()) {
|
if (auto event = sceneContext->getEventManager().lock()) {
|
||||||
event->notify<DirectionChangeEvent>(
|
event->notify(std::make_shared<DirectionChangeEvent>(entityid, getDirectionFromRotation(newRotation)));
|
||||||
{entityid, getDirectionFromRotation(newRotation)});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// setRotation(glm::degrees(glm::atan(direction.y, direction.x)));
|
//setRotation(glm::degrees(glm::atan(direction.y, direction.x)));
|
||||||
this->rotation = newRotation;
|
this->rotation = newRotation;
|
||||||
}
|
}
|
||||||
void GameActor::strafeLeft() {
|
void GameActor::strafeLeft() { position.x += sin(glm::radians(rotation)) * speed; position.y -= cos(glm::radians(rotation)) * speed; }
|
||||||
position.x += sin(glm::radians(rotation)) * speed;
|
void GameActor::strafeRight() { position.x -= sin(glm::radians(rotation)) * speed; position.y += cos(glm::radians(rotation)) * speed; }
|
||||||
position.y -= cos(glm::radians(rotation)) * speed;
|
void GameActor::moveBackward() { position.x -= cos(glm::radians(rotation)) * speed; position.y -= sin(glm::radians(rotation)) * speed; }
|
||||||
}
|
void GameActor::moveForward() {
|
||||||
void GameActor::strafeRight() {
|
|
||||||
position.x -= sin(glm::radians(rotation)) * speed;
|
|
||||||
position.y += cos(glm::radians(rotation)) * speed;
|
|
||||||
}
|
|
||||||
void GameActor::moveBackward() {
|
|
||||||
position.x -= cos(glm::radians(rotation)) * speed;
|
|
||||||
position.y -= sin(glm::radians(rotation)) * speed;
|
|
||||||
}
|
|
||||||
void GameActor::moveForward() { // More than likely the most useful of the
|
|
||||||
// movement commands so far. But this could
|
|
||||||
// change in the future
|
|
||||||
if (physics) {
|
if (physics) {
|
||||||
physics->rigidBody.velocity.x += cos(glm::radians(rotation)) * speed;
|
physics->rigidBody.velocity.x += cos(glm::radians(rotation)) * speed;
|
||||||
physics->rigidBody.velocity.y += sin(glm::radians(rotation)) * speed;
|
physics->rigidBody.velocity.y += sin(glm::radians(rotation)) * speed;
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,35 @@
|
||||||
#include "gameplay/input.h"
|
#include "gameplay/input.h"
|
||||||
#include "utility/command.h"
|
#include "utility/command.h"
|
||||||
|
#include "gameplay/gameactor.h"
|
||||||
|
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
|
|
||||||
void InputHandler::handleInput() {
|
void InputHandler::handleInput()
|
||||||
// If our input handler is not attached to an actor we return.
|
{
|
||||||
// This will be due for change given we will need to handle input during menus
|
if (!actor) return;
|
||||||
if (!actor)
|
|
||||||
return;
|
|
||||||
Uint32 currentTime = SDL_GetTicks();
|
Uint32 currentTime = SDL_GetTicks();
|
||||||
// check for bound keys that were pressed,
|
// check for bound keys that were pressed,
|
||||||
// next check if the hasn't been executed within the amount specified in delay
|
// next check if the hasn't been executed within the amount specified in delay
|
||||||
// if not execute the command and set lastExecution to currentTime
|
// if not execute the command and set lastExecution to currentTime
|
||||||
for (auto &[key, command] : keyCommands) {
|
for (auto& [key, command] : keyCommands)
|
||||||
if (keys[key] == true) {
|
{
|
||||||
if (currentTime - command.lastExecution >= command.delay) {
|
if (keys[key] == true)
|
||||||
commandQueue.push_back(command.cmd.get());
|
{
|
||||||
|
if (currentTime - command.lastExecution >= command.delay)
|
||||||
|
{
|
||||||
|
command.cmd->execute(*actor);
|
||||||
command.lastExecution = currentTime;
|
command.lastExecution = currentTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Same with the mouse, for this context we'll be checking for motion events
|
// Same with the mouse, for this context we'll be checking for motion events and for click events
|
||||||
// and for click events
|
for (auto& [button, command] : mouseCommands)
|
||||||
for (auto &[button, command] : mouseCommands) {
|
{
|
||||||
if (mouseButtons[button] == true) {
|
if (mouseButtons[button] == true)
|
||||||
if (currentTime - command.lastExecution >= command.delay) {
|
{
|
||||||
mouseQueue.push_back(command.cmd.get());
|
if (currentTime - command.lastExecution >= command.delay)
|
||||||
|
{
|
||||||
|
command.cmd->execute(*actor, mouse_state);
|
||||||
command.lastExecution = currentTime;
|
command.lastExecution = currentTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -34,20 +38,5 @@ void InputHandler::handleInput() {
|
||||||
mouseMotionCommand->execute(*actor, mouse_state);
|
mouseMotionCommand->execute(*actor, mouse_state);
|
||||||
if (mouseScrollCommand)
|
if (mouseScrollCommand)
|
||||||
mouseScrollCommand->execute(*actor, mouse_state);
|
mouseScrollCommand->execute(*actor, mouse_state);
|
||||||
mouse_state.scroll =
|
mouse_state.scroll = 0.0f; // clear mouse scroll since we have handled the event.
|
||||||
0.0f; // clear mouse scroll since we have handled the event.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Executes every captured command during the frame
|
|
||||||
void InputHandler::executeCommands() {
|
|
||||||
for (auto &command : commandQueue) {
|
|
||||||
command->execute(*actor);
|
|
||||||
}
|
|
||||||
for (auto &mouse : mouseQueue) {
|
|
||||||
mouse->execute(*actor, mouse_state);
|
|
||||||
}
|
|
||||||
commandQueue.clear();
|
|
||||||
mouseQueue.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
InputHandler::~InputHandler() {}
|
|
||||||
|
|
|
||||||
|
|
@ -1,99 +1,93 @@
|
||||||
#include "gameplay/map.h"
|
#include "gameplay/map.h"
|
||||||
|
#include "gameplay/camera.h"
|
||||||
|
#include "graphics/shader.h"
|
||||||
#include "graphics/texture.h"
|
#include "graphics/texture.h"
|
||||||
#include "utility/logger.h"
|
|
||||||
#include "utility/resourcemanager.h"
|
|
||||||
#include "utility/xmlloader.h"
|
#include "utility/xmlloader.h"
|
||||||
|
#include "utility/resourcemanager.h"
|
||||||
|
#include "utility/logger.h"
|
||||||
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
Map::Map(const MapData *mapData, const unsigned shaderID,
|
Map::Map(std::shared_ptr<MapData> mapData, const unsigned shaderID, std::shared_ptr<ResourceManager> resourceManager) :
|
||||||
std::shared_ptr<ResourceManager> resourceManager)
|
mapData(mapData),
|
||||||
: mapData(mapData), tileIds(mapData->tiles) {
|
tileIds(mapData->tiles)
|
||||||
|
{
|
||||||
this->shaderID = shaderID;
|
this->shaderID = shaderID;
|
||||||
|
|
||||||
// Tiles are held on layers, drawn back to front
|
for (auto& tileSet : mapData->tileSets)
|
||||||
for (auto &tileSet : mapData->tileSets)
|
|
||||||
tileSetData.push_back(resourceManager->loadTileSet(tileSet.path));
|
tileSetData.push_back(resourceManager->loadTileSet(tileSet.path));
|
||||||
|
|
||||||
if (!tileSetData.empty()) {
|
if (!tileSetData.empty())
|
||||||
// Storing all of the tilesets we will need to load and sending it to our
|
{
|
||||||
// texture instance handle
|
std::vector<const char*> buffer;
|
||||||
std::vector<const char *> buffer;
|
for (int layer = 0; layer < tileIds.size(); layer++)
|
||||||
for (int layer = 0; layer < tileIds.size(); layer++) {
|
{
|
||||||
buffer.clear();
|
buffer.clear();
|
||||||
for (auto &set : tileSetData)
|
for (auto& set : tileSetData)
|
||||||
buffer.push_back(set->file.c_str());
|
buffer.push_back(set->file.c_str());
|
||||||
if (!buffer.empty())
|
if (!buffer.empty())
|
||||||
instanceHandles.push_back(
|
instanceHandles.push_back(std::make_shared<TileTextureInstance>(buffer));
|
||||||
std::make_shared<TileTextureInstance>(buffer));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadMap();
|
loadMap();
|
||||||
createCollisionMap();
|
createCollisionMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
#include <glm/ext.hpp>
|
||||||
void Map::loadMap() {
|
void Map::loadMap()
|
||||||
|
{
|
||||||
tileData.resize(tileIds.size());
|
tileData.resize(tileIds.size());
|
||||||
// Tiles are drawn back to front, we track the tileset the tile comes from and
|
for (int layer = 0; layer < tileIds.size(); layer++)
|
||||||
// additional information about the tilesets themselves so the shader can
|
{
|
||||||
// properly draw the right tile. Each layer is its own instance
|
for (int y = 0; y < tileIds[layer].size(); y++)
|
||||||
for (int layer = 0; layer < tileIds.size(); layer++) {
|
{
|
||||||
for (int y = 0; y < tileIds[layer].size(); y++) {
|
for (int x = 0; x < tileIds[layer][y].size(); x++)
|
||||||
for (int x = 0; x < tileIds[layer][y].size(); x++) {
|
{
|
||||||
glm::mat4 modelMatrix =
|
glm::mat4 modelMatrix =
|
||||||
glm::translate(
|
glm::translate(glm::mat4(1.f), glm::vec3(x * mapData->tileSize, y * mapData->tileSize, 0.0f)) *
|
||||||
glm::mat4(1.f),
|
glm::scale(glm::mat4(1.f), glm::vec3(mapData->tileSize, mapData->tileSize, 1.0f));
|
||||||
glm::vec3(x * mapData->tileSize, y * mapData->tileSize, 0.0f)) *
|
|
||||||
glm::scale(glm::mat4(1.f),
|
|
||||||
glm::vec3(mapData->tileSize, mapData->tileSize, 1.0f));
|
|
||||||
|
|
||||||
int textureIndex =
|
int textureIndex = getTileSetIndex(tileIds[layer][y][x]);
|
||||||
static_cast<int>(getTileSetIndex(tileIds[layer][y][x]));
|
glm::vec2 originalSize = (textureIndex != -1) ?
|
||||||
glm::vec2 originalSize =
|
glm::vec2(tileSetData[textureIndex]->width, tileSetData[textureIndex]->height) :
|
||||||
(textureIndex != -1) ? glm::vec2(tileSetData[textureIndex]->width,
|
glm::vec2(0.0f);
|
||||||
tileSetData[textureIndex]->height)
|
int tilesPerRow = (textureIndex != -1) ? tileSetData[textureIndex]->columns : 0;
|
||||||
: glm::vec2(0.0f);
|
int startID = (textureIndex != -1) ? mapData->tileSets[textureIndex].startID : 0;
|
||||||
int tilesPerRow =
|
|
||||||
(textureIndex != -1) ? tileSetData[textureIndex]->columns : 0;
|
|
||||||
int startID =
|
|
||||||
(textureIndex != -1) ? mapData->tileSets[textureIndex].startID : 0;
|
|
||||||
int tileIndex = tileIds[layer][y][x];
|
int tileIndex = tileIds[layer][y][x];
|
||||||
|
|
||||||
tileData[layer].push_back({modelMatrix, originalSize, tileIndex,
|
tileData[layer].push_back({modelMatrix, originalSize, tileIndex, textureIndex, tilesPerRow, startID});
|
||||||
textureIndex, tilesPerRow, startID});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
instanceHandles[layer]->updateInstanceData(tileData[layer]);
|
instanceHandles[layer]->updateInstanceData(tileData[layer]);
|
||||||
}
|
}
|
||||||
// The canvas size is the same for every tile atlas, each one growing to match
|
glm::vec2 canvasSize = glm::vec2(instanceHandles[0]->getTextureArray()->getWidth(), instanceHandles[0]->getTextureArray()->getHeight());
|
||||||
// the size of the larget tileset
|
|
||||||
glm::vec2 canvasSize =
|
|
||||||
glm::vec2(instanceHandles[0]->getTextureArray()->getWidth(),
|
|
||||||
instanceHandles[0]->getTextureArray()->getHeight());
|
|
||||||
editUniformOnce("uCanvasSize", canvasSize);
|
editUniformOnce("uCanvasSize", canvasSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The collision map is just a 2D array of 0's and 1's, 1's being collidable and
|
void Map::createCollisionMap()
|
||||||
// 0's not. This may see some changes in the future to properly address special
|
{
|
||||||
// tiles, such as portals.
|
|
||||||
void Map::createCollisionMap() {
|
|
||||||
// Match collisionMap to map size
|
// Match collisionMap to map size
|
||||||
collisionMap.resize(tileIds[0].size());
|
collisionMap.resize(tileIds[0].size());
|
||||||
for (int y = 0; y < tileIds[0].size(); ++y) {
|
for (int y = 0; y < tileIds[0].size(); ++y)
|
||||||
|
{
|
||||||
collisionMap[y].resize(tileIds[0][y].size(), 0);
|
collisionMap[y].resize(tileIds[0][y].size(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int layer = 0; layer < tileIds.size(); layer++) {
|
for (int layer = 0; layer < tileIds.size(); layer++)
|
||||||
for (int y = 0; y < tileIds[layer].size(); y++) {
|
{
|
||||||
for (int x = 0; x < tileIds[layer][y].size(); x++) {
|
for (int y = 0; y < tileIds[layer].size(); y++)
|
||||||
|
{
|
||||||
|
for (int x = 0; x < tileIds[layer][y].size(); x++)
|
||||||
|
{
|
||||||
int id = tileIds[layer][y][x];
|
int id = tileIds[layer][y][x];
|
||||||
size_t tileSetIndex = getTileSetIndex(id);
|
int tileSetIndex = getTileSetIndex(id);
|
||||||
if (tileSetIndex == -1)
|
if (tileSetIndex == -1)
|
||||||
collisionMap[y][x] = 0;
|
collisionMap[y][x] = 0;
|
||||||
else {
|
else
|
||||||
|
{
|
||||||
int startID = mapData->tileSets[tileSetIndex].startID;
|
int startID = mapData->tileSets[tileSetIndex].startID;
|
||||||
auto &tile = tileSetData[tileSetIndex]->tiles[id - startID];
|
auto& tile = tileSetData[tileSetIndex]->tiles[id - startID];
|
||||||
if (!tile->walkable)
|
if (!tile->walkable)
|
||||||
collisionMap[y][x] = 1;
|
collisionMap[y][x] = 1;
|
||||||
}
|
}
|
||||||
|
|
@ -102,26 +96,28 @@ void Map::createCollisionMap() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Draw each layer in it's own instance
|
void Map::draw()
|
||||||
void Map::draw() {
|
{
|
||||||
for (int layer = 0; layer < instanceHandles.size(); layer++) {
|
for (int layer = 0; layer < instanceHandles.size(); layer++)
|
||||||
|
{
|
||||||
instanceHandles[layer]->draw();
|
instanceHandles[layer]->draw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Use this function to get the tileSetIndex from a tile ID.
|
Use this function to get the tileSetIndex from a tile ID.
|
||||||
the index of the tileSet is the same index as the texture index used in the
|
the index of the tileSet is the same index as the texture index used in the instanceHandle
|
||||||
instanceHandle
|
|
||||||
|
|
||||||
returns tileSetIndex of the tile id passed. Unless the id is either 0 or
|
returns tileSetIndex of the tile id passed. Unless the id is either 0 or
|
||||||
the returned tileSetIndex is out of bounds, returns -1
|
the returned tileSetIndex is out of bounds, returns -1
|
||||||
*/
|
*/
|
||||||
size_t Map::getTileSetIndex(int id) const {
|
int Map::getTileSetIndex(int id) const
|
||||||
|
{
|
||||||
// work from the bottom, break if ID > startID
|
// work from the bottom, break if ID > startID
|
||||||
// If we get a textureIndex of -1 then we are on an empty tile
|
// If we get a textureIndex of -1 then we are on an empty tile
|
||||||
size_t tileSetIndex = mapData->tileSets.size() - 1;
|
size_t tileSetIndex = mapData->tileSets.size() - 1;
|
||||||
for (; tileSetIndex != -1; --tileSetIndex) {
|
for (; tileSetIndex != -1; --tileSetIndex)
|
||||||
|
{
|
||||||
if (id >= mapData->tileSets[tileSetIndex].startID)
|
if (id >= mapData->tileSets[tileSetIndex].startID)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,29 +2,33 @@
|
||||||
#include "gameplay/weapons/bullet.h"
|
#include "gameplay/weapons/bullet.h"
|
||||||
#include "utility/events.h"
|
#include "utility/events.h"
|
||||||
|
|
||||||
void PhysicsEngine::hookEventManager(
|
#include "utility/logger.h"
|
||||||
const std::shared_ptr<EventManager> &eventManager) {
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void PhysicsEngine::hookEventManager(const std::shared_ptr<EventManager>& eventManager)
|
||||||
|
{
|
||||||
this->eventManager = eventManager;
|
this->eventManager = eventManager;
|
||||||
this->eventManager->subscribe<BulletFiredEvent>(
|
this->eventManager->subscribe("OnBulletFired", [this](std::shared_ptr<Event> e) {
|
||||||
[this](const BulletFiredEvent &event) {
|
auto bulletEvent = std::static_pointer_cast<BulletFiredEvent>(e);
|
||||||
if (auto bullet = event.bullet.lock()) {
|
this->addObject(bulletEvent->bullet->getPhysicsComponent());
|
||||||
this->addObject(bullet->getPhysicsComponent());
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
this->eventManager->subscribe<BulletDiedEvent>(
|
this->eventManager->subscribe("OnBulletDied", [this](std::shared_ptr<Event> e) {
|
||||||
[this](const BulletDiedEvent &event) {
|
auto bulletEvent = std::static_pointer_cast<BulletDiedEvent>(e);
|
||||||
this->removeObject(event.physObj);
|
this->removeObject(bulletEvent->physObj);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<PhysicsComponent>
|
std::shared_ptr<PhysicsComponent> PhysicsEngine::createObject(const unsigned int ID,
|
||||||
PhysicsEngine::createObject(const unsigned int ID, const glm::vec3 &pos,
|
const glm::vec3& pos,
|
||||||
float mass, PhysicsComponent::Collider::Shape shape,
|
float mass,
|
||||||
glm::vec3 dimensions, const glm::vec3 offset) {
|
PhysicsComponent::Collider::Shape shape,
|
||||||
auto component = std::make_shared<PhysicsComponent>();
|
glm::vec3 dimensions, const
|
||||||
|
glm::vec3 offset)
|
||||||
|
{
|
||||||
|
auto component = std::make_shared <PhysicsComponent>();
|
||||||
component->ID = ID;
|
component->ID = ID;
|
||||||
component->rigidBody.position = pos;
|
component->rigidBody.position = pos;
|
||||||
component->rigidBody.acceleration = glm::vec2(0.f);
|
|
||||||
component->rigidBody.mass = mass;
|
component->rigidBody.mass = mass;
|
||||||
component->collider.shape = shape;
|
component->collider.shape = shape;
|
||||||
component->collider.dimensions = dimensions;
|
component->collider.dimensions = dimensions;
|
||||||
|
|
@ -34,50 +38,50 @@ PhysicsEngine::createObject(const unsigned int ID, const glm::vec3 &pos,
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsEngine::loadCollisionMap(
|
void PhysicsEngine::loadCollisionMap(const std::vector<std::vector<int>>& collisionMap, float tileSize)
|
||||||
const std::vector<std::vector<int>> &collisionMap, float tileSize) {
|
{
|
||||||
this->collisionMap = collisionMap;
|
this->collisionMap = collisionMap;
|
||||||
this->tileSize = tileSize;
|
this->tileSize = tileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsEngine::addObject(
|
void PhysicsEngine::addObject(const std::shared_ptr<PhysicsComponent>& component)
|
||||||
const std::shared_ptr<PhysicsComponent> &component) {
|
{
|
||||||
if (component)
|
if (component)
|
||||||
objects.emplace_back(component);
|
objects.emplace_back(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsEngine::removeObject(
|
void PhysicsEngine::removeObject(const std::shared_ptr<PhysicsComponent>& component)
|
||||||
const std::shared_ptr<PhysicsComponent> &component) {
|
{
|
||||||
if (std::find(objects.begin(), objects.end(), component) != objects.end())
|
if (std::find(objects.begin(), objects.end(), component) != objects.end())
|
||||||
objects.erase(std::remove(objects.begin(), objects.end(), component));
|
objects.erase(std::remove(objects.begin(), objects.end(), component));
|
||||||
}
|
}
|
||||||
|
|
||||||
int PhysicsEngine::getTileCollider(const glm::vec2 &position) {
|
int PhysicsEngine::getTileCollider(const glm::vec3& position)
|
||||||
|
{
|
||||||
int x = static_cast<int>((position.x + 0.5f * tileSize) / tileSize);
|
int x = static_cast<int>((position.x + 0.5f * tileSize) / tileSize);
|
||||||
int y = static_cast<int>((position.y + 0.5f * tileSize) / tileSize);
|
int y = static_cast<int>((position.y + 0.5f * tileSize) / tileSize);
|
||||||
if (y >= 0 && y < collisionMap.size()) {
|
if (y >= 0 && y < collisionMap.size())
|
||||||
|
{
|
||||||
if (x >= 0 && x < collisionMap[y].size())
|
if (x >= 0 && x < collisionMap[y].size())
|
||||||
return collisionMap[y][x];
|
return collisionMap[y][x];
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsEngine::getPossibleCollisions() {
|
void PhysicsEngine::getPossibleCollisions()
|
||||||
|
{
|
||||||
objCollisions.clear();
|
objCollisions.clear();
|
||||||
for (size_t i = 0; i < objects.size(); ++i) {
|
for (size_t i = 0; i < objects.size(); ++i)
|
||||||
auto &obj = objects[i];
|
{
|
||||||
for (size_t j = i + 1; j < objects.size(); ++j) {
|
auto& obj = objects[i];
|
||||||
auto &colliderObj = objects[j];
|
for (size_t j = i + 1; j < objects.size(); ++j)
|
||||||
if (obj.get() == colliderObj.get() || obj->ID == colliderObj->ID)
|
{
|
||||||
continue;
|
auto& colliderObj = objects[j];
|
||||||
float colliderRight = colliderObj->rigidBody.position.x +
|
if (obj.get() == colliderObj.get() || obj->ID == colliderObj->ID) continue;
|
||||||
colliderObj->collider.dimensions.x;
|
float colliderRight = colliderObj->rigidBody.position.x + colliderObj->collider.dimensions.x;
|
||||||
float colliderBottom = colliderObj->rigidBody.position.y +
|
float colliderBottom = colliderObj->rigidBody.position.y + colliderObj->collider.dimensions.y;
|
||||||
colliderObj->collider.dimensions.y;
|
float objectRight = obj->rigidBody.position.x + obj->collider.dimensions.x;
|
||||||
float objectRight =
|
float objectBottom = obj->rigidBody.position.y + obj->collider.dimensions.y;
|
||||||
obj->rigidBody.position.x + obj->collider.dimensions.x;
|
|
||||||
float objectBottom =
|
|
||||||
obj->rigidBody.position.y + obj->collider.dimensions.y;
|
|
||||||
if ((obj->rigidBody.position.x <= colliderRight &&
|
if ((obj->rigidBody.position.x <= colliderRight &&
|
||||||
objectRight >= colliderObj->rigidBody.position.x) ||
|
objectRight >= colliderObj->rigidBody.position.x) ||
|
||||||
(obj->rigidBody.position.y <= colliderBottom &&
|
(obj->rigidBody.position.y <= colliderBottom &&
|
||||||
|
|
@ -87,103 +91,98 @@ void PhysicsEngine::getPossibleCollisions() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsEngine::resolvePossibleCollisions() {
|
void PhysicsEngine::resolvePossibleCollisions()
|
||||||
for (auto &objs : objCollisions) {
|
{
|
||||||
// Solve for two circles, we'll need to expand upon this for different
|
for (auto& objs : objCollisions)
|
||||||
// colliders...
|
{
|
||||||
float sumOfRadius =
|
// Solve for two circles, we'll need to expand upon this for different colliders...
|
||||||
objs.first->collider.dimensions.x + objs.second->collider.dimensions.x;
|
float sumOfRadius = objs.first->collider.dimensions.x + objs.second->collider.dimensions.x;
|
||||||
glm::vec2 objFirstCenter =
|
glm::vec3 objFirstCenter = objs.first->rigidBody.position + objs.first->collider.offset;
|
||||||
objs.first->rigidBody.position + objs.first->collider.offset;
|
glm::vec3 objSecondCenter = objs.second->rigidBody.position + objs.second->collider.offset;
|
||||||
glm::vec2 objSecondCenter =
|
glm::vec3 distance = objFirstCenter - objSecondCenter;
|
||||||
objs.second->rigidBody.position + objs.second->collider.offset;
|
if (glm::length(distance) < sumOfRadius)
|
||||||
glm::vec2 distance = objFirstCenter - objSecondCenter;
|
{
|
||||||
if (glm::length(distance) < sumOfRadius) {
|
|
||||||
// We got impact!
|
// We got impact!
|
||||||
glm::vec2 normal = distance / glm::length(distance);
|
glm::vec3 normal = distance / glm::length(distance);
|
||||||
// That impact is a bullet hitting a gameactor!
|
// That impact is a bullet hitting a gameactor!
|
||||||
if ((objs.first->isBullet || objs.second->isBullet) &&
|
if ((objs.first->isBullet || objs.second->isBullet) && !(objs.first->isBullet && objs.second->isBullet))
|
||||||
!(objs.first->isBullet && objs.second->isBullet)) {
|
{
|
||||||
eventManager->notify(std::make_shared<BulletCollideEvent>(
|
eventManager->notify(std::make_shared<BulletCollideEvent>(
|
||||||
(objs.first->isBullet) ? objs.first->ID : objs.second->ID,
|
( objs.first->isBullet) ? objs.first->ID : objs.second->ID,
|
||||||
(!objs.first->isBullet) ? objs.first->ID : objs.second->ID,
|
(!objs.first->isBullet) ? objs.first->ID : objs.second->ID,
|
||||||
std::make_shared<PhysicsComponent>(
|
std::make_shared<PhysicsComponent>(( objs.first->isBullet) ? objs.first : objs.second),
|
||||||
(objs.first->isBullet) ? objs.first : objs.second),
|
normal
|
||||||
normal));
|
));
|
||||||
}
|
}
|
||||||
// Apply impulse force
|
// Apply impulse force
|
||||||
float penetrationDepth = sumOfRadius - glm::length(distance);
|
float penetrationDepth = sumOfRadius - glm::length(distance);
|
||||||
glm::vec2 correctionVector =
|
glm::vec3 correctionVector = normal * (penetrationDepth / ((1 / objs.first->rigidBody.mass) + (1 / objs.second->rigidBody.mass)));
|
||||||
normal * (penetrationDepth / ((1 / objs.first->rigidBody.mass) +
|
glm::vec3 vrel = objs.first->rigidBody.velocity - objs.second->rigidBody.velocity;
|
||||||
(1 / objs.second->rigidBody.mass)));
|
|
||||||
glm::vec2 vrel =
|
|
||||||
objs.first->rigidBody.velocity - objs.second->rigidBody.velocity;
|
|
||||||
|
|
||||||
// smallest elasticity of the two colliders
|
// smallest elasticity of the two colliders
|
||||||
float e = std::min(objs.first->rigidBody.elasticity,
|
float e = std::min(objs.first->rigidBody.elasticity, objs.second->rigidBody.elasticity);
|
||||||
objs.second->rigidBody.elasticity);
|
float impulseMag = (-(1 + e) * glm::dot(vrel, normal)) / ((1 / objs.first->rigidBody.mass) + (1 / objs.second->rigidBody.mass));
|
||||||
float impulseMag = (-(1 + e) * glm::dot(vrel, normal)) /
|
|
||||||
((1 / objs.first->rigidBody.mass) +
|
|
||||||
(1 / objs.second->rigidBody.mass));
|
|
||||||
|
|
||||||
objs.first->rigidBody.position +=
|
objs.first->rigidBody.position += (correctionVector / objs.first->rigidBody.mass);
|
||||||
(correctionVector / objs.first->rigidBody.mass);
|
objs.second->rigidBody.position -= (correctionVector / objs.second->rigidBody.mass);
|
||||||
objs.second->rigidBody.position -=
|
objs.first->rigidBody.velocity += impulseMag * normal / objs.first->rigidBody.mass;
|
||||||
(correctionVector / objs.second->rigidBody.mass);
|
objs.second->rigidBody.velocity -= impulseMag * normal / objs.second->rigidBody.mass;
|
||||||
objs.first->rigidBody.velocity +=
|
|
||||||
impulseMag * normal / objs.first->rigidBody.mass;
|
|
||||||
objs.second->rigidBody.velocity -=
|
|
||||||
impulseMag * normal / objs.second->rigidBody.mass;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsEngine::resolveWorldCollision(
|
void PhysicsEngine::resolveWorldCollision(const std::shared_ptr<PhysicsComponent>& obj)
|
||||||
const std::shared_ptr<PhysicsComponent> &obj) {
|
{
|
||||||
switch (obj->collider.shape) {
|
switch (obj->collider.shape)
|
||||||
|
{
|
||||||
case PhysicsComponent::Collider::Shape::Circle:
|
case PhysicsComponent::Collider::Shape::Circle:
|
||||||
float radius = obj->collider.dimensions.x;
|
float radius = obj->collider.dimensions.x;
|
||||||
glm::vec2 position = obj->rigidBody.position + obj->collider.offset;
|
glm::vec3 position = obj->rigidBody.position + obj->collider.offset;
|
||||||
int topTile = getTileCollider(position - glm::vec2(0, radius));
|
int topTile = getTileCollider(position - glm::vec3(0, radius, 0));
|
||||||
int bottomTile = getTileCollider(position + glm::vec2(0, radius));
|
int bottomTile = getTileCollider(position + glm::vec3(0, radius, 0));
|
||||||
int leftTile = getTileCollider(position - glm::vec2(radius, 0));
|
int leftTile = getTileCollider(position - glm::vec3(radius, 0, 0));
|
||||||
int rightTile = getTileCollider(position + glm::vec2(radius, 0));
|
int rightTile = getTileCollider(position + glm::vec3(radius, 0, 0));
|
||||||
if (obj->isBullet) {
|
if (obj->isBullet)
|
||||||
if (topTile || bottomTile || leftTile || rightTile) {
|
{
|
||||||
|
if (topTile || bottomTile || leftTile || rightTile)
|
||||||
|
{
|
||||||
eventManager->notify(std::make_shared<BulletDiedEvent>(obj));
|
eventManager->notify(std::make_shared<BulletDiedEvent>(obj));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
int tileY = static_cast<int>((position.y) / tileSize);
|
int tileY = static_cast<int>((position.y) / tileSize);
|
||||||
int tileX = static_cast<int>((position.x) / tileSize);
|
int tileX = static_cast<int>((position.x) / tileSize);
|
||||||
if (topTile) {
|
if (topTile)
|
||||||
// obj->rigidBody.velocity.y = -obj->rigidBody.velocity.y;
|
{
|
||||||
obj->rigidBody.position.y =
|
//obj->rigidBody.velocity.y = -obj->rigidBody.velocity.y;
|
||||||
(tileY + 1) * tileSize + obj->collider.offset.y;
|
obj->rigidBody.position.y = (tileY+1) * tileSize + obj->collider.offset.y;
|
||||||
}
|
}
|
||||||
if (bottomTile) {
|
if (bottomTile)
|
||||||
// obj->rigidBody.velocity.y = -obj->rigidBody.velocity.y;
|
{
|
||||||
obj->rigidBody.position.y = (tileY)*tileSize - obj->collider.offset.y;
|
//obj->rigidBody.velocity.y = -obj->rigidBody.velocity.y;
|
||||||
|
obj->rigidBody.position.y = (tileY) * tileSize - obj->collider.offset.y;
|
||||||
}
|
}
|
||||||
if (leftTile) {
|
if (leftTile)
|
||||||
// obj->rigidBody.velocity.x = -obj->rigidBody.velocity.x;
|
{
|
||||||
obj->rigidBody.position.x =
|
//obj->rigidBody.velocity.x = -obj->rigidBody.velocity.x;
|
||||||
(tileX + 1) * tileSize + obj->collider.offset.x;
|
obj->rigidBody.position.x = (tileX + 1) * tileSize + obj->collider.offset.x;
|
||||||
}
|
}
|
||||||
if (rightTile) {
|
if (rightTile)
|
||||||
// obj->rigidBody.velocity.x = -obj->rigidBody.velocity.x;
|
{
|
||||||
obj->rigidBody.position.x = (tileX)*tileSize - obj->collider.offset.x;
|
//obj->rigidBody.velocity.x = -obj->rigidBody.velocity.x;
|
||||||
|
obj->rigidBody.position.x = (tileX) * tileSize - obj->collider.offset.x;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PhysicsEngine::update(double deltaTime) {
|
void PhysicsEngine::update(double deltaTime)
|
||||||
for (auto &obj : objects) {
|
{
|
||||||
if (!obj)
|
for (auto& obj : objects)
|
||||||
continue;
|
{
|
||||||
glm::vec2 frictionForce = obj->rigidBody.velocity * -0.1f;
|
if (!obj) continue;
|
||||||
if (std::abs(obj->rigidBody.acceleration.x) ==
|
glm::vec3 frictionForce = obj->rigidBody.velocity * -0.1f;
|
||||||
std::abs(obj->rigidBody.acceleration.y)) {
|
if (std::abs(obj->rigidBody.acceleration.x) == std::abs(obj->rigidBody.acceleration.y))
|
||||||
|
{
|
||||||
obj->rigidBody.acceleration.x *= 0.75f;
|
obj->rigidBody.acceleration.x *= 0.75f;
|
||||||
obj->rigidBody.acceleration.y *= 0.75f;
|
obj->rigidBody.acceleration.y *= 0.75f;
|
||||||
}
|
}
|
||||||
|
|
@ -193,22 +192,18 @@ void PhysicsEngine::update(double deltaTime) {
|
||||||
|
|
||||||
float maxSpeed = 500.f;
|
float maxSpeed = 500.f;
|
||||||
float curSpeed = glm::length(obj->rigidBody.velocity);
|
float curSpeed = glm::length(obj->rigidBody.velocity);
|
||||||
if (curSpeed > maxSpeed) {
|
if (curSpeed > maxSpeed)
|
||||||
|
{
|
||||||
// Move at maxspeed
|
// Move at maxspeed
|
||||||
obj->rigidBody.velocity =
|
obj->rigidBody.velocity = glm::normalize(obj->rigidBody.velocity) * maxSpeed;
|
||||||
glm::normalize(obj->rigidBody.velocity) * maxSpeed;
|
|
||||||
}
|
}
|
||||||
obj->rigidBody.acceleration = glm::vec2(0.f);
|
obj->rigidBody.acceleration = glm::vec3(0.f);
|
||||||
if (obj->collider.dimensions != glm::vec2(0.f)) {
|
if (obj->collider.dimensions != glm::vec3(0.f))
|
||||||
|
{
|
||||||
// check map collisions
|
// check map collisions
|
||||||
resolveWorldCollision(obj);
|
resolveWorldCollision(obj);
|
||||||
}
|
}
|
||||||
obj->rigidBody.position +=
|
obj->rigidBody.position += obj->rigidBody.velocity * static_cast<float>(deltaTime);
|
||||||
obj->rigidBody.velocity * static_cast<float>(deltaTime);
|
|
||||||
// Make sure we keep our Z at 0.f, a better choice would be to remove the
|
|
||||||
// need for vec3 all together!
|
|
||||||
// TODO: REMOVE VEC3 NO NEED FOR Z COODINATE!
|
|
||||||
// obj->rigidBody.position.z = 0.f;
|
|
||||||
}
|
}
|
||||||
getPossibleCollisions();
|
getPossibleCollisions();
|
||||||
if (!objCollisions.empty())
|
if (!objCollisions.empty())
|
||||||
|
|
|
||||||
|
|
@ -1,191 +1,204 @@
|
||||||
#include "gameplay/scene.h"
|
#include "gameplay/scene.h"
|
||||||
#include "gameplay/ai.h"
|
#include "gameplay/camera.h"
|
||||||
#include "gameplay/gameactor.h"
|
#include "gameplay/gameactor.h"
|
||||||
|
#include "gameplay/weapons/weapons.h"
|
||||||
|
#include "gameplay/weapons/bulletmanager.h"
|
||||||
#include "gameplay/map.h"
|
#include "gameplay/map.h"
|
||||||
#include "gameplay/physics.h"
|
#include "gameplay/physics.h"
|
||||||
#include "gameplay/weapons/bulletmanager.h"
|
#include "gameplay/ai.h"
|
||||||
#include "gameplay/weapons/weapons.h"
|
|
||||||
|
|
||||||
#include "graphics/animation.h"
|
|
||||||
#include "graphics/background.h"
|
|
||||||
#include "graphics/sprite.h"
|
#include "graphics/sprite.h"
|
||||||
|
#include "graphics/animation.h"
|
||||||
|
|
||||||
#include "utility/component.h"
|
#include "utility/component.h"
|
||||||
#include "utility/debugdraw.h"
|
|
||||||
#include "utility/events.h"
|
|
||||||
#include "utility/ftfont.h"
|
|
||||||
#include "utility/raycaster.h"
|
|
||||||
#include "utility/resourcemanager.h"
|
|
||||||
#include "utility/script.h"
|
|
||||||
#include "utility/xmlloader.h"
|
#include "utility/xmlloader.h"
|
||||||
|
#include "utility/resourcemanager.h"
|
||||||
|
#include "utility/events.h"
|
||||||
|
#include "utility/raycaster.h"
|
||||||
|
#include "utility/debugdraw.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <tracy/Tracy.hpp>
|
||||||
|
|
||||||
Scene::Scene(SceneType sceneType, std::shared_ptr<ResourceManager> resources,
|
#include <execution>
|
||||||
std::weak_ptr<EventManager> globalEvents)
|
|
||||||
: type(sceneType), resourceManager(resources),
|
// Scene xml files, should contain a node called <player> that holds the sprite location
|
||||||
globalEventManager(globalEvents) {
|
/*
|
||||||
|
like this:
|
||||||
|
<player sprite="sprites/player2Atlas.png" frameSize=64.0>
|
||||||
|
<x=5/>
|
||||||
|
<y=6/>
|
||||||
|
</player>
|
||||||
|
*/
|
||||||
|
|
||||||
|
Scene::Scene(SceneType sceneType, std::shared_ptr<ResourceManager> resources, std::weak_ptr<EventManager> globalEvents)
|
||||||
|
: type(sceneType), resourceManager(resources), globalEventManager(globalEvents)
|
||||||
|
{
|
||||||
|
camera = std::make_shared<Camera>(800.f, 600.f);
|
||||||
physicsEngine = std::make_shared<PhysicsEngine>();
|
physicsEngine = std::make_shared<PhysicsEngine>();
|
||||||
eventManager = std::make_shared<EventManager>();
|
eventManager = std::make_shared<EventManager>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::init() {
|
void Scene::init()
|
||||||
|
{
|
||||||
physicsEngine->hookEventManager(eventManager);
|
physicsEngine->hookEventManager(eventManager);
|
||||||
|
//if (sceneType == SCENE_SHOOTER)
|
||||||
loadDebugShooterScene();
|
loadDebugShooterScene();
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is full of hardcoded values and test sprites, NOT for use with
|
// This function is full of hardcoded values and test sprites, NOT for use with final product
|
||||||
// final product
|
void Scene::loadDebugShooterScene()
|
||||||
void Scene::loadDebugShooterScene() {
|
{
|
||||||
hookSceneEvents();
|
hookSceneEvents();
|
||||||
sceneData = resourceManager->loadScene("000");
|
sceneData = resourceManager->loadScene("000");
|
||||||
if (!sceneData)
|
if (!sceneData)
|
||||||
return;
|
return;
|
||||||
EntityData playerData = sceneData->entities[0];
|
EntityData playerData = sceneData->entities[0];
|
||||||
auto mapData = sceneData->map;
|
auto mapData = sceneData->map;
|
||||||
auto playerShader = resourceManager->loadShader(
|
auto playerShader = resourceManager->loadShader("GL_player", "shaders/GL_player.vert", "shaders/GL_player.frag");
|
||||||
"GL_player", "shaders/GL_player.vert", "shaders/GL_player.frag");
|
auto bubbleShader = resourceManager->loadShader("GL_bubble", "shaders/GL_bubble.vert", "shaders/GL_bubble.frag");
|
||||||
auto bubbleShader = resourceManager->loadShader(
|
auto weaponShader = resourceManager->loadShader("GL_pistol", "shaders/GL_pistol.vert", "shaders/GL_pistol.frag");
|
||||||
"GL_bubble", "shaders/GL_bubble.vert", "shaders/GL_bubble.frag");
|
|
||||||
auto weaponShader = resourceManager->loadShader(
|
|
||||||
"GL_pistol", "shaders/GL_pistol.vert", "shaders/GL_pistol.frag");
|
|
||||||
|
|
||||||
if (!sceneData->bgFile.empty()) {
|
|
||||||
LOG(INFO, "Found background loading '{}'", sceneData->bgFile);
|
|
||||||
background = resourceManager->loadBackground(sceneData->bgFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// creating map from scene
|
// creating map from scene
|
||||||
auto tileShader = resourceManager->loadShader(
|
auto tileShader = resourceManager->loadShader("GL_tile", "shaders/GL_tile.vert", "shaders/GL_tile.frag");
|
||||||
"GL_tile", "shaders/GL_tile.vert", "shaders/GL_tile.frag");
|
|
||||||
map = std::make_shared<Map>(mapData, tileShader, resourceManager);
|
map = std::make_shared<Map>(mapData, tileShader, resourceManager);
|
||||||
|
|
||||||
for (EntityData entityData : sceneData->entities) {
|
for (EntityData entityData : sceneData->entities)
|
||||||
|
{
|
||||||
auto entity = std::make_shared<GameActor>(this, playerShader);
|
auto entity = std::make_shared<GameActor>(this, playerShader);
|
||||||
// Directional is the kind of sprite sheet we are using, in this case for
|
// Directional is the kind of sprite sheet we are using, in this case for directional, I have the sprite sheet handle the rotations
|
||||||
// directional, I have the sprite sheet handle the rotations instead of just
|
// instead of just rotating the object, this makes it look quite a bit better from the end user perspective.
|
||||||
// rotating the object, this makes it look quite a bit better from the end
|
if (entityData.animated)
|
||||||
// user perspective.
|
{
|
||||||
if (entityData.animated) {
|
auto entityAnimation = resourceManager->loadAnimationSet(entityData.graphic, entity->getEntityID());
|
||||||
auto entityAnimation = resourceManager->loadAnimationSet(
|
// because we don't want to have the engine rotate the object based on the entities rotation,
|
||||||
entityData.graphic, entity->getEntityID());
|
// we set the this value to false so we no longer rotate the object.
|
||||||
// because we don't want to have the engine rotate the object based on the
|
|
||||||
// entities rotation, we set the this value to false so we no longer
|
|
||||||
// rotate the object.
|
|
||||||
if (entityAnimation->getDirectional())
|
if (entityAnimation->getDirectional())
|
||||||
entity->setRotatable(false);
|
entity->setRotatable(false);
|
||||||
entity->addComponent(
|
entity->addComponent(std::make_unique<AnimationComponent>(entityAnimation, eventManager));
|
||||||
std::make_unique<AnimationComponent>(entityAnimation, eventManager));
|
}
|
||||||
} else {
|
else
|
||||||
|
{
|
||||||
auto entitySprite = resourceManager->loadSpriteStatic(entityData.graphic);
|
auto entitySprite = resourceManager->loadSpriteStatic(entityData.graphic);
|
||||||
entity->addComponent(std::make_unique<SpriteComponent>(entitySprite));
|
entity->addComponent(std::make_unique<SpriteComponent>(entitySprite));
|
||||||
}
|
}
|
||||||
auto defaultWeapon =
|
auto defaultWeapon = resourceManager->loadWeapon("pistolGun", weaponShader, bubbleShader);
|
||||||
resourceManager->loadWeapon("gun/pistol", weaponShader, bubbleShader);
|
auto entityWeapon = resourceManager->loadWeapon(entityData.weapon, weaponShader, bubbleShader);
|
||||||
auto entityWeapon = resourceManager->loadWeapon(entityData.weapon,
|
|
||||||
weaponShader, bubbleShader);
|
|
||||||
|
|
||||||
entity->pickupWeapon(std::move(defaultWeapon));
|
entity->pickupWeapon(defaultWeapon);
|
||||||
entity->pickupWeapon(std::move(entityWeapon));
|
entity->pickupWeapon(entityWeapon);
|
||||||
entity->setPosition(glm::vec3(entityData.x * mapData->tileSize,
|
entity->setPosition(glm::vec3(entityData.x * mapData->tileSize, entityData.y * mapData->tileSize, 0.f));
|
||||||
entityData.y * mapData->tileSize, 0.f));
|
|
||||||
entity->setScale(glm::vec3(mapData->tileSize, mapData->tileSize, 1.f));
|
entity->setScale(glm::vec3(mapData->tileSize, mapData->tileSize, 1.f));
|
||||||
|
|
||||||
entity->addPhysicsComponent(physicsEngine->createObject(
|
entity->addPhysicsComponent(
|
||||||
entity->getEntityID(), entity->getPosition(), 49.0,
|
physicsEngine->createObject(entity->getEntityID(),
|
||||||
|
entity->getPosition(),
|
||||||
|
49.0,
|
||||||
PhysicsComponent::Collider::Shape::Circle,
|
PhysicsComponent::Collider::Shape::Circle,
|
||||||
glm::vec3(mapData->tileSize / 2)));
|
glm::vec3(mapData->tileSize / 2))
|
||||||
|
);
|
||||||
|
|
||||||
if (entityData.isPlayer) {
|
if (entityData.isPlayer)
|
||||||
|
{
|
||||||
player = entity;
|
player = entity;
|
||||||
} else {
|
camera->setTarget(entity.get());
|
||||||
|
entity->setLocalPosition(camera->worldToLocal(entity->getPosition()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// attach ai
|
// attach ai
|
||||||
if (!entityData.script.empty()) {
|
if (!entityData.script.empty())
|
||||||
auto behaviour =
|
{
|
||||||
resourceManager->loadScript<AIScript>(entityData.script);
|
auto behaviourScript = resourceManager->loadAIScript(entityData.script);
|
||||||
auto rayCaster = std::make_unique<Raycaster>(
|
auto rayCaster = std::make_shared<Raycaster>(40.f, 300.f, map->getCollisionMap(), mapData->tileSize);
|
||||||
40.f, 300.f, map->getCollisionMap(), mapData->tileSize);
|
auto ai = std::make_shared<AI>(entity, rayCaster);
|
||||||
auto ai = std::make_shared<AI>(entity.get(), std::move(rayCaster));
|
ai->setTarget(player);
|
||||||
ai->setTarget(player.get());
|
ai->attachBehaviourScript(behaviourScript);
|
||||||
if (behaviour != nullptr)
|
|
||||||
ai->attachBehaviourScript(std::move(behaviour));
|
|
||||||
entity->addComponent(std::make_unique<AIComponent>(ai));
|
entity->addComponent(std::make_unique<AIComponent>(ai));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entities.emplace(entity->getEntityID(), entity);
|
entities.emplace(entity->getEntityID(), entity);
|
||||||
SDL_Delay(1); // This is to make sure each entity gets a unique ID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
physicsEngine->loadCollisionMap(map->getCollisionMap(), mapData->tileSize);
|
physicsEngine->loadCollisionMap(map->getCollisionMap(), mapData->tileSize);
|
||||||
|
|
||||||
|
// Setup map and other entities...
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<GameActor> Scene::getPlayer() const {
|
std::shared_ptr<GameActor> Scene::getPlayer() const
|
||||||
|
{
|
||||||
return (!player) ? nullptr : player;
|
return (!player) ? nullptr : player;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::update(double deltaTime) {
|
void Scene::update(double deltaTime)
|
||||||
|
{
|
||||||
for (const auto &[id, e] : entities) {
|
ZoneScoped;
|
||||||
|
for (const auto& [id, e] : entities)
|
||||||
|
{
|
||||||
e->update(deltaTime);
|
e->update(deltaTime);
|
||||||
|
if (camera->getTarget() == e.get())
|
||||||
|
e->setLocalPosition(camera->worldToLocal(e->getPosition()));
|
||||||
}
|
}
|
||||||
physicsEngine->update(deltaTime);
|
physicsEngine->update(deltaTime);
|
||||||
|
camera->update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::render(std::shared_ptr<Renderer> renderer) {
|
void Scene::render(std::shared_ptr<Renderer> renderer)
|
||||||
|
{
|
||||||
|
ZoneScoped;
|
||||||
renderer->clear();
|
renderer->clear();
|
||||||
|
|
||||||
renderer->addDrawable(RenderLayer::Map, map.get());
|
renderer->setProjAndViewMatrix(camera->getProjectionMatrix(), camera->getViewMatrix());
|
||||||
if (background) {
|
renderer->addDrawable(RenderLayer::Map, map);
|
||||||
renderer->addDrawable(RenderLayer::Background,
|
//map->draw();
|
||||||
static_cast<Drawable *>(background));
|
for (auto& [id, e] : entities)
|
||||||
}
|
{
|
||||||
for (auto &[id, e] : entities) {
|
//e->draw();
|
||||||
renderer->addDrawable(RenderLayer::GameObjects, e.get());
|
renderer->addDrawable(RenderLayer::GameObjects, e);
|
||||||
if (e->getHeldWeapon()) {
|
if (e->getHeldWeapon()) {
|
||||||
renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon());
|
renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon());
|
||||||
const auto &weapons = e->getAllWeapons();
|
for (const auto& bullet : e->getHeldWeapon()->getBulletManager()->getBullets()) {
|
||||||
for (auto &w : weapons) {
|
renderer->addDrawable(RenderLayer::GameObjects, bullet);
|
||||||
for (auto b : w->getBulletManager()->getBullets()) {
|
|
||||||
renderer->addDrawable(RenderLayer::GameObjects, b.get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->render();
|
renderer->render();
|
||||||
DEBUG_TEXT(glm::vec3(10.f, 10.f, 0.f), glm::vec4(0.f, 0.f, 0.f, 1.f), 0.5f,
|
DebugDrawer::getInstance().draw(camera->getProjectionMatrix() * camera->getViewMatrix());
|
||||||
"{} / {}", getPlayer()->getHeldWeapon()->getMagazine(),
|
|
||||||
getPlayer()->getHeldWeapon()->getAmmo());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::unloadScene() {
|
void Scene::unloadScene()
|
||||||
// xmlLoader.reset();
|
{
|
||||||
|
//xmlLoader.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Scene::hookSceneEvents() {
|
void Scene::hookSceneEvents()
|
||||||
|
{
|
||||||
std::weak_ptr<Scene> weakSelf = shared_from_this();
|
std::weak_ptr<Scene> weakSelf = shared_from_this();
|
||||||
eventManager->subscribe<BulletCollideEvent>(
|
eventManager->subscribe("OnBulletCollide", [weakSelf](std::shared_ptr<Event> e) {
|
||||||
[weakSelf](const BulletCollideEvent &e) {
|
|
||||||
if (auto self = weakSelf.lock()) {
|
if (auto self = weakSelf.lock()) {
|
||||||
GameActor *shooter = self->getGameActorByID(e.ownerID);
|
auto collideEvent = std::static_pointer_cast<BulletCollideEvent>(e);
|
||||||
GameActor *target = self->getGameActorByID(e.victimID);
|
GameActor* shooter = self->getGameActorByID(collideEvent->ownerID);
|
||||||
|
GameActor* target = self->getGameActorByID(collideEvent->victimID);
|
||||||
if (shooter && target)
|
if (shooter && target)
|
||||||
if (auto weapon = shooter->getHeldWeapon())
|
if (auto& weapon = shooter->getHeldWeapon())
|
||||||
weapon->onHitCallback(target, e.bullet.get(), e.normal);
|
weapon->onHitCallback(target, collideEvent->bullet.get(), collideEvent->normal);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
GameActor *Scene::getGameActorByID(const unsigned int ID) {
|
GameActor* Scene::getGameActorByID(const unsigned int ID)
|
||||||
|
{
|
||||||
auto iterator = entities.find(ID);
|
auto iterator = entities.find(ID);
|
||||||
if (iterator == entities.end())
|
if (iterator == entities.end())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return iterator->second.get();
|
return iterator->second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::span<std::weak_ptr<GameActor>> Scene::getAllEntities() const {
|
std::span<std::weak_ptr<GameActor>> Scene::getAllEntities() const
|
||||||
|
{
|
||||||
entityCache.clear();
|
entityCache.clear();
|
||||||
for (const auto &[_, entity] : entities) {
|
for (const auto& [_, entity] : entities) {
|
||||||
entityCache.push_back(entity);
|
entityCache.push_back(entity);
|
||||||
}
|
}
|
||||||
return entityCache;
|
return entityCache;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
#include "gameplay/weapons/bullet.h"
|
#include "gameplay/weapons/bullet.h"
|
||||||
#include "utility/component.h"
|
#include "utility/component.h"
|
||||||
|
|
||||||
#include "utility/logger.h"
|
|
||||||
|
|
||||||
void Bullet::addComponent(Component* component)
|
void Bullet::addComponent(Component* component)
|
||||||
{
|
{
|
||||||
components.push_back(component);
|
components.push_back(component);
|
||||||
|
|
@ -14,8 +12,6 @@ void Bullet::update(double deltaTime)
|
||||||
|
|
||||||
deltaPosition.x += direction.x * bulletSpeed;
|
deltaPosition.x += direction.x * bulletSpeed;
|
||||||
deltaPosition.y += direction.y * bulletSpeed;
|
deltaPosition.y += direction.y * bulletSpeed;
|
||||||
|
|
||||||
//LOG(INFO, "( {}, {}, {} )", deltaPosition.x, deltaPosition.y, deltaPosition.z);
|
|
||||||
//physics->rigidBody.position = position;
|
//physics->rigidBody.position = position;
|
||||||
|
|
||||||
for (auto& component : components)
|
for (auto& component : components)
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include "gameplay/camera.h"
|
#include "gameplay/camera.h"
|
||||||
#include "utility/events.h"
|
#include "utility/events.h"
|
||||||
#include "utility/component.h"
|
#include "utility/component.h"
|
||||||
#include "utility/logger.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
@ -14,10 +13,11 @@ void BulletManager::hookEventManager(std::weak_ptr<EventManager> eventManager)
|
||||||
this->eventManager = eventManager;
|
this->eventManager = eventManager;
|
||||||
if (auto event = this->eventManager.lock()) {
|
if (auto event = this->eventManager.lock()) {
|
||||||
std::weak_ptr<BulletManager> weakSelf = shared_from_this();
|
std::weak_ptr<BulletManager> weakSelf = shared_from_this();
|
||||||
event->subscribe<BulletDiedEvent>([weakSelf](const BulletDiedEvent& e) {
|
event->subscribe("OnBulletDied", [weakSelf](std::shared_ptr<Event> e) {
|
||||||
if (auto self = weakSelf.lock()) {
|
if (auto self = weakSelf.lock()) {
|
||||||
|
auto bulletEvent = std::static_pointer_cast<BulletDiedEvent>(e);
|
||||||
auto iterator = std::find_if(self->bullets.begin(), self->bullets.end(), [&](std::shared_ptr<Bullet> bullet) {
|
auto iterator = std::find_if(self->bullets.begin(), self->bullets.end(), [&](std::shared_ptr<Bullet> bullet) {
|
||||||
return bullet->getPhysicsComponent() == e.physObj;
|
return bullet->getPhysicsComponent() == bulletEvent->physObj;
|
||||||
});
|
});
|
||||||
if (iterator != self->bullets.end())
|
if (iterator != self->bullets.end())
|
||||||
self->bullets.erase(iterator);
|
self->bullets.erase(iterator);
|
||||||
|
|
@ -52,11 +52,11 @@ void BulletManager::update(double deltaTime)
|
||||||
{
|
{
|
||||||
if (!bullet) continue;
|
if (!bullet) continue;
|
||||||
bullet->update(deltaTime);
|
bullet->update(deltaTime);
|
||||||
float distance = glm::distance(glm::vec3(bullet->getPhysicsComponent()->rigidBody.position, 0.f), bullet->getBulletOrigin());
|
float distance = glm::distance(bullet->getPhysicsComponent()->rigidBody.position, bullet->getBulletOrigin());
|
||||||
if (distance > bullet->getBulletDrop() || glm::length(bullet->getPhysicsComponent()->rigidBody.velocity) < 100.0f)
|
if (distance > bullet->getBulletDrop() || glm::length(bullet->getPhysicsComponent()->rigidBody.velocity) < 100.0f)
|
||||||
{
|
{
|
||||||
if (auto event = eventManager.lock())
|
if (auto event = eventManager.lock())
|
||||||
event->notify<BulletDiedEvent>((BulletDiedEvent){ bullet->getPhysicsComponent() });
|
event->notify(std::make_shared<BulletDiedEvent>(bullet->getPhysicsComponent()));
|
||||||
//bullets.erase(std::remove(bullets.begin(), bullets.end(), bullet));
|
//bullets.erase(std::remove(bullets.begin(), bullets.end(), bullet));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,47 +1,47 @@
|
||||||
#include "gameplay/weapons/weapon.h"
|
#include "gameplay/weapons/weapon.h"
|
||||||
|
#include "gameplay/weapons/bulletmanager.h"
|
||||||
|
#include "gameplay/weapons/bullet.h"
|
||||||
#include "gameplay/gameactor.h"
|
#include "gameplay/gameactor.h"
|
||||||
#include "gameplay/physics.h"
|
#include "gameplay/physics.h"
|
||||||
#include "gameplay/weapons/bullet.h"
|
|
||||||
#include "gameplay/weapons/bulletmanager.h"
|
|
||||||
#include <SDL_timer.h>
|
#include <SDL_timer.h>
|
||||||
|
|
||||||
#include "utility/component.h"
|
|
||||||
#include "utility/debugdraw.h"
|
#include "utility/debugdraw.h"
|
||||||
|
#include "utility/component.h"
|
||||||
#include "utility/events.h"
|
#include "utility/events.h"
|
||||||
#include "utility/logger.h"
|
|
||||||
#include "utility/resourcemanager.h"
|
#include "utility/resourcemanager.h"
|
||||||
#include "utility/script.h"
|
#include "utility/script.h"
|
||||||
|
#include "utility/logger.h"
|
||||||
|
|
||||||
// TODO: Regular clean up, make this mess readable!
|
// TODO: Regular clean up, make this mess readable!
|
||||||
|
|
||||||
Weapon::Weapon(const WeaponData *data, const unsigned weaponShaderID,
|
Weapon::Weapon(std::shared_ptr<WeaponData> data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager)
|
||||||
const unsigned bulletShaderID, ResourceManager *resourceManager)
|
:
|
||||||
: Entity(weaponShaderID), weaponType(data->id),
|
Entity (weaponShaderID),
|
||||||
weaponSize(glm::vec2(data->sizeX, data->sizeY)),
|
weaponSize (glm::vec2(data->sizeX, data->sizeY)),
|
||||||
weaponOffset(glm::vec2(data->offsetX, data->offsetY)),
|
weaponOffset (glm::vec2(data->offsetX, data->offsetY)),
|
||||||
weaponMag(data->clipSize), weaponMagSize(data->clipSize),
|
weaponMag (data->clipSize),
|
||||||
weaponAmmo(data->maxAmmo), bulletSpeed(data->bulletSpeed),
|
weaponMagSize (data->clipSize),
|
||||||
bulletDrop(data->bulletDrop), fireSpeed(data->fireSpeed),
|
weaponAmmo (data->maxAmmo),
|
||||||
bulletSize(glm::vec2(data->bulletSizeX, data->bulletSizeY)),
|
bulletSpeed (data->bulletSpeed),
|
||||||
bulletShaderID(bulletShaderID),
|
bulletDrop (data->bulletDrop),
|
||||||
bulletManager(std::make_shared<BulletManager>()),
|
fireSpeed (data->fireSpeed),
|
||||||
bulletSpread(std::make_unique<UTIL::RandomGenerator>(-data->bulletSpread,
|
bulletSize (glm::vec2(data->bulletSizeX, data->bulletSizeY)),
|
||||||
data->bulletSpread)),
|
bulletShaderID (bulletShaderID),
|
||||||
bulletModifer(
|
bulletManager (std::make_shared<BulletManager>()),
|
||||||
std::make_unique<UTIL::RandomGenerator>(data->modMin, data->modMax)) {
|
bulletSpread (std::make_unique<UTIL::RandomGenerator>(-data->bulletSpread, data->bulletSpread)),
|
||||||
|
bulletModifer (std::make_unique<UTIL::RandomGenerator>(data->modMin, data->modMax))
|
||||||
|
{
|
||||||
if (data->bulletAnimated)
|
if (data->bulletAnimated)
|
||||||
bulletSprite = std::make_unique<AnimationComponent>(
|
bulletSprite = std::make_unique<AnimationComponent>(resourceManager->loadAnimationSet(data->bulletGraphic, entityid));
|
||||||
resourceManager->loadAnimationSet(data->bulletGraphic, entityid));
|
|
||||||
else
|
else
|
||||||
bulletSprite = std::make_unique<SpriteComponent>(
|
bulletSprite = std::make_unique<SpriteComponent>(resourceManager->loadSpriteStatic(data->bulletGraphic));
|
||||||
resourceManager->loadSpriteStatic(data->bulletGraphic));
|
|
||||||
|
|
||||||
if (data->animated) {
|
if (data->animated)
|
||||||
addComponent(std::make_unique<AnimationComponent>(
|
{
|
||||||
resourceManager->loadAnimationSet(data->id, entityid)));
|
addComponent(std::make_unique<AnimationComponent>(resourceManager->loadAnimationSet(data->graphic, entityid)));
|
||||||
} else
|
}
|
||||||
addComponent(std::make_unique<SpriteComponent>(
|
else
|
||||||
resourceManager->loadSpriteStatic(data->graphic)));
|
addComponent(std::make_unique<SpriteComponent>(resourceManager->loadSpriteStatic(data->graphic)));
|
||||||
this->setScale(glm::vec3(weaponSize.x, weaponSize.y, 1.0f));
|
this->setScale(glm::vec3(weaponSize.x, weaponSize.y, 1.0f));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -49,71 +49,83 @@ void Weapon::addComponent(std::unique_ptr<Component> comp) {
|
||||||
components.push_back(std::move(comp));
|
components.push_back(std::move(comp));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::reload() {
|
void Weapon::reload()
|
||||||
if (auto event = eventManager.lock()) {
|
{
|
||||||
event->notify<EntityReloadEvent>(
|
// TODO: Create reload event that will be captured by the gun animation set, to start the reloading animation
|
||||||
{entityid, wielder->getPosition(), weaponType});
|
if (auto event = eventManager.lock())
|
||||||
|
{
|
||||||
|
event->notify(std::make_shared<EntityReloadEvent>(entityid));
|
||||||
reloading = true;
|
reloading = true;
|
||||||
if (weaponAmmo < weaponMagSize) {
|
if (weaponAmmo < weaponMagSize) {
|
||||||
weaponMag = weaponAmmo;
|
weaponMag = weaponAmmo;
|
||||||
weaponAmmo = 0;
|
weaponAmmo = 0;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
weaponMag = weaponMagSize;
|
weaponMag = weaponMagSize;
|
||||||
weaponAmmo -= weaponMagSize;
|
weaponAmmo -= weaponMagSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Weapon::shoot() {
|
bool Weapon::shoot()
|
||||||
|
{
|
||||||
bool shotsFired = false;
|
bool shotsFired = false;
|
||||||
if (wielder) {
|
if (wielder)
|
||||||
|
{
|
||||||
Uint32 currentTime = SDL_GetTicks();
|
Uint32 currentTime = SDL_GetTicks();
|
||||||
if (currentTime - lastFireTime >= fireSpeed && !reloading) {
|
if (currentTime - lastFireTime >= fireSpeed && !reloading)
|
||||||
if (weaponMag > 0) {
|
{
|
||||||
|
if (weaponMag > 0)
|
||||||
|
{
|
||||||
shotsFired = true;
|
shotsFired = true;
|
||||||
if (auto event = eventManager.lock())
|
if (auto event = eventManager.lock())
|
||||||
event->notify<EntityFireEvent>(
|
event->notify(std::make_shared<EntityFireEvent>(entityid, fireSpeed));
|
||||||
{entityid, fireSpeed, wielder->getPosition(), weaponType});
|
if (!weaponScript || !weaponScript->lua["onShoot"].valid())
|
||||||
if (!weaponScript || !weaponScript->lua["onShoot"].valid()) {
|
{
|
||||||
// create bullet using this generated data
|
// create bullet using this generated data
|
||||||
BulletData b = genBulletData();
|
BulletData b = genBulletData();
|
||||||
createBullet(b);
|
createBullet(b);
|
||||||
weaponMag -= 1;
|
weaponMag -= 1;
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
auto result = weaponScript->lua["onShoot"]();
|
auto result = weaponScript->lua["onShoot"]();
|
||||||
if (!result.valid()) {
|
if (!result.valid())
|
||||||
|
{
|
||||||
sol::error err = result;
|
sol::error err = result;
|
||||||
std::cerr << "lua error: " << err.what() << std::endl;
|
std::cerr << "lua error: " << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
// auto reload
|
weaponMag -= 1;
|
||||||
if ((weaponMag -= 1) <= 0)
|
|
||||||
reload();
|
|
||||||
}
|
}
|
||||||
} else if (weaponMag <= 0)
|
}
|
||||||
reload();
|
else if (weaponMag <= 0) reload();
|
||||||
lastFireTime = currentTime;
|
lastFireTime = currentTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return shotsFired;
|
return shotsFired;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::hookEventManager(std::weak_ptr<EventManager> eventManager) {
|
void Weapon::hookEventManager(std::weak_ptr<EventManager> eventManager)
|
||||||
|
{
|
||||||
this->eventManager = eventManager;
|
this->eventManager = eventManager;
|
||||||
|
|
||||||
for (auto &component : components) {
|
for (auto& component : components)
|
||||||
if (component->getType() == Component::TYPE::ANIMATION) {
|
{
|
||||||
auto animComponent = static_cast<AnimationComponent *>(component.get());
|
if (component->getType() == Component::TYPE::ANIMATION)
|
||||||
|
{
|
||||||
|
auto animComponent = static_cast<AnimationComponent*>(component.get());
|
||||||
animComponent->getAnimationSet()->attachEventManager(eventManager);
|
animComponent->getAnimationSet()->attachEventManager(eventManager);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto event = this->eventManager.lock()) {
|
if (auto event = this->eventManager.lock()) {
|
||||||
auto self = this;
|
std::weak_ptr<Weapon> selfWeak = shared_from_this();
|
||||||
event->subscribe<AnimationFinishedEvent>(
|
event->subscribe("OnAnimationFinished", [selfWeak](std::shared_ptr<Event> e) {
|
||||||
[self](const AnimationFinishedEvent &e) {
|
if (auto self = selfWeak.lock()) {
|
||||||
if (self) {
|
auto animFinished = std::static_pointer_cast<AnimationFinishedEvent>(e);
|
||||||
if (e.entityid == self->entityid && e.animType == "reload") {
|
if (animFinished->entityid == self->entityid && animFinished->animType == "reload")
|
||||||
if (self->reloading) {
|
{
|
||||||
|
if (self->reloading)
|
||||||
|
{
|
||||||
self->reloading = false;
|
self->reloading = false;
|
||||||
self->wasReloading = true;
|
self->wasReloading = true;
|
||||||
}
|
}
|
||||||
|
|
@ -125,63 +137,75 @@ void Weapon::hookEventManager(std::weak_ptr<EventManager> eventManager) {
|
||||||
bulletManager->hookEventManager(eventManager);
|
bulletManager->hookEventManager(eventManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::attachScript(std::unique_ptr<WeaponScript> script) {
|
void Weapon::attachScript(const std::shared_ptr<WeaponScript>& script)
|
||||||
weaponScript = std::move(script);
|
{
|
||||||
weaponScript->lua["weapon"] = this;
|
weaponScript = script;
|
||||||
LOG(DEBUG, "Weapon state bound", NULL);
|
weaponScript->lua["weapon"] = shared_from_this();
|
||||||
|
LOG(DEBUG, "Weapon state bound");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::onHitCallback(GameActor *target, PhysicsComponent *bullet,
|
void Weapon::onHitCallback(GameActor* target, PhysicsComponent* bullet, const glm::vec2& normal)
|
||||||
const glm::vec2 &normal) {
|
{
|
||||||
if (weaponScript && weaponScript->lua["onHit"].valid()) {
|
if (weaponScript && weaponScript->lua["onHit"].valid())
|
||||||
|
{
|
||||||
auto result = weaponScript->lua["onHit"](target, bullet, normal);
|
auto result = weaponScript->lua["onHit"](target, bullet, normal);
|
||||||
if (!result.valid()) {
|
if (!result.valid())
|
||||||
|
{
|
||||||
sol::error err = result;
|
sol::error err = result;
|
||||||
std::cerr << "lua error: " << err.what() << std::endl;
|
std::cerr << "lua error: " << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::update(double deltaTime) {
|
void Weapon::update(double deltaTime)
|
||||||
|
{
|
||||||
Entity::update(deltaTime);
|
Entity::update(deltaTime);
|
||||||
if (wielded) {
|
if (wielded)
|
||||||
|
{
|
||||||
// move the weapon into place as the wielder rotates and moves
|
// move the weapon into place as the wielder rotates and moves
|
||||||
if (wielder)
|
if (wielder)
|
||||||
adjustWeapon();
|
adjustWeapon();
|
||||||
|
|
||||||
for (auto &component : components)
|
for (auto& component : components)
|
||||||
component->update();
|
component->update();
|
||||||
if (wasReloading) {
|
if (wasReloading)
|
||||||
|
{
|
||||||
wasReloading = false;
|
wasReloading = false;
|
||||||
if (auto event = eventManager.lock()) {
|
if (auto event = eventManager.lock()) {
|
||||||
event->notify<EntityFinishReloadEvent>({entityid});
|
event->notify(std::make_shared<EntityFinishReloadEvent>(entityid));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bulletManager->update(deltaTime);
|
bulletManager->update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::draw() {
|
void Weapon::draw()
|
||||||
|
{
|
||||||
Entity::draw();
|
Entity::draw();
|
||||||
if (wielded) {
|
if (wielded)
|
||||||
for (auto &component : components) {
|
{
|
||||||
|
for (auto& component : components)
|
||||||
|
{
|
||||||
component->play();
|
component->play();
|
||||||
component->bind();
|
component->bind();
|
||||||
component->render();
|
component->render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// bulletManager->draw();
|
//bulletManager->draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::adjustWeapon() {
|
void Weapon::adjustWeapon()
|
||||||
|
{
|
||||||
float rotation = glm::radians(wielder->getRotation());
|
float rotation = glm::radians(wielder->getRotation());
|
||||||
|
|
||||||
glm::vec3 offset = glm::vec3(
|
glm::vec3 offset = glm::vec3(
|
||||||
cos(rotation) * ((wielder->getScale().x) - weaponSize.x * 0.5f),
|
cos(rotation) * ((wielder->getScale().x) - weaponSize.x * 0.5f),
|
||||||
sin(rotation) * ((wielder->getScale().y) - weaponSize.y * 0.5f), 0.0f);
|
sin(rotation) * ((wielder->getScale().y) - weaponSize.y * 0.5f),
|
||||||
|
0.0f
|
||||||
|
);
|
||||||
glm::vec3 origin = wielder->getCenter() + offset;
|
glm::vec3 origin = wielder->getCenter() + offset;
|
||||||
// origin.x += (weaponSize.x) * 0.25f;
|
//origin.x += (weaponSize.x) * 0.25f;
|
||||||
// origin.y += (weaponSize.y) * 0.25f;
|
//origin.y += (weaponSize.y) * 0.25f;
|
||||||
|
|
||||||
// Flip the texture if the weapon is facing upwards or downwards
|
// Flip the texture if the weapon is facing upwards or downwards
|
||||||
Direction d = getDirectionFromRotation(glm::degrees(rotation));
|
Direction d = getDirectionFromRotation(glm::degrees(rotation));
|
||||||
|
|
@ -197,14 +221,15 @@ void Weapon::adjustWeapon() {
|
||||||
lastDir = getDirectionFromRotation(glm::degrees(rotation));
|
lastDir = getDirectionFromRotation(glm::degrees(rotation));
|
||||||
}
|
}
|
||||||
|
|
||||||
Weapon::BulletData Weapon::genBulletData() {
|
Weapon::BulletData Weapon::genBulletData()
|
||||||
|
{
|
||||||
BulletData b;
|
BulletData b;
|
||||||
float rotation = glm::radians(wielder->getRotation());
|
float rotation = glm::radians(wielder->getRotation());
|
||||||
float spreadOffset =
|
|
||||||
glm::radians(static_cast<float>(bulletSpread->genFloat()));
|
|
||||||
b.mass = 0.1f;
|
b.mass = 0.1f;
|
||||||
glm::vec2 facing =
|
glm::vec2 facing = glm::vec2(
|
||||||
glm::vec2(cos(rotation + spreadOffset), sin(rotation + spreadOffset));
|
cos(rotation + glm::radians(static_cast<float>(bulletSpread->genFloat()))),
|
||||||
|
sin(rotation + glm::radians(static_cast<float>(bulletSpread->genFloat())))
|
||||||
|
);
|
||||||
b.direction = glm::normalize(facing);
|
b.direction = glm::normalize(facing);
|
||||||
b.sizeMod = bulletModifer->genFloat();
|
b.sizeMod = bulletModifer->genFloat();
|
||||||
b.speedMod = bulletModifer->genFloat();
|
b.speedMod = bulletModifer->genFloat();
|
||||||
|
|
@ -214,36 +239,44 @@ Weapon::BulletData Weapon::genBulletData() {
|
||||||
|
|
||||||
b.origin = glm::vec3(
|
b.origin = glm::vec3(
|
||||||
// x offset from the wielder
|
// x offset from the wielder
|
||||||
wielder->getCenter().x + cos(rotation) * radius -
|
wielder->getCenter().x + cos(rotation) * radius - sin(rotation) * weaponOffset.y,
|
||||||
sin(rotation) * weaponOffset.y,
|
|
||||||
// y offset from the wielder
|
// y offset from the wielder
|
||||||
wielder->getCenter().y + sin(rotation) * radius +
|
wielder->getCenter().y + sin(rotation) * radius + cos(rotation) * weaponOffset.y,
|
||||||
cos(rotation) * weaponOffset.y,
|
0.0f
|
||||||
0.0f);
|
);
|
||||||
b.origin.x -= ((bulletSize.x) * b.sizeMod) * 0.5f;
|
b.origin.x -= ((bulletSize.x) * b.sizeMod) * 0.5f;
|
||||||
b.origin.y -= ((bulletSize.y) * b.sizeMod) * 0.5f;
|
b.origin.y -= ((bulletSize.y) * b.sizeMod) * 0.5f;
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Weapon::createBullet(const Weapon::BulletData &data) {
|
void Weapon::createBullet(const Weapon::BulletData& data)
|
||||||
auto bullet = std::make_shared<Bullet>(wielder->getEntityID(), bulletShaderID,
|
{
|
||||||
data.origin, data.direction,
|
auto bullet = std::make_shared<Bullet>(wielder->getEntityID(), bulletShaderID, data.origin, data.direction, bulletSpeed, bulletDrop, bulletSize);
|
||||||
bulletSpeed, bulletDrop, bulletSize);
|
|
||||||
bullet->addComponent(bulletSprite.get());
|
bullet->addComponent(bulletSprite.get());
|
||||||
bullet->addPhysicsComponent(
|
bullet->addPhysicsComponent(std::make_shared<PhysicsComponent>(PhysicsComponentFactory::makeBullet(wielder->getEntityID(), data.origin, data.mass, bulletSize.x / 2)));
|
||||||
std::make_shared<PhysicsComponent>(PhysicsComponentFactory::makeBullet(
|
bullet->getPhysicsComponent()->rigidBody.velocity += bulletSpeed * glm::vec3(data.direction.x, data.direction.y, 0.f) / data.mass;
|
||||||
wielder->getEntityID(), data.origin, data.mass, bulletSize.x / 2)));
|
|
||||||
bullet->getPhysicsComponent()->rigidBody.velocity +=
|
|
||||||
bulletSpeed * data.direction / data.mass;
|
|
||||||
|
|
||||||
if (auto event = eventManager.lock())
|
if (auto event = eventManager.lock())
|
||||||
event->notify<BulletFiredEvent>({bullet});
|
event->notify(std::make_shared<BulletFiredEvent>(bullet));
|
||||||
bulletManager->addBullet(bullet);
|
bulletManager->addBullet(bullet);
|
||||||
}
|
}
|
||||||
|
|
||||||
Weapon::~Weapon() {
|
/*
|
||||||
if (weaponScript) {
|
!| SLATED FOR REMOVAL |!
|
||||||
weaponScript->lua["onShoot"] = sol::nil;
|
|
||||||
weaponScript->lua.collect_gc();
|
// Swap the reload animation and the regular weapon animation
|
||||||
|
void Weapon::swapSprites()
|
||||||
|
{
|
||||||
|
//std::swap(weaponSprites.first, weaponSprites.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Weapon::checkAndFinishReload()
|
||||||
|
{
|
||||||
|
if (weaponSprites.first->kill() && reloading) {
|
||||||
|
weaponSprites.first->idle();
|
||||||
|
weaponSprites.first->reset();
|
||||||
|
std::swap(weaponSprites.first, weaponSprites.second);
|
||||||
|
reloading = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
||||||
|
|
@ -3,19 +3,17 @@
|
||||||
#include "utility/xmlloader.h"
|
#include "utility/xmlloader.h"
|
||||||
#include "utility/resourcemanager.h"
|
#include "utility/resourcemanager.h"
|
||||||
#include "utility/events.h"
|
#include "utility/events.h"
|
||||||
#include "util.h"
|
|
||||||
|
|
||||||
Animation::Animation(const AnimationData* animData, ResourceManager* resourceManager) :
|
Animation::Animation(const std::shared_ptr<AnimationData>& animData, ResourceManager* resourceManager) :
|
||||||
|
animName(animData->name),
|
||||||
|
animType(animData->type),
|
||||||
spriteAtlas(resourceManager->loadSpriteAtlas(animData->spriteAtlas, animData->frameSize, animData->directional)),
|
spriteAtlas(resourceManager->loadSpriteAtlas(animData->spriteAtlas, animData->frameSize, animData->directional)),
|
||||||
FPS(animData->FPS),
|
FPS(animData->FPS),
|
||||||
currentFrame(0),
|
currentFrame(0),
|
||||||
cycles(0),
|
cycles(0),
|
||||||
isDirectional(animData->directional),
|
isDirectional(animData->directional),
|
||||||
isPlaying(isDirectional)
|
isPlaying(isDirectional)
|
||||||
{
|
{}
|
||||||
prefix = UTIL::parsePrefix(animData->id);
|
|
||||||
type = UTIL::get_type(animData->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Animation::bind()
|
void Animation::bind()
|
||||||
{
|
{
|
||||||
|
|
@ -76,25 +74,24 @@ void Animation::frameTick()
|
||||||
}
|
}
|
||||||
|
|
||||||
AnimationSet::AnimationSet(const int& entityid) : entityid(entityid), isDirectional(false) {};
|
AnimationSet::AnimationSet(const int& entityid) : entityid(entityid), isDirectional(false) {};
|
||||||
AnimationSet::AnimationSet(const int& entityid, ResourceManager* resourceManager, std::vector<AnimationData*> animSet) : entityid(entityid)
|
AnimationSet::AnimationSet(const int& entityid, ResourceManager* resourceManager, std::vector<std::shared_ptr<AnimationData>> animSet) : entityid(entityid)
|
||||||
{
|
{
|
||||||
curAnim = nullptr;
|
curAnim = nullptr;
|
||||||
for (const auto& anim : animSet)
|
for (const auto& anim : animSet)
|
||||||
{
|
{
|
||||||
std::string type = UTIL::get_type(anim->id);
|
anims.try_emplace(anim->type, std::make_unique<Animation>(anim, resourceManager));
|
||||||
anims.try_emplace(type, std::make_unique<Animation>(anim, resourceManager));
|
if (anim->type == "idle")
|
||||||
if (type == "idle")
|
curAnim = anims[anim->type].get();
|
||||||
curAnim = anims[type].get();
|
|
||||||
}
|
}
|
||||||
// if we don't have an idle animation, we are just gonna set the current animation to the top of the set
|
// if we don't have an idle animation, we are just gonna set the current animation to the top of the set
|
||||||
if (curAnim == nullptr)
|
if (curAnim == nullptr)
|
||||||
curAnim = anims[UTIL::get_type(animSet[0]->id)].get();
|
curAnim = anims[animSet[0]->type].get();
|
||||||
isDirectional = curAnim->getDirectional();
|
isDirectional = curAnim->getDirectional();
|
||||||
}
|
}
|
||||||
AnimationSet::AnimationSet(const int& entityid, std::unordered_map<std::string, std::unique_ptr<Animation>> animations)
|
AnimationSet::AnimationSet(const int& entityid, std::unordered_map<std::string, std::unique_ptr<Animation>> animations)
|
||||||
: entityid(entityid), anims(std::move(animations))
|
: entityid(entityid), anims(std::move(animations))
|
||||||
{
|
{
|
||||||
for (auto& [type, anim] : anims)
|
for (auto& [type, anim] : animations)
|
||||||
{
|
{
|
||||||
curAnim = anim.get();
|
curAnim = anim.get();
|
||||||
if (type == "idle")
|
if (type == "idle")
|
||||||
|
|
@ -112,18 +109,18 @@ void AnimationSet::attachEventManager(std::weak_ptr<EventManager> e)
|
||||||
if (auto event = eventManager.lock()) {
|
if (auto event = eventManager.lock()) {
|
||||||
std::weak_ptr<AnimationSet> weakSelf = shared_from_this();
|
std::weak_ptr<AnimationSet> weakSelf = shared_from_this();
|
||||||
|
|
||||||
event->subscribe<DirectionChangeEvent>([weakSelf](const DirectionChangeEvent& e) {
|
event->subscribe("OnDirectionChange", [weakSelf](std::shared_ptr<Event> e) {
|
||||||
if (auto self = weakSelf.lock()) {
|
if (auto self = weakSelf.lock()) {
|
||||||
if (e.entityid == self->entityid) {
|
auto directionEvent = std::static_pointer_cast<DirectionChangeEvent>(e);
|
||||||
Direction d = e.direction;
|
if (directionEvent->entityid == self->entityid)
|
||||||
self->setFacingDir(d);
|
self->setFacingDir(directionEvent->direction);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
event->subscribe<EntityMoveEvent>([weakSelf](const EntityMoveEvent& e) {
|
event->subscribe("OnEntityMove", [weakSelf](std::shared_ptr<Event> e) {
|
||||||
if (auto self = weakSelf.lock()) {
|
if (auto self = weakSelf.lock()) {
|
||||||
if (e.entityid == self->entityid)
|
auto moveEvent = std::static_pointer_cast<EntityMoveEvent>(e);
|
||||||
|
if (moveEvent->entityid == self->entityid)
|
||||||
{
|
{
|
||||||
if (self->isDirectional)
|
if (self->isDirectional)
|
||||||
{
|
{
|
||||||
|
|
@ -136,9 +133,10 @@ void AnimationSet::attachEventManager(std::weak_ptr<EventManager> e)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
event->subscribe<EntityStopEvent>([weakSelf](const EntityStopEvent& e) {
|
event->subscribe("OnEntityStop", [weakSelf](std::shared_ptr<Event> e) {
|
||||||
if (auto self = weakSelf.lock()) {
|
if (auto self = weakSelf.lock()) {
|
||||||
if (e.entityid == self->entityid)
|
auto stopEvent = std::static_pointer_cast<EntityStopEvent>(e);
|
||||||
|
if (stopEvent->entityid == self->entityid)
|
||||||
{
|
{
|
||||||
if (self->isDirectional)
|
if (self->isDirectional)
|
||||||
{
|
{
|
||||||
|
|
@ -151,49 +149,51 @@ void AnimationSet::attachEventManager(std::weak_ptr<EventManager> e)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
event->subscribe<EntityReloadEvent>([weakSelf](const EntityReloadEvent& e) {
|
event->subscribe("OnEntityReload", [weakSelf](std::shared_ptr<Event> e) {
|
||||||
if (auto self = weakSelf.lock()) {
|
if (auto self = weakSelf.lock()) {
|
||||||
if (e.entityid == self->entityid)
|
auto reloadEvent = std::static_pointer_cast<EntityReloadEvent>(e);
|
||||||
|
if (reloadEvent->entityid == self->entityid)
|
||||||
{
|
{
|
||||||
if (self->anims["reload"] != NULL)
|
if (self->anims["reload"] != NULL)
|
||||||
{
|
{
|
||||||
self->curAnim->reset();
|
|
||||||
self->curAnim = self->anims["reload"].get();
|
self->curAnim = self->anims["reload"].get();
|
||||||
|
self->curAnim->reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
event->subscribe<EntityFinishReloadEvent>([weakSelf](const EntityFinishReloadEvent& e) {
|
event->subscribe("OnEntityFinishReload", [weakSelf](std::shared_ptr<Event> e) {
|
||||||
if (auto self = weakSelf.lock()) {
|
if (auto self = weakSelf.lock()) {
|
||||||
if (e.entityid == self->entityid)
|
auto reloadEvent = std::static_pointer_cast<EntityFinishReloadEvent>(e);
|
||||||
|
if (reloadEvent->entityid == self->entityid)
|
||||||
{
|
{
|
||||||
if (self->anims["idle"] != NULL) {
|
if (self->anims["idle"] != NULL)
|
||||||
self->curAnim->reset();
|
|
||||||
self->curAnim = self->anims["idle"].get();
|
self->curAnim = self->anims["idle"].get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
event->subscribe<EntityFireEvent>([weakSelf](const EntityFireEvent& e) {
|
event->subscribe("OnEntityFire", [weakSelf](std::shared_ptr<Event> e) {
|
||||||
if (auto self = weakSelf.lock()) {
|
if (auto self = weakSelf.lock()) {
|
||||||
if (e.entityid == self->entityid)
|
auto fireEvent = std::static_pointer_cast<EntityFireEvent>(e);
|
||||||
|
if (fireEvent->entityid == self->entityid)
|
||||||
{
|
{
|
||||||
if (self->anims["fire"] != NULL)
|
if (self->anims["fire"] != NULL)
|
||||||
{
|
{
|
||||||
self->curAnim = self->anims["fire"].get();
|
self->curAnim = self->anims["fire"].get();
|
||||||
self->curAnim->reset();
|
self->curAnim->reset();
|
||||||
float newFPS = (1000.f / e.fireDelay) * 15.f;
|
float newFPS = (1000.f / fireEvent->fireDelay) * 15.f;
|
||||||
self->curAnim->setFPS(newFPS);
|
self->curAnim->setFPS(newFPS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
event->subscribe<AnimationFinishedEvent>([weakSelf](const AnimationFinishedEvent& e) {
|
event->subscribe("OnAnimationFinished", [weakSelf](std::shared_ptr<Event> e) {
|
||||||
if (auto self = weakSelf.lock()) {
|
if (auto self = weakSelf.lock()) {
|
||||||
if (e.entityid == self->entityid && e.animType == "fire")
|
auto animEvent = std::static_pointer_cast<AnimationFinishedEvent>(e);
|
||||||
|
if (animEvent->entityid == self->entityid && animEvent->animType == "fire")
|
||||||
{
|
{
|
||||||
if (self->anims["idle"] != NULL)
|
if (self->anims["idle"] != NULL)
|
||||||
self->curAnim = self->anims["idle"].get();
|
self->curAnim = self->anims["idle"].get();
|
||||||
|
|
@ -220,7 +220,7 @@ void AnimationSet::draw()
|
||||||
// If the animation has cycled, we send this event after every cycle
|
// If the animation has cycled, we send this event after every cycle
|
||||||
if ((curAnim->getCycles() - lastCycle) > 0) {
|
if ((curAnim->getCycles() - lastCycle) > 0) {
|
||||||
if (auto event = eventManager.lock()) {
|
if (auto event = eventManager.lock()) {
|
||||||
event->notify<AnimationFinishedEvent>({entityid, curAnim->getType()});
|
event->notify(std::make_shared<AnimationFinishedEvent>(entityid, curAnim->getType()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
#include "graphics/background.h"
|
|
||||||
|
|
||||||
Background::Background(const std::string& fileName)
|
|
||||||
{
|
|
||||||
// This will fallback to the generic shader.
|
|
||||||
shaderID = 0;
|
|
||||||
texture = new Texture();
|
|
||||||
quad = new ScreenQuad();
|
|
||||||
if (!texture->loadTexture(fileName.c_str()))
|
|
||||||
LOG(ERROR, "Failed to load background texture: '{}'", fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Background::draw()
|
|
||||||
{
|
|
||||||
texture->bind();
|
|
||||||
quad->draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
Background::~Background()
|
|
||||||
{
|
|
||||||
delete texture;
|
|
||||||
delete quad;
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
#include "graphics/glwindow.h"
|
|
||||||
#include <SDL_error.h>
|
|
||||||
#include <SDL_video.h>
|
|
||||||
|
|
||||||
bool GLWindow::Init() {
|
|
||||||
window = SDL_CreateWindow(name, SDL_WINDOWPOS_UNDEFINED,
|
|
||||||
SDL_WINDOWPOS_UNDEFINED, w, h, SDL_WINDOW_OPENGL);
|
|
||||||
if (!window) {
|
|
||||||
LOG(ERROR, "Failed to create window! {}", SDL_GetError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
glContext = SDL_GL_CreateContext(window);
|
|
||||||
if (!glContext) {
|
|
||||||
LOG(ERROR, "Failed to create opengl context! {}", SDL_GetError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLWindow::resizeWindow(size_t width, size_t height) {
|
|
||||||
w = width;
|
|
||||||
h = height;
|
|
||||||
}
|
|
||||||
|
|
||||||
GLWindow::~GLWindow() {
|
|
||||||
SDL_GL_DeleteContext(glContext);
|
|
||||||
SDL_DestroyWindow(window);
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
#include "graphics/instancedraw.h"
|
#include "graphics/instancedraw.h"
|
||||||
#include "graphics/texture.h"
|
#include "graphics/texture.h"
|
||||||
|
|
||||||
|
#include <glad/glad.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
TileTextureInstance::TileTextureInstance(const char* texturePath)
|
TileTextureInstance::TileTextureInstance(const char* texturePath)
|
||||||
{
|
{
|
||||||
texture = new Texture();
|
texture = new Texture();
|
||||||
|
|
@ -124,14 +127,3 @@ void TileTextureInstance::draw()
|
||||||
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, numOfInstances);
|
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, numOfInstances);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TileTextureInstance::~TileTextureInstance()
|
|
||||||
{
|
|
||||||
if (texture)
|
|
||||||
delete texture;
|
|
||||||
else if (textures)
|
|
||||||
delete textures;
|
|
||||||
glDeleteBuffers(1, &VBO);
|
|
||||||
glDeleteBuffers(1, &EBO);
|
|
||||||
glDeleteVertexArrays(1, &VAO);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ Postprocessor::Postprocessor(const std::shared_ptr<ResourceManager>& resourceMan
|
||||||
);
|
);
|
||||||
// TODO: ADD FALLBACK SHADER!
|
// TODO: ADD FALLBACK SHADER!
|
||||||
if (postProcessShader == nullptr) {
|
if (postProcessShader == nullptr) {
|
||||||
LOG(ERROR, "Failed to load post processing shader! 'shaders/GL_postprocess.*", NULL);
|
LOG(ERROR, "Failed to load post processing shader! 'shaders/GL_postprocess.*");
|
||||||
assert(postProcessShader != nullptr); // force crash
|
assert(postProcessShader != nullptr); // force crash
|
||||||
}
|
}
|
||||||
postProcessShader->use();
|
postProcessShader->use();
|
||||||
|
|
@ -21,9 +21,9 @@ Postprocessor::Postprocessor(const std::shared_ptr<ResourceManager>& resourceMan
|
||||||
|
|
||||||
unsigned int uboIndex = glGetUniformBlockIndex(postProcessShader->ID, "uPostProcess");
|
unsigned int uboIndex = glGetUniformBlockIndex(postProcessShader->ID, "uPostProcess");
|
||||||
if (uboIndex == GL_INVALID_INDEX) {
|
if (uboIndex == GL_INVALID_INDEX) {
|
||||||
LOG(ERROR, "Could not find 'uPostProcess'!", NULL);
|
LOG(ERROR, "Could not find 'uPostProcess'!");
|
||||||
}
|
}
|
||||||
unsigned int bindPoint = 1;
|
unsigned int bindPoint = 0;
|
||||||
glUniformBlockBinding(postProcessShader->ID, uboIndex, bindPoint);
|
glUniformBlockBinding(postProcessShader->ID, uboIndex, bindPoint);
|
||||||
|
|
||||||
glGenBuffers(1, &UBO);
|
glGenBuffers(1, &UBO);
|
||||||
|
|
@ -70,6 +70,7 @@ void Postprocessor::applyPostProcess(bool worldOrHud)
|
||||||
postProcessData.dt = curTime - lastTime;
|
postProcessData.dt = curTime - lastTime;
|
||||||
|
|
||||||
tickEffectTime(worldOrHud);
|
tickEffectTime(worldOrHud);
|
||||||
|
LOG(DEBUG, "Blur duration: {}", postProcessData.blurDuration);
|
||||||
|
|
||||||
postProcessShader->use();
|
postProcessShader->use();
|
||||||
postProcessShader->setBool("worldOrHud", worldOrHud);
|
postProcessShader->setBool("worldOrHud", worldOrHud);
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "graphics/quad.h"
|
#include "graphics/quad.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
Quad::Quad(const float* vertexData)
|
Quad::Quad(const float* vertexData)
|
||||||
{
|
{
|
||||||
std::memcpy(vertices, vertexData, sizeof(vertices));
|
std::memcpy(vertices, vertexData, sizeof(vertices));
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,47 @@
|
||||||
#include "graphics/renderer.h"
|
#include "graphics/renderer.h"
|
||||||
#include "graphics/shader.h"
|
#include "graphics/shader.h"
|
||||||
#include "utility/events.h"
|
|
||||||
#include "utility/logger.h"
|
|
||||||
#include "utility/resourcemanager.h"
|
#include "utility/resourcemanager.h"
|
||||||
|
#include "utility/logger.h"
|
||||||
|
#include "utility/events.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
#include <graphics/postprocess.h>
|
#include <graphics/postprocess.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
Renderer::Renderer(const std::shared_ptr<ResourceManager> &r,
|
Renderer::Renderer(const std::shared_ptr<ResourceManager>& r)
|
||||||
const std::shared_ptr<GLWindow> &w)
|
: resourceManager(r)
|
||||||
: resourceManager(r), glWindow(w) {
|
{
|
||||||
|
projMat = glm::mat4(0.f);
|
||||||
|
viewMat = glm::mat4(0.f);
|
||||||
|
|
||||||
initFrameBuffers();
|
initFrameBuffers();
|
||||||
initUniformBuffers();
|
|
||||||
screenQuad = std::make_unique<ScreenQuad>();
|
screenQuad = std::make_unique<ScreenQuad>();
|
||||||
postProcessor = std::make_unique<Postprocessor>(r);
|
postProcessor = std::make_unique<Postprocessor>(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::hookEventManager(std::weak_ptr<EventManager> eventManager) {
|
void Renderer::hookEventManager(std::weak_ptr<EventManager> eventManager)
|
||||||
|
{
|
||||||
if (auto e = eventManager.lock()) {
|
if (auto e = eventManager.lock()) {
|
||||||
e->subscribe<ScreenShakeEvent>([this](const ScreenShakeEvent &event) {
|
e->subscribe("OnScreenShake", [this](std::shared_ptr<Event> event) {
|
||||||
postProcessor->ApplyEffect(Postprocessor::SHAKE, event.intensity,
|
auto shakeEvent = std::dynamic_pointer_cast<ScreenShakeEvent>(event);
|
||||||
event.duration);
|
postProcessor->ApplyEffect(Postprocessor::SHAKE,
|
||||||
|
shakeEvent->intensity,
|
||||||
|
shakeEvent->duration
|
||||||
|
);
|
||||||
});
|
});
|
||||||
e->subscribe<ScreenBlurEvent>([this](const ScreenBlurEvent &event) {
|
e->subscribe("OnScreenBlur", [this](std::shared_ptr<Event> event) {
|
||||||
postProcessor->ApplyEffect(Postprocessor::BLUR, event.intensity,
|
auto blurEvent = std::dynamic_pointer_cast<ScreenBlurEvent>(event);
|
||||||
event.duration);
|
postProcessor->ApplyEffect(Postprocessor::BLUR,
|
||||||
|
blurEvent->intensity,
|
||||||
|
blurEvent->duration
|
||||||
|
);
|
||||||
});
|
});
|
||||||
e->subscribe<WindowResizeEvent>(
|
|
||||||
[this](const WindowResizeEvent &event) { resizeFrameBuffers(); });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the framebuffers used by the renderer to allow for post-processing
|
// Initialize the framebuffers used by the renderer to allow for post-processing effects
|
||||||
// effects
|
void Renderer::initFrameBuffers()
|
||||||
void Renderer::initFrameBuffers() {
|
{
|
||||||
glGenFramebuffers(1, &worldBuffer.frame);
|
glGenFramebuffers(1, &worldBuffer.frame);
|
||||||
glGenFramebuffers(1, &hudBuffer.frame);
|
glGenFramebuffers(1, &hudBuffer.frame);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, worldBuffer.frame);
|
glBindFramebuffer(GL_FRAMEBUFFER, worldBuffer.frame);
|
||||||
|
|
@ -43,20 +49,17 @@ void Renderer::initFrameBuffers() {
|
||||||
// World buffer creation
|
// World buffer creation
|
||||||
glGenTextures(1, &worldBuffer.texture);
|
glGenTextures(1, &worldBuffer.texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, worldBuffer.texture);
|
glBindTexture(GL_TEXTURE_2D, worldBuffer.texture);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glWindow->Width(), glWindow->Height(),
|
// !!! NEED TO CREATE STATIC WINDOW SIZING !!!
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
// Attaching empty texture as color buffer for framebuffer
|
//Attaching empty texture as color buffer for framebuffer
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, worldBuffer.texture, 0);
|
||||||
worldBuffer.texture, 0);
|
|
||||||
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
LOG(ERROR, "Failed to complete world framebuffer: {}",
|
LOG(ERROR, "Failed to complete world framebuffer: {}", glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
||||||
glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
|
||||||
assert(1 == 0); // force crash
|
assert(1 == 0); // force crash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -68,18 +71,15 @@ void Renderer::initFrameBuffers() {
|
||||||
|
|
||||||
glGenTextures(1, &hudBuffer.texture);
|
glGenTextures(1, &hudBuffer.texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, hudBuffer.texture);
|
glBindTexture(GL_TEXTURE_2D, hudBuffer.texture);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, glWindow->Width(), glWindow->Height(),
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 800, 600, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
||||||
0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, hudBuffer.texture, 0);
|
||||||
hudBuffer.texture, 0);
|
|
||||||
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
|
||||||
LOG(ERROR, "Failed to complete hud framebuffer: {}",
|
LOG(ERROR, "Failed to complete hud framebuffer: {}", glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
||||||
glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
|
||||||
assert(1 == 0); // force crash
|
assert(1 == 0); // force crash
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,55 +89,34 @@ void Renderer::initFrameBuffers() {
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::resizeFrameBuffers() {
|
void Renderer::setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view)
|
||||||
glDeleteFramebuffers(1, &worldBuffer.frame);
|
{
|
||||||
glDeleteFramebuffers(1, &hudBuffer.frame);
|
projMat = proj;
|
||||||
glDeleteTextures(1, &worldBuffer.texture);
|
viewMat = view;
|
||||||
glDeleteTextures(1, &hudBuffer.texture);
|
|
||||||
|
|
||||||
initFrameBuffers();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::initUniformBuffers() {
|
void Renderer::addDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable)
|
||||||
glGenBuffers(1, &uboMatrices);
|
{
|
||||||
|
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
|
|
||||||
glBufferData(GL_UNIFORM_BUFFER, 2 * sizeof(glm::mat4), NULL, GL_STATIC_DRAW);
|
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
|
||||||
|
|
||||||
glBindBufferBase(GL_UNIFORM_BUFFER, 0, uboMatrices);
|
|
||||||
// glBindBufferRange(GL_UNIFORM_BUFFER, 0, uboMatrices, 0, 2 *
|
|
||||||
// sizeof(glm::mat4));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::setProjAndViewMatrix(const glm::mat4 &proj,
|
|
||||||
const glm::mat4 &view) {
|
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, uboMatrices);
|
|
||||||
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(glm::mat4),
|
|
||||||
glm::value_ptr(proj));
|
|
||||||
glBufferSubData(GL_UNIFORM_BUFFER, sizeof(glm::mat4), sizeof(glm::mat4),
|
|
||||||
glm::value_ptr(view));
|
|
||||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Renderer::addDrawable(RenderLayer renderLayer, Drawable *drawable) {
|
|
||||||
if (renderLayer == RenderLayer::HUD || renderLayer == RenderLayer::Menu)
|
if (renderLayer == RenderLayer::HUD || renderLayer == RenderLayer::Menu)
|
||||||
HUDLayerPool[renderLayer].push_back(drawable);
|
HUDLayerPool[renderLayer].push_back(drawable);
|
||||||
else
|
else
|
||||||
worldLayerPool[renderLayer].push_back(drawable);
|
worldLayerPool[renderLayer].push_back(drawable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::removeDrawable(RenderLayer renderLayer, Drawable *drawable) {
|
void Renderer::removeDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable)
|
||||||
auto erase = [&](auto &pool) {
|
{
|
||||||
|
auto erase = [&](auto& pool) {
|
||||||
pool.erase(std::remove(pool.begin(), pool.end(), drawable), pool.end());
|
pool.erase(std::remove(pool.begin(), pool.end(), drawable), pool.end());
|
||||||
};
|
};
|
||||||
if (renderLayer == RenderLayer::HUD || renderLayer == RenderLayer::Menu) {
|
if (renderLayer == RenderLayer::HUD || renderLayer == RenderLayer::Menu) {
|
||||||
erase(HUDLayerPool[renderLayer]);
|
erase(HUDLayerPool[renderLayer]);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
erase(worldLayerPool[renderLayer]);
|
erase(worldLayerPool[renderLayer]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::render() {
|
void Renderer::render()
|
||||||
|
{
|
||||||
// Bind the world frame buffer
|
// Bind the world frame buffer
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, worldBuffer.frame);
|
glBindFramebuffer(GL_FRAMEBUFFER, worldBuffer.frame);
|
||||||
// clear color and depth buffer
|
// clear color and depth buffer
|
||||||
|
|
@ -157,20 +136,29 @@ void Renderer::render() {
|
||||||
screenQuad->draw();
|
screenQuad->draw();
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, hudBuffer.texture);
|
glBindTexture(GL_TEXTURE_2D, hudBuffer.texture);
|
||||||
// postProcessor->applyPostProcess(1);
|
postProcessor->applyPostProcess(1);
|
||||||
screenQuad->draw();
|
screenQuad->draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::renderPool(auto &layerPool) {
|
void Renderer::renderPool(auto& layerPool)
|
||||||
|
{
|
||||||
sortLayerPool(layerPool);
|
sortLayerPool(layerPool);
|
||||||
Shader *curShader = nullptr;
|
Shader* curShader = nullptr;
|
||||||
for (const auto &layer : renderingOrder) {
|
for (const auto& layer : renderingOrder) {
|
||||||
unsigned curShaderID = static_cast<unsigned>(-1);
|
unsigned curShaderID = static_cast<unsigned>(-1);
|
||||||
for (const auto &item : layerPool[layer]) {
|
for (const auto& item : layerPool[layer]) {
|
||||||
if (item->getShaderID() != curShaderID) {
|
if (item->getShaderID() != curShaderID) {
|
||||||
curShaderID = item->getShaderID();
|
curShaderID = item->getShaderID();
|
||||||
curShader = resourceManager->getShaderByID(curShaderID);
|
curShader = resourceManager->getShaderByID(curShaderID);
|
||||||
|
|
||||||
|
if (curShader) {
|
||||||
curShader->use();
|
curShader->use();
|
||||||
|
curShader->setMatrix4f("projection", glm::value_ptr(projMat));
|
||||||
|
curShader->setMatrix4f("view", glm::value_ptr(viewMat));
|
||||||
|
} else {
|
||||||
|
LOG(ERROR, "Shader with ID {} not found!", curShaderID);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (!item->getOneShotUniforms().empty()) {
|
if (!item->getOneShotUniforms().empty()) {
|
||||||
uploadUniforms(curShaderID, item->getOneShotUniforms());
|
uploadUniforms(curShaderID, item->getOneShotUniforms());
|
||||||
|
|
@ -184,43 +172,46 @@ void Renderer::renderPool(auto &layerPool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::clear() {
|
void Renderer::clear()
|
||||||
|
{
|
||||||
worldLayerPool.clear();
|
worldLayerPool.clear();
|
||||||
HUDLayerPool.clear();
|
HUDLayerPool.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::uploadUniforms(const unsigned shaderID,
|
void Renderer::uploadUniforms(const unsigned shaderID, const std::vector<Uniform>& uniforms)
|
||||||
const std::vector<Uniform> &uniforms) {
|
{
|
||||||
Shader *shader = resourceManager->getShaderByID(shaderID);
|
Shader *shader = resourceManager->getShaderByID(shaderID);
|
||||||
if (shader == nullptr) {
|
if (shader == nullptr) {
|
||||||
LOG(ERROR, "No shader found with id {} !", shaderID);
|
LOG(ERROR, "No shader found with id {} !", shaderID);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const auto &uniform : uniforms) {
|
for (const auto& uniform : uniforms) {
|
||||||
std::visit(
|
std::visit([&](auto&& arg) {
|
||||||
[&](auto &&arg) {
|
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
if constexpr (std::is_same_v<T, bool>) {
|
if constexpr (std::is_same_v<T, bool>) {
|
||||||
shader->setBool(uniform.name, arg);
|
shader->setBool(uniform.name, arg);
|
||||||
} else if constexpr (std::is_same_v<T, int>) {
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, int>) {
|
||||||
shader->setInt(uniform.name, arg);
|
shader->setInt(uniform.name, arg);
|
||||||
} else if constexpr (std::is_same_v<T, float>) {
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, float>) {
|
||||||
shader->setFloat(uniform.name, arg);
|
shader->setFloat(uniform.name, arg);
|
||||||
} else if constexpr (std::is_same_v<T, glm::vec2>) {
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, glm::vec2>) {
|
||||||
shader->setVec2(uniform.name, glm::value_ptr(arg));
|
shader->setVec2(uniform.name, glm::value_ptr(arg));
|
||||||
} else if constexpr (std::is_same_v<T, glm::mat4>) {
|
}
|
||||||
|
else if constexpr (std::is_same_v<T, glm::mat4>) {
|
||||||
shader->setMatrix4f(uniform.name, glm::value_ptr(arg));
|
shader->setMatrix4f(uniform.name, glm::value_ptr(arg));
|
||||||
}
|
}
|
||||||
},
|
}, uniform.value);
|
||||||
uniform.value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void Renderer::sortLayerPool(auto &layerPool) {
|
void Renderer::sortLayerPool(auto& layerPool)
|
||||||
// Sort by shader id, this works to batch shaders together to avoid shader
|
{
|
||||||
// switching too much
|
// Sort by shader id, this works to batch shaders together to avoid shader switching too much
|
||||||
for (auto &[_, pool] : layerPool) {
|
for (auto& [_,pool] : layerPool) {
|
||||||
std::sort(pool.begin(), pool.end(),
|
std::sort(pool.begin(), pool.end(),
|
||||||
[](const Drawable *a, const Drawable *b) {
|
[](const std::shared_ptr<Drawable>& a, const std::shared_ptr<Drawable>& b) {
|
||||||
return a->getShaderID() < b->getShaderID();
|
return a->getShaderID() < b->getShaderID();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,37 +3,7 @@
|
||||||
#include "utility/logger.h"
|
#include "utility/logger.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
// Load a generic fallback shader
|
Shader::Shader(const char* vertexPath, const char* fragmentPath)
|
||||||
Shader::Shader()
|
|
||||||
{
|
|
||||||
std::string vertexSource = {
|
|
||||||
// generic vertex shader program
|
|
||||||
"#version 330 core\n"
|
|
||||||
"layout (location = 0) in vec3 aPos;\n"
|
|
||||||
"layout (location = 1) in vec2 aTexCoord;\n"
|
|
||||||
"out vec2 texCoord;\n"
|
|
||||||
"void main()\n"
|
|
||||||
"{\n"
|
|
||||||
" texCoord = aTexCoord;\n"
|
|
||||||
" gl_Position = vec4(aPos, 1.0);\n"
|
|
||||||
"}\0"
|
|
||||||
};
|
|
||||||
std::string fragmentSource = {
|
|
||||||
// generic fragment shader program
|
|
||||||
"#version 330 core\n"
|
|
||||||
"in vec2 texCoord;\n"
|
|
||||||
"out vec4 FragColor;\n"
|
|
||||||
"uniform sampler2D sprite;\n"
|
|
||||||
"void main()\n"
|
|
||||||
"{\n"
|
|
||||||
" FragColor = texture(sprite, texCoord);\n"
|
|
||||||
"}\0"
|
|
||||||
};
|
|
||||||
compileAndLink(vertexSource.c_str(), fragmentSource.c_str());
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Shader::Shader(const char* vertPath, const char* fragPath) : vertexPath(vertPath), fragmentPath(fragPath)
|
|
||||||
{
|
{
|
||||||
std::string vertexSource;
|
std::string vertexSource;
|
||||||
std::string fragmentSource;
|
std::string fragmentSource;
|
||||||
|
|
@ -65,15 +35,7 @@ Shader::Shader(const char* vertPath, const char* fragPath) : vertexPath(vertPath
|
||||||
}
|
}
|
||||||
const char* vSource = vertexSource.c_str();
|
const char* vSource = vertexSource.c_str();
|
||||||
const char* fSource = fragmentSource.c_str();
|
const char* fSource = fragmentSource.c_str();
|
||||||
if (!compileAndLink(vertexSource.c_str(), fragmentSource.c_str())) {
|
|
||||||
LOG(ERROR, "Failed to compile and/or link shader! Check error details for more information.\nUsing fallback shader!", NULL);
|
|
||||||
valid = false;
|
|
||||||
}
|
|
||||||
valid = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Shader::compileAndLink(const char *vSource, const char *fSource)
|
|
||||||
{
|
|
||||||
unsigned int vertexid, fragmentid;
|
unsigned int vertexid, fragmentid;
|
||||||
char infoLog[512];
|
char infoLog[512];
|
||||||
int success;
|
int success;
|
||||||
|
|
@ -88,7 +50,6 @@ bool Shader::compileAndLink(const char *vSource, const char *fSource)
|
||||||
{
|
{
|
||||||
glGetShaderInfoLog(vertexid, 512, NULL, infoLog);
|
glGetShaderInfoLog(vertexid, 512, NULL, infoLog);
|
||||||
LOG(ERROR, "VERTEX SHADER '{}' COMPILE ERROR\n{}", vertexPath, infoLog);
|
LOG(ERROR, "VERTEX SHADER '{}' COMPILE ERROR\n{}", vertexPath, infoLog);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//compile fragment shader
|
//compile fragment shader
|
||||||
|
|
@ -101,7 +62,6 @@ bool Shader::compileAndLink(const char *vSource, const char *fSource)
|
||||||
{
|
{
|
||||||
glGetShaderInfoLog(fragmentid, 512, NULL, infoLog);
|
glGetShaderInfoLog(fragmentid, 512, NULL, infoLog);
|
||||||
LOG(ERROR, "FRAGMENT SHADER '{}' COMPILE ERROR\n{}", fragmentPath, infoLog);
|
LOG(ERROR, "FRAGMENT SHADER '{}' COMPILE ERROR\n{}", fragmentPath, infoLog);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//create and link program with compiled shaders
|
//create and link program with compiled shaders
|
||||||
|
|
@ -115,14 +75,10 @@ bool Shader::compileAndLink(const char *vSource, const char *fSource)
|
||||||
{
|
{
|
||||||
glGetProgramInfoLog(ID, 512, NULL, infoLog);
|
glGetProgramInfoLog(ID, 512, NULL, infoLog);
|
||||||
LOG(ERROR, "PROGRAM LINKER ERROR\n{}", infoLog);
|
LOG(ERROR, "PROGRAM LINKER ERROR\n{}", infoLog);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
glDeleteShader(vertexid);
|
glDeleteShader(vertexid);
|
||||||
glDeleteShader(fragmentid);
|
glDeleteShader(fragmentid);
|
||||||
|
|
||||||
glUniformBlockBinding(ID, glGetUniformBlockIndex(ID, "Matrices"), 0);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shader::setFloat(const std::string& name, float value)
|
void Shader::setFloat(const std::string& name, float value)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
#include "graphics/sprite.h"
|
#include "graphics/sprite.h"
|
||||||
#include "graphics/texture.h"
|
#include "graphics/texture.h"
|
||||||
#include "graphics/quad.h"
|
#include "graphics/quad.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "utility/events.h"
|
||||||
|
|
||||||
bool Sprite::loaded() const { return (texture != nullptr); }
|
bool Sprite::loaded() const { return (texture != nullptr); }
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,16 @@
|
||||||
#include "graphics/texture.h"
|
#include "graphics/texture.h"
|
||||||
#include "util.h"
|
|
||||||
#include "utility/logger.h"
|
#include "utility/logger.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
bool Texture::loadTexture(const char *imagePath) {
|
#include <SDL_image.h>
|
||||||
SDL_Surface *buffer = IMG_Load(imagePath);
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
bool Texture::loadTexture(const char* imagePath)
|
||||||
|
{
|
||||||
|
SDL_Surface* buffer = IMG_Load(imagePath);
|
||||||
if (!buffer)
|
if (!buffer)
|
||||||
ERROR_LOG("Failed to load image file: {}", imagePath);
|
ERROR_LOG("Failed to load image file: {}", imagePath);
|
||||||
// UTIL::flip_surface(buffer);
|
//UTIL::flip_surface(buffer);
|
||||||
|
|
||||||
glGenTextures(1, &ID);
|
glGenTextures(1, &ID);
|
||||||
/*
|
/*
|
||||||
|
|
@ -18,13 +22,12 @@ bool Texture::loadTexture(const char *imagePath) {
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, ID);
|
glBindTexture(GL_TEXTURE_2D, ID);
|
||||||
|
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, buffer->w, buffer->h, 0, GL_RGBA,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, buffer->w, buffer->h, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer->pixels);
|
||||||
GL_UNSIGNED_BYTE, buffer->pixels);
|
|
||||||
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
glGenerateMipmap(ID);
|
glGenerateMipmap(ID);
|
||||||
|
|
||||||
textureWidth = buffer->w;
|
textureWidth = buffer->w;
|
||||||
|
|
@ -35,43 +38,62 @@ bool Texture::loadTexture(const char *imagePath) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::bind() {
|
void Texture::bind()
|
||||||
|
{
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D, ID);
|
glBindTexture(GL_TEXTURE_2D, ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture::~Texture() { glDeleteTextures(1, &ID); }
|
|
||||||
|
|
||||||
bool TextureArray::loadTextures(std::vector<const char *> imagePaths) {
|
Texture::~Texture()
|
||||||
std::vector<SDL_Surface *> surfaces;
|
{
|
||||||
|
glDeleteTextures(1, &ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TextureArray::loadTextures(std::vector<const char*> imagePaths)
|
||||||
|
{
|
||||||
|
std::vector<SDL_Surface*> surfaces;
|
||||||
surfaces.resize(imagePaths.size());
|
surfaces.resize(imagePaths.size());
|
||||||
// Fill surfaces vector
|
// Fill surfaces vector
|
||||||
for (int i = 0; i < imagePaths.size(); ++i) {
|
for (int i = 0; i < imagePaths.size(); ++i)
|
||||||
|
{
|
||||||
surfaces[i] = IMG_Load(imagePaths[i]);
|
surfaces[i] = IMG_Load(imagePaths[i]);
|
||||||
if (!surfaces[i])
|
if (!surfaces[i])
|
||||||
ERROR_LOG("Failed to load image file: {}", imagePaths[i]);
|
ERROR_LOG("Failed to load image file: {}", imagePaths[i]);
|
||||||
}
|
}
|
||||||
if (!adjustCanvasSizes(surfaces))
|
if (!adjustCanvasSizes(surfaces))
|
||||||
ERROR_LOG(
|
ERROR_LOG("Failed to adjust canvas size of images! \n Make sure to check that every tileset has square dimensions! (512x512, 756x756 ... etc)");
|
||||||
"Failed to adjust canvas size of images! \n Make sure to check that "
|
|
||||||
"every tileset has square dimensions! (512x512, 756x756 ... etc)",
|
|
||||||
NULL);
|
|
||||||
if (surfaces.empty())
|
if (surfaces.empty())
|
||||||
ERROR_LOG("No surfaces created!", NULL);
|
ERROR_LOG("No surfaces created!");
|
||||||
numOfLayers = imagePaths.size();
|
numOfLayers = imagePaths.size();
|
||||||
|
|
||||||
glGenTextures(1, &ID);
|
glGenTextures(1, &ID);
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, ID);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, ID);
|
||||||
|
|
||||||
// Creating the texture array all of our textures will live in.
|
// Creating the texture array all of our textures will live in.
|
||||||
// adjustCanvasSizes makes every image the same size, so we can just use the
|
// adjustCanvasSizes makes every image the same size, so we can just use the first
|
||||||
// first surface in the list of surfaces
|
// surface in the list of surfaces
|
||||||
glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, surfaces[0]->w, surfaces[0]->h,
|
glTexImage3D(GL_TEXTURE_2D_ARRAY,
|
||||||
(GLsizei)numOfLayers, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
0,
|
||||||
|
GL_RGBA,
|
||||||
|
surfaces[0]->w,
|
||||||
|
surfaces[0]->h,
|
||||||
|
(GLsizei)numOfLayers,
|
||||||
|
0,
|
||||||
|
GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
for (int layer = 0; layer < numOfLayers; ++layer) {
|
for (int layer = 0; layer < numOfLayers; ++layer)
|
||||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, layer, surfaces[layer]->w,
|
{
|
||||||
surfaces[layer]->h, 1, GL_RGBA, GL_UNSIGNED_BYTE,
|
glTexSubImage3D(GL_TEXTURE_2D_ARRAY,
|
||||||
|
0,
|
||||||
|
0, 0, layer,
|
||||||
|
surfaces[layer]->w,
|
||||||
|
surfaces[layer]->h,
|
||||||
|
1,
|
||||||
|
GL_RGBA,
|
||||||
|
GL_UNSIGNED_BYTE,
|
||||||
surfaces[layer]->pixels);
|
surfaces[layer]->pixels);
|
||||||
}
|
}
|
||||||
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
|
|
@ -81,36 +103,40 @@ bool TextureArray::loadTextures(std::vector<const char *> imagePaths) {
|
||||||
|
|
||||||
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||||
|
|
||||||
for (auto &surface : surfaces)
|
for (auto& surface : surfaces)
|
||||||
SDL_FreeSurface(surface);
|
SDL_FreeSurface(surface);
|
||||||
surfaces.clear();
|
surfaces.clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureArray::bind() {
|
void TextureArray::bind()
|
||||||
|
{
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_2D_ARRAY, ID);
|
glBindTexture(GL_TEXTURE_2D_ARRAY, ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextureArray::adjustCanvasSizes(std::vector<SDL_Surface *> &surfaces) {
|
bool TextureArray::adjustCanvasSizes(std::vector<SDL_Surface*>& surfaces)
|
||||||
|
{
|
||||||
int maxWidth = 0;
|
int maxWidth = 0;
|
||||||
int maxHeight = 0;
|
int maxHeight = 0;
|
||||||
for (auto &surface : surfaces) {
|
for (auto& surface : surfaces)
|
||||||
|
{
|
||||||
if (surface->w != surface->h)
|
if (surface->w != surface->h)
|
||||||
ERROR_LOG("Image must be a square!", NULL);
|
ERROR_LOG("Image must be a square!");
|
||||||
|
|
||||||
if (surface->w > maxWidth)
|
if (surface->w > maxWidth) maxWidth = surface->w;
|
||||||
maxWidth = surface->w;
|
if (surface->h > maxHeight) maxHeight = surface->h;
|
||||||
if (surface->h > maxHeight)
|
textures.push_back(new TextureData({ surface->w, surface->h }));
|
||||||
maxHeight = surface->h;
|
|
||||||
textures.push_back(TextureData({surface->w, surface->h}));
|
|
||||||
}
|
}
|
||||||
for (int i = 0; i < surfaces.size(); ++i) {
|
for (int i = 0; i < surfaces.size(); ++i)
|
||||||
SDL_Surface *canvas = SDL_CreateRGBSurface(
|
{
|
||||||
0, maxWidth, maxHeight, surfaces[i]->format->BitsPerPixel,
|
SDL_Surface* canvas = SDL_CreateRGBSurface(0, maxWidth, maxHeight,
|
||||||
surfaces[i]->format->Rmask, surfaces[i]->format->Gmask,
|
surfaces[i]->format->BitsPerPixel,
|
||||||
surfaces[i]->format->Bmask, surfaces[i]->format->Amask);
|
surfaces[i]->format->Rmask,
|
||||||
|
surfaces[i]->format->Gmask,
|
||||||
|
surfaces[i]->format->Bmask,
|
||||||
|
surfaces[i]->format->Amask);
|
||||||
|
|
||||||
SDL_FillRect(canvas, NULL, SDL_MapRGBA(canvas->format, 0, 0, 0, 0));
|
SDL_FillRect(canvas, NULL, SDL_MapRGBA(canvas->format, 0, 0, 0, 0));
|
||||||
|
|
||||||
|
|
@ -126,4 +152,7 @@ bool TextureArray::adjustCanvasSizes(std::vector<SDL_Surface *> &surfaces) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureArray::~TextureArray() { glDeleteTextures(1, &ID); }
|
TextureArray::~TextureArray()
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &ID);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
#include <SDL.h>
|
#include <SDL.h>
|
||||||
#include <SDL_events.h>
|
|
||||||
#include <SDL_image.h>
|
#include <SDL_image.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <tracy/Tracy.hpp>
|
||||||
|
|
||||||
|
// TODO: Fix circular dependency issues, mostly with input.h needing gameactor.h and command.h
|
||||||
#include "gameplay/game.h"
|
#include "gameplay/game.h"
|
||||||
#include "utility/logger.h"
|
|
||||||
|
const float vertices[] = {
|
||||||
|
0.0f, 0.5f, 0.0f,
|
||||||
|
-0.5f, -0.5f, 0.0f,
|
||||||
|
0.5f, -0.5f, 0.0f
|
||||||
|
};
|
||||||
|
|
||||||
int main(int argc, char* args[])
|
int main(int argc, char* args[])
|
||||||
{
|
{
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||||
LOG(ERROR, "Failed to initialize SDL!", NULL);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
if (IMG_Init(IMG_INIT_PNG) < 0)
|
||||||
if (IMG_Init(IMG_INIT_PNG) < 0) {
|
|
||||||
LOG(ERROR, "Could not initialize png library", NULL);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
|
||||||
|
|
@ -25,13 +27,13 @@ int main(int argc, char* args[])
|
||||||
Game* game = new Game();
|
Game* game = new Game();
|
||||||
if (!game->init())
|
if (!game->init())
|
||||||
{
|
{
|
||||||
LOG(ERROR, "Failed to init game!", NULL);
|
std::cout << "Failed to init game!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!game->loadDebugScene())
|
if (!game->loadDebugScene())
|
||||||
{
|
{
|
||||||
LOG(ERROR, "Failed to load debug scene!", NULL);
|
std::cout << "Failed to load debug scene!" << std::endl;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -43,21 +45,19 @@ int main(int argc, char* args[])
|
||||||
Uint64 curCounter = SDL_GetPerformanceCounter();
|
Uint64 curCounter = SDL_GetPerformanceCounter();
|
||||||
double deltaTime = ((curCounter - lastCounter) / freq);
|
double deltaTime = ((curCounter - lastCounter) / freq);
|
||||||
deltaTime = (deltaTime < 1.0) ? deltaTime : 1.0;
|
deltaTime = (deltaTime < 1.0) ? deltaTime : 1.0;
|
||||||
while (SDL_PollEvent(&e)) {
|
SDL_PollEvent(&e);
|
||||||
if (e.type == SDL_QUIT)
|
if (e.type == SDL_QUIT)
|
||||||
game->quit();
|
game->quit();
|
||||||
|
|
||||||
game->captureInput(e);
|
game->handleInput(e);
|
||||||
}
|
|
||||||
game->executeInputs();
|
game->update(deltaTime);
|
||||||
|
|
||||||
game->render();
|
game->render();
|
||||||
game->update(deltaTime);
|
|
||||||
lastCounter = curCounter;
|
lastCounter = curCounter;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete game;
|
|
||||||
IMG_Quit();
|
IMG_Quit();
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,200 +0,0 @@
|
||||||
#include "sound/audiostream.h"
|
|
||||||
|
|
||||||
AudioStream::AudioStream()
|
|
||||||
{
|
|
||||||
alGenBuffers(4, buffers);
|
|
||||||
alGenSources(1, &source);
|
|
||||||
data = (short *)std::malloc(UTIL::AUDIO::CHUNK_SIZE * sizeof(short) * 2); // Make space for stereo even if we are playing mono
|
|
||||||
stopThread = false;
|
|
||||||
eof = true;
|
|
||||||
paused = true;
|
|
||||||
streamThread = std::thread(&AudioStream::stream, this);
|
|
||||||
//streamThread.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string AudioStream::CurStreamName()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
return songNames.front();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AudioStream::PlayStream()
|
|
||||||
{
|
|
||||||
if (CurStreamName().empty()) {
|
|
||||||
LOG(WARN, "Song queue empty!", NULL);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
LOG(INFO, "Current song is: {}", CurStreamName());
|
|
||||||
return (paused = true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioStream::AddToQueue(std::string songName)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
LOG(INFO, "Adding song {} to queue", songName);
|
|
||||||
songNames.push(songName);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AudioStream::openFile(std::string fileName)
|
|
||||||
{
|
|
||||||
int error = 0;
|
|
||||||
file = stb_vorbis_open_filename(CurStreamName().c_str(), &error, NULL);
|
|
||||||
if (file == nullptr || error != STBVorbisError::VORBIS__no_error) {
|
|
||||||
LOG(ERROR, "Failed to open file: '{}' error code: {}", CurStreamName(), error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
info = stb_vorbis_get_info(file);
|
|
||||||
if (info.sample_rate != UTIL::AUDIO::SAMPLE_RATE) {
|
|
||||||
LOG(ERROR, "Failed to open file: '{}', make sure to convert sample rate to 44100!", CurStreamName());
|
|
||||||
stb_vorbis_close(file);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
stb_vorbis_seek_start(file);
|
|
||||||
std::free(data);
|
|
||||||
data = (short *)std::malloc(UTIL::AUDIO::CHUNK_SIZE * sizeof(short) * info.channels);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AudioStream::loadChunk(ALuint buffer)
|
|
||||||
{
|
|
||||||
int sample = 0;
|
|
||||||
if (file == NULL) {
|
|
||||||
return sample;
|
|
||||||
}
|
|
||||||
if (info.channels == 0) {
|
|
||||||
return sample;
|
|
||||||
}
|
|
||||||
sample = stb_vorbis_get_samples_short_interleaved(file, info.channels, data, UTIL::AUDIO::CHUNK_SIZE);
|
|
||||||
if (sample == 0)
|
|
||||||
return sample;
|
|
||||||
format = info.channels == 1 ? AL_FORMAT_MONO16 : AL_FORMAT_STEREO16;
|
|
||||||
//LOG(INFO, "Buffer id {}, Format {}, data size {}, sample rate {},\nfilename {}",
|
|
||||||
// buffer, format == AL_FORMAT_MONO16 ? "MONO" : "STEREO", sample * info.channels * sizeof(short), info.sample_rate, songNames.front());
|
|
||||||
alBufferData(buffer, format, data, sample * info.channels * sizeof(short), info.sample_rate);
|
|
||||||
|
|
||||||
return sample;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AudioStream::loadInitalChunk()
|
|
||||||
{
|
|
||||||
int samples = 0;
|
|
||||||
if (!openFile(CurStreamName())) {
|
|
||||||
return samples;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
samples = loadChunk(buffers[i]);
|
|
||||||
if (samples == 0) {
|
|
||||||
LOG(ERROR, "Music file {} too small!", CurStreamName());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AudioStream::loadNextChunk()
|
|
||||||
{
|
|
||||||
int samples = loadChunk(buffers[last_buffer]);
|
|
||||||
return samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioStream::popQueue()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
if (songNames.empty())
|
|
||||||
return;
|
|
||||||
songNames.pop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioStream::cycleQueue()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
|
||||||
LOG(INFO, "Cycling queue", NULL);
|
|
||||||
if (songNames.empty())
|
|
||||||
return;
|
|
||||||
std::string buffer = songNames.front();
|
|
||||||
songNames.pop();
|
|
||||||
songNames.push(buffer);
|
|
||||||
LOG(INFO, "New front: {}", songNames.front());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioStream::stream()
|
|
||||||
{
|
|
||||||
int processed = 0;
|
|
||||||
int queued = 0;
|
|
||||||
bool inital = true;
|
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
|
||||||
|
|
||||||
//LOG(INFO, "Call from in audio thread!", NULL);
|
|
||||||
//LOG(INFO, "Top of queue is: {}", CurStreamName());
|
|
||||||
paused = false;
|
|
||||||
|
|
||||||
while (!stopThread) {
|
|
||||||
if (songNames.empty() || paused) {
|
|
||||||
LOG(INFO, "Paused or queue empty", NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
|
||||||
if (inital) {
|
|
||||||
int samples = loadInitalChunk();
|
|
||||||
if (samples == 0) {
|
|
||||||
LOG(ERROR, "Music file '{}' either failed to load or not big enough!", CurStreamName());
|
|
||||||
popQueue();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
alSourceQueueBuffers(source, 4, buffers);
|
|
||||||
alSourcePlay(source);
|
|
||||||
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
|
||||||
inital = false;
|
|
||||||
eof = false;
|
|
||||||
}
|
|
||||||
// If we are at the end of file, the and stream queue has a song in it
|
|
||||||
// Load in the inital buffers
|
|
||||||
if (state != AL_PLAYING) {
|
|
||||||
alSourcePlay(source);
|
|
||||||
}
|
|
||||||
while (state == AL_PLAYING && !stopThread) {
|
|
||||||
if (paused) {
|
|
||||||
alSourcePause(source);
|
|
||||||
}
|
|
||||||
alGetSourcei(source, AL_SOURCE_STATE, &state);
|
|
||||||
alGetSourcei(source, AL_BUFFERS_PROCESSED, &processed);
|
|
||||||
alGetSourcei(source, AL_BUFFERS_QUEUED, &queued);
|
|
||||||
|
|
||||||
while (processed != 0 && !stopThread) {
|
|
||||||
ALuint unqueued;
|
|
||||||
alSourceUnqueueBuffers(source, 1, &unqueued);
|
|
||||||
for (int i = 0; i < 4; ++i)
|
|
||||||
if (unqueued == buffers[i])
|
|
||||||
last_buffer = i;
|
|
||||||
int samples = loadNextChunk();
|
|
||||||
if (samples == 0) {
|
|
||||||
LOG(INFO, "Hit the end of the song!", NULL);
|
|
||||||
cycleQueue();
|
|
||||||
stb_vorbis_close(file);
|
|
||||||
while (!openFile(CurStreamName())) {
|
|
||||||
LOG(ERROR, "Failed to open next in stream! {}", CurStreamName());
|
|
||||||
popQueue();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
//LOG(INFO, "Buffer index: {}", last_buffer);
|
|
||||||
alSourceQueueBuffers(source, 1, &buffers[last_buffer]);
|
|
||||||
//last_buffer = (last_buffer + 1) % 4;
|
|
||||||
processed--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioStream::~AudioStream()
|
|
||||||
{
|
|
||||||
stopThread = true;
|
|
||||||
if (streamThread.joinable())
|
|
||||||
streamThread.join();
|
|
||||||
stb_vorbis_close(file);
|
|
||||||
std::free(data);
|
|
||||||
alSourcei(source, AL_BUFFER, 0);
|
|
||||||
alDeleteSources(1, &source);
|
|
||||||
alDeleteBuffers(4, buffers);
|
|
||||||
}
|
|
||||||
|
|
@ -1,92 +0,0 @@
|
||||||
#include "sound/engine.h"
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <AL/alc.h>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
|
|
||||||
AudioEngine::AudioEngine(std::weak_ptr<ResourceManager> _resource)
|
|
||||||
{
|
|
||||||
// Open the default device for now
|
|
||||||
if ((device = alcOpenDevice(NULL)) == NULL) {
|
|
||||||
LOG(ERROR, "Failed to open default device {}", alGetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
context = alcCreateContext(device, NULL);
|
|
||||||
alcMakeContextCurrent(context);
|
|
||||||
musicPlayer = std::make_unique<AudioStream>();
|
|
||||||
soundManager = std::make_unique<SoundManager>();
|
|
||||||
resourceManager = _resource;
|
|
||||||
alGetError();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEngine::hookEventManager(std::weak_ptr<EventManager> _events)
|
|
||||||
{
|
|
||||||
globalEventManager = _events;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEngine::hookSceneManager(std::weak_ptr<EventManager> _events)
|
|
||||||
{
|
|
||||||
sceneEventManager = _events;
|
|
||||||
if (auto weak = sceneEventManager.lock()) {
|
|
||||||
std::weak_ptr<AudioEngine> weakSelf = shared_from_this();
|
|
||||||
auto play_sound = [weakSelf](const std::string& id, int priority, const std::optional<glm::vec3>& pos = std::nullopt) {
|
|
||||||
if (auto self = weakSelf.lock()) {
|
|
||||||
if (auto res = self->resourceManager.lock()) {
|
|
||||||
auto buf = res->loadSoundEffect(id);
|
|
||||||
if (buf != 0) {
|
|
||||||
if (pos != std::nullopt)
|
|
||||||
self->soundManager->playSound(buf, priority, pos.value());
|
|
||||||
else
|
|
||||||
self->soundManager->playSound(buf, priority);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
weak->subscribe<EntityFireEvent>([weakSelf,play_sound](const EntityFireEvent& e){
|
|
||||||
play_sound(e.weaponType + "/shoot", 10, e.firePosition);
|
|
||||||
});
|
|
||||||
weak->subscribe<EntityReloadEvent>([weakSelf,play_sound](const EntityReloadEvent& e) {
|
|
||||||
play_sound(e.weaponType + "/reload", 9, e.position);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEngine::poll()
|
|
||||||
{
|
|
||||||
soundManager->pollSources();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEngine::updateListener(const glm::vec3& pos)
|
|
||||||
{
|
|
||||||
alListenerfv(AL_POSITION, glm::value_ptr(pos));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEngine::pushMusic(std::string _songName)
|
|
||||||
{
|
|
||||||
LOG(INFO, "Loading song {}", _songName);
|
|
||||||
musicPlayer->AddToQueue(_songName);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEngine::playMusic()
|
|
||||||
{
|
|
||||||
LOG(INFO, "Playing stream", NULL);
|
|
||||||
musicPlayer->PlayStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEngine::pauseMusic()
|
|
||||||
{
|
|
||||||
musicPlayer->PauseStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AudioEngine::killMusic()
|
|
||||||
{
|
|
||||||
musicPlayer->kill();
|
|
||||||
}
|
|
||||||
|
|
||||||
AudioEngine::~AudioEngine()
|
|
||||||
{
|
|
||||||
musicPlayer->kill();
|
|
||||||
alcMakeContextCurrent(NULL);
|
|
||||||
alcDestroyContext(context);
|
|
||||||
alcCloseDevice(device);
|
|
||||||
}
|
|
||||||
|
|
@ -1,32 +0,0 @@
|
||||||
#include "sound/soundeffect.h"
|
|
||||||
#include "util.h"
|
|
||||||
#include <AL/al.h>
|
|
||||||
|
|
||||||
SoundEffect::SoundEffect(const std::string& filename)
|
|
||||||
{
|
|
||||||
valid = loadFile(filename);
|
|
||||||
}
|
|
||||||
|
|
||||||
// load the whole file into a buffer, this should only be used for small sound effects. Never with music or sounds exceeding 10MB!
|
|
||||||
bool SoundEffect::loadFile(const std::string& filename)
|
|
||||||
{
|
|
||||||
short *data;
|
|
||||||
//std::unique_ptr<short[]> data((short*)new short[UTIL::AUDIO::CHUNK_SIZE * sizeof(short) * 2]());
|
|
||||||
//std::vector<short> data(UTIL::AUDIO::CHUNK_SIZE * sizeof(short) * 2);
|
|
||||||
int channels, sample_rate, samples;
|
|
||||||
|
|
||||||
samples = stb_vorbis_decode_filename(filename.c_str(), &channels, &sample_rate, &data);
|
|
||||||
if (samples == 0) {
|
|
||||||
LOG(ERROR, "Failed to load sound effect '{}'", filename);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
alGenBuffers(1, &buffer);
|
|
||||||
alBufferData(buffer, channels == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_MONO16, data, samples * channels * sizeof(short), sample_rate);
|
|
||||||
std::free(data);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundEffect::~SoundEffect()
|
|
||||||
{
|
|
||||||
alDeleteBuffers(1, &buffer);
|
|
||||||
}
|
|
||||||
|
|
@ -1,108 +0,0 @@
|
||||||
#include "sound/soundmanager.h"
|
|
||||||
#include <AL/al.h>
|
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
|
||||||
|
|
||||||
SoundManager::SoundManager()
|
|
||||||
{
|
|
||||||
for (auto& s : sources) {
|
|
||||||
alGenSources(1, &s.source);
|
|
||||||
s.inUse = false;
|
|
||||||
s.priority = 0;
|
|
||||||
alSourcef(s.source, AL_REFERENCE_DISTANCE, 1.0f);
|
|
||||||
alSourcef(s.source, AL_MAX_DISTANCE, 10000.f);
|
|
||||||
alSourcef(s.source, AL_ROLLOFF_FACTOR, 0.3f);
|
|
||||||
}
|
|
||||||
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoundManager::playSound(ALuint buffer, int priority, const glm::vec3& pos)
|
|
||||||
{
|
|
||||||
std::size_t ring = lastUsed;
|
|
||||||
AudioSource* nextBest = nullptr;
|
|
||||||
std::size_t secIndex = 0;
|
|
||||||
auto nextIndex = [](std::size_t i){ return (i + 1) % 10; };
|
|
||||||
|
|
||||||
if (!sources[ring].inUse) {
|
|
||||||
sources[ring].inUse = true;
|
|
||||||
sources[ring].priority = priority;
|
|
||||||
sources[ring].buffer = buffer;
|
|
||||||
alSourcei(sources[ring].source, AL_BUFFER, buffer);
|
|
||||||
if (pos != glm::vec3(0)) {
|
|
||||||
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 1);
|
|
||||||
alSourcefv(sources[ring].source, AL_POSITION, glm::value_ptr(pos));
|
|
||||||
} else {
|
|
||||||
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 0);
|
|
||||||
}
|
|
||||||
alSourcePlay(sources[ring].source);
|
|
||||||
lastUsed = nextIndex(lastUsed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (ring = nextIndex(lastUsed); ring != lastUsed; ring = nextIndex(ring)) {
|
|
||||||
if (!sources[ring].inUse) {
|
|
||||||
sources[ring].inUse = true;
|
|
||||||
sources[ring].priority = priority;
|
|
||||||
sources[ring].buffer = buffer;
|
|
||||||
alSourcei(sources[ring].source, AL_BUFFER, buffer);
|
|
||||||
if (pos != glm::vec3(0)) {
|
|
||||||
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 1);
|
|
||||||
alSourcefv(sources[ring].source, AL_POSITION, glm::value_ptr(pos));
|
|
||||||
} else {
|
|
||||||
//alSourcei(sources[ring].source, AL_SOURCE_RELATIVE, 0);
|
|
||||||
}
|
|
||||||
alSourcePlay(sources[ring].source);
|
|
||||||
lastUsed = nextIndex(ring);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sources[ring].priority > priority || (sources[ring].buffer != buffer && sources[ring].priority == priority)) {
|
|
||||||
if (nextBest) {
|
|
||||||
if (nextBest->priority >= sources[ring].priority) {
|
|
||||||
nextBest = &sources[ring];
|
|
||||||
secIndex = ring;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
nextBest = &sources[ring];
|
|
||||||
secIndex = ring;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (nextBest) {
|
|
||||||
nextBest->priority = priority;
|
|
||||||
alSourcei(nextBest->source, AL_BUFFER, 0);
|
|
||||||
alSourcei(nextBest->source, AL_BUFFER, buffer);
|
|
||||||
nextBest->buffer = buffer;
|
|
||||||
if (pos != glm::vec3(0)) {
|
|
||||||
//alSourcei(nextBest->source, AL_SOURCE_RELATIVE, 1);
|
|
||||||
alSourcefv(nextBest->source, AL_POSITION, glm::value_ptr(pos));
|
|
||||||
} else {
|
|
||||||
//alSourcei(nextBest->source, AL_SOURCE_RELATIVE, 0);
|
|
||||||
}
|
|
||||||
alSourcePlay(nextBest->source);
|
|
||||||
lastUsed = secIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SoundManager::pollSources()
|
|
||||||
{
|
|
||||||
for (auto& s : sources) {
|
|
||||||
if (s.inUse) {
|
|
||||||
ALint processed, state;
|
|
||||||
alGetSourcei(s.source, AL_BUFFERS_PROCESSED, &processed);
|
|
||||||
alGetSourcei(s.source, AL_SOURCE_STATE, &state);
|
|
||||||
if (state == AL_STOPPED) {
|
|
||||||
s.inUse = false;
|
|
||||||
s.buffer = 0;
|
|
||||||
alSourcei(s.source, AL_BUFFER, 0);
|
|
||||||
}
|
|
||||||
//else if (state != AL_PLAYING)
|
|
||||||
// alSourcePlay(s.source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundManager::~SoundManager()
|
|
||||||
{
|
|
||||||
for (auto& s : sources) {
|
|
||||||
alSourcei(s.source, AL_BUFFER, 0);
|
|
||||||
alDeleteSources(1, &s.source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1140
YuppleMayham/src/thirdparty/glad.c
vendored
1140
YuppleMayham/src/thirdparty/glad.c
vendored
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue