/** * 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(), Lantern(), _movement(0.f), _movementSpeed(0.6f), _movementMomentum(0.f), _movementAcceleration(7.f), _movementSuppresion(10.f), _rotation(0.f), _rotationSpeed(0.6f), _rotationMomentum(0.f), _rotationAcceleration(38.f), _rotationSuppresion(20.f), _hit(false), _dead(false), _won(false), //_particleSystem(512, 512), _ammo(4), _life(sf::Color::Red, 1.f), _mana(sf::Color::Blue, 0.942f), _type(Type::Tropical) { /** * 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(13)); _inputMap.map(6, Input(15, Input::Type::Pressed)); } 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)); _inputMap.map(6, Input(sf::Keyboard::LControl, Input::Type::Pressed)); } /** * 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() > 750 and _ammo > 0) { // Does not check if _context != nullptr // so please do remember to call setContext(). --_ammo; _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 -= (rand() % 3000 + 8000) / 1000.f; _life.show(); _mana.show(); } }); bind(6, [this](const sf::Event&, float) { _lightType++; _lightType %= 2; switch(_lightType) { case 0: light()->_emissionSprite.setTexture(_context->assets->loadTexture("data/background/Light_Alt.png")); light()->_emissionSprite.setOrigin(sf::Vector2f(_context->assets->loadTexture("data/background/Light_Alt.png").getSize().x / 2u, _context->assets->loadTexture("data/background/Light_Alt.png").getSize().y - (_type == Illuminati ? 71 : 0))); break; case 1: light()->_emissionSprite.setTexture(_context->assets->loadTexture("data/background/Light.png")); light()->_emissionSprite.setOrigin(sf::Vector2f(_context->assets->loadTexture("data/background/Light.png").getSize().x / 2u, _context->assets->loadTexture("data/background/Light.png").getSize().y / 2u - (_type == Illuminati ? 30 : 0))); break; default: break; } }); /** * Particles */ // _particleSystem.setDissolutionRate(255.f); /** * Technical */ genCollisionBox("data/hitbox/Player.png", sf::Vector2f(71.f, 100.f)); //_particleSystem.setOrigin(256.f, 256.f); _bullets.reserve(10); _bulletTimer.restart(); _durability = 0.4f; light()->_emissionSprite.setColor(sf::Color::White); } 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")); _context->assets->loadTexture("data/triangle/Arc.png").setSmooth(true); _life.setTexture(_context->assets->loadTexture("data/triangle/Arc.png")); _mana.setTexture(_context->assets->loadTexture("data/triangle/Arc.png")); _lightType = 0; light()->_emissionSprite.setTexture(_context->assets->loadTexture("data/background/Light_Alt.png")); light()->_emissionSprite.setOrigin(sf::Vector2f(_context->assets->loadTexture("data/background/Light_Alt.png").getSize().x / 2u, _context->assets->loadTexture("data/background/Light_Alt.png").getSize().y - (_type == Illuminati ? 71 : 0))); } const bool Player::isDead() const { return _dead; } const bool Player::hasWon() const { return _won; } void Player::setTexture(sf::Texture& texture) { _innerTexture = texture; _image = texture.copyToImage(); //_particleSystem.loadColors(_image); _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); } void Player::setType(Type type) { _type = type; } bool Player::checkCollision(Foreground& foreground, bool pixel) { Collidable::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 && 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 || 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; _life.show(); _mana.show(); 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::update(sf::Time delta) { keyboardControls(delta); sf::Vector2f position = getPosition(); bool all = false; for(unsigned i = 0; i < _bullets.size(); ++i) { _bullets[i].update(delta, position); if(!_bullets[i].isDead()) all = true; } if(!all) _bullets.clear(); //_particleSystem.setPosition(position); sf::Listener::setPosition(position.x, position.y, 0); _life.setPosition(position); _mana.setPosition(position); _life.setSize((unsigned)getHullLeft()); _mana.setSize(_ammo * 10); _life.update(delta); _mana.update(delta); if(getScale().x == 1.f) { //_particleSystem.clear(); //_particleSystem.update(delta); //_particleSystem.render(); } if(getScale().x < 0.1f) { _dead = true; _won = true; } light()->_emissionSprite.setPosition(getPosition()); light()->_emissionSprite.setRotation(getRotation()); } const float Player::getHullLeft() const { return ((_pointCount * _durability - _cbanned.size()) / (_pointCount * _durability)) * 100.f; } void Player::draw(sf::RenderTarget& target, sf::RenderStates states) const { //if(_particleSystem.isEnabled()) //target.draw(_particleSystem); 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); target.draw(_life); target.draw(_mana); }