#include #include "Character.h" #include "GameLogic.h" #include "Common.h" #include "GameDisplay.h" Character::Character() { this->lastDirChangeTime = SDL_GetTicks(); } void Character::update() { GameStatus &status = GameStatus::NewSingleton(); //GameOptions &opts = GameOptions::NewSingleton(); GameDisplay &display = GameDisplay::NewSingleton(); Game &game = Game::NewSingleton(); //std::cerr << "Updating character with userType " << this->userType << "\n"; if ( !this->hasState(STATE_DYING) && !this->hasState(STATE_DEAD) ) { if ( (this->userType & ENEMYTYPE_ENEMY2) == ENEMYTYPE_ENEMY2 ) { //std::cerr << "WAVY ENEMY IS CHECKING TIMES\n"; if (SDL_GetTicks() > (this->lastDirChangeTime + 1000)) { if ( this->hasState(STATE_MOVERIGHT) ) { this->removeState(STATE_MOVERIGHT); this->addState(STATE_MOVELEFT); } else { this->removeState(STATE_MOVELEFT); this->addState(STATE_MOVERIGHT); } this->lastDirChangeTime = SDL_GetTicks(); } else { if ( this->velocity.x == 0 ) { this->velocity.x = 3; this->addState(STATE_MOVERIGHT); } } } else if ((this->userType & ENEMYTYPE_ENEMY3) == ENEMYTYPE_ENEMY3 ) { if ( this->velocity.x == 0 ) { this->velocity.x = this->velocity.y; } if ( this->target != NULL ) { if ( this->target->getPosition().x - this->position.x > -(this->velocity.x) || this->target->getPosition().x - this->position.x < this->velocity.x ) { this->position.x = this->target->getPosition().x; } else if ( this->target->getPosition().x < this->position.x ) { this->removeState(STATE_MOVERIGHT); this->addState(STATE_MOVELEFT); } else if ( this->target->getPosition().x > this->position.x ) { this->removeState(STATE_MOVELEFT); this->addState(STATE_MOVERIGHT); } if ( this->target->getPosition().x == this->position.x ) { this->velocity.y = status.enemyVelocity.y; } else { this->velocity.y = status.enemyVelocity.y / 2; } if ( this->target->hasState(STATE_DEAD) || this->target->hasState(STATE_DYING) ) { this->target = NULL; } } } else if ( (this->userType & ENEMYTYPE_ENEMY4) == ENEMYTYPE_ENEMY4 ) { if ( this->target != NULL ) { if ( this->position.x - this->velocity.x <= 0 ) { this->removeState(STATE_MOVELEFT); this->addState(STATE_MOVERIGHT); } else if ( this->position.x + this->velocity.x > 800 ) { this->removeState(STATE_MOVERIGHT); this->addState(STATE_MOVELEFT); } if ( this->position.y + this->velocity.y > 600 ) { this->removeState(STATE_MOVEDOWN); this->addState(STATE_MOVEUP); } else if ( this->position.y - this->velocity.y <= 0 ) { this->removeState(STATE_MOVEUP); this->addState(STATE_MOVEDOWN); } } } } if ( this->health <= 0 && (!this->hasState(STATE_DYING))) { std::cerr << "Character " << this << " is now dying\n"; game.playSound(this->deathSound); this->setState(STATE_DYING); if ( ((rand()%100)+1) <= status.powerDropChance ) { Actor *pwup = game.newActor(); if ( pwup != NULL ) { int pwuptype = (rand()%3)+1; std::cerr << "Generating powerup type " << pwuptype << "\n"; switch ( pwuptype ) { case 1: pwup->setUserType(ACTOR_TEAM_POWERUP | POWERUP_SPREADSHOT); pwup->addAnimation(game.getAnimation(ANIM_PWUP_SPREADSHOT), STATE_DEFAULT); break; case 2: pwup->setUserType(ACTOR_TEAM_POWERUP | POWERUP_ONEUP); pwup->addAnimation(game.getAnimation(ANIM_PWUP_ONEUP), STATE_DEFAULT); break; case 3: pwup->setUserType(ACTOR_TEAM_POWERUP | POWERUP_SHIELDRECHARGE); pwup->addAnimation(game.getAnimation(ANIM_PWUP_SHIELD), STATE_DEFAULT); break; case 4: pwup->setUserType(ACTOR_TEAM_POWERUP | POWERUP_BIGSHIP); pwup->addAnimation(game.getAnimation(ANIM_PWUP_BIGSHIP), STATE_DEFAULT); break; } pwup->setPosition((Vector){this->position.x, this->position.y, 0}); pwup->setState(STATE_NONE); display.addActor(pwup, LAYER_SPRITE3); display.colliders.push_back(pwup); } } } if ( this->state != STATE_DYING && ((this->userType & ACTOR_TEAM_ENEMY) == ACTOR_TEAM_ENEMY) ) { if ( ((rand()%100)+1) < status.enemyShootChance ) { this->fireProjectile(); } } Actor::update(); } void Character::fireProjectile(Vector velocity, int playSound) { // FIXME : Causes segfault on win32, modification of memory after it's freed // TODO : get a generator for the Projectile class SDL_Surface *laserFrame = NULL; SDL_Surface *playerFrame = NULL; Game &myGame = Game::NewSingleton(); GameDisplay &gameDisplay = GameDisplay::NewSingleton(); GameStatus &status = GameStatus::NewSingleton(); Projectile *shotActor = NULL; if ( this->hasState(STATE_DEAD) || this->hasState(STATE_DYING) ) { return; } if ( this->hasState(STATE_SPREADSHOT) && (!this->hasState(STATE_FIRING))) { this->addState(STATE_FIRING); this->projectileAnim = myGame.getAnimation(ANIM_PLAYERSPREAD1); this->fireProjectile((Vector){-5, 10, 0}, 0); this->lastFireTime = 0; this->projectileAnim = myGame.getAnimation(ANIM_PLAYERSPREAD3); this->fireProjectile((Vector){5, 10, 0}, 0); this->lastFireTime = 0; this->projectileAnim = myGame.getAnimation(ANIM_PLAYERSPREAD2); this->fireProjectile((Vector){0, 10, 0}, 0); this->lastFireTime = SDL_GetTicks(); myGame.playSound(this->projectileSound); this->removeState(STATE_FIRING); } if ( SDL_GetTicks() - this->lastFireTime > status.weaponSpeed && (this->projectileAnim != NULL) ) { //std::cerr << "TRYING TO FIRE\n"; shotActor = new Projectile(); if ( shotActor == NULL ) { std::cerr << "firePlayerLaser BAILING OUT for NULL Projectile!\n"; return; } //std::cerr << "Got new projectile\n"; this->lastFireTime = SDL_GetTicks(); shotActor->addAnimation(this->projectileAnim, STATE_DEFAULT); shotActor->addAnimation(NULL, STATE_DYING); shotActor->addAnimation(NULL, STATE_DEAD); Vector playerPos = this->getPosition(); laserFrame = shotActor->nextFrame(); playerFrame = this->nextFrame(); if ( laserFrame == NULL || playerFrame == NULL ) { return; } shotActor->setPosition((Vector){(playerPos.x + ((playerFrame->w/2) - (laserFrame->w/2))), playerPos.y, playerPos.z}); if ( velocity.x < 0 ) { shotActor->addState(STATE_MOVELEFT); velocity.x = -(velocity.x); } else if ( velocity.x > 0 ) shotActor->addState(STATE_MOVERIGHT); if ( (this->userType & ACTOR_TEAM_PLAYER) == ACTOR_TEAM_PLAYER ) shotActor->addState(STATE_MOVEUP); else if ( ((this->userType & ENEMYTYPE_ENEMY4 ) == ENEMYTYPE_ENEMY4) && (this->target != NULL) && (this->target->getPosition().y < this->position.y) ) { shotActor->addState(STATE_MOVEUP); } else shotActor->addState(STATE_MOVEDOWN); shotActor->setVelocity((Vector){velocity.x, velocity.y, velocity.z}); shotActor->setUserType((this->userType & ACTOR_TEAMMASK) | ACTORTYPE_PROJECTILE); shotActor->damage = this->weaponDamage; shotActor->parent = this; //std::cerr << "Setting player's laser bolt to do " << shotActor->damage << " points of damage\n"; gameDisplay.addActor(shotActor, LAYER_SPRITE2); if ( playSound == 1) myGame.playSound(this->projectileSound); gameDisplay.colliders.push_back(shotActor); std::cerr << "Added new laser beam " << shotActor << " to colliders list.\n"; } } void Character::collide(Character *ptr) { std::cerr << "CHARACTER [" << this << "] I AM COLLIDING WITH " << ptr << "\n"; if ( ptr != NULL && (this->state != STATE_DYING && this->state != STATE_DEAD) && (!ptr->hasState(STATE_DYING) && !ptr->hasState(STATE_DEAD))) { std::cerr << "I DID " << this->damage << " POINTS OF DAMAGE TO " << ptr << "\n"; ptr->health -= this->damage; } else if ( ptr == NULL ) { std::cerr << " I CANNOT COLLIDE WITH NULL\n"; } else { std::cerr << "I AM DEAD, I CAN'T COLLIDE WITH SHIT\n"; } } void Projectile::collide(Character *ptr) { //std::cerr << "PROJECTILE [" << this << "] I AM COLLIDING WITH " << ptr << "\n"; if ( ptr != NULL && (this->state != STATE_DYING && this->state != STATE_DEAD) && (!ptr->hasState(STATE_DYING) && !ptr->hasState(STATE_DEAD)) && ((ptr->getUserType() & ACTOR_TEAM_POWERUP) != ACTOR_TEAM_POWERUP) ) { //std::cerr << "I DID " << this->damage << " POINTS OF DAMAGE TO " << ptr << "\n"; ptr->health = ptr->health - this->damage; if ( (ptr->getUserType() & ACTOR_TEAMMASK) != (this->getUserType() & ACTOR_TEAMMASK) ) { //std::cerr << "Projectile " << this << " with userType " << this->getUserType() << " is killing itself against an object with userType " << ptr->getUserType() << "!\n"; this->state = STATE_DEAD; } if ( this->parent != NULL && ((ptr->getUserType() & ACTORTYPE_PROJECTILE) != ACTORTYPE_PROJECTILE) ) { ((Character *)this->parent)->score += ptr->score; } } } void Player::collide(Character *ptr) { Game &game = Game::NewSingleton(); Character::collide(ptr); if ( (ptr->getUserType() & ACTOR_TEAM_POWERUP) == ACTOR_TEAM_POWERUP ) { if ( ((ptr->getUserType() & POWERUP_ONEUP) == POWERUP_ONEUP) && this->lives < 4 ) { this->lives += 1; } else if ( (ptr->getUserType() & POWERUP_BIGSHIP) == POWERUP_BIGSHIP ) { this->addAnimation(game.getAnimation(ANIM_PLAYERDOUBLE), STATE_DEFAULT); this->projectileAnim = game.getAnimation(ANIM_PLAYERLASERDOUBLE); } else if ( (ptr->getUserType() & POWERUP_SHIELDRECHARGE) == POWERUP_SHIELDRECHARGE ) { this->health = 100; } else if ( (ptr->getUserType() & POWERUP_SPREADSHOT) == POWERUP_SPREADSHOT ) { this->addState(STATE_SPREADSHOT); } ptr->setState(STATE_DEAD); } } void Player::update() { GameOptions &opts = GameOptions::NewSingleton(); //std::cerr << "During update player health is " << this->health << "\n"; if ( this->playerDieTimer != 0 && this->state != STATE_DYING ) { // without this, input from the player will make us reappear on the screen this->state = STATE_DYING; } if ( this->health <= 0 && (this->state != STATE_DYING && this->state != STATE_DEAD)) { this->setState(STATE_DYING); this->playerDieTimer = SDL_GetTicks(); } else if ( this->state == STATE_DYING && (SDL_GetTicks() - this->playerDieTimer < 5000) ) { return; } else if ( (this->state == STATE_DYING || this->state == STATE_DEAD)&& (SDL_GetTicks() - this->playerDieTimer > 5000) && (this->lives > -1) ) { this->setState(STATE_NONE); this->lives -= 1; this->playerDieTimer = 0; this->health = opts.playerStartHealth; } Actor::update(); }