Revamped animation system
Smoother reloading Added idle atlas for player
This commit is contained in:
parent
90a843946a
commit
846f85f1f6
28 changed files with 836 additions and 302 deletions
6
Resources/animations/bubble_anim.xml
Normal file
6
Resources/animations/bubble_anim.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<animations>
|
||||||
|
<animation name="bubble_idle_anim" type="idle">
|
||||||
|
<FPS>2</FPS>
|
||||||
|
<sprite path="sprites/bubbleoAtlas64.png" frameSize="64.0"/>
|
||||||
|
</animation>
|
||||||
|
</animations>
|
||||||
10
Resources/animations/machine_gun_anim.xml
Normal file
10
Resources/animations/machine_gun_anim.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<animations>
|
||||||
|
<animation name="machine_gun_idle_anim" type="idle">
|
||||||
|
<FPS>4</FPS>
|
||||||
|
<sprite path="sprites/machineGunAtlas256.png" frameSize="256.0"/>
|
||||||
|
</animation>
|
||||||
|
<animation name="machine_gun_reload_anim" type="reload">
|
||||||
|
<FPS>2</FPS>
|
||||||
|
<sprite path="sprites/pistolAtlas256.png" frameSize="256.0"/>
|
||||||
|
</animation>
|
||||||
|
</animations>
|
||||||
6
Resources/animations/pistol_anim.xml
Normal file
6
Resources/animations/pistol_anim.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<animations>
|
||||||
|
<animation name="pistol_idle_anim" type="idle">
|
||||||
|
<FPS>4</FPS>
|
||||||
|
<sprite path="sprites/pistolAtlas256.png" frameSize="256.0"/>
|
||||||
|
</animation>
|
||||||
|
</animations>
|
||||||
11
Resources/animations/player_anim.xml
Normal file
11
Resources/animations/player_anim.xml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
<animations directional="true">
|
||||||
|
<animation name="player_move_anim" type="move">
|
||||||
|
<FPS>7</FPS>
|
||||||
|
<sprite path="sprites/player3AtlasMove64.png" frameSize="64.0"/>
|
||||||
|
</animation>
|
||||||
|
|
||||||
|
<animation name="player_idle_anim" type="idle">
|
||||||
|
<FPS>5</FPS>
|
||||||
|
<sprite path="sprites/player3AtlasIdle64.png" frameSize="64.0"/>
|
||||||
|
</animation>
|
||||||
|
</animations>
|
||||||
6
Resources/animations/tmp_enemy_anim.xml
Normal file
6
Resources/animations/tmp_enemy_anim.xml
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
<animations>
|
||||||
|
<animation name="tmp_enemy_move_anim" type="move">
|
||||||
|
<FPS>7</FPS>
|
||||||
|
<sprite path="sprites/player2Atlas.png" frameSize="128.0"/>
|
||||||
|
</animation>
|
||||||
|
</animations>
|
||||||
|
|
@ -35,18 +35,18 @@
|
||||||
</map>
|
</map>
|
||||||
<entities>
|
<entities>
|
||||||
<player x="7" y="5" weapon="shotGun">
|
<player x="7" y="5" weapon="shotGun">
|
||||||
<sprite file="sprites/player3Atlas.png" framesize="64.0" directional="true"/>
|
<animation name="player_anim"/>
|
||||||
</player>
|
</player>
|
||||||
<entity x="10" y="3" weapon="pistolGun">
|
<entity x="10" y="3" weapon="pistolGun">
|
||||||
<sprite file="sprites/player3Atlas.png" frameSize="64.0" directional="true"/>
|
<animation name="player_anim"/>
|
||||||
<script file="scripts/ai/grunt_behaviour.lua"/>
|
<script file="scripts/ai/grunt_behaviour.lua"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity x="6" y="3" weapon="pistolGun">
|
<entity x="6" y="3" weapon="pistolGun">
|
||||||
<sprite file="sprites/player2Atlas.png" frameSize="128.0"/>
|
<animation name="tmp_enemy_anim"/>
|
||||||
<script file="scripts/ai/grunt_behaviour.lua"/>
|
<script file="scripts/ai/grunt_behaviour.lua"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity x="5" y="3" weapon="pistolGun">
|
<entity x="5" y="3" weapon="pistolGun">
|
||||||
<sprite file="sprites/player2Atlas.png" frameSize="128.0"/>
|
<animation name="tmp_enemy_anim"/>
|
||||||
<script file="scripts/ai/grunt_behaviour.lua"/>
|
<script file="scripts/ai/grunt_behaviour.lua"/>
|
||||||
</entity>
|
</entity>
|
||||||
</entities>
|
</entities>
|
||||||
|
|
|
||||||
BIN
Resources/sprites/player3AtlasIdle64.png
Normal file
BIN
Resources/sprites/player3AtlasIdle64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
Resources/sprites/player3AtlasMove64.png
Normal file
BIN
Resources/sprites/player3AtlasMove64.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
|
|
@ -1,8 +1,8 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<weapons>
|
<weapons>
|
||||||
<weapon name="bubbleGun" fireSpeed="100.0">
|
<weapon name="bubbleGun" fireSpeed="100.0" maxAmmo="40000" clipSize="1000">
|
||||||
<bullet sprite="sprites/bubbleoAtlas64.png" animated="true" frameSize="64.0">
|
<bullet anim="bubble_anim">
|
||||||
<spread>60</spread>
|
<spread>60</spread>
|
||||||
<speed>20.0</speed>
|
<speed>20.0</speed>
|
||||||
<drop>250.0</drop>
|
<drop>250.0</drop>
|
||||||
|
|
@ -11,13 +11,13 @@
|
||||||
</bullet>
|
</bullet>
|
||||||
</weapon>
|
</weapon>
|
||||||
|
|
||||||
<weapon name="shotGun" fireSpeed="750.0">
|
<weapon name="shotGun" fireSpeed="750.0" maxAmmo="64" clipSize="4">
|
||||||
<script file="scripts/weapons/shotgun_script.lua"/>
|
<script file="scripts/weapons/shotgun_script.lua"/>
|
||||||
<sprite file="sprites/machineGunAtlas256.png" animated="true" frameSize="256.0">
|
<animation name="machine_gun_anim">
|
||||||
<size x="55.0" y="55.0"/>
|
<size x="55.0" y="55.0"/>
|
||||||
<offset x="-30.0" y="0.0"/>
|
<offset x="-30.0" y="0.0"/>
|
||||||
</sprite>
|
</animation>
|
||||||
<bullet sprite="sprites/bullet.png" animated="false" frameSize="64.0">
|
<bullet sprite="sprites/bullet.png">
|
||||||
<spread>50</spread>
|
<spread>50</spread>
|
||||||
<speed>60.0</speed>
|
<speed>60.0</speed>
|
||||||
<drop>550.0</drop>
|
<drop>550.0</drop>
|
||||||
|
|
@ -26,12 +26,12 @@
|
||||||
</bullet>
|
</bullet>
|
||||||
</weapon>
|
</weapon>
|
||||||
|
|
||||||
<weapon name="machineGun" fireSpeed="50.0">
|
<weapon name="machineGun" fireSpeed="50.0" maxAmmo="512" clipSize="64">
|
||||||
<sprite file="sprites/machineGunAtlas256.png" animated="true" frameSize="256.0">
|
<animation name="machine_gun_anim">
|
||||||
<size x="55.0" y="55.0"/>
|
<size x="55.0" y="55.0"/>
|
||||||
<offset x="-30.0" y="0.0"/>
|
<offset x="-30.0" y="0.0"/>
|
||||||
</sprite>
|
</animation>
|
||||||
<bullet sprite="sprites/bullet.png" animated="false" frameSize="64.0">
|
<bullet sprite="sprites/bullet.png">
|
||||||
<spread>20</spread>
|
<spread>20</spread>
|
||||||
<speed>60.0</speed>
|
<speed>60.0</speed>
|
||||||
<drop>950.0</drop>
|
<drop>950.0</drop>
|
||||||
|
|
@ -40,12 +40,12 @@
|
||||||
</bullet>
|
</bullet>
|
||||||
</weapon>
|
</weapon>
|
||||||
|
|
||||||
<weapon name="pistolGun" fireSpeed="750.0">
|
<weapon name="pistolGun" fireSpeed="750.0" maxAmmo="512" clipSize="21">
|
||||||
<sprite file="sprites/pistolAtlas256.png" animated="true" frameSize="256.0">
|
<animation name="pistol_anim">
|
||||||
<size x="30.0" y="30.0"/>
|
<size x="30.0" y="30.0"/>
|
||||||
<offset x="0.0" y="0.0"/>
|
<offset x="0.0" y="0.0"/>
|
||||||
</sprite>
|
</animation>
|
||||||
<bullet sprite="sprites/bullet.png" animated="false" frameSize="64.0">
|
<bullet sprite="sprites/bullet.png">
|
||||||
<spread>5.0</spread>
|
<spread>5.0</spread>
|
||||||
<speed>50.0</speed>
|
<speed>50.0</speed>
|
||||||
<drop>500.0</drop>
|
<drop>500.0</drop>
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,7 @@ 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")
|
||||||
|
|
||||||
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>)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
#include <SDL_timer.h>
|
||||||
|
|
||||||
#include "graphics/shader.h"
|
#include "graphics/shader.h"
|
||||||
|
|
||||||
|
|
@ -19,7 +20,9 @@ public:
|
||||||
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())
|
||||||
|
{};
|
||||||
virtual ~Entity() {};
|
virtual ~Entity() {};
|
||||||
|
|
||||||
void setPosition(const glm::vec3& position);
|
void setPosition(const glm::vec3& position);
|
||||||
|
|
@ -39,6 +42,7 @@ public:
|
||||||
const glm::vec2 getFacingDir() const { return glm::vec2(cos(glm::radians(rotation)), sin(glm::radians(rotation))); }
|
const glm::vec2 getFacingDir() const { return glm::vec2(cos(glm::radians(rotation)), sin(glm::radians(rotation))); }
|
||||||
const glm::vec3 getCenter() const { return glm::vec3(position.x + (0.5f * scale.x), position.y + (0.5f * scale.y), 0.0f); }
|
const glm::vec3 getCenter() const { return glm::vec3(position.x + (0.5f * scale.x), position.y + (0.5f * scale.y), 0.0f); }
|
||||||
const bool getIsMoving() const { return isMoving; }
|
const bool getIsMoving() const { return isMoving; }
|
||||||
|
const int getEntityID() const { return entityid; }
|
||||||
const std::shared_ptr<PhysicsComponent> getPhysicsComponent() const { return physics; }
|
const std::shared_ptr<PhysicsComponent> getPhysicsComponent() const { return physics; }
|
||||||
|
|
||||||
// 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
|
||||||
|
|
@ -53,9 +57,12 @@ protected:
|
||||||
float rotation;
|
float rotation;
|
||||||
float speed;
|
float speed;
|
||||||
|
|
||||||
|
int entityid;
|
||||||
|
|
||||||
std::shared_ptr<PhysicsComponent> physics;
|
std::shared_ptr<PhysicsComponent> physics;
|
||||||
|
|
||||||
bool isMoving = false;
|
bool isMoving = false;
|
||||||
|
bool wasMoving = false;
|
||||||
bool isRotatable = true;
|
bool isRotatable = true;
|
||||||
bool flipped = false;
|
bool flipped = false;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class EventManager;
|
||||||
class GameActor : public Entity
|
class GameActor : public Entity
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GameActor(const std::shared_ptr<Shader>& shader) : Entity(shader) { actorid = SDL_GetTicks(); }
|
GameActor(const std::shared_ptr<Shader>& shader) : Entity(shader) {}
|
||||||
~GameActor();
|
~GameActor();
|
||||||
|
|
||||||
void addComponent(std::shared_ptr<Component> component);
|
void addComponent(std::shared_ptr<Component> component);
|
||||||
|
|
@ -28,8 +28,7 @@ public:
|
||||||
void update(float deltaTime) override;
|
void update(float deltaTime) override;
|
||||||
void render(const std::shared_ptr<Camera>& camera) override;
|
void render(const std::shared_ptr<Camera>& camera) override;
|
||||||
|
|
||||||
const std::optional<std::shared_ptr<Weapon>>& getHeldWeapon() const;
|
const std::optional<std::shared_ptr<Weapon>> getHeldWeapon() const;
|
||||||
const int getActorID() const { return actorid; }
|
|
||||||
|
|
||||||
void setRotation(const float& rotation) override;
|
void setRotation(const float& rotation) override;
|
||||||
|
|
||||||
|
|
@ -52,7 +51,6 @@ private:
|
||||||
using component_vector_t = std::vector<std::shared_ptr<Component>>;
|
using component_vector_t = std::vector<std::shared_ptr<Component>>;
|
||||||
using weapon_vector_t = std::vector<std::shared_ptr<Weapon>>;
|
using weapon_vector_t = std::vector<std::shared_ptr<Weapon>>;
|
||||||
|
|
||||||
int actorid;
|
|
||||||
component_vector_t components;
|
component_vector_t components;
|
||||||
weapon_vector_t weapons;
|
weapon_vector_t weapons;
|
||||||
size_t currentWeaponIndex = 0;
|
size_t currentWeaponIndex = 0;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
class Component;
|
class Component;
|
||||||
|
class AnimationSet;
|
||||||
class Camera;
|
class Camera;
|
||||||
|
|
||||||
class Bullet : public Entity
|
class Bullet : public Entity
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ public:
|
||||||
Weapon(const WeaponData* data, const std::shared_ptr<Shader>& weaponShader, const std::shared_ptr<Shader>& bulletShader, ResourceManager* resourceManager);
|
Weapon(const WeaponData* data, const std::shared_ptr<Shader>& weaponShader, const std::shared_ptr<Shader>& bulletShader, 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 wield() { wielded = true; }
|
void wield() { wielded = true; }
|
||||||
void putaway() { wielded = false; }
|
void putaway() { wielded = false; }
|
||||||
|
|
||||||
|
|
@ -37,16 +38,17 @@ public:
|
||||||
void attachScript(const std::shared_ptr<WeaponScript>& script);
|
void attachScript(const std::shared_ptr<WeaponScript>& script);
|
||||||
void hookEventManager(const std::shared_ptr<EventManager>& eventManager);
|
void hookEventManager(const std::shared_ptr<EventManager>& eventManager);
|
||||||
void shoot();
|
void shoot();
|
||||||
|
void reload();
|
||||||
void update(float deltaTime);
|
void update(float deltaTime);
|
||||||
void render(const std::shared_ptr<Camera>& camera);
|
void render(const std::shared_ptr<Camera>& camera);
|
||||||
|
|
||||||
struct BulletData {
|
struct BulletData {
|
||||||
glm::vec3 origin;
|
glm::vec3 origin;
|
||||||
glm::vec2 direction;
|
glm::vec2 direction;
|
||||||
float mass;
|
float mass = 1.f;
|
||||||
float sizeMod;
|
float sizeMod = 1.f;
|
||||||
float speedMod;
|
float speedMod = 1.f;
|
||||||
float dropMod;
|
float dropMod = 1.f;
|
||||||
};
|
};
|
||||||
void onHitCallback(std::shared_ptr<GameActor> target, std::shared_ptr<PhysicsComponent> bullet, const glm::vec2& normal);
|
void onHitCallback(std::shared_ptr<GameActor> target, std::shared_ptr<PhysicsComponent> bullet, const glm::vec2& normal);
|
||||||
|
|
||||||
|
|
@ -66,6 +68,12 @@ private:
|
||||||
|
|
||||||
glm::vec2 weaponSize;
|
glm::vec2 weaponSize;
|
||||||
glm::vec2 weaponOffset;
|
glm::vec2 weaponOffset;
|
||||||
|
// TODO: Add reloading
|
||||||
|
// weaponMag will be unused for now, but we will do a reload animation and reload the weapon eventually
|
||||||
|
Uint16 weaponMag, weaponMagSize, weaponAmmo;
|
||||||
|
bool reloading = false;
|
||||||
|
bool wasReloading = false;
|
||||||
|
bool infiniteAmmo = false;
|
||||||
|
|
||||||
float bulletSpeed;
|
float bulletSpeed;
|
||||||
float bulletDrop;
|
float bulletDrop;
|
||||||
|
|
|
||||||
102
YuppleMayham/include/graphics/animation.h
Normal file
102
YuppleMayham/include/graphics/animation.h
Normal file
|
|
@ -0,0 +1,102 @@
|
||||||
|
#ifndef _H_ANIMATION_H
|
||||||
|
#define _H_ANIMATION_H
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <SDL_timer.h>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "utility/direction.h"
|
||||||
|
|
||||||
|
class SpriteAtlas;
|
||||||
|
class ResourceManager;
|
||||||
|
class EventManager;
|
||||||
|
|
||||||
|
// Each entity will contain animation data,
|
||||||
|
// this data will hold:
|
||||||
|
// name of the animation,
|
||||||
|
// type of animation ie. idle animation, directional, etc.
|
||||||
|
// directory of the animation atlas containing the frames
|
||||||
|
struct AnimationData;
|
||||||
|
|
||||||
|
class Animation
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Animation(const std::shared_ptr<AnimationData>& animData, ResourceManager* resourceManager);
|
||||||
|
|
||||||
|
std::string getName() const { return animName; }
|
||||||
|
std::string getType() const { return animType; }
|
||||||
|
|
||||||
|
void bind();
|
||||||
|
void draw();
|
||||||
|
void draw(Direction dir);
|
||||||
|
|
||||||
|
void play() { isPlaying = true; }
|
||||||
|
void stop() { isPlaying = false; }
|
||||||
|
|
||||||
|
const bool getPlaying() const { return isPlaying; }
|
||||||
|
const bool getDirectional() const { return isDirectional; }
|
||||||
|
const int getCycles() const { return cycles; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string animName;
|
||||||
|
std::string animType;
|
||||||
|
|
||||||
|
std::shared_ptr<SpriteAtlas> spriteAtlas;
|
||||||
|
|
||||||
|
Uint32 elapsedTime = 0;
|
||||||
|
Uint32 lastFrameTick = 0;
|
||||||
|
float FPS;
|
||||||
|
int currentFrame;
|
||||||
|
int cycles;
|
||||||
|
|
||||||
|
bool isDirectional;
|
||||||
|
bool isPlaying;
|
||||||
|
|
||||||
|
// this ticks our frame forward according to ticks passed
|
||||||
|
void frameTick();
|
||||||
|
|
||||||
|
void singleDraw();
|
||||||
|
void directionalDraw(Direction dir);
|
||||||
|
};
|
||||||
|
|
||||||
|
// We will load our animation component with every loaded animation,
|
||||||
|
// this will be the handler for every animation an entity uses
|
||||||
|
class AnimationSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AnimationSet(const int& entityid);
|
||||||
|
AnimationSet(const int& entityid, ResourceManager* resourceManager, std::vector<std::shared_ptr<AnimationData>> animSet);
|
||||||
|
AnimationSet(const int& entityid, const std::unordered_map<std::string, std::shared_ptr<Animation>>& animations);
|
||||||
|
|
||||||
|
std::shared_ptr<Animation>& operator [](std::string animType) { return anims[animType]; }
|
||||||
|
|
||||||
|
void addAnimation(const std::shared_ptr<Animation> anim) { anims.try_emplace(anim->getType(), anim); }
|
||||||
|
void setAnimation(const std::string& animType) { curAnim = anims[animType]; }
|
||||||
|
|
||||||
|
const int getEntityID() const { return entityid; }
|
||||||
|
const bool getDirectional() const { return isDirectional; }
|
||||||
|
|
||||||
|
void bind();
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
void play() { curAnim->play(); }
|
||||||
|
void stop() { curAnim->stop(); }
|
||||||
|
|
||||||
|
void setFacingDir(Direction& dir) { facing = dir; }
|
||||||
|
|
||||||
|
void attachEventManager(const std::shared_ptr<EventManager>& e);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int entityid;
|
||||||
|
bool isDirectional;
|
||||||
|
|
||||||
|
Direction facing = Direction::Down;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<Animation>> anims;
|
||||||
|
std::shared_ptr<Animation> curAnim;
|
||||||
|
|
||||||
|
std::shared_ptr<EventManager> eventManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _H_ANIMATION_H
|
||||||
|
|
@ -23,8 +23,6 @@ public:
|
||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
virtual void draw() = 0;
|
virtual void draw() = 0;
|
||||||
virtual void play() = 0;
|
|
||||||
virtual void idle() = 0;
|
|
||||||
|
|
||||||
virtual std::shared_ptr<Sprite> clone() const = 0;
|
virtual std::shared_ptr<Sprite> clone() const = 0;
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -42,8 +40,6 @@ public:
|
||||||
~SpriteStatic();
|
~SpriteStatic();
|
||||||
|
|
||||||
void draw() override;
|
void draw() override;
|
||||||
void play() override { /*unused*/ }
|
|
||||||
void idle() override { /*unused*/ }
|
|
||||||
|
|
||||||
std::shared_ptr<Sprite> clone() const override {
|
std::shared_ptr<Sprite> clone() const override {
|
||||||
return std::make_shared<SpriteStatic>(*this);
|
return std::make_shared<SpriteStatic>(*this);
|
||||||
|
|
@ -66,73 +62,54 @@ private:
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SpriteAnimated : public Sprite
|
class SpriteAtlas : public Sprite
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// let's keep texture grids squares, saves everyone time...
|
|
||||||
SpriteAnimated(const char* textureAtlasPath, float frameSize);
|
|
||||||
~SpriteAnimated();
|
|
||||||
|
|
||||||
void draw() override;
|
|
||||||
|
|
||||||
void play() override;
|
|
||||||
void idle() override;
|
|
||||||
|
|
||||||
std::shared_ptr<Sprite> clone() const override {
|
|
||||||
return std::make_shared<SpriteAnimated>(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isPlaying = false;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SetupAnimated(float frameSize);
|
|
||||||
|
|
||||||
struct VertexIDs {
|
struct VertexIDs {
|
||||||
unsigned VAO, VBO;
|
unsigned VAO, VBO;
|
||||||
};
|
};
|
||||||
unsigned EBO;
|
// let's keep texture grids squares, saves everyone time...
|
||||||
|
SpriteAtlas(const char* textureAtlasPath, float frameSize, bool isDirectional = false);
|
||||||
// Vertex array buffer IDs
|
~SpriteAtlas();
|
||||||
std::vector<VertexIDs> ids;
|
|
||||||
|
|
||||||
int currentFrame = 0;
|
|
||||||
float FPS = 7.5f;
|
|
||||||
Uint32 lastFrameTick = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SpriteDirectionalAnimated : public Sprite
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
SpriteDirectionalAnimated(const char* textureAtlasPath, float frameSize);
|
|
||||||
~SpriteDirectionalAnimated();
|
|
||||||
|
|
||||||
|
void bindFrame(VertexIDs* f);
|
||||||
|
// draw current frame
|
||||||
void draw() override;
|
void draw() override;
|
||||||
|
|
||||||
void play() override;
|
VertexIDs frame(int index, Direction dir = Direction::None) {
|
||||||
void idle() override;
|
if (dir == Direction::None) return singleFrame(index);
|
||||||
|
return dirFrames(dir, index);
|
||||||
std::shared_ptr<Sprite> clone() const override {
|
|
||||||
return std::make_shared<SpriteDirectionalAnimated>(*this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Direction direction = Direction::Down;
|
size_t size() { return (isDirectional) ? directionalIDs.size() : singleIDs.size(); }
|
||||||
void setDirection(Direction& dir) { direction = dir; }
|
|
||||||
bool isPlaying = false;
|
std::shared_ptr<Sprite> clone() const override {
|
||||||
|
return std::make_shared<SpriteAtlas>(*this);
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Setup(float frameSize);
|
void Setup(float frameSize);
|
||||||
|
void SetupDirectional(float frameSize);
|
||||||
|
|
||||||
struct VertexIDs {
|
|
||||||
unsigned VAO, VBO;
|
|
||||||
};
|
|
||||||
unsigned EBO;
|
unsigned EBO;
|
||||||
|
bool isDirectional;
|
||||||
|
|
||||||
std::unordered_map<Direction, VertexIDs> idleIDs;
|
VertexIDs* curFrame;
|
||||||
std::unordered_map<Direction, std::vector<VertexIDs>> walkingIDs;
|
|
||||||
|
|
||||||
int currentFrame = 0;
|
VertexIDs singleFrame(int index) const {
|
||||||
float FPS = 7.5f;
|
return (index < 0 || index >= singleIDs.size()) ? singleIDs[0] : singleIDs[index];
|
||||||
Uint32 lastFrameTick = 0;
|
}
|
||||||
|
|
||||||
|
// return the frame in the direction at the selected index
|
||||||
|
VertexIDs dirFrames(Direction dir, int index) const {
|
||||||
|
return (index < 0 || index >= directionalIDs.at(dir).size()) ? directionalIDs.at(dir)[0] : directionalIDs.at(dir)[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vertex array buffer IDs, if the sprite atlas is non-directional
|
||||||
|
std::vector<VertexIDs> singleIDs;
|
||||||
|
|
||||||
|
// Vertex ids if the sprite atlas is directional
|
||||||
|
std::unordered_map<Direction, std::vector<VertexIDs>> directionalIDs;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _H_SPRITE_H
|
#endif // _H_SPRITE_H
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "graphics/mesh.h"
|
#include "graphics/mesh.h"
|
||||||
#include "graphics/sprite.h"
|
#include "graphics/sprite.h"
|
||||||
#include "graphics/shader.h"
|
#include "graphics/shader.h"
|
||||||
|
#include "graphics/animation.h"
|
||||||
#include "gameplay/ai.h"
|
#include "gameplay/ai.h"
|
||||||
#include "events.h"
|
#include "events.h"
|
||||||
|
|
||||||
|
|
@ -21,6 +22,7 @@ public:
|
||||||
virtual void idle() = 0;
|
virtual void idle() = 0;
|
||||||
|
|
||||||
int ownerid = 0;
|
int ownerid = 0;
|
||||||
|
private:
|
||||||
std::shared_ptr<EventManager> eventManager;
|
std::shared_ptr<EventManager> eventManager;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -37,6 +39,7 @@ public:
|
||||||
void play() override { /*unused*/ }
|
void play() override { /*unused*/ }
|
||||||
void idle() override { /*unused*/ }
|
void idle() override { /*unused*/ }
|
||||||
|
|
||||||
|
|
||||||
~MeshComponent() { mesh->~Mesh(); }
|
~MeshComponent() { mesh->~Mesh(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -48,33 +51,16 @@ class SpriteComponent : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SpriteComponent(std::shared_ptr<Sprite> sprite) : sprite(sprite), Component(nullptr) {}
|
SpriteComponent(std::shared_ptr<Sprite> sprite) : sprite(sprite), Component(nullptr) {}
|
||||||
SpriteComponent(std::shared_ptr<Sprite> sprite, const std::shared_ptr<EventManager>& eventManager) :
|
|
||||||
Component(eventManager), sprite(sprite) {
|
|
||||||
auto directionalSprite = std::dynamic_pointer_cast<SpriteDirectionalAnimated>(sprite);
|
|
||||||
if (directionalSprite)
|
|
||||||
{
|
|
||||||
eventManager->subscribe("OnDirectionChange", [sprite, this](std::shared_ptr<Event> e) {
|
|
||||||
auto directionEvent = std::static_pointer_cast<DirectionChangeEvent>(e);
|
|
||||||
auto directionSprite = std::static_pointer_cast<SpriteDirectionalAnimated>(sprite);
|
|
||||||
if (directionEvent->actorid == ownerid)
|
|
||||||
directionSprite->setDirection(directionEvent->direction);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void bind() override {
|
void bind() override {
|
||||||
if (sprite) sprite->bind();
|
if (sprite) sprite->bind();
|
||||||
}
|
}
|
||||||
void update() override {}
|
void update() override { /*unused*/ }
|
||||||
void render() override {
|
void render() override {
|
||||||
if (sprite) sprite->draw();
|
if (sprite) sprite->draw();
|
||||||
}
|
}
|
||||||
void play() override {
|
void play() override { /*unused*/ }
|
||||||
if (sprite) sprite->play();
|
void idle() override { /*unused*/ }
|
||||||
}
|
|
||||||
void idle() override {
|
|
||||||
if (sprite) sprite->idle();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Sprite>& getSprite() { return sprite; }
|
std::shared_ptr<Sprite>& getSprite() { return sprite; }
|
||||||
|
|
||||||
|
|
@ -84,6 +70,42 @@ private:
|
||||||
std::shared_ptr<Sprite> sprite;
|
std::shared_ptr<Sprite> sprite;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class AnimationComponent : public Component
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AnimationComponent(std::shared_ptr<AnimationSet> animSet) : animSet(animSet), Component(nullptr) {};
|
||||||
|
AnimationComponent(std::shared_ptr<AnimationSet> animSet, const std::shared_ptr<EventManager>& eventManager) :
|
||||||
|
animSet(animSet), Component(nullptr)
|
||||||
|
{
|
||||||
|
this->animSet->attachEventManager(eventManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
void bind() override {
|
||||||
|
if (animSet)
|
||||||
|
animSet->bind();
|
||||||
|
}
|
||||||
|
void update() override {/*unused*/}
|
||||||
|
void render() override {
|
||||||
|
if (animSet)
|
||||||
|
animSet->draw();
|
||||||
|
}
|
||||||
|
void play() override {
|
||||||
|
if (animSet)
|
||||||
|
animSet->play();
|
||||||
|
}
|
||||||
|
void idle() override {
|
||||||
|
if (animSet)
|
||||||
|
animSet->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<AnimationSet>& getAnimationSet() { return animSet; }
|
||||||
|
|
||||||
|
~AnimationComponent() { }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<AnimationSet> animSet;
|
||||||
|
};
|
||||||
|
|
||||||
class ShaderComponent : public Component
|
class ShaderComponent : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
enum class Direction {
|
enum class Direction {
|
||||||
|
|
||||||
|
None = 0,
|
||||||
Down = 1,
|
Down = 1,
|
||||||
Right = 2,
|
Right = 2,
|
||||||
Left = 3,
|
Left = 3,
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,46 @@ public:
|
||||||
|
|
||||||
class DirectionChangeEvent : public Event {
|
class DirectionChangeEvent : public Event {
|
||||||
public:
|
public:
|
||||||
DirectionChangeEvent(const int actorid, Direction direction) : actorid(actorid), direction(direction) {}
|
DirectionChangeEvent(const int entityid, Direction direction) : entityid(entityid), direction(direction) {}
|
||||||
std::string getType() const override { return "OnDirectionChange"; }
|
std::string getType() const override { return "OnDirectionChange"; }
|
||||||
Direction direction;
|
Direction direction;
|
||||||
int actorid;
|
int entityid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntityMoveEvent : public Event {
|
||||||
|
public:
|
||||||
|
EntityMoveEvent(const int entityid) : entityid(entityid) {}
|
||||||
|
std::string getType() const override { return "OnEntityMove"; }
|
||||||
|
int entityid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntityStopEvent : public Event {
|
||||||
|
public:
|
||||||
|
EntityStopEvent(const int entityid) : entityid(entityid) {}
|
||||||
|
std::string getType() const override { return "OnEntityStop"; }
|
||||||
|
int entityid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntityReloadEvent : public Event {
|
||||||
|
public:
|
||||||
|
EntityReloadEvent(const int entityid) : entityid(entityid) {}
|
||||||
|
std::string getType() const override { return "OnEntityReload"; }
|
||||||
|
int entityid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntityFinishReloadEvent : public Event {
|
||||||
|
public:
|
||||||
|
EntityFinishReloadEvent(const int entityid) : entityid(entityid) {}
|
||||||
|
std::string getType() const override { return "OnEntityFinishReload"; }
|
||||||
|
int entityid;
|
||||||
|
};
|
||||||
|
|
||||||
|
class AnimationFinishedEvent : public Event {
|
||||||
|
public:
|
||||||
|
AnimationFinishedEvent(const int entityid, const std::string animType) : entityid(entityid), animType(animType) {}
|
||||||
|
std::string getType() const override { return "OnAnimationFinished"; }
|
||||||
|
std::string animType;
|
||||||
|
int entityid;
|
||||||
};
|
};
|
||||||
|
|
||||||
class EventManager {
|
class EventManager {
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,11 @@
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
class Sprite;
|
class Sprite;
|
||||||
|
class SpriteAtlas;
|
||||||
class Shader;
|
class Shader;
|
||||||
class Weapon;
|
class Weapon;
|
||||||
class Script;
|
class Script;
|
||||||
|
class AnimationSet;
|
||||||
class AIScript;
|
class AIScript;
|
||||||
class WeaponScript;
|
class WeaponScript;
|
||||||
class TileSet;
|
class TileSet;
|
||||||
|
|
@ -25,10 +27,10 @@ public:
|
||||||
{
|
{
|
||||||
xmlLoader->loadWeapons("weapons");
|
xmlLoader->loadWeapons("weapons");
|
||||||
xmlLoader->loadScenes("scenes");
|
xmlLoader->loadScenes("scenes");
|
||||||
|
xmlLoader->loadAnimations("animations");
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<Sprite> loadSpriteAnimated (const std::string& path, float frameSize);
|
std::shared_ptr<SpriteAtlas> loadSpriteAtlas (const std::string& path, float frameSize, bool isDirectional = false);
|
||||||
std::shared_ptr<Sprite> loadSpriteDirAnimated (const std::string& path, float frameSize);
|
|
||||||
std::shared_ptr<Sprite> loadSpriteStatic (const std::string& path);
|
std::shared_ptr<Sprite> loadSpriteStatic (const std::string& path);
|
||||||
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);
|
||||||
|
|
@ -37,6 +39,7 @@ public:
|
||||||
std::shared_ptr<Shader> loadShader (const std::string& name, const std::string& vertexPath, const std::string& fragPath);
|
std::shared_ptr<Shader> 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, std::shared_ptr<Shader> weaponShader, std::shared_ptr<Shader> bulletShader);
|
||||||
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);
|
||||||
|
|
||||||
void clearResources();
|
void clearResources();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,11 @@ struct Tile;
|
||||||
|
|
||||||
struct EntityData {
|
struct EntityData {
|
||||||
bool isPlayer;
|
bool isPlayer;
|
||||||
|
bool animated;
|
||||||
int x = 0, y = 0;
|
int x = 0, y = 0;
|
||||||
std::string sprite;
|
std::string graphic;
|
||||||
float frameSize = 0.f;
|
|
||||||
std::string weapon = "pistolGun";
|
std::string weapon = "pistolGun";
|
||||||
std::string script;
|
std::string script;
|
||||||
bool isDirectional = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MapData {
|
struct MapData {
|
||||||
|
|
@ -37,26 +36,44 @@ struct SceneData {
|
||||||
struct WeaponData {
|
struct WeaponData {
|
||||||
std::string name;
|
std::string name;
|
||||||
float fireSpeed = 250.0f;
|
float fireSpeed = 250.0f;
|
||||||
|
int clipSize = 21;
|
||||||
|
int maxAmmo = 512;
|
||||||
std::string script = "";
|
std::string script = "";
|
||||||
std::string sprite;
|
std::string graphic;
|
||||||
|
std::string animSet;
|
||||||
bool animated = false;
|
bool animated = false;
|
||||||
float frameSize;
|
|
||||||
float sizeX = 50.f, sizeY = 50.f;
|
float sizeX = 50.f, sizeY = 50.f;
|
||||||
float offsetX = 0.f, offsetY = 0.f;
|
float offsetX = 0.f, offsetY = 0.f;
|
||||||
float bulletFrameSize;
|
|
||||||
float bulletSizeX = 50.f, bulletSizeY = 50.f;
|
float bulletSizeX = 50.f, bulletSizeY = 50.f;
|
||||||
std::string bulletSprite;
|
std::string bulletGraphic;
|
||||||
bool bulletAnimated = false;
|
bool bulletAnimated = false;
|
||||||
float bulletSpread = 1.0f, bulletSpeed = 3.0f, bulletDrop = 500.f;
|
float bulletSpread = 1.0f, bulletSpeed = 3.0f, bulletDrop = 500.f;
|
||||||
float modMin = 0.5f, modMax = 1.0f;
|
float modMin = 0.5f, modMax = 1.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AnimationData {
|
||||||
|
std::string name;
|
||||||
|
std::string type;
|
||||||
|
std::string spriteAtlas;
|
||||||
|
// Each entity will have a set of animations,
|
||||||
|
// this animation set is meant to keep each group
|
||||||
|
// of animations within their set.
|
||||||
|
// The actual set name is based on the file the animation
|
||||||
|
// is held in.
|
||||||
|
std::string animSet;
|
||||||
|
bool directional = false;
|
||||||
|
bool oneShot;
|
||||||
|
float FPS = 1.f;
|
||||||
|
float frameSize;
|
||||||
|
};
|
||||||
|
|
||||||
class XMLLoader
|
class XMLLoader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
XMLLoader() {}
|
XMLLoader() {}
|
||||||
bool loadScenes(const char* sceneFolder);
|
bool loadScenes(const char* sceneFolder);
|
||||||
bool loadWeapons(const char* weaponFolder);
|
bool loadWeapons(const char* weaponFolder);
|
||||||
|
bool loadAnimations(const char* animationFolder);
|
||||||
|
|
||||||
const std::shared_ptr<SceneData> getSceneData(const std::string& id) const {
|
const std::shared_ptr<SceneData> getSceneData(const std::string& id) const {
|
||||||
try {
|
try {
|
||||||
|
|
@ -66,15 +83,39 @@ public:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<AnimationData> getAnimationData(const std::string& name) const {
|
||||||
|
try {
|
||||||
|
return animations.at(name);
|
||||||
|
}
|
||||||
|
catch (std::exception&) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return a full set of animations, may need further optimization.
|
||||||
|
// one idea is when loading animations we create a seperate map that holds each set by their reference, so we can just do a simple,
|
||||||
|
// hash table lookup.
|
||||||
|
std::vector<std::shared_ptr<AnimationData>> getAnimationSet(const std::string& set) const {
|
||||||
|
std::vector<std::shared_ptr<AnimationData>> animSet;
|
||||||
|
animSet.reserve(animations.size());
|
||||||
|
for (const auto& [name, anim] : animations) {
|
||||||
|
if (anim->animSet == set) animSet.push_back(anim);
|
||||||
|
}
|
||||||
|
animSet.shrink_to_fit();
|
||||||
|
return animSet;
|
||||||
|
}
|
||||||
|
|
||||||
const WeaponData* getWeaponDataByName(const char* name) const;
|
const WeaponData* getWeaponDataByName(const char* name) const;
|
||||||
|
|
||||||
void clearData() { scenes.clear(); weaponData.clear(); }
|
void clearData() { scenes.clear(); weaponData.clear(); animations.clear(); }
|
||||||
protected:
|
protected:
|
||||||
bool loadXmlScene(const char* xmlFile, SceneData* out);
|
bool loadXmlScene(const char* xmlFile, SceneData* out);
|
||||||
bool loadMap(const char* xmlFile, SceneData* out);
|
bool loadMap(const char* xmlFile, SceneData* out);
|
||||||
bool loadEntityData(const char* xmlFile, SceneData* out);
|
bool loadEntityData(const char* xmlFile, SceneData* out);
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, std::shared_ptr<SceneData>> scenes;
|
std::unordered_map<std::string, std::shared_ptr<SceneData>> scenes;
|
||||||
|
std::unordered_map<std::string, std::shared_ptr<AnimationData>> animations;
|
||||||
|
|
||||||
std::vector<WeaponData> weaponData;
|
std::vector<WeaponData> weaponData;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,11 @@ GameActor::~GameActor() { }
|
||||||
|
|
||||||
void GameActor::addComponent(std::shared_ptr<Component> component)
|
void GameActor::addComponent(std::shared_ptr<Component> component)
|
||||||
{
|
{
|
||||||
component->ownerid = actorid;
|
component->ownerid = entityid;
|
||||||
components.push_back(component);
|
components.push_back(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::optional<std::shared_ptr<Weapon>>& GameActor::getHeldWeapon() const
|
const std::optional<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()) ? std::nullopt : std::make_optional(weapons[currentWeaponIndex]);
|
||||||
}
|
}
|
||||||
|
|
@ -23,6 +23,7 @@ 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.
|
||||||
getHeldWeapon().value()->putaway();
|
getHeldWeapon().value()->putaway();
|
||||||
currentWeaponIndex = weapons.size() - 1;
|
currentWeaponIndex = weapons.size() - 1;
|
||||||
getHeldWeapon().value()->wield();
|
getHeldWeapon().value()->wield();
|
||||||
|
|
@ -40,7 +41,7 @@ void GameActor::setRotation(const float& rotation)
|
||||||
if (!isRotatable && eventManager) {
|
if (!isRotatable && eventManager) {
|
||||||
Direction newDir = getDirectionFromRotation(rotation);
|
Direction newDir = getDirectionFromRotation(rotation);
|
||||||
if (getDirectionFromRotation(this->rotation) != newDir)
|
if (getDirectionFromRotation(this->rotation) != newDir)
|
||||||
eventManager->notify(std::make_shared<DirectionChangeEvent>(actorid, newDir));
|
eventManager->notify(std::make_shared<DirectionChangeEvent>(entityid, newDir));
|
||||||
}
|
}
|
||||||
this->rotation = rotation;
|
this->rotation = rotation;
|
||||||
updateModelMatrix();
|
updateModelMatrix();
|
||||||
|
|
@ -54,24 +55,36 @@ void GameActor::update(float deltaTime)
|
||||||
component->update();
|
component->update();
|
||||||
for (auto& weapon : weapons)
|
for (auto& weapon : weapons)
|
||||||
weapon->update(deltaTime);
|
weapon->update(deltaTime);
|
||||||
|
|
||||||
|
if (eventManager)
|
||||||
|
{
|
||||||
|
if (isMoving && !wasMoving)
|
||||||
|
{
|
||||||
|
eventManager->notify(std::make_shared<EntityMoveEvent>(entityid));
|
||||||
|
wasMoving = true;
|
||||||
|
}
|
||||||
|
else if (!isMoving && wasMoving)
|
||||||
|
{
|
||||||
|
eventManager->notify(std::make_shared<EntityStopEvent>(entityid));
|
||||||
|
wasMoving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isMoving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GameActor::render(const std::shared_ptr<Camera>& camera)
|
void GameActor::render(const std::shared_ptr<Camera>& camera)
|
||||||
{
|
{
|
||||||
Entity::render(camera);
|
Entity::render(camera);
|
||||||
|
|
||||||
|
// regular loop through components, but if the component returns true to kill, we erase it.
|
||||||
|
// Components are always assumed to be smart pointers!
|
||||||
for (auto& component : components)
|
for (auto& component : components)
|
||||||
{
|
{
|
||||||
if (isMoving)
|
|
||||||
component->play();
|
|
||||||
else
|
|
||||||
component->idle();
|
|
||||||
component->bind();
|
component->bind();
|
||||||
component->render();
|
component->render();
|
||||||
}
|
}
|
||||||
for (auto& weapon : weapons)
|
for (auto& weapon : weapons)
|
||||||
weapon->render(camera);
|
weapon->render(camera);
|
||||||
isMoving = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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; }
|
||||||
|
|
@ -108,7 +121,7 @@ void GameActor::followMouse(const MouseState& mouse_state)
|
||||||
float newRotation = glm::degrees(glm::atan(direction.y, direction.x));
|
float newRotation = glm::degrees(glm::atan(direction.y, direction.x));
|
||||||
if (getDirectionFromRotation(rotation) != getDirectionFromRotation(newRotation))
|
if (getDirectionFromRotation(rotation) != getDirectionFromRotation(newRotation))
|
||||||
if (eventManager)
|
if (eventManager)
|
||||||
eventManager->notify(std::make_shared<DirectionChangeEvent>(actorid, getDirectionFromRotation(newRotation)));
|
eventManager->notify(std::make_shared<DirectionChangeEvent>(entityid, getDirectionFromRotation(newRotation)));
|
||||||
//setRotation(glm::degrees(glm::atan(direction.y, direction.x)));
|
//setRotation(glm::degrees(glm::atan(direction.y, direction.x)));
|
||||||
this->rotation = newRotation;
|
this->rotation = newRotation;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "graphics/tile.h"
|
#include "graphics/tile.h"
|
||||||
#include "graphics/sprite.h"
|
#include "graphics/sprite.h"
|
||||||
|
#include "graphics/animation.h"
|
||||||
|
|
||||||
#include "utility/component.h"
|
#include "utility/component.h"
|
||||||
#include "utility/xmlloader.h"
|
#include "utility/xmlloader.h"
|
||||||
|
|
@ -57,22 +58,25 @@ void Scene::loadDebugShooterScene()
|
||||||
for (EntityData entityData : sceneData->entities)
|
for (EntityData entityData : sceneData->entities)
|
||||||
{
|
{
|
||||||
auto entity = std::make_shared<GameActor>(playerShader);
|
auto entity = std::make_shared<GameActor>(playerShader);
|
||||||
std::shared_ptr<Sprite> entitySprite;
|
|
||||||
// Directional is the kind of sprite sheet we are using, in this case for directional, I have the sprite sheet handle the rotations
|
// Directional is the kind of sprite sheet we are using, in this case for directional, I have the sprite sheet handle the rotations
|
||||||
// instead of just rotating the object, this makes it look quite a bit better from the end user perspective.
|
// instead of just rotating the object, this makes it look quite a bit better from the end user perspective.
|
||||||
if (entityData.isDirectional)
|
if (entityData.animated)
|
||||||
{
|
{
|
||||||
entitySprite = resourceManager->loadSpriteDirAnimated(entityData.sprite, entityData.frameSize);
|
auto entityAnimation = resourceManager->loadAnimationSet(entityData.graphic, entity->getEntityID());
|
||||||
// because we don't want to have the engine rotate the object based on the entities rotation,
|
// because we don't want to have the engine rotate the object based on the entities rotation,
|
||||||
// we set the this value to false so we no longer rotate the object.
|
// we set the this value to false so we no longer rotate the object.
|
||||||
|
if (entityAnimation->getDirectional())
|
||||||
entity->setRotatable(false);
|
entity->setRotatable(false);
|
||||||
|
entity->addComponent(std::make_shared<AnimationComponent>(entityAnimation, eventManager));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
entitySprite = resourceManager->loadSpriteAnimated(entityData.sprite, entityData.frameSize);
|
{
|
||||||
|
auto entitySprite = resourceManager->loadSpriteStatic(entityData.graphic);
|
||||||
|
entity->addComponent(std::make_shared<SpriteComponent>(entitySprite));
|
||||||
|
}
|
||||||
auto defaultWeapon = resourceManager->loadWeapon("pistolGun", weaponShader, bubbleShader);
|
auto defaultWeapon = resourceManager->loadWeapon("pistolGun", weaponShader, bubbleShader);
|
||||||
auto entityWeapon = resourceManager->loadWeapon(entityData.weapon, weaponShader, bubbleShader);
|
auto entityWeapon = resourceManager->loadWeapon(entityData.weapon, weaponShader, bubbleShader);
|
||||||
|
|
||||||
entity->addComponent(std::make_shared<SpriteComponent>(entitySprite, eventManager));
|
|
||||||
entity->pickupWeapon(defaultWeapon);
|
entity->pickupWeapon(defaultWeapon);
|
||||||
entity->pickupWeapon(entityWeapon);
|
entity->pickupWeapon(entityWeapon);
|
||||||
entity->hookEventManager(eventManager);
|
entity->hookEventManager(eventManager);
|
||||||
|
|
@ -80,7 +84,7 @@ void Scene::loadDebugShooterScene()
|
||||||
entity->setScale(glm::vec3(mapData.tileSize, mapData.tileSize, 1.f));
|
entity->setScale(glm::vec3(mapData.tileSize, mapData.tileSize, 1.f));
|
||||||
|
|
||||||
entity->addPhysicsComponent(
|
entity->addPhysicsComponent(
|
||||||
physicsEngine->createObject(entity->getActorID(),
|
physicsEngine->createObject(entity->getEntityID(),
|
||||||
entity->getPosition(),
|
entity->getPosition(),
|
||||||
49.0,
|
49.0,
|
||||||
PhysicsComponent::Collider::Shape::Circle,
|
PhysicsComponent::Collider::Shape::Circle,
|
||||||
|
|
@ -107,7 +111,7 @@ void Scene::loadDebugShooterScene()
|
||||||
entity->addComponent(std::make_shared<AIComponent>(ai));
|
entity->addComponent(std::make_shared<AIComponent>(ai));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
entities.emplace(entity->getActorID(), entity);
|
entities.emplace(entity->getEntityID(), entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
physicsEngine->loadCollisionMap(map->getCollisionMap(), sceneData->map.tileSize);
|
physicsEngine->loadCollisionMap(map->getCollisionMap(), sceneData->map.tileSize);
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
#include "utility/script.h"
|
#include "utility/script.h"
|
||||||
|
|
||||||
// TODO: Regular clean up, make this mess readable!
|
// TODO: Regular clean up, make this mess readable!
|
||||||
// TODO: Attach script to weapons, create custom shoot scripts, allowing the addition of shotguns and other whacky things
|
|
||||||
// TODO: Finally just allow the XMLLoader to read the weaponscript supplied and load it into the weapon
|
|
||||||
|
|
||||||
Weapon::Weapon(const WeaponData* data, const std::shared_ptr<Shader>& weaponShader, const std::shared_ptr<Shader>& bulletShader, ResourceManager* resourceManager)
|
Weapon::Weapon(const WeaponData* data, const std::shared_ptr<Shader>& weaponShader, const std::shared_ptr<Shader>& bulletShader, ResourceManager* resourceManager)
|
||||||
:
|
:
|
||||||
|
|
@ -21,25 +19,28 @@ Weapon::Weapon(const WeaponData* data, const std::shared_ptr<Shader>& weaponShad
|
||||||
bulletShader (bulletShader),
|
bulletShader (bulletShader),
|
||||||
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),
|
||||||
|
weaponMag (data->clipSize),
|
||||||
|
weaponAmmo (data->maxAmmo),
|
||||||
bulletDrop (data->bulletDrop),
|
bulletDrop (data->bulletDrop),
|
||||||
bulletSpeed (data->bulletSpeed),
|
bulletSpeed (data->bulletSpeed),
|
||||||
bulletSize (glm::vec2(data->bulletSizeX, data->bulletSizeY)),
|
bulletSize (glm::vec2(data->bulletSizeX, data->bulletSizeY)),
|
||||||
bulletSpread (std::make_shared<UTIL::RandomGenerator>(-data->bulletSpread, data->bulletSpread)),
|
bulletSpread (std::make_shared<UTIL::RandomGenerator>(-data->bulletSpread, data->bulletSpread)),
|
||||||
bulletModifer (std::make_shared<UTIL::RandomGenerator>(data->modMin, data->modMax)),
|
bulletModifer (std::make_shared<UTIL::RandomGenerator>(data->modMin, data->modMax)),
|
||||||
fireSpeed (data->fireSpeed),
|
fireSpeed (data->fireSpeed),
|
||||||
bulletManager (std::make_shared<BulletManager>()),
|
bulletManager (std::make_shared<BulletManager>())
|
||||||
bulletSprite (data->bulletAnimated ?
|
|
||||||
std::make_shared<SpriteComponent>(resourceManager->loadSpriteAnimated(data->bulletSprite, data->bulletFrameSize))
|
|
||||||
: std::make_shared<SpriteComponent>(resourceManager->loadSpriteStatic(data->bulletSprite)))
|
|
||||||
{
|
{
|
||||||
|
if (data->bulletAnimated)
|
||||||
|
bulletSprite = std::make_shared<AnimationComponent>(resourceManager->loadAnimationSet(data->bulletGraphic, entityid));
|
||||||
|
else
|
||||||
|
bulletSprite = std::make_shared<SpriteComponent>(resourceManager->loadSpriteStatic(data->bulletGraphic));
|
||||||
|
|
||||||
if (data->animated)
|
if (data->animated)
|
||||||
{
|
{
|
||||||
addComponent(std::make_shared<SpriteComponent>(resourceManager->loadSpriteAnimated(data->sprite, data->frameSize)));
|
addComponent(std::make_shared<AnimationComponent>(resourceManager->loadAnimationSet(data->graphic, entityid)));
|
||||||
for (auto& c : components)
|
|
||||||
c->play();
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
addComponent(std::make_shared<SpriteComponent>(resourceManager->loadSpriteStatic(data->sprite)));
|
addComponent(std::make_shared<SpriteComponent>(resourceManager->loadSpriteStatic(data->graphic)));
|
||||||
this->setScale(glm::vec3(weaponSize.x, weaponSize.y, 1.0f));
|
this->setScale(glm::vec3(weaponSize.x, weaponSize.y, 1.0f));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -47,18 +48,38 @@ void Weapon::addComponent(const std::shared_ptr<Component>& comp) {
|
||||||
components.push_back(comp);
|
components.push_back(comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Weapon::reload()
|
||||||
|
{
|
||||||
|
// TODO: Create reload event that will be captured by the gun animation set, to start the reloading animation
|
||||||
|
if (eventManager)
|
||||||
|
{
|
||||||
|
eventManager->notify(std::make_shared<EntityReloadEvent>(entityid));
|
||||||
|
reloading = true;
|
||||||
|
if (weaponAmmo < weaponMagSize) {
|
||||||
|
weaponMag = weaponAmmo;
|
||||||
|
weaponAmmo = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
weaponMag = weaponMagSize;
|
||||||
|
weaponAmmo -= weaponMagSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Weapon::shoot()
|
void Weapon::shoot()
|
||||||
{
|
{
|
||||||
if (wielder)
|
if (wielder)
|
||||||
{
|
{
|
||||||
Uint32 currentTime = SDL_GetTicks();
|
Uint32 currentTime = SDL_GetTicks();
|
||||||
if (currentTime - lastFireTime >= fireSpeed)
|
if (weaponMag <= 0 && !reloading) reload();
|
||||||
|
if (currentTime - lastFireTime >= fireSpeed && !reloading && weaponMag > 0)
|
||||||
{
|
{
|
||||||
if (!weaponScript || !weaponScript->lua["onShoot"].valid())
|
if (!weaponScript || !weaponScript->lua["onShoot"].valid())
|
||||||
{
|
{
|
||||||
// create bullet using this generated data
|
// create bullet using this generated data
|
||||||
BulletData b = genBulletData();
|
BulletData b = genBulletData();
|
||||||
createBullet(b);
|
createBullet(b);
|
||||||
|
weaponMag -= 1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
auto result = weaponScript->lua["onShoot"]();
|
auto result = weaponScript->lua["onShoot"]();
|
||||||
|
|
@ -67,6 +88,7 @@ void Weapon::shoot()
|
||||||
sol::error err = result;
|
sol::error err = result;
|
||||||
std::cerr << "lua error: " << err.what() << std::endl;
|
std::cerr << "lua error: " << err.what() << std::endl;
|
||||||
}
|
}
|
||||||
|
weaponMag -= 1;
|
||||||
}
|
}
|
||||||
lastFireTime = currentTime;
|
lastFireTime = currentTime;
|
||||||
}
|
}
|
||||||
|
|
@ -76,6 +98,28 @@ void Weapon::shoot()
|
||||||
void Weapon::hookEventManager(const std::shared_ptr<EventManager>& eventManager)
|
void Weapon::hookEventManager(const std::shared_ptr<EventManager>& eventManager)
|
||||||
{
|
{
|
||||||
this->eventManager = eventManager;
|
this->eventManager = eventManager;
|
||||||
|
|
||||||
|
for (auto& component : components)
|
||||||
|
{
|
||||||
|
auto animComponent = std::dynamic_pointer_cast<AnimationComponent>(component);
|
||||||
|
if (animComponent != nullptr)
|
||||||
|
{
|
||||||
|
animComponent->getAnimationSet()->attachEventManager(eventManager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->eventManager->subscribe("OnAnimationFinished", [&, this](std::shared_ptr<Event> e) {
|
||||||
|
auto animFinished = std::static_pointer_cast<AnimationFinishedEvent>(e);
|
||||||
|
if (animFinished->entityid == entityid && animFinished->animType == "reload")
|
||||||
|
{
|
||||||
|
if (reloading)
|
||||||
|
{
|
||||||
|
reloading = false;
|
||||||
|
wasReloading = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
bulletManager->hookEventManager(eventManager);
|
bulletManager->hookEventManager(eventManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -110,6 +154,11 @@ void Weapon::update(float deltaTime)
|
||||||
|
|
||||||
for (auto& component : components)
|
for (auto& component : components)
|
||||||
component->update();
|
component->update();
|
||||||
|
if (eventManager && wasReloading)
|
||||||
|
{
|
||||||
|
wasReloading = false;
|
||||||
|
eventManager->notify(std::make_shared<EntityFinishReloadEvent>(entityid));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
bulletManager->update(deltaTime);
|
bulletManager->update(deltaTime);
|
||||||
}
|
}
|
||||||
|
|
@ -121,6 +170,7 @@ void Weapon::render(const std::shared_ptr<Camera>& camera)
|
||||||
{
|
{
|
||||||
for (auto& component : components)
|
for (auto& component : components)
|
||||||
{
|
{
|
||||||
|
component->play();
|
||||||
component->bind();
|
component->bind();
|
||||||
component->render();
|
component->render();
|
||||||
}
|
}
|
||||||
|
|
@ -185,9 +235,9 @@ 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->getActorID(), bulletShader, data.origin, data.direction, bulletSpeed, bulletDrop, bulletSize);
|
auto bullet = std::make_shared<Bullet>(wielder->getEntityID(), bulletShader, data.origin, data.direction, bulletSpeed, bulletDrop, bulletSize);
|
||||||
bullet->addComponent(bulletSprite);
|
bullet->addComponent(bulletSprite);
|
||||||
bullet->addPhysicsComponent(std::make_shared<PhysicsComponent>(PhysicsComponentFactory::makeBullet(wielder->getActorID(), 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;
|
||||||
|
|
||||||
if (eventManager)
|
if (eventManager)
|
||||||
|
|
@ -195,3 +245,22 @@ void Weapon::createBullet(const Weapon::BulletData& data)
|
||||||
bulletManager->addBullet(bullet);
|
bulletManager->addBullet(bullet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
!| SLATED FOR REMOVAL |!
|
||||||
|
|
||||||
|
// Swap the reload animation and the regular weapon animation
|
||||||
|
void Weapon::swapSprites()
|
||||||
|
{
|
||||||
|
//std::swap(weaponSprites.first, weaponSprites.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Weapon::checkAndFinishReload()
|
||||||
|
{
|
||||||
|
if (weaponSprites.first->kill() && reloading) {
|
||||||
|
weaponSprites.first->idle();
|
||||||
|
weaponSprites.first->reset();
|
||||||
|
std::swap(weaponSprites.first, weaponSprites.second);
|
||||||
|
reloading = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
|
||||||
181
YuppleMayham/src/graphics/animation.cpp
Normal file
181
YuppleMayham/src/graphics/animation.cpp
Normal file
|
|
@ -0,0 +1,181 @@
|
||||||
|
#include "graphics/animation.h"
|
||||||
|
#include "graphics/sprite.h"
|
||||||
|
#include "utility/xmlloader.h"
|
||||||
|
#include "utility/resourcemanager.h"
|
||||||
|
#include "utility/events.h"
|
||||||
|
|
||||||
|
Animation::Animation(const std::shared_ptr<AnimationData>& animData, ResourceManager* resourceManager) :
|
||||||
|
animName(animData->name),
|
||||||
|
animType(animData->type),
|
||||||
|
FPS(animData->FPS),
|
||||||
|
currentFrame(0),
|
||||||
|
cycles(0),
|
||||||
|
isDirectional(animData->directional),
|
||||||
|
isPlaying(isDirectional),
|
||||||
|
spriteAtlas(resourceManager->loadSpriteAtlas(animData->spriteAtlas, animData->frameSize, animData->directional))
|
||||||
|
{}
|
||||||
|
|
||||||
|
void Animation::bind()
|
||||||
|
{
|
||||||
|
spriteAtlas->bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::draw()
|
||||||
|
{
|
||||||
|
singleDraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::draw(Direction dir)
|
||||||
|
{
|
||||||
|
directionalDraw(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::singleDraw()
|
||||||
|
{
|
||||||
|
if (isPlaying)
|
||||||
|
{
|
||||||
|
frameTick();
|
||||||
|
auto frame = spriteAtlas->frame(currentFrame);
|
||||||
|
spriteAtlas->bindFrame(&frame);
|
||||||
|
spriteAtlas->draw();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto frame = spriteAtlas->frame(0);
|
||||||
|
spriteAtlas->bindFrame(&frame);
|
||||||
|
spriteAtlas->draw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::directionalDraw(Direction dir)
|
||||||
|
{
|
||||||
|
if (isPlaying)
|
||||||
|
{
|
||||||
|
frameTick();
|
||||||
|
}
|
||||||
|
auto frame = spriteAtlas->frame(currentFrame, dir);
|
||||||
|
spriteAtlas->bindFrame(&frame);
|
||||||
|
spriteAtlas->draw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Animation::frameTick()
|
||||||
|
{
|
||||||
|
Uint32 currentTime = SDL_GetTicks();
|
||||||
|
elapsedTime = currentTime - lastFrameTick;
|
||||||
|
if (elapsedTime >= 1000.0f / FPS)
|
||||||
|
{
|
||||||
|
if (++currentFrame > spriteAtlas->size() - 1)
|
||||||
|
{
|
||||||
|
currentFrame = 0;
|
||||||
|
cycles += 1;
|
||||||
|
}
|
||||||
|
lastFrameTick = currentTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimationSet::AnimationSet(const int& entityid) : entityid(entityid), isDirectional(false) {};
|
||||||
|
AnimationSet::AnimationSet(const int& entityid, ResourceManager* resourceManager, std::vector<std::shared_ptr<AnimationData>> animSet) : entityid(entityid)
|
||||||
|
{
|
||||||
|
for (const auto& anim : animSet)
|
||||||
|
{
|
||||||
|
anims.try_emplace(anim->type, std::make_shared<Animation>(anim, resourceManager));
|
||||||
|
if (anim->type == "idle")
|
||||||
|
curAnim = anims[anim->type];
|
||||||
|
}
|
||||||
|
// if we don't have an idle animation, we are just gonna set the current animation to the top of the set
|
||||||
|
if (curAnim == nullptr)
|
||||||
|
curAnim = anims[animSet[0]->type];
|
||||||
|
isDirectional = curAnim->getDirectional();
|
||||||
|
}
|
||||||
|
AnimationSet::AnimationSet(const int& entityid, const std::unordered_map<std::string, std::shared_ptr<Animation>>& animations) : entityid(entityid), anims(animations)
|
||||||
|
{
|
||||||
|
for (const auto& [type, anim] : animations)
|
||||||
|
{
|
||||||
|
curAnim = anim;
|
||||||
|
if (type == "idle")
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isDirectional = curAnim->getDirectional();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimationSet::attachEventManager(const std::shared_ptr<EventManager>& e)
|
||||||
|
{
|
||||||
|
eventManager = e;
|
||||||
|
|
||||||
|
eventManager->subscribe("OnDirectionChange", [this](std::shared_ptr<Event> e) {
|
||||||
|
auto directionEvent = std::static_pointer_cast<DirectionChangeEvent>(e);
|
||||||
|
if (directionEvent->entityid == entityid)
|
||||||
|
setFacingDir(directionEvent->direction);
|
||||||
|
});
|
||||||
|
|
||||||
|
eventManager->subscribe("OnEntityMove", [this](std::shared_ptr<Event> e) {
|
||||||
|
auto moveEvent = std::static_pointer_cast<EntityMoveEvent>(e);
|
||||||
|
if (moveEvent->entityid == entityid)
|
||||||
|
{
|
||||||
|
if (isDirectional)
|
||||||
|
{
|
||||||
|
if (anims["move"] != NULL)
|
||||||
|
curAnim = anims["move"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
play();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
eventManager->subscribe("OnEntityStop", [this](std::shared_ptr<Event> e) {
|
||||||
|
auto stopEvent = std::static_pointer_cast<EntityStopEvent>(e);
|
||||||
|
if (stopEvent->entityid == entityid)
|
||||||
|
{
|
||||||
|
if (isDirectional)
|
||||||
|
{
|
||||||
|
if (anims["idle"] != NULL)
|
||||||
|
curAnim = anims["idle"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
eventManager->subscribe("OnEntityReload", [this](std::shared_ptr<Event> e) {
|
||||||
|
auto reloadEvent = std::static_pointer_cast<EntityReloadEvent>(e);
|
||||||
|
if (reloadEvent->entityid == entityid)
|
||||||
|
{
|
||||||
|
if (anims["reload"] != NULL)
|
||||||
|
curAnim = anims["reload"];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
eventManager->subscribe("OnEntityFinishReload", [this](std::shared_ptr<Event> e) {
|
||||||
|
auto reloadEvent = std::static_pointer_cast<EntityFinishReloadEvent>(e);
|
||||||
|
if (reloadEvent->entityid == entityid)
|
||||||
|
{
|
||||||
|
if (anims["idle"] != NULL)
|
||||||
|
curAnim = anims["idle"];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimationSet::bind()
|
||||||
|
{
|
||||||
|
curAnim->bind();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnimationSet::draw()
|
||||||
|
{
|
||||||
|
int lastCycle = curAnim->getCycles();
|
||||||
|
if (curAnim->getDirectional())
|
||||||
|
curAnim->draw(facing);
|
||||||
|
else
|
||||||
|
curAnim->draw();
|
||||||
|
|
||||||
|
// Sending animation events
|
||||||
|
if (eventManager)
|
||||||
|
{
|
||||||
|
// If the animation has cycled, we send this event after every cycle
|
||||||
|
if ((curAnim->getCycles() - lastCycle) > 0)
|
||||||
|
eventManager->notify(std::make_shared<AnimationFinishedEvent>(entityid, curAnim->getType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -59,16 +59,21 @@ SpriteStatic::~SpriteStatic()
|
||||||
glDeleteVertexArrays(1, &VAO);
|
glDeleteVertexArrays(1, &VAO);
|
||||||
}
|
}
|
||||||
|
|
||||||
SpriteAnimated::SpriteAnimated(const char* textureAtlasPath, float frameSize)
|
SpriteAtlas::SpriteAtlas(const char* textureAtlasPath, float frameSize, bool isDirectional) : isDirectional(isDirectional), curFrame(nullptr)
|
||||||
{
|
{
|
||||||
EBO = 0;
|
EBO = 0;
|
||||||
texture = new Texture();
|
texture = new Texture();
|
||||||
texture->loadTexture(textureAtlasPath);
|
texture->loadTexture(textureAtlasPath);
|
||||||
if (texture)
|
if (texture)
|
||||||
SetupAnimated(frameSize);
|
{
|
||||||
|
if (!isDirectional)
|
||||||
|
Setup(frameSize);
|
||||||
|
else
|
||||||
|
SetupDirectional(frameSize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteAnimated::SetupAnimated(float frameSize)
|
void SpriteAtlas::Setup(float frameSize)
|
||||||
{
|
{
|
||||||
int width = texture->getWidth();
|
int width = texture->getWidth();
|
||||||
int height = texture->getHeight();
|
int height = texture->getHeight();
|
||||||
|
|
@ -110,57 +115,44 @@ void SpriteAnimated::SetupAnimated(float frameSize)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
ids.push_back({ VAO, VBO });
|
singleIDs.push_back({ VAO, VBO });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteAnimated::draw()
|
void SpriteAtlas::bindFrame(VertexIDs* f)
|
||||||
{
|
{
|
||||||
if (isPlaying)
|
curFrame = f;
|
||||||
{
|
|
||||||
Uint32 currentTime = SDL_GetTicks();
|
|
||||||
if (currentTime - lastFrameTick >= 1000.f / FPS)
|
|
||||||
{
|
|
||||||
if (++currentFrame > ids.size() - 1)
|
|
||||||
currentFrame = 0;
|
|
||||||
lastFrameTick = currentTime;
|
|
||||||
}
|
}
|
||||||
glBindVertexArray(ids[currentFrame].VAO);
|
|
||||||
|
void SpriteAtlas::draw()
|
||||||
|
{
|
||||||
|
glBindVertexArray(curFrame->VAO);
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
glBindVertexArray(ids[0].VAO);
|
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpriteAnimated::play() { isPlaying = true; }
|
SpriteAtlas::~SpriteAtlas()
|
||||||
void SpriteAnimated::idle() { isPlaying = false; }
|
|
||||||
|
|
||||||
SpriteAnimated::~SpriteAnimated()
|
|
||||||
{
|
{
|
||||||
delete texture;
|
delete texture;
|
||||||
glDeleteBuffers(1, &EBO);
|
glDeleteBuffers(1, &EBO);
|
||||||
for (VertexIDs idSet : ids)
|
for (VertexIDs idSet : singleIDs)
|
||||||
{
|
{
|
||||||
glDeleteBuffers(1, &idSet.VBO);
|
glDeleteBuffers(1, &idSet.VBO);
|
||||||
glDeleteVertexArrays(1, &idSet.VAO);
|
glDeleteVertexArrays(1, &idSet.VAO);
|
||||||
}
|
}
|
||||||
|
auto deleteBufferList = [](std::pair <Direction, std::vector<VertexIDs>> items) {
|
||||||
|
for (VertexIDs v : items.second) {
|
||||||
|
glDeleteBuffers(1, &v.VBO);
|
||||||
|
glDeleteVertexArrays(1, &v.VAO);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::for_each(directionalIDs.begin(), directionalIDs.end(), deleteBufferList);
|
||||||
|
singleIDs.clear();
|
||||||
|
directionalIDs.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
SpriteDirectionalAnimated::SpriteDirectionalAnimated(const char* textureAtlas, float frameSize)
|
void SpriteAtlas::SetupDirectional(float frameSize)
|
||||||
{
|
|
||||||
texture = new Texture();
|
|
||||||
texture->loadTexture(textureAtlas);
|
|
||||||
if (texture)
|
|
||||||
Setup(frameSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpriteDirectionalAnimated::Setup(float frameSize)
|
|
||||||
{
|
{
|
||||||
int width = texture->getWidth();
|
int width = texture->getWidth();
|
||||||
int height = texture->getHeight();
|
int height = texture->getHeight();
|
||||||
|
|
@ -174,10 +166,10 @@ void SpriteDirectionalAnimated::Setup(float frameSize)
|
||||||
for (int col = 0; col < frameCols; col++)
|
for (int col = 0; col < frameCols; col++)
|
||||||
{
|
{
|
||||||
Direction dir;
|
Direction dir;
|
||||||
// top of the spritesheet is the entities idle directions
|
// Directional spritesheets are stored, with an animation for each row,
|
||||||
// then each row is a 4 frame walk cycle of each direction
|
// on the first row we are looking down, then right etc...
|
||||||
if (row == 0) dir = (Direction)(col + 1);
|
// refer to utility/direction.h to each index
|
||||||
else dir = (Direction)(row);
|
dir = (Direction)(row + 1); // note we add one, since dir: 0 is None, this is for non-directional sprites
|
||||||
|
|
||||||
float left = (col) * (frameSize / width);
|
float left = (col) * (frameSize / width);
|
||||||
float right = (col + 1) * (frameSize / width);
|
float right = (col + 1) * (frameSize / width);
|
||||||
|
|
@ -209,56 +201,7 @@ void SpriteDirectionalAnimated::Setup(float frameSize)
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
if (row == 0)
|
directionalIDs[dir].push_back({ VAO, VBO });
|
||||||
idleIDs.emplace(std::pair<Direction, VertexIDs>(dir, { VAO, VBO }));
|
|
||||||
else
|
|
||||||
walkingIDs[dir].push_back({ VAO, VBO });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpriteDirectionalAnimated::draw()
|
|
||||||
{
|
|
||||||
if (isPlaying)
|
|
||||||
{
|
|
||||||
Uint32 currentTime = SDL_GetTicks();
|
|
||||||
if (currentTime - lastFrameTick >= 1000.f / FPS)
|
|
||||||
{
|
|
||||||
if (++currentFrame > walkingIDs[direction].size() - 1)
|
|
||||||
currentFrame = 0;
|
|
||||||
lastFrameTick = currentTime;
|
|
||||||
}
|
|
||||||
glBindVertexArray(walkingIDs[direction][currentFrame].VAO);
|
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
glBindVertexArray(idleIDs[direction].VAO);
|
|
||||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SpriteDirectionalAnimated::play() { isPlaying = true; }
|
|
||||||
void SpriteDirectionalAnimated::idle() { isPlaying = false; }
|
|
||||||
|
|
||||||
SpriteDirectionalAnimated::~SpriteDirectionalAnimated()
|
|
||||||
{
|
|
||||||
delete texture;
|
|
||||||
glDeleteBuffers(1, &EBO);
|
|
||||||
auto deleteBuffers = [](std::pair<Direction, VertexIDs> item) {
|
|
||||||
glDeleteBuffers(1, &item.second.VBO);
|
|
||||||
glDeleteVertexArrays(1, &item.second.VAO);
|
|
||||||
};
|
|
||||||
auto deleteBufferList = [](std::pair <Direction, std::vector<VertexIDs>> items) {
|
|
||||||
for (VertexIDs v : items.second) {
|
|
||||||
glDeleteBuffers(1, &v.VBO);
|
|
||||||
glDeleteVertexArrays(1, &v.VAO);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
std::for_each(idleIDs.begin(), idleIDs.end(), deleteBuffers);
|
|
||||||
std::for_each(walkingIDs.begin(), walkingIDs.end(), deleteBufferList);
|
|
||||||
idleIDs.clear();
|
|
||||||
walkingIDs.clear();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -5,23 +5,19 @@
|
||||||
#include "utility/script.h"
|
#include "utility/script.h"
|
||||||
#include "graphics/tiletype.h"
|
#include "graphics/tiletype.h"
|
||||||
#include "graphics/shader.h"
|
#include "graphics/shader.h"
|
||||||
|
#include "graphics/animation.h"
|
||||||
#include "gameplay/weapons/weapons.h"
|
#include "gameplay/weapons/weapons.h"
|
||||||
|
|
||||||
std::shared_ptr<Sprite> ResourceManager::loadSpriteAnimated(const std::string& path, float frameSize)
|
std::shared_ptr<SpriteAtlas> ResourceManager::loadSpriteAtlas(const std::string& path, float frameSize, bool isDirectional)
|
||||||
{
|
{
|
||||||
auto iterator = sprites.find(path);
|
auto iterator = sprites.find(path);
|
||||||
if (iterator != sprites.end())
|
if (iterator != sprites.end())
|
||||||
return iterator->second;
|
return std::dynamic_pointer_cast<SpriteAtlas>(iterator->second);
|
||||||
auto sprite = std::make_shared<SpriteAnimated>(path.c_str(), frameSize);
|
auto sprite = std::make_shared<SpriteAtlas>(path.c_str(), frameSize, isDirectional);
|
||||||
sprites[path] = sprite;
|
sprites[path] = sprite;
|
||||||
return sprite;
|
return sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Sprite> ResourceManager::loadSpriteDirAnimated(const std::string& path, float frameSize)
|
|
||||||
{
|
|
||||||
return std::make_shared<SpriteDirectionalAnimated>(path.c_str(), frameSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<Sprite> ResourceManager::loadSpriteStatic(const std::string& path)
|
std::shared_ptr<Sprite> ResourceManager::loadSpriteStatic(const std::string& path)
|
||||||
{
|
{
|
||||||
auto iterator = sprites.find(path);
|
auto iterator = sprites.find(path);
|
||||||
|
|
@ -78,6 +74,12 @@ std::shared_ptr<SceneData> ResourceManager::loadScene(const std::string& id)
|
||||||
return xmlLoader->getSceneData(id);
|
return xmlLoader->getSceneData(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<AnimationSet> ResourceManager::loadAnimationSet(const std::string& name, int entityid)
|
||||||
|
{
|
||||||
|
auto animSetData = xmlLoader->getAnimationSet(name);
|
||||||
|
return std::make_shared<AnimationSet>(entityid, this, animSetData);
|
||||||
|
}
|
||||||
|
|
||||||
// this will need some work, but for now where there is only one weapon type we can work with it
|
// this will need some work, but for now where there is only one weapon type we can work with it
|
||||||
// TODO: Allow different weapon types!
|
// TODO: Allow different weapon types!
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -127,50 +127,72 @@ bool XMLLoader::loadEntityData(const char* xmlFile, SceneData* out)
|
||||||
tinyxml2::XMLElement* playerElement = entities->FirstChildElement("player");
|
tinyxml2::XMLElement* playerElement = entities->FirstChildElement("player");
|
||||||
if (playerElement == NULL)
|
if (playerElement == NULL)
|
||||||
return false;
|
return false;
|
||||||
int x, y;
|
|
||||||
float frameSize = 64.f;
|
EntityData playData;
|
||||||
bool isDirectional = false;
|
const char *graphic, *weaponName = "pistolGun";
|
||||||
const char* spritePath, * weaponName = "pistolGun";
|
|
||||||
if (playerElement->QueryIntAttribute("x", &x) != tinyxml2::XML_SUCCESS ||
|
if (playerElement->QueryIntAttribute("x", &playData.x) != tinyxml2::XML_SUCCESS ||
|
||||||
playerElement->QueryIntAttribute("y", &y) != tinyxml2::XML_SUCCESS)
|
playerElement->QueryIntAttribute("y", &playData.y) != tinyxml2::XML_SUCCESS)
|
||||||
return false;
|
return false;
|
||||||
playerElement->QueryStringAttribute("weapon", &weaponName);
|
playerElement->QueryStringAttribute("weapon", &weaponName);
|
||||||
|
tinyxml2::XMLElement* anim = playerElement->FirstChildElement("animation");
|
||||||
|
if (anim == NULL)
|
||||||
|
{
|
||||||
|
playData.animated = false;
|
||||||
tinyxml2::XMLElement* sprite = playerElement->FirstChildElement("sprite");
|
tinyxml2::XMLElement* sprite = playerElement->FirstChildElement("sprite");
|
||||||
if (sprite == NULL)
|
if (sprite == NULL)
|
||||||
return false;
|
return false;
|
||||||
if (sprite->QueryStringAttribute("file", &spritePath) != tinyxml2::XML_SUCCESS)
|
if (sprite->QueryStringAttribute("file", &graphic) != tinyxml2::XML_SUCCESS)
|
||||||
return false;
|
return false;
|
||||||
sprite->QueryFloatAttribute("framesize", &frameSize);
|
}
|
||||||
sprite->QueryBoolAttribute("directional", &isDirectional);
|
else
|
||||||
out->entities.push_back({ true, x, y, spritePath, frameSize, weaponName, "", isDirectional});
|
{
|
||||||
|
playData.animated = true;
|
||||||
|
if (anim->QueryStringAttribute("name", &graphic) != tinyxml2::XML_SUCCESS)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
playData.isPlayer = true;
|
||||||
|
playData.graphic = graphic;
|
||||||
|
playData.weapon = weaponName;
|
||||||
|
|
||||||
|
out->entities.push_back(playData);
|
||||||
|
|
||||||
// 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"))
|
||||||
{
|
{
|
||||||
int x, y;
|
|
||||||
float frameSize = 64.f;
|
EntityData data;
|
||||||
const char* spritePath, * weaponName = "pistolGun", * scriptPath;
|
const char *graphic, *weaponName = "pistolGun", *scriptPath;
|
||||||
bool isDirectional = false;
|
if (e->QueryIntAttribute("x", &data.x) != tinyxml2::XML_SUCCESS ||
|
||||||
if (e->QueryIntAttribute("x", &x) != tinyxml2::XML_SUCCESS ||
|
e->QueryIntAttribute("y", &data.y) != tinyxml2::XML_SUCCESS)
|
||||||
e->QueryIntAttribute("y", &y) != tinyxml2::XML_SUCCESS)
|
|
||||||
return false;
|
return false;
|
||||||
e->QueryStringAttribute("weapon", &weaponName);
|
e->QueryStringAttribute("weapon", &weaponName);
|
||||||
|
tinyxml2::XMLElement* anim = e->FirstChildElement("animation");
|
||||||
|
if (anim == NULL)
|
||||||
|
{
|
||||||
|
data.animated = false;
|
||||||
tinyxml2::XMLElement* sprite = e->FirstChildElement("sprite");
|
tinyxml2::XMLElement* sprite = e->FirstChildElement("sprite");
|
||||||
if (sprite == NULL)
|
if (sprite == NULL)
|
||||||
return false;
|
continue;
|
||||||
if (sprite->QueryStringAttribute("file", &spritePath) != tinyxml2::XML_SUCCESS)
|
if (sprite->QueryStringAttribute("file", &graphic) != tinyxml2::XML_SUCCESS)
|
||||||
return false;
|
|
||||||
sprite->QueryFloatAttribute("frameSize", &frameSize);
|
|
||||||
sprite->QueryBoolAttribute("directional", &isDirectional);
|
|
||||||
tinyxml2::XMLElement* script = e->FirstChildElement("script");
|
|
||||||
if (script == NULL || script->QueryStringAttribute("file", &scriptPath))
|
|
||||||
{
|
|
||||||
out->entities.push_back({ false, x, y, spritePath, frameSize, weaponName, "", isDirectional });
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
out->entities.push_back({ false, x, y, spritePath, frameSize, weaponName, scriptPath, isDirectional });
|
else
|
||||||
|
{
|
||||||
|
data.animated = true;
|
||||||
|
if (anim->QueryStringAttribute("name", &graphic) != tinyxml2::XML_SUCCESS)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tinyxml2::XMLElement* script = e->FirstChildElement("script");
|
||||||
|
script->QueryStringAttribute("file", &scriptPath);
|
||||||
|
data.isPlayer = false;
|
||||||
|
data.graphic = graphic;
|
||||||
|
data.script = scriptPath;
|
||||||
|
data.weapon = weaponName;
|
||||||
|
|
||||||
|
out->entities.push_back(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -207,11 +229,13 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
|
||||||
{
|
{
|
||||||
// populate weapon data into this temp buffer, then push it into our list of weapons
|
// populate weapon data into this temp buffer, then push it into our list of weapons
|
||||||
WeaponData data;
|
WeaponData data;
|
||||||
const char* name, * sprite, * bulletSprite, * script;
|
const char *name, *graphic, *bulletGraphic, *script;
|
||||||
// Getting top level weapon data, attribs in the weapon Node
|
// Getting top level weapon data, attribs in the weapon Node
|
||||||
if (weapon->QueryStringAttribute("name", &name) != tinyxml2::XML_SUCCESS)
|
if (weapon->QueryStringAttribute("name", &name) != tinyxml2::XML_SUCCESS)
|
||||||
continue;
|
continue;
|
||||||
weapon->QueryFloatAttribute("fireSpeed", &data.fireSpeed);
|
weapon->QueryFloatAttribute("fireSpeed", &data.fireSpeed);
|
||||||
|
weapon->QueryIntAttribute("maxAmmo", &data.maxAmmo);
|
||||||
|
weapon->QueryIntAttribute("clipSize", &data.clipSize);
|
||||||
// Getting script file if Node exists
|
// Getting script file if Node exists
|
||||||
tinyxml2::XMLElement* wepScript = weapon->FirstChildElement("script");
|
tinyxml2::XMLElement* wepScript = weapon->FirstChildElement("script");
|
||||||
if (wepScript)
|
if (wepScript)
|
||||||
|
|
@ -219,13 +243,31 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
|
||||||
else
|
else
|
||||||
script = "";
|
script = "";
|
||||||
// Getting weapon sprite information, held in the sprite node
|
// Getting weapon sprite information, held in the sprite node
|
||||||
tinyxml2::XMLElement* wepSprite = weapon->FirstChildElement("sprite");
|
tinyxml2::XMLElement* anim = weapon->FirstChildElement("animation");
|
||||||
if (wepSprite)
|
if (anim)
|
||||||
{
|
{
|
||||||
wepSprite->QueryStringAttribute("file", &sprite);
|
data.animated = true;
|
||||||
wepSprite->QueryBoolAttribute("animated", &data.animated);
|
if (anim->QueryStringAttribute("name", &graphic) != tinyxml2::XML_SUCCESS)
|
||||||
if (data.animated)
|
continue;
|
||||||
wepSprite->QueryFloatAttribute("frameSize", &data.frameSize);
|
|
||||||
|
if (anim->ChildElementCount() != 0)
|
||||||
|
{
|
||||||
|
tinyxml2::XMLElement* size = anim->FirstChildElement("size");
|
||||||
|
size->QueryFloatAttribute("x", &data.sizeX);
|
||||||
|
size->QueryFloatAttribute("y", &data.sizeY);
|
||||||
|
tinyxml2::XMLElement* offset = anim->FirstChildElement("offset");
|
||||||
|
offset->QueryFloatAttribute("x", &data.offsetX);
|
||||||
|
offset->QueryFloatAttribute("y", &data.offsetY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tinyxml2::XMLElement* wepSprite = weapon->FirstChildElement("sprite");
|
||||||
|
if (wepSprite == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
wepSprite->QueryStringAttribute("file", &graphic);
|
||||||
|
data.animated = false;
|
||||||
if (wepSprite->ChildElementCount() != 0)
|
if (wepSprite->ChildElementCount() != 0)
|
||||||
{
|
{
|
||||||
tinyxml2::XMLElement* size = wepSprite->FirstChildElement("size");
|
tinyxml2::XMLElement* size = wepSprite->FirstChildElement("size");
|
||||||
|
|
@ -236,31 +278,32 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
|
||||||
offset->QueryFloatAttribute("y", &data.offsetY);
|
offset->QueryFloatAttribute("y", &data.offsetY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// If we don't have a sprite element, default to pistol
|
|
||||||
sprite = "sprites/pistolAtlas256.png";
|
|
||||||
data.animated = true;
|
|
||||||
data.frameSize = 256.f;
|
|
||||||
data.sizeX = 30.f;
|
|
||||||
data.sizeY = 30.f;
|
|
||||||
}
|
|
||||||
// getting bullet information held in the bullet node and each child node held therein
|
// getting bullet information held in the bullet node and each child node held therein
|
||||||
tinyxml2::XMLElement* bullet = weapon->FirstChildElement("bullet");
|
tinyxml2::XMLElement* bullet = weapon->FirstChildElement("bullet");
|
||||||
|
|
||||||
if (bullet->QueryStringAttribute("sprite", &bulletSprite) != tinyxml2::XML_SUCCESS ||
|
if (bullet->FindAttribute("anim"))
|
||||||
bullet->QueryBoolAttribute( "animated", &data.bulletAnimated) != tinyxml2::XML_SUCCESS ||
|
{
|
||||||
bullet->FirstChildElement("size")->QueryFloatAttribute("x", &data.bulletSizeX) != tinyxml2::XML_SUCCESS ||
|
data.bulletAnimated = true;
|
||||||
|
if (bullet->QueryStringAttribute("anim", &bulletGraphic) != tinyxml2::XML_SUCCESS)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.bulletAnimated = false;
|
||||||
|
if (bullet->QueryStringAttribute("sprite", &bulletGraphic) != tinyxml2::XML_SUCCESS)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (bullet->FirstChildElement("size")->QueryFloatAttribute("x", &data.bulletSizeX) != tinyxml2::XML_SUCCESS ||
|
||||||
bullet->FirstChildElement("size")->QueryFloatAttribute("y", &data.bulletSizeY) != tinyxml2::XML_SUCCESS)
|
bullet->FirstChildElement("size")->QueryFloatAttribute("y", &data.bulletSizeY) != tinyxml2::XML_SUCCESS)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
data.name = name;
|
data.name = name;
|
||||||
data.script = script;
|
data.script = script;
|
||||||
data.sprite = sprite;
|
data.graphic = graphic;
|
||||||
data.bulletSprite = bulletSprite;
|
data.bulletGraphic = bulletGraphic;
|
||||||
|
|
||||||
if (data.animated)
|
|
||||||
if (bullet->QueryFloatAttribute("frameSize", &data.bulletFrameSize) != tinyxml2::XML_SUCCESS)
|
|
||||||
continue;
|
|
||||||
tinyxml2::XMLElement* spread = bullet->FirstChildElement("spread");
|
tinyxml2::XMLElement* spread = bullet->FirstChildElement("spread");
|
||||||
tinyxml2::XMLElement* speed = bullet->FirstChildElement("speed");
|
tinyxml2::XMLElement* speed = bullet->FirstChildElement("speed");
|
||||||
tinyxml2::XMLElement* drop = bullet->FirstChildElement("drop");
|
tinyxml2::XMLElement* drop = bullet->FirstChildElement("drop");
|
||||||
|
|
@ -282,3 +325,47 @@ bool XMLLoader::loadWeapons(const char* weaponFolder)
|
||||||
}
|
}
|
||||||
return (!weaponData.empty());
|
return (!weaponData.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool XMLLoader::loadAnimations(const char* animationFolder)
|
||||||
|
{
|
||||||
|
std::filesystem::path folder(animationFolder);
|
||||||
|
if (!std::filesystem::exists(folder) || !std::filesystem::is_directory(folder))
|
||||||
|
return false;
|
||||||
|
for (auto& file : std::filesystem::directory_iterator(folder))
|
||||||
|
{
|
||||||
|
if (!file.path().has_extension() || !file.path().has_filename() || !file.exists() || file.is_directory())
|
||||||
|
continue;
|
||||||
|
tinyxml2::XMLDocument doc;
|
||||||
|
if (doc.LoadFile(file.path().generic_string().c_str()) != tinyxml2::XML_SUCCESS)
|
||||||
|
continue;
|
||||||
|
tinyxml2::XMLElement* anims = doc.FirstChildElement("animations");
|
||||||
|
bool directional = false;
|
||||||
|
anims->QueryBoolAttribute("directional", &directional);
|
||||||
|
if (anims == NULL)
|
||||||
|
continue;
|
||||||
|
for (tinyxml2::XMLElement* e = anims->FirstChildElement("animation"); e != NULL; e = e->NextSiblingElement("animation"))
|
||||||
|
{
|
||||||
|
AnimationData animData;
|
||||||
|
const char *name, *type, *spriteAtlas;
|
||||||
|
|
||||||
|
if (e->QueryStringAttribute("name", &name) != tinyxml2::XML_SUCCESS ||
|
||||||
|
e->QueryStringAttribute("type", &type) != tinyxml2::XML_SUCCESS)
|
||||||
|
continue;
|
||||||
|
tinyxml2::XMLElement* fps = e->FirstChildElement("FPS");
|
||||||
|
fps->QueryFloatText(&animData.FPS);
|
||||||
|
|
||||||
|
tinyxml2::XMLElement* sprite = e->FirstChildElement("sprite");
|
||||||
|
if (sprite->QueryStringAttribute("path", &spriteAtlas) != tinyxml2::XML_SUCCESS ||
|
||||||
|
sprite->QueryFloatAttribute("frameSize", &animData.frameSize) != tinyxml2::XML_SUCCESS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
animData.name = name;
|
||||||
|
animData.type = type;
|
||||||
|
animData.spriteAtlas = spriteAtlas;
|
||||||
|
animData.animSet = file.path().stem().string();
|
||||||
|
animData.directional = directional;
|
||||||
|
animations.try_emplace(animData.name, std::make_shared<AnimationData>(animData));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue