Browse Source

Saturday updat

POSITIVE-MENTAL-ATTITUDE 8 years ago
parent
commit
6e95f5d476
20 changed files with 589 additions and 84 deletions
  1. 1 1
      Bullet.cpp
  2. 1 1
      Foreground.cpp
  3. 1 1
      Foreground.hpp
  4. 2 2
      GuiTriangle.cpp
  5. 3 0
      IngameState.cpp
  6. 46 11
      Input.cpp
  7. 4 1
      Input.hpp
  8. 0 5
      InputMap.hpp
  9. 9 15
      InputTarget.hpp
  10. 62 6
      MenuState.cpp
  11. 1 0
      MenuState.hpp
  12. 108 0
      Particle.cpp
  13. 102 0
      Particle.hpp
  14. 163 32
      Player.cpp
  15. 5 0
      Player.hpp
  16. 8 5
      Triangles.cpp
  17. 1 1
      Triangles.hpp
  18. 17 2
      TrianglesWindow.cpp
  19. 3 1
      TrianglesWindow.hpp
  20. 52 0
      Utility.hpp

+ 1 - 1
Bullet.cpp

@@ -55,7 +55,7 @@ void Bullet::draw(sf::RenderTarget& target, sf::RenderStates states) const
     
     
 	target.draw(_vertex, 4, sf::Quads, states);
 	target.draw(_vertex, 4, sf::Quads, states);
 }
 }
-#include "iostream"
+
 void Bullet::destroyPixels(int& k, int x, int y)
 void Bullet::destroyPixels(int& k, int x, int y)
 {
 {
 	int plus = 1;
 	int plus = 1;

+ 1 - 1
Foreground.cpp

@@ -27,7 +27,7 @@ Foreground::~Foreground()
 	_tiles.clear();
 	_tiles.clear();
 }
 }
 
 
-sf::Vector2u Foreground::getSize()
+const sf::Vector2u Foreground::getSize() const
 {
 {
 	return {_tileCount.x * _tileSize, _tileCount.y * _tileSize};
 	return {_tileCount.x * _tileSize, _tileCount.y * _tileSize};
 }
 }

+ 1 - 1
Foreground.hpp

@@ -39,7 +39,7 @@ class Foreground: public sf::Drawable
 		void reloadFromTile(int x, int y, bool neighbouring = false);
 		void reloadFromTile(int x, int y, bool neighbouring = false);
 		void reloadFromPixel(int x, int y, bool neighbouring = false);
 		void reloadFromPixel(int x, int y, bool neighbouring = false);
 		bool destroy(unsigned x, unsigned y);
 		bool destroy(unsigned x, unsigned y);
-		sf::Vector2u getSize();
+		const sf::Vector2u getSize() const;
 		const unsigned getTileSize() const;
 		const unsigned getTileSize() const;
 		unsigned const tileAlpha(unsigned x, unsigned y, unsigned pixelX, unsigned pixelY);
 		unsigned const tileAlpha(unsigned x, unsigned y, unsigned pixelX, unsigned pixelY);
 
 

+ 2 - 2
GuiTriangle.cpp

@@ -23,10 +23,10 @@ GuiTriangle::GuiTriangle(): Triangle(), _scale(1.f)
 	/// A default empty lambda.
 	/// A default empty lambda.
 	bind([](){});
 	bind([](){});
 }
 }
-#include <iostream>
+
 bool GuiTriangle::mouseIntersection(sf::Vector2i mouseXY)
 bool GuiTriangle::mouseIntersection(sf::Vector2i mouseXY)
 {	
 {	
-	double degree = 3.14159265358 / 180.;
+	const double degree = 3.14159265358 / 180.;
 	sf::Vector2f A = sf::Vector2f(std::sin((0.f + getRotation()) * degree) * getSize() * getScale().x, -std::cos((0.f + getRotation()) * degree) * getSize() * getScale().x) + getPosition(); 
 	sf::Vector2f A = sf::Vector2f(std::sin((0.f + getRotation()) * degree) * getSize() * getScale().x, -std::cos((0.f + getRotation()) * degree) * getSize() * getScale().x) + getPosition(); 
 	sf::Vector2f B = sf::Vector2f(std::sin((165.f + getRotation()) * degree) * getSize() * getScale().x, -std::cos((165.f + getRotation()) * degree) * getSize() * getScale().x) + getPosition(); 
 	sf::Vector2f B = sf::Vector2f(std::sin((165.f + getRotation()) * degree) * getSize() * getScale().x, -std::cos((165.f + getRotation()) * degree) * getSize() * getScale().x) + getPosition(); 
 	sf::Vector2f C = sf::Vector2f(std::sin((195.f + getRotation()) * degree) * getSize() * getScale().x, -std::cos((195.f + getRotation()) * degree) * getSize() * getScale().x) + getPosition(); 
 	sf::Vector2f C = sf::Vector2f(std::sin((195.f + getRotation()) * degree) * getSize() * getScale().x, -std::cos((195.f + getRotation()) * degree) * getSize() * getScale().x) + getPosition(); 

+ 3 - 0
IngameState.cpp

@@ -126,6 +126,9 @@ void IngameState::coreUpdate(sf::Time delta)
 
 
 	if(_paused)
 	if(_paused)
 		return;
 		return;
+		
+	if(sf::Joystick::isConnected(0))
+		_context->window->lockMouse();
 
 
 	const sf::Vector2f pos = _player.getPosition();
 	const sf::Vector2f pos = _player.getPosition();
 	_player.update(delta);
 	_player.update(delta);

+ 46 - 11
Input.cpp

@@ -1,6 +1,6 @@
 #include "Input.hpp"
 #include "Input.hpp"
 
 
-Input::Input(const Input& other): _type(other._type)
+Input::Input(const Input& other): _type(other._type), _positive(other._positive)
 {
 {
 	std::memcpy(&_event, &other._event, sizeof(sf::Event));
 	std::memcpy(&_event, &other._event, sizeof(sf::Event));
 }
 }
@@ -10,53 +10,88 @@ Input& Input::operator=(const Input& other)
 	_type = other._type;
 	_type = other._type;
 	return *this;
 	return *this;
 }
 }
-Input::Input(const sf::Keyboard::Key& key, int type): _type(type)
+Input::Input(const sf::Keyboard::Key& key, int type): _type(type), _positive(true)
 {
 {
 	_event.type = sf::Event::EventType::KeyPressed;
 	_event.type = sf::Event::EventType::KeyPressed;
 	_event.key.code = key;
 	_event.key.code = key;
 }
 }
-Input::Input(const sf::Mouse::Button& button, int type): _type(type)
+Input::Input(const sf::Mouse::Button& button, int type): _type(type), _positive(true)
 {
 {
 	_event.type = sf::Event::EventType::MouseButtonPressed;
 	_event.type = sf::Event::EventType::MouseButtonPressed;
 	_event.mouseButton.button = button;
 	_event.mouseButton.button = button;
 }
 }
-bool Input::test() const
+
+Input::Input(const int joystickButton, int type): _type(type), _positive(true)
+{
+	_event.type = sf::Event::EventType::JoystickButtonPressed;
+	_event.joystickButton.button = joystickButton;
+}
+
+Input::Input(const sf::Joystick::Axis& axis, bool positive): _type(Type::RealTime|Type::Pressed), _positive(positive)
+{
+	_event.type = sf::Event::EventType::JoystickMoved;
+	_event.joystickMove.joystickId = 0;
+	_event.joystickMove.axis = axis;
+}
+
+float Input::test() const
 {
 {
 	switch(_event.type)
 	switch(_event.type)
 	{
 	{
 		case sf::Event::EventType::KeyPressed:
 		case sf::Event::EventType::KeyPressed:
 			if(_type & Type::Pressed)
 			if(_type & Type::Pressed)
-				return sf::Keyboard::isKeyPressed(_event.key.code);
+				return sf::Keyboard::isKeyPressed(_event.key.code) ? 1.f : 0.f;
 			break;
 			break;
 		case sf::Event::EventType::MouseButtonPressed:
 		case sf::Event::EventType::MouseButtonPressed:
 			if(_type & Type::Pressed)
 			if(_type & Type::Pressed)
-				return sf::Mouse::isButtonPressed(_event.mouseButton.button);
+				return sf::Mouse::isButtonPressed(_event.mouseButton.button) ? 1.f : 0.f;
+			break;
+		case sf::Event::EventType::JoystickButtonPressed:
+			if(_type & Type::Pressed)
+				return sf::Joystick::isButtonPressed(0, _event.joystickButton.button) ? 1.f : 0.f;
+			break;
+		case sf::Event::EventType::JoystickMoved:
+			if(_type & Type::Pressed)
+			{
+				float f = sf::Joystick::getAxisPosition(_event.joystickMove.joystickId, _event.joystickMove.axis) / 100.f;
+				if(!_positive)
+					f = -f;
+				return f > 0.f ? f : 0.f;
+			}
 			break;
 			break;
 		default:
 		default:
 			break;
 			break;
 	}
 	}
-	return false;
+	return 0.f;
 }
 }
 bool Input::operator==(const sf::Event& event) const
 bool Input::operator==(const sf::Event& event) const
 {
 {
 	switch(event.type)
 	switch(event.type)
 	{
 	{
 		case sf::Event::EventType::KeyPressed:
 		case sf::Event::EventType::KeyPressed:
-			if(_type & Type::Pressed and _event.type == sf::Event::EventType::KeyPressed)
+			if(_type & Type::Pressed && _event.type == sf::Event::EventType::KeyPressed)
 				return event.key.code == _event.key.code;
 				return event.key.code == _event.key.code;
 			break;
 			break;
 		case sf::Event::EventType::KeyReleased:
 		case sf::Event::EventType::KeyReleased:
-			if(_type & Type::Released and _event.type == sf::Event::EventType::KeyPressed)
+			if(_type & Type::Released && _event.type == sf::Event::EventType::KeyPressed)
 				return event.key.code == _event.key.code;
 				return event.key.code == _event.key.code;
 			break;
 			break;
 		case sf::Event::EventType::MouseButtonPressed:
 		case sf::Event::EventType::MouseButtonPressed:
-			if(_type & Type::Pressed and _event.type == sf::Event::EventType::MouseButtonPressed)
+			if(_type & Type::Pressed && _event.type == sf::Event::EventType::MouseButtonPressed)
 				return event.mouseButton.button == _event.mouseButton.button;
 				return event.mouseButton.button == _event.mouseButton.button;
 			break;
 			break;
 		case sf::Event::EventType::MouseButtonReleased:
 		case sf::Event::EventType::MouseButtonReleased:
-			if(_type & Type::Released and _event.type == sf::Event::EventType::MouseButtonPressed)
+			if(_type & Type::Released && _event.type == sf::Event::EventType::MouseButtonPressed)
 				return event.mouseButton.button == _event.mouseButton.button;
 				return event.mouseButton.button == _event.mouseButton.button;
 			break;
 			break;
+		case sf::Event::EventType::JoystickButtonPressed:
+			if(_type & Type::Pressed && _event.type == sf::Event::EventType::JoystickButtonPressed)
+				return event.joystickButton.button == _event.joystickButton.button;
+			break;
+		case sf::Event::EventType::JoystickMoved:
+			if(_type & Type::Pressed && _event.type == sf::Event::EventType::JoystickMoved)
+				return event.joystickMove.position == _event.joystickMove.position;
+			break;
 		default: 
 		default: 
 			break;
 			break;
 	}
 	}

+ 4 - 1
Input.hpp

@@ -17,8 +17,10 @@ class Input
 		Input& operator=(const Input& other);
 		Input& operator=(const Input& other);
 		Input(const sf::Keyboard::Key& key, int type=Type::RealTime|Type::Pressed);
 		Input(const sf::Keyboard::Key& key, int type=Type::RealTime|Type::Pressed);
 		Input(const sf::Mouse::Button& button, int type=Type::RealTime|Type::Pressed);
 		Input(const sf::Mouse::Button& button, int type=Type::RealTime|Type::Pressed);
+		Input(const int joystickButton, int type=Type::RealTime|Type::Pressed);
+		Input(const sf::Joystick::Axis& axis, bool positive);
 		
 		
-		bool test() const;
+		float test() const;
 		
 		
 		bool operator==(const sf::Event& event) const;
 		bool operator==(const sf::Event& event) const;
 		bool operator==(const Input& other) const;
 		bool operator==(const Input& other) const;
@@ -26,5 +28,6 @@ class Input
 		template<typename> friend class InputTarget;
 		template<typename> friend class InputTarget;
 		sf::Event _event;
 		sf::Event _event;
 		int _type;
 		int _type;
+		bool _positive;
 };
 };
 
 

+ 0 - 5
InputMap.hpp

@@ -17,11 +17,6 @@ class InputMap
 		{
 		{
 			_map.emplace(key, input);
 			_map.emplace(key, input);
 		}
 		}
-		void duoMap(const T& key, const Input& input1, const Input& input2)
-		{
-			_map.emplace(key, input1);
-			_map.emplace(-key, input2);
-		}
 		const Input& get(const T& key) const
 		const Input& get(const T& key) const
 		{
 		{
 			return _map.at(key);
 			return _map.at(key);

+ 9 - 15
InputTarget.hpp

@@ -4,12 +4,11 @@
 #include <functional>
 #include <functional>
 #include <SFML/Window.hpp>
 #include <SFML/Window.hpp>
 #include "InputMap.hpp"
 #include "InputMap.hpp"
-
+#include <iostream>
 template<typename T = int>
 template<typename T = int>
 class InputTarget
 class InputTarget
 {
 {
 	public:
 	public:
-		using Func = std::function<void(const sf::Event&)>;
 		InputTarget(const InputTarget<T>&) = delete;
 		InputTarget(const InputTarget<T>&) = delete;
 		InputTarget<T>& operator=(const InputTarget<T>&) = delete;
 		InputTarget<T>& operator=(const InputTarget<T>&) = delete;
 		
 		
@@ -21,7 +20,7 @@ class InputTarget
 			{
 			{
 				if(_inputMap.get(pair.first) == event)
 				if(_inputMap.get(pair.first) == event)
 				{
 				{
-					pair.second(event);
+					pair.second(event, 1.f);
 					return true;
 					return true;
 				}
 				}
 			}
 			}
@@ -32,12 +31,13 @@ class InputTarget
 			for(auto& pair: _eventsRealTime)
 			for(auto& pair: _eventsRealTime)
 			{
 			{
 				const Input& input = _inputMap.get(pair.first);
 				const Input& input = _inputMap.get(pair.first);
-				if(input.test())
-					pair.second(input._event);
+				float power = input.test();
+				if(power != 0.f)
+					pair.second(input._event, power);
 			}
 			}
 		}
 		}
 		
 		
-		void bind(const T& key, const Func& callback)
+		void bind(const T& key, const std::function<void(const sf::Event&, float)>& callback)
 		{
 		{
 			const Input& input = _inputMap.get(key);
 			const Input& input = _inputMap.get(key);
 			if(input._type & Input::Type::RealTime)
 			if(input._type & Input::Type::RealTime)
@@ -46,15 +46,9 @@ class InputTarget
 				_eventsPoll.emplace_back(key, callback);
 				_eventsPoll.emplace_back(key, callback);
 		}
 		}
 
 
-		void duoBind(const T& key, const Func& callback)
-		{
-			bind(key, callback);
-			bind(-key, callback);
-		}
-
 		void unbind(const T& key)
 		void unbind(const T& key)
 		{
 		{
-			auto remove_func = [&key](const std::pair<T,Func>& pair) -> bool
+			auto remove_func = [&key](const std::pair<T, std::function<void(const sf::Event&, float)>>& pair) -> bool
 			{
 			{
 				return pair.first == key;
 				return pair.first == key;
 			};
 			};
@@ -66,8 +60,8 @@ class InputTarget
 		}
 		}
 	
 	
 	private:
 	private:
-		std::list<std::pair<T, Func>> _eventsRealTime;
-		std::list<std::pair<T, Func>> _eventsPoll;
+		std::list<std::pair<T, std::function<void(const sf::Event&, float power)>>> _eventsRealTime;
+		std::list<std::pair<T, std::function<void(const sf::Event&, float power)>>> _eventsPoll;
 		
 		
 		const InputMap<T>& _inputMap;
 		const InputMap<T>& _inputMap;
 };
 };

+ 62 - 6
MenuState.cpp

@@ -20,11 +20,9 @@
 #include <sstream>
 #include <sstream>
 #include "MenuState.hpp"
 #include "MenuState.hpp"
 #include "Triangles.hpp"
 #include "Triangles.hpp"
+#include "Utility.hpp"
 
 
-MenuState::MenuState()
-{
-	
-}
+MenuState::MenuState(): State(), _padSelection(0) {}
 
 
 void MenuState::init()
 void MenuState::init()
 {
 {
@@ -151,7 +149,7 @@ void MenuState::refresh()
 
 
 void MenuState::coreThink(const sf::Event& event)
 void MenuState::coreThink(const sf::Event& event)
 {
 {
-	if(event.type == sf::Event::MouseButtonPressed and event.mouseButton.button == sf::Mouse::Left)
+	if(event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Left)
 	{
 	{
 		sf::Vector2i xy = _context->window->getMousePosition();
 		sf::Vector2i xy = _context->window->getMousePosition();
 		switch(_subStatus)
 		switch(_subStatus)
@@ -171,8 +169,44 @@ void MenuState::coreThink(const sf::Event& event)
 		
 		
 		_quit.click(xy);
 		_quit.click(xy);
 	}
 	}
-	if(event.type == sf::Event::Closed or (event.type == sf::Event::KeyPressed and event.key.code == sf::Keyboard::Escape))
+	
+	if(event.type == sf::Event::Closed || (event.type == sf::Event::KeyPressed and event.key.code == sf::Keyboard::Escape))
 		_context->running = false;
 		_context->running = false;
+	if(event.type == sf::Event::JoystickMoved && event.joystickMove.axis == sf::Joystick::Axis::PovX)
+	{
+		if(event.joystickMove.position == -100)
+			switch(_padSelection)
+			{
+				case 1: _padSelection = 2; break;
+				default: break;
+			}
+		if(event.joystickMove.position == 100)
+			switch(_padSelection)
+			{
+				case 0: _padSelection = 1; break;
+				case 2: _padSelection = 1; break; 
+				default: break;
+			}
+	}
+	if(event.type == sf::Event::JoystickMoved && event.joystickMove.axis == sf::Joystick::Axis::PovY)
+	{
+		if(event.joystickMove.position == -100)
+			switch(_padSelection)
+			{
+				case 1: _padSelection = 0; break;
+				case 2: _padSelection = 0; break;
+				case 3: _padSelection = 1; break;
+				default: break;
+			}
+		if(event.joystickMove.position == 100)
+			switch(_padSelection)
+			{
+				case 0: _padSelection = 2; break;
+				case 1: _padSelection = 3; break;
+				case 2: _padSelection = 3; break;
+				default: break;
+			}
+	}
 }
 }
 void MenuState::coreInput()
 void MenuState::coreInput()
 {
 {
@@ -261,6 +295,28 @@ void MenuState::coreUpdate(sf::Time delta)
 	static sf::Clock clock;
 	static sf::Clock clock;
 	_waterSine.setParameter("time", clock.getElapsedTime().asSeconds());
 	_waterSine.setParameter("time", clock.getElapsedTime().asSeconds());
 	
 	
+	if(sf::Joystick::isConnected(0))
+	{
+		sf::Vector2f v;
+		switch(_padSelection)
+		{
+			case 0:
+				v = _logo.getPosition();
+				break;
+			case 1:
+				v = _play.getPosition();
+				break;
+			case 2:
+				v = _settings.getPosition();
+				break;
+			case 3:
+				v = _quit.getPosition();
+				break;
+				
+		}
+		_context->window->lockMouse(sf::Vector2i(v));
+	}
+	
 	_logo.update(_context->window->getMousePosition(), delta);
 	_logo.update(_context->window->getMousePosition(), delta);
 	_play.update(_context->window->getMousePosition(), delta);
 	_play.update(_context->window->getMousePosition(), delta);
 	_settings.update(_context->window->getMousePosition(), delta);
 	_settings.update(_context->window->getMousePosition(), delta);

+ 1 - 0
MenuState.hpp

@@ -53,4 +53,5 @@ class MenuState: public State
 		sf::Shader _waterFrag;
 		sf::Shader _waterFrag;
 		sf::Music _music;
 		sf::Music _music;
 		sf::Color _color;
 		sf::Color _color;
+		int _padSelection;
 };
 };

+ 108 - 0
Particle.cpp

@@ -0,0 +1,108 @@
+/**
+ *  Triangles
+ *  Copyright (C) 2016 POSITIVE MENTAL ATTITUDE
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+ 
+ /**
+  * This is based on a wiki entry
+  * https://github.com/SFML/SFML/wiki/Source:-Particle-System
+  */
+
+#include <sstream>
+#include "Particle.hpp"
+
+ParticleSystem::ParticleSystem( int width, int height )
+{
+	_transparent = sf::Color( 0, 0, 0, 0 );
+	_image.create( width, height, _transparent );
+	_texture.loadFromImage(_image);
+	_sprite = sf::Sprite(_texture);
+	_position.x	= 0.5f * width;
+	_position.y	= 0.5f * height;
+	_particleSpeed = 20.0f;
+	_dissolutionRate = 60.f;
+}
+
+ParticleSystem::~ParticleSystem()
+{
+	for(auto it = _particles.begin(); it != _particles.end(); it++)
+	{
+		delete *it;
+	}
+}
+
+void ParticleSystem::fuel(int particles, float angle)
+{
+	Particle* particle;
+	const double degree = 3.14159265358 / 180.;
+	for(int i = 0; i < particles; i++)
+	{
+		particle = new Particle();
+		particle->pos.x = _position.x;
+		particle->pos.y = _position.y;
+	
+		do
+		{
+			particle->vel.x = _randomizer.rnd(0.0f, 15.0f) * -std::sin(angle * degree);
+			particle->vel.y = _randomizer.rnd(0.0f, 15.0f) * std::cos(angle * degree);
+		} while(particle->vel.x == 0.0f && particle->vel.y == 0.0f);
+
+		particle->color.r = std::rand() % 100 + 150;
+		particle->color.g = std::rand() % 50 + 150;
+        particle->color.b = std::rand() % 50;
+		particle->transparency = 255.f;
+		particle->color.a = sf::Uint8(particle->transparency);
+		_particles.push_back(particle);
+	}
+}
+#include "iostream"
+void ParticleSystem::update(sf::Time delta)
+{
+	float time = delta.asSeconds();
+
+	for(auto it = _particles.begin(); it != _particles.end(); it++ )
+	{
+        (*it)->pos.x += (*it)->vel.x * time * _particleSpeed;
+	    (*it)->pos.y += (*it)->vel.y * time * _particleSpeed;
+
+		(*it)->transparency -= (_dissolutionRate * time);
+		(*it)->color.a = sf::Uint8((*it)->transparency);
+
+		if((*it)->pos.x > _image.getSize().x || (*it)->pos.x < 0 || (*it)->pos.y > _image.getSize().y || (*it)->pos.y < 0 || (*it)->color.a < 10)
+		{
+            delete (*it);
+		    it = _particles.erase(it);
+		    if(it == _particles.end()) 
+				return;
+        }
+	}
+}
+
+void ParticleSystem::render()
+{
+	for(auto it = _particles.begin(); it != _particles.end(); it++ )
+	{
+  	  _image.setPixel( (int)(*it)->pos.x, (int)(*it)->pos.y, (*it)->color );
+	}
+    _texture.update(_image);
+}
+
+void ParticleSystem::clear()
+{
+	for(auto it = _particles.begin(); it != _particles.end(); it++ )
+	{
+	    _image.setPixel( (int)(*it)->pos.x, (int)(*it)->pos.y, _transparent );
+	}
+}

+ 102 - 0
Particle.hpp

@@ -0,0 +1,102 @@
+/**
+ *  Triangles
+ *  Copyright (C) 2016 POSITIVE MENTAL ATTITUDE
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, version 3 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+ 
+ /**
+  * This is based on a wiki entry
+  * https://github.com/SFML/SFML/wiki/Source:-Particle-System
+  */
+
+#pragma once
+
+#include <SFML/System/Vector2.hpp>
+#include <SFML/System/Clock.hpp>
+#include <SFML/Graphics/Color.hpp>
+#include <SFML/Graphics/Image.hpp>
+#include <SFML/Graphics/Sprite.hpp>
+#include <SFML/Graphics/Texture.hpp>
+#include <vector>
+#include <random>
+
+class Randomizer 
+{
+    public:
+        Randomizer() : device_(), engine_(device_()){};
+        int rnd(int a, int b) {
+            std::uniform_int_distribution<int> uni_dist(a, b);
+            return uni_dist(engine_);
+        };
+        double rnd(double a, double b) {
+            std::uniform_real_distribution<double> uni_dist(a, b);
+            return uni_dist(engine_);
+        };
+    private:
+        std::random_device device_;
+        std::default_random_engine engine_;
+};
+
+struct Particle
+{
+    sf::Vector2f pos;
+    sf::Vector2f vel;
+    sf::Color color;
+	float transparency;
+};
+
+class ParticleSystem
+{
+	public:
+		ParticleSystem( int width, int height );
+		~ParticleSystem();
+
+		void fuel(int particles, float angle);
+		void update(sf::Time delta);
+		void render();
+		void clear();
+
+		void setPosition(const sf::Vector2f position) 
+		{ 
+			_position = position;
+		}
+		void setPosition(float x, float y) 
+		{ 
+			setPosition(sf::Vector2f(x, y));
+		}
+		void setParticleSpeed(float particleSpeed) 
+		{ 
+			_particleSpeed = particleSpeed; 
+		}
+		void setDissolutionRate(float dissolutionRate) 
+		{ 
+			_dissolutionRate = dissolutionRate; 
+		}
+		const sf::Sprite& getSprite() const
+		{ 
+			return _sprite; 
+		}
+
+	private:
+		sf::Vector2f			_position; // Particle origin (pixel co-ordinates)
+		sf::Clock   			_clock;    // Used to scale particle motion
+		sf::Color   			_transparent;  // sf::Color( 0, 0, 0, 0 )
+		sf::Image   			_image;    // See render() and remove()
+		sf::Texture 			_texture;
+		Randomizer  			_randomizer;
+		sf::Sprite  			_sprite;   // Connected to m_image
+		float       			_particleSpeed;// Pixels per second (at most)
+		float	 				_dissolutionRate;
+		std::vector<Particle*>	_particles;
+};

+ 163 - 32
Player.cpp

@@ -24,47 +24,59 @@ Player::Player():
 	InputTarget(_inputMap), 
 	InputTarget(_inputMap), 
 	Collidable(),
 	Collidable(),
 	_movement(0.f), 
 	_movement(0.f), 
-	_movementSpeed(4.f), 
+	_movementSpeed(2.f), 
 	_movementMomentum(0.f),
 	_movementMomentum(0.f),
 	_movementAcceleration(10.f),
 	_movementAcceleration(10.f),
-	_movementSuppresion(5.f),
+	_movementSuppresion(10.f),
 	_rotation(0.f), 
 	_rotation(0.f), 
 	_rotationSpeed(0.6f), 
 	_rotationSpeed(0.6f), 
 	_rotationMomentum(0.f),
 	_rotationMomentum(0.f),
 	_rotationAcceleration(38.f),
 	_rotationAcceleration(38.f),
 	_rotationSuppresion(20.f),
 	_rotationSuppresion(20.f),
 	_hit(false),
 	_hit(false),
-	_dead(false)
+	_dead(false),
+	_particleSystem(1920, 1080)
 {
 {
 	/**
 	/**
-	 * Default binding
+	 *  Default binding
 	 */
 	 */
-	_inputMap.duoMap(1, Input(sf::Keyboard::Up), Input(sf::Keyboard::W));
-	_inputMap.duoMap(2, Input(sf::Keyboard::Down), Input(sf::Keyboard::S));
-	_inputMap.duoMap(3, Input(sf::Keyboard::Left), Input(sf::Keyboard::A));
-	_inputMap.duoMap(4, Input(sf::Keyboard::Right), Input(sf::Keyboard::D));
-	_inputMap.map(5, Input(sf::Keyboard::Space));
+	 if(sf::Joystick::isConnected(0))
+	 {
+		_inputMap.map(1, Input(sf::Joystick::Axis::Y, false));
+		_inputMap.map(2, Input(sf::Joystick::Axis::Y, true));
+		_inputMap.map(3, Input(sf::Joystick::Axis::Z, false));
+		_inputMap.map(4, Input(sf::Joystick::Axis::Z, true));
+		_inputMap.map(5, Input(7));
+	 }
+	 else
+	 {
+		_inputMap.map(1, Input(sf::Keyboard::W));
+		_inputMap.map(2, Input(sf::Keyboard::S));
+		_inputMap.map(3, Input(sf::Keyboard::A));
+		_inputMap.map(4, Input(sf::Keyboard::D));
+		_inputMap.map(5, Input(sf::Keyboard::Space));
+	 }
 	
 	
 	/**
 	/**
-	 * Input lambdas
+	 *  Input lambdas
 	 */
 	 */
-	duoBind(1, [this](const sf::Event&)
+	bind(1, [this](const sf::Event&, float power)
 	{
 	{
-		_movement += 1.f;
-	});
-	duoBind(2, [this](const sf::Event&)
+		_movement += power;
+	}); 
+	bind(2, [this](const sf::Event&, float power)
 	{
 	{
-		_movement -= 0.8f;
+		_movement -= power * 0.8f;
 	});
 	});
-	duoBind(3, [this](const sf::Event&)
+	bind(3, [this](const sf::Event&, float power)
 	{
 	{
-		_rotation -= 1.f;
+		_rotation -= power;
 	});
 	});
-	duoBind(4, [this](const sf::Event&)
+	bind(4, [this](const sf::Event&, float power)
 	{
 	{
-		_rotation += 1.f;
+		_rotation += power;
 	});
 	});
-	bind(5, [this](const sf::Event&)
+	bind(5, [this](const sf::Event&, float)
 	{
 	{
 		if(_bulletTimer.getElapsedTime().asMilliseconds() > 1500)
 		if(_bulletTimer.getElapsedTime().asMilliseconds() > 1500)
 		{
 		{
@@ -81,14 +93,20 @@ Player::Player():
 	});
 	});
 	
 	
 	/**
 	/**
-	 * Technical
+	*  Particles
+	*/
+
+    _particleSystem.setDissolutionRate(255.f);
+
+	/**
+	 *  Technical
 	 */
 	 */
 	
 	
 	genCollisionBox("data/hitbox/Player.png", sf::Vector2f(71.f, 100.f));
 	genCollisionBox("data/hitbox/Player.png", sf::Vector2f(71.f, 100.f));
 	
 	
 	_bullets.reserve(10);
 	_bullets.reserve(10);
 	_bulletTimer.restart();
 	_bulletTimer.restart();
-	
+	 
 	_durability = 0.99f; 
 	_durability = 0.99f; 
 }
 }
 
 
@@ -175,7 +193,7 @@ bool Player::checkCollision(Foreground& foreground)
 		return false;
 		return false;
 }
 }
 
 
-void Player::update(sf::Time delta)
+void Player::keyboardControls(sf::Time delta)
 {
 {
 	float seconds = delta.asSeconds();
 	float seconds = delta.asSeconds();
 	const double degree = 3.14159265358 / 180.;
 	const double degree = 3.14159265358 / 180.;
@@ -191,18 +209,24 @@ void Player::update(sf::Time delta)
 
 
 	_movementMomentum += _movementAcceleration * seconds * _movement;
 	_movementMomentum += _movementAcceleration * seconds * _movement;
 
 
-	if(_movementMomentum > _movementSuppresion * seconds)
-		_movementMomentum -= _movementSuppresion * seconds;
-	else if(_movementMomentum < -_movementSuppresion * seconds)
-		_movementMomentum += _movementSuppresion * seconds;
-	else
-		_movementMomentum = 0.f;
+	if(_movement == 0.f)
+	{
+		if(_movementMomentum > _movementSuppresion * seconds)
+			_movementMomentum -= _movementSuppresion * seconds;
+		else if(_movementMomentum < -_movementSuppresion * seconds)
+			_movementMomentum += _movementSuppresion * seconds;
+		else
+			_movementMomentum = 0.f;
+	}
 
 
 	sf::Vector2f movement;
 	sf::Vector2f movement;
 	movement.x = std::sin(getRotation() * degree) * 60.f * _movementSpeed * _movementMomentum * seconds;
 	movement.x = std::sin(getRotation() * degree) * 60.f * _movementSpeed * _movementMomentum * seconds;
 	movement.y = -std::cos(getRotation() * degree) * 60.f * _movementSpeed * _movementMomentum * seconds;
 	movement.y = -std::cos(getRotation() * degree) * 60.f * _movementSpeed * _movementMomentum * seconds;
+	
 	move(movement);
 	move(movement);
-	//px.move(movement);
+
+	_particleSystem.fuel(movement.x * 20.f, getRotation());
+	_particleSystem.fuel(movement.y * 20.f, getRotation());
 
 
 	_movement = 0.f;
 	_movement = 0.f;
 
 
@@ -217,9 +241,108 @@ void Player::update(sf::Time delta)
 
 
 	float rotation = 90.f * _rotationSpeed * _rotationMomentum * seconds;
 	float rotation = 90.f * _rotationSpeed * _rotationMomentum * seconds;
 	rotate(rotation);
 	rotate(rotation);
-	//px.rotate(rotation);
 
 
 	_rotation = 0.f;
 	_rotation = 0.f;
+}
+
+void Player::padControls(sf::Time delta)
+{
+	float seconds = delta.asSeconds();
+	const double degree = 3.14159265358 / 180.;
+	
+	sf::Vector2f v = sf::Vector2f(
+	sf::Joystick::getAxisPosition(0, sf::Joystick::Axis::X) / 100.f, 
+	sf::Joystick::getAxisPosition(0, sf::Joystick::Axis::Y) / 100.f);
+	
+	float curr = getRotation();
+	static float supposed;
+	if(v.x != 0 or v.y != 0)
+		supposed = atan2(v.x, -v.y) / degree;
+
+	if(supposed < 0.f) 
+		supposed += 360.f;
+
+	float c = supposed - curr;
+	if(curr > 180.f && supposed < 180.f)
+	{
+		float a = (supposed - curr);
+		float b = (supposed - curr + 360.f);
+		if(std::fabs(a) < std::fabs(b))
+			c = a;
+		else
+			c = b;
+	}
+	if(curr < 180.f && supposed > 180.f)
+	{
+		float a = (supposed - curr);
+		float b = (supposed - curr - 360.f);
+		if(std::fabs(a) < std::fabs(b))
+			c = a;
+		else
+			c = b;
+	}
+	
+	if(v.x != 0 or v.y != 0) 
+	{
+		if(c > 0.f)
+			_rotationMomentum += _rotationAcceleration * seconds;
+		else if(c < 0.f)
+			_rotationMomentum -= _rotationAcceleration * seconds; 
+	}
+		
+	if(_rotationMomentum > _rotationSuppresion * seconds)
+		_rotationMomentum -= _rotationSuppresion * seconds;
+	else if(_rotationMomentum < -_rotationSuppresion * seconds)
+		_rotationMomentum += _rotationSuppresion * seconds;
+	else
+		_rotationMomentum = 0.f;
+		
+	float rotation = 90.f * _rotationSpeed * _rotationMomentum * seconds;
+	
+	rotate(rotation);
+	
+	if((v.x != 0 || v.y != 0) && c < 1.f)
+		_movement = std::fabs(v.x + v.y);
+	
+	if(_hit)
+	{
+		if(_movement > 0 || _movementMomentum > 0)
+			_movementMomentum -= seconds * 15.f;
+		if(_movement < 0 || _movementMomentum < 0)
+			_movementMomentum += seconds * 15.f;
+		_movement *= 0.6f;
+	}
+
+	_movementMomentum += _movementAcceleration * seconds * _movement;
+
+	if(_movement == 0.f)
+	{
+		if(_movementMomentum > _movementSuppresion * seconds)
+			_movementMomentum -= _movementSuppresion * seconds;
+		else if(_movementMomentum < -_movementSuppresion * seconds)
+			_movementMomentum += _movementSuppresion * seconds;
+		else
+			_movementMomentum = 0.f;
+	}
+
+	sf::Vector2f movement;
+	movement.x = std::sin(getRotation() * degree) * 60.f * _movementSpeed * _movementMomentum * seconds;
+	movement.y = -std::cos(getRotation() * degree) * 60.f * _movementSpeed * _movementMomentum * seconds;
+	
+	move(movement);
+	
+	_particleSystem.fuel(movement.x * 20.f, getRotation());
+	_particleSystem.fuel(movement.y * 20.f, getRotation());
+
+	_movement = 0.f;
+}
+
+void Player::update(sf::Time delta)
+{	
+	//if(sf::Joystick::isConnected(0))
+		//padControls(delta);
+	//else
+		keyboardControls(delta);
 	
 	
 	for(unsigned i = 0; i < _bullets.size(); ++i)
 	for(unsigned i = 0; i < _bullets.size(); ++i)
 	{
 	{
@@ -227,10 +350,18 @@ void Player::update(sf::Time delta)
 		if(_bullets[i].isDead())
 		if(_bullets[i].isDead())
 			_bullets.erase(_bullets.begin() + i);
 			_bullets.erase(_bullets.begin() + i);
 	}
 	}
+
+	_particleSystem.setPosition(getPosition());
+
+	_particleSystem.clear();
+    _particleSystem.update(delta);
+    _particleSystem.render();
 }
 }
 
 
 void Player::draw(sf::RenderTarget& target, sf::RenderStates states) const
 void Player::draw(sf::RenderTarget& target, sf::RenderStates states) const
-{
+{	
+	target.draw(_particleSystem.getSprite());
+	
 	for(unsigned i = 0; i < _bullets.size(); ++i)
 	for(unsigned i = 0; i < _bullets.size(); ++i)
 		target.draw(_bullets[i]);
 		target.draw(_bullets[i]);
 		
 		

+ 5 - 0
Player.hpp

@@ -24,6 +24,7 @@
 #include "Bullet.hpp"
 #include "Bullet.hpp"
 #include "Collidable.hpp"
 #include "Collidable.hpp"
 #include "Context.hpp"
 #include "Context.hpp"
+#include "Particle.hpp"
 
 
 /**
 /**
  * @class Player
  * @class Player
@@ -51,7 +52,10 @@ class Player: public Triangle, public InputTarget<int>, public Collidable
 		sf::Image _image;
 		sf::Image _image;
 		sf::Texture _innerTexture;
 		sf::Texture _innerTexture;
 		void setContext(Context* context);
 		void setContext(Context* context);
+
 	private:
 	private:
+		void keyboardControls(sf::Time delta);
+		void padControls(sf::Time delta);
 		Context* _context;
 		Context* _context;
 		std::vector<Bullet> _bullets;
 		std::vector<Bullet> _bullets;
 		sf::Clock _bulletTimer;
 		sf::Clock _bulletTimer;
@@ -65,4 +69,5 @@ class Player: public Triangle, public InputTarget<int>, public Collidable
 		virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const final override;
 		virtual void draw(sf::RenderTarget& target, sf::RenderStates states) const final override;
 		sf::Sound _glass;
 		sf::Sound _glass;
 		sf::Sound _deathSound;
 		sf::Sound _deathSound;
+		ParticleSystem _particleSystem;
 };
 };

+ 8 - 5
Triangles.cpp

@@ -228,14 +228,15 @@ void Triangles::load(int stateType)
 	
 	
 	_current->setContext(&_context);
 	_current->setContext(&_context);
 	
 	
-	_window.setActive(false); // Weird behaviour without this.
-	_window.lockFramerate(true);
-	
 	_loadingHint.setString(_loadingHints[rand() % _loadingHints.size()]);
 	_loadingHint.setString(_loadingHints[rand() % _loadingHints.size()]);
 	_loadingHint.setPosition(_window.getSize().x / 2.f - _loadingHint.getLocalBounds().width / 2.f, _window.getSize().y - 60.f);
 	_loadingHint.setPosition(_window.getSize().x / 2.f - _loadingHint.getLocalBounds().width / 2.f, _window.getSize().y - 60.f);
+	
+	_window.lockFramerate(true);
+	_window.setActive(false);
 
 
 	std::thread t1(&Triangles::loadingRender, this);
 	std::thread t1(&Triangles::loadingRender, this);
 	std::thread t2(&State::init, _current);
 	std::thread t2(&State::init, _current);
+	
 	t1.join();
 	t1.join();
 	t2.join();
 	t2.join();
 	
 	
@@ -279,12 +280,14 @@ int Triangles::run(unsigned count)
 		coreThink();
 		coreThink();
 		coreInput();
 		coreInput();
 		delta = clock.restart();
 		delta = clock.restart();
-		coreFPScalc(delta);
+		fpsCalc(delta);
+
 		while(delta > epsilon)
 		while(delta > epsilon)
 		{
 		{
 			delta -= epsilon;
 			delta -= epsilon;
 			coreUpdate(epsilon);
 			coreUpdate(epsilon);
 		}
 		}
+
 		coreUpdate(delta);
 		coreUpdate(delta);
 		coreRender();
 		coreRender();
 	}
 	}
@@ -313,7 +316,7 @@ void Triangles::coreInput()
 	_window.think();
 	_window.think();
 }
 }
 
 
-void Triangles::coreFPScalc(sf::Time delta)
+void Triangles::fpsCalc(sf::Time delta)
 {
 {
 	static sf::Clock clock;
 	static sf::Clock clock;
 	static float avg = 0.f, avgL = 0.f;
 	static float avg = 0.f, avgL = 0.f;

+ 1 - 1
Triangles.hpp

@@ -66,7 +66,7 @@ class Triangles
 		 * @brief Handles the top-left fps counter, if it is enabled.
 		 * @brief Handles the top-left fps counter, if it is enabled.
 		 * @param delta Delta time since last update.
 		 * @param delta Delta time since last update.
 		 */
 		 */
-		void coreFPScalc(sf::Time delta);
+		void fpsCalc(sf::Time delta);
 		/**
 		/**
 		 * @brief Game logic
 		 * @brief Game logic
 		 * @param delta Delta time since last update.
 		 * @param delta Delta time since last update.

+ 17 - 2
TrianglesWindow.cpp

@@ -21,11 +21,12 @@
 TrianglesWindow::TrianglesWindow(const std::string& title, sf::Vector2u size):
 TrianglesWindow::TrianglesWindow(const std::string& title, sf::Vector2u size):
 	InputTarget(_inputMap),
 	InputTarget(_inputMap),
 	_size(size),
 	_size(size),
-	_title(title)
+	_title(title),
+	_mouseLocked(false)
 {
 {
 	_context = nullptr;
 	_context = nullptr;
 	_inputMap.map(0, Input(sf::Keyboard::R, Input::Type::Pressed));
 	_inputMap.map(0, Input(sf::Keyboard::R, Input::Type::Pressed));
-	bind(0, [this](const sf::Event&)
+	bind(0, [this](const sf::Event&, float power)
 	{
 	{
 		if(_size == sf::Vector2u(640u, 480u))
 		if(_size == sf::Vector2u(640u, 480u))
 			_size = sf::Vector2u(1366u, 768u);
 			_size = sf::Vector2u(1366u, 768u);
@@ -59,6 +60,7 @@ void TrianglesWindow::clear(sf::Color color)
 void TrianglesWindow::render()
 void TrianglesWindow::render()
 {
 {
 	_window.display();
 	_window.display();
+	_window.setMouseCursorVisible(true);
 }
 }
 
 
 void TrianglesWindow::recreate()
 void TrianglesWindow::recreate()
@@ -130,6 +132,17 @@ sf::Vector2i TrianglesWindow::getMousePosition()
 	return sf::Mouse::getPosition(_window);
 	return sf::Mouse::getPosition(_window);
 }
 }
 
 
+void TrianglesWindow::lockMouse()
+{
+	lockMouse(sf::Vector2i(_size.x / 2.f, _size.y / 2.f));
+}
+
+void TrianglesWindow::lockMouse(sf::Vector2i position)
+{
+	_window.setMouseCursorVisible(false);
+	sf::Mouse::setPosition(position, _window);
+}
+#include "Utility.hpp"
 void TrianglesWindow::open()
 void TrianglesWindow::open()
 {
 {
 	sf::ContextSettings settings;
 	sf::ContextSettings settings;
@@ -138,6 +151,8 @@ void TrianglesWindow::open()
 	settings.antialiasingLevel = 8;
 	settings.antialiasingLevel = 8;
 	_window.create(sf::VideoMode(_size.x, _size.y), _title, (_context->fullscreen ? sf::Style::Fullscreen : (sf::Style::Titlebar | sf::Style::Close)), settings);
 	_window.create(sf::VideoMode(_size.x, _size.y), _title, (_context->fullscreen ? sf::Style::Fullscreen : (sf::Style::Titlebar | sf::Style::Close)), settings);
 	_window.setKeyRepeatEnabled(false);
 	_window.setKeyRepeatEnabled(false);
+	Echo::debug("Debug window position set to 1200 800");
+	_window.setPosition(sf::Vector2i(1200, 800));
 	if(_context->vsync)
 	if(_context->vsync)
 		_window.setVerticalSyncEnabled(true);
 		_window.setVerticalSyncEnabled(true);
 	if(_context)
 	if(_context)

+ 3 - 1
TrianglesWindow.hpp

@@ -46,6 +46,8 @@ class TrianglesWindow: public InputTarget<int>
 		void draw(sf::Drawable& drawable, sf::Shader* shader);
 		void draw(sf::Drawable& drawable, sf::Shader* shader);
 		bool pollEvent(sf::Event& event);
 		bool pollEvent(sf::Event& event);
 		sf::Vector2i getMousePosition();
 		sf::Vector2i getMousePosition();
+		void lockMouse();
+		void lockMouse(sf::Vector2i position);
 
 
 	private:
 	private:
 		void open();
 		void open();
@@ -56,6 +58,6 @@ class TrianglesWindow: public InputTarget<int>
 		sf::RenderWindow _window;
 		sf::RenderWindow _window;
 		sf::Vector2u _size;
 		sf::Vector2u _size;
 		std::string _title;
 		std::string _title;
-
+		bool _mouseLocked;
 };
 };
 
 

+ 52 - 0
Utility.hpp

@@ -50,6 +50,18 @@ class Echo
 		
 		
 		template<typename Type, typename... Args>
 		template<typename Type, typename... Args>
 		static void out(int prefix, Type out, Args... args);
 		static void out(int prefix, Type out, Args... args);
+		
+		template<typename Type, typename... Args>
+		static void debug(Type out, Args... args);
+		
+		template<typename Type, typename... Args>
+		static void info(Type out, Args... args);
+		
+		template<typename Type, typename... Args>
+		static void load(Type out, Args... args);
+		
+		template<typename Type, typename... Args>
+		static void error(Type out, Args... args);
 
 
 		static void out(std::string debug);
 		static void out(std::string debug);
 		static void out(float debug);
 		static void out(float debug);
@@ -105,4 +117,44 @@ void Echo::out(int order, Type out, Args... args)
 		helper(false, out, args...);
 		helper(false, out, args...);
 		std::cout << std::endl;
 		std::cout << std::endl;
 	}
 	}
+}
+
+template<typename Type, typename... Args>
+void Echo::debug(Type out, Args... args)
+{
+	if(!printType(Debug))
+		return;
+
+	helper(false, out, args...);
+	std::cout << std::endl;
+}
+
+template<typename Type, typename... Args>
+void Echo::info(Type out, Args... args)
+{
+	if(!printType(Info))
+		return;
+
+	helper(false, out, args...);
+	std::cout << std::endl;
+}
+
+template<typename Type, typename... Args>
+void Echo::load(Type out, Args... args)
+{
+	if(!printType(Load))
+		return;
+
+	helper(false, out, args...);
+	std::cout << std::endl;
+}
+
+template<typename Type, typename... Args>
+void Echo::error(Type out, Args... args)
+{
+	if(!printType(Error))
+		return;
+
+	helper(true, out, args...);
+	std::cerr << std::endl;
 }
 }