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