1
0
mirror of https://github.com/sigonasr2/Shep.git synced 2026-08-18 05:43:22 -05:00

Implement object identifiers and player movement.

This commit is contained in:
sigonasr2 2025-08-26 04:38:53 -05:00
parent 65b6166972
commit b145bb07d0
17 changed files with 495 additions and 18 deletions

5
.gitignore vendored
View File

@ -73,7 +73,6 @@ x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
@ -275,8 +274,6 @@ _pkginfo.txt
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
@ -446,3 +443,5 @@ FodyWeavers.xsd
/CMakeFiles
/CMakeCache.txt
/assets/gfx/Cute RPG
/bin/assets/gfx/Cute RPG
/bin

View File

@ -37,4 +37,69 @@ Playtesting / Tweaks / Bugfixes
Multiple Puzzle Variations
Building 1: 8x6
Building 1: 8x6
Battle Mechanics:
Moves have a Color. When the Shep uses a move, their border shifts
into the color of the move they just used.
If a move hits an opponent of matching color, the damage is doubled.
Each move has a "Recharge time". Using the move before the recharge time
has finished makes it deal normal damage (%-based on full charge).
A move that is fully recharged deals 200% damage. Moves start with 1 charge.
Moves that do apply status effects only work when fully charged.
Capturing Mechanics:
The lower the health of the Shep being attacked, the higher the chance of capture.
From 5% at full health to 95% at lowest health.
For legendaries the capturing rate is halved.
For shinies the capturing rate is halved again.
Chance of a legendary encounter is 1% (1/100)
Each area has one legendary
Chance of a shiny encounter is 0.5% (1/200)
Hint Man
Everytime the day/night cycle shifts (every 6 minutes) the hint man will move
to one of a few predetermined spawn locations. If the player finds them they can
ask for a hint to solving the puzzle (after first encountering it).
First hint is free
Second hint costs 100 geometry stars (GS)
Every hint thereafter costs 200 GS
Each time you are shown a picture of the puzzle with one more slot solved.
When you go to solve it a faint overlay with the hint so far is shown.
Each shape defeated awards you with some GS. Some NPCs will ask if you want to trade Sheps.
Once traded, you are stuck with it, but may make it easier to unlock what you need.
Each locked area is comprised of multiple Shep:
First Area: 2 Shep
Second Area: 3 Shep (2 from second area, 1 from first)
Third Area: 4 Shep (3 from third area, 1 from second/first)
Final Area: 6 Shep (4 from final area, 1 from third, 1 from second/first)
In the final area, you will face legendary shep (6 in a row) at really high levels.
Take them out or capture them and proceed to the higher tiers.
Damage Formula:
PWR = Move Base Power
ATK = Shep Attack
MAX(PWR+PWR*(ATK*0.01)-PWR*(DEF*0.01),1)
Tackle 20 2
Rush 30 2
Flash Hit 20 3 Has priority
Scratch 20 2
Slash 40 3

View File

@ -354,6 +354,10 @@ if %errorlevel% neq 0 goto :VCEnd</Command>
<ClCompile Include="src\util.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\AnimationState.h">
<SubType>
</SubType>
</ClInclude>
<ClInclude Include="src\GameObject.h">
<SubType>
</SubType>
@ -377,6 +381,10 @@ if %errorlevel% neq 0 goto :VCEnd</Command>
</ClInclude>
<ClInclude Include="src\olcPGEX_MiniAudio.h" />
<ClInclude Include="src\olcPixelGameEngine.h" />
<ClInclude Include="src\olcUTIL_Animate2D.h">
<SubType>
</SubType>
</ClInclude>
<ClInclude Include="src\olcUTIL_Geometry2D.h" />
<ClInclude Include="src\olcUTIL_Hardware3D.h" />
<ClInclude Include="src\ShepGame.h">

View File

@ -68,5 +68,11 @@
<ClInclude Include="src\ObjectFlag.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\olcUTIL_Animate2D.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="src\AnimationState.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

BIN
bin/assets/gfx/Shep.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
bin/assets/gfx/Town1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.10.2" name="Collision" tilewidth="16" tileheight="16" tilecount="1" columns="1">
<image source="collision_tileset.png" width="16" height="16"/>
</tileset>

BIN
bin/assets/maps/Town1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

96
bin/assets/maps/Town1.tmx Normal file
View File

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.10" tiledversion="1.10.2" orientation="orthogonal" renderorder="right-down" width="35" height="24" tilewidth="16" tileheight="16" infinite="0" nextlayerid="6" nextobjectid="2">
<tileset firstgid="1" source="Village.tsx"/>
<tileset firstgid="1025" source="Collision.tsx"/>
<layer id="1" name="Tile Layer 1" width="35" height="24">
<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,33,34,34,34,34,34,34,34,34,34,34,34,35,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,67,0,0,0,0,4,34,34,34,34,34,34,5,0,0,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,69,34,34,34,34,68,66,66,66,66,66,66,69,5,0,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,69,35,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,67,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,67,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,67,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,67,0,0,0,0,0,0,0,
0,65,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,66,67,0,0,0,0,0,0,0,
0,97,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,98,99,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,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="2" name="Decorations" width="35" height="24">
<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,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,39,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,8,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,7,0,41,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,9,0,6,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,100,66,101,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,65,66,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,65,66,67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,289,290,290,290,290,324,322,325,290,290,290,290,290,290,290,291,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,289,290,324,322,322,322,322,322,322,322,322,322,322,322,322,322,322,323,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,321,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,323,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,321,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,323,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,289,290,324,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,323,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,321,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,323,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,321,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,322,323,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,353,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,354,355,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,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="5" name="Collision Layer" width="35" height="24" visible="0">
<data encoding="csv">
1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,1025,1025,1025,0,0,0,0,0,0,0,0,1025,1025,0,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,1025,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,
1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,
1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,
0,0,0,0,0,0,0,1025,1025,1025,1025,1025,1025,0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,1025,1025,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,
0,0,0,1025,1025,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,
0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,
0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,
0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,
0,0,0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1025,0,0,0,0,0,0,0,0,0,0,
0,0,0,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,1025,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<objectgroup id="4" name="Object Layer 1" visible="0">
<object id="1" type="Building" x="64" y="48" width="128" height="96">
<properties>
<property name="Building Type" propertytype="Buildings" value="building1"/>
</properties>
</object>
</objectgroup>
</map>

Binary file not shown.

After

Width:  |  Height:  |  Size: 609 B

46
src/AnimationState.h Normal file
View File

@ -0,0 +1,46 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2024 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#pragma once
enum class AnimationState{
STAND,
WALK_N,
WALK_E,
WALK_S,
WALK_W,
};

View File

@ -36,12 +36,12 @@ All rights reserved.
*/
#pragma endregion
#include "ShepGame.h"
#include "GameObject.h"
#include "GameSettings.h"
GameObject::GameObject(const vf3d&pos,const vf3d&scale,const std::string&spriteMeshName,const MeshType&type)
:pos(pos),scale(scale),spriteMeshName(spriteMeshName),type(type){};
GameObject::GameObject(const vf3d&pos,const vf3d&scale,const ObjectID&id,const std::string&spriteMeshName,const MeshType&type)
:pos(pos),scale(scale),id(id),spriteMeshName(spriteMeshName),type(type){};
const MeshType GameObject::GetMeshType()const{
return type;
@ -82,4 +82,18 @@ void GameObject::SetAutoScale(const vf2d&unitDivision){
const vf2d imgSize{spr.Sprite()->Size()};
scale.x=imgSize.x/unitDivision.x;
scale.z=imgSize.y/unitDivision.y;
}
void GameObject::Update(const float&fElapsedTime){
if(anim)ShepGame::Game().animation.UpdateState(*anim,fElapsedTime);
auto&game{ShepGame::Game()};
switch(id){
case ObjectID::PLAYER:{
if(game.GetKey(Key::W).bHeld){pos.z-=fElapsedTime*GameSettings::playerSpd;}
if(game.GetKey(Key::A).bHeld){pos.x-=fElapsedTime*GameSettings::playerSpd;}
if(game.GetKey(Key::S).bHeld){pos.z+=fElapsedTime*GameSettings::playerSpd;}
if(game.GetKey(Key::D).bHeld){pos.x+=fElapsedTime*GameSettings::playerSpd;}
}break;
}
}

View File

@ -38,10 +38,18 @@ All rights reserved.
#pragma once
#include "MeshType.h"
#include "olcUTIL_Animate2D.h"
#include "AnimationState.h"
class GameObject{
public:
GameObject(const vf3d&pos,const vf3d&scale,const std::string&spriteMeshName,const MeshType&type);
enum class ObjectID{
DEFAULT,
PLAYER,
};
GameObject(const vf3d&pos,const vf3d&scale,const ObjectID&id,const std::string&spriteMeshName,const MeshType&type);
void Update(const float&fElapsedTime);
const MeshType GetMeshType()const;
const hw3d::mesh&GetMesh()const;
const vf3d&GetPos()const;
@ -51,6 +59,9 @@ public:
private:
vf3d pos;
vf3d scale;
ObjectID id;
std::string spriteMeshName;
MeshType type;
AnimationState state;
std::optional<Animate2D::AnimationState>anim;
};

View File

@ -39,6 +39,8 @@ All rights reserved.
class GameSettings{
public:
inline static bool LIGHTS_VISIBLE{true};
inline static bool DEBUG_CAMERA{true};
inline static constexpr bool LIGHTS_VISIBLE{true};
inline static constexpr bool DEBUG_CAMERA{true};
inline static constexpr float playerSpd{5.f};
};

View File

@ -49,7 +49,7 @@ void ShepGame::LoadSprite(const std::string&filename){
assets[filename].Load("assets/gfx/"+filename);
}
GameObject&ShepGame::AddGameObject(const vf3d&pos,const vf3d&scale,const std::string&spriteMeshName,const MeshType&type){
GameObject&ShepGame::AddGameObject(const vf3d&pos,const vf3d&scale,const GameObject::ObjectID&id,const std::string&spriteMeshName,const MeshType&type){
switch(type){
case MeshType::FLOOR:
case MeshType::SPRITE:{
@ -59,7 +59,7 @@ GameObject&ShepGame::AddGameObject(const vf3d&pos,const vf3d&scale,const std::st
if(!meshes.count(spriteMeshName.substr(0,spriteMeshName.length()-4)+".obj"))LoadObj("building1.obj");
}break;
}
return objects.emplace_back(pos,scale,spriteMeshName,type);
return objects.emplace_back(pos,scale,id,spriteMeshName,type);
}
void ShepGame::AddLight(const Light&light){
@ -99,10 +99,8 @@ bool ShepGame::OnUserCreate(){
LoadMap("Town1.tmx");
for(int i:std::ranges::iota_view(0,3)){
AddGameObject({float(i),0,0},{1,2,1},"nico-Trapper_512.png",MeshType::SPRITE);
}
auto&town{AddGameObject({0,0,0},{1,1,1},"Town1.png",MeshType::FLOOR)};
AddGameObject({0,0,0},{1,2,1},GameObject::ObjectID::PLAYER,"nico-Trapper_512.png",MeshType::SPRITE);
auto&town{AddGameObject({0,0,0},{1,1,1},GameObject::ObjectID::DEFAULT,"Town1.png",MeshType::FLOOR)};
town.SetAutoScale({16,16});
AddLight({{4,0,10},WHITE});
@ -135,7 +133,7 @@ void ShepGame::LoadMap(const std::string&filename){
for(const XMLTag&tag:zone.properties){
const auto&data{tag.data};
if(data.at("name")=="Building Type"){
AddGameObject({float(spawnCoords.x),0,float(spawnCoords.y)},{1,1,1},data.at("value")+".png",MeshType::OBJ);
AddGameObject({float(spawnCoords.x),0,float(spawnCoords.y)},{1,1,1},GameObject::ObjectID::DEFAULT,data.at("value")+".png",MeshType::OBJ);
}
}
@ -218,6 +216,7 @@ bool ShepGame::OnUserUpdate(float fElapsedTime){
for(GameObject&obj:objects){
Render3DModel(obj);
obj.Update(fElapsedTime);
}
if(GameSettings::LIGHTS_VISIBLE){

View File

@ -49,7 +49,7 @@ class ShepGame : public olc::PixelGameEngine
{
public:
ShepGame();
GameObject&AddGameObject(const vf3d&pos,const vf3d&scale,const std::string&spriteMeshName,const MeshType&type); //Auto handles resources management! You do not have to add the sprites yourself (via LoadSprite)
GameObject&AddGameObject(const vf3d&pos,const vf3d&scale,const GameObject::ObjectID&id,const std::string&spriteMeshName,const MeshType&type); //Auto handles resources management! You do not have to add the sprites yourself (via LoadSprite)
void AddLight(const Light&light);
const Renderable&GetSpr(const std::string&filename)const;
const hw3d::mesh&GetMesh(const std::string&filename)const;
@ -57,6 +57,7 @@ public:
const hw3d::mesh&GetSpriteMesh()const;
static ShepGame&Game();
void LoadMap(const std::string&filename);
Animate2D::Animation<AnimationState>animation;
private:
static ShepGame*game;

226
src/olcUTIL_Animate2D.h Normal file
View File

@ -0,0 +1,226 @@
/*
OneLoneCoder - Animate2D v1.01
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Handles animated Sprites efficiently
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2018 - 2024 OneLoneCoder.com
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions or derivations of source code must retain the above
copyright notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce
the above copyright notice. This list of conditions and the following
disclaimer must be reproduced in the documentation and/or other
materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Links
~~~~~
YouTube: https://www.youtube.com/javidx9
Discord: https://discord.gg/WhwHUMV
Twitter: https://www.twitter.com/javidx9
Twitch: https://www.twitch.tv/javidx9
GitHub: https://www.github.com/onelonecoder
Homepage: https://www.onelonecoder.com
Author
~~~~~~
David Barr, aka javidx9, ©OneLoneCoder 2019, 2020, 2021, 2022, 2023, 2024
Versions
~~~~~~~~
1.01 +PingPong Style Animation
*/
#pragma once
#include "olcUTIL_Geometry2D.h"
#include "olcPixelGameEngine.h"
#include <unordered_map>
namespace olc::utils::Animate2D
{
// This class rerpresents a valid "frame" of an animation. It could be from any image source, and
// any location withing that image source. Once it's constructed, it's advised not to change it, as
// this likely indicates a usage bug.
//
// "Sourceless" frames are valid too - this is useful if you have a particular animation set, but
// want to apply it to a variety of sources, for example sprite maps with common layouts.
class Frame
{
public:
inline Frame(const olc::Renderable* gfxSource, const geom2d::rect<int32_t>& rectSource = { {0,0},{0,0} })
: gfxImageSource(gfxSource), rectFrameSource(rectSource)
{
// If no source rectangle specified then use whole image source. Ignore in the event
// that a frame is set up as source-less
if(gfxSource && rectFrameSource.size.x == 0)
rectFrameSource.size = gfxSource->Sprite()->Size();
}
inline const olc::Renderable* GetSourceImage() const
{
return gfxImageSource;
}
inline const geom2d::rect<int32_t>& GetSourceRect() const
{
return rectFrameSource;
}
inline const geom2d::rect<float>& GetSourceUV() const
{
return geom2d::rect<float>{vf2d{rectFrameSource.pos}/gfxImageSource->Sprite()->Size(),vf2d{rectFrameSource.size}/gfxImageSource->Sprite()->Size()};
}
private:
const olc::Renderable* gfxImageSource;
geom2d::rect<int32_t> rectFrameSource;
};
// Animation styles decide how the frames should be traversed in time
enum class Style : uint8_t
{
Repeat, // Cycle through, go back to beginning
OneShot, // Play once and suspend on final frame
PingPong, // Traverse through forwards, then backwards
Reverse, // Cycle through sequence backwards
};
class FrameSequence
{
public:
// Constructs a sequence of frames with a duration and a traversal style
inline FrameSequence(const float fFrameDuration = 0.1f, const Style nStyle = Style::Repeat)
{
m_fFrameDuration = fFrameDuration;
m_fFrameRate = 1.0f / m_fFrameDuration;
m_nStyle = nStyle;
}
// Adds a frame to this sequence
inline void AddFrame(const Frame& frame)
{
m_vFrames.emplace_back(frame);
}
// Returns a Frame Object for a given time into an animation
inline const Frame& GetFrame(const float fTime) const
{
return m_vFrames[ConvertTimeToFrame(fTime)];
}
private:
Style m_nStyle;
std::vector<Frame> m_vFrames;
float m_fFrameDuration = 0.1f;
float m_fFrameRate = 10.0f;
inline const size_t ConvertTimeToFrame(const float fTime) const
{
switch (m_nStyle)
{
case Style::Repeat:
return size_t(fTime * m_fFrameRate) % m_vFrames.size();
break;
case Style::OneShot:
return std::clamp(size_t(fTime * m_fFrameRate), size_t(0), m_vFrames.size() - 1);
break;
case Style::PingPong:
{
// Thanks @sigonasr2 (discord)
size_t frame = size_t(m_fFrameRate * fTime) % (m_vFrames.size() * 2 - 1);
return frame >= m_vFrames.size() ? m_vFrames.size() - frame % m_vFrames.size() - 1 : frame;
}
break;
case Style::Reverse:
return (m_vFrames.size() - 1) - (size_t(fTime * m_fFrameRate) % m_vFrames.size());
break;
}
return 0;
}
};
// A Animate2D::State is a lightweight token that can be attached to things
// that are animated. Under normal circumstances, it is never updated manually
struct AnimationState
{
private:
size_t nIndex = 0;
float fTime = 0.0f;
template<typename StatesEnum>
friend class Animation;
};
// Animation object holds a group of frame sequences and can mutate an AnimationState token
template<typename StatesEnum>
class Animation
{
public:
Animation() = default;
// Change an animation state token to a new state
inline bool ChangeState(AnimationState& state, const StatesEnum& sStateName) const
{
size_t idx = m_mapStateIndices.at(sStateName);
if (state.nIndex != idx)
{
state.fTime = 0.0f;
state.nIndex = idx;
return true;
}
return false;
}
// Update an animation state token
inline void UpdateState(AnimationState& state, const float fElapsedTime) const
{
state.fTime += fElapsedTime;
}
public:
// Retrieve the frame information for a given animation state
inline const Frame& GetFrame(const AnimationState& state) const
{
return m_vSequences[state.nIndex].GetFrame(state.fTime);
}
public:
// Add a named Frame sequence as a state
inline void AddState(const StatesEnum& sStateName, const FrameSequence& sequence)
{
m_vSequences.emplace_back(sequence);
m_mapStateIndices[sStateName] = m_vSequences.size() - 1;
}
private:
std::vector<FrameSequence> m_vSequences;
std::unordered_map<StatesEnum, size_t> m_mapStateIndices;
};
}