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 <algorithm>
|
||||
#include <cstdio>
|
||||
#include <frostbite2D/core/application.h>
|
||||
#include <frostbite2D/graphics/renderer.h>
|
||||
#include <frostbite2D/platform/switch.h>
|
||||
#include <frostbite2D/types/type_math.h>
|
||||
#include <frostbite2D/utils/asset.h>
|
||||
#include <frostbite2D/scene/scene_manager.h>
|
||||
namespace frostbite2D {
|
||||
|
||||
Application &Application::get() {
|
||||
@@ -169,7 +171,6 @@ void Application::mainLoop() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!paused_) {
|
||||
update();
|
||||
}
|
||||
@@ -184,6 +185,8 @@ void Application::update() {
|
||||
lastFrameTime_ = currentTime;
|
||||
totalTime_ += deltaTime_;
|
||||
|
||||
SceneManager::get().Update(deltaTime_);
|
||||
|
||||
frameCount_++;
|
||||
fpsTimer_ += deltaTime_;
|
||||
if (fpsTimer_ >= fpsUpdateInterval_) {
|
||||
@@ -194,6 +197,8 @@ void Application::update() {
|
||||
}
|
||||
|
||||
void Application::render() {
|
||||
SceneManager::get().Render();
|
||||
|
||||
if (window_) {
|
||||
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 <glad/glad.h>
|
||||
|
||||
#include <frostbite2D/scene/scene.h>
|
||||
#include <frostbite2D/scene/scene_manager.h>
|
||||
|
||||
using namespace frostbite2D;
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
Reference in New Issue
Block a user