Minor README update and some git hassles
This commit is contained in:
parent
4431771af1
commit
e11ea35c4c
19
Makefile
19
Makefile
|
@ -1,7 +1,7 @@
|
|||
CC=g++
|
||||
SRCDIR=./src
|
||||
outputDir=./build
|
||||
CFLAGS=-fPIC -O2
|
||||
CFLAGS=-fPIC -O2 -g
|
||||
WarningFlags=-Wpedantic -pedantic -Wall -Wextra
|
||||
SDL_FLAGS=-lSDL2 -lSDL2main -lSDL2_image -lSDL2_ttf -lSDL2_mixer -lSDL2_gfx
|
||||
INCLUDES=-I./include
|
||||
|
@ -9,6 +9,9 @@ LIBFILE=libbirb2d.so
|
|||
|
||||
all: test engine_lib
|
||||
|
||||
docs:
|
||||
doxygen ./doxygen_config
|
||||
|
||||
test: tests.o logger.o renderwindow.o values.o timestep.o utils.o math.o
|
||||
mkdir -p build
|
||||
$(CC) $^ $(SDL_FLAGS) $(WarningFlags) -o $(outputDir)/test
|
||||
|
@ -16,22 +19,24 @@ test: tests.o logger.o renderwindow.o values.o timestep.o utils.o math.o
|
|||
run_tests: test
|
||||
./build/test
|
||||
|
||||
engine_obj: audio.o entity.o logger.o math.o renderwindow.o physics.o timer.o timestep.o utils.o values.o
|
||||
engine_lib: audio.o entity.o logger.o math.o renderwindow.o physics.o timer.o timestep.o ui.o utils.o values.o
|
||||
mkdir -p build
|
||||
ld -r $^ -o $(outputDir)/birb2d.o
|
||||
g++ -shared -g $(SDL_FLAGS) -o $(outputDir)/$(LIBFILE) $^
|
||||
|
||||
engine_lib: audio.o entity.o logger.o math.o renderwindow.o physics.o timer.o timestep.o utils.o values.o
|
||||
static_engine_lib: audio.o entity.o logger.o math.o renderwindow.o physics.o timer.o timestep.o ui.o utils.o values.o
|
||||
mkdir -p build
|
||||
g++ -shared $(SDL_FLAGS) -o $(outputDir)/$(LIBFILE) $^
|
||||
g++ -static $(SDL_FLAGS) -o $(outputDir)/$(LIBFILE) $^
|
||||
|
||||
install: engine_lib
|
||||
cp $(outputDir)/$(LIBFILE) /usr/lib/
|
||||
mkdir -p /usr/local/include/birb2d
|
||||
cp ./include/* /usr/local/include/birb2d/
|
||||
ldconfig
|
||||
|
||||
uninstall:
|
||||
rm -f /usr/lib/$(LIBFILE)
|
||||
rm -rf /usr/local/include/birb2d
|
||||
ldconfig
|
||||
|
||||
audio.o: $(SRCDIR)/audio.cpp
|
||||
$(CC) -c $(CFLAGS) $(INCLUDES) $^ -o audio.o
|
||||
|
@ -60,6 +65,9 @@ timer.o: $(SRCDIR)/timer.cpp
|
|||
timestep.o: $(SRCDIR)/timestep.cpp
|
||||
$(CC) -c $(CFLAGS) $(INCLUDES) $(WarningFlags) $^ -o timestep.o
|
||||
|
||||
ui.o: $(SRCDIR)/ui.cpp
|
||||
$(CC) -c $(CFLAGS) $(INCLUDES) $(WarningFlags) $^ -o ui.o
|
||||
|
||||
utils.o: $(SRCDIR)/utils.cpp
|
||||
$(CC) -c $(CFLAGS) $(INCLUDES) $(WarningFlags) $^ -o utils.o
|
||||
|
||||
|
@ -72,3 +80,4 @@ values.o: $(SRCDIR)/values.cpp
|
|||
clean:
|
||||
rm -f *.o log.txt
|
||||
rm -rf $(outputDir)
|
||||
rm -rf docs
|
||||
|
|
|
@ -63,6 +63,6 @@ make uninstall
|
|||
- [ ] Resolution independent UI scaling
|
||||
- [ ] Anchors
|
||||
- [x] Sound
|
||||
- [ ] Animation
|
||||
- [x] Animation (sprite based animations supported)
|
||||
- [ ] Physics
|
||||
- [ ] To be continued...
|
||||
|
|
|
@ -1,21 +1,62 @@
|
|||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#include "Utils.hpp"
|
||||
#include "Timer.hpp"
|
||||
|
||||
namespace Birb
|
||||
{
|
||||
/// TextComponent contains details needed to generate a sprite for the Entity in case the Entity is used to display text.
|
||||
struct TextComponent
|
||||
namespace EntityComponent
|
||||
{
|
||||
TextComponent();
|
||||
TextComponent(std::string p_text, TTF_Font* font, SDL_Color* p_color);
|
||||
std::string text;
|
||||
TTF_Font* font;
|
||||
SDL_Color* color; ///< Surface color of the text
|
||||
};
|
||||
/// TextComponent contains details needed to generate a sprite for the Entity in case the Entity is used to display text.
|
||||
struct TextComponent
|
||||
{
|
||||
TextComponent();
|
||||
TextComponent(std::string p_text, TTF_Font* font, SDL_Color* p_color);
|
||||
TextComponent(std::string p_text, TTF_Font* font, SDL_Color* p_color, SDL_Color* p_bgColor);
|
||||
std::string text;
|
||||
TTF_Font* font;
|
||||
SDL_Color* color; ///< Surface color of the text
|
||||
SDL_Color* bgColor; ///< Background color for the text component
|
||||
};
|
||||
|
||||
/// ClickComponent adds button functionality to the Entity
|
||||
struct ClickComponent
|
||||
{
|
||||
ClickComponent();
|
||||
ClickComponent(std::function<void()> p_onClick);
|
||||
bool active;
|
||||
std::function<void()> onClick;
|
||||
};
|
||||
|
||||
/// AnimationComponent allows for texture atlas based sprite animations
|
||||
struct AnimationComponent
|
||||
{
|
||||
AnimationComponent();
|
||||
AnimationComponent(Vector2int p_spriteSize, int p_frameCount, int p_fps);
|
||||
AnimationComponent(Vector2int p_spriteSize, int p_frameCount, int p_fps, bool p_loop);
|
||||
|
||||
int fps;
|
||||
bool loop; ///< Start the animation over when it ends
|
||||
int frameIndex; ///< Current visible frame
|
||||
int frameCount; ///< Total amount of sprites in the atlas
|
||||
Vector2int spriteSize; ///< The size of one sprite in the atlas. Used for cropping
|
||||
Timer frameTimer;
|
||||
|
||||
bool animationQueued;
|
||||
int lastFrame;
|
||||
|
||||
|
||||
void StartAnimation();
|
||||
void StartAnimation(int startFrame);
|
||||
void StartAnimation(int startFrame, int endFrame);
|
||||
void ResetAnimationAtlas();
|
||||
};
|
||||
}
|
||||
|
||||
/// Entities are objects that contain all of the information required to render stuff
|
||||
|
||||
|
@ -24,7 +65,7 @@ namespace Birb
|
|||
{
|
||||
Entity(); ///< Creates empty Entity object
|
||||
Entity(std::string p_name, Rect p_rect, SDL_Texture* p_texture); ///< Creates an Entity with a SDL_Texture to render with custom scale
|
||||
Entity(std::string p_name, Vector2int pos, TextComponent p_textComponent); ///< Creates a Text Entity using a TextComponent
|
||||
Entity(std::string p_name, Vector2int pos, EntityComponent::TextComponent p_textComponent); ///< Creates a Text Entity using a TextComponent
|
||||
Entity(std::string p_name, Vector2int pos, SDL_Texture* p_texture); ///< Creates an Entity with a SDL_Texture to render without specifying a scale
|
||||
|
||||
/* Make it possible to update the TextComponent */
|
||||
|
@ -33,16 +74,24 @@ namespace Birb
|
|||
void SetColor(SDL_Color* color); ///< Change the color in TextComponent and reload the sprite
|
||||
|
||||
std::string name; ///< Name of the entity. Used for debugging
|
||||
|
||||
/* Sprite handlings */
|
||||
SDL_Texture* sprite; ///< Sprite to be rendered
|
||||
|
||||
float angle; ///< Sets the rotation of the entity when rendering it
|
||||
Rect rect; ///< Sets the position and the dimensions of the entity
|
||||
Vector2f localScale; ///< Scale modifier for the Entity rendering
|
||||
|
||||
TextComponent textComponent; ///< Having a TextComponent in an Entity enables the rendering of Text
|
||||
EntityComponent::TextComponent textComponent; ///< Enables the rendering of Text
|
||||
EntityComponent::ClickComponent clickComponent; ///< Enables button-like functionality
|
||||
EntityComponent::AnimationComponent animationComponent; ///< Enables animations for sprite rendering
|
||||
void LoadSprite(); ///< Create a sprite for the Entity using details found in the textComponent variable
|
||||
void ReloadSprite(); ///< Destroy the old sprite and create a new one. Useful for refreshing text after editing the textComponent variable
|
||||
void SetBaseEntityValues(); ///< Used to set some default value when they aren't provided during Entity initialization
|
||||
|
||||
/* Informational functions */
|
||||
bool isHovering(); ///< Check if the cursor is hovering over this entity
|
||||
Vector2int getAtlasPosition(int frame); ///< Get position in a texture atlas given the sprite index
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ namespace Birb
|
|||
{
|
||||
static SDL_Texture* LoadTexture(std::string p_filePath);
|
||||
static SDL_Texture* TextSprite(std::string text, TTF_Font* font, SDL_Color& color);
|
||||
static SDL_Texture* TextSprite(std::string text, TTF_Font* font, SDL_Color& color, SDL_Color& bgColor);
|
||||
static TTF_Font* LoadFont(std::string p_filePath, int p_fontSize);
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include "Entity.hpp"
|
||||
#include "Renderwindow.hpp"
|
||||
|
||||
namespace Birb
|
||||
{
|
||||
class UI
|
||||
{
|
||||
public:
|
||||
UI();
|
||||
std::vector<Entity> Buttons;
|
||||
void AddButton(Entity buttonEntity);
|
||||
void PollButtons(Window window);
|
||||
};
|
||||
}
|
120
src/entity.cpp
120
src/entity.cpp
|
@ -4,16 +4,114 @@
|
|||
|
||||
namespace Birb
|
||||
{
|
||||
TextComponent::TextComponent()
|
||||
namespace EntityComponent
|
||||
{
|
||||
text = "";
|
||||
font = NULL;
|
||||
color = NULL;
|
||||
TextComponent::TextComponent()
|
||||
{
|
||||
text = "";
|
||||
font = NULL;
|
||||
color = NULL;
|
||||
bgColor = NULL;
|
||||
}
|
||||
|
||||
TextComponent::TextComponent(std::string p_text, TTF_Font* p_font, SDL_Color* p_color)
|
||||
:text(p_text), font(p_font), color(p_color)
|
||||
{
|
||||
bgColor = NULL;
|
||||
}
|
||||
|
||||
TextComponent::TextComponent(std::string p_text, TTF_Font* p_font, SDL_Color* p_color, SDL_Color* p_bgColor)
|
||||
:text(p_text), font(p_font), color(p_color), bgColor(p_bgColor)
|
||||
{}
|
||||
|
||||
void PlaceHolderClickEvent()
|
||||
{
|
||||
Debug::Log("This button is working");
|
||||
}
|
||||
|
||||
ClickComponent::ClickComponent()
|
||||
{
|
||||
active = true;
|
||||
onClick = PlaceHolderClickEvent;
|
||||
}
|
||||
|
||||
ClickComponent::ClickComponent(std::function<void()> p_onClick)
|
||||
:onClick(p_onClick)
|
||||
{
|
||||
active = true;
|
||||
}
|
||||
|
||||
AnimationComponent::AnimationComponent()
|
||||
{
|
||||
fps = 24;
|
||||
loop = false;
|
||||
frameIndex = 0;
|
||||
frameCount = 0;
|
||||
spriteSize = { 16, 16 };
|
||||
animationQueued = false;
|
||||
}
|
||||
|
||||
AnimationComponent::AnimationComponent(Vector2int p_spriteSize, int p_frameCount, int p_fps)
|
||||
:spriteSize(p_spriteSize), frameCount(p_frameCount), fps(p_fps), lastFrame(p_frameCount - 1)
|
||||
{
|
||||
frameIndex = 0;
|
||||
loop = false;
|
||||
animationQueued = false;
|
||||
}
|
||||
|
||||
AnimationComponent::AnimationComponent(Vector2int p_spriteSize, int p_frameCount, int p_fps, bool p_loop)
|
||||
:spriteSize(p_spriteSize), frameCount(p_frameCount), fps(p_fps), loop(p_loop), lastFrame(p_frameCount - 1)
|
||||
{
|
||||
frameIndex = 0;
|
||||
animationQueued = false;
|
||||
}
|
||||
|
||||
|
||||
void AnimationComponent::ResetAnimationAtlas()
|
||||
{
|
||||
frameIndex = 0;
|
||||
lastFrame = frameCount - 1;
|
||||
}
|
||||
|
||||
void AnimationComponent::StartAnimation()
|
||||
{
|
||||
ResetAnimationAtlas();
|
||||
animationQueued = true;
|
||||
}
|
||||
|
||||
void AnimationComponent::StartAnimation(int p_startFrame)
|
||||
{
|
||||
frameIndex = p_startFrame;
|
||||
lastFrame = frameCount - 1;
|
||||
animationQueued = true;
|
||||
}
|
||||
|
||||
void AnimationComponent::StartAnimation(int p_startFrame, int p_lastFrame)
|
||||
{
|
||||
frameIndex = p_startFrame;
|
||||
lastFrame = p_lastFrame;
|
||||
animationQueued = true;
|
||||
}
|
||||
}
|
||||
|
||||
TextComponent::TextComponent(std::string p_text, TTF_Font* p_font, SDL_Color* p_color)
|
||||
:text(p_text), font(p_font), color(p_color)
|
||||
{}
|
||||
Vector2int Entity::getAtlasPosition(int frame)
|
||||
{
|
||||
Vector2int pos;
|
||||
int index = frame;
|
||||
|
||||
int texWidth;
|
||||
int texHeight;
|
||||
SDL_QueryTexture(sprite, NULL, NULL, &texWidth, &texHeight);
|
||||
|
||||
int spritesPerRow = texWidth / animationComponent.spriteSize.x;
|
||||
float fullRowCount = std::floor(index / spritesPerRow);
|
||||
float leftOver = ((index / (float)spritesPerRow) - fullRowCount) * spritesPerRow;
|
||||
|
||||
pos.x = leftOver * animationComponent.spriteSize.x;
|
||||
pos.y = fullRowCount * animationComponent.spriteSize.y;
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
void Entity::SetText(std::string newText)
|
||||
{
|
||||
|
@ -59,7 +157,7 @@ namespace Birb
|
|||
SetBaseEntityValues();
|
||||
}
|
||||
|
||||
Entity::Entity(std::string p_name, Vector2int pos, TextComponent p_textComponent)
|
||||
Entity::Entity(std::string p_name, Vector2int pos, EntityComponent::TextComponent p_textComponent)
|
||||
:name(p_name)
|
||||
{
|
||||
/* Load the text sprite */
|
||||
|
@ -91,8 +189,10 @@ namespace Birb
|
|||
/* There's a text component. Let's generate a text sprite for it */
|
||||
if (textComponent.text != "")
|
||||
{
|
||||
//Debug::Log("Loading a text sprite '" + name + "'");
|
||||
sprite = Resources::TextSprite(textComponent.text, textComponent.font, *textComponent.color);
|
||||
if (textComponent.bgColor == NULL)
|
||||
sprite = Resources::TextSprite(textComponent.text, textComponent.font, *textComponent.color);
|
||||
else
|
||||
sprite = Resources::TextSprite(textComponent.text, textComponent.font, *textComponent.color, *textComponent.bgColor);
|
||||
|
||||
if (sprite == nullptr)
|
||||
Debug::Log("Something went wrong while creating the text sprite for '" + name + "'", Debug::error);
|
||||
|
|
|
@ -102,6 +102,24 @@ namespace Birb
|
|||
SDL_RenderPresent(Global::RenderVars::Renderer);
|
||||
}
|
||||
|
||||
Vector2int Window::CursorPosition()
|
||||
{
|
||||
Vector2int pos;
|
||||
SDL_GetMouseState(&pos.x, &pos.y);
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool Window::CursorInRect(Rect rect)
|
||||
{
|
||||
Vector2int cursorPos = CursorPosition();
|
||||
|
||||
if (cursorPos.x > rect.x && cursorPos.x < rect.x + rect.w)
|
||||
if (cursorPos.y > rect.y && cursorPos.y < rect.y + rect.h)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void Window::SetWindowSize(Vector2int dimensions)
|
||||
{
|
||||
SDL_SetWindowSize(win, dimensions.x, dimensions.y);
|
||||
|
@ -180,6 +198,27 @@ namespace Birb
|
|||
return texture;
|
||||
}
|
||||
|
||||
SDL_Texture* Resources::TextSprite(std::string text, TTF_Font* font, SDL_Color& color, SDL_Color& bgColor)
|
||||
{
|
||||
/* Check if the arguments are valid */
|
||||
if (font == nullptr)
|
||||
{
|
||||
Debug::Log("Tried to render text with invalid font!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_Surface* surface = TTF_RenderText_Shaded(font, text.c_str(), color, bgColor);
|
||||
if (surface == nullptr)
|
||||
Debug::Log("Error creating SDL_Surface. Text: " + (std::string)text + ". SDL Error: " + (std::string)SDL_GetError(), Debug::error);
|
||||
|
||||
SDL_Texture* texture = SDL_CreateTextureFromSurface(Global::RenderVars::Renderer, surface);
|
||||
if (texture == nullptr)
|
||||
Debug::Log("Error creating texture from surface: " + (std::string)SDL_GetError(), Debug::error);
|
||||
|
||||
SDL_FreeSurface(surface);
|
||||
return texture;
|
||||
}
|
||||
|
||||
void Render::DrawEntity(Entity& entity)
|
||||
{
|
||||
if (entity.sprite == nullptr)
|
||||
|
@ -197,15 +236,65 @@ namespace Birb
|
|||
int texHeight;
|
||||
SDL_QueryTexture(entity.sprite, NULL, NULL, &texWidth, &texHeight);
|
||||
|
||||
src.x = 0;
|
||||
src.y = 0;
|
||||
src.w = texWidth;
|
||||
src.h = texHeight;
|
||||
if (entity.animationComponent.frameCount == 0)
|
||||
{
|
||||
src.x = 0;
|
||||
src.y = 0;
|
||||
src.w = texWidth;
|
||||
src.h = texHeight;
|
||||
|
||||
dst.x = entity.rect.x;
|
||||
dst.y = entity.rect.y;
|
||||
dst.w = entity.rect.w * entity.localScale.x;
|
||||
dst.h = entity.rect.h * entity.localScale.y;
|
||||
dst.x = entity.rect.x;
|
||||
dst.y = entity.rect.y;
|
||||
dst.w = entity.rect.w * entity.localScale.x;
|
||||
dst.h = entity.rect.h * entity.localScale.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Entity probably has an animation component */
|
||||
//src.x = entity.animationComponent.curAtlasPosition.x;
|
||||
//src.y = entity.animationComponent.curAtlasPosition.y;
|
||||
Vector2int atlasPos = entity.getAtlasPosition(entity.animationComponent.frameIndex);
|
||||
src.x = atlasPos.x;
|
||||
src.y = atlasPos.y;
|
||||
src.w = entity.animationComponent.spriteSize.x;
|
||||
src.h = entity.animationComponent.spriteSize.y;
|
||||
|
||||
dst.x = entity.rect.x;
|
||||
dst.y = entity.rect.y;
|
||||
dst.w = src.w * entity.localScale.x;
|
||||
dst.h = src.h * entity.localScale.y;
|
||||
|
||||
|
||||
|
||||
/* Set the current atlast position to the next frame */
|
||||
if (entity.animationComponent.animationQueued || entity.animationComponent.loop)
|
||||
{
|
||||
if (entity.animationComponent.frameTimer.running && entity.animationComponent.frameTimer.ElapsedSeconds() >= (1.0 / entity.animationComponent.fps))
|
||||
{
|
||||
if (entity.animationComponent.frameIndex < entity.animationComponent.lastFrame)
|
||||
{
|
||||
entity.animationComponent.frameIndex++;
|
||||
entity.animationComponent.frameTimer.Stop();
|
||||
entity.animationComponent.frameTimer.Start();
|
||||
}
|
||||
}
|
||||
else if (!entity.animationComponent.frameTimer.running)
|
||||
{
|
||||
/* Start the frame timer */
|
||||
entity.animationComponent.frameTimer.Start();
|
||||
}
|
||||
|
||||
if (entity.animationComponent.loop && entity.animationComponent.frameIndex >= entity.animationComponent.lastFrame)
|
||||
{
|
||||
entity.animationComponent.frameIndex = 0;
|
||||
}
|
||||
else if (entity.animationComponent.animationQueued && entity.animationComponent.frameIndex >= entity.animationComponent.lastFrame)
|
||||
{
|
||||
entity.animationComponent.frameIndex = entity.animationComponent.lastFrame;
|
||||
entity.animationComponent.animationQueued = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
centerPoint = Vector2int(entity.rect.w / 2, entity.rect.h / 2);
|
||||
SDL_Point center = { centerPoint.x, centerPoint.y };
|
||||
|
|
|
@ -22,7 +22,7 @@ TEST_CASE("logging")
|
|||
|
||||
TEST_CASE("window and rendering functions")
|
||||
{
|
||||
Birb::Window window("Title", Birb::Vector2int(1280, 720), 60);
|
||||
Birb::Window window("Title", Birb::Vector2int(1280, 720), 60, false);
|
||||
SDL_Texture* texture = Birb::Resources::LoadTexture("/home/toasterbirb/git/birb2d/res/textures/giga_stretch.png");
|
||||
TTF_Font* font = Birb::Resources::LoadFont("/home/toasterbirb/git/birb2d/res/fonts/freefont/FreeMonoBold.ttf", 32);
|
||||
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#include "UI.hpp"
|
||||
|
||||
namespace Birb
|
||||
{
|
||||
UI::UI() {}
|
||||
|
||||
void UI::AddButton(Entity buttonEntity)
|
||||
{
|
||||
Buttons.push_back(buttonEntity);
|
||||
}
|
||||
|
||||
void UI::PollButtons(Window window)
|
||||
{
|
||||
for (int i = 0; i < Buttons.size(); i++)
|
||||
{
|
||||
/* Skip inactive buttons */
|
||||
if (!Buttons[i].clickComponent.active)
|
||||
continue;
|
||||
|
||||
/* Check if the cursor is on top of the button */
|
||||
if (!window.CursorInRect(Buttons[i].rect))
|
||||
continue;
|
||||
|
||||
/* Run the button click event */
|
||||
Buttons[i].clickComponent.onClick();
|
||||
|
||||
/* You can really only click one button at once, so lets stop if we got this far */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue