feat(场景管理): 实现场景管理系统及基础2D角色框架
添加场景管理器(SceneManager)和场景(Scene)类,用于管理游戏场景的压入、弹出和切换 实现基础2D角色(Actor)类,支持父子关系和场景管理 添加侵入式链表(IntrusiveList)工具类,用于高效管理场景中的角色对象 在应用主循环中集成场景更新和渲染逻辑
This commit is contained in:
90
Frostbite2D/include/frostbite2D/2d/actor.h
Normal file
90
Frostbite2D/include/frostbite2D/2d/actor.h
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/base/RefObject.h>
|
||||||
|
#include <frostbite2D/types/type_alias.h>
|
||||||
|
#include <frostbite2D/types/type_math.h>
|
||||||
|
#include <frostbite2D/utils/intrusive_list.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
class Actor;
|
||||||
|
class Scene;
|
||||||
|
|
||||||
|
using ActorList = IntrusiveList<RefPtr<Actor>>;
|
||||||
|
|
||||||
|
class Actor : public RefObject, protected IntrusiveListValue<RefPtr<Actor>> {
|
||||||
|
public:
|
||||||
|
using IntrusiveListValue<RefPtr<Actor>>::GetNext;
|
||||||
|
using IntrusiveListValue<RefPtr<Actor>>::GetPrev;
|
||||||
|
|
||||||
|
Actor();
|
||||||
|
virtual ~Actor();
|
||||||
|
|
||||||
|
virtual void Update(float deltaTime);
|
||||||
|
virtual void Render();
|
||||||
|
|
||||||
|
void AddChild(RefPtr<Actor> child);
|
||||||
|
void RemoveChild(RefPtr<Actor> child);
|
||||||
|
void RemoveAllChildren();
|
||||||
|
|
||||||
|
Actor* GetParent() const { return parent_; }
|
||||||
|
Scene* GetScene() const { return scene_; }
|
||||||
|
|
||||||
|
const std::string& GetName() const { return name_; }
|
||||||
|
void SetName(const std::string& name) { name_ = name; }
|
||||||
|
|
||||||
|
const Vec2& GetPosition() const { return position_; }
|
||||||
|
void SetPosition(const Vec2& pos) { position_ = pos; }
|
||||||
|
void SetPosition(float x, float y) { position_ = Vec2(x, y); }
|
||||||
|
|
||||||
|
float GetRotation() const { return rotation_; }
|
||||||
|
void SetRotation(float rotation) { rotation_ = rotation; }
|
||||||
|
|
||||||
|
const Vec2& GetScale() const { return scale_; }
|
||||||
|
void SetScale(const Vec2& scale) { scale_ = scale; }
|
||||||
|
void SetScale(float scale) { scale_ = Vec2(scale, scale); }
|
||||||
|
|
||||||
|
const Vec2& GetSize() const { return size_; }
|
||||||
|
void SetSize(const Vec2& size) { size_ = size; }
|
||||||
|
void SetSize(float width, float height) { size_ = Vec2(width, height); }
|
||||||
|
|
||||||
|
bool IsVisible() const { return visible_; }
|
||||||
|
void SetVisible(bool visible) { visible_ = visible; }
|
||||||
|
|
||||||
|
int GetZOrder() const { return zOrder_; }
|
||||||
|
void SetZOrder(int zOrder) { zOrder_ = zOrder; }
|
||||||
|
|
||||||
|
float GetOpacity() const { return opacity_; }
|
||||||
|
void SetOpacity(float opacity) { opacity_ = opacity; }
|
||||||
|
|
||||||
|
ActorList& GetChildren() { return children_; }
|
||||||
|
const ActorList& GetChildren() const { return children_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetParent(Actor* parent) { parent_ = parent; }
|
||||||
|
void SetScene(Scene* scene) { scene_ = scene; }
|
||||||
|
|
||||||
|
void UpdateChildren(float deltaTime);
|
||||||
|
void RenderChildren();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Actor* parent_;
|
||||||
|
Scene* scene_;
|
||||||
|
ActorList children_;
|
||||||
|
|
||||||
|
std::string name_;
|
||||||
|
Vec2 position_;
|
||||||
|
float rotation_;
|
||||||
|
Vec2 scale_;
|
||||||
|
Vec2 size_;
|
||||||
|
bool visible_;
|
||||||
|
int zOrder_;
|
||||||
|
float opacity_;
|
||||||
|
|
||||||
|
friend class Scene;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
40
Frostbite2D/include/frostbite2D/scene/scene.h
Normal file
40
Frostbite2D/include/frostbite2D/scene/scene.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/base/RefObject.h>
|
||||||
|
#include <frostbite2D/types/type_alias.h>
|
||||||
|
#include <frostbite2D/utils/intrusive_list.hpp>
|
||||||
|
#include <frostbite2D/2d/actor.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
using ActorList = IntrusiveList<RefPtr<Actor>>;
|
||||||
|
|
||||||
|
class Scene : public RefObject {
|
||||||
|
public:
|
||||||
|
Scene();
|
||||||
|
virtual ~Scene();
|
||||||
|
|
||||||
|
virtual void onEnter();
|
||||||
|
virtual void onExit();
|
||||||
|
|
||||||
|
void Update(float deltaTime);
|
||||||
|
void Render();
|
||||||
|
|
||||||
|
void AddActor(RefPtr<Actor> actor);
|
||||||
|
void RemoveActor(RefPtr<Actor> actor);
|
||||||
|
void RemoveAllActors();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void UpdateActors(float deltaTime);
|
||||||
|
void RenderActors();
|
||||||
|
|
||||||
|
private:
|
||||||
|
ActorList actors_;
|
||||||
|
|
||||||
|
friend class Actor;
|
||||||
|
friend class SceneManager;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
36
Frostbite2D/include/frostbite2D/scene/scene_manager.h
Normal file
36
Frostbite2D/include/frostbite2D/scene/scene_manager.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <frostbite2D/types/type_alias.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
class Scene;
|
||||||
|
|
||||||
|
class SceneManager {
|
||||||
|
public:
|
||||||
|
static SceneManager& get();
|
||||||
|
|
||||||
|
SceneManager(const SceneManager&) = delete;
|
||||||
|
SceneManager& operator=(const SceneManager&) = delete;
|
||||||
|
|
||||||
|
void PushScene(Ptr<Scene> scene);
|
||||||
|
void PopScene();
|
||||||
|
void ReplaceScene(Ptr<Scene> scene);
|
||||||
|
void ClearAll();
|
||||||
|
|
||||||
|
void Update(float deltaTime);
|
||||||
|
void Render();
|
||||||
|
|
||||||
|
Scene* GetCurrentScene() const;
|
||||||
|
bool HasActiveScene() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SceneManager() = default;
|
||||||
|
~SceneManager();
|
||||||
|
|
||||||
|
std::vector<Ptr<Scene>> sceneStack_;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
395
Frostbite2D/include/frostbite2D/utils/intrusive_list.hpp
Normal file
395
Frostbite2D/include/frostbite2D/utils/intrusive_list.hpp
Normal file
@@ -0,0 +1,395 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <iterator>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
template <typename _PtrTy>
|
||||||
|
class IntrusiveListValue;
|
||||||
|
|
||||||
|
template <typename _PtrTy>
|
||||||
|
class IntrusiveList {
|
||||||
|
public:
|
||||||
|
using value_type = typename std::pointer_traits<_PtrTy>::pointer;
|
||||||
|
using pointer = value_type*;
|
||||||
|
using reference = value_type&;
|
||||||
|
|
||||||
|
IntrusiveList()
|
||||||
|
: first_(nullptr)
|
||||||
|
, last_(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~IntrusiveList() {
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_type& GetFirst() const {
|
||||||
|
return first_;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type& GetFirst() {
|
||||||
|
return first_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_type& GetLast() const {
|
||||||
|
return last_;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type& GetLast() {
|
||||||
|
return last_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsEmpty() const {
|
||||||
|
return first_ == nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushBack(reference child) {
|
||||||
|
if (child->GetPrev()) {
|
||||||
|
child->GetPrev()->GetNext() = child->GetNext();
|
||||||
|
}
|
||||||
|
if (child->GetNext()) {
|
||||||
|
child->GetNext()->GetPrev() = child->GetPrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
child->GetPrev() = last_;
|
||||||
|
child->GetNext() = nullptr;
|
||||||
|
|
||||||
|
if (first_) {
|
||||||
|
last_->GetNext() = child;
|
||||||
|
} else {
|
||||||
|
first_ = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_ = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PushFront(reference child) {
|
||||||
|
if (child->GetPrev()) {
|
||||||
|
child->GetPrev()->GetNext() = child->GetNext();
|
||||||
|
}
|
||||||
|
if (child->GetNext()) {
|
||||||
|
child->GetNext()->GetPrev() = child->GetPrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
child->GetPrev() = nullptr;
|
||||||
|
child->GetNext() = first_;
|
||||||
|
|
||||||
|
if (first_) {
|
||||||
|
first_->GetPrev() = child;
|
||||||
|
} else {
|
||||||
|
last_ = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
first_ = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InsertBefore(reference child, reference before) {
|
||||||
|
if (child->GetPrev()) {
|
||||||
|
child->GetPrev()->GetNext() = child->GetNext();
|
||||||
|
}
|
||||||
|
if (child->GetNext()) {
|
||||||
|
child->GetNext()->GetPrev() = child->GetPrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (before->GetPrev()) {
|
||||||
|
before->GetPrev()->GetNext() = child;
|
||||||
|
} else {
|
||||||
|
first_ = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
child->GetPrev() = before->GetPrev();
|
||||||
|
child->GetNext() = before;
|
||||||
|
before->GetPrev() = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InsertAfter(reference child, reference after) {
|
||||||
|
if (child->GetPrev()) {
|
||||||
|
child->GetPrev()->GetNext() = child->GetNext();
|
||||||
|
}
|
||||||
|
if (child->GetNext()) {
|
||||||
|
child->GetNext()->GetPrev() = child->GetPrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (after->GetNext()) {
|
||||||
|
after->GetNext()->GetPrev() = child;
|
||||||
|
} else {
|
||||||
|
last_ = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
child->GetNext() = after->GetNext();
|
||||||
|
child->GetPrev() = after;
|
||||||
|
after->GetNext() = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Remove(reference child) {
|
||||||
|
if (child->GetNext()) {
|
||||||
|
child->GetNext()->GetPrev() = child->GetPrev();
|
||||||
|
} else {
|
||||||
|
last_ = child->GetPrev();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child->GetPrev()) {
|
||||||
|
child->GetPrev()->GetNext() = child->GetNext();
|
||||||
|
} else {
|
||||||
|
first_ = child->GetNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
child->GetPrev() = nullptr;
|
||||||
|
child->GetNext() = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear() {
|
||||||
|
value_type p = first_;
|
||||||
|
while (p) {
|
||||||
|
value_type tmp = p;
|
||||||
|
p = p->GetNext();
|
||||||
|
if (tmp) {
|
||||||
|
tmp->GetNext() = nullptr;
|
||||||
|
tmp->GetPrev() = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
first_ = nullptr;
|
||||||
|
last_ = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckValid() {
|
||||||
|
if (!first_) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos = 0;
|
||||||
|
|
||||||
|
value_type p = first_;
|
||||||
|
value_type tmp = p;
|
||||||
|
do {
|
||||||
|
tmp = p;
|
||||||
|
p = p->GetNext();
|
||||||
|
++pos;
|
||||||
|
|
||||||
|
if (p) {
|
||||||
|
if (p->GetPrev() != tmp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (tmp != last_) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (p);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <typename _IterPtrTy>
|
||||||
|
struct Iterator {
|
||||||
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
using value_type = _IterPtrTy;
|
||||||
|
using pointer = _IterPtrTy*;
|
||||||
|
using reference = _IterPtrTy&;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
|
||||||
|
inline Iterator(value_type ptr = nullptr, bool is_end = false)
|
||||||
|
: base_(ptr)
|
||||||
|
, is_end_(is_end) {
|
||||||
|
}
|
||||||
|
|
||||||
|
inline reference operator*() const {
|
||||||
|
assert(base_ && !is_end_);
|
||||||
|
return const_cast<reference>(base_);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline pointer operator->() const {
|
||||||
|
return std::pointer_traits<pointer>::pointer_to(**this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Iterator& operator++() {
|
||||||
|
assert(base_ && !is_end_);
|
||||||
|
value_type next = base_->GetNext();
|
||||||
|
if (next) {
|
||||||
|
base_ = next;
|
||||||
|
} else {
|
||||||
|
is_end_ = true;
|
||||||
|
}
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Iterator operator++(int) {
|
||||||
|
Iterator old = (*this);
|
||||||
|
++(*this);
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Iterator& operator--() {
|
||||||
|
assert(base_);
|
||||||
|
if (is_end_) {
|
||||||
|
is_end_ = false;
|
||||||
|
} else {
|
||||||
|
base_ = base_->GetPrev();
|
||||||
|
}
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Iterator operator--(int) {
|
||||||
|
Iterator old = (*this);
|
||||||
|
--(*this);
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const Iterator& other) const {
|
||||||
|
return base_ == other.base_ && is_end_ == other.is_end_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator!=(const Iterator& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline operator bool() const {
|
||||||
|
return base_ != nullptr && !is_end_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_end_;
|
||||||
|
|
||||||
|
typename std::remove_const<value_type>::type base_;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
using iterator = Iterator<value_type>;
|
||||||
|
using const_iterator = Iterator<const value_type>;
|
||||||
|
using reverse_iterator = std::reverse_iterator<iterator>;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
|
||||||
|
inline iterator begin() {
|
||||||
|
return iterator(first_, first_ == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator begin() const {
|
||||||
|
return const_iterator(first_, first_ == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator cbegin() const {
|
||||||
|
return begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline iterator end() {
|
||||||
|
return iterator(last_, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator end() const {
|
||||||
|
return const_iterator(last_, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_iterator cend() const {
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline reverse_iterator rbegin() {
|
||||||
|
return reverse_iterator(end());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_reverse_iterator rbegin() const {
|
||||||
|
return const_reverse_iterator(end());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_reverse_iterator crbegin() const {
|
||||||
|
return rbegin();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline reverse_iterator rend() {
|
||||||
|
return reverse_iterator(begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_reverse_iterator rend() const {
|
||||||
|
return const_reverse_iterator(begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const_reverse_iterator crend() const {
|
||||||
|
return rend();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline value_type& front() {
|
||||||
|
if (IsEmpty()) {
|
||||||
|
throw std::out_of_range("front() called on empty list");
|
||||||
|
}
|
||||||
|
return first_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const value_type& front() const {
|
||||||
|
if (IsEmpty()) {
|
||||||
|
throw std::out_of_range("front() called on empty list");
|
||||||
|
}
|
||||||
|
return first_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline value_type& back() {
|
||||||
|
if (IsEmpty()) {
|
||||||
|
throw std::out_of_range("back() called on empty list");
|
||||||
|
}
|
||||||
|
return last_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const value_type& back() const {
|
||||||
|
if (IsEmpty()) {
|
||||||
|
throw std::out_of_range("back() called on empty list");
|
||||||
|
}
|
||||||
|
return last_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
value_type first_;
|
||||||
|
value_type last_;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
friend class IntrusiveListValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename _PtrTy>
|
||||||
|
class IntrusiveListValue {
|
||||||
|
public:
|
||||||
|
using value_type = typename std::pointer_traits<_PtrTy>::pointer;
|
||||||
|
using reference = value_type&;
|
||||||
|
using pointer = value_type*;
|
||||||
|
|
||||||
|
IntrusiveListValue()
|
||||||
|
: prev_(nullptr)
|
||||||
|
, next_(nullptr) {
|
||||||
|
}
|
||||||
|
|
||||||
|
IntrusiveListValue(value_type rhs)
|
||||||
|
: prev_(nullptr)
|
||||||
|
, next_(nullptr) {
|
||||||
|
if (rhs) {
|
||||||
|
prev_ = rhs->GetPrev();
|
||||||
|
next_ = rhs->GetNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_type& GetPrev() const {
|
||||||
|
return prev_;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type& GetPrev() {
|
||||||
|
return prev_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const value_type& GetNext() const {
|
||||||
|
return next_;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type& GetNext() {
|
||||||
|
return next_;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
value_type prev_;
|
||||||
|
value_type next_;
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
friend class IntrusiveList;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
79
Frostbite2D/src/frostbite2D/2d/actor.cpp
Normal file
79
Frostbite2D/src/frostbite2D/2d/actor.cpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include <frostbite2D/2d/actor.h>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
Actor::Actor()
|
||||||
|
: parent_(nullptr)
|
||||||
|
, scene_(nullptr)
|
||||||
|
, rotation_(0.0f)
|
||||||
|
, visible_(true)
|
||||||
|
, zOrder_(0)
|
||||||
|
, opacity_(1.0f) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Actor::~Actor() {
|
||||||
|
RemoveAllChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::Update(float deltaTime) {
|
||||||
|
UpdateChildren(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::Render() {
|
||||||
|
RenderChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::AddChild(Ptr<Actor> child) {
|
||||||
|
if (!child) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child->GetParent() == this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child->GetParent()) {
|
||||||
|
child->GetParent()->RemoveChild(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
child->SetParent(this);
|
||||||
|
child->SetScene(scene_);
|
||||||
|
children_.PushBack(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::RemoveChild(Ptr<Actor> child) {
|
||||||
|
if (!child || child->GetParent() != this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
child->SetParent(nullptr);
|
||||||
|
child->SetScene(nullptr);
|
||||||
|
children_.Remove(child);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::RemoveAllChildren() {
|
||||||
|
while (!children_.IsEmpty()) {
|
||||||
|
Ptr<Actor> child = children_.GetFirst();
|
||||||
|
RemoveChild(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::UpdateChildren(float deltaTime) {
|
||||||
|
for (auto it = children_.begin(); it != children_.end(); ++it) {
|
||||||
|
if (*it && (*it)->IsVisible()) {
|
||||||
|
(*it)->Update(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Actor::RenderChildren() {
|
||||||
|
for (auto it = children_.begin(); it != children_.end(); ++it) {
|
||||||
|
if (*it && (*it)->IsVisible()) {
|
||||||
|
(*it)->Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cstdio>
|
||||||
#include <frostbite2D/core/application.h>
|
#include <frostbite2D/core/application.h>
|
||||||
#include <frostbite2D/graphics/renderer.h>
|
#include <frostbite2D/graphics/renderer.h>
|
||||||
#include <frostbite2D/platform/switch.h>
|
#include <frostbite2D/platform/switch.h>
|
||||||
#include <frostbite2D/types/type_math.h>
|
#include <frostbite2D/types/type_math.h>
|
||||||
#include <frostbite2D/utils/asset.h>
|
#include <frostbite2D/utils/asset.h>
|
||||||
|
#include <frostbite2D/scene/scene_manager.h>
|
||||||
namespace frostbite2D {
|
namespace frostbite2D {
|
||||||
|
|
||||||
Application &Application::get() {
|
Application &Application::get() {
|
||||||
@@ -169,7 +171,6 @@ void Application::mainLoop() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!paused_) {
|
if (!paused_) {
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
@@ -184,6 +185,8 @@ void Application::update() {
|
|||||||
lastFrameTime_ = currentTime;
|
lastFrameTime_ = currentTime;
|
||||||
totalTime_ += deltaTime_;
|
totalTime_ += deltaTime_;
|
||||||
|
|
||||||
|
SceneManager::get().Update(deltaTime_);
|
||||||
|
|
||||||
frameCount_++;
|
frameCount_++;
|
||||||
fpsTimer_ += deltaTime_;
|
fpsTimer_ += deltaTime_;
|
||||||
if (fpsTimer_ >= fpsUpdateInterval_) {
|
if (fpsTimer_ >= fpsUpdateInterval_) {
|
||||||
@@ -194,6 +197,8 @@ void Application::update() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::render() {
|
void Application::render() {
|
||||||
|
SceneManager::get().Render();
|
||||||
|
|
||||||
if (window_) {
|
if (window_) {
|
||||||
window_->swap();
|
window_->swap();
|
||||||
}
|
}
|
||||||
|
|||||||
76
Frostbite2D/src/frostbite2D/scene/scene.cpp
Normal file
76
Frostbite2D/src/frostbite2D/scene/scene.cpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#include <frostbite2D/scene/scene.h>
|
||||||
|
#include <frostbite2D/2d/actor.h>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
Scene::Scene() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene::~Scene() {
|
||||||
|
RemoveAllActors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::onEnter() {
|
||||||
|
SDL_Log("Scene onEnter");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::onExit() {
|
||||||
|
SDL_Log("Scene onExit");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::Update(float deltaTime) {
|
||||||
|
UpdateActors(deltaTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::Render() {
|
||||||
|
RenderActors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::AddActor(Ptr<Actor> actor) {
|
||||||
|
if (!actor) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (actor->GetParent()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actor->SetScene(this);
|
||||||
|
actors_.PushBack(actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::RemoveActor(Ptr<Actor> actor) {
|
||||||
|
if (!actor || actor->GetScene() != this) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
actor->SetScene(nullptr);
|
||||||
|
actors_.Remove(actor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::RemoveAllActors() {
|
||||||
|
while (!actors_.IsEmpty()) {
|
||||||
|
Ptr<Actor> actor = actors_.GetFirst();
|
||||||
|
RemoveActor(actor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::UpdateActors(float deltaTime) {
|
||||||
|
for (auto it = actors_.begin(); it != actors_.end(); ++it) {
|
||||||
|
if (*it && (*it)->IsVisible()) {
|
||||||
|
(*it)->Update(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scene::RenderActors() {
|
||||||
|
for (auto it = actors_.begin(); it != actors_.end(); ++it) {
|
||||||
|
if (*it && (*it)->IsVisible()) {
|
||||||
|
(*it)->Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
82
Frostbite2D/src/frostbite2D/scene/scene_manager.cpp
Normal file
82
Frostbite2D/src/frostbite2D/scene/scene_manager.cpp
Normal file
@@ -0,0 +1,82 @@
|
|||||||
|
#include <frostbite2D/scene/scene_manager.h>
|
||||||
|
#include <frostbite2D/scene/scene.h>
|
||||||
|
#include <SDL2/SDL.h>
|
||||||
|
|
||||||
|
namespace frostbite2D {
|
||||||
|
|
||||||
|
SceneManager& SceneManager::get() {
|
||||||
|
static SceneManager instance;
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneManager::~SceneManager() {
|
||||||
|
ClearAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::PushScene(Ptr<Scene> scene) {
|
||||||
|
if (!scene) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sceneStack_.empty()) {
|
||||||
|
sceneStack_.back()->onExit();
|
||||||
|
}
|
||||||
|
|
||||||
|
sceneStack_.push_back(scene);
|
||||||
|
scene->onEnter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::PopScene() {
|
||||||
|
if (sceneStack_.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sceneStack_.back()->onExit();
|
||||||
|
sceneStack_.pop_back();
|
||||||
|
|
||||||
|
if (!sceneStack_.empty()) {
|
||||||
|
sceneStack_.back()->onEnter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::ReplaceScene(Ptr<Scene> scene) {
|
||||||
|
if (!scene) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
PopScene();
|
||||||
|
PushScene(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::ClearAll() {
|
||||||
|
while (!sceneStack_.empty()) {
|
||||||
|
sceneStack_.back()->onExit();
|
||||||
|
sceneStack_.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::Update(float deltaTime) {
|
||||||
|
if (!sceneStack_.empty()) {
|
||||||
|
sceneStack_.back()->Update(deltaTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneManager::Render() {
|
||||||
|
if (!sceneStack_.empty()) {
|
||||||
|
sceneStack_.back()->Render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scene* SceneManager::GetCurrentScene() const {
|
||||||
|
if (sceneStack_.empty()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return sceneStack_.back().Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SceneManager::HasActiveScene() const {
|
||||||
|
return !sceneStack_.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@@ -6,6 +6,9 @@
|
|||||||
#include <frostbite2D/graphics/texture.h>
|
#include <frostbite2D/graphics/texture.h>
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
|
|
||||||
|
#include <frostbite2D/scene/scene.h>
|
||||||
|
#include <frostbite2D/scene/scene_manager.h>
|
||||||
|
|
||||||
using namespace frostbite2D;
|
using namespace frostbite2D;
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|||||||
Reference in New Issue
Block a user