/** * 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; }