Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
94 KB
Referenced Files
None
Subscribers
None
diff --git a/src/BaseCreatureEntity.cpp b/src/BaseCreatureEntity.cpp
index 43599c8..e0f1bf4 100644
--- a/src/BaseCreatureEntity.cpp
+++ b/src/BaseCreatureEntity.cpp
@@ -1,344 +1,346 @@
#include "BaseCreatureEntity.h"
#include "sfml_game/ImageManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
BaseCreatureEntity::BaseCreatureEntity(sf::Texture* image, float x = 0.0f, float y = 0.0f, int spriteWidth = -1, int spriteHeight = -1)
: CollidingSpriteEntity (image, x, y, spriteWidth, spriteHeight )
{
hurting = false;
hurtingType = ShotTypeStandard;
shadowFrame = -1;
setMap(game().getCurrentMap(), TILE_WIDTH, TILE_HEIGHT, OFFSET_X, OFFSET_Y);
hpDisplay = 0;
movingStyle = movWalking;
for (int i = 0; i < NB_SPECIAL_STATES; i++)
{
specialState[i].type = (enumSpecialState)i;
specialState[i].resistance = ResistanceStandard;
specialState[i].active = false;
specialState[i].timer = 0.0f;
+ specialState[i].level = 0;
}
recoil.active = false;
facingDirection = 2;
}
int BaseCreatureEntity::getHp()
{
return hp;
}
int BaseCreatureEntity::getHpMax()
{
return hpMax;
}
void BaseCreatureEntity::setHp(int hp)
{
this->hp = hp;
}
void BaseCreatureEntity::setHpMax(int hpMax)
{
this->hpMax = hpMax;
}
int BaseCreatureEntity::getHpDisplay()
{
return hpDisplay;
}
IntCoord BaseCreatureEntity::getCurrentTile()
{
int xMap = (x - OFFSET_X) / TILE_WIDTH;
int yMap = (y - OFFSET_Y) / TILE_HEIGHT;
return (IntCoord(xMap, yMap));
}
BaseCreatureEntity::enumMovingStyle BaseCreatureEntity::getMovingStyle()
{
return movingStyle;
}
float BaseCreatureEntity::animateStates(float delay)
{
for (int i = 0; i < NB_SPECIAL_STATES; i++)
{
if (specialState[i].active)
{
specialState[i].timer -= delay;
if (specialState[i].timer <= 0.0f) specialState[i].active = false;
}
}
- if (specialState[SpecialStateIce].active) delay *= STATUS_FROZEN_MULT;
+ if (specialState[SpecialStateIce].active) delay *= STATUS_FROZEN_MULT[specialState[SpecialStateIce].level];
return delay;
}
void BaseCreatureEntity::animateColors(float delay)
{
// no color
sprite.setColor(sf::Color(255, 255, 255, 255 ));
if (hurting and hp > 0)
{
hurtingDelay -= delay;
if (hurtingDelay > 0.0f)
{
int fadeColor = (sf::Uint8)((HURTING_DELAY - hurtingDelay) * 255);
if (hurtingDelay > HURTING_DELAY) fadeColor = 0;
if (hurtingType == ShotTypeIce)
sprite.setColor(sf::Color(fadeColor, fadeColor, 255, 255 )); // blue
else
sprite.setColor(sf::Color(255, fadeColor, fadeColor, 255 )); // red
}
else
{
hurting = false;
sprite.setColor(sf::Color(255, 255, 255, 255 ));
}
}
if (specialState[SpecialStateIce].active) sprite.setColor(sf::Color(100, 100, 255, 255 ));
}
void BaseCreatureEntity::animateRecoil(float delay)
{
// recoil
if (recoil.active)
{
recoil.velocity.x *= 0.97f;
recoil.velocity.y *= 0.97f;
recoil.timer -= delay;
if (recoil.timer <= 0.0f)
{
recoil.active = false;
computeFacingDirection();
// TODO ?
}
}
}
void BaseCreatureEntity::animatePhysics(float delay)
{
velocity.x *= viscosity;
velocity.y *= viscosity;
float velx = velocity.x;
float vely = velocity.y;
if (recoil.active)
{
if (recoil.stun)
{
velx = 0.0f;
vely = 0.0f;
}
velx += recoil.velocity.x;
vely += recoil.velocity.y;
}
spin *= viscosity;
angle += spin * delay;
if ((int)velx > 0)
{
x += velx * delay;
if (collideWithMap(DIRECTION_LEFT))
{
x = (float)((int)x);
while (collideWithMap(DIRECTION_LEFT))
x--;
collideMapRight();
}
else if (x > map->getWidth() * tileWidth + offsetX)
{
exitMap(DIRECTION_RIGHT);
}
}
else if ((int)velx < 0)
{
x += velx * delay;
if (collideWithMap(DIRECTION_RIGHT))
{
x = (float)((int)x);
while (collideWithMap(DIRECTION_RIGHT))
x++;
collideMapLeft();
}
else if (x < offsetX)
{
exitMap(DIRECTION_LEFT);
}
}
vely += weight * delay;
if ( vely > maxY) vely = maxY;
if ((int)vely > 0)
{
y += vely * delay;
if (collideWithMap(DIRECTION_BOTTOM))
{
y = (float)((int)y);
while (collideWithMap(DIRECTION_BOTTOM))
y--;
collideMapBottom();
}
}
else if ((int)vely < 0)
{
y += vely * delay;
if (collideWithMap(DIRECTION_TOP))
{
y = (float)((int)y);
while (collideWithMap(DIRECTION_TOP))
y++;
collideMapTop();
}
}
if (lifetime > 0)
{
if (age >= lifetime) isDying = true;
}
age += delay;
}
void BaseCreatureEntity::animate(float delay)
{
if (hpDisplay > hp) hpDisplay--;
else if (hpDisplay < hp) hpDisplay++;
delay = animateStates(delay);
animateColors(delay);
animateRecoil(delay);
animatePhysics(delay);
z = y + height/2;
}
void BaseCreatureEntity::render(sf::RenderTarget* app)
{
if (!isDying && shadowFrame > -1)
{
// shadow
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
}
CollidingSpriteEntity::render(app);
#ifdef SHOW_BOUNDING_BOX
sf::Vertex line[] =
{
sf::Vertex(sf::Vector2f(boundingBox.left, boundingBox.top)),
sf::Vertex(sf::Vector2f(boundingBox.left + boundingBox.width, boundingBox.top)),
sf::Vertex(sf::Vector2f(boundingBox.left + boundingBox.width, boundingBox.top)),
sf::Vertex(sf::Vector2f(boundingBox.left + boundingBox.width, boundingBox.top + boundingBox.height)),
sf::Vertex(sf::Vector2f(boundingBox.left + boundingBox.width, boundingBox.top + boundingBox.height)),
sf::Vertex(sf::Vector2f(boundingBox.left, boundingBox.top + boundingBox.height)),
sf::Vertex(sf::Vector2f(boundingBox.left, boundingBox.top + boundingBox.height)),
sf::Vertex(sf::Vector2f(boundingBox.left, boundingBox.top))
};
app->draw(line, 8, sf::Lines);
#endif
}
void BaseCreatureEntity::calculateBB()
{
}
bool BaseCreatureEntity::collideWithMap(int direction)
{
calculateBB();
int xTile0 = (boundingBox.left - offsetX) / tileWidth;
int xTilef = (boundingBox.left + boundingBox.width - offsetX) / tileWidth;
int yTile0 = (boundingBox.top - offsetY) / tileHeight;
int yTilef = (boundingBox.top + boundingBox.height - offsetY) / tileHeight;
if (boundingBox.top < 0) yTile0 = -1;
for (int xTile = xTile0; xTile <= xTilef; xTile++)
for (int yTile = yTile0; yTile <= yTilef; yTile++)
{
if (movingStyle == movWalking)
{
if ( dynamic_cast<DungeonMap*>(map)->isWalkable(xTile, yTile) == false ) return true;
}
else if (movingStyle == movFlying)
{
if ( dynamic_cast<DungeonMap*>(map)->isFlyable(xTile, yTile) == false ) return true;
}
}
return false;
}
-bool BaseCreatureEntity::hurt(int damages, enumShotType hurtingType)
+bool BaseCreatureEntity::hurt(int damages, enumShotType hurtingType, int level = 1)
{
hurting = true;
hurtingDelay = HURTING_DELAY;
this->hurtingType = hurtingType;
if (hurtingType == ShotTypeIce && specialState[SpecialStateIce].resistance > ResistanceImmune)
{
specialState[SpecialStateIce].active = true;
- specialState[SpecialStateIce].timer = STATUS_FROZEN_DELAY;
+ specialState[SpecialStateIce].timer = STATUS_FROZEN_DELAY[level];
+ specialState[SpecialStateIce].level = level;
}
hp -= damages;
if (hp <= 0)
{
hp = 0;
prepareDying();
}
return true;
}
void BaseCreatureEntity::prepareDying()
{
dying();
}
void BaseCreatureEntity::dying()
{
isDying = true;
}
void BaseCreatureEntity::computeFacingDirection()
{
if (abs((int)velocity.x) > 0 || abs((int)velocity.y) > 0)
{
if (abs((int)velocity.x) > abs((int)velocity.y))
{
if (velocity.x > 0.0f) facingDirection = 6;
else facingDirection = 4;
}
else
{
if (velocity.y > 0.0f) facingDirection = 2;
else facingDirection = 8;
}
}
}
void BaseCreatureEntity::giveRecoil(bool stun, Vector2D velocity, float timer)
{
if (!(recoil.active && recoil.stun))
{
recoil.active = true;
recoil.stun = stun;
recoil.velocity = velocity;
recoil.timer = timer;
}
}
void BaseCreatureEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
{
}
diff --git a/src/BaseCreatureEntity.h b/src/BaseCreatureEntity.h
index 839c58e..1b4b047 100644
--- a/src/BaseCreatureEntity.h
+++ b/src/BaseCreatureEntity.h
@@ -1,76 +1,77 @@
#ifndef BASECREATUREENTITY_H
#define BASECREATUREENTITY_H
#include "sfml_game/CollidingSpriteEntity.h"
#include "Constants.h"
const int NB_SPECIAL_STATES = 1;
class BaseCreatureEntity : public CollidingSpriteEntity
{
public:
BaseCreatureEntity(sf::Texture* image, float x, float y, int spriteWidth, int spriteHeight);
int getHp();
int getHpMax();
void setHp(int hp);
void setHpMax(int hpMax);
int getHpDisplay();
IntCoord getCurrentTile();
virtual void animate(float delay);
virtual float animateStates(float delay);
virtual void animateColors(float delay);
virtual void animateRecoil(float delay);
virtual void animatePhysics(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
virtual bool collideWithMap(int direction);
- virtual bool hurt(int damages, enumShotType hurtingType);
+ virtual bool hurt(int damages, enumShotType hurtingType, int level);
virtual void prepareDying();
virtual void dying();
enum enumMovingStyle { movWalking, movFlying};
virtual enumMovingStyle getMovingStyle();
enum enumBloodColor { bloodRed, bloodGreen};
enum enumSpecialState
{
SpecialStateIce // = 0
};
enum enumStateResistance { ResistanceImmune, ResistanceResistant, ResistanceStandard, ResistanceLow, ResistanceVeryLow};
- struct itemStuct
+ struct specialStateStuct
{
enumSpecialState type;
enumStateResistance resistance;
bool active;
float timer;
+ int level;
};
- itemStuct specialState[NB_SPECIAL_STATES];
+ specialStateStuct specialState[NB_SPECIAL_STATES];
virtual void giveRecoil(bool stun, Vector2D velocity, float timer);
virtual void inflictsRecoilTo(BaseCreatureEntity* targetEntity);
virtual void computeFacingDirection();
protected:
int hp;
int hpMax;
int hpDisplay;
float creatureSpeed;
int shadowFrame;
int facingDirection;
bool hurting;
float hurtingDelay;
enumShotType hurtingType;
enumBloodColor bloodColor;
enumMovingStyle movingStyle;
struct recoilStruct
{
bool active;
Vector2D velocity;
bool stun;
float timer;
} recoil;
private:
};
#endif // BASECREATUREENTITY_H
diff --git a/src/BoltEntity.cpp b/src/BoltEntity.cpp
index 43be80a..e080f76 100644
--- a/src/BoltEntity.cpp
+++ b/src/BoltEntity.cpp
@@ -1,218 +1,224 @@
#include "BoltEntity.h"
#include "Constants.h"
#include "DungeonMap.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
-BoltEntity::BoltEntity(sf::Texture* image, float x, float y, float boltLifeTime, enumShotType boltType) : CollidingSpriteEntity (image, x, y, BOLT_WIDTH, BOLT_HEIGHT)
+BoltEntity::BoltEntity(sf::Texture* image, float x, float y, float boltLifeTime, enumShotType boltType, int level = 1) : CollidingSpriteEntity (image, x, y, BOLT_WIDTH, BOLT_HEIGHT)
{
lifetime = boltLifeTime;
setDamages(INITIAL_BOLT_DAMAGES);
type = ENTITY_BOLT;
viscosity = 0.97f;
+ this->level = level;
if (boltType == ShotTypeLightning) viscosity = 0.98f;
frame = 0;
this->boltType = boltType;
switch (boltType)
{
case ShotTypeStandard: frame = 0; break;
case ShotTypeIce: frame = 2; break;
case ShotTypeStone: frame = 4; break;
case ShotTypeLightning: frame = 5; break;
case ShotTypeIllusion: frame = 3; break;
}
testWallsCollision = false;
}
int BoltEntity::getDamages()
{
return damages;
}
+unsigned int BoltEntity::getLevel()
+{
+ return level;
+}
+
void BoltEntity::setDamages(int damages)
{
this->damages = damages;
if (damages <= 4) renderScale = 0.8f;
else if (damages <= 8) renderScale = 0.85f;
else if (damages <= 12) renderScale = 0.9f;
else if (damages <= 16) renderScale = 1.0f;
else if (damages <= 20) renderScale = 1.1f;
else if (damages <= 24) renderScale = 1.2f;
else if (damages <= 30) renderScale = 1.3f;
else renderScale = 1.4f;
sprite.scale(renderScale, renderScale);
}
enumShotType BoltEntity::getBoltType()
{
return boltType;
}
void BoltEntity::animate(float delay)
{
SpriteEntity* trace = new SpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_BOLT), x, y, BOLT_WIDTH, BOLT_HEIGHT);
trace->setFading(true);
trace->setZ(y);
trace->setLifetime(0.2f);
trace->setShrinking(true, renderScale, renderScale);
trace->setType(16);
trace->setFrame(frame);
z = y + height;
testWallsCollision = true;
CollidingSpriteEntity::animate(delay);
testWallsCollision = false;
if ( (lifetime - age) < 0.2f)
{
if (age >= lifetime)
sprite.setColor(sf::Color(255, 255, 255, 0));
else
sprite.setColor(sf::Color(255, 255, 255, (sf::Uint8)((lifetime - age) / 0.2f * 255)));
}
if (((velocity.x)*(velocity.x) + (velocity.y)*(velocity.y)) < 1500.0f) isDying = true;
}
void BoltEntity::calculateBB()
{
int colSize = testWallsCollision ? 1 : 10;
boundingBox.left = x - colSize;
boundingBox.width = colSize * 2;
boundingBox.top = y - colSize;
boundingBox.height = colSize * 2;
}
void BoltEntity::collide()
{
isDying = true;
for (int i=0; i<5; i++)
{
Vector2D vel(40.0f + rand() % 50);
generateParticule(vel);
}
}
void BoltEntity::generateParticule(Vector2D vel)
{
SpriteEntity* trace = new SpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_BOLT), x, y, BOLT_WIDTH, BOLT_HEIGHT);
trace->setFading(true);
trace->setZ(y);
trace->setLifetime(0.5f);
trace->setScale(0.3f, 0.3f);
trace->setVelocity(vel);
trace->setViscosity(0.97f);
trace->setType(16);
trace->setFrame(frame);
}
bool BoltEntity::collideWithMap(int direction)
{
calculateBB();
int xTile0 = (boundingBox.left - offsetX) / tileWidth;
int xTilef = (boundingBox.left + boundingBox.width - offsetX) / tileWidth;
int yTile0 = (boundingBox.top - offsetY) / tileHeight;
int yTilef = (boundingBox.top + boundingBox.height - offsetY) / tileHeight;
if (boundingBox.top < 0) yTile0 = -1;
for (int xTile = xTile0; xTile <= xTilef; xTile++)
for (int yTile = yTile0; yTile <= yTilef; yTile++)
{
if (boltType != ShotTypeIllusion)
{
if ( dynamic_cast<DungeonMap*>(map)->isShootable(xTile, yTile) == false ) return true;
}
}
return false;
}
void BoltEntity::collideMapRight()
{
if (boltType == ShotTypeLightning)
{
velocity.x = -velocity.x;
}
else
{
velocity.x = 0.0f;
isDying = true;
SoundManager::getSoundManager()->playSound(SOUND_WALL_IMPACT);
for (int i=0; i<5; i++)
{
Vector2D vel(100.0f + rand() % 150);
if (vel.x > 0.0f) vel.x = - vel.x;
generateParticule(vel);
}
}
}
void BoltEntity::collideMapLeft()
{
if (boltType == ShotTypeLightning)
{
velocity.x = -velocity.x;
}
else
{
velocity.x = 0.0f;
isDying = true;
SoundManager::getSoundManager()->playSound(SOUND_WALL_IMPACT);
for (int i=0; i<5; i++)
{
Vector2D vel(100.0f + rand() % 150);
if (vel.x < 0.0f) vel.x = - vel.x;
generateParticule(vel);
}
}
}
void BoltEntity::collideMapTop()
{
if (boltType == ShotTypeLightning)
{
velocity.y = -velocity.y;
}
else
{
velocity.y = 0.0f;
isDying = true;
SoundManager::getSoundManager()->playSound(SOUND_WALL_IMPACT);
for (int i=0; i<5; i++)
{
Vector2D vel(100.0f + rand() % 150);
if (vel.y < 0.0f) vel.y = - vel.y;
generateParticule(vel);
}
}
}
void BoltEntity::collideMapBottom()
{
if (boltType == ShotTypeLightning)
{
velocity.y = -velocity.y;
}
else
{
velocity.y = 0.0f;
isDying = true;
SoundManager::getSoundManager()->playSound(SOUND_WALL_IMPACT);
for (int i=0; i<5; i++)
{
Vector2D vel(100.0f + rand() % 150);
if (vel.y > 0.0f) vel.y = - vel.y;
generateParticule(vel);
}
}
}
diff --git a/src/BoltEntity.h b/src/BoltEntity.h
index 61b3592..dfaec53 100644
--- a/src/BoltEntity.h
+++ b/src/BoltEntity.h
@@ -1,40 +1,42 @@
#ifndef BOLTENTITY_H
#define BOLTENTITY_H
#include "sfml_game/CollidingSpriteEntity.h"
#include "Constants.h"
/*! \class BoltEntity
* \brief bolt thrown by the player
*
* BoltEntity are the missile weapons thrown by the player.
* The can collide with an enemy (to hurt him) or with the walls.
*/
class BoltEntity : public CollidingSpriteEntity
{
public:
- BoltEntity(sf::Texture* image, float x, float y, float boltLifeTime, enumShotType boltType);
+ BoltEntity(sf::Texture* image, float x, float y, float boltLifeTime, enumShotType boltType, int level);
virtual void animate(float delay);
void collide();
void generateParticule(Vector2D vel);
int getDamages();
+ unsigned int getLevel();
void setDamages(int damages);
enumShotType getBoltType();
protected:
virtual void calculateBB();
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
virtual bool collideWithMap(int direction);
int damages;
float renderScale;
enumShotType boltType;
private:
bool testWallsCollision;
+ unsigned int level;
};
#endif // BOLTENTITY_H
diff --git a/src/Constants.h b/src/Constants.h
index ebc9536..e2db3be 100644
--- a/src/Constants.h
+++ b/src/Constants.h
@@ -1,295 +1,299 @@
/** This file is part of Witch Blast.
*
* Witch Blast 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, either version 3 of the License, or
* (at your option) any later version.
*
* Witch Blast 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 Witch Blast. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONSTANTS_H_INCLUDED
#define CONSTANTS_H_INCLUDED
// uncomment to show bounding box in the app
// #define SHOW_BOUNDING_BOX
#include <string>
const std::string APP_NAME = "Witch Blast";
const std::string APP_VERSION = "0.1.2";
const std::string CONFIG_FILE = "config.dat";
const std::string SAVE_FILE = "game.sav";
const std::string SAVE_VERSION = "SAVE_0.1.2.1";
// Client size
const int SCREEN_WIDTH = 970;
const int SCREEN_HEIGHT = 720;
// Tile set
const int TILE_WIDTH = 64;
const int TILE_HEIGHT = 64;
// Tile map offset
const int OFFSET_X = 5;
const int OFFSET_Y = 5;
const int MAP_WIDTH = 15;
const int MAP_HEIGHT = 9;
const int MENU_MAP_WIDTH = 16;
const int MENU_MAP_HEIGHT = 13;
const int GAME_WIDTH = MAP_WIDTH * TILE_WIDTH;
const int GAME_HEIGHT = MAP_HEIGHT * TILE_HEIGHT;
const int FLOOR_WIDTH = 13;
const int FLOOR_HEIGHT = 7;
const int ITEM_WIDTH = 32;
const int ITEM_HEIGHT = 32;
const int BOLT_WIDTH = 24;
const int BOLT_HEIGHT = 24;
const int BB_LEFT = 22;
const int BB_RIGHT = 22;
const int BB_TOP = 4;
const int BB_BOTTOM = 31;
const float FADE_IN_DELAY = 1.0f;
const float FADE_OUT_DELAY = 1.0f;
enum item_images {
IMAGE_PLAYER_BASE,
IMAGE_PLAYER_EQUIP,
IMAGE_PLAYER_COLLAR,
IMAGE_BOLT,
IMAGE_TILES,
IMAGE_RAT,
IMAGE_MINIMAP,
IMAGE_DOOR,
IMAGE_ITEMS,
IMAGE_ITEMS_EQUIP,
IMAGE_CHEST,
IMAGE_BAT,
IMAGE_FLOWER,
IMAGE_SLIME,
IMAGE_GIANT_SLIME,
IMAGE_KING_RAT,
IMAGE_BLOOD,
IMAGE_CORPSES,
IMAGE_CORPSES_BIG,
IMAGE_STAR,
IMAGE_STAR_2,
IMAGE_INTERFACE,
IMAGE_HUD_SHOTS,
IMAGE_PNJ,
IMAGE_FAIRY
};
enum sound_resources {
SOUND_STEP,
SOUND_BLAST_STANDARD,
SOUND_BLAST_FLOWER,
SOUND_DOOR_CLOSING,
SOUND_DOOR_OPENING,
SOUND_CHEST_OPENING,
SOUND_IMPACT,
SOUND_BONUS,
SOUND_DRINK,
SOUND_EAT,
SOUND_PLAYER_HIT,
SOUND_PLAYER_DIE,
SOUND_ENNEMY_DYING,
SOUND_COIN_PICK_UP,
SOUND_PAY,
SOUND_WALL_IMPACT,
SOUND_BIG_WALL_IMPACT,
SOUND_KING_RAT_1,
SOUND_KING_RAT_2,
SOUND_KING_RAT_DIE,
SOUND_SLIME_JUMP,
SOUND_SLIME_IMAPCT,
SOUND_SLIME_IMAPCT_WEAK,
SOUND_SLIME_SMASH,
SOUND_ICE_CHARGE,
SOUND_ELECTRIC_CHARGE,
SOUND_SHOT_SELECT,
SOUND_HEART
};
enum corpses_ressources{
FRAME_CORPSE_RAT,
FRAME_CORPSE_BAT,
FRAME_CORPSE_FLOWER,
FRAME_CORPSE_GREEN_RAT,
FRAME_CORPSE_SLIME,
FRAME_CORPSE_BLACK_RAT,
FRAME_CORPSE_KING_RAT,
FRAME_CORPSE_GIANT_SLIME
};
// Player game play
const float INITIAL_PLAYER_SPEED = 180.0f;
const int INITIAL_PLAYER_HP = 20;
const float INITIAL_PLAYER_FIRE_DELAY = 0.7f;
const float ACQUIRE_DELAY = 2.8f;
const float UNLOCK_DELAY = 1.0f;
const float INITIAL_BOLT_LIFE = 0.4f;
const int INITIAL_BOLT_DAMAGES = 8;
const float INITIAL_BOLT_VELOCITY = 700.0f;
const float FAIRY_SPEED = 180.0f;
const float FAIRY_FIRE_DELAY = 0.8f;
const float ICE_FAIRY_FIRE_DELAY = 1.3f;
const float FAIRY_BOLT_LIFE = 0.4f;
const int FAIRY_BOLT_DAMAGES = 8;
const float FAIRY_BOLT_VELOCITY = 700.0f;
enum chest_type_enum {
CHEST_BASIC,
CHEST_EXIT,
CHEST_FAIRY
};
// Artefact Info
const float ARTEFACT_RECT_WIDTH = 600.0f;
const float ARTEFACT_RECT_HEIGHT = 100.0f;
const float ARTEFACT_POS_Y = 450.0f;
const float ARTEFACT_BORDER = 8.0f;
const float ARTEFACT_ZOOM_TIME = 0.5f;
// shot types
enum enumShotType {
ShotTypeStandard,
ShotTypeIce,
ShotTypeIllusion,
ShotTypeStone,
ShotTypeLightning
};
-// status
-const float STATUS_FROZEN_DELAY = 5.0f; // how long the freeze occurs
-const float STATUS_FROZEN_BOLT_DELAY = 2.5f; // how long the freeze occurs
-const float STATUS_FROZEN_MULT = 0.33f; // speed multiplier (= 3 times slower)
-
+// special shots effects
+const int MAX_SHOT_LEVEL = 3;
+
+const float STATUS_FROZEN_DELAY[MAX_SHOT_LEVEL] // how long the freeze occurs
+ = { 4.0f, 5.0f, 6.0f };
+const float STATUS_FROZEN_BOLT_DELAY[MAX_SHOT_LEVEL] // how long the freeze occurs
+ = { 3.0f, 2.6f, 2.0f };
+const float STATUS_FROZEN_MULT[MAX_SHOT_LEVEL] // speed multiplier (= 3 times slower)
+ = { 0.38f, 0.33f, 0.28f };
// entity type
const int ENTITY_PLAYER = 1;
const int ENTITY_FAMILIAR = 2;
const int ENTITY_DOOR = 3;
const int ENTITY_ARTIFACT_DESCRIPTION = 9;
const int ENTITY_BLOOD = 11;
const int ENTITY_CORPSE = 12;
const int ENTITY_EFFECT = 13;
const int ENTITY_BOLT = 15;
const int ENTITY_ENNEMY_BOLT = 16;
const int ENTITY_PNJ = 17;
const int ENTITY_CHEST = 18;
const int ENTITY_ITEM = 19;
const int ENTITY_ENNEMY = 21;
const int ENTITY_ENNEMY_INVOCATED = 22;
const int ENTITY_ENNEMY_BOSS = 23;
const int ENTITY_ENNEMY_MAX = 23;
// monster type
enum monster_type_enum
{
MONSTER_RAT,
MONSTER_BAT,
MONSTER_EVIL_FLOWER,
MONSTER_SLIME,
MONSTER_BLACK_RAT,
MONSTER_KING_RAT
};
const float DOOR_OPEN_TIME = 1.0f;
const float DOOR_CLOSE_TIME = 1.0f;
// Rat
const float RAT_SPEED = 160.0f;
const int RAT_HP = 24;
const int RAT_DAMAGES = 5;
const int RAT_BB_LEFT = 14;
const int RAT_BB_WIDTH_DIFF = 28;
const int RAT_BB_TOP = 22;
const int RAT_BB_HEIGHT_DIFF = 22;
// Green Rat
const float GREEN_RAT_SPEED = 170.0f;
const int GREEN_RAT_HP = 16;
const int GREEN_RAT_DAMAGES = 5;
const float GREEN_RAT_FADE = 1.0f;
// Black Rat
const float BLACK_RAT_SPEED = 160.0f;
const int BLACK_RAT_HP = 24;
const int BLACK_RAT_DAMAGES = 5;
// Bat
const float BAT_SPEED = 250.0f;
const int BAT_HP = 8;
const int BAT_DAMAGES = 5;
const int BAT_BB_LEFT = 5;
const int BAT_BB_WIDTH_DIFF = 10;
const int BAT_BB_TOP = 2;
const int BAT_BB_HEIGHT_DIFF = 32;
// Evl Flower
const int EVIL_FLOWER_HP = 16;
const int EVIL_FLOWER_MELEE_DAMAGES = 8;
const int EVIL_FLOWER_MISSILE_DAMAGES = 5;
const int EVIL_FLOWER_BB_LEFT = 14;
const int EVIL_FLOWER_BB_WIDTH_DIFF = 28;
const int EVIL_FLOWER_BB_TOP = 22;
const int EVIL_FLOWER_BB_HEIGHT_DIFF = 22;
const float EVIL_FLOWER_FIRE_DELAY = 2.7f;
const float EVIL_FLOWER_FIRE_VELOCITY = 220.0f;
// Slime
const int SLIME_HP = 16;
const int SLIME_DAMAGES = 5;
const int SLIME_BB_LEFT = 13;
const int SLIME_BB_WIDTH_DIFF = 26;
const int SLIME_BB_TOP = 38;
const int SLIME_BB_HEIGHT_DIFF = 40;
// Giant Slime
const int GIANT_SLIME_HP = 650;
const int GIANT_SLIME_DAMAGES = 8;
const int GIANT_SLIME_MISSILE_DAMAGES = 6;
const float GIANT_SLIME_MISSILE_DELAY = 0.33f;
const float GIANT_SLIME_FIRE_VELOCITY = 200.0f;
const int GIANT_SLIME_BB_LEFT = 26;
const int GIANT_SLIME_BB_WIDTH_DIFF = 52;
const int GIANT_SLIME_BB_TOP = 64;
const int GIANT_SLIME_BB_HEIGHT_DIFF = 12;
const int GIANT_SLIME_SPEED = 85.0f;
// KingRat
const float KING_RAT_SPEED = 200.0f;
const float KING_RAT_RUNNING_SPEED = 600.0f;
const float KING_RAT_BERSERK_SPEED = 250.0f;
const float KING_RAT_RUNNING_RECOIL = 750.0f;
const int KING_RAT_HP = 700;
const int KING_RAT_DAMAGES = 8;
// EFFECTS
const float HURTING_DELAY = 0.4f;
const float HEART_BEAT_DELAY = 1.2f;
#endif // CONSTANTS_H_INCLUDED
diff --git a/src/EnnemyEntity.cpp b/src/EnnemyEntity.cpp
index 0f229b8..59e447c 100644
--- a/src/EnnemyEntity.cpp
+++ b/src/EnnemyEntity.cpp
@@ -1,172 +1,172 @@
#include "EnnemyEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include <iostream>
#include "WitchBlastGame.h"
EnnemyEntity::EnnemyEntity(sf::Texture* image, float x, float y)
: BaseCreatureEntity (image, x, y, 64, 64)
{
type = ENTITY_ENNEMY;
bloodColor = bloodRed;
z = y;
age = -0.001f * (rand()%800) - 0.4f;
}
void EnnemyEntity::animate(float delay)
{
if (canCollide()) testSpriteCollisions();
if (age > 0.0f)
BaseCreatureEntity::animate(delay);
else
age += delay;
}
void EnnemyEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2;
boundingBox.width = width;
boundingBox.top = (int)y - height / 2;
boundingBox.height = height;
}
void EnnemyEntity::collideMapRight()
{
velocity.x = 0.0f;
}
void EnnemyEntity::collideMapLeft()
{
velocity.x = 0.0f;
}
void EnnemyEntity::collideMapTop()
{
velocity.y = 0.0f;
}
void EnnemyEntity::collideMapBottom()
{
velocity.y = 0.0f;
}
void EnnemyEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (collideWithEntity(entity))
{
if (entity->getType() == ENTITY_PLAYER || entity->getType() == ENTITY_BOLT )
{
PlayerEntity* playerEntity = dynamic_cast<PlayerEntity*>(entity);
BoltEntity* boltEntity = dynamic_cast<BoltEntity*>(entity);
if (playerEntity != NULL && !playerEntity->isDead())
{
if (playerEntity->hurt(meleeDamages, ShotTypeStandard))
{
float xs = (x + playerEntity->getX()) / 2;
float ys = (y + playerEntity->getY()) / 2;
SpriteEntity* star = new SpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_STAR_2), xs, ys);
star->setFading(true);
star->setZ(y+ 100);
star->setLifetime(0.7f);
star->setType(16);
star->setSpin(400.0f);
}
inflictsRecoilTo(playerEntity);
}
else if (boltEntity != NULL && !boltEntity->getDying() && !isDying && boltEntity->getAge() > 0.05f)
{
boltEntity->collide();
- hurt(boltEntity->getDamages(), boltEntity->getBoltType());
+ hurt(boltEntity->getDamages(), boltEntity->getBoltType(), boltEntity->getLevel());
game().generateBlood(x, y, bloodColor);
SoundManager::getSoundManager()->playSound(SOUND_IMPACT);
float xs = (x + boltEntity->getX()) / 2;
float ys = (y + boltEntity->getY()) / 2;
SpriteEntity* star = new SpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_STAR_2), xs, ys);
star->setFading(true);
star->setZ(y+ 100);
star->setLifetime(0.7f);
star->setType(16);
star->setSpin(400.0f);
if (boltEntity->getBoltType() == ShotTypeStone)
{
Vector2D recoilVector = Vector2D(boltEntity->getX(), boltEntity->getY()).vectorTo(Vector2D(x, y), 110 );
giveRecoil(true, recoilVector, 0.15f);
}
}
}
else // collision with other enemy ?
{
if (entity->getType() >= ENTITY_ENNEMY && entity->getType() <= ENTITY_ENNEMY_MAX)
{
if (this != entity)
collideWithEnnemy(entity);
}
}
}
/*
if (x < OFFSET_X + TILE_WIDTH)
{
x = OFFSET_X + TILE_WIDTH;
if (velocity.x > 1.0f) velocity.x = -velocity.x;
else if (velocity.x > -1.0f) velocity.x = -1.0f;
}
else if (x > OFFSET_X + TILE_WIDTH * (MAP_WIDTH - 1))
{
x = OFFSET_X + TILE_WIDTH * (MAP_WIDTH - 1);
if (velocity.x < -1.0f) velocity.x = -velocity.x;
else if (velocity.x < 1.0f) velocity.x = 1.0f;
}
if (y < OFFSET_Y + TILE_HEIGHT)
{
y = OFFSET_Y + TILE_HEIGHT;
if (velocity.y > 1.0f) velocity.y = -velocity.y;
else if (velocity.y > -1.0f) velocity.y = -1.0f;
}
else if (y > OFFSET_Y + TILE_HEIGHT * (MAP_HEIGHT - 1))
{
y = OFFSET_Y + TILE_HEIGHT * (MAP_HEIGHT - 1);
if (velocity.y < -1.0f) velocity.y = -velocity.y;
else if (velocity.y < 1.0f) velocity.y = 1.0f;
}*/
}
void EnnemyEntity::collideWithEnnemy(GameEntity* collidingEntity)
{
// To implement the behaviour when colliding with another ennemy
}
void EnnemyEntity::dying()
{
isDying = true;
SpriteEntity* deadRat = new SpriteEntity(ImageManager::getImageManager()->getImage(3), x, y, 64, 64);
deadRat->setZ(OFFSET_Y);
deadRat->setFrame(2);
deadRat->setType(13);
}
void EnnemyEntity::drop()
{
if (rand() % 5 == 0)
{
ItemEntity* newItem = new ItemEntity(ItemCopperCoin, x, y);
newItem->setMap(map, TILE_WIDTH, TILE_HEIGHT, OFFSET_X, OFFSET_Y);
newItem->setVelocity(Vector2D(100.0f + rand()% 250));
newItem->setViscosity(0.96f);
}
}
bool EnnemyEntity::canCollide()
{
return true;
}
diff --git a/src/EvilFlowerEntity.cpp b/src/EvilFlowerEntity.cpp
index 3dba4f8..32fad74 100644
--- a/src/EvilFlowerEntity.cpp
+++ b/src/EvilFlowerEntity.cpp
@@ -1,100 +1,100 @@
#include "EvilFlowerEntity.h"
#include "BoltEntity.h"
#include "EnnemyBoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include <math.h>
EvilFlowerEntity::EvilFlowerEntity(float x, float y)
: EnnemyEntity (ImageManager::getImageManager()->getImage(IMAGE_FLOWER), x, y)
{
hp = EVIL_FLOWER_HP;
meleeDamages = EVIL_FLOWER_MELEE_DAMAGES;
setSpin(50.0f);
frame = 0;
type = 23;
bloodColor = bloodGreen;
//shadowFrame = 2;
fireDelay = EVIL_FLOWER_FIRE_DELAY;
age = -1.0f + (rand() % 2500) * 0.001f;
}
void EvilFlowerEntity::animate(float delay)
{
float flowerDelay = delay;
- if (specialState[SpecialStateIce].active) flowerDelay = delay * STATUS_FROZEN_MULT;
+ if (specialState[SpecialStateIce].active) flowerDelay = delay * STATUS_FROZEN_MULT[specialState[SpecialStateIce].level];
if (fireDelay < 0.7f) setSpin(500.0f);
else if (fireDelay < 1.4f) setSpin(120.0f);
else setSpin(50.0f);
EnnemyEntity::animate(delay);
angle += spin * flowerDelay;
if (age > 0.0f)
{
fireDelay -= flowerDelay;
if (fireDelay <= 0.0f)
{
fireDelay = EVIL_FLOWER_FIRE_DELAY;
fire();
}
}
}
void EvilFlowerEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2 + EVIL_FLOWER_BB_LEFT;
boundingBox.width = width - EVIL_FLOWER_BB_WIDTH_DIFF;
boundingBox.top = (int)y - height / 2 + EVIL_FLOWER_BB_TOP;
boundingBox.height = height - EVIL_FLOWER_BB_HEIGHT_DIFF;
}
void EvilFlowerEntity::dying()
{
isDying = true;
SpriteEntity* deadFlower = new SpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_CORPSES), x, y, 64, 64);
deadFlower->setZ(OFFSET_Y);
deadFlower->setFrame(FRAME_CORPSE_FLOWER);
deadFlower->setType(ENTITY_CORPSE);
for (int i = 0; i < 4; i++) game().generateBlood(x, y, bloodColor);
drop();
SoundManager::getSoundManager()->playSound(SOUND_ENNEMY_DYING);
}
void EvilFlowerEntity::fire()
{
SoundManager::getSoundManager()->playSound(SOUND_BLAST_FLOWER);
EnnemyBoltEntity* bolt = new EnnemyBoltEntity
(ImageManager::getImageManager()->getImage(IMAGE_BOLT), x, y + 10);
bolt->setFrame(1);
bolt->setMap(map, TILE_WIDTH, TILE_HEIGHT, OFFSET_X, OFFSET_Y);
float flowerFireVelocity = EVIL_FLOWER_FIRE_VELOCITY;
if (specialState[SpecialStateIce].active) flowerFireVelocity *= 0.5f;
bolt->setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), flowerFireVelocity ));
}
void EvilFlowerEntity::render(sf::RenderTarget* app)
{
sprite.setPosition(x, y);
float savedAngle = sprite.getRotation();
sprite.setRotation(0.0f);
// shadow
sprite.setTextureRect(sf::IntRect(width * 2, 0, width, height));
app->draw(sprite);
sprite.setTextureRect(sf::IntRect(width, 0, width, height));
app->draw(sprite);
sprite.setRotation(savedAngle);
EnnemyEntity::render(app);
}
diff --git a/src/FairyEntity.cpp b/src/FairyEntity.cpp
index faa6902..4b0778b 100644
--- a/src/FairyEntity.cpp
+++ b/src/FairyEntity.cpp
@@ -1,148 +1,149 @@
#include "FairyEntity.h"
#include "BoltEntity.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "sfml_game/MyTools.h"
#include <iostream>
FairyEntity::FairyEntity(float x, float y, enumFamiliar fairyType) : SpriteEntity (ImageManager::getImageManager()->getImage(IMAGE_FAIRY), x, y, 48, 72)
{
this->x = x;
this->y = y;
this->setFrame(0);
imagesProLine = 6;
this->parentEntity = game().getPlayer();
type = ENTITY_FAMILIAR;
this->fairyType = fairyType;
fireDelay = -1.0f;
facingDirection = 2;
+ shotLevel = 1;
switch (fairyType)
{
case FamiliarFairy: shotType = ShotTypeStandard; fairyFireDelay = FAIRY_FIRE_DELAY; break;
case FamiliarFairyIce: shotType = ShotTypeIce; fairyFireDelay = ICE_FAIRY_FIRE_DELAY; break;
case FamiliarNone: break;
}
}
void FairyEntity::animate(float delay)
{
z = y + height;
if (fireDelay > 0) fireDelay -= delay;
float dist2 = (x - parentEntity->getX()) * (x - parentEntity->getX()) + (y - parentEntity->getY()) * (y - parentEntity->getY());
if (dist2 > 15000.0f)
{
float tan = (parentEntity->getX() - x) / (parentEntity->getY() - y);
float angle = atan(tan);
if (parentEntity->getY() > y)
setVelocity(Vector2D(sin(angle) * FAIRY_SPEED, cos(angle) * FAIRY_SPEED));
else
setVelocity(Vector2D(-sin(angle) * FAIRY_SPEED, -cos(angle) * FAIRY_SPEED));
viscosity = 1.0f;
}
else if (dist2 < 50000.0f)
{
viscosity = 0.96f;
}
checkCollisions();
computeFacingDirection();
isMirroring = false;
frame = ((int)(age * 10.0f)) % 2;
if (facingDirection == 8) frame += 2;
else if (facingDirection == 4) frame += 4;
else if (facingDirection == 6)
{
frame += 4;
isMirroring = true;
}
frame += (int)(fairyType) * 6;
SpriteEntity::animate(delay);
}
void FairyEntity::fire(int dir, GameMap* map)
{
if (fireDelay <= 0.0f)
{
SoundManager::getSoundManager()->playSound(SOUND_BLAST_STANDARD);
fireDelay = fairyFireDelay;
float velx = 0.0f;
float vely = 0.0f;
if (dir == 4) velx = - FAIRY_BOLT_VELOCITY;
if (dir == 6) velx = + FAIRY_BOLT_VELOCITY;
if (dir == 2) vely = + FAIRY_BOLT_VELOCITY;
if (dir == 8) vely = - FAIRY_BOLT_VELOCITY;
- BoltEntity* bolt = new BoltEntity(ImageManager::getImageManager()->getImage(IMAGE_BOLT), x, y, FAIRY_BOLT_LIFE, shotType);
+ BoltEntity* bolt = new BoltEntity(ImageManager::getImageManager()->getImage(IMAGE_BOLT), x, y, FAIRY_BOLT_LIFE, shotType, shotLevel);
bolt->setMap(map, TILE_WIDTH, TILE_HEIGHT, OFFSET_X, OFFSET_Y);
bolt->setDamages(FAIRY_BOLT_DAMAGES);
bolt->setVelocity(Vector2D(velx, vely));
}
}
void FairyEntity::computeFacingDirection()
{
if (parentEntity->getFireDirection() != 5)
{
facingDirection = parentEntity->getFireDirection();
}
else if (abs((int)velocity.x) > 0 || abs((int)velocity.y) > 0)
{
if (abs((int)velocity.x) > abs((int)velocity.y))
{
if (velocity.x > 0.0f) facingDirection = 6;
else facingDirection = 4;
}
else
{
if (velocity.y > 0.0f) facingDirection = 2;
else facingDirection = 8;
}
}
}
void FairyEntity::checkCollisions()
{
int n = parentEntity->getFairieNumber();
if (n > 1)
{
for (int i = 0; i < n; i++)
{
FairyEntity* fairy = parentEntity->getFairy(i);
if (this != fairy)
{
bool isColliding = true;
int dist = 40;
if (x > fairy->getX() + dist || x < fairy->getX() - dist
|| y > fairy->getY() + dist || y < fairy->getY() - dist)
isColliding = false;
if (isColliding)
{
Vector2D vel = (Vector2D(fairy->getX(), fairy->getY()).vectorTo(Vector2D(x, y), FAIRY_SPEED * 0.5f));
velocity.x += vel.x;
velocity.y += vel.y;
fairy->setVelocity(Vector2D(fairy->getVelocity().x - vel.x, fairy->getVelocity().y - vel.y));
}
}
}
}
}
diff --git a/src/FairyEntity.h b/src/FairyEntity.h
index 76e998f..77ac8cc 100644
--- a/src/FairyEntity.h
+++ b/src/FairyEntity.h
@@ -1,29 +1,30 @@
#ifndef FAIRYENTITY_H
#define FAIRYENTITY_H
#include "sfml_game/SpriteEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/GameMap.h"
class FairyEntity : public SpriteEntity
{
public:
FairyEntity(float x, float y, enumFamiliar fairyType);
virtual void animate(float delay);
void fire(int dir, GameMap* map);
protected:
private:
PlayerEntity* parentEntity;
float fireDelay;
int facingDirection;
enumFamiliar fairyType;
enumShotType shotType;
float fairyFireDelay;
+ unsigned int shotLevel;
void computeFacingDirection();
void checkCollisions();
};
#endif // MAGNETENTITY_H
diff --git a/src/KingRatEntity.cpp b/src/KingRatEntity.cpp
index 9aaa5ea..823e370 100644
--- a/src/KingRatEntity.cpp
+++ b/src/KingRatEntity.cpp
@@ -1,374 +1,366 @@
#include "KingRatEntity.h"
#include "GreenRatEntity.h"
#include "BoltEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include <iostream>
KingRatEntity::KingRatEntity(float x, float y)
: EnnemyEntity (ImageManager::getImageManager()->getImage(IMAGE_KING_RAT), x, y)
{
width = 128;
height = 128;
creatureSpeed = KING_RAT_SPEED;
velocity = Vector2D(creatureSpeed);
hp = KING_RAT_HP;
hpDisplay = hp;
hpMax = KING_RAT_HP;
meleeDamages = KING_RAT_DAMAGES;
type = ENTITY_ENNEMY_BOSS;
bloodColor = bloodRed;
shadowFrame = 4;
frame = 0;
if (game().getPlayerPosition().x > x) sprite.setScale(-1.0f, 1.0f);
sprite.setOrigin(64.0f, 64.0f);
state = 0;
timer = 2.0f + (rand() % 40) / 10.0f;
age = -2.0f;
berserkDelay = 1.0f + rand()%5 * 0.1f;
hasBeenBerserk = false;
specialState[SpecialStateIce].resistance = ResistanceImmune;
}
void KingRatEntity::animate(float delay)
{
if (age <= 0.0f)
{
age += delay;
return;
}
float timerMult = 1.0f;
if (hp <= hpMax / 4)
{
creatureSpeed = KING_RAT_SPEED * 1.4f;
timerMult = 0.7f;
}
else if (hp <= hpMax / 2)
{
creatureSpeed = KING_RAT_SPEED * 1.2f;
timerMult = 0.85f;
}
else
{
creatureSpeed = KING_RAT_SPEED;
}
if (state == 5)
{
velocity.x *= 0.965f;
velocity.y *= 0.965f;
}
else
{
if (velocity.x > 0.1f) sprite.setScale(-1.0f, 1.0f);
else if (velocity.x < -0.1f) sprite.setScale(1.0f, 1.0f);
}
timer -= delay;
if (timer <= 0.0f)
{
if (state == 0)
{
state = 1;
// generate rats
generateGreenRats();
SoundManager::getSoundManager()->playSound(SOUND_KING_RAT_1);
timer = 2.0f;
velocity.x = 0.0f;
velocity.y = 0.0f;
}
else if (state == 1) // generate rats
{
// to normal or berserk
if (hp < hpMax / 4 && !hasBeenBerserk)
{
hasBeenBerserk = true;
timer = 12.0f;
state = 6;
velocity = Vector2D(KING_RAT_BERSERK_SPEED);
SoundManager::getSoundManager()->playSound(SOUND_KING_RAT_2);
}
else
{
timer = 7.0f * timerMult;
velocity = Vector2D(creatureSpeed);
state = 2;
}
}
else if (state == 2) // normal -> rush
{
state = 3;
// angry
timer = 2.0f;
velocity.x = 0.0f;
velocity.y = 0.0f;
SoundManager::getSoundManager()->playSound(SOUND_KING_RAT_2);
}
else if (state == 3) // normal -> rush
{
state = 4;
// rush
timer = 12.0f;
float tan = (game().getPlayer()->getX() - x) / (game().getPlayer()->getY() - y);
float angle = atan(tan);
if (game().getPlayer()->getY() > y)
setVelocity(Vector2D(sin(angle) * KING_RAT_RUNNING_SPEED,
cos(angle) * KING_RAT_RUNNING_SPEED));
else
setVelocity(Vector2D(-sin(angle) * KING_RAT_RUNNING_SPEED,
-cos(angle) * KING_RAT_RUNNING_SPEED));
}
else if (state == 5) // wall impact
{
// to normal or berserk
if (hp < hpMax / 4 && !hasBeenBerserk)
{
hasBeenBerserk = true;
timer = 12.0f;
state = 6;
velocity = Vector2D(KING_RAT_BERSERK_SPEED);
SoundManager::getSoundManager()->playSound(SOUND_KING_RAT_2);
}
else
{
timer = 7.0f * timerMult;
velocity = Vector2D(creatureSpeed);
state = 0;
}
}
else if (state == 6)
{
timer = 7.0f * timerMult;
velocity = Vector2D(creatureSpeed);
state = 0;
}
}
if (state == 6)
{
berserkDelay -= delay;
if (berserkDelay <= 0.0f)
{
berserkDelay = 0.8f + (rand()%10) / 10.0f;
SoundManager::getSoundManager()->playSound(SOUND_KING_RAT_2);
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(),KING_RAT_BERSERK_SPEED ));
}
}
frame = 0;
if (state == 1)
frame = 3;
else if (state == 3 || state == 6)
{
frame = 3; //0;
int r = ((int)(age * 10.0f)) % 2;
if (r == 0)
sprite.setScale(-1.0f, 1.0f);
else
sprite.setScale(1.0f, 1.0f);
}
else if (state == 4)
{
int r = ((int)(age * 7.5f)) % 4;
if (r == 1) frame = 1;
else if (r == 3) frame = 2;
}
else if (state == 5)
{
frame = 0;
}
else
{
int r = ((int)(age * 5.0f)) % 4;
if (r == 1) frame = 1;
else if (r == 3) frame = 2;
}
EnnemyEntity::animate(delay);
}
-bool KingRatEntity::hurt(int damages)
+bool KingRatEntity::hurt(int damages, enumShotType hurtingType, int level)
{
- hurting = true;
- hurtingDelay = HURTING_DELAY;
-
+ int newDamages = damages;
+ // berserk state protects
if (state == 6)
- hp -= damages / 4;
- else
- hp -= damages;
+ damages = damages / 4;
- if (hp <= 0)
- {
- hp = 0;
- dying();
- }
- return true;
+ return BaseCreatureEntity::hurt(damages, hurtingType, level);
}
void KingRatEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2 + 25;
boundingBox.width = width - 50;
boundingBox.top = (int)y - height / 2 + 25;
boundingBox.height = height - 35;
}
void KingRatEntity::afterWallCollide()
{
if (state == 4)
{
state = 5;
timer = 1.4f;
velocity.x *= 0.75f;
velocity.y *= 0.75f;
SoundManager::getSoundManager()->playSound(SOUND_BIG_WALL_IMPACT);
game().makeShake(0.75f);
}
}
void KingRatEntity::collideMapRight()
{
velocity.x = -velocity.x;
afterWallCollide();
}
void KingRatEntity::collideMapLeft()
{
velocity.x = -velocity.x;
afterWallCollide();
}
void KingRatEntity::collideMapTop()
{
velocity.y = -velocity.y;
afterWallCollide();
}
void KingRatEntity::collideMapBottom()
{
velocity.y = -velocity.y;
afterWallCollide();
}
void KingRatEntity::dying()
{
isDying = true;
SpriteEntity* deadRat = new SpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_CORPSES_BIG), x, y, 128, 128);
deadRat->setZ(OFFSET_Y);
deadRat->setFrame(FRAME_CORPSE_KING_RAT - FRAME_CORPSE_KING_RAT);
deadRat->setType(ENTITY_CORPSE);
for (int i = 0; i < 10; i++) game().generateBlood(x, y, bloodColor);
SoundManager::getSoundManager()->playSound(SOUND_KING_RAT_DIE);
ItemEntity* newItem = new ItemEntity(itemBossHeart, x, y);
//newItem->setMap(map, TILE_WIDTH, TILE_HEIGHT, OFFSET_X, OFFSET_Y);
newItem->setVelocity(Vector2D(100.0f + rand()% 250));
newItem->setViscosity(0.96f);
}
void KingRatEntity::generateGreenRats()
{
for (int i = 0; i < 5; i++)
{
float xr = x + -100 + rand() % 200;
float yr = y + -100 + rand() % 200;
if (xr > OFFSET_X + TILE_WIDTH * 1.5f && xr < OFFSET_X + TILE_WIDTH * (MAP_WIDTH - 2)
&& yr > OFFSET_Y + TILE_HEIGHT * 1.5f && yr < OFFSET_Y + TILE_HEIGHT * (MAP_HEIGHT - 2))
{
new GreenRatEntity(xr, yr);
}
else
i--;
}
}
void KingRatEntity::render(sf::RenderTarget* app)
{
EnnemyEntity::render(app);
if (state == 6)
{
int r = ((int)(age *12.0f)) % 2;
if (r == 0)
sprite.setTextureRect(sf::IntRect(1 * width, 1 * height, width, height));
else
sprite.setTextureRect(sf::IntRect(2 * width, 1 * height, -width, height));
sprite.setPosition(x, y);
sprite.setColor(sf::Color(255, 255, 255, 190));
app->draw(sprite);
sprite.setColor(sf::Color(255, 255, 255, 255));
}
float l = hpDisplay * ((MAP_WIDTH - 1) * TILE_WIDTH) / KING_RAT_HP;
sf::RectangleShape rectangle(sf::Vector2f((MAP_WIDTH - 1) * TILE_WIDTH, 25));
rectangle.setFillColor(sf::Color(0, 0, 0,128));
rectangle.setPosition(sf::Vector2f(OFFSET_X + TILE_WIDTH / 2, OFFSET_Y + 25 + (MAP_HEIGHT - 1) * TILE_HEIGHT));
app->draw(rectangle);
rectangle.setSize(sf::Vector2f(l, 25));
rectangle.setFillColor(sf::Color(190, 20, 20));
rectangle.setPosition(sf::Vector2f(OFFSET_X + TILE_WIDTH / 2, OFFSET_Y + 25 + (MAP_HEIGHT - 1) * TILE_HEIGHT));
app->draw(rectangle);
game().write( "Rat King",
18,
OFFSET_X + TILE_WIDTH / 2 + 10.0f,
OFFSET_Y + 25 + (MAP_HEIGHT - 1) * TILE_HEIGHT + 1.0f,
ALIGN_LEFT,
sf::Color(255, 255, 255),
app, 0 , 0);
}
void KingRatEntity::collideWithEnnemy(GameEntity* collidingEntity)
{
EnnemyEntity* entity = static_cast<EnnemyEntity*>(collidingEntity);
if (entity->getMovingStyle() == movWalking)
{
inflictsRecoilTo(entity);
}
}
void KingRatEntity::inflictsRecoilTo(BaseCreatureEntity* targetEntity)
{
if (state == 4 || state == 6)
{
Vector2D recoilVector = Vector2D(x, y).vectorTo(Vector2D(targetEntity->getX(), targetEntity->getY()), KING_RAT_RUNNING_RECOIL );
targetEntity->giveRecoil(true, recoilVector, 1.0f);
}
}
diff --git a/src/KingRatEntity.h b/src/KingRatEntity.h
index f919856..42f1765 100644
--- a/src/KingRatEntity.h
+++ b/src/KingRatEntity.h
@@ -1,34 +1,34 @@
#ifndef KINGRATSPRITE_H
#define KINGRATSPRITE_H
#include "EnnemyEntity.h"
#include "PlayerEntity.h"
class KingRatEntity : public EnnemyEntity
{
public:
KingRatEntity(float x, float y);
virtual void animate(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
virtual void inflictsRecoilTo(BaseCreatureEntity* targetEntity);
protected:
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
void afterWallCollide();
- virtual bool hurt(int damages);
+ virtual bool hurt(int damages, enumShotType hurtingType, int level);
void generateGreenRats();
virtual void collideWithEnnemy(GameEntity* collidingEntity);
virtual void dying();
private:
float timer;
float berserkDelay;
int state;
bool hasBeenBerserk;
};
#endif // KINGRATSPRITE_H
diff --git a/src/PlayerEntity.cpp b/src/PlayerEntity.cpp
index 5acabd9..0da1f97 100644
--- a/src/PlayerEntity.cpp
+++ b/src/PlayerEntity.cpp
@@ -1,903 +1,905 @@
#include "PlayerEntity.h"
#include "BoltEntity.h"
#include "EnnemyBoltEntity.h"
#include "ItemEntity.h"
#include "FairyEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
#include "TextEntity.h"
#include <iostream>
#include <sstream>
PlayerEntity::PlayerEntity(float x, float y)
: BaseCreatureEntity (ImageManager::getImageManager()->getImage(IMAGE_PLAYER_BASE), x, y, 80, 128)
{
currentFireDelay = -1.0f;
canFirePlayer = true;
type = ENTITY_PLAYER;
imagesProLine = 8;
playerStatus = playerStatusPlaying;
hp = INITIAL_PLAYER_HP;
hpDisplay = hp;
hpMax = INITIAL_PLAYER_HP;
gold = 0;
boltLifeTime = INITIAL_BOLT_LIFE;
specialBoltTimer = -1.0f;
bloodColor = bloodRed;
// init the equipment (to empty)
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++) equip[i] = false;
collidingDirection = 0;
// init the shots (to none)
for (int i = 0; i < SPECIAL_SHOT_SLOTS; i++) specialShots[i] = ShotTypeStandard;
specialShotIndex = 0;
needInitShotType = false;
+ shotLevel = 1; // TODO
computePlayer();
firingDirection = 5;
facingDirection = 2;
}
void PlayerEntity::moveTo(float newX, float newY)
{
float dx = newX - x;
float dy = newY - y;
x = newX;
y = newY;
for(int unsigned i = 0; i < fairies.size(); i++)
{
fairies[i]->setX(fairies[i]->getX() + dx);
fairies[i]->setY(fairies[i]->getY() + dy);
}
}
int PlayerEntity::getFacingDirection()
{
return facingDirection;
}
float PlayerEntity::getPercentFireDelay()
{
if (canFirePlayer) return 1.0f;
else return (1.0f - currentFireDelay / fireDelay);
}
int PlayerEntity::getCollidingDirection()
{
return collidingDirection;
}
PlayerEntity::playerStatusEnum PlayerEntity::getPlayerStatus()
{
return playerStatus;
}
void PlayerEntity::setPlayerStatus(PlayerEntity::playerStatusEnum playerStatus)
{
this->playerStatus = playerStatus;
}
bool PlayerEntity::isDead()
{
return playerStatus==playerStatusDead;
}
void PlayerEntity::setEntering()
{
playerStatus = playerStatusEntering;
}
void PlayerEntity::setLeavingLevel()
{
playerStatus = playerStatusGoingUp;
}
void PlayerEntity::pay(int price)
{
gold -= price;
if (gold < 0) gold = 0;
SoundManager::getSoundManager()->playSound(SOUND_PAY);
}
void PlayerEntity::animate(float delay)
{
// shot timer
if (specialBoltTimer >= 0.0f)
{
specialBoltTimer -= delay;
if (specialBoltTimer <= 0.0f)
{
if (getShotType() == ShotTypeIce) SoundManager::getSoundManager()->playSound(SOUND_ICE_CHARGE);
}
}
// rate of fire
if (!canFirePlayer)
{
currentFireDelay -= delay;
canFirePlayer = (currentFireDelay <= 0.0f);
}
// acquisition animation
if (playerStatus == playerStatusAcquire)
{
acquireDelay -= delay;
if (acquireDelay <= 0.0f)
{
if (acquiredItem >= FirstEquipItem)
{
equip[acquiredItem - FirstEquipItem] = true;
if (items[acquiredItem].familiar > FamiliarNone)
{
setEquiped(acquiredItem - FirstEquipItem, true);
}
if (items[acquiredItem].specialShot != (ShotTypeStandard))
registerSpecialShot(acquiredItem);
computePlayer();
}
else
{
if (acquiredItem == itemBossHeart)
{
int hpBonus = 2 + rand() % 4;
hpMax += hpBonus;
hp += hpBonus;
hpDisplay += hpBonus;
SoundManager::getSoundManager()->playSound(SOUND_EAT);
std::ostringstream oss;
oss << "HP Max +" << hpBonus;
TextEntity* text = new TextEntity(oss.str(), 14, x, y - 50.0f);
text->setColor(TextEntity::COLOR_GREEN);
text->setLifetime(2.0f);
text->setWeight(-100.0f);
}
}
playerStatus = playerStatusPlaying;
}
}
// unlocking animation
else if (playerStatus == playerStatusUnlocking)
{
acquireDelay -= delay;
if (acquireDelay <= 0.0f)
{
playerStatus = playerStatusPlaying;
}
}
if (playerStatus == playerStatusDead)
velocity = Vector2D(0.0f, 0.0f);
else
testSpriteCollisions();
collidingDirection = 0;
BaseCreatureEntity::animate(delay);
if (firingDirection != 5)
facingDirection = firingDirection;
if (isMoving())
{
frame = ((int)(age * 5.0f)) % 4;
if (frame == 3) frame = 1;
SoundManager::getSoundManager()->playSound(SOUND_STEP);
}
else if (playerStatus == playerStatusAcquire || playerStatus == playerStatusUnlocking)
frame = 0;
else if (playerStatus == playerStatusDead)
frame = 0;
else // standing
{
frame = 1;
}
if (x < OFFSET_X)
game().moveToOtherMap(4);
else if (x > OFFSET_X + MAP_WIDTH * TILE_WIDTH)
game().moveToOtherMap(6);
else if (y < OFFSET_Y)
game().moveToOtherMap(8);
else if (y > OFFSET_Y + MAP_HEIGHT * TILE_HEIGHT - 15)
game().moveToOtherMap(2);
if (playerStatus == playerStatusEntering)
{
if (boundingBox.left > OFFSET_X + TILE_WIDTH
&& (boundingBox.left + boundingBox.width) < OFFSET_X + TILE_WIDTH * (MAP_WIDTH - 1)
&& boundingBox.top > OFFSET_Y + TILE_HEIGHT
&& (boundingBox.top + boundingBox.height) < OFFSET_Y + TILE_HEIGHT * (MAP_HEIGHT - 1))
{
playerStatus = playerStatusPlaying;
game().closeDoors();
}
}
if (playerStatus == playerStatusDead)
{
z = OFFSET_Y - 2;
}
}
void PlayerEntity::renderHead(sf::RenderTarget* app)
{
if (playerStatus != playerStatusDead)
{
sprite.setTextureRect(sf::IntRect( (frame / 3 + spriteDx) * width, 0, width, height));
app->draw(sprite);
if (equip[EQUIP_ENCHANTER_HAT])
{
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_EQUIP));
if (playerStatus == playerStatusAcquire || playerStatus == playerStatusUnlocking)
sprite.setTextureRect(sf::IntRect( 0, 0, width, height));
else
sprite.setTextureRect(sf::IntRect( (frame / 3 + spriteDx) * width, 0, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_BASE));
}
}
}
void PlayerEntity::renderBody(sf::RenderTarget* app)
{
sprite.setTextureRect(sf::IntRect( (frame + spriteDx) * width, height, width, height));
app->draw(sprite);
if (equip[EQUIP_CONCENTRATION_AMULET])
{
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_COLLAR));
if (playerStatus == playerStatusAcquire || playerStatus == playerStatusUnlocking)
sprite.setTextureRect(sf::IntRect( 0, 0, width, height));
else
sprite.setTextureRect(sf::IntRect( (spriteDx / 3) * width, 0, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_BASE));
}
if (equip[EQUIP_LEATHER_BELT])
{
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_EQUIP));
sprite.setTextureRect(sf::IntRect( (frame + spriteDx) * width, height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_BASE));
}
}
void PlayerEntity::renderHands(sf::RenderTarget* app)
{
if (equip[EQUIP_VIBRATION_GLOVES]) sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_EQUIP));
sprite.setTextureRect(sf::IntRect( (frame + spriteDx) * width, height * 3, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_BASE));
}
void PlayerEntity::renderFeet(sf::RenderTarget* app)
{
if (equip[EQUIP_LEATHER_BOOTS]) sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_EQUIP));
sprite.setTextureRect(sf::IntRect( (frame + spriteDx) * width, height * 2, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_BASE));
}
void PlayerEntity::renderStaff(sf::RenderTarget* app)
{
if (equip[EQUIP_MAHOGANY_STAFF]) sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_EQUIP));
int xSnake, ySnake;
int xStone, yStone;
if (playerStatus == playerStatusAcquire || playerStatus == playerStatusUnlocking)
{
sprite.setTextureRect(sf::IntRect( 12 * width, height * 4, width, height));
app->draw(sprite);
xSnake = 13 * width;
ySnake = height * 4;
xStone = 13 * width;
yStone = height * 4;
}
else if (isMoving() || firingDirection != 5)
{
sprite.setTextureRect(sf::IntRect( (frame / 3 + spriteDx) * width, height * 4, width, height));
app->draw(sprite);
xSnake = (frame / 3 + spriteDx + 1) * width;
ySnake = height * 4;
xStone = (frame / 3 + spriteDx + 1) * width;
yStone = height * 4;
}
else
{
sprite.setTextureRect(sf::IntRect( (spriteDx / 3 + 14) * width, height * 4, width, height));
app->draw(sprite);
xSnake = (spriteDx / 3 + 14) * width;
ySnake = 0;
xStone = (spriteDx / 3 + 14) * width;
yStone = height * 2;
}
if (equip[EQUIP_BLOOD_SNAKE])
{
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_EQUIP));
sprite.setTextureRect(sf::IntRect( xSnake, ySnake, width, height));
app->draw(sprite);
}
sprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_PLAYER_BASE));
if (getShotType() != ShotTypeStandard)
{
switch (getShotType())
{
case ShotTypeIce: sprite.setColor(sf::Color(100, 220, 255, 255)); break;
case ShotTypeStone: sprite.setColor(sf::Color(120, 120, 150, 255)); break;
case ShotTypeLightning: sprite.setColor(sf::Color(255, 255, 0, 255)); break;
case ShotTypeIllusion: sprite.setColor(sf::Color(240, 180, 250, 255)); break;
case ShotTypeStandard: sprite.setColor(sf::Color(255, 255, 255, 0)); break;
}
sprite.setTextureRect(sf::IntRect( xStone, yStone, width, height));
app->draw(sprite);
sprite.setColor(sf::Color(255, 255, 255, 255));
}
}
void PlayerEntity::render(sf::RenderTarget* app)
{
sprite.setPosition(x, y);
spriteDx = 0;
if (facingDirection == 8) spriteDx = 3;
if (facingDirection == 4) spriteDx = 6;
if (facingDirection == 6) spriteDx = 9;
if (playerStatus == playerStatusAcquire || playerStatus == playerStatusUnlocking) spriteDx = 12;
if (playerStatus == playerStatusDead)
{
spriteDx = 13;
// blood
sprite.setTextureRect(sf::IntRect( width, 0, width, height));
app->draw(sprite);
}
else
{
// shadow
sprite.setTextureRect(sf::IntRect( 2 * width, 0, width, height));
app->draw(sprite);
}
if (facingDirection == 8 || facingDirection == 4)
{
renderStaff(app);
renderHead(app);
renderBody(app);
renderFeet(app);
renderHands(app);
}
else
{
renderBody(app);
renderHead(app);
renderFeet(app);
renderStaff(app);
renderHands(app);
}
// gems
if (getShotType() == ShotTypeIce || getShotType() == ShotTypeLightning)
{
int fade;
if (getShotType() != ShotTypeIce || specialBoltTimer <= 0.0f) fade = 255;
- else fade = ((STATUS_FROZEN_BOLT_DELAY - specialBoltTimer) / STATUS_FROZEN_BOLT_DELAY) * 128;
+ else fade = ((STATUS_FROZEN_BOLT_DELAY[shotLevel] - specialBoltTimer) / STATUS_FROZEN_BOLT_DELAY[shotLevel]) * 128;
if (getShotType() == ShotTypeLightning)
fade = 150 + rand() % 105;
if (getShotType() == ShotTypeIce)
sprite.setTextureRect(sf::IntRect(320, 0, 20, 20));
else if (getShotType() == ShotTypeLightning)
sprite.setTextureRect(sf::IntRect(340, 0, 20, 20));
sprite.setColor(sf::Color(255, 255, 255, fade));
if (isMoving() || firingDirection != 5)
{
if (facingDirection == 2 )
sprite.setPosition(x + 16, y + 36);
else if (facingDirection == 8 )
sprite.setPosition(x + 43, y + 36);
else if (facingDirection == 4 )
sprite.setPosition(x - 3 , y + 41);
else
sprite.setPosition(x + 63, y + 41);
}
else if (playerStatus == playerStatusAcquire || playerStatus == playerStatusUnlocking)
{
sprite.setPosition(x + 57, y + 18);
}
else
{
if (facingDirection == 2 )
sprite.setPosition(x + 16, y + 36);
else if (facingDirection == 8 )
sprite.setPosition(x + 43, y + 29);
else if (facingDirection == 4 )
sprite.setPosition(x + 13, y + 35);
else
sprite.setPosition(x + 46, y + 35);
}
sf::RenderStates r;
r.blendMode = sf::BlendAdd;
app->draw(sprite, r);
sprite.setPosition(x, y);
sprite.setColor(sf::Color(255, 255, 255, 255));
}
}
void PlayerEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2;
boundingBox.width = width;
boundingBox.top = (int)y - height / 2;
boundingBox.height = height;
boundingBox.left += 25;
boundingBox.width -= 50;
boundingBox.top += 80.0f;
boundingBox.height = boundingBox.height - 90.0f;
}
void PlayerEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (playerStatus == playerStatusDead) return;
EnnemyBoltEntity* boltEntity = dynamic_cast<EnnemyBoltEntity*>(entity);
if (collideWithEntity(entity))
{
if (boltEntity != NULL && !boltEntity->getDying())
{
boltEntity->collide();
hurt(boltEntity->getDamages(), ShotTypeStandard);
game().generateBlood(x, y, bloodColor);
}
}
}
void PlayerEntity::move(int direction)
{
if (playerStatus == playerStatusPlaying)
{
float speedx = 0.0f, speedy = 0.0f;
if (direction == 4)
speedx = - creatureSpeed;
else if (direction == 1 || direction == 7)
speedx = - creatureSpeed * 0.7f;
else if (direction == 6)
speedx = creatureSpeed;
else if (direction == 3 || direction == 9)
speedx = creatureSpeed * 0.7f;
if (direction == 2)
speedy = creatureSpeed;
else if (direction == 1 || direction == 3)
speedy = creatureSpeed * 0.7f;
else if (direction == 8)
speedy = - creatureSpeed;
else if (direction == 7 || direction == 9)
speedy = - creatureSpeed * 0.7f;
setVelocity(Vector2D(speedx, speedy));
{
switch (direction)
{
case 8: facingDirection = 8; break;
case 2: facingDirection = 2; break;
case 4: facingDirection = 4; break;
case 6: facingDirection = 6; break;
case 7: if (facingDirection != 4 && facingDirection != 8) facingDirection = 4; break;
case 1: if (facingDirection != 4 && facingDirection != 2) facingDirection = 4; break;
case 9: if (facingDirection != 6 && facingDirection != 8) facingDirection = 6; break;
case 3: if (facingDirection != 6 && facingDirection != 2) facingDirection = 6; break;
}
}
}
}
bool PlayerEntity::isMoving()
{
if (velocity.x < -1.0f || velocity.x > 1.0f) return true;
if (velocity.y < -1.0f || velocity.y > 1.0f) return true;
return false;
}
bool PlayerEntity::isEquiped(int eq)
{
return equip[eq];
}
void PlayerEntity::setEquiped(int item, bool toggleEquipped)
{
equip[item] = toggleEquipped;
if (toggleEquipped && items[FirstEquipItem + item].familiar > FamiliarNone)
{
FairyEntity* fairy = new FairyEntity(x - 50.0f + rand() % 100,
y - 50.0f + rand() % 100,
items[FirstEquipItem + item].familiar);
fairies.push_back(fairy);
}
computePlayer();
}
void PlayerEntity::generateBolt(float velx, float vely)
{
enumShotType boltType = ShotTypeStandard;
+ unsigned int shotLevel = 1;
+ // TODO
switch (getShotType())
{
case ShotTypeIce:
if (getShotType() == ShotTypeIce)
{
if (specialBoltTimer <= 0.0f)
{
boltType = ShotTypeIce;
needInitShotType = true;
}
else boltType = ShotTypeStandard;
}
break;
case ShotTypeStandard:
case ShotTypeIllusion:
case ShotTypeStone:
case ShotTypeLightning:
boltType = getShotType(); break;
}
-
- BoltEntity* bolt = new BoltEntity(ImageManager::getImageManager()->getImage(1), x, y + 30, boltLifeTime, boltType);
+ BoltEntity* bolt = new BoltEntity(ImageManager::getImageManager()->getImage(1), x, y + 30, boltLifeTime, boltType, shotLevel);
bolt->setMap(map, TILE_WIDTH, TILE_HEIGHT, OFFSET_X, OFFSET_Y);
bolt->setDamages(fireDamages);
bolt->setVelocity(Vector2D(velx, vely));
}
void PlayerEntity::resestFireDirection()
{
firingDirection = 5;
}
int PlayerEntity::getFireDirection()
{
return firingDirection;
}
void PlayerEntity::fire(int direction)
{
firingDirection = direction;
if (playerStatus != playerStatusDead)
for(int unsigned i = 0; i < fairies.size(); i++)
fairies[i]->fire(direction, map);
if (canFirePlayer && playerStatus != playerStatusDead && playerStatus != playerStatusAcquire)
{
SoundManager::getSoundManager()->playSound(SOUND_BLAST_STANDARD);
if (equip[EQUIP_BOOK_DUAL])
{
float shoot_angle = 0.2f;
if ((direction == 4 && velocity.x < -1.0f) || (direction == 6 && velocity.x > 1.0f)
|| (direction == 8 && velocity.y < -1.0f) || (direction == 2 && velocity.y > 1.0f))
shoot_angle = 0.1f;
else if ((direction == 6 && velocity.x < -1.0f) || (direction == 4 && velocity.x > 1.0f)
|| (direction == 2 && velocity.y < -1.0f) || (direction == 8 && velocity.y > 1.0f))
shoot_angle = 0.35f;
if (equip[EQUIP_VIBRATION_GLOVES]) shoot_angle += (1000 - rand() % 2000) * 0.0001f;
switch(direction)
{
case 4: generateBolt(-fireVelocity * cos(shoot_angle), fireVelocity * sin(shoot_angle));
generateBolt(-fireVelocity * cos(shoot_angle), - fireVelocity * sin(shoot_angle));break;
case 6: generateBolt(fireVelocity * cos(shoot_angle), fireVelocity * sin(shoot_angle));
generateBolt(fireVelocity * cos(shoot_angle), - fireVelocity * sin(shoot_angle));break;
case 8: generateBolt(fireVelocity * sin(shoot_angle), -fireVelocity * cos(shoot_angle));
generateBolt(-fireVelocity * sin(shoot_angle), - fireVelocity * cos(shoot_angle));break;
case 2: generateBolt(fireVelocity * sin(shoot_angle), fireVelocity * cos(shoot_angle));
generateBolt(-fireVelocity * sin(shoot_angle), fireVelocity * cos(shoot_angle));break;
}
}
else
{
if (equip[EQUIP_VIBRATION_GLOVES])
{
float shoot_angle = (1000 - rand() % 2000) * 0.0001f;
switch(direction)
{
case 4: generateBolt(-fireVelocity * cos(shoot_angle), fireVelocity * sin(shoot_angle)); break;
case 6: generateBolt(fireVelocity * cos(shoot_angle), fireVelocity * sin(shoot_angle)); break;
case 8: generateBolt(fireVelocity * sin(shoot_angle), -fireVelocity * cos(shoot_angle)); break;
case 2: generateBolt(fireVelocity * sin(shoot_angle), fireVelocity * cos(shoot_angle)); break;
}
}
else
{
switch(direction)
{
case 4: generateBolt(-fireVelocity, 0.0f); break;
case 6: generateBolt(fireVelocity, 0.0f); break;
case 8: generateBolt(0.0f, -fireVelocity); break;
case 2: generateBolt(0.0f, fireVelocity); break;
}
}
}
canFirePlayer = false;
currentFireDelay = fireDelay;
if (needInitShotType) initShotType();
}
}
bool PlayerEntity::canMove()
{
return (playerStatus == playerStatusPlaying);
}
bool PlayerEntity::hurt(int damages, enumShotType hurtingType)
{
if (!hurting)
{
SoundManager::getSoundManager()->playSound(SOUND_PLAYER_HIT);
- BaseCreatureEntity::hurt(damages, ShotTypeStandard);
+ BaseCreatureEntity::hurt(damages, ShotTypeStandard, 1);
hurtingDelay = HURTING_DELAY * 2.0f;
game().generateBlood(x, y, bloodColor);
game().generateBlood(x, y, bloodColor);
return true;
}
return false;
}
void PlayerEntity::loseItem(enumItemType itemType, bool isEquip)
{
CollidingSpriteEntity* itemSprite
= new CollidingSpriteEntity(ImageManager::getImageManager()->getImage(isEquip ? IMAGE_ITEMS_EQUIP : IMAGE_ITEMS), x, y, 32, 32);
itemSprite->setMap(map, TILE_WIDTH, TILE_HEIGHT, OFFSET_X, OFFSET_Y);
itemSprite->setZ(OFFSET_Y - 1);
itemSprite->setFrame(itemType);
itemSprite->setImagesProLine(10);
itemSprite->setType(ENTITY_BLOOD);
itemSprite->setVelocity(Vector2D(rand()%450));
itemSprite->setViscosity(0.95f);
itemSprite->setSpin( (rand() % 700) - 350.0f);
}
void PlayerEntity::dying()
{
playerStatus = playerStatusDead;
hp = 0;
SoundManager::getSoundManager()->playSound(SOUND_PLAYER_DIE);
setVelocity(Vector2D(0.0f, 0.0f));
int i;
for (i = 0; i < gold; i++) loseItem(ItemCopperCoin, false);
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++)
if (equip[i]) loseItem(enumItemType(i), true);
for (i = 0; i < 8; i++) game().generateBlood(x, y, bloodColor);
CollidingSpriteEntity* itemSprite
= new CollidingSpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_PLAYER_BASE), x, y, 80, 120);
itemSprite->setMap(map, TILE_WIDTH, TILE_HEIGHT, OFFSET_X, OFFSET_Y);
itemSprite->setZ(OFFSET_Y - 1);
itemSprite->setImagesProLine(14);
itemSprite->setFrame(13);
itemSprite->setType(ENTITY_BLOOD);
itemSprite->setVelocity(Vector2D(rand()%450));
itemSprite->setViscosity(0.95f);
itemSprite->setSpin( (rand() % 700) - 350.0f);
}
void PlayerEntity::acquireItem(enumItemType type)
{
if (items[type].generatesStance) acquireStance(type);
else switch (type)
{
case ItemCopperCoin: gold++;
SoundManager::getSoundManager()->playSound(SOUND_COIN_PICK_UP);
break;
case ItemSilverCoin: gold = gold + 5;
SoundManager::getSoundManager()->playSound(SOUND_COIN_PICK_UP);
break;
case ItemGoldCoin: gold = gold + 10;
SoundManager::getSoundManager()->playSound(SOUND_COIN_PICK_UP);
break;
case itemHealth: hp += 15;
SoundManager::getSoundManager()->playSound(SOUND_DRINK);
if (hp > hpMax) hp = hpMax; break;
default: break;
}
}
void PlayerEntity::computePlayer()
{
float boltLifeTimeBonus = 1.0f;
float fireDelayBonus = 1.0f;
float creatureSpeedBonus = 1.0f;
float fireVelocityBonus = 1.0f;
float fireDamagesBonus = 1.0f;
if (equip[EQUIP_VIBRATION_GLOVES]) fireDelayBonus -= 0.10f;
if (equip[EQUIP_ENCHANTER_HAT]) fireDelayBonus -= 0.2f;
if (equip[EQUIP_LEATHER_BELT]) fireDelayBonus -= 0.15f;
if (equip[EQUIP_LEATHER_BOOTS]) creatureSpeedBonus += 0.15f;
if (equip[EQUIP_BOOK_DUAL]) fireDelayBonus += 0.6f;
if (equip[EQUIP_CONCENTRATION_AMULET]) boltLifeTimeBonus += 0.5f;
if (equip[EQUIP_MAHOGANY_STAFF])
{
fireVelocityBonus += 0.15f;
fireDamagesBonus += 0.5f;
}
if (equip[EQUIP_BLOOD_SNAKE]) fireDamagesBonus += 1.0f;
fireDelay = INITIAL_PLAYER_FIRE_DELAY * fireDelayBonus;
creatureSpeed = INITIAL_PLAYER_SPEED * creatureSpeedBonus;
fireVelocity = INITIAL_BOLT_VELOCITY * fireVelocityBonus;
fireDamages = INITIAL_BOLT_DAMAGES * fireDamagesBonus;
boltLifeTime = INITIAL_BOLT_LIFE * boltLifeTimeBonus;
// gems
if (getShotType() == ShotTypeIllusion) fireDamages *= 0.8f;
}
void PlayerEntity::acquireStance(enumItemType type)
{
velocity.x = 0.0f;
velocity.y = 0.0f;
playerStatus = playerStatusAcquire;
acquireDelay = ACQUIRE_DELAY;
acquiredItem = (enumItemType)(type);
SoundManager::getSoundManager()->playSound(SOUND_BONUS);
}
void PlayerEntity::collideMapRight()
{
collidingDirection = 6;
}
void PlayerEntity::collideMapLeft()
{
collidingDirection = 4;
}
void PlayerEntity::collideMapTop()
{
collidingDirection = 8;
}
void PlayerEntity::collideMapBottom()
{
collidingDirection = 2;
}
void PlayerEntity::useBossKey()
{
velocity.x = 0.0f;
velocity.y = 0.0f;
playerStatus = playerStatusUnlocking;
acquireDelay = UNLOCK_DELAY;
acquiredItem = (enumItemType)(type - FirstEquipItem);
SoundManager::getSoundManager()->playSound(SOUND_BONUS);
equip[EQUIP_BOSS_KEY] = false;
SpriteEntity* spriteItem = new SpriteEntity(
ImageManager::getImageManager()->getImage(IMAGE_ITEMS_EQUIP),
x, y - 60.0f, ITEM_WIDTH, ITEM_HEIGHT);
spriteItem->setFrame(EQUIP_BOSS_KEY);
spriteItem->setZ(z);
spriteItem->setLifetime(UNLOCK_DELAY);
}
enumShotType PlayerEntity::getShotType()
{
return specialShots[specialShotIndex];
}
int PlayerEntity::getShotIndex()
{
return specialShotIndex;
}
void PlayerEntity::setShotIndex(int index)
{
specialShotIndex = index;
}
enumShotType PlayerEntity::getShotType(int slot)
{
return specialShots[slot];
}
void PlayerEntity::setShotType(int slot, enumShotType shotType)
{
specialShots[slot] = shotType;
}
void PlayerEntity::registerSpecialShot(int item)
{
bool found = false;
int index = 1;
while (index < SPECIAL_SHOT_SLOTS && !found)
{
found = specialShots[index] == ShotTypeStandard;
if (!found) index++;
}
if (found)
{
this->specialShots[index] = items[item].specialShot;
specialShotIndex = index;
initShotType();
}
}
void PlayerEntity::selectNextShotType()
{
int index = specialShotIndex + 1;
bool found = false;
while (index < SPECIAL_SHOT_SLOTS && !found)
{
if (specialShots[index] == ShotTypeStandard) index++;
else found = true;
}
if (found)
{
specialShotIndex = index;
initShotType();
}
else
specialShotIndex = 0;
SoundManager::getSoundManager()->playSound(SOUND_SHOT_SELECT);
computePlayer();
}
void PlayerEntity::initShotType()
{
- specialBoltTimer = STATUS_FROZEN_BOLT_DELAY;
+ specialBoltTimer = STATUS_FROZEN_BOLT_DELAY[shotLevel];
needInitShotType = false;
if (getShotType() == ShotTypeLightning)
SoundManager::getSoundManager()->playSound(SOUND_ELECTRIC_CHARGE);
}
int PlayerEntity::getFairieNumber()
{
return fairies.size();
}
FairyEntity* PlayerEntity::getFairy(unsigned int n)
{
if (n < fairies.size())
return fairies[n];
else
return NULL;
}
diff --git a/src/PlayerEntity.h b/src/PlayerEntity.h
index 7e2da2f..c5e57b3 100644
--- a/src/PlayerEntity.h
+++ b/src/PlayerEntity.h
@@ -1,430 +1,431 @@
#ifndef PLAYERSPRITE_H
#define PLAYERSPRITE_H
#include "BaseCreatureEntity.h"
#include "ItemEntity.h"
#include "Constants.h"
class FairyEntity;
/*! \class PlayerEntity
* \brief Class for the player
*
* It contains the game logic of the player and the rendering.
*/
class PlayerEntity : public BaseCreatureEntity
{
public:
/*!
* \brief Constructor
*
* Constructor of the PlayerEntity class.
*
* \param x : x position of the player
* \param y : y position of the player
*/
PlayerEntity(float x, float y);
/*!
* \brief updates the player
*
* Updates the player.
* Called in the game loop.
*
* \param delay : elapsed time since the last call
*/
virtual void animate(float delay);
/*!
* \brief render the player
*
* Render the player.
* Called in the game loop.
*
* \param app : Rendering target
*/
virtual void render(sf::RenderTarget* app);
/*!
* \brief Moves the player to another place
*
* Moves the player to another place.
* Called when changing room, the "familiers" will move too.
*
* \param newX : target x position of the player
* \param newY : target y position of the player
*/
void moveTo(float newX, float newY);
/*!
* \brief returns the direction the player is facing
*
* Return the direction the player is facing.
* Use to know in which direction he has to fire with the "one button" gameplay.
*
* \return : the facing direction. 4 = left, 8 = north, 6 = right, 2 = south
*/
int getFacingDirection();
/*!
* \brief update the bounding box
*
* Update the bounding box of the player.
* Used before testing collision.
*/
virtual void calculateBB();
/*!
* \brief Moves the player in the given direction
*
* Moves the player in the given direction.
*
* \param direction : direction of the new map. Numeric pad, diagonals included : 4 = left, 8 = north, 7 = north-west...
*/
void move(int direction);
/*!
* \brief Fires in the given direction
*
* Fires the player in the given direction.
*
* \param direction : direction of the new map. 4 = left, 8 = north, 6 = right, 2 = south
*/
void fire(int direction);
/*!
* \brief reset the fire direction of the player
*/
void resestFireDirection();
/*!
* \brief accessor on the fire direction of the player
*/
int getFireDirection();
/*!
* \brief returns if the player is moving or not
*
* Returns if the player is moving or not.
*
* \return : True if the player is moving
*/
bool isMoving();
/*!
* \brief returns if an item is equipped or not
*
* Returns if an item is equipped or not.
*
* \param eq : the equip item ID
* \return : True if the item is in possession of the player
*/
bool isEquiped(int eq);
/*!
* \brief updates the equipment of the player
*
* Updates the equipment of the player.
*
* \param item : the equip item ID
* \param toggleEquipped : True if the item has to be equipped
*/
void setEquiped(int item, bool toggleEquipped);
/*!
* \brief updates the entering status of the player
*
* Updates the entering status of the player.
* Used when the player is entering in a not yet cleared room.
*/
void setEntering();
/*!
* \brief updates the status of the player to going up
*
* Updates the status of the player to going up.
* Used when the player is leaving a level.
*/
void setLeavingLevel();
/*!
* \brief returns if the player can move or not
*
* Returns if the player can move or not.
*
* \return : True if the player can move
*/
bool canMove();
/*!
* \brief called when the player is dying
*
* Called when the player is dying (HP <= 0).
*/
virtual void dying();
/*!
* \brief hurts the player
*
* Hurts the player.
* Calld when the player is hurt, usually when colliding with a monster or a missile.
*
* \param damages : the inflicted damages
* \param hurtingType : damages type
* \return : True if the player has been hurt
*/
virtual bool hurt(int damages, enumShotType hurtingType);
/*!
* \brief returns if the player is dead or not
*
* Returns if the player is dead or not.
*
* \return : True if the player is dead
*/
bool isDead();
/*!
* \brief returns the fire delay percentage
*
* Returns the fire delay percentage.
* Used (currently) when displaying the blue bar in the HUD.
*
* \return : the percentage (between 0.0f for empty to 1.0 for full)
*/
float getPercentFireDelay();
/*!
* \brief called when the player get an item
*
* Called when the player get an item.
* When the item is an equip item, he starts an "acquiring stance".
*
* \param type : item ID
*/
void acquireItem(enumItemType type);
/*!
* \brief makes the player drop an item
*
* Makes the player drop an item.
* Called when the player dies.
*
* \param itemType : item ID
* \param isEquip : True if it's an equip item (not the same texture)
*/
void loseItem(enumItemType itemType, bool isEquip);
/*!
* \brief starts the acquire stance
*
* Starts the acquire stance.
* Called when the player get an equip object. The item is "highlighted" and a description is displayed.
*
* \param type : item ID
*/
void acquireStance(enumItemType type);
/*!
* \brief starts the opening stance
*
* Starts the boss door opening animation.
* Remove the key from the inventory.
*/
void useBossKey();
/*!
* \brief accessor on the gold
*
* Accessor on the gold.
*
* \return : the gold
*/
int getGold() {return gold; }
/*!
* \brief mutator on the gold
*
* Mutator on the gold.
*
* \param gold : the new gold value
*/
void setGold(int gold) { this->gold = gold; }
/*!
* \brief pay some gold
*
* Pay some gold. Usually in shops.
*
* \param gold : the price to pay
*/
void pay(int price);
/** Player status enum
* The different player states.
*/
enum playerStatusEnum
{
playerStatusPlaying, /**< Player is playing "normally" */
playerStatusEntering, /**< Player is entering a not yet cleared room (walking is forced) */
playerStatusAcquire, /**< Player is under acquiring stance */
playerStatusUnlocking, /**< Player is under unlocking stance */
playerStatusGoingUp, /**< Player goes to next level */
playerStatusDead /**< Player RIP */
};
/*!
* \brief accessor on the player status
*
* Accessor on the player status.
*
* \return : the player status
*/
playerStatusEnum getPlayerStatus();
/*!
* \brief mutator on the player status
*
* Mutator on the player status.
*
* \param player status : the new player status value
*/
void setPlayerStatus(playerStatusEnum playerStatus);
/*!
* \brief accessor on the colliding direction
*
* Accessor on the colliding direction.
*
* \return : the colliding direction
*/
int getCollidingDirection();
/*!
* \brief register a new special shot and select it
*
* Register a new special shot and select it.
*
* \param item : Item which provides the shot
*/
void registerSpecialShot(int item);
/*!
* \brief accessor on current shot type
*
* Accessor on the current shot type.
*
* \return : the current shot type
*/
enumShotType getShotType();
/*!
* \brief accessor on current shot index
*
* Accessor on the current shot index.
*
* \return : the current shot index
*/
int getShotIndex();
/*!
* \brief mutator on the shot index
*
* Mutator on the shot index.
*
* \param index : the new shot index
*/
void setShotIndex(int index);
/*!
* \brief accessor on current shot type of a slot
*
* Accessor on the current shot type of a slot.
*
* \param slot : The slot number
* \return : the current shot type
*/
enumShotType getShotType(int slot);
/*!
* \brief mutator on a shot slot
*
* Mutator on a shot slot.
*
* \param index : the shot index
* \param shotType : the shot type to set
*/
void setShotType(int slot, enumShotType shotType);
/*!
* \brief select the next shot type
*
* Select the next shot type.
*/
void selectNextShotType();
/*!
* \brief accessor on the fairies number
*/
int getFairieNumber();
/*!
* \brief accessor on a fairy
* \param n : index of the fairy in the vector
*/
FairyEntity* getFairy(unsigned int n);
protected:
void computePlayer();
virtual void readCollidingEntity(CollidingSpriteEntity* entity);
void generateBolt(float velx, float vely);
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
private:
int fireDamages;
float fireVelocity;
float fireDelay;
float currentFireDelay;
float boltLifeTime;
int gold;
bool canFirePlayer;
playerStatusEnum playerStatus;
float acquireDelay;
enumItemType acquiredItem;
bool equip[NUMBER_EQUIP_ITEMS];
float specialBoltTimer;
enumShotType specialShots[SPECIAL_SHOT_SLOTS];
int specialShotIndex;
+ int shotLevel;
bool needInitShotType;
int collidingDirection; /*!< Colliding direction (4, 8, 6, 2) to detect collision with closed doors */
int firingDirection;
std::vector<FairyEntity*> fairies;
int spriteDx;
void renderHead(sf::RenderTarget* app);
void renderBody(sf::RenderTarget* app);
void renderHands(sf::RenderTarget* app);
void renderFeet(sf::RenderTarget* app);
void renderStaff(sf::RenderTarget* app);
/*!
* \brief init the current shot type.
*
* Init the current shot type.
* Called when the player get a new shot, or after a switch.
*/
void initShotType();
};
#endif // PLAYERSPRITE_H
diff --git a/src/SlimeEntity.cpp b/src/SlimeEntity.cpp
index e2b49fe..2e92462 100644
--- a/src/SlimeEntity.cpp
+++ b/src/SlimeEntity.cpp
@@ -1,256 +1,256 @@
#include "SlimeEntity.h"
#include "PlayerEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
SlimeEntity::SlimeEntity(float x, float y, bool invocated)
: EnnemyEntity (ImageManager::getImageManager()->getImage(IMAGE_SLIME), x, y)
{
creatureSpeed = 0.0f;
velocity = Vector2D(0.0f, 0.0f);
hp = SLIME_HP;
meleeDamages = SLIME_DAMAGES;
this->invocated = invocated;
if (invocated)
{
type = ENTITY_ENNEMY_INVOCATED;
jumpingDelay = 0.1f;
age = 0.0f;
}
else
{
type = ENTITY_ENNEMY;
jumpingDelay = 0.6f + 0.1f * (rand() % 20);
}
bloodColor = bloodGreen;
frame = 0;
shadowFrame = 3;
isJumping = false;
h = 0.0f;
viscosity = 0.98f;
}
void SlimeEntity::animate(float delay)
{
float slimeDelay = delay;
- if (specialState[SpecialStateIce].active) slimeDelay = delay * STATUS_FROZEN_MULT;
+ if (specialState[SpecialStateIce].active) slimeDelay = delay * STATUS_FROZEN_MULT[specialState[SpecialStateIce].level];
if (isJumping)
{
hVelocity -= 700.0f * slimeDelay;
h += hVelocity * slimeDelay;
if (h <= 0.0f)
{
if (hp <= 0)
dying();
else
{
h = 0.0f;
if (isFirstJumping)
{
isFirstJumping = false;
hVelocity = 160.0f;
SoundManager::getSoundManager()->playSound(SOUND_SLIME_IMAPCT);
}
else
{
jumpingDelay = 0.4f + 0.1f * (rand() % 20);
isJumping = false;
SoundManager::getSoundManager()->playSound(SOUND_SLIME_IMAPCT_WEAK);
}
}
}
if (hVelocity > 0.0f) frame = 2;
else frame = 0;
}
else
{
jumpingDelay -= slimeDelay;
if (jumpingDelay < 0.0f)
{
SoundManager::getSoundManager()->playSound(SOUND_SLIME_JUMP);
hVelocity = 350.0f + rand() % 300;
isJumping = true;
isFirstJumping = true;
float randVel = 250.0f + rand() % 250;
if (rand() % 2 == 0)
{
float tan = (game().getPlayer()->getX() - x) / (game().getPlayer()->getY() - y);
float angle = atan(tan);
if (game().getPlayer()->getY() > y)
setVelocity(Vector2D(sin(angle) * randVel,
cos(angle) * randVel));
else
setVelocity(Vector2D(-sin(angle) * randVel,
-cos(angle) * randVel));
}
else
velocity = Vector2D(randVel);
}
else if (jumpingDelay < 0.25f)
frame = 1;
else frame = 0;
}
EnnemyEntity::animate(delay);
}
void SlimeEntity::render(sf::RenderTarget* app)
{
if (!isDying && shadowFrame > -1)
{
// shadow
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
}
sprite.setPosition(x, y - h);
sprite.setTextureRect(sf::IntRect(frame * width, 0, width, height));
app->draw(sprite);
#ifdef SHOW_BOUNDING_BOX
sf::Vertex line[] =
{
sf::Vertex(sf::Vector2f(boundingBox.left, boundingBox.top)),
sf::Vertex(sf::Vector2f(boundingBox.left + boundingBox.width, boundingBox.top)),
sf::Vertex(sf::Vector2f(boundingBox.left + boundingBox.width, boundingBox.top)),
sf::Vertex(sf::Vector2f(boundingBox.left + boundingBox.width, boundingBox.top + boundingBox.height)),
sf::Vertex(sf::Vector2f(boundingBox.left + boundingBox.width, boundingBox.top + boundingBox.height)),
sf::Vertex(sf::Vector2f(boundingBox.left, boundingBox.top + boundingBox.height)),
sf::Vertex(sf::Vector2f(boundingBox.left, boundingBox.top + boundingBox.height)),
sf::Vertex(sf::Vector2f(boundingBox.left, boundingBox.top))
};
app->draw(line, 8, sf::Lines);
#endif
}
void SlimeEntity::calculateBB()
{
boundingBox.left = (int)x - width / 2 + SLIME_BB_LEFT;
boundingBox.width = width - SLIME_BB_WIDTH_DIFF;
boundingBox.top = (int)y - height / 2 + SLIME_BB_TOP;
boundingBox.height = height - SLIME_BB_HEIGHT_DIFF;
}
void SlimeEntity::collideMapRight()
{
// if (x > OFFSET_X + MAP_WIDTH * TILE_WIDTH)
velocity.x = -velocity.x * 0.8f;
}
void SlimeEntity::collideMapLeft()
{
// if (x < OFFSET_X + MAP_WIDTH )
velocity.x = -velocity.x * 0.8f;
}
void SlimeEntity::collideMapTop()
{
// if (y > OFFSET_Y + MAP_HEIGHT * TILE_HEIGHT)
velocity.y = -velocity.y * 0.8f;
}
void SlimeEntity::collideMapBottom()
{
// if (y < OFFSET_Y + MAP_HEIGHT )
velocity.y = -velocity.y * 0.8f;
}
void SlimeEntity::collideWithEnnemy(GameEntity* collidingEntity)
{
if (recoil.active && recoil.stun) return;
EnnemyEntity* entity = static_cast<EnnemyEntity*>(collidingEntity);
if (entity->getMovingStyle() == movWalking)
{
Vector2D vel = Vector2D(entity->getX(), entity->getY()).vectorTo(Vector2D(x, y), 100.0f );
giveRecoil(false, vel, 0.3f);
computeFacingDirection();
}
}
bool SlimeEntity::collideWithMap(int direction)
{
calculateBB();
int xTile0 = (boundingBox.left - offsetX) / tileWidth;
int xTilef = (boundingBox.left + boundingBox.width - offsetX) / tileWidth;
int yTile0 = (boundingBox.top - offsetY) / tileHeight;
int yTilef = (boundingBox.top + boundingBox.height - offsetY) / tileHeight;
if (boundingBox.top < 0) yTile0 = -1;
for (int xTile = xTile0; xTile <= xTilef; xTile++)
for (int yTile = yTile0; yTile <= yTilef; yTile++)
{
if (xTile == 0 || xTile == MAP_WIDTH - 1 || yTile == 0 || yTile == MAP_HEIGHT - 1)
{
switch (direction)
{
case DIRECTION_LEFT:
if (map->isLeftBlocking(xTile, yTile)) return true;
break;
case DIRECTION_RIGHT:
if (map->isRightBlocking(xTile, yTile)) return true;
break;
case DIRECTION_TOP:
if (map->isUpBlocking(xTile, yTile)) return true;
break;
case DIRECTION_BOTTOM:
if (map->isDownBlocking(xTile, yTile)) return true;
break;
}
}
}
return false;
}
void SlimeEntity::dying()
{
isDying = true;
SpriteEntity* deadSlime = new SpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_CORPSES), x, y, 64, 64);
deadSlime->setZ(OFFSET_Y);
deadSlime->setFrame(FRAME_CORPSE_SLIME);
deadSlime->setType(ENTITY_CORPSE);
for (int i = 0; i < 4; i++) game().generateBlood(x, y, bloodColor);
if (!invocated) drop();
SoundManager::getSoundManager()->playSound(SOUND_ENNEMY_DYING);
}
void SlimeEntity::prepareDying()
{
if (!isJumping)
dying();
}
bool SlimeEntity::canCollide()
{
return h <= 70.0f;
}
BaseCreatureEntity::enumMovingStyle SlimeEntity::getMovingStyle()
{
if (h <= 70.0f)
return movWalking;
else
return movFlying;
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Jun 11, 10:50 AM (3 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
68543
Default Alt Text
(94 KB)

Event Timeline