/**
* one room arena
* 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 .
*/
#include
#include
#include "Player.hpp"
#include "Map.hpp"
#include "Bullet.hpp"
#include "Powerup.hpp"
ActualPlayer* Player::actualPlayer;
std::vector* Player::aiPlayer;
unsigned Player::totalScore = 0;
Player::Player(Map* map):
ConvexShape(6),
_nukes(0),
_speed(400.f),
_strength(200),
_rateOfFire(1.f),
_map(map),
_dead(false)
{
const int playerRadius = 30;
const float angle = 40.f;
this->setPoint(0, Vector2f(0, -playerRadius));
this->setPoint(1, Vector2f(-std::sin(angle * 3.1415f / 180.f) * playerRadius / 3.25f, -std::cos(angle * 3.1415f / 180.f) * playerRadius / 3.f));
this->setPoint(2, Vector2f(-std::sin(angle * 3.1415f / 180.f) * playerRadius, std::cos(angle * 3.1415f / 180.f) * playerRadius));
this->setPoint(3, Vector2f(0, playerRadius / 4.f));
this->setPoint(4, Vector2f(std::sin(angle * 3.1415f / 180.f) * playerRadius, std::cos(angle * 3.1415f / 180.f) * playerRadius));
this->setPoint(5, Vector2f(std::sin(angle * 3.1415f / 180.f) * playerRadius / 3.25f, -std::cos(angle * 3.1415f / 180.f) * playerRadius / 3.f));
this->setOutlineThickness(playerRadius * 6.f);
_killKill.loadFromFile("data/explosion.ogg");
_kill.setBuffer(_killKill);
_laserLaser.loadFromFile("data/shoot.ogg");
_laser.setBuffer(_laserLaser);
_powerupPowerup.loadFromFile("data/powerup.ogg");
_powerup.setBuffer(_powerupPowerup);
}
Player::~Player()
{
}
void Player::setColor(Color color)
{
this->setFillColor(color);
this->setOutlineColor(Color(color.r, color.g, color.b, 15));
_color = color;
}
float mouseToRotation(Vector2f mouse)
{
float val = std::atan(-mouse.y / mouse.x) * 180.f / 3.1415f;
if(mouse.x < 0.f)
val += 180.f;
else if(mouse.x > 0.f && mouse.y > 0.f)
val += 360.f;
val += 270.f;
val = std::fmod(val, 360.f);
val = 360.f - val;
return val;
}
void ActualPlayer::input(float delta, Map* map, const Vector2f mouse)
{
static Clock clock;
if(Mouse::isButtonPressed(Mouse::Left))
{
if(clock.getElapsedTime().asSeconds() >= _rateOfFire)
{
spawnBullet(false);
clock.restart();
}
}
bool left = Keyboard::isKeyPressed(Keyboard::A);
bool right = Keyboard::isKeyPressed(Keyboard::D);
bool up = Keyboard::isKeyPressed(Keyboard::W);
bool down = Keyboard::isKeyPressed(Keyboard::S);
float targetRotation = mouseToRotation(mouse);
Transform transform;
transform.translate(getPosition());
transform.rotate(targetRotation);
for(unsigned i = 0; i < getPointCount(); ++i)
{
Vector2f pos = transform.transformPoint(getPoint(i));
if(map->collision(pos))
break;
if(i == getPointCount() - 1)
setRotation(targetRotation);
}
static float velocityF = 0.f;
static float velocityS = 0.f;
static Vector2f movement;
movement = movementHelper(delta, right, left, velocityS, getRotation() + 90.f, _speed, 0.75f) * delta;
movement += movementHelper(delta, up, down, velocityF, getRotation(), _speed, 0.5f) * delta;
for(unsigned i = 0; i < getPointCount(); ++i)
{
Vector2f pos = movement + getTransform().transformPoint(getPoint(i));
if(map->collision(pos))
{
velocityF *= -1.f;
velocityS *= -1.f;
movement *= -1.f;
break;
}
}
move(movement);
}
void AiPlayer::updateAi(Map* map, ActualPlayer* player)
{
if(std::pow(player->getPosition().x - getPosition().x, 2) + std::pow(player->getPosition().y - getPosition().y, 2) < 1000*1000)
{
_targetRotation = mouseToRotation(Vector2f(player->getPosition().x - getPosition().x, player->getPosition().y - getPosition().y)) + _targetRotationDeviation;
if(_nukes-- > 0)
spawnBullet(true);
else
_nukes = 0;
}
else if(_powerupManager != nullptr)
{
for(unsigned i = 0; i < _powerupManager->getSize(); ++i)
{
if(std::pow(_powerupManager->getPowerup(i).getPosition().x - getPosition().x, 2) + std::pow(_powerupManager->getPowerup(i).getPosition().y - getPosition().y, 2) < 1000*1000)
{
_targetRotation = mouseToRotation(Vector2f(_powerupManager->getPowerup(i).getPosition().x - getPosition().x, _powerupManager->getPowerup(i).getPosition().y - getPosition().y)) + _targetRotationDeviation;
}
}
}
}
void AiPlayer::input(float delta, Map* map, ActualPlayer* player)
{
if(_clock.getElapsedTime().asSeconds() >= _rateOfFire)
{
spawnBullet(false);
_clock.restart();
}
if(_clock2.getElapsedTime().asSeconds() >= 0.5f)
{
updateAi(map, player);
_clock2.restart();
}
Transform transform;
transform.translate(getPosition());
transform.rotate(_targetRotation);
for(unsigned i = 0; i < getPointCount(); ++i)
{
Vector2f pos = transform.transformPoint(getPoint(i));
if(map->collision(pos))
break;
if(i == getPointCount() - 1)
setRotation(_targetRotation);
}
Vector2f movement;
movement = movementHelper(delta, true, false, _velocity, getRotation(), _speed, 0.5f) * delta;
for(unsigned i = 0; i < getPointCount(); ++i)
{
Vector2f pos = movement + getTransform().transformPoint(getPoint(i));
if(map->collision(pos))
{
_velocity *= -1.f;
movement *= -1.f;
break;
}
}
for(unsigned i = 0; i < getPointCount(); ++i)
{
Vector2f pos = movement * 100.f + getTransform().transformPoint(getPoint(i));
if(map->collision(pos))
{
_targetRotation += delta * 720.f;
_targetRotationDeviation += delta * 720.f;
_targetRotation = std::fmod(_targetRotation, 360.f);
_targetRotationDeviation = std::fmod(_targetRotationDeviation, 360.f);
break;
}
if(i == getPointCount() - 1)
_targetRotationDeviation = 0;
}
move(movement);
_laser.setPosition(Vector3f(getPosition().x - player->getPosition().x, getPosition().y - player->getPosition().y, 0) / 100.f);
_powerup.setPosition(Vector3f(getPosition().x - player->getPosition().x, getPosition().y - player->getPosition().y, 0) / 100.f);
if(_kill.getStatus() != Sound::Playing)
_kill.setPosition(Vector3f(getPosition().x - player->getPosition().x, getPosition().y - player->getPosition().y, 0) / 200.f);
}
void AiPlayer::registerPowerups(PowerupManager* mgr)
{
_powerupManager = mgr;
}
void Player::logic(float delta)
{
for(unsigned i = 0; i < _bullets.size(); ++i)
{
_bullets[i]->update(delta);
if(_bullets[i]->isDead())
{
_bullets.erase(_bullets.begin() + i);
if(_bullets[i]->isExplosive())
{
_kill.setPosition(Vector3f(0.f, 0.f, 0.f));
_kill.play();
}
}
}
}
void Player::spawnBullet(bool altFire)
{
if(!altFire)
{
_bullets.push_back(new RectBullet(getPosition(), getRotation(), _strength));
_laser.play();
}
else
{
if(_nukes--)
_bullets.push_back(new NukeBullet(getPosition(), getRotation(), _strength));
else
{
_nukes = 0;
return;
}
}
if(this == actualPlayer)
_bullets.back()->madeByPlayer();
_bullets.back()->registerSelf(this);
_bullets.back()->registerMap(_map);
_bullets.back()->setColor(_color);
}
void Player::drawBullets(RenderTarget& target) const
{
for(unsigned i = 0; i < _bullets.size(); ++i)
{
target.draw(*_bullets[i]);
}
}
void Player::hasten()
{
_powerup.play();
_speed += 150.f;
}
void Player::addNuke()
{
_powerup.play();
++_nukes;
}
int Player::nukes() const
{
return _nukes;
}
void Player::growStronger()
{
if(_strength <= 600)
{
_powerup.play();
_strength += 50;
}
}
void Player::rateOfFire()
{
if(_rateOfFire > 0.2f)
{
_powerup.play();
_rateOfFire -= 0.1f;
}
}
void Player::kill(bool increaseScore)
{
totalScore += 1000 * increaseScore;
_dead = true;
_kill.play();
}
bool Player::isDead() const
{
return _dead;
}
Vector2f Player::movementHelper(float delta, bool key1, bool key2, float& velocity, float angle, float speed, float damping)
{
Vector2f rotated = Vector2f(std::sin(angle * 3.1415f / 180.f), -std::cos(angle * 3.1415f / 180.f));
if(key1 && !key2)
{
if(velocity < speed)
velocity += speed * delta;
}
else if(!key1 && key2)
{
if(velocity > -speed)
velocity -= speed * delta;
}
else
{
if(std::fabs(velocity) < 50.f)
velocity = 0.f;
else if(velocity > 0.f)
velocity -= speed * delta * damping;
else
velocity += speed * delta * damping;
}
return rotated * velocity;
}