diff options
| -rw-r--r-- | game/CMakeLists.txt | 9 | ||||
| -rw-r--r-- | game/Config.h | 19 | ||||
| -rw-r--r-- | game/GameScene.cpp | 58 | ||||
| -rw-r--r-- | game/Random.cpp | 2 | ||||
| -rw-r--r-- | game/Random.h | 1 | ||||
| -rw-r--r-- | game/background/CMakeLists.txt | 9 | ||||
| -rw-r--r-- | game/main.cpp | 9 | ||||
| -rw-r--r-- | game/menus/MenusConfig.h | 1 | ||||
| -rw-r--r-- | game/menus/mainmenu/ITransitionScript.cpp | 1 | ||||
| -rw-r--r-- | game/prefab/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | game/prefab/ZapperObject.cpp | 118 | ||||
| -rw-r--r-- | game/prefab/ZapperObject.h | 40 | ||||
| -rw-r--r-- | game/prefab/ZapperPoolScript.cpp | 70 | ||||
| -rw-r--r-- | game/prefab/ZapperPoolScript.h | 33 | ||||
| -rw-r--r-- | game/prefab/ZapperPoolSubScene.cpp | 18 | ||||
| -rw-r--r-- | game/prefab/ZapperPoolSubScene.h | 19 | ||||
| -rwxr-xr-x | game/util/scrollgen | 36 | ||||
| -rw-r--r-- | src/crepe/Collider.h | 3 | ||||
| -rw-r--r-- | src/crepe/api/Components.h | 16 | ||||
| -rw-r--r-- | src/crepe/api/Config.h | 3 | ||||
| -rw-r--r-- | src/crepe/api/Vector2.h | 46 | ||||
| -rw-r--r-- | src/crepe/api/Vector2.hpp | 15 | ||||
| -rw-r--r-- | src/test/Vector2Test.cpp | 10 | 
23 files changed, 466 insertions, 76 deletions
| diff --git a/game/CMakeLists.txt b/game/CMakeLists.txt index f81850d..497b880 100644 --- a/game/CMakeLists.txt +++ b/game/CMakeLists.txt @@ -7,7 +7,10 @@ set(CMAKE_BUILD_TYPE Debug)  project(game C CXX)  add_subdirectory(../src crepe) -add_executable(main + +add_executable(main) + +target_sources(main PUBLIC  	background/AquariumSubScene.cpp  	background/AquariumScript.cpp  	background/BackgroundSubScene.cpp @@ -57,5 +60,9 @@ add_executable(main  	Random.cpp  ) +add_subdirectory(background) +add_subdirectory(prefab) +  target_link_libraries(main PUBLIC crepe) +target_include_directories(main PRIVATE .) diff --git a/game/Config.h b/game/Config.h index c2f95c0..37be1a6 100644 --- a/game/Config.h +++ b/game/Config.h @@ -1,6 +1,17 @@  #pragma once  #include "types.h" +#include <crepe/api/Config.h> + +static const crepe::Config ENGINE_CONFIG { +	.log { +		.level = crepe::Log::Level::DEBUG, +	}, +	.window_settings { +		.window_title = "Jetpack joyride clone", +	}, +}; +  static constexpr int SORT_IN_LAY_BACK_BACKGROUND = 3; // For all scenes  static constexpr int SORT_IN_LAY_BACKGROUND = 4; // For all scenes  static constexpr int SORT_IN_LAY_FORE_BACKGROUND = 5; // For all scenes @@ -21,11 +32,12 @@ static constexpr int COLL_LAY_ZAPPER = 6; // Only for GameScene  static constexpr int COLL_LAY_LASER = 7; // Only for GameScene  static constexpr int COLL_LAY_MISSILE = 8; // Only for GameScene -static constexpr int GAME_HEIGHT = 800; // In game units +static constexpr float GAME_HEIGHT = 800; // In game units +static constexpr float HALLWAY_HEIGHT = 475; // In game units -static constexpr int VIEWPORT_X = 1100; // In game units +static constexpr float VIEWPORT_X = 1100; // In game units  // 'GAME_HEIGHT' (below) should be replaced by '500' when game development is finished -static constexpr int VIEWPORT_Y = 500; // In game units +static constexpr float VIEWPORT_Y = 500; // In game units  // Font settings  static constexpr const char * FONT = "Jetpackia"; @@ -46,5 +58,6 @@ static constexpr const char * PLAYER_NAME = "player";  static constexpr int PLAYER_SPEED = 7500; // In game units  static constexpr int PLAYER_GRAVITY_SCALE = 60; // In game units +static constexpr const char * CAMERA_NAME = "camera";  // Jetpack particles  static constexpr const char * JETPACK_PARTICLES = "jetpack_particles"; diff --git a/game/GameScene.cpp b/game/GameScene.cpp index c84ec24..9de2fd1 100644 --- a/game/GameScene.cpp +++ b/game/GameScene.cpp @@ -11,6 +11,7 @@  #include "hud/SpeedScript.h"  #include "menus/endgame/EndGameSubScene.h"  #include "player/PlayerSubScene.h" +#include "prefab/ZapperPoolSubScene.h"  #include "workers/WorkersSubScene.h"  #include <cmath> @@ -34,9 +35,11 @@ using namespace crepe;  using namespace std;  void GameScene::load_scene() { +	logf(Log::DEBUG, "Loading (main) GameScene..."); +  	BackgroundSubScene background(*this); -	GameObject camera = new_object("camera", "camera", vec2(650, 0)); +	GameObject camera = new_object(CAMERA_NAME, "camera", vec2(650, 0));  	camera.add_component<Camera>(  		ivec2(990, 720), vec2(VIEWPORT_X, VIEWPORT_Y),  		Camera::Data { @@ -78,6 +81,8 @@ void GameScene::load_scene() {  	});  	ceiling.add_component<BoxCollider>(vec2(INFINITY, 200)); +	ZapperPoolSubScene {*this}; +  	GameObject start_game_script = new_object("start_game_script", "script", vec2(0, 0));  	start_game_script.add_component<BehaviorScript>().set_script<StartGameScript>(); @@ -87,6 +92,7 @@ void GameScene::load_scene() {  	HudSubScene hud;  	hud.create(*this); +  	GameObject background_music = new_object("background_music", "audio", vec2(0, 0));  	Asset background_music_asset {"asset/music/level.ogg"};  	background_music.add_component<AudioSource>(background_music_asset); @@ -95,56 +101,6 @@ void GameScene::load_scene() {  	Asset boom_audio_asset {"asset/sfx/window_smash.ogg"};  	boom_audio.add_component<AudioSource>(boom_audio_asset); -	// zapper, laser and missile (below) for testing purpose only!!! -	GameObject zapper = new_object("zapper", "zapper", vec2(1000, 200)); -	Asset zapper_asset {"asset/obstacles/zapper/regular_zappers/zapEffect.png"}; -	Sprite & zapper_sprite = zapper.add_component<Sprite>( -		zapper_asset, -		Sprite::Data { -			.sorting_in_layer = SORT_IN_LAY_OBSTACLES, -			.order_in_layer = 0, -			.size = vec2(100, 100), -		} -	); -	zapper.add_component<Rigidbody>(Rigidbody::Data { -		.body_type = Rigidbody::BodyType::KINEMATIC, -		.kinematic_collision = false, -		.collision_layer = COLL_LAY_ZAPPER, -	}); -	zapper.add_component<BoxCollider>(vec2(100, 100)); -	GameObject laser = new_object("laser", "laser", vec2(2000, 200)); -	Asset laser_asset {"asset/obstacles/laser/laserPower.png"}; -	Sprite & laser_sprite = laser.add_component<Sprite>( -		laser_asset, -		Sprite::Data { -			.sorting_in_layer = SORT_IN_LAY_OBSTACLES, -			.order_in_layer = 0, -			.size = vec2(100, 100), -		} -	); -	laser.add_component<Rigidbody>(Rigidbody::Data { -		.body_type = Rigidbody::BodyType::KINEMATIC, -		.kinematic_collision = false, -		.collision_layer = COLL_LAY_LASER, -	}); -	laser.add_component<BoxCollider>(vec2(100, 100)); -	GameObject missile = new_object("missile", "missile", vec2(4000, 200)); -	Asset missile_asset {"asset/obstacles/missile/missile.png"}; -	Sprite & missile_sprite = missile.add_component<Sprite>( -		missile_asset, -		Sprite::Data { -			.sorting_in_layer = SORT_IN_LAY_OBSTACLES, -			.order_in_layer = 0, -			.size = vec2(100, 100), -		} -	); -	missile.add_component<Rigidbody>(Rigidbody::Data { -		.body_type = Rigidbody::BodyType::KINEMATIC, -		.kinematic_collision = false, -		.collision_layer = COLL_LAY_MISSILE, -	}); -	missile.add_component<BoxCollider>(vec2(100, 100)); -  	EndGameSubScene endgamewindow;  	endgamewindow.create(*this);  } diff --git a/game/Random.cpp b/game/Random.cpp index ace6245..64cf1f3 100644 --- a/game/Random.cpp +++ b/game/Random.cpp @@ -25,3 +25,5 @@ unsigned Random::u(unsigned upper, unsigned lower) {  	unsigned x = rand() % range;  	return x + lower;  } + +bool Random::b() { return rand() % 2; } diff --git a/game/Random.h b/game/Random.h index 8af9669..94f98d2 100644 --- a/game/Random.h +++ b/game/Random.h @@ -6,4 +6,5 @@ public:  	static double d(double upper = 1.0, double lower = 0.0);  	static int i(int upper, int lower = 0);  	static unsigned u(unsigned upper, unsigned lower = 0); +	static bool b();  }; diff --git a/game/background/CMakeLists.txt b/game/background/CMakeLists.txt new file mode 100644 index 0000000..1d705f5 --- /dev/null +++ b/game/background/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(main PUBLIC +	AquariumSubScene.cpp +	BackgroundSubScene.cpp +	ForestParallaxScript.cpp +	ForestSubScene.cpp +	HallwaySubScene.cpp +	StartSubScene.cpp +) + diff --git a/game/main.cpp b/game/main.cpp index e341353..b6458b8 100644 --- a/game/main.cpp +++ b/game/main.cpp @@ -1,6 +1,9 @@ +#include <cstdlib> +  #include <crepe/api/Engine.h>  #include <crepe/api/Script.h> +#include "Config.h"  #include "GameScene.h"  #include "menus/mainmenu/MainMenuScene.h"  #include "menus/shop/ShopMenuScene.h" @@ -8,10 +11,14 @@  using namespace crepe;  int main() { +	srand(time(NULL)); + +	Config::get_instance() = ENGINE_CONFIG; +  	Engine gameloop; +	gameloop.add_scene<GameScene>();  	gameloop.add_scene<MainMenuScene>();  	gameloop.add_scene<ShopMenuScene>(); -	gameloop.add_scene<GameScene>();  	return gameloop.main();  } diff --git a/game/menus/MenusConfig.h b/game/menus/MenusConfig.h index 6ec5689..24b60e8 100644 --- a/game/menus/MenusConfig.h +++ b/game/menus/MenusConfig.h @@ -3,7 +3,6 @@  //generic menu config  static constexpr int STARTING_SORTING_IN_LAYER = 7; -static constexpr const char * CAMERA_NAME = "camera";  //Scene names  static constexpr const char * START_SCENE = "scene1";  static constexpr const char * PREVIEW_SCENE = "scene1"; diff --git a/game/menus/mainmenu/ITransitionScript.cpp b/game/menus/mainmenu/ITransitionScript.cpp index cd929a0..54b0875 100644 --- a/game/menus/mainmenu/ITransitionScript.cpp +++ b/game/menus/mainmenu/ITransitionScript.cpp @@ -1,6 +1,7 @@  #include "ITransitionScript.h"  #include "MainMenuConfig.h" +#include "../../Config.h"  #include "../MenusConfig.h"  #include <crepe/api/Camera.h> diff --git a/game/prefab/CMakeLists.txt b/game/prefab/CMakeLists.txt new file mode 100644 index 0000000..6c36ef2 --- /dev/null +++ b/game/prefab/CMakeLists.txt @@ -0,0 +1,6 @@ +target_sources(main PUBLIC +	ZapperObject.cpp +	ZapperPoolSubScene.cpp +	ZapperPoolScript.cpp +) + diff --git a/game/prefab/ZapperObject.cpp b/game/prefab/ZapperObject.cpp new file mode 100644 index 0000000..24bbbd2 --- /dev/null +++ b/game/prefab/ZapperObject.cpp @@ -0,0 +1,118 @@ +#include <crepe/api/Transform.h> + +#include "Config.h" +#include "ZapperObject.h" + +using namespace crepe; + +ZapperObject::ZapperObject(crepe::GameObject && base) +	: GameObject(std::move(base)), +	  sprite { +		  .orb_start = add_component<Sprite>( +			  Asset {"asset/obstacles/zapper/orbAnim.png"}, +			  Sprite::Data { +				  .sorting_in_layer = SORT_IN_LAY_OBSTACLES, +				  .order_in_layer = 1, +				  .size = vec2(0, 50) * SCALE, +			  } +		  ), +		  .orb_end = add_component<Sprite>( +			  sprite.orb_start.source, +			  Sprite::Data { +				  .flip = {true, true}, +				  .sorting_in_layer = SORT_IN_LAY_OBSTACLES, +				  .order_in_layer = 1, +				  .size = vec2(0, 50) * SCALE, +			  } +		  ), +		  .glow_start = add_component<Sprite>( +			  Asset {"asset/obstacles/zapper/regular_zappers/glow.png"}, +			  Sprite::Data { +				  .sorting_in_layer = SORT_IN_LAY_OBSTACLES, +				  .order_in_layer = -1, +				  .size = vec2(128, 128) * SCALE, +			  } +		  ), +		  .glow_end = add_component<Sprite>( +			  sprite.glow_start.source, +			  Sprite::Data { +				  .flip = {true, true}, +				  .sorting_in_layer = SORT_IN_LAY_OBSTACLES, +				  .order_in_layer = -1, +				  .size = vec2(128, 128) * SCALE, +			  } +		  ), +		  .beam = add_component<Sprite>( +			  Asset {"asset/obstacles/zapper/regular_zappers/zapEffect.png"}, +			  Sprite::Data { +				  .sorting_in_layer = SORT_IN_LAY_OBSTACLES, +				  .order_in_layer = 0, +				  .size = vec2(0, 40 * SCALE), +				  .angle_offset = 90, +			  } +		  ), +	  }, +	  animator { +		  .orb_start = add_component<Animator>( +			  sprite.orb_start, ivec2(62, 42), uvec2(4, 1), +			  Animator::Data { +				  .fps = 10, +				  .looping = true, +			  } +		  ), +		  .orb_end = add_component<Animator>( +			  sprite.orb_end, ivec2(62, 42), uvec2(4, 1), animator.orb_start.data +		  ), +		  .glow_start = add_component<Animator>( +			  sprite.glow_start, ivec2(128, 128), uvec2(16, 1), +			  Animator::Data { +				  .fps = 30, +				  .looping = true, +			  } +		  ), +		  .glow_end = add_component<Animator>( +			  sprite.glow_end, ivec2(128, 128), uvec2(16, 1), animator.glow_start.data +		  ), +	  }, +	  body {add_component<Rigidbody>(Rigidbody::Data { +		  .body_type = Rigidbody::BodyType::KINEMATIC, +		  .kinematic_collision = false, +		  .collision_layer = COLL_LAY_ZAPPER, +	  })}, +	  collider {add_component<BoxCollider>(vec2(0, 0))} { +	this->set_active(false); +} + +void ZapperObject::place(const crepe::vec2 & position, float rotation, float length) { +	this->transform.position = position; +	this->transform.rotation = rotation; + +	vec2 offset = vec2(0, 1) * length / 2; + +	this->sprite.orb_start.data.position_offset = offset; +	this->sprite.glow_start.data.position_offset = offset; +	this->sprite.orb_end.data.position_offset = -offset; +	this->sprite.glow_end.data.position_offset = -offset; + +	this->sprite.beam.data.size.x = length; + +	this->collider.dimensions = offset.rotate(rotation) * 2 + vec2(30, 30) * SCALE; +} + +void ZapperObject::set_active(bool active) { +	this->sprite.orb_start.active = active; +	this->sprite.orb_end.active = active; +	this->sprite.glow_start.active = active; +	this->sprite.glow_end.active = active; +	this->sprite.beam.active = active; + +	this->animator.orb_start.active = active; +	this->animator.orb_end.active = active; +	this->animator.glow_start.active = active; +	this->animator.glow_end.active = active; + +	this->body.active = active; +	this->collider.active = active; + +	this->active = active; +} diff --git a/game/prefab/ZapperObject.h b/game/prefab/ZapperObject.h new file mode 100644 index 0000000..42edc51 --- /dev/null +++ b/game/prefab/ZapperObject.h @@ -0,0 +1,40 @@ +#pragma once + +#include <crepe/api/Animator.h> +#include <crepe/api/BoxCollider.h> +#include <crepe/api/GameObject.h> +#include <crepe/api/Rigidbody.h> +#include <crepe/api/Sprite.h> + +class ZapperObject : public crepe::GameObject { +public: +	ZapperObject(crepe::GameObject &&); + +public: +	bool active = true; + +	struct { +		crepe::Sprite & orb_start; +		crepe::Sprite & orb_end; +		crepe::Sprite & glow_start; +		crepe::Sprite & glow_end; +		crepe::Sprite & beam; +	} sprite; + +	struct { +		crepe::Animator & orb_start; +		crepe::Animator & orb_end; +		crepe::Animator & glow_start; +		crepe::Animator & glow_end; +	} animator; + +	crepe::Rigidbody & body; +	crepe::BoxCollider & collider; + +private: +	static constexpr float SCALE = 0.8; + +public: +	void place(const crepe::vec2 & position, float rotation, float length); +	void set_active(bool active); +}; diff --git a/game/prefab/ZapperPoolScript.cpp b/game/prefab/ZapperPoolScript.cpp new file mode 100644 index 0000000..b832ddd --- /dev/null +++ b/game/prefab/ZapperPoolScript.cpp @@ -0,0 +1,70 @@ +#include <crepe/api/Camera.h> + +#include "../Config.h" +#include "../Random.h" + +#include "ZapperPoolScript.h" +#include "ZapperPoolSubScene.h" +#include "util/OptionalRef.h" + +using namespace crepe; +using namespace std; + +ZapperPoolScript::ZapperPoolScript(std::vector<ZapperObject> && pool) : pool(pool) {} + +void ZapperPoolScript::init() { +	subscribe<CreateZapperEvent>([this](const CreateZapperEvent &) { +		this->spawn_random(); +		return true; +	}); + +	camera_transform = get_components_by_name<Transform>(CAMERA_NAME).back(); +	camera_camera = get_components_by_name<Camera>(CAMERA_NAME).back(); +} + +void ZapperPoolScript::fixed_update(crepe::duration_t) { +	float threshold +		= camera_transform->position.x - camera_camera->viewport_size.x / 2 - OFFSCREEN_MARGIN; +	for (ZapperObject & zapper : this->pool) { +		if (!zapper.active) continue; + +		if (zapper.transform.position.x < threshold) zapper.set_active(false); +	} +} + +void ZapperPoolScript::spawn_random() { +	OptionalRef<ZapperObject> zapper = this->get_next_zapper(); +	if (!zapper) return; // pool exhausted + +	bool horizontal = Random::b(); +	vec2 pos; +	float rotation, length; +	pos.x +		= camera_transform->position.x + camera_camera->viewport_size.x / 2 + OFFSCREEN_MARGIN; + +	if (horizontal) { +		rotation = 90; +		length = Random::f(400, 200); +		pos.y = Random::f(0.5, -0.5) * HALLWAY_HEIGHT; +		// align zapper to right edge of camera +		pos.x -= MAX_LENGTH - (length / 2); +	} else { +		rotation = 0; +		length = Random::f(200, 75); +		// ensure zapper doesn't crash into ceiling or floor +		pos.y = Random::f(0.5, -0.5) * (HALLWAY_HEIGHT - length); +		// align zapper to right edge of camera +		pos.x -= MAX_LENGTH; +	} + +	zapper->place(pos, rotation, length); +	zapper->set_active(true); +} + +OptionalRef<ZapperObject> ZapperPoolScript::get_next_zapper() { +	for (ZapperObject & zapper : this->pool) { +		if (zapper.active) continue; +		return zapper; +	} +	return {}; +} diff --git a/game/prefab/ZapperPoolScript.h b/game/prefab/ZapperPoolScript.h new file mode 100644 index 0000000..2208c80 --- /dev/null +++ b/game/prefab/ZapperPoolScript.h @@ -0,0 +1,33 @@ +#pragma once + +#include <crepe/api/Script.h> + +#include "ZapperObject.h" +#include "util/OptionalRef.h" + +class ZapperPoolSubScene; + +class ZapperPoolScript : public crepe::Script { +public: +	ZapperPoolScript(std::vector<ZapperObject> && pool); + +	void init(); +	void fixed_update(crepe::duration_t); + +	unsigned i = 0; + +private: +	std::vector<ZapperObject> pool; + +private: +	crepe::OptionalRef<crepe::Transform> camera_transform; +	crepe::OptionalRef<crepe::Camera> camera_camera; +	crepe::OptionalRef<ZapperObject> get_next_zapper(); + +private: +	void spawn_random(); + +private: +	static constexpr float MAX_LENGTH = 400; +	static constexpr float OFFSCREEN_MARGIN = 50 + MAX_LENGTH; +}; diff --git a/game/prefab/ZapperPoolSubScene.cpp b/game/prefab/ZapperPoolSubScene.cpp new file mode 100644 index 0000000..8422b8c --- /dev/null +++ b/game/prefab/ZapperPoolSubScene.cpp @@ -0,0 +1,18 @@ +#include <crepe/api/BehaviorScript.h> + +#include "ZapperPoolScript.h" +#include "ZapperPoolSubScene.h" + +using namespace crepe; +using namespace std; + +ZapperPoolSubScene::ZapperPoolSubScene(Scene & scene) +	: controller {scene.new_object("controller")} { + +	Log::logf(Log::DEBUG, "Building zapper pool..."); +	vector<ZapperObject> pool; +	for (size_t i = 0; i < this->POOL_SIZE; i++) +		pool.emplace_back(scene.new_object("zapper", "zapper")); +	BehaviorScript & behavior = this->controller.add_component<BehaviorScript>(); +	behavior.set_script<ZapperPoolScript>(std::move(pool)); +} diff --git a/game/prefab/ZapperPoolSubScene.h b/game/prefab/ZapperPoolSubScene.h new file mode 100644 index 0000000..6f6e297 --- /dev/null +++ b/game/prefab/ZapperPoolSubScene.h @@ -0,0 +1,19 @@ +#pragma once + +#include <crepe/api/Event.h> +#include <crepe/api/GameObject.h> +#include <crepe/api/Scene.h> +#include <crepe/util/OptionalRef.h> + +class CreateZapperEvent : public crepe::Event {}; + +class ZapperPoolSubScene { +public: +	ZapperPoolSubScene(crepe::Scene & scene); + +private: +	crepe::GameObject controller; + +private: +	static constexpr size_t POOL_SIZE = 4; +}; diff --git a/game/util/scrollgen b/game/util/scrollgen new file mode 100755 index 0000000..0389107 --- /dev/null +++ b/game/util/scrollgen @@ -0,0 +1,36 @@ +#!/bin/sh +INPUT="$1" +FRAMES="$2" + +die() { +	echo "$@" +	exit 1 +} +check_command() { +	cmd="$1" +	command -v "$cmd" > /dev/null || die "command '$cmd' not found" +} + +check_command magick +check_command identify +[ "$#" -eq 2 ] || die "usage: $0 <input image> <frame count>" +[ -e "$INPUT" ] || die "file not found: $INPUT" +[ "$FRAMES" -gt 0 ] || die "invalid frame count: $FRAMES" + +tile_width=$(identify -format "%w" "$INPUT") +tile_height=$(identify -format "%h" "$INPUT") + +OUTPUT="$INPUT.scroll.png" +magick -size "${tile_width}x$(( $tile_height * $FRAMES ))" 'xc:#ff00ff00' "$OUTPUT" + +for i in $(seq 0 $(( $FRAMES - 1 ))); do +	offset_x=$(( $tile_width * $i / $FRAMES )) +	offset_y=$(( i * $tile_height )) + +	magick "$OUTPUT" "$INPUT" -geometry "+${offset_x}+${offset_y}" -composite "$OUTPUT" +	magick "$OUTPUT" "$INPUT" -geometry "+$(( $offset_x - $tile_width ))+${offset_y}" -composite "$OUTPUT" +	echo "+${offset_x}+${offset_y}" +done + +# magick -size ${total_width}x${sprite_height} xc:none canvas.png + diff --git a/src/crepe/Collider.h b/src/crepe/Collider.h index 42ccfd4..4344f15 100644 --- a/src/crepe/Collider.h +++ b/src/crepe/Collider.h @@ -5,6 +5,9 @@  namespace crepe { +/** + * \brief Base collider class + */  class Collider : public Component {  public:  	Collider(game_object_id_t id, const vec2 & offset); diff --git a/src/crepe/api/Components.h b/src/crepe/api/Components.h new file mode 100644 index 0000000..fa0663d --- /dev/null +++ b/src/crepe/api/Components.h @@ -0,0 +1,16 @@ +#pragma once + +#include "AI.h" +#include "Animator.h" +#include "AudioSource.h" +#include "BehaviorScript.h" +#include "BoxCollider.h" +#include "Button.h" +#include "Camera.h" +#include "CircleCollider.h" +#include "Metadata.h" +#include "ParticleEmitter.h" +#include "Rigidbody.h" +#include "Sprite.h" +#include "Text.h" +#include "Transform.h" diff --git a/src/crepe/api/Config.h b/src/crepe/api/Config.h index 9c226a3..7475528 100644 --- a/src/crepe/api/Config.h +++ b/src/crepe/api/Config.h @@ -60,7 +60,8 @@ struct Config final {  	struct {  		//! default screen size in pixels  		ivec2 default_size = {1280, 720}; -		std::string window_title = "Jetpack joyride clone"; +		//! default window title +		std::string window_title = "crepe window";  	} window_settings;  	//! Asset loading options diff --git a/src/crepe/api/Vector2.h b/src/crepe/api/Vector2.h index 52e1bb6..6613641 100644 --- a/src/crepe/api/Vector2.h +++ b/src/crepe/api/Vector2.h @@ -1,5 +1,7 @@  #pragma once +#include <format> +  namespace crepe {  //! 2D vector @@ -11,55 +13,55 @@ struct Vector2 {  	T y = 0;  	//! Subtracts another vector from this vector and returns the result. -	Vector2 operator-(const Vector2<T> & other) const; +	Vector2<T> operator-(const Vector2<T> & other) const;  	//! Subtracts a scalar value from both components of this vector and returns the result. -	Vector2 operator-(T scalar) const; +	Vector2<T> operator-(T scalar) const;  	//! Adds another vector to this vector and returns the result. -	Vector2 operator+(const Vector2<T> & other) const; +	Vector2<T> operator+(const Vector2<T> & other) const;  	//! Adds a scalar value to both components of this vector and returns the result. -	Vector2 operator+(T scalar) const; +	Vector2<T> operator+(T scalar) const;  	//! Multiplies this vector by another vector element-wise and returns the result. -	Vector2 operator*(const Vector2<T> & other) const; +	Vector2<T> operator*(const Vector2<T> & other) const;  	//! Multiplies this vector by a scalar and returns the result. -	Vector2 operator*(T scalar) const; +	Vector2<T> operator*(T scalar) const;  	//! Divides this vector by another vector element-wise and returns the result. -	Vector2 operator/(const Vector2<T> & other) const; +	Vector2<T> operator/(const Vector2<T> & other) const;  	//! Divides this vector by a scalar and returns the result. -	Vector2 operator/(T scalar) const; +	Vector2<T> operator/(T scalar) const;  	//! Adds another vector to this vector and updates this vector. -	Vector2 & operator+=(const Vector2<T> & other); +	Vector2<T> & operator+=(const Vector2<T> & other);  	//! Adds a scalar value to both components of this vector and updates this vector. -	Vector2 & operator+=(T other); +	Vector2<T> & operator+=(T other);  	//! Subtracts another vector from this vector and updates this vector. -	Vector2 & operator-=(const Vector2<T> & other); +	Vector2<T> & operator-=(const Vector2<T> & other);  	//! Subtracts a scalar value from both components of this vector and updates this vector. -	Vector2 & operator-=(T other); +	Vector2<T> & operator-=(T other);  	//! Multiplies this vector by another vector element-wise and updates this vector. -	Vector2 & operator*=(const Vector2<T> & other); +	Vector2<T> & operator*=(const Vector2<T> & other);  	//! Multiplies this vector by a scalar and updates this vector. -	Vector2 & operator*=(T other); +	Vector2<T> & operator*=(T other);  	//! Divides this vector by another vector element-wise and updates this vector. -	Vector2 & operator/=(const Vector2<T> & other); +	Vector2<T> & operator/=(const Vector2<T> & other);  	//! Divides this vector by a scalar and updates this vector. -	Vector2 & operator/=(T other); +	Vector2<T> & operator/=(T other);  	//! Returns the negation of this vector. -	Vector2 operator-() const; +	Vector2<T> operator-() const;  	//! Checks if this vector is equal to another vector.  	bool operator==(const Vector2<T> & other) const; @@ -89,12 +91,20 @@ struct Vector2 {  	T distance_squared(const Vector2<T> & other) const;  	//! Returns the perpendicular vector to this vector. -	Vector2 perpendicular() const; +	Vector2<T> perpendicular() const;  	//! Checks if both components of the vector are NaN.  	bool is_nan() const; + +	//! Rotate this vector clockwise by \c deg degrees +	Vector2<T> rotate(float deg) const;  };  } // namespace crepe +template <typename T> +struct std::formatter<crepe::Vector2<T>> : std::formatter<std::string> { +	format_context::iterator format(crepe::Vector2<T> vec, format_context & ctx) const; +}; +  #include "Vector2.hpp" diff --git a/src/crepe/api/Vector2.hpp b/src/crepe/api/Vector2.hpp index e195760..30441d2 100644 --- a/src/crepe/api/Vector2.hpp +++ b/src/crepe/api/Vector2.hpp @@ -168,4 +168,19 @@ bool Vector2<T>::is_nan() const {  	return std::isnan(x) && std::isnan(y);  } +template <class T> +Vector2<T> Vector2<T>::rotate(float deg) const { +	float rad = -deg / 180 * M_PI; +	return { +		x * std::cos(rad) - y * std::sin(rad), +		x * std::sin(rad) + y * std::cos(rad), +	}; +} +  } // namespace crepe + +template <typename T> +std::format_context::iterator +std::formatter<crepe::Vector2<T>>::format(crepe::Vector2<T> vec, format_context & ctx) const { +	return formatter<string>::format(std::format("{{{}, {}}}", vec.x, vec.y), ctx); +} diff --git a/src/test/Vector2Test.cpp b/src/test/Vector2Test.cpp index 1e21af9..b17f95a 100644 --- a/src/test/Vector2Test.cpp +++ b/src/test/Vector2Test.cpp @@ -1,6 +1,7 @@  #include <gtest/gtest.h>  #include <crepe/api/Vector2.h> +#include <crepe/types.h>  using namespace crepe; @@ -530,3 +531,12 @@ TEST_F(Vector2Test, Perpendicular) {  	EXPECT_FLOAT_EQ(result4.x, -4.0f);  	EXPECT_FLOAT_EQ(result4.y, 3.0f);  } + +TEST_F(Vector2Test, Rotate) { +	vec2 foo {0, 1}; + +	foo = foo.rotate(90); +	const float GOOD_ENOUGH = 0.001; +	EXPECT_NEAR(foo.x, 1, GOOD_ENOUGH); +	EXPECT_NEAR(foo.y, 0, GOOD_ENOUGH); +} |