/** * 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 . */ #include #include "Player.hpp" #include "Assets.hpp" Player::Player(): Triangle(), InputTarget(_inputMap), Collidable(), _movement(0.f), _movementSpeed(2.f), _movementMomentum(0.f), _movementAcceleration(10.f), _movementSuppresion(10.f), _rotation(0.f), _rotationSpeed(0.6f), _rotationMomentum(0.f), _rotationAcceleration(38.f), _rotationSuppresion(20.f), _hit(false), _dead(false), _particleSystem(1920, 1080) { /** * Default binding */ 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 */ bind(1, [this](const sf::Event&, float power) { _movement += power; }); bind(2, [this](const sf::Event&, float power) { _movement -= power * 0.8f; }); bind(3, [this](const sf::Event&, float power) { _rotation -= power; }); bind(4, [this](const sf::Event&, float power) { _rotation += power; }); bind(5, [this](const sf::Event&, float) { if(_bulletTimer.getElapsedTime().asMilliseconds() > 1500) { // Does not check if _context != nullptr // so please do remember to call setContext(). _bullets.emplace_back(getRotation(), getPosition(), _context->assets->loadSound("data/audio/Shotgun.ogg"), _context->assets->loadSound("data/audio/Bomb.ogg"), _context->foreground); _bullets.back().setTexture(_innerTexture); _bulletTimer.restart(); _movementMomentum -= 3.f; } }); /** * Particles */ _particleSystem.setDissolutionRate(255.f); /** * Technical */ genCollisionBox("data/hitbox/Player.png", sf::Vector2f(71.f, 100.f)); _bullets.reserve(10); _bulletTimer.restart(); _durability = 0.99f; } void Player::setContext(Context* context) { _context = context; _glass.setBuffer(_context->assets->loadSound("data/audio/GlassHit.ogg")); _deathSound.setBuffer(_context->assets->loadSound("data/audio/GlassRekt.ogg")); } bool Player::isDead() { return _dead; } void Player::setTexture(sf::Texture& texture) { _innerTexture = texture; _image = texture.copyToImage(); _texture = &_innerTexture; vertexFit(); unsigned pointCount = 0; for(unsigned i = 0; i < _image.getSize().x; ++i) for(unsigned j = 0; j < _image.getSize().y; ++j) if(_image.getPixel(i, j).a > 0) ++pointCount; setPointCount(pointCount); } bool Player::checkCollision(Foreground& foreground) { updateTransform(getTransform()); int k = pixelPerfect(foreground); if(k == -1) { if(_glass.getStatus() != sf::Sound::Status::Playing) _glass.setVolume(0.f); _hit = false; return false; } float i = 10.f; while(k != -1) { sf::Vector2f pos = _cmap[k]; sf::Vector2f center = sf::Vector2f(_image.getSize().x / 2.f, 100.f); if(center.x + pos.x >= 0 && center.x + pos.x < _image.getSize().x and center.y + pos.y >= 0 && center.y + pos.y < _image.getSize().y) _image.setPixel(center.x + pos.x, center.y + pos.y, sf::Color(0, 0, 0, 0)); for(int i = -1; i <= 1; i++) for(int j = -1; j <= 1; j++) { if(i == 0 && j == 0) continue; if(pos.x + center.x + i < 0 || pos.y + center.y + j < 0 or pos.x + center.x + i > _image.getSize().x || pos.y + center.y + j > _image.getSize().y) continue; if(_image.getPixel(pos.x + center.x + i, pos.y + center.y + j).a > 0) { sf::Vector2f vec; vec.x = pos.x + i; vec.y = pos.y + j; if(std::find(_cmap.begin(), _cmap.end(), vec) == _cmap.end()) if(std::find(_cbanned.begin(), _cbanned.end(), vec) == _cbanned.end()) _cmap.push_back(vec); } } _cmap.erase(_cmap.begin() + k); _cbanned.push_back(pos); k = pixelPerfect(foreground); if(i < 100.f) i += 0.1f; } if(i > _glass.getVolume()) _glass.setVolume(i); if(_glass.getStatus() != sf::Sound::Status::Playing) _glass.play(); _innerTexture.loadFromImage(_image); _hit = true; if(_pointCount * _durability < _cbanned.size()) { _dead = true; _deathSound.play(); return true; } else return false; } void Player::keyboardControls(sf::Time delta) { float seconds = delta.asSeconds(); const double degree = 3.14159265358 / 180.; 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; _rotationMomentum += _rotationAcceleration * seconds * _rotation; 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); _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) { _bullets[i].update(delta); if(_bullets[i].isDead()) _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 { target.draw(_particleSystem.getSprite()); for(unsigned i = 0; i < _bullets.size(); ++i) target.draw(_bullets[i]); states.transform *= getTransform(); if(_texture != nullptr) states.texture = (_texture); target.draw(_vertices, states); }