SpriteRenderer
This commit is contained in:
@ -0,0 +1,132 @@
|
||||
// IAEngine: 2D Game Engine by IA
|
||||
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <IAEngine/Engine.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
SpriteComponent::SpriteComponent(IN Node2D *node) : TextureComponent(node)
|
||||
{
|
||||
}
|
||||
|
||||
VOID SpriteComponent::Draw()
|
||||
{
|
||||
const auto &animFrame = m_currentAnimationState;
|
||||
PositionOffset() = animFrame.Position;
|
||||
ScaleOffset() = animFrame.Scale;
|
||||
RotationOffset() = animFrame.Rotation;
|
||||
ColorOverlay() = animFrame.ColorOverlay;
|
||||
SetTexture(animFrame.Texture);
|
||||
TextureComponent::Draw();
|
||||
}
|
||||
|
||||
VOID SpriteComponent::DebugDraw()
|
||||
{
|
||||
TextureComponent::DebugDraw();
|
||||
}
|
||||
|
||||
VOID SpriteComponent::Update()
|
||||
{
|
||||
TextureComponent::Update();
|
||||
|
||||
UpdateAnimation();
|
||||
}
|
||||
|
||||
VOID SpriteComponent::FixedUpdate()
|
||||
{
|
||||
TextureComponent::FixedUpdate();
|
||||
}
|
||||
|
||||
Handle SpriteComponent::AddAnimation(IN CONST Animation &animation)
|
||||
{
|
||||
if (animation.Keys.empty())
|
||||
return INVALID_HANDLE;
|
||||
m_animations.pushBack(animation);
|
||||
if(m_animations.size() == 1)
|
||||
ForceSetActiveAnimation(0);
|
||||
return m_animations.size() - 1;
|
||||
}
|
||||
|
||||
VOID SpriteComponent::SetActiveAnimation(IN Handle animation)
|
||||
{
|
||||
if (animation == m_activeAnimationHandle)
|
||||
return;
|
||||
ForceSetActiveAnimation(animation);
|
||||
}
|
||||
|
||||
VOID SpriteComponent::ForceSetActiveAnimation(IN Handle animation)
|
||||
{
|
||||
IA_RELEASE_ASSERT((animation != INVALID_HANDLE) && (animation < m_animations.size()));
|
||||
m_prevAnimationKeyFrameIndex = 0;
|
||||
m_activeAnimation = m_animations[animation];
|
||||
|
||||
m_prevAnimationKeyFrame = GetKeyFrame(m_prevAnimationKeyFrameIndex + 0);
|
||||
m_nextAnimationKeyFrame = GetKeyFrame(m_prevAnimationKeyFrameIndex + 1);
|
||||
|
||||
m_currentAnimationState = m_prevAnimationKeyFrame;
|
||||
m_activeAnimationHandle = animation;
|
||||
|
||||
SetTexture(m_currentAnimationState.Texture);
|
||||
}
|
||||
|
||||
VOID SpriteComponent::SetAnimationFrame(IN INT32 animation, IN INT32 frame)
|
||||
{
|
||||
m_activeAnimation = {};
|
||||
m_currentAnimationState = m_animations[animation].Keys[frame];
|
||||
}
|
||||
|
||||
VOID SpriteComponent::UpdateAnimation()
|
||||
{
|
||||
const auto keyCount = m_activeAnimation.Keys.size();
|
||||
if (keyCount <= 1)
|
||||
return;
|
||||
|
||||
if (m_currentAnimationState.ShouldInterpolate)
|
||||
{
|
||||
const auto t = m_timelinePosition / m_prevAnimationKeyFrame.Duration;
|
||||
#define INTERP_PROPERTY(name) \
|
||||
m_currentAnimationState.name = \
|
||||
m_prevAnimationKeyFrame.name + (m_nextAnimationKeyFrame.name - m_prevAnimationKeyFrame.name) * t;
|
||||
|
||||
INTERP_PROPERTY(Position);
|
||||
INTERP_PROPERTY(Rotation);
|
||||
INTERP_PROPERTY(Scale);
|
||||
INTERP_PROPERTY(ColorOverlay);
|
||||
|
||||
#undef INTERP_PROPERTY
|
||||
}
|
||||
|
||||
if (m_timelinePosition >= m_prevAnimationKeyFrame.Duration)
|
||||
{
|
||||
m_prevAnimationKeyFrameIndex = (m_prevAnimationKeyFrameIndex + 1) % keyCount;
|
||||
if (!m_prevAnimationKeyFrameIndex && !m_activeAnimation.ShouldLoop)
|
||||
{
|
||||
m_activeAnimation = {};
|
||||
return;
|
||||
}
|
||||
m_prevAnimationKeyFrame = GetKeyFrame(m_prevAnimationKeyFrameIndex + 0);
|
||||
m_nextAnimationKeyFrame = GetKeyFrame(m_prevAnimationKeyFrameIndex + 1);
|
||||
m_currentAnimationState = m_prevAnimationKeyFrame;
|
||||
m_timelinePosition = 0;
|
||||
}
|
||||
m_timelinePosition += Engine::GetFrameDeltaTime() * 1000;
|
||||
}
|
||||
|
||||
SpriteComponent::AnimationKeyFrame SpriteComponent::GetKeyFrame(IN INT32 index)
|
||||
{
|
||||
return m_activeAnimation.Keys[index % m_activeAnimation.Keys.size()];
|
||||
}
|
||||
} // namespace ia::iae
|
||||
25
Engine/Src/Imp/CPP/Nodes/SpriteNode.cpp
Normal file
25
Engine/Src/Imp/CPP/Nodes/SpriteNode.cpp
Normal file
@ -0,0 +1,25 @@
|
||||
// IAEngine: 2D Game Engine by IA
|
||||
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#include <IAEngine/Engine.hpp>
|
||||
#include <IAEngine/Nodes/SpriteNode.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
SpriteNode::SpriteNode(IN CONST String &name) : Node2D(name), m_spriteComponent(AddComponent<SpriteComponent>())
|
||||
{
|
||||
}
|
||||
} // namespace ia::iae
|
||||
@ -16,12 +16,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IACore/Map.hpp>
|
||||
#include <IACore/Exception.hpp>
|
||||
#include <IACore/Logger.hpp>
|
||||
#include <IACore/Map.hpp>
|
||||
#include <IACore/Memory.hpp>
|
||||
#include <IACore/String.hpp>
|
||||
#include <IACore/Vector.hpp>
|
||||
#include <IACore/Exception.hpp>
|
||||
|
||||
#include <IAEngine/glm/ext/matrix_clip_space.hpp>
|
||||
#include <IAEngine/glm/ext/matrix_transform.hpp>
|
||||
@ -111,7 +111,22 @@ namespace ia::iae
|
||||
|
||||
Vec4 GetAsFloatVec() CONST
|
||||
{
|
||||
return {(FLOAT32)R/255.0f, (FLOAT32)G/255.0f, (FLOAT32)B/255.0f, (FLOAT32)A/255.0f};
|
||||
return {(FLOAT32) R / 255.0f, (FLOAT32) G / 255.0f, (FLOAT32) B / 255.0f, (FLOAT32) A / 255.0f};
|
||||
}
|
||||
|
||||
Color operator+(IN CONST Color &other) CONST
|
||||
{
|
||||
return Color{(UINT8) (R + other.R), (UINT8) (G + other.G), (UINT8) (B + other.B), (UINT8) (A + other.A)};
|
||||
}
|
||||
|
||||
Color operator-(IN CONST Color &other) CONST
|
||||
{
|
||||
return Color{(UINT8) (R - other.R), (UINT8) (G - other.G), (UINT8) (B - other.B), (UINT8) (A - other.A)};
|
||||
}
|
||||
|
||||
Color operator*(IN FLOAT32 v) CONST
|
||||
{
|
||||
return Color{(UINT8) (R * v), (UINT8) (G * v), (UINT8) (B * v), (UINT8) (A * v)};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -0,0 +1,88 @@
|
||||
// IAEngine: 2D Game Engine by IA
|
||||
// Copyright (C) 2025 IASoft (PVT) LTD (oss@iasoft.dev)
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Components/TextureComponent.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
class SpriteComponent : public TextureComponent
|
||||
{
|
||||
public:
|
||||
struct AnimationKeyFrame
|
||||
{
|
||||
Handle Texture;
|
||||
INT32 Duration{100};
|
||||
BOOL ShouldInterpolate{};
|
||||
|
||||
FLOAT32 Rotation{};
|
||||
Vec2 Position{};
|
||||
Vec2 Scale{1.0f, 1.0f};
|
||||
Color ColorOverlay{0xFF, 0xFF, 0xFF, 0xFF};
|
||||
};
|
||||
|
||||
struct Animation
|
||||
{
|
||||
BOOL ShouldLoop{false};
|
||||
Vector<AnimationKeyFrame> Keys;
|
||||
};
|
||||
|
||||
public:
|
||||
SpriteComponent(IN Node2D *node);
|
||||
|
||||
public:
|
||||
VIRTUAL VOID Draw();
|
||||
VIRTUAL VOID DebugDraw();
|
||||
|
||||
VIRTUAL VOID Update();
|
||||
VIRTUAL VOID FixedUpdate();
|
||||
|
||||
public:
|
||||
Handle AddAnimation(IN CONST Animation &animation);
|
||||
|
||||
VOID SetActiveAnimation(IN Handle animation);
|
||||
VOID ForceSetActiveAnimation(IN Handle animation);
|
||||
|
||||
VOID SetAnimationFrame(IN INT32 animation, IN INT32 frame);
|
||||
|
||||
public:
|
||||
Vector<Animation> &Animations()
|
||||
{
|
||||
return m_animations;
|
||||
}
|
||||
|
||||
CONST Vector<Animation> &Animations() CONST
|
||||
{
|
||||
return m_animations;
|
||||
}
|
||||
|
||||
private:
|
||||
VOID UpdateAnimation();
|
||||
|
||||
AnimationKeyFrame GetKeyFrame(IN INT32 index);
|
||||
|
||||
private:
|
||||
FLOAT32 m_timelinePosition{};
|
||||
Animation m_activeAnimation{};
|
||||
Handle m_activeAnimationHandle{INVALID_HANDLE};
|
||||
Vector<Animation> m_animations;
|
||||
AnimationKeyFrame m_currentAnimationState{};
|
||||
AnimationKeyFrame m_nextAnimationKeyFrame{};
|
||||
AnimationKeyFrame m_prevAnimationKeyFrame{};
|
||||
INT32 m_prevAnimationKeyFrameIndex{};
|
||||
};
|
||||
} // namespace ia::iae
|
||||
@ -23,17 +23,17 @@ namespace ia::iae
|
||||
class TextureComponent : public IComponent
|
||||
{
|
||||
public:
|
||||
TextureComponent(IN Node2D *node);
|
||||
TextureComponent(IN Node2D *node);
|
||||
|
||||
public:
|
||||
VOID Draw();
|
||||
VOID DebugDraw();
|
||||
|
||||
VOID Update();
|
||||
VOID FixedUpdate();
|
||||
VIRTUAL VOID Draw();
|
||||
VIRTUAL VOID DebugDraw();
|
||||
|
||||
VIRTUAL VOID Update();
|
||||
VIRTUAL VOID FixedUpdate();
|
||||
|
||||
public:
|
||||
VOID SetTexture(IN Handle image);
|
||||
VOID SetTexture(IN Handle image);
|
||||
|
||||
Handle GetTexture() CONST
|
||||
{
|
||||
@ -97,6 +97,6 @@ namespace ia::iae
|
||||
Vec2 m_drawnSize{};
|
||||
|
||||
Vec2 m_textureExtent{};
|
||||
Handle m_texture{INVALID_HANDLE};
|
||||
Handle m_texture{0};
|
||||
};
|
||||
} // namespace ia::iae
|
||||
@ -16,10 +16,23 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <IAEngine/Nodes/Node2D.hpp>
|
||||
#include <IAEngine/Components/SpriteComponent.hpp>
|
||||
#include <IAEngine/Nodes/Node2D.hpp>
|
||||
|
||||
namespace ia::iae
|
||||
{
|
||||
|
||||
}
|
||||
class SpriteNode : public Node2D
|
||||
{
|
||||
public:
|
||||
SpriteNode(IN CONST String &name);
|
||||
|
||||
public:
|
||||
SpriteComponent *GetSpriteComponent()
|
||||
{
|
||||
return m_spriteComponent;
|
||||
}
|
||||
|
||||
protected:
|
||||
SpriteComponent *CONST m_spriteComponent{};
|
||||
};
|
||||
} // namespace ia::iae
|
||||
Reference in New Issue
Block a user