Collision class base

mail@pastecode.io avatar
unknown
c_cpp
a year ago
9.6 kB
22
Indexable
Never
#pragma once
#include <SFML/Graphics.hpp>
#include <string>
#include "Collider.h"
#include <iostream>
#include <cmath>
#include "Tile.h"
#include "Ray.h"
#include "Tilemap.h"
#include <vector>

using namespace std;

class Player
{
public:
	sf::Vector2f position;
	sf::Vector2f size;
	Collider collider;
	sf::Sprite sprite;
	int acceleration_max;
	bool left;
	bool right;
	bool onGround;
	float v;
	float speed;
	int f;
	float mass;
	sf::Text text_pos;
	sf::Font font;
	bool debug;
	bool up;
	bool running;
	sf::Vector2f screen_size;
	bool isJumping;
	float speed_original;
	bool isRunning;
	string lastError = "0x0";

	Player()
	{
		this->position = sf::Vector2f(0, 0);
		this->speed = 3;
		this->speed_original = 3;
		this->v = 5;
		this->mass = 4;
		this->up = false;
		this->size = sf::Vector2f(50, 50);
		this->collider = Collider(this->position, this->size, true);
		this->acceleration_max = 1;
		this->left = false;
		this->right = false;
		this->onGround = false;
		this->font.loadFromFile("resources/fonts/RobotoMono-Light.ttf");
		this->f = 0;
		this->text_pos.setFont(this->font);
		this->text_pos.setCharacterSize(12);
		this->text_pos.setFillColor(sf::Color::White);
		this->text_pos.setStyle(sf::Text::Bold);
		this->text_pos.setString(to_string((int)this->position.x) + "\n" + to_string((int)this->position.y));
		this->debug = false;
		this->isRunning = false;
	}

	Player(sf::Vector2f position, sf::Vector2f velocity, sf::Vector2f acceleration, sf::Vector2f size, sf::Vector2f screen_size, Tilemap tilemap)
	{
		this->position = position;
		this->speed =3;
		this->speed_original = 3;
		this->v = 5;
		this->mass = 4;
		this->up = false;
		this->size = size;
		this->collider = Collider(this->position, this->size, true);
		this->acceleration_max = 1;
		this->left = false;
		this->right = false;
		this->onGround = false;
		this->font.loadFromFile("resources/fonts/RobotoMono-Light.ttf");
		this->f = 0;
		this->text_pos.setFont(this->font);
		this->text_pos.setCharacterSize(12);
		this->text_pos.setFillColor(sf::Color::White);
		this->text_pos.setStyle(sf::Text::Bold);
		this->text_pos.setString(to_string((int)this->position.x) + "\n" + to_string((int)this->position.y));
		this->debug = false;
		this->screen_size = screen_size;
		this->isRunning = false;

	}

	void update(sf::Vector2f mouse_pos, vector<Tile> close_tiles)
	{
		if (isRunning && onGround)
		{
			this->speed = this->speed_original * 2;
		}
		if (!isRunning && onGround)
		{
			this->speed = this->speed_original;
		}

		calculateMovement();
		checkUp(close_tiles);
		checkGround(close_tiles);
		checkLeft(close_tiles);
		checkRight(close_tiles);

		if (!isJumping)
		{
			if (detectFloating(close_tiles))
			{
				this->onGround = false;
				this->isJumping = false;
			}
			else
			{
				this->onGround = true;
			}
		}

		if (this->position.y > 500)
		{
			this->position.y = -500;
		}

		if (!onGround && isJumping)
		{
			this->mass = 4;
			f = (int)(mass * v);
			this->position += sf::Vector2f(0, -f);
			v-=.5f;
			if (v < -4)
				v = -4;

		}
		else if (!onGround && !isJumping)
		{
			this->mass = 3;
			v = -4;
			f = (int)(mass * v);
			this->position += sf::Vector2f(0, -f);
			
			
		}
		else if (onGround && !isJumping)
		{
			this->v = 5;
			this->mass = 0;

		}
		else if (onGround && isJumping)
		{

		}

		this->collider.update(sf::Vector2f(screen_size.x / 2, screen_size.y / 2));
		if (this->debug)
			setDebugInfo(mouse_pos);
	}

	void checkGround(vector<Tile> close_tiles)
	{
		
		for (int i = 0; i < close_tiles.size(); i++)
		{
			if (close_tiles[i].collider.top.getGlobalBounds().intersects(this->collider.bottom.getGlobalBounds()))
			{
				this->onGround = true;
				this->isJumping = false;

				this->v = 5;
				this->mass = 0;
				
				correctYPos(close_tiles[i]);
				i = close_tiles.size();
				return;
			}
		}
		
	}

	void checkLeft(vector<Tile> close_tiles)
	{
		for (int i = 0; i < close_tiles.size(); i++)
		{
			//if (passesCollisionTestLeft(close_tiles[i])) return;
			if (close_tiles[i].collider.right.getGlobalBounds().intersects(this->collider.left.getGlobalBounds()))
			{
				this->position += sf::Vector2f((getOverlapLeft(close_tiles[i])), 0);
			}
		}
		return;
	}

	void checkRight(vector<Tile> close_tiles)
	{
		for (int i = 0; i < close_tiles.size(); i++)
		{
			//if (passesCollisionTestRight(close_tiles[i])) return;
			if (close_tiles[i].collider.left.getGlobalBounds().intersects(this->collider.right.getGlobalBounds()))
			{
				this->position -= sf::Vector2f(getOverlapRight(close_tiles[i]), 0);
				//right = false;

			}
		}
		return;
	}

	void checkUp(vector<Tile> close_tiles)
	{
		for (int i = 0; i < close_tiles.size(); i++)
		{
			if (close_tiles[i].collider.bottom.getGlobalBounds().intersects(this->collider.top.getGlobalBounds()))
			{
				this->position += sf::Vector2f(0, getOverlapUp(close_tiles[i]));
				this->v = 0;
				return;
			}
		}
	}

	/*bool isCloseToWall(Tile close_tile)
	{
		if (close_tile.position_tilemap.x < this->position.x + 80 && close_tile.position_tilemap.x > this->position.x - 80)
		{
			return true;
		}
		
		return false;
	}*/

	bool passesCollisionTestRight(Tile tile)
	{
		//check if at any point in the next frame moving right at speed, the player will be inside the tile
		//if so, return false
		//else return true

		if (this->position.x + this->speed < (tile.position.x - 20) && tile.isSolid)
		{
			return false;
		}
		else
		{
			tile.collider.top.setFillColor(sf::Color::Red);
			tile.collider.bottom.setFillColor(sf::Color::Red);
			tile.collider.left.setFillColor(sf::Color::Red);
			tile.collider.right.setFillColor(sf::Color::Red);
		}
		return false;
	}

	bool passesCollisionTestLeft(Tile tile)
	{
		 //check if at any point in the next frame moving right at speed, the player will be inside the tile
		//if so, return false
		//else return true
		if (this->position.x - this->speed > tile.position.x + 20 && tile.isSolid)
		{
			return false;
		}
		return false;
	}

	bool detectFloating(vector<Tile> close_tiles)
	{
		bool isFloating = true;
		for (int i = 0; i < close_tiles.size(); i++)
		{
			if (this->collider.groundcheck.getGlobalBounds().intersects(close_tiles[i].collider.top.getGlobalBounds()) || this->collider.groundcheck_left.getGlobalBounds().intersects(close_tiles[i].collider.top.getGlobalBounds()) || this->collider.groundcheck_right.getGlobalBounds().intersects(close_tiles[i].collider.top.getGlobalBounds()))
			{
				isFloating = false;
				
			}
			else
			{
				//
			}
		}
		return isFloating;
	}

	void correctYPos(Tile tile)
	{
		
		float overlap = getOverlapBelow(tile);
		this->position += sf::Vector2f(0, -overlap);
		//this->collider.update(sf::Vector2f(screen_size.x / 2, screen_size.y / 2));

	}

	float getOverlapBelow(Tile tile)
	{
		float overlap = 0;
		if (this->collider.bottom.getGlobalBounds().intersects(tile.collider.top.getGlobalBounds()))
		{
			overlap = this->collider.bottom.getGlobalBounds().height - (tile.collider.top.getGlobalBounds().top - this->collider.bottom.getGlobalBounds().top);
		}
		return overlap;
	}

	float getOverlapLeft(Tile tile)
	{
		float overlap = 0;
		if (this->collider.left.getGlobalBounds().intersects(tile.collider.right.getGlobalBounds()))
		{
			//overlap is the x distance between (tile.collider.pos.x + tile.collider.size.width/2) and (this->collider.pos.x + player.collider.size.width/2)
			float y = tile.collider.right.getPosition().x + ((int)tile.collider.right.getSize().x / 2);
			float x = this->collider.left.getPosition().x;
			
			overlap = (int)std::abs(x - y);
		}
		return overlap;
	}

	float getOverlapRight(Tile tile)
	{
		float overlap = 0;
		if (this->collider.right.getGlobalBounds().intersects(tile.collider.left.getGlobalBounds()))
		{
			overlap = this->collider.right.getGlobalBounds().width - (tile.collider.left.getGlobalBounds().left - this->collider.right.getGlobalBounds().left);
		}
		return overlap;
	}

	float getOverlapUp(Tile tile)
	{
		float overlap = 0;
		if (this->collider.top.getGlobalBounds().intersects(tile.collider.bottom.getGlobalBounds()))
		{
			overlap = this->collider.top.getGlobalBounds().height - (tile.collider.bottom.getGlobalBounds().top - this->collider.top.getGlobalBounds().top);
		}
		return overlap;
	}

	void calculateMovement()
	{
		if (this->left)
			this->position += sf::Vector2f(-speed, 0);
		else if (this->right)
			this->position += sf::Vector2f(speed, 0);
		//this->collider.update(sf::Vector2f(screen_size.x / 2, screen_size.y / 2));
	}

	void draw(sf::RenderWindow& window)
	{
		window.draw(this->sprite);
		this->collider.draw(window);
		if (this->debug)
			window.draw(text_pos);
	}

	int distanceFromPlayer(Tile tile)
	{
		int dist = sqrt(pow((this->position.x - tile.position.x), 2) + pow((this->position.y - tile.position.y), 2));
	}

	int isColliding(Collider& other)
	{
		return this->collider.isTopColliding(other);
		// 1 - top
		// 2 - bottom
		// 3 - left
		// 4 - right
		// 0 - no collision
	}
 
	void collide()
	{
		//this->position.y = 200;
		this->onGround = true;
		f = 0;
		mass = 5;
		v = 10;
	}

	void setDebugInfo(sf::Vector2f mouse_pos)
	{
		this->text_pos.setString(
			"player_pos: " + to_string((int)position.x) + ", " + to_string((int)position.y) + "\n" +
			"mouse_pos: " + to_string((int)mouse_pos.x) + ", " + to_string((int)mouse_pos.y) + "\n" +
			(onGround ? "On ground: True" : "On ground: False") + "\n" +
			"\nv: " + to_string(this->v) + "\n" +
			"m: " + to_string((int)this->mass) + "\n" +
			"f: " + to_string(this->f) + "\n" +
			"lastERR: " + lastError);

		text_pos.setPosition(sf::Vector2f(5, 5));
	}
};