/** * 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(4.f), _movementMomentum(0.f), _movementAcceleration(10.f), _movementSuppresion(5.f), _rotation(0.f), _rotationSpeed(0.6f), _rotationMomentum(0.f), _rotationAcceleration(38.f), _rotationSuppresion(20.f), _hit(false), _dead(false) { /** * Default binding */ _inputMap.duoMap(1, Input(sf::Keyboard::Up), Input(sf::Keyboard::W)); _inputMap.duoMap(2, Input(sf::Keyboard::Down), Input(sf::Keyboard::S)); _inputMap.duoMap(3, Input(sf::Keyboard::Left), Input(sf::Keyboard::A)); _inputMap.duoMap(4, Input(sf::Keyboard::Right), Input(sf::Keyboard::D)); _inputMap.map(5, Input(sf::Keyboard::Space)); /** * Input lambdas */ duoBind(1, [this](const sf::Event&) { _movement += 1.f; }); duoBind(2, [this](const sf::Event&) { _movement -= 0.8f; }); duoBind(3, [this](const sf::Event&) { _rotation -= 1.f; }); duoBind(4, [this](const sf::Event&) { _rotation += 1.f; }); bind(5, [this](const sf::Event&) { 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; } }); /** * 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::update(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(_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); //px.move(movement); _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); //px.rotate(rotation); _rotation = 0.f; for(unsigned i = 0; i < _bullets.size(); ++i) { _bullets[i].update(delta); if(_bullets[i].isDead()) _bullets.erase(_bullets.begin() + i); } } void Player::draw(sf::RenderTarget& target, sf::RenderStates states) const { 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); }