Compare commits

..

5 commits

71 changed files with 1887 additions and 268 deletions

36
.vscode/launch.json vendored Normal file
View file

@ -0,0 +1,36 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) Launch",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/out/build/x64-debug/YuppleMayham/YuppleMayham.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/out/build/x64-debug/YuppleMayham/",
"environment": [],
"console": "externalTerminal"
},
{
"name": "(gdb) Attach",
"type": "cppdbg",
"request": "attach",
"program": "${workspaceFolder}/YuppleMayham.exe",
"MIMode": "gdb",
"miDebuggerPath": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Set Disassembly Flavor to Intel",
"text": "-gdb-set disassembly-flavor intel",
"ignoreFailures": true
}
]
},
]
}

5
.vscode/settings.json vendored Normal file
View file

@ -0,0 +1,5 @@
{
"files.associations": {
"memory": "cpp"
}
}

28
.vscode/tasks.json vendored Normal file
View file

@ -0,0 +1,28 @@
{
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: cl.exe build active file",
"command": "cl.exe",
"args": [
"/Zi",
"/EHsc",
"/nologo",
"/Fe${fileDirname}\\${fileBasenameNoExtension}.exe",
"${file}"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$msCompile"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}

View file

@ -1,7 +1,7 @@
# CMakeList.txt : Top-level CMake project file, do global configuration # CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here. # and include sub-projects here.
# #
cmake_minimum_required (VERSION 3.8) cmake_minimum_required (VERSION 3.11)
# Enable Hot Reload for MSVC compilers if supported. # Enable Hot Reload for MSVC compilers if supported.
if (POLICY CMP0141) if (POLICY CMP0141)
@ -9,6 +9,22 @@ if (POLICY CMP0141)
set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>") set(CMAKE_MSVC_DEBUG_INFORMATION_FORMAT "$<IF:$<AND:$<C_COMPILER_ID:MSVC>,$<CXX_COMPILER_ID:MSVC>>,$<$<CONFIG:Debug,RelWithDebInfo>:EditAndContinue>,$<$<CONFIG:Debug,RelWithDebInfo>:ProgramDatabase>>")
endif() endif()
include(FetchContent)
SET(TRACY_ENABLE 1)
SET(TRACY_ON_DEMAND 1)
SET(TRACY_ONLY_LOCALHOST 1)
FetchContent_Declare(
tracy
GIT_REPOSITORY https://github.com/wolfpld/tracy.git
GIT_TAG v0.11.1
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
)
FetchContent_MakeAvailable(tracy)
project ("YuppleMayham") project ("YuppleMayham")
# Include sub-projects. # Include sub-projects.

View file

@ -1,4 +1,4 @@
{ {
"version": 3, "version": 3,
"configurePresets": [ "configurePresets": [
{ {
@ -97,5 +97,13 @@
} }
} }
} }
],
"buildPresets": [
{
"name": "x64-release",
"description": "",
"displayName": "",
"configurePreset": "x64-release"
}
] ]
} }

View file

@ -0,0 +1,14 @@
<animations>
<animation name="shot_gun_idle_anim" type="idle">
<FPS>4</FPS>
<sprite path="sprites/shotGunIdle128.png" frameSize="128.0"/>
</animation>
<animation name="shot_gun_fire_anim" type="fire">
<FPS>8</FPS>
<sprite path="sprites/shotGunFire128.png" frameSize="128.0"/>
</animation>
<animation name="shot_gun_reload_anim" type="reload">
<FPS>8</FPS>
<sprite path="sprites/shotGunReload128.png" frameSize="128.0"/>
</animation>
</animations>

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

View file

@ -1,20 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="64" tileheight="64" infinite="0" nextlayerid="4" nextobjectid="20"> <map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="62" tileheight="62" infinite="0" nextlayerid="5" nextobjectid="20">
<tileset firstgid="1" source="tilesets/shooterWorldOne.tsx"/> <tileset firstgid="1" source="tilesets/shooterWorldOne.tsx"/>
<tileset firstgid="65" source="tilesets/wOne.tsx"/>
<layer id="2" name="Tile Layer 2" width="30" height="20"> <layer id="2" name="Tile Layer 2" width="30" height="20">
<data encoding="csv"> <data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,28,28,29,25,28,28,29,27,31,28,28,31,28,32,26,29,30,27,25,27,32,28,31,26,29,25,29,32,0, 0,28,28,29,25,28,28,29,27,31,28,28,31,28,32,26,29,30,27,25,27,32,28,31,26,29,25,29,32,0,
0,32,27,22,16,16,23,31,26,30,31,31,29,28,30,25,28,26,26,25,29,26,25,32,28,28,31,32,25,0, 0,32,27,22,16,16,23,31,26,30,31,31,29,28,30,25,28,26,26,25,29,26,25,32,28,28,31,32,25,0,
0,30,24,11,4,8,14,26,28,31,26,24,16,16,16,16,23,27,25,25,30,26,29,29,30,29,25,29,27,0, 0,30,24,11,4,8,14,26,28,31,26,24,16,16,16,16,23,27,25,25,30,26,29,29,30,29,25,29,27,0,
0,25,15,6,1,2,14,28,32,30,24,11,8,7,3,8,12,23,28,27,25,32,30,32,30,28,27,27,26,0, 0,25,15,6,1,2,14,28,32,30,24,11,0,0,0,8,12,23,28,27,25,32,30,32,30,28,27,27,26,0,
0,28,20,13,13,13,19,32,28,29,15,5,2,5,3,5,2,14,25,32,31,32,24,16,16,16,23,29,27,0, 0,28,20,13,13,13,19,32,28,29,15,0,0,0,0,0,0,14,25,32,91,32,24,16,16,16,23,29,27,0,
0,31,29,31,27,26,27,30,29,27,15,8,7,5,2,3,6,14,27,32,32,29,15,8,4,2,14,26,27,0, 0,31,29,31,27,26,27,30,29,27,0,0,0,0,0,0,0,0,27,32,32,29,15,8,4,2,14,26,27,0,
0,30,30,30,25,32,29,31,30,29,20,10,1,3,5,3,9,19,27,25,29,31,20,13,13,13,19,31,26,0, 0,30,30,30,25,32,29,30,27,28,32,32,30,0,0,0,0,0,27,25,29,31,20,13,13,13,19,31,26,0,
0,28,30,30,28,24,23,27,31,28,29,20,13,13,13,13,19,27,31,28,27,26,29,26,32,25,31,25,32,0, 0,28,30,30,28,31,26,29,31,29,26,20,31,0,0,0,0,31,31,28,27,26,29,26,32,25,31,25,32,0,
0,26,26,31,29,20,19,30,25,29,25,25,25,28,30,27,28,25,31,30,27,26,26,28,25,29,25,32,31,0, 0,26,26,31,29,20,29,31,25,32,28,25,25,28,30,27,28,25,31,30,27,26,26,28,25,29,25,32,31,0,
0,30,32,29,29,32,31,27,25,31,31,31,26,30,31,27,29,25,29,32,0,0,0,0,30,26,31,0,0,0, 0,30,32,29,29,32,31,28,25,31,31,31,26,30,31,27,29,25,29,32,0,0,0,0,30,26,31,0,0,0,
0,30,27,31,31,28,25,25,28,26,30,27,26,28,30,29,30,25,30,32,0,0,0,0,0,0,0,0,0,0, 0,30,27,31,31,28,25,32,28,26,30,27,26,28,30,29,30,25,30,32,0,0,0,0,0,0,0,0,0,0,
0,27,29,22,21,30,29,29,32,0,0,0,0,32,30,30,31,32,26,28,0,0,0,0,0,0,0,0,0,0, 0,27,29,22,21,30,29,29,32,0,0,0,0,32,30,30,31,32,26,28,0,0,0,0,0,0,0,0,0,0,
0,27,25,18,17,30,28,30,0,0,0,0,0,26,31,26,25,30,27,29,26,0,0,0,0,0,0,0,0,0, 0,27,25,18,17,30,28,30,0,0,0,0,0,26,31,26,25,30,27,29,26,0,0,0,0,0,0,0,0,0,
0,32,30,31,30,30,28,0,0,0,0,0,0,32,27,31,30,28,26,31,26,0,0,0,0,0,0,0,0,0, 0,32,30,31,30,30,28,0,0,0,0,0,0,32,27,31,30,28,26,31,26,0,0,0,0,0,0,0,0,0,
@ -43,20 +44,44 @@
<object id="18" gid="57" x="126" y="894" width="64" height="64"/> <object id="18" gid="57" x="126" y="894" width="64" height="64"/>
<object id="19" gid="58" x="1536" y="260" width="64" height="64"/> <object id="19" gid="58" x="1536" y="260" width="64" height="64"/>
</objectgroup> </objectgroup>
<layer id="4" name="Tile Layer 3" width="30" height="20">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,176,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,56,156,155,156,157,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="1" name="Tile Layer 1" width="30" height="20"> <layer id="1" name="Tile Layer 1" width="30" height="20">
<data encoding="csv"> <data encoding="csv">
35,36,34,35,33,38,38,34,35,34,34,39,38,39,35,39,38,37,39,39,33,33,38,34,34,34,33,37,34,40, 35,36,34,35,33,38,38,34,35,34,34,39,38,39,35,39,38,37,39,39,33,33,38,34,34,34,33,37,34,40,
37,41,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,42,34, 37,41,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,45,42,34,
38,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,33, 38,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,33,
36,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,39, 36,46,0,0,0,0,0,0,0,0,0,31,32,27,31,30,29,0,0,0,0,0,0,0,0,0,0,0,47,39,
37,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,36, 37,46,0,0,0,0,0,0,0,0,25,25,28,27,25,27,32,27,0,126,127,128,0,0,0,0,0,0,47,36,
35,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,34, 35,46,0,176,149,150,150,144,0,0,30,28,31,30,32,29,31,32,0,117,141,131,0,0,0,0,0,0,47,34,
37,46,0,28,28,30,25,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,39, 37,46,0,177,182,181,180,169,0,0,27,29,28,30,27,26,26,30,0,124,125,132,0,0,0,0,0,0,47,39,
34,46,0,30,30,29,25,25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,34, 34,46,0,153,180,146,156,175,149,164,176,149,144,25,27,25,31,32,0,0,0,0,0,0,0,0,0,0,47,34,
40,46,0,29,26,31,29,26,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,47,35, 40,46,0,151,180,167,164,177,161,145,177,166,145,27,25,31,32,0,0,0,0,0,0,0,0,0,0,0,47,35,
33,46,0,30,31,32,27,27,0,0,0,0,0,0,0,0,0,0,0,56,48,48,48,48,55,0,56,48,43,33, 33,46,0,153,180,181,145,151,180,167,165,159,169,0,0,0,0,0,0,56,48,48,48,48,55,0,56,48,43,33,
35,46,0,25,30,32,31,28,0,0,0,0,0,0,0,0,0,0,0,47,34,36,34,39,44,48,43,34,36,40, 35,46,0,151,152,146,147,177,166,161,180,161,169,0,0,0,0,0,0,47,34,36,34,39,44,48,43,34,36,40,
40,46,0,0,0,0,0,0,56,48,48,48,48,55,0,0,0,0,0,47,36,36,34,39,38,36,36,38,36,37, 40,46,0,154,155,157,0,178,155,48,48,48,48,55,0,0,0,0,0,47,36,36,34,39,38,36,36,38,36,37,
35,46,0,0,0,0,0,56,43,36,38,38,39,46,0,0,0,0,0,47,40,39,38,36,38,40,40,34,38,37, 35,46,0,0,0,0,0,56,43,36,38,38,39,46,0,0,0,0,0,47,40,39,38,36,38,40,40,34,38,37,
38,46,0,0,0,0,56,43,37,39,36,36,33,46,0,0,0,0,0,0,42,39,35,36,33,34,33,38,40,39, 38,46,0,0,0,0,56,43,37,39,36,36,33,46,0,0,0,0,0,0,42,39,35,36,33,34,33,38,40,39,
34,46,0,0,0,0,47,35,34,40,39,38,36,46,0,0,0,0,0,0,47,38,36,34,34,33,36,40,35,40, 34,46,0,0,0,0,47,35,34,40,39,38,36,46,0,0,0,0,0,0,47,38,36,34,34,33,36,40,35,40,

100
Resources/maps/newmap.tmx Normal file
View file

@ -0,0 +1,100 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.11.0" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="62" tileheight="62" infinite="0" nextlayerid="5" nextobjectid="1">
<tileset firstgid="1" source="tilesets/wOne.tsx"/>
<layer id="2" name="Tile Layer 2" width="30" height="20">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,34,31,31,30,70,72,30,34,29,34,73,33,29,71,72,30,33,31,71,29,70,34,0,0,0,0,0,0,0,
0,31,29,54,33,27,29,32,31,28,29,71,54,72,27,71,71,31,33,70,70,73,31,0,0,0,0,0,0,0,
0,72,70,34,73,31,0,0,30,31,33,32,29,34,70,71,33,27,32,30,31,30,29,0,0,0,0,0,0,0,
0,27,28,31,29,0,0,0,0,34,32,30,28,32,31,27,34,31,54,33,27,27,29,0,0,0,0,0,0,0,
0,54,27,54,28,0,0,0,0,54,31,72,71,34,27,72,70,29,71,73,30,30,71,70,0,0,0,0,0,0,
0,32,27,29,54,70,0,0,71,32,54,70,71,72,34,70,54,70,32,34,72,33,72,32,34,0,0,0,0,0,
0,70,27,54,34,31,27,33,31,28,31,33,54,71,29,33,73,28,34,34,34,71,32,33,30,73,0,0,0,0,
0,29,71,27,31,34,30,71,70,32,72,54,29,31,29,29,54,28,73,33,72,30,30,31,72,31,32,0,0,0,
0,34,72,29,72,29,71,34,31,33,27,70,70,29,71,27,33,28,34,73,54,72,70,73,71,31,54,0,0,0,
0,31,73,27,27,33,34,29,54,73,54,54,70,73,30,73,73,54,34,30,54,34,30,29,34,70,54,0,0,0,
0,28,72,28,28,33,33,29,31,32,30,27,73,27,31,34,73,54,31,32,28,34,70,73,72,33,28,0,0,0,
0,0,73,34,54,32,33,34,33,54,30,29,70,72,73,70,70,54,29,29,34,27,70,71,72,28,70,0,0,0,
0,0,0,29,30,32,27,32,31,28,73,27,72,28,73,71,31,28,71,30,28,34,72,73,54,27,32,0,0,0,
0,0,0,32,27,31,33,33,27,27,30,31,71,28,29,32,31,27,34,34,31,32,27,30,72,54,31,0,0,0,
0,0,0,0,0,34,32,31,29,70,33,32,0,34,34,33,72,70,70,28,30,70,29,30,30,30,34,0,0,0,
0,0,0,0,0,0,0,28,30,27,73,0,0,0,0,70,28,30,34,54,33,32,34,54,27,71,28,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,54,32,32,27,31,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="3" name="Tile Layer 3" width="30" height="20">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,14,16,16,49,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,50,51,22,20,43,44,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,21,20,38,38,19,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,21,1,3,19,22,45,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,40,37,6,2,39,46,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,36,41,41,42,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="4" name="Tile Layer 4" width="30" height="20">
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,77,0,0,0,77,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,75,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="1" name="Tile Layer 1" width="30" height="20">
<data encoding="csv">
88,94,102,97,116,102,96,102,117,88,116,116,118,118,117,95,117,96,115,116,115,116,115,115,97,116,115,116,96,102,
88,106,91,92,92,91,91,92,92,92,91,92,92,91,91,92,92,92,92,91,91,92,108,116,115,97,117,94,94,115,
95,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,113,88,118,95,117,116,116,95,
118,105,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,88,116,94,96,95,102,102,
88,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,113,115,95,115,94,115,88,118,
94,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,108,96,96,88,116,97,102,
117,105,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,108,117,115,117,94,95,
116,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,108,118,95,118,118,
88,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,108,102,115,94,
118,105,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,97,118,117,
115,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,115,88,95,
97,103,100,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,116,96,88,
97,116,103,80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,95,96,96,
88,96,97,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,97,102,88,
118,94,115,103,86,100,0,0,0,0,0,112,86,100,0,0,0,0,0,0,0,0,0,0,0,0,89,88,117,118,
95,97,96,97,118,103,85,100,0,0,112,101,88,103,86,100,0,0,0,0,0,0,0,0,0,0,87,102,94,88,
115,94,97,115,115,96,96,103,86,86,101,94,96,116,96,103,85,86,100,0,0,0,0,84,85,86,101,97,116,97,
95,88,116,96,115,116,97,97,96,115,97,117,115,102,102,97,115,118,103,85,86,85,86,101,94,115,97,118,117,115,
102,116,118,88,102,97,102,102,88,97,117,116,88,102,95,94,117,97,117,116,88,96,116,94,115,96,94,97,115,117,
88,95,96,115,94,97,117,116,96,94,94,94,116,96,88,102,97,115,94,94,117,97,116,88,88,88,96,118,118,116
</data>
</layer>
</map>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.11.0" name="worldOne" class="shooter" tilewidth="64" tileheight="64" tilecount="64" columns="8"> <tileset version="1.10" tiledversion="1.11.0" name="worldOne" class="shooter" tilewidth="62" tileheight="62" spacing="2" tilecount="64" columns="8">
<grid orientation="orthogonal" width="64" height="64"/>
<image source="shooterWorldOneAtlas64.png" width="512" height="512"/> <image source="shooterWorldOneAtlas64.png" width="512" height="512"/>
<tile id="0" type="grass"> <tile id="0" type="grass">
<properties> <properties>

View file

@ -0,0 +1,570 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.11.0" name="wOne" class="shooter" tilewidth="62" tileheight="62" spacing="2" tilecount="484" columns="11">
<grid orientation="orthogonal" width="30" height="30"/>
<image source="worldOne.png" width="704" height="704"/>
<tile id="0" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="1" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="2" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="3" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="4" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="5" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="6" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="7" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="8" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="9" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="10" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="11" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="12" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="13" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="14" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="15" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="16" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="17" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="18" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="19" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="20" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="21" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="22" type="grass"/>
<tile id="23" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="24" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="25" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="26" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="27" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="28" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="29" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="30" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="31" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="32" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="33" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="34" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="35" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="36" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="37" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="38" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="39" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="40" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="41" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="42" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="43" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="44" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="45" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="46" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="47" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="48" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="49" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="50" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="51" type="grass">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="52" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="53" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="54" type="dirt"/>
<tile id="55" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="56" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="57" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="58" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="59" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="60" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="61" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="62" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="63" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="64" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="65" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="66" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="67" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="68" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="69" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="70" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="71" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="72" type="dirt">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="73" type="bush"/>
<tile id="74" type="bush"/>
<tile id="75" type="bush"/>
<tile id="76" type="bush"/>
<tile id="77" type="bush"/>
<tile id="78" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="79" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="80" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="81" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="82" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="83" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="84" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="85" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="86" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="87" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="88" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="89" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="90" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="91" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="92" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="93" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="94" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="95" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="96" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="97" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="98" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="99" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="100" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="101" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="102" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="103" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="104" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="105" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="106" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="107" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="108" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="109" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="110" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="111" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="112" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="113" type="water">
<properties>
<property name="walkable" type="bool" value="true"/>
</properties>
</tile>
<tile id="114" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="115" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="116" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="117" type="water">
<properties>
<property name="walkable" type="bool" value="false"/>
</properties>
</tile>
<tile id="118" type="water"/>
<tile id="119" type="water"/>
<tile id="120" type="water"/>
</tileset>

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,6 +1,13 @@
{ {
"activeFile": "", "Map/SizeTest": {
"height": 4300,
"width": 2
},
"activeFile": "debugmap.tmx",
"expandedProjectPaths": [ "expandedProjectPaths": [
"tilesets",
"C:/Users/Ethan/source/repos/YuppleMayham/Resources",
"."
], ],
"fileStates": { "fileStates": {
"": { "": {
@ -22,33 +29,76 @@
"scaleInEditor": 1 "scaleInEditor": 1
}, },
"debugmap.tmx": { "debugmap.tmx": {
"scale": 0.45125, "scale": 0.75,
"selectedLayer": 0, "selectedLayer": 2,
"viewCenter": { "viewCenter": {
"x": 959.5567867036011, "x": 989.3333333333334,
"y": 955.1246537396123 "y": 665.3333333333334
}
},
"newmap.tmx": {
"scale": 0.5,
"selectedLayer": 1,
"viewCenter": {
"x": 930,
"y": 621
} }
}, },
"shooterWorldOneAtlas.tsx": { "shooterWorldOneAtlas.tsx": {
"scaleInDock": 0.5, "scaleInDock": 0.5,
"scaleInEditor": 1 "scaleInEditor": 1
}, },
"tilesets/shooterWorldOne.tsx": {
"scaleInDock": 0.5,
"scaleInEditor": 1
},
"tilesets/shooterWorldOneAtlas.tsx": { "tilesets/shooterWorldOneAtlas.tsx": {
"scaleInDock": 0.5, "scaleInDock": 0.5,
"scaleInEditor": 1 "scaleInEditor": 1
},
"tilesets/wOne.tsx": {
"scaleInDock": 0.33,
"scaleInEditor": 1
},
"tilesets/was.tsx": {
"scaleInDock": 1,
"scaleInEditor": 1
},
"tilesets/wsa.tsx": {
"dynamicWrapping": false,
"scaleInDock": 0.5,
"scaleInEditor": 1
} }
}, },
"last.externalTilesetPath": "C:/Users/Ethan/source/repos/YuppleMayham/Resources/maps/tilesets", "last.externalTilesetPath": "C:/Users/Ethan/source/repos/YuppleMayham/Resources/maps/tilesets",
"last.imagePath": "C:/Users/Ethan/source/repos/YuppleMayham/Resources/maps/tilesets", "last.imagePath": "C:/Users/Ethan/source/repos/YuppleMayham/Resources/maps/tilesets",
"map.lastUsedFormat": "tmx",
"openFiles": [ "openFiles": [
"debugmap.tmx",
"tilesets/shooterWorldOne.tsx",
"newmap.tmx",
"tilesets/wOne.tsx"
], ],
"project": "yupple.tiled-project", "project": "yupple.tiled-project",
"property.type": "bool", "property.type": "bool",
"recentFiles": [ "recentFiles": [
"tilesets/wOne.tsx",
"newmap.tmx",
"tilesets/shooterWorldOne.tsx",
"debugmap.tmx",
"tilesets/wsa.tsx",
"tilesets/was.tsx",
"tilesets/shooterWorldOneAtlas.tsx", "tilesets/shooterWorldOneAtlas.tsx",
"shooterWorldOneAtlas.tsx", "shooterWorldOneAtlas.tsx",
"C:/Users/Ethan/Documents/yupplemayham/shooterWorldOneAtlas.tsx", "C:/Users/Ethan/Documents/yupplemayham/shooterWorldOneAtlas.tsx",
"C:/Users/Ethan/Documents/yupplemayham/debugmap.tmx" "C:/Users/Ethan/Documents/yupplemayham/debugmap.tmx"
], ],
"tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)" "tileset.lastUsedFilter": "Tiled tileset files (*.tsx *.xml)",
"tileset.lastUsedFormat": "tsx",
"tileset.margin": 0,
"tileset.spacing": 2,
"tileset.tileSize": {
"height": 62,
"width": 62
}
} }

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<scene type="shooter" id="000"> <scene type="shooter" id="000" bg="backgrounds/blue_sky.png">
<map name="debugmap"/> <map name="newmap"/>
<entities> <entities>
<player x="7" y="5" weapon="shotGun"> <player x="7" y="5" weapon="shotGun">
<animation name="player_anim"/> <animation name="player_anim"/>

View file

@ -3,22 +3,26 @@ patrolDestination = { x=500.0, y=500.0, z=0.0 }
moveLeft = true moveLeft = true
-- helper functions -- helper functions
function watchPosition(actor, pos) function watchPosition(actor, pos)
y = pos.y - actor.position.y local y = pos.y - actor.position.y
x = pos.x - actor.position.x local x = pos.x - actor.position.x
rotation = math.atan(y, x) local rotation = math.atan(y, x)
actor.rotation = math.deg(rotation) actor.rotation = math.deg(rotation)
end end
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)) local dx = a.x - b.x
local dy = a.y - b.y
return math.sqrt(dx * dx + dy * dy)
end end
function moveTo(actor, pos) function moveTo(actor, pos)
watchPosition(actor, pos) local a = actor
if distance(actor.position, pos) < 50 then local p = pos
watchPosition(a, p)
if distance(a.position, p) < 50 then
return true return true
end end
actor:moveForward() a:moveForward()
return false return false
end end
@ -28,19 +32,23 @@ end
-- The AI will be spawned in idle mode, so if you want to put the bot into patrol mode -- The AI will be spawned in idle mode, so if you want to put the bot into patrol mode
-- It's on you to do that in this function. -- It's on you to do that in this function.
function idle(actor, target) function idle(actor, target)
if target ~= nil then local a = actor
local t = target
if t ~= nil then
-- print("target is at " .. target.position.x) -- print("target is at " .. target.position.x)
-- watchPosition(actor, target.position) -- watchPosition(actor, target.position)
ai.state = AIState.Patrol ai.state = AIState.Patrol
actor.rotation = 180 a.rotation = 180
end end
actor:shoot() a:shoot()
--print("actor is idling at " .. actor.position.x) --print("actor is idling at " .. actor.position.x)
end end
-- It is most appropriate to put any patrolling behaviour into this function of course -- It is most appropriate to put any patrolling behaviour into this function of course
function patrol(actor, target) function patrol(actor, target)
if target ~= nil then local a = actor
local t = target
if t ~= nil then
-- print("target is at " .. target.position.x) -- print("target is at " .. target.position.x)
end end
--if moveTo(actor, patrolDestination) == true then --if moveTo(actor, patrolDestination) == true then
@ -52,7 +60,7 @@ function patrol(actor, target)
--if raycaster:performRaycast(actor.position, actor.rotation, target.position) == true then --if raycaster:performRaycast(actor.position, actor.rotation, target.position) == true then
--ai.state = AIState.Alert --ai.state = AIState.Alert
--end --end
if raycaster:bresenhamRaycast(actor.position, actor.rotation, target.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
@ -60,32 +68,34 @@ function patrol(actor, target)
upOrDown = math.random(2) upOrDown = math.random(2)
if moveLeft == true then if moveLeft == true then
if upOrDown == 1 then if upOrDown == 1 then
actor.rotation = 180 a.rotation = 180
else else
actor.rotation = 270 a.rotation = 270
end end
moveLeft = false moveLeft = false
else else
if upOrDown == 1 then if upOrDown == 1 then
actor.rotation = 0 a.rotation = 0
else else
actor.rotation = 90 a.rotation = 90
end end
moveLeft = true moveLeft = true
end end
end end
actor:moveForward() a:moveForward()
end end
-- the ai has found the player, this is what function is called -- the ai has found the player, this is what function is called
function alert(actor, target) function alert(actor, target)
local a = actor
local t = target
if target ~= nil then if target ~= nil then
-- print("target is at " .. target.position.x) -- print("target is at " .. target.position.x)
watchPosition(actor, target.position) watchPosition(a, t.position)
end end
--print("actor is alert at " .. actor.position.x) --print("actor is alert at " .. actor.position.x)
if distance(actor.position, target.position) > 300 then if distance(a.position, t.position) > 300 then
actor:moveForward() a:moveForward()
end end
actor:shoot() a:shoot()
end end

View file

@ -6,8 +6,12 @@ out vec2 texCoord;
uniform mat4 MVP; uniform mat4 MVP;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
void main() void main()
{ {
texCoord = aTexCoord; texCoord = aTexCoord;
gl_Position = MVP * vec4(aPos, 1.0); gl_Position = projection * view * model * vec4(aPos, 1.0);
} }

View file

@ -0,0 +1,11 @@
#version 330 core
in vec2 texCoord;
out vec4 FragColor;
uniform sampler2D sprite;
void main()
{
FragColor = texture(sprite, texCoord) * vec4(1.0, 0.8, 1.0, 1.0);
}

View file

@ -0,0 +1,15 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec2 aTexCoord;
out vec2 texCoord;
uniform mat4 projection;
uniform mat4 view;
void main()
{
texCoord = aTexCoord;
gl_Position = projection * vec4(aPos.xyz, 1.0);
}

View file

@ -5,12 +5,16 @@ layout (location = 1) in vec2 aTexCoord;
out vec2 texCoord; out vec2 texCoord;
uniform mat4 MVP; uniform mat4 MVP;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
uniform bool flip; uniform bool flip;
void main() void main()
{ {
texCoord = aTexCoord; texCoord = aTexCoord;
gl_Position = MVP * vec4(aPos, 1.0); gl_Position = projection * view * model * vec4(aPos, 1.0);
if (flip) if (flip)
{ {
texCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y); texCoord = vec2(aTexCoord.x, 1.0 - aTexCoord.y);

View file

@ -7,9 +7,13 @@ out vec2 texPos;
uniform mat4 MVP; uniform mat4 MVP;
uniform mat4 model;
uniform mat4 projection;
uniform mat4 view;
void main() void main()
{ {
pos = aPos; pos = aPos;
texPos = aTexPos; texPos = aTexPos;
gl_Position = MVP * vec4(aPos, 1.0); gl_Position = projection * view * model * vec4(aPos, 1.0);
} }

View file

@ -1,8 +1,9 @@
#version 330 core #version 330 core
out vec4 FragColor; out vec4 FragColor;
in vec2 texCoord; in vec2 texCoord;
flat in int textureIndex;
uniform sampler2D tileTexture; uniform sampler2DArray tileTexture;
void main() void main()
{ {
@ -12,7 +13,7 @@ void main()
} }
else else
{ {
FragColor = texture(tileTexture, texCoord); FragColor = texture(tileTexture, vec3(texCoord.xy, textureIndex));
} }
//FragColor = vec4(mod(tileindex / float(tilesperrow), 1.0), mod(tileindex / float(tilesperrow), 1.0), 0.0, 1.0); //FragColor = vec4(mod(tileindex / float(tilesperrow), 1.0), mod(tileindex / float(tilesperrow), 1.0), 0.0, 1.0);
} }

View file

@ -2,32 +2,37 @@
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 (location = 2) in int aTileIndex; layout (location = 2) in int aTileIndex;
layout (location = 3) in mat4 aModel; layout (location = 3) in int aTextureIndex;
layout (location = 4) in int aTilesPerRow;
layout (location = 5) in int aStartIndex;
layout (location = 6) in vec2 aOriginalSize;
layout (location = 7) in mat4 aModel;
uniform int tilesPerRow; uniform vec2 uCanvasSize;
uniform mat4 proj; uniform mat4 projection;
uniform mat4 view; uniform mat4 view;
out vec2 texCoord; out vec2 texCoord;
out int tileIndex; flat out int textureIndex;
void main() void main()
{ {
tileIndex = aTileIndex; int tilesPerRow = aTilesPerRow;
gl_Position = proj * view * aModel * vec4(aPos, 1.0); gl_Position = projection * view * aModel * vec4(aPos, 1.0);
if (tileIndex != 0) textureIndex = aTextureIndex;
if (aTileIndex != 0)
{ {
int index = tileIndex - 1; vec2 scale = vec2(aOriginalSize.x / uCanvasSize.x, aOriginalSize.y / uCanvasSize.y);
int index = aTileIndex - aStartIndex;
float tileSize = 1.0 / float(tilesPerRow); float tileSize = 1.0 / float(tilesPerRow);
int row = index / tilesPerRow; int row = index / tilesPerRow;
int col = index % tilesPerRow; int col = index % tilesPerRow;
float offsetX = float(col) * tileSize;
float offsetY = float(row) * tileSize;
texCoord.x = (aTexCoord.x + col) * tileSize; texCoord.x = (aTexCoord.x + col) * tileSize;
texCoord.y = (aTexCoord.y + row) * tileSize; texCoord.y = (aTexCoord.y + row) * tileSize;
texCoord = texCoord * scale;
} }
else else
{ {

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

View file

@ -11,9 +11,9 @@
</bullet> </bullet>
</weapon> </weapon>
<weapon name="shotGun" fireSpeed="750.0" maxAmmo="64" clipSize="4"> <weapon name="shotGun" fireSpeed="1750.0" maxAmmo="64" clipSize="4">
<script file="scripts/weapons/shotgun_script.lua"/> <script file="scripts/weapons/shotgun_script.lua"/>
<animation name="machine_gun_anim"> <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>

View file

@ -13,7 +13,11 @@ 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/lua-5.4.6/include")
include_directories(SYSTEM "C:/sdks/freetype-2.13.2/include") include_directories(SYSTEM "C:/sdks/freetype-2.13.2/include")
link_directories(SYSTEM "C:/sdks/freetype-2.13.2/objs") link_directories(SYSTEM "C:/sdks/freetype-2.13.2/objs")
link_directories(SYSTEM "c:/sdks/tinyxml2-10.0.0/debug/lib") 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") link_directories(SYSTEM "c:/sdks/lua-5.4.6/lib")
include_directories("${PROJECT_SOURCE_DIR}/YuppleMayham/include") include_directories("${PROJECT_SOURCE_DIR}/YuppleMayham/include")
@ -67,7 +71,12 @@ add_executable (YuppleMayham
"include/utility/raycaster.h" "include/utility/raycaster.h"
"include/utility/ftfont.h" "include/utility/ftfont.h"
"include/utility/direction.h" "include/utility/direction.h"
"include/graphics/animation.h" "src/graphics/animation.cpp") "include/graphics/animation.h"
"src/graphics/animation.cpp"
"include/utility/logger.h"
"src/utility/logger.cpp"
"include/graphics/renderer.h"
"src/graphics/renderer.cpp")
add_custom_command(TARGET YuppleMayham PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Resources/ $<TARGET_FILE_DIR:YuppleMayham>) add_custom_command(TARGET YuppleMayham PRE_BUILD COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/Resources/ $<TARGET_FILE_DIR:YuppleMayham>)
@ -75,6 +84,6 @@ if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET YuppleMayham PROPERTY CXX_STANDARD 20) set_property(TARGET YuppleMayham PROPERTY CXX_STANDARD 20)
endif() endif()
target_link_libraries(YuppleMayham SDL2::SDL2main SDL2::SDL2 SDL2_image::SDL2_image tinyxml2 lua_static freetype) target_link_libraries(YuppleMayham SDL2::SDL2main SDL2::SDL2 SDL2_image::SDL2_image tinyxml2 lua_static freetype Tracy::TracyClient)
# TODO: Add tests and install targets if needed. # TODO: Add tests and install targets if needed.

View file

@ -2,7 +2,10 @@
#define _H_AI_H #define _H_AI_H
#include <memory> #include <memory>
#include <thread>
#include <mutex>
#include <string> #include <string>
#include <sol/sol.hpp>
class GameActor; class GameActor;
class Raycaster; class Raycaster;
@ -33,6 +36,14 @@ private:
std::shared_ptr<AIScript> behaviour; std::shared_ptr<AIScript> behaviour;
std::shared_ptr<GameActor> actor; std::shared_ptr<GameActor> actor;
std::shared_ptr<GameActor> target; std::shared_ptr<GameActor> target;
// cache our lua function calls
sol::function idleFunc;
sol::function patrolFunc;
sol::function alertFunc;
std::chrono::high_resolution_clock::time_point lastGCTime;
std::chrono::minutes GCTimeout;
}; };
#endif #endif

View file

@ -6,23 +6,22 @@
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include <SDL_timer.h> #include <SDL_timer.h>
#include "graphics/shader.h" #include "graphics/renderer.h"
class Camera; class Camera;
struct PhysicsComponent; struct PhysicsComponent;
// TODO: Allow speed to be changed and add speed as creation value in XML File! // TODO: Allow speed to be changed and add speed as creation value in XML File!
// TODO: Create Entity System that loads entity types and creates them in scene according to name. // TODO: Create Entity System that loads entity types and creates them in scene according to name.
class Entity class Entity : public Drawable
{ {
public: public:
Entity(const std::shared_ptr<Shader>& shader) : Entity(unsigned shaderID) :
shader(shader),
position(glm::vec3(0.0f)), position(glm::vec3(0.0f)),
scale(glm::vec3(1.0f)), scale(glm::vec3(1.0f)),
rotation(0.0f), rotation(0.0f),
speed(20.0f), speed(20.0f),
entityid(SDL_GetTicks()) entityid(SDL_GetTicks())
{}; { this->shaderID = shaderID; };
virtual ~Entity() {}; virtual ~Entity() {};
void setPosition(const glm::vec3& position); void setPosition(const glm::vec3& position);
@ -44,10 +43,11 @@ public:
const bool getIsMoving() const { return isMoving; } const bool getIsMoving() const { return isMoving; }
const int getEntityID() const { return entityid; } const int getEntityID() const { return entityid; }
const std::shared_ptr<PhysicsComponent> getPhysicsComponent() const { return physics; } const std::shared_ptr<PhysicsComponent> getPhysicsComponent() const { return physics; }
const unsigned getShaderID() const { return shaderID; }
// TODO: right now there is no default behavior, but eventually the Entity class will be expanded to handle physics // TODO: right now there is no default behavior, but eventually the Entity class will be expanded to handle physics
virtual void update(float deltaTime) = 0; virtual void update(double deltaTime) = 0;
virtual void render(const std::shared_ptr<Camera>& camera) = 0; virtual void draw() = 0;
protected: protected:
glm::vec3 localPosition; glm::vec3 localPosition;
@ -69,8 +69,6 @@ protected:
glm::mat4 modelMatrix; glm::mat4 modelMatrix;
void updateModelMatrix(); void updateModelMatrix();
std::shared_ptr<Shader> shader;
}; };

View file

@ -8,6 +8,7 @@ class InputHandler;
class Scene; class Scene;
class Text; class Text;
class ResourceManager; class ResourceManager;
class Renderer;
class GLWindow; class GLWindow;
enum { enum {
@ -27,7 +28,7 @@ public:
void handleInput(SDL_Event& e); void handleInput(SDL_Event& e);
void update(float deltaTime); void update(double deltaTime);
void render(); void render();
const unsigned getGameState() const { return game_state; } const unsigned getGameState() const { return game_state; }
@ -45,6 +46,7 @@ private:
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<Text> textHandler; std::shared_ptr<Text> textHandler;
}; };

View file

@ -19,16 +19,16 @@ class EventManager;
class GameActor : public Entity class GameActor : public Entity
{ {
public: public:
GameActor(const std::shared_ptr<Shader>& shader) : Entity(shader) {} GameActor(const unsigned shaderID) : Entity(shaderID) {}
~GameActor(); ~GameActor();
void addComponent(std::shared_ptr<Component> component); void addComponent(std::shared_ptr<Component> component);
void pickupWeapon(std::shared_ptr<Weapon> weapon); void pickupWeapon(std::shared_ptr<Weapon> weapon);
void hookEventManager(std::shared_ptr<EventManager> eventManager); void hookEventManager(std::shared_ptr<EventManager> eventManager);
void update(float deltaTime) override; void update(double deltaTime) override;
void render(const std::shared_ptr<Camera>& camera) override; void draw() override;
const std::optional<std::shared_ptr<Weapon>> getHeldWeapon() const; const std::shared_ptr<Weapon> getHeldWeapon() const;
void setRotation(const float& rotation) override; void setRotation(const float& rotation) override;

View file

@ -5,6 +5,7 @@
#include <memory> #include <memory>
#include "graphics/instancedraw.h" #include "graphics/instancedraw.h"
#include "graphics/renderer.h"
class Shader; class Shader;
class Camera; class Camera;
@ -12,24 +13,25 @@ class ResourceManager;
struct MapData; struct MapData;
struct TileSetData; struct TileSetData;
class Map class Map : public Drawable
{ {
public: public:
Map(std::shared_ptr<MapData> mapData, const std::shared_ptr<Shader>& shader, 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; }
void render(const std::shared_ptr<Camera>& camera); void draw() override;
private: private:
void loadMap(); void loadMap();
void createCollisionMap(); void createCollisionMap();
int getTileSetIndex(int id) const;
std::shared_ptr<MapData> mapData; std::shared_ptr<MapData> mapData;
std::shared_ptr<TileSetData> tileSetData; std::vector<std::shared_ptr<TileSetData>> tileSetData;
std::vector<std::shared_ptr<TileTextureInstance>> instanceHandles; std::vector<std::shared_ptr<TileTextureInstance>> instanceHandles;
std::shared_ptr<Shader> shader;
std::vector<std::vector<std::vector<int>>> tileIds; std::vector<std::vector<std::vector<int>>> tileIds;
std::vector<std::vector<int>> collisionMap; std::vector<std::vector<int>> collisionMap;
std::vector<std::vector<InstanceData>> tileData; std::vector<std::vector<InstanceData>> tileData;

View file

@ -9,10 +9,13 @@ class Entity;
class Camera; class Camera;
class Map; class Map;
class ResourceManager; class ResourceManager;
class Renderer;
class EventManager; class EventManager;
class GameActor; class GameActor;
class Line; class Line;
class PhysicsEngine; class PhysicsEngine;
class Sprite;
class Shader;
struct SceneData; struct SceneData;
@ -26,8 +29,8 @@ class Scene
public: public:
Scene(SceneType type, std::shared_ptr<ResourceManager> resources); Scene(SceneType type, std::shared_ptr<ResourceManager> resources);
void update(float deltaTime); void update(double deltaTime);
void render(); void render(std::shared_ptr<Renderer> renderer);
std::shared_ptr<GameActor> getPlayer() const; std::shared_ptr<GameActor> getPlayer() const;

View file

@ -14,14 +14,14 @@ public:
Bullet Bullet
( (
const unsigned int owner, const unsigned int owner,
std::shared_ptr<Shader> shader, unsigned shaderID,
glm::vec3 fireFrom, glm::vec3 fireFrom,
glm::vec2 direction, glm::vec2 direction,
float bulletSpeed, float bulletSpeed,
float bulletDrop, float bulletDrop,
glm::vec2 bulletSize glm::vec2 bulletSize
) : ) :
Entity(shader), Entity(shaderID),
origin(fireFrom), origin(fireFrom),
direction(direction), direction(direction),
bulletSpeed(bulletSpeed), bulletSpeed(bulletSpeed),
@ -35,8 +35,8 @@ public:
void addComponent(std::shared_ptr<Component> component); void addComponent(std::shared_ptr<Component> component);
void update(float deltaTime) override; void update(double deltaTime) override;
void render(const std::shared_ptr<Camera>& camera) override; void draw() override;
float getBulletDrop() const { return bulletDrop; } float getBulletDrop() const { return bulletDrop; }
glm::vec3 getBulletOrigin() const { return origin; } glm::vec3 getBulletOrigin() const { return origin; }

View file

@ -22,14 +22,16 @@ public:
float bulletSpeed, float bulletSpeed,
float bulletDrop, float bulletDrop,
glm::vec2 bulletSize, glm::vec2 bulletSize,
const std::shared_ptr<Shader>& shader, const unsigned& shaderID,
const std::shared_ptr<Component>& sprite); const std::shared_ptr<Component>& sprite);
void update(float deltaTime); void update(double deltaTime);
void render(const std::shared_ptr<Camera>& camera); void draw();
void hookEventManager(const std::shared_ptr<EventManager>& eventManager); void hookEventManager(const std::shared_ptr<EventManager>& eventManager);
const std::vector<std::shared_ptr<Bullet>> getBullets() { return bullets; }
private: private:
std::vector<std::shared_ptr<Bullet>> bullets; std::vector<std::shared_ptr<Bullet>> bullets;
std::shared_ptr<EventManager> eventManager; std::shared_ptr<EventManager> eventManager;

View file

@ -27,7 +27,7 @@ struct WeaponData;
class Weapon : public Entity, public std::enable_shared_from_this<Weapon> class Weapon : public Entity, public std::enable_shared_from_this<Weapon>
{ {
public: public:
Weapon(std::shared_ptr<WeaponData> data, const std::shared_ptr<Shader>& weaponShader, const std::shared_ptr<Shader>& bulletShader, ResourceManager* resourceManager); Weapon(std::shared_ptr<WeaponData> data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager);
void setWielder(const std::shared_ptr<GameActor>& wielder) { this->wielder = wielder; } void setWielder(const std::shared_ptr<GameActor>& wielder) { this->wielder = wielder; }
void toggleInfiniteAmmo() { infiniteAmmo = !infiniteAmmo; } void toggleInfiniteAmmo() { infiniteAmmo = !infiniteAmmo; }
@ -39,8 +39,8 @@ public:
void hookEventManager(const std::shared_ptr<EventManager>& eventManager); void hookEventManager(const std::shared_ptr<EventManager>& eventManager);
void shoot(); void shoot();
void reload(); void reload();
void update(float deltaTime); void update(double deltaTime);
void render(const std::shared_ptr<Camera>& camera); void draw();
struct BulletData { struct BulletData {
glm::vec3 origin; glm::vec3 origin;
@ -65,6 +65,8 @@ public:
Weapon::BulletData genBulletData (); Weapon::BulletData genBulletData ();
void createBullet (const BulletData& data); void createBullet (const BulletData& data);
const std::shared_ptr<BulletManager>& getBulletManager() { return bulletManager; }
private: private:
void adjustWeapon(); void adjustWeapon();
@ -82,7 +84,7 @@ private:
// in ms // in ms
float fireSpeed; float fireSpeed;
glm::vec2 bulletSize; glm::vec2 bulletSize;
std::shared_ptr<Shader> bulletShader; unsigned bulletShaderID;
std::shared_ptr<Component> bulletSprite; std::shared_ptr<Component> bulletSprite;
std::shared_ptr<BulletManager> bulletManager; std::shared_ptr<BulletManager> bulletManager;
std::shared_ptr<EventManager> eventManager; std::shared_ptr<EventManager> eventManager;

View file

@ -33,11 +33,14 @@ public:
void play() { isPlaying = true; } void play() { isPlaying = true; }
void stop() { isPlaying = false; } void stop() { isPlaying = false; }
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; }
const int getCycles() const { return cycles; } const int getCycles() const { return cycles; }
void setFPS(const float fps) { FPS = fps; }
private: private:
std::string animName; std::string animName;
std::string animType; std::string animType;

View file

@ -5,12 +5,18 @@
#include <glm/glm.hpp> #include <glm/glm.hpp>
#define MAX_INSTANCES 1000 #define MAX_INSTANCES 1000
#define MAX_TEXTURES 31
class Texture; class Texture;
class TextureArray;
struct InstanceData { struct InstanceData {
glm::mat4 modelMatrix; glm::mat4 modelMatrix;
glm::vec2 originalSize;
int tileIndex = 0; int tileIndex = 0;
int textureIndex = 0;
int tilesPerRow = 0;
int startID = 0;
}; };
class BaseInstanceDraw class BaseInstanceDraw
@ -26,7 +32,6 @@ protected:
Texture* texture = nullptr; Texture* texture = nullptr;
InstanceData instanceData[MAX_INSTANCES]; InstanceData instanceData[MAX_INSTANCES];
size_t numOfInstances = 0; size_t numOfInstances = 0;
size_t numOfLayers = 0;
unsigned indices[6] = { unsigned indices[6] = {
0, 1, 2, 0, 1, 2,
3, 2, 0 3, 2, 0
@ -37,12 +42,17 @@ class TileTextureInstance : public BaseInstanceDraw
{ {
public: public:
TileTextureInstance(const char* texturePath); TileTextureInstance(const char* texturePath);
TileTextureInstance(const std::vector<const char*> texturePaths);
void updateInstanceData(const std::vector<InstanceData>&) override; void updateInstanceData(const std::vector<InstanceData>&) override;
void draw() override; void draw() override;
const TextureArray* getTextureArray() { return textures; }
const Texture* getTexture() { return texture; }
private: private:
void setup() override; void setup() override;
TextureArray* textures = nullptr;
float vertices[20] = { float vertices[20] = {
// vertex // vertex
0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom left 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, // bottom left

View file

@ -0,0 +1,94 @@
#ifndef _H_RENDERER_H
#define _H_RENDERER_H
#include <unordered_map>
#include <memory>
#include <variant>
#include <string>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
class ResourceManager;
enum class RenderLayer {
Background,
Map,
GameObjects,
Effects,
HUD,
Menu
};
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;
};
class Renderer
{
public:
Renderer(const std::shared_ptr<ResourceManager>&);
void clear();
void setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view);
void addDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable);
void removeDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable);
void render();
private:
std::unordered_map<RenderLayer, std::vector<std::shared_ptr<Drawable>>> layerPool;
std::vector<RenderLayer> renderingOrder = {
RenderLayer::Background,
RenderLayer::Map,
RenderLayer::GameObjects,
RenderLayer::Effects,
RenderLayer::HUD,
RenderLayer::Menu
};
void uploadUniforms(const unsigned shaderID, const std::vector<Uniform>& uniforms);
glm::mat4 projMat;
glm::mat4 viewMat;
std::shared_ptr<ResourceManager> resourceManager;
};
#endif

View file

@ -18,6 +18,7 @@ public:
void setFloat(const std::string& name, float value); void setFloat(const std::string& name, float value);
void setInt(const std::string& name, int value); void setInt(const std::string& name, int value);
void setBool(const std::string& name, bool value); void setBool(const std::string& name, bool 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);
~Shader(); ~Shader();

View file

@ -24,6 +24,8 @@ public:
void bind(); void bind();
virtual void draw() = 0; virtual void draw() = 0;
bool loaded() const;
virtual std::shared_ptr<Sprite> clone() const = 0; virtual std::shared_ptr<Sprite> clone() const = 0;
protected: protected:
Texture* texture = nullptr; Texture* texture = nullptr;

View file

@ -1,6 +1,10 @@
#ifndef _H_TEXTURE_H #ifndef _H_TEXTURE_H
#define _H_TEXTURE_H #define _H_TEXTURE_H
#include <vector>
struct SDL_Surface;
class Texture class Texture
{ {
public: public:
@ -19,4 +23,43 @@ private:
int textureHeight = 0; int textureHeight = 0;
}; };
class TextureArray
{
private:
struct TextureData {
int width, height;
};
public:
TextureArray() : numOfLayers(0) {}
/* We are going to assume each texture atlas is a square (512x512, 756x756 ... etc) */
bool loadTextures(std::vector<const char*> imagePaths);
void bind();
TextureData* operator[](const size_t index) {
try
{
return textures.at(index);
}
catch (std::exception&)
{
return nullptr;
}
}
const int getWidth() const { return canvasWidth; }
const int getHeight() const { return canvasHeight; }
~TextureArray();
private:
bool adjustCanvasSizes(std::vector<SDL_Surface*>& surfaces);
size_t numOfLayers;
unsigned ID = 0;
std::vector<TextureData*> textures;
int canvasWidth = 0;
int canvasHeight = 0;
};
#endif #endif

View file

@ -78,6 +78,14 @@ public:
int entityid; 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;
float fireDelay;
};
class AnimationFinishedEvent : public Event { class AnimationFinishedEvent : public Event {
public: public:
AnimationFinishedEvent(const int entityid, const std::string animType) : entityid(entityid), animType(animType) {} AnimationFinishedEvent(const int entityid, const std::string animType) : entityid(entityid), animType(animType) {}

View file

@ -0,0 +1,79 @@
#ifndef _H_LOGGER_H
#define _H_LOGGER_H
#include <mutex>
#include <chrono>
#include <iostream>
#include <sstream>
#define LOG(lvl, msg, ...) Logger::getInstance()->log(lvl, msg, __VA_ARGS__)
#define ERROR_LOG(msg, ...) {Logger::getInstance()->log(ERROR, msg, __VA_ARGS__); return false;}
#define LOG_LEVEL(lvl) Logger::getInstance()->setLevel(lvl)
enum LogLevel {DEBUG, INFO, WARN, ERROR};
class Logger
{
public:
static Logger* getInstance();
template <typename... Args>
void log(LogLevel level, const std::string& message, Args... args) const
{
if (level >= currentLogLevel)
{
std::lock_guard<std::mutex> lock(mutex);
auto msg = formatString(message, args...);
std::cout
<< "["
<< logTag(level)
<< "] "
<< "["
<< std::format("{:%m-%d-%Y %X}", std::chrono::current_zone()->to_local(std::chrono::system_clock::now()))
<< "] "
<< msg
<< std::endl;
}
}
void setLevel(LogLevel level) { currentLogLevel = level; }
Logger(const Logger& l) = delete;
void operator=(const Logger& l) = delete;
protected:
Logger()
{
};
~Logger() { };
LogLevel currentLogLevel = INFO;
template <typename... Args>
std::string formatString(const std::string& str, Args... args) const
{
return std::vformat(str, std::make_format_args(args...));
}
inline const std::string logTag(LogLevel lvl) const
{
switch (lvl)
{
case DEBUG:
return "DEBUG";
case INFO:
return "INFO";
case WARN:
return "WARN";
case ERROR:
return "ERROR";
}
return "INFO";
};
private:
static Logger* instance;
static std::mutex mutex;
};
#endif

View file

@ -6,11 +6,11 @@
#include <string> #include <string>
#include "utility/xmlloader.h" #include "utility/xmlloader.h"
#include "graphics/shader.h"
#include <cassert> #include <cassert>
class Sprite; class Sprite;
class SpriteAtlas; class SpriteAtlas;
class Shader;
class Weapon; class Weapon;
class Script; class Script;
class AnimationSet; class AnimationSet;
@ -37,17 +37,22 @@ public:
std::shared_ptr<AIScript> loadAIScript (const std::string& path); std::shared_ptr<AIScript> loadAIScript (const std::string& path);
std::shared_ptr<WeaponScript> loadWeaponScript (const std::string& path); std::shared_ptr<WeaponScript> loadWeaponScript (const std::string& path);
std::shared_ptr<Shader> loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath); const unsigned loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath);
std::shared_ptr<Weapon> loadWeapon (const std::string& name, std::shared_ptr<Shader> weaponShader, std::shared_ptr<Shader> bulletShader); std::shared_ptr<Weapon> loadWeapon (const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID);
std::shared_ptr<SceneData> loadScene (const std::string& id); std::shared_ptr<SceneData> loadScene (const std::string& id);
std::shared_ptr<AnimationSet> loadAnimationSet(const std::string& name, int entityid = 0); std::shared_ptr<AnimationSet> loadAnimationSet(const std::string& name, int entityid = 0);
std::shared_ptr<TileSetData> loadTileSet (const std::string& name); std::shared_ptr<TileSetData> loadTileSet (const std::string& name);
Shader* getShaderByID(unsigned int ID);
void clearResources(); void clearResources();
~ResourceManager();
private: private:
std::unordered_map<std::string, std::unique_ptr<Shader>> shaders;
std::unordered_map<unsigned, Shader*> shaderIDs;
std::unordered_map<std::string, std::shared_ptr<Sprite>> sprites; std::unordered_map<std::string, std::shared_ptr<Sprite>> sprites;
std::unordered_map<std::string, std::shared_ptr<Shader>> shaders;
std::unordered_map<std::string, std::shared_ptr<Weapon>> weapons; std::unordered_map<std::string, std::shared_ptr<Weapon>> weapons;
std::unordered_map<std::string, std::shared_ptr<Script>> scripts; 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<TileSetData>>tileSets;

View file

@ -4,6 +4,7 @@
#define SOL_ALL_SAFETIES_ON 1 #define SOL_ALL_SAFETIES_ON 1
#include <sol/sol.hpp> #include <sol/sol.hpp>
#include <chrono>
#include <memory> #include <memory>
class Script { class Script {

View file

@ -25,11 +25,15 @@ struct EntityData {
struct MapData { struct MapData {
std::string name; std::string name;
std::string tileSet; struct TileSet {
int startID = 1;
std::string path;
};
std::vector<TileSet> tileSets;
int width = 0, height = 0; int width = 0, height = 0;
float tileSize = 32.f; float tileSize = 32.f;
// 3D array, 0: layer, 1: y, 2: x // 3D array, 0: layer, 1: y, 2: x
// Holding tile ids + 1, 0 is an empty tile // Holding tile startID + ids, 0 is an empty tile
std::vector<std::vector<std::vector<int>>> tiles; std::vector<std::vector<std::vector<int>>> tiles;
}; };
@ -61,6 +65,7 @@ struct TileSetData {
struct SceneData { struct SceneData {
std::string id; std::string id;
std::string type; std::string type;
std::string bgFile;
std::shared_ptr<MapData> map; std::shared_ptr<MapData> map;
std::vector<EntityData> entities; std::vector<EntityData> entities;

View file

@ -4,9 +4,12 @@
#include "utility/raycaster.h" #include "utility/raycaster.h"
#include "utility/script.h" #include "utility/script.h"
#include <tracy/Tracy.hpp>
AI::AI(const std::shared_ptr<GameActor>& actor, const std::shared_ptr<Raycaster>& raycaster) AI::AI(const std::shared_ptr<GameActor>& actor, const std::shared_ptr<Raycaster>& raycaster)
: actor(actor), raycaster(raycaster), state(AIState::Idle) : actor(actor), raycaster(raycaster), state(AIState::Idle),
lastGCTime(std::chrono::high_resolution_clock::now()), GCTimeout(3)
{} {}
void AI::attachBehaviourScript(const std::shared_ptr<AIScript>& behaviour) void AI::attachBehaviourScript(const std::shared_ptr<AIScript>& behaviour)
@ -16,6 +19,13 @@ void AI::attachBehaviourScript(const std::shared_ptr<AIScript>& behaviour)
this->behaviour = behaviour; this->behaviour = behaviour;
this->behaviour->lua["raycaster"] = raycaster; this->behaviour->lua["raycaster"] = raycaster;
this->behaviour->lua["ai"] = shared_from_this(); this->behaviour->lua["ai"] = shared_from_this();
if (this->behaviour->lua["idle"].valid())
idleFunc = this->behaviour->lua["idle"];
if (this->behaviour->lua["patrol"].valid())
patrolFunc = this->behaviour->lua["patrol"];
if (this->behaviour->lua["alert"].valid())
alertFunc = this->behaviour->lua["alert"];
} }
void AI::update() void AI::update()
@ -24,9 +34,9 @@ void AI::update()
switch (state) switch (state)
{ {
case AIState::Idle: case AIState::Idle:
if (behaviour && behaviour->lua["idle"].valid()) if (idleFunc.valid())
{ {
auto result = behaviour->lua["idle"](actor, target); auto result = idleFunc(actor, target);
if (!result.valid()) if (!result.valid())
{ {
sol::error err = result; sol::error err = result;
@ -35,9 +45,9 @@ void AI::update()
} }
break; break;
case AIState::Patrol: case AIState::Patrol:
if (behaviour && behaviour->lua["patrol"].valid()) if (patrolFunc.valid())
{ {
auto result = behaviour->lua["patrol"](actor, target); auto result = patrolFunc(actor, target);
if (!result.valid()) if (!result.valid())
{ {
sol::error err = result; sol::error err = result;
@ -46,9 +56,9 @@ void AI::update()
} }
break; break;
case AIState::Alert: case AIState::Alert:
if (behaviour && behaviour->lua["alert"].valid()) if (alertFunc.valid())
{ {
auto result = behaviour->lua["alert"](actor, target); auto result = alertFunc(actor, target);
if (!result.valid()) if (!result.valid())
{ {
sol::error err = result; sol::error err = result;
@ -57,7 +67,12 @@ void AI::update()
} }
break; break;
} }
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;
}
} }
catch (const std::exception& e) { catch (const std::exception& e) {
std::cerr << "Error during AI update: " << e.what() << std::endl; std::cerr << "Error during AI update: " << e.what() << std::endl;

View file

@ -4,9 +4,9 @@ void Camera::update(float deltaTime)
{ {
if (target == nullptr) if (target == nullptr)
return; return;
float smoothingFactor = 0.01f; float smoothingFactor = 5.0f;
if (glm::distance(target->getCenter(), getCenterPos()) > 20.f) //if (glm::distance(target->getCenter(), getCenterPos()) > 20.f)
position += (target->getCenter() - getCenterPos()) * speed * smoothingFactor * deltaTime; position += (target->getCenter() - getCenterPos()) * smoothingFactor * deltaTime;
} }
glm::mat4 Camera::getViewMatrix() glm::mat4 Camera::getViewMatrix()

View file

@ -38,7 +38,7 @@ void Entity::addPhysicsComponent(const std::shared_ptr<PhysicsComponent>& physic
this->physics = physics; this->physics = physics;
} }
void Entity::update(float deltaTime) void Entity::update(double deltaTime)
{ {
if (physics && physics->rigidBody.velocity != glm::vec3(0.0f)) if (physics && physics->rigidBody.velocity != glm::vec3(0.0f))
{ {
@ -54,13 +54,11 @@ void Entity::update(float deltaTime)
} }
} }
void Entity::render(const std::shared_ptr<Camera>& camera) void Entity::draw()
{ {
glm::mat4 mvp = camera->getProjectionMatrix() * camera->getViewMatrix() * modelMatrix; //glm::mat4 mvp = camera->getProjectionMatrix() * camera->getViewMatrix() * modelMatrix;
editUniform("model", modelMatrix);
shader->use(); editUniform("flip", flipped);
shader->setMatrix4f("MVP", glm::value_ptr(mvp));
shader->setBool("flip", flipped);
} }
void Entity::updateModelMatrix() void Entity::updateModelMatrix()
@ -73,5 +71,4 @@ void Entity::updateModelMatrix()
rotationMat * rotationMat *
origin * origin *
glm::scale(glm::mat4(1.0f), scale); glm::scale(glm::mat4(1.0f), scale);
} }

View file

@ -9,6 +9,7 @@
#include "utility/command.h" #include "utility/command.h"
#include "utility/resourcemanager.h" #include "utility/resourcemanager.h"
#include "utility/ftfont.h" #include "utility/ftfont.h"
#include "utility/logger.h"
#include "graphics/glwindow.h" #include "graphics/glwindow.h"
@ -20,16 +21,16 @@ bool Game::init()
window = std::make_shared<GLWindow>("Yupple Mayham", 800, 600); window = std::make_shared<GLWindow>("Yupple Mayham", 800, 600);
if (!window->Init()) if (!window->Init())
{ ERROR_LOG("Failed to init GLWindow: {}", SDL_GetError());
std::cout << "Failed to init GLWindow: \n" << SDL_GetError() << std::endl;
return false;
}
if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress)) if (!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress))
{ ERROR_LOG("Failed to load GLLoader");
std::cout << "Failed to load GLLoader" << std::endl;
return false; #if _DEBUG
} LOG_LEVEL(DEBUG);
#else
LOG_LEVEL(INFO);
#endif
SDL_GL_SetSwapInterval(1); SDL_GL_SetSwapInterval(1);
glViewport(0, 0, window->width(), window->height()); glViewport(0, 0, window->width(), window->height());
@ -49,6 +50,7 @@ bool Game::init()
game_state |= GAME_RUNNING; game_state |= GAME_RUNNING;
resourceManager = std::make_shared<ResourceManager>(); resourceManager = std::make_shared<ResourceManager>();
renderer = std::make_shared<Renderer>(resourceManager);
textHandler = std::make_shared<Text>(); textHandler = std::make_shared<Text>();
if (!textHandler->loadFonts("fonts")) if (!textHandler->loadFonts("fonts"))
return false; return false;
@ -74,7 +76,7 @@ void Game::handleInput(SDL_Event& e)
inputHandler->handleInput(); inputHandler->handleInput();
} }
void Game::update(float deltaTime) void Game::update(double deltaTime)
{ {
if (currentScene) if (currentScene)
currentScene->update(deltaTime); currentScene->update(deltaTime);
@ -87,11 +89,11 @@ void Game::render()
if (currentScene) if (currentScene)
{ {
currentScene->render(); currentScene->render(renderer);
/*Debug ammo indicator*/ /*Debug ammo indicator*/
textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->get()->getMagazine()), glm::vec2(10, 10), 0.5f); 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", "/", glm::vec2(50, 10), 0.5f);
textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->get()->getAmmo()), glm::vec2(90, 10), 0.5f); textHandler->DrawText("comic.ttf", std::to_string(currentScene->getPlayer()->getHeldWeapon()->getAmmo()), glm::vec2(90, 10), 0.5f);
} }
window->swap(); window->swap();

View file

@ -14,9 +14,9 @@ void GameActor::addComponent(std::shared_ptr<Component> component)
components.push_back(component); components.push_back(component);
} }
const std::optional<std::shared_ptr<Weapon>> GameActor::getHeldWeapon() const const std::shared_ptr<Weapon> GameActor::getHeldWeapon() const
{ {
return (weapons.empty() || currentWeaponIndex >= weapons.size()) ? std::nullopt : std::make_optional(weapons[currentWeaponIndex]); return (weapons.empty() || currentWeaponIndex >= weapons.size()) ? nullptr : weapons[currentWeaponIndex];
} }
void GameActor::pickupWeapon(std::shared_ptr<Weapon> weapon) void GameActor::pickupWeapon(std::shared_ptr<Weapon> weapon)
@ -24,9 +24,9 @@ void GameActor::pickupWeapon(std::shared_ptr<Weapon> weapon)
weapon->setWielder(std::shared_ptr<GameActor>(this)); weapon->setWielder(std::shared_ptr<GameActor>(this));
weapons.push_back(weapon); weapons.push_back(weapon);
// wield the newly picked up weapon. // wield the newly picked up weapon.
getHeldWeapon().value()->putaway(); getHeldWeapon()->putaway();
currentWeaponIndex = weapons.size() - 1; currentWeaponIndex = weapons.size() - 1;
getHeldWeapon().value()->wield(); getHeldWeapon()->wield();
} }
void GameActor::hookEventManager(std::shared_ptr<EventManager> eventManager) void GameActor::hookEventManager(std::shared_ptr<EventManager> eventManager)
@ -47,13 +47,13 @@ void GameActor::setRotation(const float& rotation)
updateModelMatrix(); updateModelMatrix();
} }
void GameActor::update(float deltaTime) void GameActor::update(double deltaTime)
{ {
Entity::update(deltaTime); Entity::update(deltaTime);
for (auto& component : components) for (const auto& component : components)
component->update(); component->update();
for (auto& weapon : weapons) for (const auto& weapon : weapons)
weapon->update(deltaTime); weapon->update(deltaTime);
if (eventManager) if (eventManager)
@ -72,19 +72,19 @@ void GameActor::update(float deltaTime)
isMoving = false; isMoving = false;
} }
void GameActor::render(const std::shared_ptr<Camera>& camera) void GameActor::draw()
{ {
Entity::render(camera); Entity::draw();
// regular loop through components, but if the component returns true to kill, we erase it. // regular loop through components, but if the component returns true to kill, we erase it.
// Components are always assumed to be smart pointers! // Components are always assumed to be smart pointers!
for (auto& component : components) for (const auto& component : components)
{ {
component->bind(); component->bind();
component->render(); component->render();
} }
for (auto& weapon : weapons) //for (auto& weapon : weapons)
weapon->render(camera); // weapon->draw();
} }
void GameActor::moveUp() { if (physics) physics->rigidBody.applyForce(glm::vec3( 0.f,-1.f, 0.f), 1500.25f); isMoving = true; } void GameActor::moveUp() { if (physics) physics->rigidBody.applyForce(glm::vec3( 0.f,-1.f, 0.f), 1500.25f); isMoving = true; }
@ -93,7 +93,7 @@ void GameActor::moveLeft() { if (physics) physics->rigidBody.applyForce(glm::vec
void GameActor::moveRight(){ 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 { if (auto& weapon = getHeldWeapon()) weapon.value()->shoot(); } void GameActor::fireWeapon()const { if (auto& weapon = getHeldWeapon()) weapon->shoot(); }
void GameActor::cycleUpWeapons() { void GameActor::cycleUpWeapons() {
if (!weapons.empty()) { if (!weapons.empty()) {
weapons[currentWeaponIndex]->putaway(); weapons[currentWeaponIndex]->putaway();

View file

@ -1,21 +1,33 @@
#include "gameplay/map.h" #include "gameplay/map.h"
#include "gameplay/camera.h" #include "gameplay/camera.h"
#include "graphics/shader.h" #include "graphics/shader.h"
#include "graphics/texture.h"
#include "utility/xmlloader.h" #include "utility/xmlloader.h"
#include "utility/resourcemanager.h" #include "utility/resourcemanager.h"
#include <glm/gtc/matrix_transform.hpp> #include <glm/gtc/matrix_transform.hpp>
Map::Map(std::shared_ptr<MapData> mapData, const std::shared_ptr<Shader>& shader, std::shared_ptr<ResourceManager> resourceManager) : Map::Map(std::shared_ptr<MapData> mapData, const unsigned shaderID, std::shared_ptr<ResourceManager> resourceManager) :
shader(shader),
mapData(mapData), mapData(mapData),
tileIds(mapData->tiles) tileIds(mapData->tiles)
{ {
tileSetData = resourceManager->loadTileSet(mapData->tileSet); this->shaderID = shaderID;
if (tileSetData)
for (auto& tileSet : mapData->tileSets)
tileSetData.push_back(resourceManager->loadTileSet(tileSet.path));
if (!tileSetData.empty())
{ {
std::vector<const char*> buffer;
for (int layer = 0; layer < tileIds.size(); layer++) for (int layer = 0; layer < tileIds.size(); layer++)
instanceHandles.push_back(std::make_shared<TileTextureInstance>(tileSetData->file.c_str())); {
buffer.clear();
for (auto& set : tileSetData)
buffer.push_back(set->file.c_str());
if (!buffer.empty())
instanceHandles.push_back(std::make_shared<TileTextureInstance>(buffer));
}
loadMap(); loadMap();
createCollisionMap(); createCollisionMap();
} }
@ -34,14 +46,23 @@ void Map::loadMap()
glm::mat4 modelMatrix = glm::mat4 modelMatrix =
glm::translate(glm::mat4(1.f), glm::vec3(x * mapData->tileSize, y * mapData->tileSize, 0.0f)) * glm::translate(glm::mat4(1.f), glm::vec3(x * mapData->tileSize, y * mapData->tileSize, 0.0f)) *
glm::scale(glm::mat4(1.f), glm::vec3(mapData->tileSize, mapData->tileSize, 1.0f)); glm::scale(glm::mat4(1.f), glm::vec3(mapData->tileSize, mapData->tileSize, 1.0f));
int tileIndex = static_cast<int>(tileIds[layer][y][x]);
tileData[layer].push_back({modelMatrix, tileIndex});
int textureIndex = getTileSetIndex(tileIds[layer][y][x]);
glm::vec2 originalSize = (textureIndex != -1) ?
glm::vec2(tileSetData[textureIndex]->width, tileSetData[textureIndex]->height) :
glm::vec2(0.0f);
int tilesPerRow = (textureIndex != -1) ? tileSetData[textureIndex]->columns : 0;
int startID = (textureIndex != -1) ? mapData->tileSets[textureIndex].startID : 0;
int tileIndex = tileIds[layer][y][x];
tileData[layer].push_back({modelMatrix, originalSize, tileIndex, textureIndex, tilesPerRow, startID});
} }
} }
instanceHandles[layer]->updateInstanceData(tileData[layer]);
} }
shader->use(); glm::vec2 canvasSize = glm::vec2(instanceHandles[0]->getTextureArray()->getWidth(), instanceHandles[0]->getTextureArray()->getHeight());
// TODO: Figure someway to put these in with my xml data editUniformOnce("uCanvasSize", canvasSize);
shader->setInt("tilesPerRow", tileSetData->columns);
} }
void Map::createCollisionMap() void Map::createCollisionMap()
@ -60,11 +81,13 @@ void Map::createCollisionMap()
for (int x = 0; x < tileIds[layer][y].size(); x++) for (int x = 0; x < tileIds[layer][y].size(); x++)
{ {
int id = tileIds[layer][y][x]; int id = tileIds[layer][y][x];
if (id == 0) int tileSetIndex = getTileSetIndex(id);
if (tileSetIndex == -1)
collisionMap[y][x] = 0; collisionMap[y][x] = 0;
else else
{ {
auto& tile = tileSetData->tiles[id - 1]; int startID = mapData->tileSets[tileSetIndex].startID;
auto& tile = tileSetData[tileSetIndex]->tiles[id - startID];
if (!tile->walkable) if (!tile->walkable)
collisionMap[y][x] = 1; collisionMap[y][x] = 1;
} }
@ -73,14 +96,30 @@ void Map::createCollisionMap()
} }
} }
void Map::render(const std::shared_ptr<Camera>& camera) void Map::draw()
{ {
shader->use();
shader->setMatrix4f("proj", glm::value_ptr(camera->getProjectionMatrix()));
shader->setMatrix4f("view", glm::value_ptr(camera->getViewMatrix()));
for (int layer = 0; layer < instanceHandles.size(); layer++) for (int layer = 0; layer < instanceHandles.size(); layer++)
{ {
instanceHandles[layer]->updateInstanceData(tileData[layer]);
instanceHandles[layer]->draw(); instanceHandles[layer]->draw();
} }
} }
/*
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 instanceHandle
returns tileSetIndex of the tile id passed. Unless the id is either 0 or
the returned tileSetIndex is out of bounds, returns -1
*/
int Map::getTileSetIndex(int id) const
{
// work from the bottom, break if ID > startID
// If we get a textureIndex of -1 then we are on an empty tile
int tileSetIndex = mapData->tileSets.size() - 1;
for (; tileSetIndex != -1; --tileSetIndex)
{
if (id >= mapData->tileSets[tileSetIndex].startID)
break;
}
return (tileSetIndex >= mapData->tileSets.size()) ? -1 : tileSetIndex;
}

View file

@ -2,6 +2,8 @@
#include "gameplay/weapons/bullet.h" #include "gameplay/weapons/bullet.h"
#include "utility/events.h" #include "utility/events.h"
#include "utility/logger.h"
#include <iostream> #include <iostream>
void PhysicsEngine::hookEventManager(const std::shared_ptr<EventManager>& eventManager) void PhysicsEngine::hookEventManager(const std::shared_ptr<EventManager>& eventManager)
@ -21,7 +23,7 @@ std::shared_ptr<PhysicsComponent> PhysicsEngine::createObject(const unsigned int
const glm::vec3& pos, const glm::vec3& pos,
float mass, float mass,
PhysicsComponent::Collider::Shape shape, PhysicsComponent::Collider::Shape shape,
glm::vec3 dimensions, glm::vec3 dimensions, const
glm::vec3 offset) glm::vec3 offset)
{ {
auto component = std::make_shared <PhysicsComponent>(); auto component = std::make_shared <PhysicsComponent>();

View file

@ -2,6 +2,7 @@
#include "gameplay/camera.h" #include "gameplay/camera.h"
#include "gameplay/gameactor.h" #include "gameplay/gameactor.h"
#include "gameplay/weapons/weapons.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/ai.h" #include "gameplay/ai.h"
@ -16,6 +17,8 @@
#include "utility/raycaster.h" #include "utility/raycaster.h"
#include "utility/debugdraw.h" #include "utility/debugdraw.h"
#include <tracy/Tracy.hpp>
#include <execution> #include <execution>
// Scene xml files, should contain a node called <player> that holds the sprite location // Scene xml files, should contain a node called <player> that holds the sprite location
@ -123,8 +126,9 @@ std::shared_ptr<GameActor> Scene::getPlayer() const
return (!player) ? nullptr : player; return (!player) ? nullptr : player;
} }
void Scene::update(float deltaTime) void Scene::update(double deltaTime)
{ {
ZoneScoped;
for (const auto& [id, e] : entities) for (const auto& [id, e] : entities)
{ {
e->update(deltaTime); e->update(deltaTime);
@ -135,14 +139,29 @@ void Scene::update(float deltaTime)
camera->update(deltaTime); camera->update(deltaTime);
} }
void Scene::render() void Scene::render(std::shared_ptr<Renderer> renderer)
{ {
map->render(camera); ZoneScoped;
renderer->clear();
renderer->setProjAndViewMatrix(camera->getProjectionMatrix(), camera->getViewMatrix());
renderer->addDrawable(RenderLayer::Map, map);
//map->draw();
for (auto& [id, e] : entities) for (auto& [id, e] : entities)
{ {
e->render(camera); //e->draw();
renderer->addDrawable(RenderLayer::GameObjects, e);
if (e->getHeldWeapon()) {
renderer->addDrawable(RenderLayer::GameObjects, e->getHeldWeapon());
for (const auto& bullet : e->getHeldWeapon()->getBulletManager()->getBullets()) {
renderer->addDrawable(RenderLayer::GameObjects, bullet);
} }
}
}
DebugDrawer::getInstance().draw(camera->getProjectionMatrix() * camera->getViewMatrix()); DebugDrawer::getInstance().draw(camera->getProjectionMatrix() * camera->getViewMatrix());
renderer->render();
} }
void Scene::unloadScene() void Scene::unloadScene()
@ -158,7 +177,7 @@ void Scene::hookSceneEvents()
std::shared_ptr<GameActor> target = getGameActorByID(collideEvent->victimID); std::shared_ptr<GameActor> target = getGameActorByID(collideEvent->victimID);
if (shooter && target) if (shooter && target)
if (auto& weapon = shooter->getHeldWeapon()) if (auto& weapon = shooter->getHeldWeapon())
weapon.value()->onHitCallback(target, collideEvent->bullet, collideEvent->normal); weapon->onHitCallback(target, collideEvent->bullet, collideEvent->normal);
}); });
} }

View file

@ -2,12 +2,14 @@
#include "gameplay/physics.h" #include "gameplay/physics.h"
#include "utility/component.h" #include "utility/component.h"
#include "gameplay/camera.h"
void Bullet::addComponent(std::shared_ptr<Component> component) void Bullet::addComponent(std::shared_ptr<Component> component)
{ {
components.push_back(component); components.push_back(component);
} }
void Bullet::update(float deltaTime) void Bullet::update(double deltaTime)
{ {
Entity::update(deltaTime); Entity::update(deltaTime);
@ -19,11 +21,10 @@ void Bullet::update(float deltaTime)
component->update(); component->update();
} }
void Bullet::render(const std::shared_ptr<Camera>& camera) void Bullet::draw()
{ {
Entity::render(camera); Entity::draw();
shader->use();
for (auto& component : components) for (auto& component : components)
{ {
component->play(); component->play();

View file

@ -1,6 +1,7 @@
#include "gameplay/weapons/bulletmanager.h" #include "gameplay/weapons/bulletmanager.h"
#include "gameplay/weapons/bullet.h" #include "gameplay/weapons/bullet.h"
#include "gameplay/physics.h" #include "gameplay/physics.h"
#include "gameplay/camera.h"
#include "utility/events.h" #include "utility/events.h"
#include "utility/component.h" #include "utility/component.h"
@ -29,16 +30,16 @@ void BulletManager::addBullet(const unsigned int owner, const glm::vec3& fireFro
float bulletSpeed, float bulletSpeed,
float bulletDrop, float bulletDrop,
glm::vec2 bulletSize, glm::vec2 bulletSize,
const std::shared_ptr<Shader>& shader, const unsigned& shaderID,
const std::shared_ptr<Component>& sprite) const std::shared_ptr<Component>& sprite)
{ {
auto bullet = std::make_shared<Bullet>(owner, shader, fireFrom, direction, bulletSpeed, bulletDrop, bulletSize); auto bullet = std::make_shared<Bullet>(owner, shaderID, fireFrom, direction, bulletSpeed, bulletDrop, bulletSize);
bullet->addComponent(sprite); bullet->addComponent(sprite);
//bullet->addPhysicsComponent(phy) //bullet->addPhysicsComponent(phy)
bullets.emplace_back(bullet); bullets.emplace_back(bullet);
} }
void BulletManager::update(float deltaTime) void BulletManager::update(double deltaTime)
{ {
for (auto& bullet : bullets) for (auto& bullet : bullets)
{ {
@ -54,11 +55,11 @@ void BulletManager::update(float deltaTime)
} }
} }
void BulletManager::render(const std::shared_ptr<Camera>& camera) void BulletManager::draw()
{ {
for (auto& bullet : bullets) for (auto& bullet : bullets)
{ {
if (!bullet) continue; if (!bullet) continue;
bullet->render(camera); bullet->draw();
} }
} }

View file

@ -10,13 +10,14 @@
#include "utility/events.h" #include "utility/events.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(std::shared_ptr<WeaponData> data, const std::shared_ptr<Shader>& weaponShader, const std::shared_ptr<Shader>& bulletShader, ResourceManager* resourceManager) Weapon::Weapon(std::shared_ptr<WeaponData> data, const unsigned weaponShaderID, const unsigned bulletShaderID, ResourceManager* resourceManager)
: :
Entity (weaponShader), Entity (weaponShaderID),
bulletShader (bulletShader), bulletShaderID (bulletShaderID),
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)),
weaponMagSize (data->clipSize), weaponMagSize (data->clipSize),
@ -71,9 +72,12 @@ void Weapon::shoot()
if (wielder) if (wielder)
{ {
Uint32 currentTime = SDL_GetTicks(); Uint32 currentTime = SDL_GetTicks();
if (weaponMag <= 0 && !reloading) reload(); if (currentTime - lastFireTime >= fireSpeed && !reloading)
if (currentTime - lastFireTime >= fireSpeed && !reloading && weaponMag > 0)
{ {
if (weaponMag > 0)
{
if (eventManager)
eventManager->notify(std::make_shared<EntityFireEvent>(entityid, fireSpeed));
if (!weaponScript || !weaponScript->lua["onShoot"].valid()) if (!weaponScript || !weaponScript->lua["onShoot"].valid())
{ {
// create bullet using this generated data // create bullet using this generated data
@ -90,6 +94,8 @@ void Weapon::shoot()
} }
weaponMag -= 1; weaponMag -= 1;
} }
}
else if (weaponMag <= 0) reload();
lastFireTime = currentTime; lastFireTime = currentTime;
} }
} }
@ -127,7 +133,7 @@ void Weapon::attachScript(const std::shared_ptr<WeaponScript>& script)
{ {
weaponScript = script; weaponScript = script;
weaponScript->lua["weapon"] = shared_from_this(); weaponScript->lua["weapon"] = shared_from_this();
std::cout << "weapon state bound" << std::endl; LOG(DEBUG, "Weapon state bound");
} }
void Weapon::onHitCallback(std::shared_ptr<GameActor> target, std::shared_ptr<PhysicsComponent> bullet, const glm::vec2& normal) void Weapon::onHitCallback(std::shared_ptr<GameActor> target, std::shared_ptr<PhysicsComponent> bullet, const glm::vec2& normal)
@ -143,7 +149,7 @@ void Weapon::onHitCallback(std::shared_ptr<GameActor> target, std::shared_ptr<Ph
} }
} }
void Weapon::update(float deltaTime) void Weapon::update(double deltaTime)
{ {
Entity::update(deltaTime); Entity::update(deltaTime);
if (wielded) if (wielded)
@ -163,9 +169,9 @@ void Weapon::update(float deltaTime)
bulletManager->update(deltaTime); bulletManager->update(deltaTime);
} }
void Weapon::render(const std::shared_ptr<Camera>& camera) void Weapon::draw()
{ {
Entity::render(camera); Entity::draw();
if (wielded) if (wielded)
{ {
for (auto& component : components) for (auto& component : components)
@ -175,7 +181,7 @@ void Weapon::render(const std::shared_ptr<Camera>& camera)
component->render(); component->render();
} }
} }
bulletManager->render(camera); //bulletManager->draw();
} }
void Weapon::adjustWeapon() void Weapon::adjustWeapon()
@ -235,7 +241,7 @@ Weapon::BulletData Weapon::genBulletData()
void Weapon::createBullet(const Weapon::BulletData& data) void Weapon::createBullet(const Weapon::BulletData& data)
{ {
auto bullet = std::make_shared<Bullet>(wielder->getEntityID(), bulletShader, data.origin, data.direction, bulletSpeed, bulletDrop, bulletSize); auto bullet = std::make_shared<Bullet>(wielder->getEntityID(), bulletShaderID, data.origin, data.direction, bulletSpeed, bulletDrop, bulletSize);
bullet->addComponent(bulletSprite); bullet->addComponent(bulletSprite);
bullet->addPhysicsComponent(std::make_shared<PhysicsComponent>(PhysicsComponentFactory::makeBullet(wielder->getEntityID(), data.origin, data.mass, bulletSize.x / 2))); bullet->addPhysicsComponent(std::make_shared<PhysicsComponent>(PhysicsComponentFactory::makeBullet(wielder->getEntityID(), data.origin, data.mass, bulletSize.x / 2)));
bullet->getPhysicsComponent()->rigidBody.velocity += bulletSpeed * glm::vec3(data.direction.x, data.direction.y, 0.f) / data.mass; bullet->getPhysicsComponent()->rigidBody.velocity += bulletSpeed * glm::vec3(data.direction.x, data.direction.y, 0.f) / data.mass;

View file

@ -143,7 +143,10 @@ void AnimationSet::attachEventManager(const std::shared_ptr<EventManager>& e)
if (reloadEvent->entityid == entityid) if (reloadEvent->entityid == entityid)
{ {
if (anims["reload"] != NULL) if (anims["reload"] != NULL)
{
curAnim = anims["reload"]; curAnim = anims["reload"];
curAnim->reset();
}
} }
}); });
@ -155,6 +158,29 @@ void AnimationSet::attachEventManager(const std::shared_ptr<EventManager>& e)
curAnim = anims["idle"]; curAnim = anims["idle"];
} }
}); });
eventManager->subscribe("OnEntityFire", [this](std::shared_ptr<Event> e) {
auto fireEvent = std::static_pointer_cast<EntityFireEvent>(e);
if (fireEvent->entityid == entityid)
{
if (anims["fire"] != NULL)
{
curAnim = anims["fire"];
curAnim->reset();
float newFPS = (1000.f / fireEvent->fireDelay) * 15.f;
curAnim->setFPS(newFPS);
}
}
});
eventManager->subscribe("OnAnimationFinished", [this](std::shared_ptr<Event> e) {
auto animEvent = std::static_pointer_cast<AnimationFinishedEvent>(e);
if (animEvent->entityid == entityid && animEvent->animType == "fire")
{
if (anims["idle"] != NULL)
curAnim = anims["idle"];
}
});
} }
void AnimationSet::bind() void AnimationSet::bind()

View file

@ -12,6 +12,13 @@ TileTextureInstance::TileTextureInstance(const char* texturePath)
setup(); setup();
} }
TileTextureInstance::TileTextureInstance(const std::vector<const char*> texturePaths)
{
textures = new TextureArray();
if (textures->loadTextures(texturePaths))
setup();
}
void TileTextureInstance::setup() void TileTextureInstance::setup()
{ {
glGenVertexArrays(1, &VAO); glGenVertexArrays(1, &VAO);
@ -37,15 +44,38 @@ void TileTextureInstance::setup()
glBufferData(GL_ARRAY_BUFFER, sizeof(InstanceData) * MAX_INSTANCES, nullptr, GL_DYNAMIC_DRAW); glBufferData(GL_ARRAY_BUFFER, sizeof(InstanceData) * MAX_INSTANCES, nullptr, GL_DYNAMIC_DRAW);
// tileIndex instanceData layout position 2
glVertexAttribIPointer(2, 1, GL_INT, sizeof(InstanceData), (void*)(offsetof(InstanceData, tileIndex))); glVertexAttribIPointer(2, 1, GL_INT, sizeof(InstanceData), (void*)(offsetof(InstanceData, tileIndex)));
glEnableVertexAttribArray(2); glEnableVertexAttribArray(2);
glVertexAttribDivisor(2, 1); glVertexAttribDivisor(2, 1);
// textureIndex instanceData layout position 3 -> We are using multiple textures to hold each tileset
glVertexAttribIPointer(3, 1, GL_INT, sizeof(InstanceData), (void*)(offsetof(InstanceData, textureIndex)));
glEnableVertexAttribArray(3);
glVertexAttribDivisor(3, 1);
// tilesPerRow instanceData layout position 4, This is needed since we are supporting multiple tilesets
// of different sizes
glVertexAttribIPointer(4, 1, GL_INT, sizeof(InstanceData), (void*)(offsetof(InstanceData, tilesPerRow)));
glEnableVertexAttribArray(4);
glVertexAttribDivisor(4, 1);
// startID instanceData layout position 5
glVertexAttribIPointer(5, 1, GL_INT, sizeof(InstanceData), (void*)(offsetof(InstanceData, startID)));
glEnableVertexAttribArray(5);
glVertexAttribDivisor(5, 1);
// originalSize instanceData layout position 6
glVertexAttribPointer(6, 2, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (void*)(offsetof(InstanceData, originalSize)));
glEnableVertexAttribArray(6);
glVertexAttribDivisor(6, 1);
// modelMatrix instanceData as 4 vec 4s (a 4x4 matrix) layout head position 7
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
{ {
glVertexAttribPointer(3 + i, 4, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (void*)(offsetof(InstanceData, modelMatrix) + (sizeof(glm::vec4) * i))); glVertexAttribPointer(7 + i, 4, GL_FLOAT, GL_FALSE, sizeof(InstanceData), (void*)(offsetof(InstanceData, modelMatrix) + (sizeof(glm::vec4) * i)));
glEnableVertexAttribArray(3 + i); glEnableVertexAttribArray(7 + i);
glVertexAttribDivisor(3 + i, 1); glVertexAttribDivisor(7 + i, 1);
} }
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0); glBindVertexArray(0);
@ -60,23 +90,39 @@ void TileTextureInstance::updateInstanceData(const std::vector<InstanceData>& in
InstanceData* instances = (InstanceData*)glMapBufferRange(GL_ARRAY_BUFFER, 0, InstanceData* instances = (InstanceData*)glMapBufferRange(GL_ARRAY_BUFFER, 0,
sizeof(InstanceData) * instanceData.size(), sizeof(InstanceData) * instanceData.size(),
GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
if (!instances) if (!instances)
return; return;
if (instances)
{
std::memcpy(instances, instanceData.data(), sizeof(InstanceData) * instanceData.size());
glUnmapBuffer(GL_ARRAY_BUFFER);
}
/*
for (int i = 0; i < instanceData.size(); i++) for (int i = 0; i < instanceData.size(); i++)
{ {
instances[i].modelMatrix = instanceData[i].modelMatrix; instances[i].modelMatrix = instanceData[i].modelMatrix;
instances[i].originalSize = instanceData[i].originalSize;
instances[i].tileIndex = instanceData[i].tileIndex; instances[i].tileIndex = instanceData[i].tileIndex;
instances[i].textureIndex = instanceData[i].textureIndex;
instances[i].tilesPerRow = instanceData[i].tilesPerRow;
instances[i].startID = instanceData[i].startID;
} }
*/
glUnmapBuffer(GL_ARRAY_BUFFER);
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
} }
void TileTextureInstance::draw() void TileTextureInstance::draw()
{ {
// bind textures
if (texture)
texture->bind(); texture->bind();
else if (textures)
textures->bind();
glBindVertexArray(VAO); glBindVertexArray(VAO);
glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, numOfInstances); glDrawElementsInstanced(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr, numOfInstances);
glBindVertexArray(0); glBindVertexArray(0);

View file

@ -0,0 +1,102 @@
#include "graphics/renderer.h"
#include "graphics/shader.h"
#include "utility/resourcemanager.h"
#include "utility/logger.h"
#include <algorithm>
Renderer::Renderer(const std::shared_ptr<ResourceManager>& r)
: resourceManager(r)
{
projMat = glm::mat4(0.f);
viewMat = glm::mat4(0.f);
}
void Renderer::setProjAndViewMatrix(const glm::mat4& proj, const glm::mat4& view)
{
projMat = proj;
viewMat = view;
}
void Renderer::addDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable)
{
layerPool[renderLayer].push_back(drawable);
}
void Renderer::removeDrawable(RenderLayer renderLayer, std::shared_ptr<Drawable> drawable)
{
auto& pool = layerPool[renderLayer];
pool.erase(std::remove(pool.begin(), pool.end(), drawable));
}
void Renderer::render()
{
// Sort by shader id, this works to batch shaders together to avoid shader switching too much
for (auto& [_,pool] : layerPool) {
std::sort(pool.begin(), pool.end(),
[](const std::shared_ptr<Drawable>& a, const std::shared_ptr<Drawable>& b) {
return a->getShaderID() < b->getShaderID();
});
}
Shader* curShader = nullptr;
for (const auto& layer : renderingOrder) {
unsigned curShaderID = static_cast<unsigned>(-1);
for (const auto& item : layerPool[layer]) {
if (item->getShaderID() != curShaderID) {
curShaderID = item->getShaderID();
curShader = resourceManager->getShaderByID(curShaderID);
if (curShader) {
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()) {
uploadUniforms(curShaderID, item->getOneShotUniforms());
item->clearOneShot();
}
uploadUniforms(curShaderID, item->getUniforms());
item->clearUniforms();
item->draw();
}
}
}
void Renderer::clear()
{
layerPool.clear();
}
void Renderer::uploadUniforms(const unsigned shaderID, const std::vector<Uniform>& uniforms)
{
Shader *shader = resourceManager->getShaderByID(shaderID);
if (shader == nullptr) {
LOG(ERROR, "No shader found with id {} !", shaderID);
return;
}
for (const auto& uniform : uniforms) {
std::visit([&](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<T, bool>) {
shader->setBool(uniform.name, arg);
}
else if constexpr (std::is_same_v<T, int>) {
shader->setInt(uniform.name, arg);
}
else if constexpr (std::is_same_v<T, float>) {
shader->setFloat(uniform.name, arg);
}
else if constexpr (std::is_same_v<T, glm::vec2>) {
shader->setVec2(uniform.name, glm::value_ptr(arg));
}
else if constexpr (std::is_same_v<T, glm::mat4>) {
shader->setMatrix4f(uniform.name, glm::value_ptr(arg));
}
}, uniform.value);
}
}

View file

@ -93,6 +93,11 @@ void Shader::setBool(const std::string& name, bool value)
glUniform1i(glGetUniformLocation(ID, name.c_str()), value); glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
} }
void Shader::setVec2(const std::string& name, const float* value)
{
glUniform2fv(glGetUniformLocation(ID, name.c_str()), 1, value);
}
void Shader::setMatrix4f(const std::string& name, const float* value) void Shader::setMatrix4f(const std::string& name, const float* value)
{ {
GLuint loc = glGetUniformLocation(ID, name.c_str()); GLuint loc = glGetUniformLocation(ID, name.c_str());

View file

@ -3,6 +3,8 @@
#include "util.h" #include "util.h"
#include "utility/events.h" #include "utility/events.h"
bool Sprite::loaded() const { return (texture != nullptr); }
SpriteStatic::SpriteStatic(const char* texturePath) SpriteStatic::SpriteStatic(const char* texturePath)
{ {
EBO = 0, VBO = 0, VAO = 0; EBO = 0, VBO = 0, VAO = 0;
@ -10,6 +12,8 @@ SpriteStatic::SpriteStatic(const char* texturePath)
texture->loadTexture(texturePath); texture->loadTexture(texturePath);
if (texture) if (texture)
setupSprite(); setupSprite();
else
delete texture;
} }
void SpriteStatic::setupSprite() void SpriteStatic::setupSprite()
@ -71,6 +75,8 @@ SpriteAtlas::SpriteAtlas(const char* textureAtlasPath, float frameSize, bool isD
else else
SetupDirectional(frameSize); SetupDirectional(frameSize);
} }
else
delete texture;
} }
void SpriteAtlas::Setup(float frameSize) void SpriteAtlas::Setup(float frameSize)

View file

@ -1,25 +1,24 @@
#include "graphics/texture.h" #include "graphics/texture.h"
#include "utility/logger.h"
#include "util.h" #include "util.h"
#include <SDL_image.h> #include <SDL_image.h>
#include <iostream>
#include <glad/glad.h> #include <glad/glad.h>
bool Texture::loadTexture(const char* imagePath) bool Texture::loadTexture(const char* imagePath)
{ {
SDL_Surface* buffer = IMG_Load(imagePath); SDL_Surface* buffer = IMG_Load(imagePath);
if (!buffer) if (!buffer)
{ ERROR_LOG("Failed to load image file: {}", imagePath);
std::cout << "Failed to load image file: " << imagePath << std::endl;
return false;
}
//UTIL::flip_surface(buffer); //UTIL::flip_surface(buffer);
glGenTextures(1, &ID); glGenTextures(1, &ID);
/*
GLenum error = glGetError(); GLenum error = glGetError();
if(error != GL_NO_ERROR) { if(error != GL_NO_ERROR) {
std::cout << "OpenGL error: " << error << std::endl; std::cout << "OpenGL error: " << error << std::endl;
} }
*/
glBindTexture(GL_TEXTURE_2D, ID); glBindTexture(GL_TEXTURE_2D, ID);
@ -45,7 +44,115 @@ void Texture::bind()
glBindTexture(GL_TEXTURE_2D, ID); glBindTexture(GL_TEXTURE_2D, ID);
} }
Texture::~Texture() Texture::~Texture()
{ {
glDeleteTextures(1, &ID); glDeleteTextures(1, &ID);
} }
bool TextureArray::loadTextures(std::vector<const char*> imagePaths)
{
std::vector<SDL_Surface*> surfaces;
surfaces.resize(imagePaths.size());
// Fill surfaces vector
for (int i = 0; i < imagePaths.size(); ++i)
{
surfaces[i] = IMG_Load(imagePaths[i]);
if (!surfaces[i])
ERROR_LOG("Failed to load image file: {}", imagePaths[i]);
}
if (!adjustCanvasSizes(surfaces))
ERROR_LOG("Failed to adjust canvas size of images! \n Make sure to check that every tileset has square dimensions! (512x512, 756x756 ... etc)");
if (surfaces.empty())
ERROR_LOG("No surfaces created!");
numOfLayers = imagePaths.size();
glGenTextures(1, &ID);
glBindTexture(GL_TEXTURE_2D_ARRAY, ID);
// Creating the texture array all of our textures will live in.
// adjustCanvasSizes makes every image the same size, so we can just use the first
// surface in the list of surfaces
glTexImage3D(GL_TEXTURE_2D_ARRAY,
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)
{
glTexSubImage3D(GL_TEXTURE_2D_ARRAY,
0,
0, 0, layer,
surfaces[layer]->w,
surfaces[layer]->h,
1,
GL_RGBA,
GL_UNSIGNED_BYTE,
surfaces[layer]->pixels);
}
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
for (auto& surface : surfaces)
SDL_FreeSurface(surface);
surfaces.clear();
return true;
}
void TextureArray::bind()
{
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, ID);
}
bool TextureArray::adjustCanvasSizes(std::vector<SDL_Surface*>& surfaces)
{
int maxWidth = 0;
int maxHeight = 0;
for (auto& surface : surfaces)
{
if (surface->w != surface->h)
ERROR_LOG("Image must be a square!");
if (surface->w > maxWidth) maxWidth = surface->w;
if (surface->h > maxHeight) maxHeight = surface->h;
textures.push_back(new TextureData({ surface->w, surface->h }));
}
for (int i = 0; i < surfaces.size(); ++i)
{
SDL_Surface* canvas = SDL_CreateRGBSurface(0, maxWidth, maxHeight,
surfaces[i]->format->BitsPerPixel,
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_BlitSurface(surfaces[i], NULL, canvas, NULL);
SDL_FreeSurface(surfaces[i]);
surfaces[i] = canvas;
}
canvasWidth = maxWidth;
canvasHeight = maxHeight;
return true;
}
TextureArray::~TextureArray()
{
glDeleteTextures(1, &ID);
}

View file

@ -1,8 +1,8 @@
#include <SDL.h> #include <SDL.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 // TODO: Fix circular dependency issues, mostly with input.h needing gameactor.h and command.h
#include "gameplay/game.h" #include "gameplay/game.h"
@ -43,8 +43,8 @@ int main(int argc, char* args[])
while (game->getGameState() & GAME_RUNNING) while (game->getGameState() & GAME_RUNNING)
{ {
Uint64 curCounter = SDL_GetPerformanceCounter(); Uint64 curCounter = SDL_GetPerformanceCounter();
float deltaTime = ((curCounter - lastCounter) / freq); double deltaTime = ((curCounter - lastCounter) / freq);
deltaTime = (deltaTime < 10.f) ? deltaTime : 1.f; deltaTime = (deltaTime < 1.0) ? deltaTime : 1.0;
SDL_PollEvent(&e); SDL_PollEvent(&e);
if (e.type == SDL_QUIT) if (e.type == SDL_QUIT)
game->quit(); game->quit();

View file

@ -1,4 +1,5 @@
#include "utility/ftfont.h" #include "utility/ftfont.h"
#include "utility/logger.h"
#include <glad/glad.h> #include <glad/glad.h>
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
@ -97,6 +98,9 @@ bool Text::loadFonts(const std::string& font_folder)
} }
// load every font in the fonts folder then create corresponding textures for each character of each font. // load every font in the fonts folder then create corresponding textures for each character of each font.
std::filesystem::path folder(font_folder); std::filesystem::path folder(font_folder);
if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(font_folder))
ERROR_LOG("{} folder does not exist!", font_folder);
for (auto& file : std::filesystem::directory_iterator(folder)) for (auto& file : std::filesystem::directory_iterator(folder))
{ {
if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory()) if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory())

View file

@ -0,0 +1,14 @@
#include "utility/logger.h"
Logger* Logger::instance{ nullptr };
std::mutex Logger::mutex;
Logger* Logger::getInstance()
{
std::lock_guard<std::mutex> lock(mutex);
if (instance == nullptr)
{
instance = new Logger();
}
return instance;
}

View file

@ -22,6 +22,8 @@ std::shared_ptr<Sprite> ResourceManager::loadSpriteStatic(const std::string& pat
if (iterator != sprites.end()) if (iterator != sprites.end())
return iterator->second; return iterator->second;
auto sprite = std::make_shared<SpriteStatic>(path.c_str()); auto sprite = std::make_shared<SpriteStatic>(path.c_str());
if (!sprite->loaded())
return nullptr;
sprites[path] = sprite; sprites[path] = sprite;
return sprite; return sprite;
} }
@ -41,22 +43,30 @@ std::shared_ptr<TileSetData> ResourceManager::loadTileSet(const std::string& nam
return xmlLoader->getTileSetData(name); return xmlLoader->getTileSetData(name);
} }
std::shared_ptr<Shader> ResourceManager::loadShader(const std::string& name, const std::string& vertexPath, const std::string& fragPath) const unsigned ResourceManager::loadShader(const std::string& name, const std::string& vertexPath, const std::string& fragPath)
{ {
auto iterator = shaders.find(name); auto iterator = shaders.find(name);
if (iterator != shaders.end()) if (iterator != shaders.end())
return iterator->second; return iterator->second->ID;
auto shader = std::make_shared<Shader>(vertexPath.c_str(), fragPath.c_str()); auto shader = std::make_unique<Shader>(vertexPath.c_str(), fragPath.c_str());
shaders[name] = shader; unsigned id = shader->ID;
return shader; shaderIDs[shader->ID] = shader.get();
shaders[name] = std::move(shader);
return id;
}
Shader* ResourceManager::getShaderByID(unsigned int ID)
{
auto iterator = shaderIDs.find(ID);
return (iterator != shaderIDs.end() ? iterator->second : nullptr);
} }
// We attach our script after we create our weapon because we are passing a reference to the weapon into the script and we don't want to pass an // We attach our script after we create our weapon because we are passing a reference to the weapon into the script and we don't want to pass an
// incomplete reference to our script. // incomplete reference to our script.
std::shared_ptr<Weapon> ResourceManager::loadWeapon(const std::string& name, std::shared_ptr<Shader> weaponShader, std::shared_ptr<Shader> shader) std::shared_ptr<Weapon> ResourceManager::loadWeapon(const std::string& name, const unsigned weaponShaderID, const unsigned bulletShaderID)
{ {
std::shared_ptr<WeaponData> data = xmlLoader->getWeaponData(name); std::shared_ptr<WeaponData> data = xmlLoader->getWeaponData(name);
auto weapon = std::make_shared<Weapon>(data, weaponShader, shader, this); auto weapon = std::make_shared<Weapon>(data, weaponShaderID, bulletShaderID, this);
if (!data->script.empty()) if (!data->script.empty())
weapon->attachScript(loadWeaponScript(data->script)); weapon->attachScript(loadWeaponScript(data->script));
return weapon; return weapon;
@ -70,6 +80,7 @@ std::shared_ptr<SceneData> ResourceManager::loadScene(const std::string& id)
std::shared_ptr<AnimationSet> ResourceManager::loadAnimationSet(const std::string& name, int entityid) std::shared_ptr<AnimationSet> ResourceManager::loadAnimationSet(const std::string& name, int entityid)
{ {
auto animSetData = xmlLoader->getAnimationSet(name); auto animSetData = xmlLoader->getAnimationSet(name);
return std::make_shared<AnimationSet>(entityid, this, animSetData); return std::make_shared<AnimationSet>(entityid, this, animSetData);
} }
@ -91,6 +102,13 @@ void ResourceManager::clearResources()
{ {
sprites.clear(); sprites.clear();
shaders.clear(); shaders.clear();
shaderIDs.clear();
weapons.clear(); weapons.clear();
tileSets.clear(); tileSets.clear();
} }
ResourceManager::~ResourceManager()
{
clearResources();
xmlLoader.reset();
}

View file

@ -106,4 +106,5 @@ Script::Script(const std::string& path)
lua.open_libraries(sol::lib::base, sol::lib::math); lua.open_libraries(sol::lib::base, sol::lib::math);
registerGlobalUserTypes(); registerGlobalUserTypes();
loadScript(path); loadScript(path);
} }

View file

@ -1,5 +1,7 @@
#include "utility/xmlloader.h" #include "utility/xmlloader.h"
#include "utility/logger.h"
/* /*
Loading every scene in the scene folder and storing in hashmap scenes Loading every scene in the scene folder and storing in hashmap scenes
hashkey is the id of the scene hashkey is the id of the scene
@ -7,6 +9,8 @@
bool XMLLoader::loadScenes(const char* sceneFolder) bool XMLLoader::loadScenes(const char* sceneFolder)
{ {
std::filesystem::path folder(sceneFolder); std::filesystem::path folder(sceneFolder);
if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder))
ERROR_LOG("'{}' folder not found!", sceneFolder);
for (auto& file : std::filesystem::directory_iterator(folder)) for (auto& file : std::filesystem::directory_iterator(folder))
{ {
if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory()) if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory())
@ -26,26 +30,32 @@ bool XMLLoader::loadXmlScene(const char* xmlFile, SceneData* out)
{ {
tinyxml2::XMLDocument doc; tinyxml2::XMLDocument doc;
if (doc.LoadFile(xmlFile) != tinyxml2::XML_SUCCESS) if (doc.LoadFile(xmlFile) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Failed to load file: {}", xmlFile);
tinyxml2::XMLElement* scene = doc.FirstChildElement("scene"); tinyxml2::XMLElement* scene = doc.FirstChildElement("scene");
const char* type, * id, * mapName; const char* type, * id, * mapName, * bgFile;
if (scene->QueryStringAttribute("type", &type) != tinyxml2::XML_SUCCESS || if (scene->QueryStringAttribute("type", &type) != tinyxml2::XML_SUCCESS ||
scene->QueryStringAttribute("id", &id) != tinyxml2::XML_SUCCESS) scene->QueryStringAttribute("id", &id) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Could not read type or id tag in file: {}", xmlFile);
out->type = type; out->type = type;
out->id = id; out->id = id;
if (scene->QueryStringAttribute("bg", &bgFile) != tinyxml2::XML_SUCCESS)
LOG(WARN, "No background set! attribute 'bg' is empty");
else
out->bgFile = bgFile;
tinyxml2::XMLElement* map = scene->FirstChildElement("map"); tinyxml2::XMLElement* map = scene->FirstChildElement("map");
if (map == NULL) if (map == NULL)
return false; ERROR_LOG("Could not find 'map' tag in file: {}", xmlFile);
if (map->QueryStringAttribute("name", &mapName) != tinyxml2::XML_SUCCESS) if (map->QueryStringAttribute("name", &mapName) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Could not find attribute 'name' in map tag. file: {}", xmlFile)
if (!(out->map = getMapData(mapName))) if (!(out->map = getMapData(mapName)))
return false; return false;
if (!loadEntityData(xmlFile, out)) if (!loadEntityData(xmlFile, out))
return false; return false;
LOG(DEBUG, "Loading scene: {}", xmlFile);
return true; return true;
} }
@ -56,21 +66,21 @@ bool XMLLoader::loadEntityData(const char* xmlFile, SceneData* out)
{ {
tinyxml2::XMLDocument doc; tinyxml2::XMLDocument doc;
if (doc.LoadFile(xmlFile) != tinyxml2::XML_SUCCESS) if (doc.LoadFile(xmlFile) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Failed to load file: {}", xmlFile);
tinyxml2::XMLElement* entities = doc.FirstChildElement()->FirstChildElement("entities"); tinyxml2::XMLElement* entities = doc.FirstChildElement()->FirstChildElement("entities");
// Adding the player. Player must be in the scene or the scene will not load! // Adding the player. Player must be in the scene or the scene will not load!
tinyxml2::XMLElement* playerElement = entities->FirstChildElement("player"); tinyxml2::XMLElement* playerElement = entities->FirstChildElement("player");
if (playerElement == NULL) if (playerElement == NULL)
return false; ERROR_LOG("Player element not found in scene! File: {}", xmlFile);
EntityData playData; EntityData playData;
const char *graphic, *weaponName = "pistolGun"; const char *graphic, *weaponName = "pistolGun";
if (playerElement->QueryIntAttribute("x", &playData.x) != tinyxml2::XML_SUCCESS || if (playerElement->QueryIntAttribute("x", &playData.x) != tinyxml2::XML_SUCCESS ||
playerElement->QueryIntAttribute("y", &playData.y) != tinyxml2::XML_SUCCESS) playerElement->QueryIntAttribute("y", &playData.y) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Failed to find x or y attribute in 'player' tag. File: {}", xmlFile);
playerElement->QueryStringAttribute("weapon", &weaponName); playerElement->QueryStringAttribute("weapon", &weaponName);
tinyxml2::XMLElement* anim = playerElement->FirstChildElement("animation"); tinyxml2::XMLElement* anim = playerElement->FirstChildElement("animation");
if (anim == NULL) if (anim == NULL)
@ -78,33 +88,33 @@ bool XMLLoader::loadEntityData(const char* xmlFile, SceneData* out)
playData.animated = false; playData.animated = false;
tinyxml2::XMLElement* sprite = playerElement->FirstChildElement("sprite"); tinyxml2::XMLElement* sprite = playerElement->FirstChildElement("sprite");
if (sprite == NULL) if (sprite == NULL)
return false; ERROR_LOG("Could not find tag 'sprite' in 'player' tag. File: {}", xmlFile);
if (sprite->QueryStringAttribute("file", &graphic) != tinyxml2::XML_SUCCESS) if (sprite->QueryStringAttribute("file", &graphic) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Could not find attribute 'file' in 'player' -> 'sprite' tag. File: {}", xmlFile);
} }
else else
{ {
playData.animated = true; playData.animated = true;
if (anim->QueryStringAttribute("name", &graphic) != tinyxml2::XML_SUCCESS) if (anim->QueryStringAttribute("name", &graphic) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Could not find 'name' attribute in 'animation' tag. File: {}", xmlFile);
} }
playData.isPlayer = true; playData.isPlayer = true;
playData.graphic = graphic; playData.graphic = graphic;
playData.weapon = weaponName; playData.weapon = weaponName;
out->entities.push_back(playData); out->entities.push_back(playData);
LOG(DEBUG, "Loaded player with sprite: {} in file: {}", graphic, xmlFile);
// Adding every other entity... // Adding every other entity...
// TODO: Add npcs to game and enable their use with XMLLoader // TODO: Add npcs to game and enable their use with XMLLoader
for (tinyxml2::XMLElement* e = entities->FirstChildElement("entity"); e != NULL; e = e->NextSiblingElement("entity")) for (tinyxml2::XMLElement* e = entities->FirstChildElement("entity"); e != NULL; e = e->NextSiblingElement("entity"))
{ {
EntityData data; EntityData data;
const char *graphic, *weaponName = "pistolGun", *scriptPath; const char *graphic, *weaponName = "pistolGun", *scriptPath;
if (e->QueryIntAttribute("x", &data.x) != tinyxml2::XML_SUCCESS || if (e->QueryIntAttribute("x", &data.x) != tinyxml2::XML_SUCCESS ||
e->QueryIntAttribute("y", &data.y) != tinyxml2::XML_SUCCESS) e->QueryIntAttribute("y", &data.y) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Could not load position coordinates for entity. File: {}", xmlFile);
e->QueryStringAttribute("weapon", &weaponName); e->QueryStringAttribute("weapon", &weaponName);
tinyxml2::XMLElement* anim = e->FirstChildElement("animation"); tinyxml2::XMLElement* anim = e->FirstChildElement("animation");
if (anim == NULL) if (anim == NULL)
@ -154,7 +164,7 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
// We are gonna check every xml file within the weaponFolder, then check every weapon node within each file. // We are gonna check every xml file within the weaponFolder, then check every weapon node within each file.
std::filesystem::path folder(weaponFolder); std::filesystem::path folder(weaponFolder);
if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder)) if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder))
return false; ERROR_LOG("'{}' folder does not exist!", weaponFolder);
for (auto& file : std::filesystem::directory_iterator(folder)) for (auto& file : std::filesystem::directory_iterator(folder))
{ {
if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory()) if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory())
@ -261,6 +271,7 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
modifier->QueryFloatAttribute("max", &data.modMax); modifier->QueryFloatAttribute("max", &data.modMax);
} }
LOG(DEBUG, "Loaded {} from {}", data.name, file.path().filename().generic_string());
weapons.try_emplace(data.name, std::make_shared<WeaponData>(data)); weapons.try_emplace(data.name, std::make_shared<WeaponData>(data));
} }
} }
@ -274,19 +285,22 @@ bool XMLLoader::loadAnimations(const char* animationFolder)
{ {
std::filesystem::path folder(animationFolder); std::filesystem::path folder(animationFolder);
if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder)) if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder))
return false; ERROR_LOG("'{}' folder does not exist!", animationFolder);
for (auto& file : std::filesystem::directory_iterator(folder)) for (auto& file : std::filesystem::directory_iterator(folder))
{ {
if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory()) if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory())
continue; continue;
tinyxml2::XMLDocument doc; tinyxml2::XMLDocument doc;
if (doc.LoadFile(file.path().generic_string().c_str()) != tinyxml2::XML_SUCCESS) if (doc.LoadFile(file.path().generic_string().c_str()) != tinyxml2::XML_SUCCESS)
continue; continue;
tinyxml2::XMLElement* anims = doc.FirstChildElement("animations"); tinyxml2::XMLElement* anims = doc.FirstChildElement("animations");
bool directional = false; bool directional = false;
anims->QueryBoolAttribute("directional", &directional); anims->QueryBoolAttribute("directional", &directional);
if (anims == NULL) if (anims == NULL)
continue; continue;
for (tinyxml2::XMLElement* e = anims->FirstChildElement("animation"); e != NULL; e = e->NextSiblingElement("animation")) for (tinyxml2::XMLElement* e = anims->FirstChildElement("animation"); e != NULL; e = e->NextSiblingElement("animation"))
{ {
AnimationData animData; AnimationData animData;
@ -295,6 +309,7 @@ bool XMLLoader::loadAnimations(const char* animationFolder)
if (e->QueryStringAttribute("name", &name) != tinyxml2::XML_SUCCESS || if (e->QueryStringAttribute("name", &name) != tinyxml2::XML_SUCCESS ||
e->QueryStringAttribute("type", &type) != tinyxml2::XML_SUCCESS) e->QueryStringAttribute("type", &type) != tinyxml2::XML_SUCCESS)
continue; continue;
tinyxml2::XMLElement* fps = e->FirstChildElement("FPS"); tinyxml2::XMLElement* fps = e->FirstChildElement("FPS");
fps->QueryFloatText(&animData.FPS); fps->QueryFloatText(&animData.FPS);
@ -333,7 +348,7 @@ bool XMLLoader::loadTileSets(const char* tileSetFolder)
{ {
std::filesystem::path folder(tileSetFolder); std::filesystem::path folder(tileSetFolder);
if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder)) if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder))
return false; ERROR_LOG("'{}' folder failed to load!", tileSetFolder);
for (auto& file : std::filesystem::directory_iterator(folder)) for (auto& file : std::filesystem::directory_iterator(folder))
{ {
@ -347,11 +362,12 @@ bool XMLLoader::loadTileSets(const char* tileSetFolder)
if (tileSet == NULL) if (tileSet == NULL)
continue; continue;
TileSetData tileSetData; TileSetData tileSetData;
const char* setName, * setType, * setFile; const char* setName, * setType = "shooter", * setFile;
tileSet->QueryStringAttribute("class", &setType);
// Read attributes of tileset element // Read attributes of tileset element
if (tileSet->QueryStringAttribute("name", &setName) != tinyxml2::XML_SUCCESS || if (tileSet->QueryStringAttribute("name", &setName) != tinyxml2::XML_SUCCESS ||
tileSet->QueryStringAttribute("class", &setType) != tinyxml2::XML_SUCCESS ||
tileSet->QueryFloatAttribute("tilewidth", &tileSetData.tileSize) != tinyxml2::XML_SUCCESS || tileSet->QueryFloatAttribute("tilewidth", &tileSetData.tileSize) != tinyxml2::XML_SUCCESS ||
tileSet->QueryIntAttribute("tilecount", &tileSetData.tileCount) != tinyxml2::XML_SUCCESS || tileSet->QueryIntAttribute("tilecount", &tileSetData.tileCount) != tinyxml2::XML_SUCCESS ||
tileSet->QueryIntAttribute("columns", &tileSetData.columns) != tinyxml2::XML_SUCCESS) tileSet->QueryIntAttribute("columns", &tileSetData.columns) != tinyxml2::XML_SUCCESS)
@ -390,10 +406,10 @@ bool XMLLoader::loadTile(tinyxml2::XMLElement* tileElement, TileSetData::TileDat
const char* tileType; const char* tileType;
if (tileElement == NULL) if (tileElement == NULL)
return false; ERROR_LOG("Failed to find 'tile' tag.");
if (tileElement->QueryIntAttribute("id", &tileData.id) != tinyxml2::XML_SUCCESS || if (tileElement->QueryIntAttribute("id", &tileData.id) != tinyxml2::XML_SUCCESS ||
tileElement->QueryStringAttribute("type", &tileType) != tinyxml2::XML_SUCCESS) tileElement->QueryStringAttribute("type", &tileType) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Failed to load tile id or type. {}", tileElement->Value());
if (std::string(tileType).compare("object") == 0) if (std::string(tileType).compare("object") == 0)
{ {
@ -405,7 +421,7 @@ bool XMLLoader::loadTile(tinyxml2::XMLElement* tileElement, TileSetData::TileDat
*/ */
tinyxml2::XMLElement* objectGroup = tileElement->FirstChildElement("objectgroup"); tinyxml2::XMLElement* objectGroup = tileElement->FirstChildElement("objectgroup");
if (objectGroup == NULL) if (objectGroup == NULL)
return false; ERROR_LOG("Failed to find tag 'objectgroup' in tile id: {}", tileData.id);
for (tinyxml2::XMLElement* obj = objectGroup->FirstChildElement("object"); obj != NULL; obj = obj->NextSiblingElement("object")) for (tinyxml2::XMLElement* obj = objectGroup->FirstChildElement("object"); obj != NULL; obj = obj->NextSiblingElement("object"))
{ {
TileSetData::TileData::ObjectData objData; TileSetData::TileData::ObjectData objData;
@ -414,7 +430,7 @@ bool XMLLoader::loadTile(tinyxml2::XMLElement* tileElement, TileSetData::TileDat
tileData.objects.push_back(std::make_shared<TileSetData::TileData::ObjectData>(objData)); tileData.objects.push_back(std::make_shared<TileSetData::TileData::ObjectData>(objData));
} }
if (tileData.objects.empty()) if (tileData.objects.empty())
return false; ERROR_LOG("No objects found");
} }
else else
{ {
@ -445,19 +461,19 @@ bool XMLLoader::loadObject(tinyxml2::XMLElement* objElement, TileSetData::TileDa
// avoid null pointer exception // avoid null pointer exception
if (objElement == NULL) if (objElement == NULL)
return false; ERROR_LOG("Failed to find 'object' tag");
// load id and name // load id and name
if (objElement->QueryIntAttribute("id", &objData.id) != tinyxml2::XML_SUCCESS || if (objElement->QueryIntAttribute("id", &objData.id) != tinyxml2::XML_SUCCESS ||
objElement->QueryStringAttribute("name", &objName) != tinyxml2::XML_SUCCESS) objElement->QueryStringAttribute("name", &objName) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("No id or name found for object. {}", objElement->Value());
// load position into vec2 // load position into vec2
if (objElement->QueryFloatAttribute("x", &objData.pos.x) != tinyxml2::XML_SUCCESS || if (objElement->QueryFloatAttribute("x", &objData.pos.x) != tinyxml2::XML_SUCCESS ||
objElement->QueryFloatAttribute("y", &objData.pos.y) != tinyxml2::XML_SUCCESS) objElement->QueryFloatAttribute("y", &objData.pos.y) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Failed to load position coordinates for object: {}", objData.name);
// load size into seperate vec2 // load size into seperate vec2
if (objElement->QueryFloatAttribute("width", &objData.size.x) != tinyxml2::XML_SUCCESS || if (objElement->QueryFloatAttribute("width", &objData.size.x) != tinyxml2::XML_SUCCESS ||
objElement->QueryFloatAttribute("height", &objData.size.y) != tinyxml2::XML_SUCCESS) objElement->QueryFloatAttribute("height", &objData.size.y) != tinyxml2::XML_SUCCESS)
return false; ERROR_LOG("Failed to load size of object: {}", objData.name);
// refer to comment in XMLLoader::loadTile regarding the properties portion as to why we return true here // refer to comment in XMLLoader::loadTile regarding the properties portion as to why we return true here
tinyxml2::XMLElement* properties = objElement->FirstChildElement("properties"); tinyxml2::XMLElement* properties = objElement->FirstChildElement("properties");
@ -479,7 +495,7 @@ bool XMLLoader::loadMaps(const char* mapFolder)
{ {
std::filesystem::path folder(mapFolder); std::filesystem::path folder(mapFolder);
if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder)) if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder))
return false; ERROR_LOG("'{}' folder not found!", mapFolder);
for (auto& file : std::filesystem::directory_iterator(folder)) for (auto& file : std::filesystem::directory_iterator(folder))
{ {
@ -493,17 +509,23 @@ bool XMLLoader::loadMaps(const char* mapFolder)
if (map == NULL) if (map == NULL)
continue; continue;
MapData mapData; MapData mapData;
const char* tileSetPath;
if (map->QueryIntAttribute("width", &mapData.width) != tinyxml2::XML_SUCCESS || if (map->QueryIntAttribute("width", &mapData.width) != tinyxml2::XML_SUCCESS ||
map->QueryIntAttribute("height", &mapData.height) != tinyxml2::XML_SUCCESS || map->QueryIntAttribute("height", &mapData.height) != tinyxml2::XML_SUCCESS ||
map->QueryFloatAttribute("tilewidth", &mapData.tileSize) != tinyxml2::XML_SUCCESS) map->QueryFloatAttribute("tilewidth", &mapData.tileSize) != tinyxml2::XML_SUCCESS)
continue; continue;
tinyxml2::XMLElement* tileSet = map->FirstChildElement("tileset"); for (tinyxml2::XMLElement* tileSet = map->FirstChildElement("tileset"); tileSet != NULL; tileSet = tileSet->NextSiblingElement("tileset"))
if (tileSet == NULL) {
int firstGID = 0;
const char* tileSetPath;
if (tileSet->QueryStringAttribute("source", &tileSetPath) != tinyxml2::XML_SUCCESS ||
tileSet->QueryIntAttribute("firstgid", &firstGID) != tinyxml2::XML_SUCCESS)
continue; continue;
if (tileSet->QueryStringAttribute("source", &tileSetPath) != tinyxml2::XML_SUCCESS) mapData.tileSets.push_back({ firstGID, tileSetPath });
}
if (mapData.tileSets.empty())
continue; continue;
mapData.tiles.reserve(10); mapData.tiles.reserve(10);
@ -557,7 +579,6 @@ bool XMLLoader::loadMaps(const char* mapFolder)
/* TODO: Add object layer */ /* TODO: Add object layer */
mapData.name = file.path().stem().string(); mapData.name = file.path().stem().string();
mapData.tileSet = tileSetPath;
maps.try_emplace(mapData.name, std::make_shared<MapData>(mapData)); maps.try_emplace(mapData.name, std::make_shared<MapData>(mapData));
} }