I have finally implemented sprite editor. The sprite sheet can be edit inside the engine and sliced down. Currently there is only manual slicing available, but I am planning to add automatic slicing tool in the future, which will slice down the entire sprite sheet in equally regions..
This addition is improving productivity when creating game as you can do everything from within the engine. When editing the sprite sheet you can select only the sprites you want appear in your animation, They do not have to be selected in order , which can produce very interesting results. There are many more feature on my list, which I would like to add the the sprite editor, but for now the basic sprite editor will be enough. I will definitely modify it in the near future.
]]>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 //Measure the time of executing function. The lifetime of the function
struct ExecutionTimer
{
std::chrono::time_point<std::chrono::steady_clock> start;
std::chrono::time_point<std::chrono::steady_clock> end;
std::string function_name;
std::string file_name;
const float error_time = 0.01f;
const float warning_time = 0.005f;
ExecutionTimer(std::string const& fileName, std::string const& functionName);
~ExecutionTimer();
};
ExecutionTimer::ExecutionTimer(std::string const& fileName, std::string const& functionName)
: start(std::chrono::high_resolution_clock::now())
, function_name(functionName)
, file_name(fileName)
{
}
ExecutionTimer::~ExecutionTimer()
{
end = std::chrono::high_resolution_clock::now();
//If the function is already in the vector do not add it just modify start and end time if is greater than the current value
const auto result = std::find_if(ProfilerDataList.begin(), ProfilerDataList.end(),
[&](const auto& element)
{
return (element.function_name == function_name && element.file_name == file_name);
});
if (result == ProfilerDataList.end())
{
//Not found
ProfilerDataList.emplace_back(
ProfilerData{
file_name,
function_name,
start,
end
});
}
}
To have simple access to the class I have decided to add a simple macro which could be put at the beginning of the function and measure its performance.
1
2
3
4
5
6
7
8 //to print only file name without full path
#define __FILENAME__ (strrchr(__FILE__,'\')+1)
#ifdef USE_PROFILER
#define SCOPE_MEMBER() ExecutionTimer(__FILENAME__, __FUNCTION__)
#else
#define SCOPE_MEMBER()
#endif
All of the results are than saved in the vector files and outputted to the HTML report. Below is the report generated by the engine.
]]>Finally I have found suitable GUI library. I have decided to use Dear ImGui library you can find it here.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 #include "Sprite.h"
#include "Utilities.h"
#include "ShaderManager.h"
#include "PlayerBehaviour.h"
Sprite::Sprite()
: position_(glm::vec3(0.0f, 0.0f, 0.0f))
, scale_(glm::vec3(1.0f, 1.0f, 1.0f))
{
}
void Sprite::Init(std::string const& file_name, RenderingOrder order, int column_number, int row_number, float pos_x, float pos_y)
{
SCOPE_MEMBER();
rendering_order_ = order;
position_.x = pos_x;
position_.y = pos_y;
name_ = file_name;
AddComponent(new TransformComponentData(position_, scale_, shared_from_this()));
AddComponent(new SpriteRendererComponentData(
file_name,
row_number,
column_number,
1,
1,
60,
shared_from_this()
));
AddComponent(new WindowsSoundComponentData("c:\\windows\\media\\Alarm05.wav"));
if (HasComponent(BEHAVIOUR_COMPONENT))
{
GetComponent<BehaviourComponentData>()->behaviour_component->Start();
}
}
void Sprite::Update(float delta_time) //IEntity
{
IEntity::Update(delta_time);
if (HasComponent(BEHAVIOUR_COMPONENT))
{
GetComponent<BehaviourComponentData>()->behaviour_component->Update(delta_time);
}
}
RenderingOrder Sprite::GetRenderingOrder()
{
return renderingOrder_;
}
this is the example code how we can use this entity inside our game project
1
2
3
4
5 sprite_test = make_shared();
sprite_test->Init("BoneSprite.png", RenderingOrder::RO_FIRST, 5, 1, 100, 20);
sprite_test->GetComponent()->autoAnimate = true;
sprite_test->GetComponent()->updateFrameRate = 15;
EntityManager::GetManager()->registerEntity(sprite_test);
This is the definition of one of the standard entity, which can be used. Although There is also possible to create custom Entity inside the game project and assign wanted components to it.
To separate entity logic and make our project cleaner we can attach behavior script to this entity and put our logic in it. The standard behavior script have to inherit from IBehaviourComponentClass and implement Start() and Update() function. Start Function is called only once per game ,where update is called every frame.
Below is the code snipped from the PlayerBehaviourScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 #pragma once
#include "IBehaviourComponent.h"
#include "IEntity.h"
class PlayerBehaviour : public IBehaviourComponent
{
public:
PlayerBehaviour() = default;
PlayerBehaviour(IEntity* entity);
~PlayerBehaviour();
//IBehaviourComponent
void Start();
void Update();
void SetOwner(IEntity* entity) { entity_ = entity; }
private:
IEntity* entity_;
};
//***************************************************************************************
PlayerBehaviour.cpp
//***************************************************************************************
#include "PlayerBehaviour.h"
#include "GLWindow.h"
#include "EntityManager.h"
PlayerBehaviour::PlayerBehaviour(IEntity* entity)
{
entity_ = entity;
}
PlayerBehaviour::~PlayerBehaviour()
{
if (entity_)
delete entity_;
}
//IBehaviourComponent
void PlayerBehaviour::Start()
{
}
void PlayerBehaviour::Update()
{
if (Cyber::Input::IsMouseButtonPressed(CB_MOUSE_BUTTON_1))
{
entity_->GetComponent<TransformComponentData>()->position.x += (1.0f * delta_time);
}
}
And this is how the Bhaviour script can be assigned to the specific Entity
1
2
3
4
5
6 shared_ptr NewSprite = make_shared();
NewSprite->SetName(name);
// ScriptFactory::GetBehaviourScript(ScriptName);
NewSprite->AddScript(ScriptFactory::GetNewScript(ScriptName));
NewSprite->Init("BoneSprite.png", RenderingOrder::RO_FIRST, 5, 1, 100, 20);
EntityManager::GetManager()->RegisterEntity(NewSprite);
We can get different entity from our script and access its functionality. This make its easy to implement our game logic.
Like above we access Enemy position from PlayerBehaviour script.
]]>