#include "Player.h"
#include "BasicEnemy.h"
USING_NS_CC;
Player::Player() :_speed(150),
_numBullets(30),
_bulletIndex(0),
_initialiced(false)
{
}
bool Player::init(){
//superclass first
if (!Sprite::init())
{
return false;
}
for (int i = 0; i < _numBullets; i++){
_bulletPool.pushBack(Bullet::createPlayerBullet());
}
_currentAnimation = IDLE;
_controller = TouchController::create();
addChild(_controller);
createIdleAnimation();
createExplosionAnimation();
// lanzamos la animacion por defecto
runAction(_idleAnimation);
scheduleShoot();
return true;
}
void Player::setVisible(bool visible){
Sprite::setVisible(visible);
if (visible){
runAction(_shoot);
}
else{
stopActionByTag(SHOOT_TAG);
}
}
void Player::setTargets(cocos2d::Vector& targets){
_targets = targets;
for (int i = 0; i < _numBullets; i++){
_bulletPool.at(i)->setPlayerTargets(_targets);
}
}
void Player::setParent(Node* parent){
Sprite::setParent(parent);
//impide que las balas se incorporen mas de una vez a la escena
if (!_initialiced){
for (int i = 0; i < _numBullets; i++){
//incorporan las balas al la escena
getParent()->addChild(_bulletPool.at(i));
}
_initialiced = true;
}
}
void Player::scheduleShoot(){
//establecemos que la nave disparara cada medio segundo
DelayTime *delayAction = DelayTime::create(0.5f);
// creamos una accion a partir de una funcion
CallFunc *callSelectorAction = CallFunc::create(CC_CALLBACK_0(Player::shoot, this));
//creamos una secuencia que primero espera y luego dispara
auto shootSequence = Sequence::create(delayAction, callSelectorAction, NULL);
// envolvemos la secuencia un una accion RepeatForever
_shoot = RepeatForever::create(shootSequence);
_shoot->setTag(SHOOT_TAG);
runAction(_shoot);
}
void Player::createIdleAnimation(){
//creamos un pool de imagenes para la animacion
Vector animFrames;
auto acc = 0;
for (int i = 0; i < 4; i++){
auto frame = SpriteFrame::create("animacion_nave.png", Rect(acc, 0, 50, 63));
acc += 50;
animFrames.pushBack(frame);
}
//si ninguna animacion esta corriendo el esprite por defecto es definido aqui
this->setSpriteFrame(animFrames.at(0));
//creamos una animacion con un tiempo de espera entre cada frame de 0.25s
auto animation = Animation::createWithSpriteFrames(animFrames, 0.25f);
//creamos la accion de animar el objeto animation
auto animate = Animate::create(animation);
//creamos la accion de animar el objeto animation
_idleAnimation = RepeatForever::create(animate);
//creamos una accion que repita para siempre la animacion
_idleAnimation->setTag(Player::Animations::IDLE);
// le decimos a cocos que no elimine este objeto hasta que lo indiquemos o
//hasta que el objeto player se elimine
_idleAnimation->retain();
}
void Player::createExplosionAnimation(){
Vector animFrames;
auto acc = 0;
for (int i = 0; i < 4; i++){
auto frame = SpriteFrame::create("player_explosion.png", Rect(acc, 0, 50, 63));
acc += 50;
animFrames.pushBack(frame);
}
auto animation = Animation::createWithSpriteFrames(animFrames, 0.15f);
_explosionAnimation = Animate::create(animation);
//creamos la accion de animar el objeto animation, en este caso no necesitamos
//un RepeatForever porque solo debe explotar una vez y parar.
_explosionAnimation->setTag(Player::Animations::EXPLOSION);
_explosionAnimation->retain();
}
void Player::setCurrentAnimation(Animations anim){
if (_currentAnimation == anim) return;
_currentAnimation = anim;
if (_currentAnimation == IDLE){
stopActionByTag(EXPLOSION);
runAction(_idleAnimation);
}
if (_currentAnimation == EXPLOSION){
stopActionByTag(IDLE);
runAction(_explosionAnimation);
}
}
void Player::update(float dt){
//si la nave es destruida no podra moverse y dejara de verse tras explotar
if (_currentAnimation == EXPLOSION){
//ademas debe dejar de disparar
stopActionByTag(SHOOT_TAG);
if (_explosionAnimation->isDone() && isVisible()){
setVisible(false);
}
return;
}
//mover la nave a donde el controlador indique
float speed = _speed*dt;
auto controller = _controller->getController();
if (controller.upRight){
setPosition(getPositionX() + speed, getPositionY() + speed);
}
else if (controller.upLeft){
setPosition(getPositionX() - speed, getPositionY() + speed);
}
else if (controller.downRight){
setPosition(getPositionX() + speed, getPositionY() - speed);
}
else if (controller.downLeft){
setPosition(getPositionX() - speed, getPositionY() - speed);
}
else if (controller.left){
setPositionX(getPositionX() - speed);
}
else if (controller.right){
setPositionX(getPositionX() + speed);
}
else if (controller.down){
setPositionY(getPositionY() - speed);
}
else if (controller.up){
setPositionY(getPositionY() + speed);
}
}
void Player::shoot(){
_bulletIndex = _bulletIndex % _numBullets;
auto bullet = _bulletPool.at(_bulletIndex);
bullet->setAnchorPoint(Point(0.5, 0));
if (!bullet->isVisible()){
bullet->setPosition(getPositionX(), getPositionY() + getBoundingBox().size.height*0.5);
bullet->setVisible(true);
}
_bulletIndex++;
}