diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/crepe/api/Color.cpp | 37 | ||||
| -rw-r--r-- | src/crepe/api/Color.h | 49 | ||||
| -rw-r--r-- | src/crepe/api/Sprite.h | 3 | ||||
| -rw-r--r-- | src/crepe/facade/SDLContext.h | 6 | ||||
| -rw-r--r-- | src/crepe/system/RenderSystem.cpp | 43 | ||||
| -rw-r--r-- | src/crepe/system/RenderSystem.h | 32 | ||||
| -rw-r--r-- | src/doc/feature/script.dox | 62 | ||||
| -rw-r--r-- | src/doc/features.dox | 10 | ||||
| -rw-r--r-- | src/doc/index.dox | 10 | ||||
| -rw-r--r-- | src/doc/installing.dox | 9 | ||||
| -rw-r--r-- | src/doc/layout.xml | 252 | ||||
| -rw-r--r-- | src/doc/style.css | 4 | ||||
| -rw-r--r-- | src/example/rendering.cpp | 27 | ||||
| -rw-r--r-- | src/makefile | 7 | ||||
| -rw-r--r-- | src/test/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/test/ParticleTest.cpp | 2 | ||||
| -rw-r--r-- | src/test/RenderSystemTest.cpp | 174 | 
17 files changed, 630 insertions, 98 deletions
| diff --git a/src/crepe/api/Color.cpp b/src/crepe/api/Color.cpp index 9e5f187..29bd77a 100644 --- a/src/crepe/api/Color.cpp +++ b/src/crepe/api/Color.cpp @@ -2,32 +2,11 @@  using namespace crepe; -Color Color::white = Color(255, 255, 255, 0); -Color Color::red = Color(255, 0, 0, 0); -Color Color::green = Color(0, 255, 0, 0); -Color Color::blue = Color(0, 0, 255, 0); -Color Color::black = Color(0, 0, 0, 0); -Color Color::cyan = Color(0, 255, 255, 0); -Color Color::yellow = Color(255, 255, 0, 0); -Color Color::magenta = Color(255, 0, 255, 0); - -Color::Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha) { -	this->a = alpha; -	this->r = red; -	this->g = green; -	this->b = blue; -}; - -const Color & Color::get_white() { return Color::white; }; - -const Color & Color::get_red() { return Color::red; }; -const Color & Color::get_green() { return Color::green; }; -const Color & Color::get_blue() { return Color::blue; }; - -const Color & Color::get_black() { return Color::black; }; - -const Color & Color::get_cyan() { return Color::cyan; }; - -const Color & Color::get_yellow() { return Color::yellow; }; - -const Color & Color::get_magenta() { return Color::magenta; }; +const Color Color::WHITE{0xff, 0xff, 0xff}; +const Color Color::RED{0xff, 0x00, 0x00}; +const Color Color::GREEN{0x00, 0xff, 0x00}; +const Color Color::BLUE{0x00, 0x00, 0xff}; +const Color Color::BLACK{0x00, 0x00, 0x00}; +const Color Color::CYAN{0x00, 0xff, 0xff}; +const Color Color::YELLOW{0xff, 0xff, 0x00}; +const Color Color::MAGENTA{0xff, 0x00, 0xff}; diff --git a/src/crepe/api/Color.h b/src/crepe/api/Color.h index aa47bf4..84edb5c 100644 --- a/src/crepe/api/Color.h +++ b/src/crepe/api/Color.h @@ -4,41 +4,20 @@  namespace crepe { -// TODO: make Color a struct w/o constructors/destructors -class Color { - -	// FIXME: can't these colors be defined as a `static constexpr const Color` -	// instead? - -public: -	Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha); -	static const Color & get_white(); -	static const Color & get_red(); -	static const Color & get_green(); -	static const Color & get_blue(); -	static const Color & get_cyan(); -	static const Color & get_magenta(); -	static const Color & get_yellow(); -	static const Color & get_black(); - -private: -	// TODO: why are these private!? -	uint8_t r; -	uint8_t g; -	uint8_t b; -	uint8_t a; - -	static Color white; -	static Color red; -	static Color green; -	static Color blue; -	static Color cyan; -	static Color magenta; -	static Color yellow; -	static Color black; - -private: -	friend class SDLContext; +struct Color { +	uint8_t r = 0x00; +	uint8_t g = 0x00; +	uint8_t b = 0x00; +	uint8_t a = 0xff; + +	static const Color WHITE; +	static const Color RED; +	static const Color GREEN; +	static const Color BLUE; +	static const Color CYAN; +	static const Color MAGENTA; +	static const Color YELLOW; +	static const Color BLACK;  };  } // namespace crepe diff --git a/src/crepe/api/Sprite.h b/src/crepe/api/Sprite.h index 0192793..74a55d4 100644 --- a/src/crepe/api/Sprite.h +++ b/src/crepe/api/Sprite.h @@ -2,8 +2,9 @@  #include <memory> +#include "../Component.h" +  #include "Color.h" -#include "Component.h"  #include "Texture.h"  namespace crepe { diff --git a/src/crepe/facade/SDLContext.h b/src/crepe/facade/SDLContext.h index 007092b..652a83e 100644 --- a/src/crepe/facade/SDLContext.h +++ b/src/crepe/facade/SDLContext.h @@ -21,9 +21,6 @@ namespace crepe {  // typedef is unusable when crepe is packaged. Wouter will fix this later.  typedef SDL_Keycode CREPE_KEYCODES; -class Texture; -class LoopManager; -  /**   * \class SDLContext   * \brief Facade for the SDL library @@ -91,9 +88,6 @@ private:  	//! Will use the funtions: texture_from_path, get_width,get_height.  	friend class Texture; -	//! Will use the funtions: texture_from_path, get_width,get_height. -	friend class Animator; -  	/**  	 * \brief Loads a texture from a file path.  	 * \param path Path to the image file. diff --git a/src/crepe/system/RenderSystem.cpp b/src/crepe/system/RenderSystem.cpp index fa3d0de..96c5f27 100644 --- a/src/crepe/system/RenderSystem.cpp +++ b/src/crepe/system/RenderSystem.cpp @@ -1,38 +1,59 @@ +#include <algorithm> +#include <cassert>  #include <functional> +#include <stdexcept>  #include <vector>  #include "../ComponentManager.h"  #include "../api/Sprite.h"  #include "../api/Transform.h"  #include "../facade/SDLContext.h" -#include "../util/Log.h"  #include "RenderSystem.h"  using namespace crepe; +using namespace std; -void RenderSystem::clear_screen() const { SDLContext::get_instance().clear_screen(); } +void RenderSystem::clear_screen() { this->context.clear_screen(); } -void RenderSystem::present_screen() const { SDLContext::get_instance().present_screen(); } +void RenderSystem::present_screen() { this->context.present_screen(); }  void RenderSystem::update_camera() {  	ComponentManager & mgr = this->component_manager;  	std::vector<std::reference_wrapper<Camera>> cameras = mgr.get_components_by_type<Camera>(); +	if (cameras.size() == 0) throw std::runtime_error("No cameras in current scene"); +  	for (Camera & cam : cameras) { -		SDLContext::get_instance().camera(cam); -		this->curr_cam = &cam; +		this->context.camera(cam); +		this->curr_cam_ref = &cam;  	}  } -void RenderSystem::render_sprites() const { -	ComponentManager & mgr = this->component_manager; -	std::vector<std::reference_wrapper<Sprite>> sprites = mgr.get_components_by_type<Sprite>(); +bool sorting_comparison(const Sprite & a, const Sprite & b) { +	if (a.sorting_in_layer < b.sorting_in_layer) return true; +	if (a.sorting_in_layer == b.sorting_in_layer) return a.order_in_layer < b.order_in_layer; + +	return false; +} + +std::vector<std::reference_wrapper<Sprite>> +RenderSystem::sort(std::vector<std::reference_wrapper<Sprite>> & objs) { + +	std::vector<std::reference_wrapper<Sprite>> sorted_objs(objs); +	std::sort(sorted_objs.begin(), sorted_objs.end(), sorting_comparison); + +	return sorted_objs; +} + +void RenderSystem::render_sprites() { +	ComponentManager & mgr = this->component_manager; +	vector<reference_wrapper<Sprite>> sprites = mgr.get_components_by_type<Sprite>(); +	vector<reference_wrapper<Sprite>> sorted_sprites = this->sort(sprites); -	SDLContext & render = SDLContext::get_instance(); -	for (const Sprite & sprite : sprites) { +	for (const Sprite & sprite : sorted_sprites) {  		auto transforms = mgr.get_components_by_id<Transform>(sprite.game_object_id); -		render.draw(sprite, transforms[0], *curr_cam); +		this->context.draw(sprite, transforms[0], *this->curr_cam_ref);  	}  } diff --git a/src/crepe/system/RenderSystem.h b/src/crepe/system/RenderSystem.h index 87ec494..57b9c73 100644 --- a/src/crepe/system/RenderSystem.h +++ b/src/crepe/system/RenderSystem.h @@ -1,18 +1,23 @@  #pragma once -#include "api/Camera.h" +#include <functional> +#include <vector> + +#include "facade/SDLContext.h"  #include "System.h"  namespace crepe { +class Camera; +class Sprite; +  /**   * \class RenderSystem   * \brief Manages rendering operations for all game objects.   * - * RenderSystem is responsible for rendering sprites, clearing and presenting the screen, and - * managing the active camera. It functions as a singleton, providing centralized rendering - * services for the application. + * RenderSystem is responsible for rendering, clearing and presenting the screen, and + * managing the active camera.    */  class RenderSystem : public System {  public: @@ -25,16 +30,25 @@ public:  private:  	//! Clears the screen in preparation for rendering. -	void clear_screen() const; +	void clear_screen();  	//! Presents the rendered frame to the display. -	void present_screen() const; +	void present_screen();  	//! Updates the active camera used for rendering.  	void update_camera();  	//! Renders all active sprites to the screen. -	void render_sprites() const; +	void render_sprites(); + +	/** +	 * \brief sort a vector sprite objects with +	 * +	 * \param objs the vector that will do a sorting algorithm on  +	 * \return returns a sorted reference vector +	 */ +	std::vector<std::reference_wrapper<Sprite>> +	sort(std::vector<std::reference_wrapper<Sprite>> & objs);  	/**  	 * \todo Include color handling for sprites. @@ -48,8 +62,10 @@ private:  private:  	//! Pointer to the current active camera for rendering -	Camera * curr_cam = nullptr; +	Camera * curr_cam_ref = nullptr;  	// TODO: needs a better solution + +	SDLContext & context = SDLContext::get_instance();  };  } // namespace crepe diff --git a/src/doc/feature/script.dox b/src/doc/feature/script.dox new file mode 100644 index 0000000..d25a63b --- /dev/null +++ b/src/doc/feature/script.dox @@ -0,0 +1,62 @@ +// vim:ft=doxygen +namespace crepe { +/** + +\defgroup feature_script Scripting +\ingroup feature +\brief User-defined scripts for game objects + +Scripts can be used to implement game behavior, and allow arbitrary code to run +as part of the game loop. Scripts are implemented as derivative classes of +Script, which are added to game objects using the BehaviorScript \ref Component +"component". + +\todo This section is incomplete: +- Utility functions to get components/events/etc inside script +- How to listen for events +- Extensions of script (keylistener) + +\see Script +\see BehaviorScript +\see GameObject + +\par Example + +First, define a class that inherits from Script. This class acts as an +interface, and has two functions (\ref Script::init "\c init()" and \ref +Script::update "\c update()"), which may be implemented (they are empty by +default). From now on, this derivative class will be referred to as a *concrete +script*. + +```cpp +#include <crepe/api/Script.h> +#include <crepe/api/BehaviorScript.h> + +class MyScript : public crepe::Script { +	void init() { +		// called once +	} +	void update() { +		// called on fixed update +	} +}; +``` + +Concrete scripts can be instantiated and attached to \ref GameObject +"game objects" using the BehaviorScript \ref Component "component". + +```cpp +using namespace crepe; +GameObject obj = component_manager.new_object("name"); + +// create BehaviorScript instance +BehaviorScript & behavior_script = obj.add_component<BehaviorScript>(); +// attach (and instantiate) MyScript to behavior_script +behavior_script.set_script<MyScript>(); + +// the above can also be done in a single call for convenience: +obj.add_component<BehaviorScript>().set_script<MyScript>(); +``` + +*/ +} diff --git a/src/doc/features.dox b/src/doc/features.dox new file mode 100644 index 0000000..4786bed --- /dev/null +++ b/src/doc/features.dox @@ -0,0 +1,10 @@ +// vim:ft=doxygen +/** + +\defgroup feature Features +\brief Engine components + +This page lists engine features and contains usage instructions for each +feature. + +*/ diff --git a/src/doc/index.dox b/src/doc/index.dox new file mode 100644 index 0000000..5ec7889 --- /dev/null +++ b/src/doc/index.dox @@ -0,0 +1,10 @@ +// vim:ft=doxygen +/** + +\mainpage crêpe game engine + +Welcome to the documentation for the crêpe game engine. + +\see feature + +*/ diff --git a/src/doc/installing.dox b/src/doc/installing.dox new file mode 100644 index 0000000..48b27d7 --- /dev/null +++ b/src/doc/installing.dox @@ -0,0 +1,9 @@ +// vim:ft=doxygen +/** + +\defgroup install Installation +\brief Engine installation instructions + +\todo This entire page + +*/ diff --git a/src/doc/layout.xml b/src/doc/layout.xml new file mode 100644 index 0000000..2244fa7 --- /dev/null +++ b/src/doc/layout.xml @@ -0,0 +1,252 @@ +<?xml version="1.0" encoding="UTF-8"?> +<doxygenlayout version="1.0"> +	<navindex> +		<tab type="mainpage" visible="yes" title=""/> +		<tab type="pages" visible="no" title="" intro=""/> +		<tab type="topics" visible="yes" title="" intro=""/> +		<tab type="modules" visible="yes" title="" intro=""> +			<tab type="modulelist" visible="yes" title="" intro=""/> +			<tab type="modulemembers" visible="yes" title="" intro=""/> +		</tab> +		<tab type="namespaces" visible="no" title=""> +			<tab type="namespacelist" visible="yes" title="" intro=""/> +			<tab type="namespacemembers" visible="yes" title="" intro=""/> +		</tab> +		<tab type="concepts" visible="yes" title=""> +		</tab> +		<tab type="interfaces" visible="yes" title=""> +			<tab type="interfacelist" visible="yes" title="" intro=""/> +			<tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/> +			<tab type="interfacehierarchy" visible="yes" title="" intro=""/> +		</tab> +		<tab type="classes" visible="yes" title=""> +			<tab type="classlist" visible="yes" title="" intro=""/> +			<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/> +			<tab type="hierarchy" visible="yes" title="" intro=""/> +			<tab type="classmembers" visible="yes" title="" intro=""/> +		</tab> +		<tab type="structs" visible="yes" title=""> +			<tab type="structlist" visible="yes" title="" intro=""/> +			<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/> +		</tab> +		<tab type="exceptions" visible="yes" title=""> +			<tab type="exceptionlist" visible="yes" title="" intro=""/> +			<tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/> +			<tab type="exceptionhierarchy" visible="yes" title="" intro=""/> +		</tab> +		<tab type="files" visible="yes" title=""> +			<tab type="filelist" visible="yes" title="" intro=""/> +			<tab type="globals" visible="yes" title="" intro=""/> +		</tab> +		<tab type="examples" visible="yes" title="" intro=""/> +	</navindex> +	<class> +		<briefdescription visible="yes"/> +		<includes visible="$SHOW_HEADERFILE"/> +		<inheritancegraph visible="yes"/> +		<collaborationgraph visible="yes"/> +		<memberdecl> +			<nestedclasses visible="yes" title=""/> +			<publictypes title=""/> +			<services title=""/> +			<interfaces title=""/> +			<publicslots title=""/> +			<signals title=""/> +			<publicmethods title=""/> +			<publicstaticmethods title=""/> +			<publicattributes title=""/> +			<publicstaticattributes title=""/> +			<protectedtypes title=""/> +			<protectedslots title=""/> +			<protectedmethods title=""/> +			<protectedstaticmethods title=""/> +			<protectedattributes title=""/> +			<protectedstaticattributes title=""/> +			<packagetypes title=""/> +			<packagemethods title=""/> +			<packagestaticmethods title=""/> +			<packageattributes title=""/> +			<packagestaticattributes title=""/> +			<properties title=""/> +			<events title=""/> +			<privatetypes title=""/> +			<privateslots title=""/> +			<privatemethods title=""/> +			<privatestaticmethods title=""/> +			<privateattributes title=""/> +			<privatestaticattributes title=""/> +			<friends title=""/> +			<related title="" subtitle=""/> +			<membergroups visible="yes"/> +		</memberdecl> +		<detaileddescription title=""/> +		<memberdef> +			<inlineclasses title=""/> +			<typedefs title=""/> +			<enums title=""/> +			<services title=""/> +			<interfaces title=""/> +			<constructors title=""/> +			<functions title=""/> +			<related title=""/> +			<variables title=""/> +			<properties title=""/> +			<events title=""/> +		</memberdef> +		<allmemberslink visible="yes"/> +		<usedfiles visible="$SHOW_USED_FILES"/> +		<authorsection visible="yes"/> +	</class> +	<namespace> +		<briefdescription visible="yes"/> +		<memberdecl> +			<nestednamespaces visible="yes" title=""/> +			<constantgroups visible="yes" title=""/> +			<interfaces visible="yes" title=""/> +			<classes visible="yes" title=""/> +			<concepts visible="yes" title=""/> +			<structs visible="yes" title=""/> +			<exceptions visible="yes" title=""/> +			<typedefs title=""/> +			<sequences title=""/> +			<dictionaries title=""/> +			<enums title=""/> +			<functions title=""/> +			<variables title=""/> +			<properties title=""/> +			<membergroups visible="yes"/> +		</memberdecl> +		<detaileddescription title=""/> +		<memberdef> +			<inlineclasses title=""/> +			<typedefs title=""/> +			<sequences title=""/> +			<dictionaries title=""/> +			<enums title=""/> +			<functions title=""/> +			<variables title=""/> +			<properties title=""/> +		</memberdef> +		<authorsection visible="yes"/> +	</namespace> +	<concept> +		<briefdescription visible="yes"/> +		<includes visible="$SHOW_HEADERFILE"/> +		<definition visible="yes" title=""/> +		<detaileddescription title=""/> +		<authorsection visible="yes"/> +	</concept> +	<file> +		<briefdescription visible="yes"/> +		<includes visible="$SHOW_INCLUDE_FILES"/> +		<includegraph visible="yes"/> +		<includedbygraph visible="yes"/> +		<sourcelink visible="yes"/> +		<memberdecl> +			<interfaces visible="yes" title=""/> +			<classes visible="yes" title=""/> +			<structs visible="yes" title=""/> +			<exceptions visible="yes" title=""/> +			<namespaces visible="yes" title=""/> +			<concepts visible="yes" title=""/> +			<constantgroups visible="yes" title=""/> +			<defines title=""/> +			<typedefs title=""/> +			<sequences title=""/> +			<dictionaries title=""/> +			<enums title=""/> +			<functions title=""/> +			<variables title=""/> +			<properties title=""/> +			<membergroups visible="yes"/> +		</memberdecl> +		<detaileddescription title=""/> +		<memberdef> +			<inlineclasses title=""/> +			<defines title=""/> +			<typedefs title=""/> +			<sequences title=""/> +			<dictionaries title=""/> +			<enums title=""/> +			<functions title=""/> +			<variables title=""/> +			<properties title=""/> +		</memberdef> +		<authorsection/> +	</file> +	<group> +		<detaileddescription title=""/> +		<groupgraph visible="yes"/> +		<memberdecl> +			<nestedgroups visible="yes" title=""/> +			<modules visible="yes" title=""/> +			<dirs visible="yes" title=""/> +			<files visible="yes" title=""/> +			<namespaces visible="yes" title=""/> +			<concepts visible="yes" title=""/> +			<classes visible="yes" title=""/> +			<defines title=""/> +			<typedefs title=""/> +			<sequences title=""/> +			<dictionaries title=""/> +			<enums title=""/> +			<enumvalues title=""/> +			<functions title=""/> +			<variables title=""/> +			<signals title=""/> +			<publicslots title=""/> +			<protectedslots title=""/> +			<privateslots title=""/> +			<events title=""/> +			<properties title=""/> +			<friends title=""/> +			<membergroups visible="yes"/> +		</memberdecl> +		<memberdef> +			<pagedocs/> +			<inlineclasses title=""/> +			<defines title=""/> +			<typedefs title=""/> +			<sequences title=""/> +			<dictionaries title=""/> +			<enums title=""/> +			<enumvalues title=""/> +			<functions title=""/> +			<variables title=""/> +			<signals title=""/> +			<publicslots title=""/> +			<protectedslots title=""/> +			<privateslots title=""/> +			<events title=""/> +			<properties title=""/> +			<friends title=""/> +		</memberdef> +		<authorsection visible="yes"/> +	</group> +	<module> +		<briefdescription visible="yes"/> +		<exportedmodules visible="yes"/> +		<memberdecl> +			<concepts visible="yes" title=""/> +			<classes visible="yes" title=""/> +			<enums title=""/> +			<typedefs title=""/> +			<functions title=""/> +			<variables title=""/> +			<membergroups title=""/> +		</memberdecl> +		<detaileddescription title=""/> +		<memberdecl> +			<files visible="yes"/> +		</memberdecl> +	</module> +	<directory> +		<briefdescription visible="yes"/> +		<directorygraph visible="yes"/> +		<memberdecl> +			<dirs visible="yes"/> +			<files visible="yes"/> +		</memberdecl> +		<detaileddescription title=""/> +	</directory> +</doxygenlayout> diff --git a/src/doc/style.css b/src/doc/style.css new file mode 100644 index 0000000..08bc9f5 --- /dev/null +++ b/src/doc/style.css @@ -0,0 +1,4 @@ +#titlearea, +address { +	display: none; +} diff --git a/src/example/rendering.cpp b/src/example/rendering.cpp index c813524..522ec0f 100644 --- a/src/example/rendering.cpp +++ b/src/example/rendering.cpp @@ -30,14 +30,27 @@ int main() {  	// Normal adding components  	{  		Color color(0, 0, 0, 0); -		obj.add_component<Sprite>( -			make_shared<Texture>("asset/texture/img.png"), color, FlipSettings{false, false}); -		obj.add_component<Camera>(Color::get_red()); +		Sprite & sprite +			= obj.add_component<Sprite>(make_shared<Texture>("asset/texture/img.png"), +										color, FlipSettings{false, false}); +		sprite.sorting_in_layer = 2; +		sprite.order_in_layer = 1; +		obj.add_component<Camera>(Color::RED);  	}  	{  		Color color(0, 0, 0, 0); -		obj1.add_component<Sprite>( -			make_shared<Texture>("asset/texture/second.png"), color, FlipSettings{true, true}); +		Sprite & sprite = obj1.add_component<Sprite>( +			make_shared<Texture>("asset/texture/img.png"), color, FlipSettings{true, true}); +		sprite.sorting_in_layer = 2; +		sprite.order_in_layer = 2; +	} + +	{ +		Color color(0, 0, 0, 0); +		Sprite & sprite = obj2.add_component<Sprite>( +			make_shared<Texture>("asset/texture/img.png"), color, FlipSettings{true, true}); +		sprite.sorting_in_layer = 1; +		sprite.order_in_layer = 2;  	}  	/* @@ -48,8 +61,12 @@ int main() {  	}  	*/ +	sys.update(); +	/* +  	auto start = std::chrono::steady_clock::now();  	while (std::chrono::steady_clock::now() - start < std::chrono::seconds(5)) {  		sys.update();  	} +	*/  } diff --git a/src/makefile b/src/makefile index 5f80204..a0e8f02 100644 --- a/src/makefile +++ b/src/makefile @@ -1,6 +1,9 @@  .PHONY: FORCE -FMT := $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp')  format: FORCE -	clang-tidy -p build/compile_commands.json --fix-errors $(FMT) +	$(MAKE) -C .. $@ + +LINT := $(shell git ls-files '*.c' '*.cpp' '*.h' '*.hpp') +lint: FORCE +	clang-tidy -p build/compile_commands.json --fix-errors $(LINT) diff --git a/src/test/CMakeLists.txt b/src/test/CMakeLists.txt index f722082..f6e1dbb 100644 --- a/src/test/CMakeLists.txt +++ b/src/test/CMakeLists.txt @@ -5,5 +5,6 @@ target_sources(test_main PUBLIC  	ParticleTest.cpp  	AssetTest.cpp  	OptionalRefTest.cpp +	RenderSystemTest.cpp  ) diff --git a/src/test/ParticleTest.cpp b/src/test/ParticleTest.cpp index 4e655a9..cfbbc0e 100644 --- a/src/test/ParticleTest.cpp +++ b/src/test/ParticleTest.cpp @@ -29,7 +29,7 @@ public:  			Color color(0, 0, 0, 0);  			Sprite test_sprite = game_object.add_component<Sprite>( -				make_shared<Texture>("../asset/texture/img.png"), color, +				make_shared<Texture>("asset/texture/img.png"), color,  				FlipSettings{true, true});  			game_object.add_component<ParticleEmitter>(ParticleEmitter::Data{ diff --git a/src/test/RenderSystemTest.cpp b/src/test/RenderSystemTest.cpp new file mode 100644 index 0000000..ac479d3 --- /dev/null +++ b/src/test/RenderSystemTest.cpp @@ -0,0 +1,174 @@ +#include "api/Camera.h" +#include <functional> +#include <gtest/gtest.h> +#include <memory> +#include <vector> + +#define private public +#define protected public + +#include <crepe/ComponentManager.h> +#include <crepe/api/Color.h> +#include <crepe/api/GameObject.h> +#include <crepe/api/Sprite.h> +#include <crepe/api/Texture.h> + +#include <crepe/system/RenderSystem.h> + +using namespace std; +using namespace crepe; +using namespace testing; + +class RenderSystemTest : public Test { +public: +	ComponentManager mgr{}; +	RenderSystem sys{mgr}; +	GameObject entity1 = this->mgr.new_object("name"); +	GameObject entity2 = this->mgr.new_object("name"); +	GameObject entity3 = this->mgr.new_object("name"); +	GameObject entity4 = this->mgr.new_object("name"); + +	void SetUp() override { +		auto & sprite1 +			= entity1.add_component<Sprite>(make_shared<Texture>("../asset/texture/img.png"), +											Color(0, 0, 0, 0), FlipSettings{false, false}); +		ASSERT_NE(sprite1.sprite_image.get(), nullptr); +		sprite1.order_in_layer = 5; +		sprite1.sorting_in_layer = 5; +		EXPECT_EQ(sprite1.order_in_layer, 5); +		EXPECT_EQ(sprite1.sorting_in_layer, 5); +		auto & sprite2 +			= entity2.add_component<Sprite>(make_shared<Texture>("../asset/texture/img.png"), +											Color(0, 0, 0, 0), FlipSettings{false, false}); +		ASSERT_NE(sprite2.sprite_image.get(), nullptr); +		sprite2.sorting_in_layer = 2; +		sprite2.order_in_layer = 1; + +		EXPECT_EQ(sprite2.sorting_in_layer, 2); +		EXPECT_EQ(sprite2.order_in_layer, 1); + +		auto & sprite3 +			= entity3.add_component<Sprite>(make_shared<Texture>("../asset/texture/img.png"), +											Color(0, 0, 0, 0), FlipSettings{false, false}); +		ASSERT_NE(sprite3.sprite_image.get(), nullptr); +		sprite3.sorting_in_layer = 1; +		sprite3.order_in_layer = 2; + +		EXPECT_EQ(sprite3.sorting_in_layer, 1); +		EXPECT_EQ(sprite3.order_in_layer, 2); + +		auto & sprite4 +			= entity4.add_component<Sprite>(make_shared<Texture>("../asset/texture/img.png"), +											Color(0, 0, 0, 0), FlipSettings{false, false}); +		ASSERT_NE(sprite4.sprite_image.get(), nullptr); +		sprite4.sorting_in_layer = 1; +		sprite4.order_in_layer = 1; +		EXPECT_EQ(sprite4.sorting_in_layer, 1); +		EXPECT_EQ(sprite4.order_in_layer, 1); +	} +}; + +TEST_F(RenderSystemTest, expected_throws) { +	GameObject entity1 = this->mgr.new_object("NAME"); + +	// no texture img +	EXPECT_ANY_THROW({ +		entity1.add_component<Sprite>(make_shared<Texture>("NO_IMAGE"), Color(0, 0, 0, 0), +									  FlipSettings{false, false}); +	}); + +	// No camera +	EXPECT_ANY_THROW({ this->sys.update(); }); +} + +TEST_F(RenderSystemTest, make_sprites) {} + +TEST_F(RenderSystemTest, sorting_sprites) { +	vector<reference_wrapper<Sprite>> sprites = this->mgr.get_components_by_type<Sprite>(); +	ASSERT_EQ(sprites.size(), 4); + +	vector<reference_wrapper<Sprite>> sorted_sprites = this->sys.sort(sprites); +	ASSERT_EQ(sorted_sprites.size(), 4); + +	// Expected order after sorting: +	// 1. sorting_in_layer: 1, order_in_layer: 1 (entity4) +	// 2. sorting_in_layer: 1, order_in_layer: 2 (entity3) +	// 3. sorting_in_layer: 2, order_in_layer: 1 (entity2) +	// 4. sorting_in_layer: 5, order_in_layer: 5 (entity1) + +	EXPECT_EQ(sorted_sprites[0].get().sorting_in_layer, 1); +	EXPECT_EQ(sorted_sprites[0].get().order_in_layer, 1); + +	EXPECT_EQ(sorted_sprites[1].get().sorting_in_layer, 1); +	EXPECT_EQ(sorted_sprites[1].get().order_in_layer, 2); + +	EXPECT_EQ(sorted_sprites[2].get().sorting_in_layer, 2); +	EXPECT_EQ(sorted_sprites[2].get().order_in_layer, 1); + +	EXPECT_EQ(sorted_sprites[3].get().sorting_in_layer, 5); +	EXPECT_EQ(sorted_sprites[3].get().order_in_layer, 5); + +	for (size_t i = 1; i < sorted_sprites.size(); ++i) { +		const Sprite & prev = sorted_sprites[i - 1].get(); +		const Sprite & curr = sorted_sprites[i].get(); + +		if (prev.sorting_in_layer == curr.sorting_in_layer) { +			EXPECT_LE(prev.order_in_layer, curr.order_in_layer); +		} else { +			EXPECT_LE(prev.sorting_in_layer, curr.sorting_in_layer); +		} +	} +} + +TEST_F(RenderSystemTest, Update) { +	entity1.add_component<Camera>(Color::WHITE); +	{ +		vector<reference_wrapper<Sprite>> sprites = this->mgr.get_components_by_type<Sprite>(); +		ASSERT_EQ(sprites.size(), 4); + +		EXPECT_EQ(sprites[0].get().game_object_id, 0); +		EXPECT_EQ(sprites[1].get().game_object_id, 1); +		EXPECT_EQ(sprites[2].get().game_object_id, 2); +		EXPECT_EQ(sprites[3].get().game_object_id, 3); +	} +	this->sys.update(); +	{ +		vector<reference_wrapper<Sprite>> sprites = this->mgr.get_components_by_type<Sprite>(); +		ASSERT_EQ(sprites.size(), 4); + +		EXPECT_EQ(sprites[0].get().game_object_id, 0); +		EXPECT_EQ(sprites[1].get().game_object_id, 1); +		EXPECT_EQ(sprites[2].get().game_object_id, 2); +		EXPECT_EQ(sprites[3].get().game_object_id, 3); +	} +} + +TEST_F(RenderSystemTest, Camera) { +	{ +		auto cameras = this->mgr.get_components_by_type<Camera>(); +		EXPECT_NE(cameras.size(), 1); +	} +	{ +		entity1.add_component<Camera>(Color::WHITE); +		auto cameras = this->mgr.get_components_by_type<Camera>(); +		EXPECT_EQ(cameras.size(), 1); +	} + +	//TODO improve with newer version +} +TEST_F(RenderSystemTest, Color) { +	entity1.add_component<Camera>(Color::WHITE); +	auto & sprite = this->mgr.get_components_by_id<Sprite>(entity1.id).front().get(); +	ASSERT_NE(sprite.sprite_image.get(), nullptr); + +	sprite.color = Color::GREEN; +	EXPECT_EQ(sprite.color.r, Color::GREEN.r); +	EXPECT_EQ(sprite.color.g, Color::GREEN.g); +	EXPECT_EQ(sprite.color.b, Color::GREEN.b); +	EXPECT_EQ(sprite.color.a, Color::GREEN.a); +	this->sys.update(); +	EXPECT_EQ(sprite.color.r, Color::GREEN.r); +	EXPECT_EQ(sprite.color.g, Color::GREEN.g); +	EXPECT_EQ(sprite.color.b, Color::GREEN.b); +	EXPECT_EQ(sprite.color.a, Color::GREEN.a); +} |