Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
88 KB
Referenced Files
None
Subscribers
None
diff --git a/media/giant_slime.png b/media/giant_slime.png
new file mode 100644
index 0000000..14af7fb
Binary files /dev/null and b/media/giant_slime.png differ
diff --git a/src/Constants.h b/src/Constants.h
index c24873c..405d001 100644
--- a/src/Constants.h
+++ b/src/Constants.h
@@ -1,271 +1,284 @@
/** 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.0.8";
const std::string CONFIG_FILE = "config.dat";
// 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 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_ICE_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
};
// 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 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_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)
// 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 = 600;
+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 = 600;
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/GiantSlimeEntity.cpp b/src/GiantSlimeEntity.cpp
new file mode 100644
index 0000000..a2c49a0
--- /dev/null
+++ b/src/GiantSlimeEntity.cpp
@@ -0,0 +1,342 @@
+#include "GiantSlimeEntity.h"
+#include "BoltEntity.h"
+#include "EnnemyBoltEntity.h"
+#include "PlayerEntity.h"
+#include "SlimeEntity.h"
+#include "sfml_game/SpriteEntity.h"
+#include "sfml_game/ImageManager.h"
+#include "sfml_game/SoundManager.h"
+#include "Constants.h"
+#include "WitchBlastGame.h"
+
+#include <iostream>
+
+GiantSlimeEntity::GiantSlimeEntity(float x, float y)
+ : EnnemyEntity (ImageManager::getImageManager()->getImage(IMAGE_GIANT_SLIME), x, y)
+{
+ width = 128;
+ height = 128;
+ creatureSpeed = GIANT_SLIME_SPEED;
+ velocity = Vector2D(creatureSpeed);
+ hp = GIANT_SLIME_HP;
+ hpDisplay = hp;
+ hpMax = GIANT_SLIME_HP;
+ meleeDamages = GIANT_SLIME_DAMAGES;
+
+ type = ENTITY_ENNEMY_BOSS;
+ bloodColor = bloodGreen;
+ shadowFrame = 3;
+ frame = 0;
+ sprite.setOrigin(64.0f, 64.0f);
+ h = 0.0f;
+
+ age = 0.0f;
+
+ changeToState(0);
+ slimeCounter = 0;
+ slimeTimer =5.0f;
+
+ specialState[SpecialStateIce].resistance = ResistanceImmune;
+}
+
+void GiantSlimeEntity::changeToState(int n)
+{
+ if (n == 0) // walking
+ {
+ state = 0;
+ counter = 8 + rand() % 7;
+ timer = -1.0f;
+ viscosity = 1.0f;
+ }
+ else if (n == 1 || n == 3) // waiting
+ {
+ state = n;
+ timer = 2.0f;
+ setVelocity(Vector2D(0.0f, 0.0f));
+ }
+ else if (n == 2) // jumping
+ {
+ state = 2;
+ timer = 4.0f;
+
+ viscosity = 0.991f;
+
+ SoundManager::getSoundManager()->playSound(SOUND_SLIME_JUMP);
+ hVelocity = 380.0f + rand() % 420;
+
+ 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 (n == 4) // walking
+ {
+ state = 4;
+ counter = 10;
+ timer = GIANT_SLIME_MISSILE_DELAY;
+ }
+}
+
+void GiantSlimeEntity::animate(float delay)
+{
+ slimeTimer -= delay;
+ if (slimeTimer <= 0.0f)
+ {
+ switch (slimeCounter)
+ {
+ case 0: new SlimeEntity(OFFSET_X + TILE_WIDTH * 1.5f, OFFSET_Y + TILE_HEIGHT * 1.5f, true); break;
+ case 1: new SlimeEntity(OFFSET_X + TILE_WIDTH * (MAP_WIDTH - 2) + TILE_WIDTH * 0.5f, OFFSET_Y + TILE_HEIGHT * 1.5f, true); break;
+ case 2: new SlimeEntity(OFFSET_X + TILE_WIDTH * (MAP_WIDTH - 2) + TILE_WIDTH * 0.5f, OFFSET_Y + TILE_HEIGHT * (MAP_HEIGHT - 2) + TILE_HEIGHT * 0.5f, true); break;
+ case 3: new SlimeEntity(OFFSET_X + TILE_WIDTH * 1.5f, OFFSET_Y + TILE_HEIGHT * (MAP_HEIGHT - 2) + TILE_HEIGHT * 0.5f, true); break;
+ }
+ slimeTimer = 6.0f;
+ slimeCounter ++;
+ if (slimeCounter == 4) slimeCounter = 0;
+ }
+
+ timer -= delay;
+ if (timer <= 0.0f)
+ {
+ if (state == 0) // walking
+ {
+ counter--;
+ if (counter >= 0)
+ {
+ timer = 0.5f;
+ setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(),GIANT_SLIME_SPEED ));
+ }
+ else
+ {
+ changeToState(1);
+ }
+ }
+ else if (state == 1) // waiting
+ {
+ changeToState(2);; // jumping
+ //counter = 8 + rand() % 7;
+ }
+ else if (state == 2)
+ {
+ changeToState(3);
+ }
+ else if (state == 3)
+ {
+ changeToState(4);
+ }
+ else if (state == 4) // walking
+ {
+ counter--;
+ if (counter >= 0)
+ {
+ timer = GIANT_SLIME_MISSILE_DELAY;
+ fire();
+ }
+ else
+ {
+ changeToState(0);
+ }
+ }
+ }
+
+
+ if (state == 0) // walking
+ {
+ frame = ((int)(age * 2.0f)) % 2;
+ }
+ else if (state == 1) // waiting to jump
+ {
+ if (timer < 0.25f)
+ frame = 1;
+ else
+ frame = 0;
+ }
+ else if (state == 2) // jumping
+ {
+ hVelocity -= 700.0f * delay;
+
+ h += hVelocity * delay;
+
+ 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
+ {
+ //changeToState(0);
+ SoundManager::getSoundManager()->playSound(SOUND_SLIME_IMAPCT_WEAK);
+ }
+ }
+ }
+ if (hVelocity > 0.0f) frame = 2;
+ else frame = 0;
+ }
+
+// else if (state == 0)
+
+ EnnemyEntity::animate(delay);
+}
+
+bool GiantSlimeEntity::hurt(int damages)
+{
+ hurting = true;
+ hurtingDelay = HURTING_DELAY;
+
+ if (state == 6)
+ hp -= damages / 4;
+ else
+ hp -= damages;
+
+ if (hp <= 0)
+ {
+ hp = 0;
+ dying();
+ }
+ return true;
+}
+
+void GiantSlimeEntity::calculateBB()
+{
+ boundingBox.left = (int)x - width / 2 + GIANT_SLIME_BB_LEFT;
+ boundingBox.width = width - GIANT_SLIME_BB_WIDTH_DIFF;
+ boundingBox.top = (int)y - height / 2 + GIANT_SLIME_BB_TOP;
+ boundingBox.height = height - GIANT_SLIME_BB_HEIGHT_DIFF - GIANT_SLIME_BB_TOP;
+}
+
+
+void GiantSlimeEntity::collideMapRight()
+{
+ velocity.x = -velocity.x;
+}
+
+void GiantSlimeEntity::collideMapLeft()
+{
+ velocity.x = -velocity.x;
+}
+
+void GiantSlimeEntity::collideMapTop()
+{
+ velocity.y = -velocity.y;
+}
+
+void GiantSlimeEntity::collideMapBottom()
+{
+ velocity.y = -velocity.y;
+}
+
+
+void GiantSlimeEntity::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->setVelocity(Vector2D(100.0f + rand()% 250));
+ newItem->setViscosity(0.96f);
+}
+
+void GiantSlimeEntity::render(sf::RenderTarget* app)
+{
+ //EnnemyEntity::render(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);
+
+ 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( "Giant Slime",
+ 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);
+}
+
+void GiantSlimeEntity::collideWithEnnemy(GameEntity* collidingEntity)
+{
+ EnnemyEntity* entity = static_cast<EnnemyEntity*>(collidingEntity);
+ if (entity->getMovingStyle() == movWalking)
+ {
+ inflictsRecoilTo(entity);
+ }
+}
+
+void GiantSlimeEntity::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);
+ }
+}
+
+bool GiantSlimeEntity::canCollide()
+{
+ return h <= 70.0f;
+}
+
+BaseCreatureEntity::enumMovingStyle GiantSlimeEntity::getMovingStyle()
+{
+ if (h <= 70.0f)
+ return movWalking;
+ else
+ return movFlying;
+}
+
+void GiantSlimeEntity::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);
+
+ bolt->setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(),GIANT_SLIME_FIRE_VELOCITY ));
+}
diff --git a/src/SlimeEntity.h b/src/GiantSlimeEntity.h
similarity index 50%
copy from src/SlimeEntity.h
copy to src/GiantSlimeEntity.h
index 2e8db1a..6d52d8c 100644
--- a/src/SlimeEntity.h
+++ b/src/GiantSlimeEntity.h
@@ -1,38 +1,43 @@
-#ifndef SLIMESPRITE_H
-#define SLIMESPRITE_H
+#ifndef GIANTSLIMESPRITE_H
+#define GIANTSLIMESPRITE_H
#include "EnnemyEntity.h"
#include "PlayerEntity.h"
-class SlimeEntity : public EnnemyEntity
+class GiantSlimeEntity : public EnnemyEntity
{
public:
- SlimeEntity(float x, float y);
+ GiantSlimeEntity(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 bool collideWithMap(int direction);
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
+ void afterWallCollide();
+ virtual bool hurt(int damages);
- virtual void collideWithEnnemy(GameEntity* collidingEntity);
+ void changeToState(int n);
+ virtual void collideWithEnnemy(GameEntity* collidingEntity);
virtual void dying();
- virtual void prepareDying();
- virtual bool canCollide();
+ virtual bool canCollide();
virtual enumMovingStyle getMovingStyle();
private:
- float jumpingDelay;
+ float timer;
+ int state, counter;
+ float slimeTimer;
+ int slimeCounter;
float h;
float hVelocity;
-
- bool isJumping;
bool isFirstJumping;
+
+ void fire();
};
-#endif // SLIMESPRITE_H
+#endif // GIANTSLIMESPRITE_H
diff --git a/src/SlimeEntity.cpp b/src/SlimeEntity.cpp
index 94286f2..67499c7 100644
--- a/src/SlimeEntity.cpp
+++ b/src/SlimeEntity.cpp
@@ -1,246 +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)
+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;
- type = ENTITY_ENNEMY;
+ this->invocated = invocated;
+ if (invocated)
+ {
+ type = ENTITY_ENNEMY_INVOCATED;
+ jumpingDelay = 0.0f;
+ age = 0.0f;
+ }
+ else
+ {
+ type = ENTITY_ENNEMY;
+ jumpingDelay = 0.6f + 0.1f * (rand() % 20);
+ }
+
bloodColor = bloodGreen;
- jumpingDelay = 2.0f;
+ frame = 0;
shadowFrame = 3;
isJumping = false;
h = 0.0f;
viscosity = 0.98f;
- frame = 0;
- jumpingDelay = 0.6f + 0.1f * (rand() % 20);
}
void SlimeEntity::animate(float delay)
{
float slimeDelay = delay;
if (specialState[SpecialStateIce].active) slimeDelay = delay * STATUS_FROZEN_MULT;
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);
- drop();
+ 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;
}
diff --git a/src/SlimeEntity.h b/src/SlimeEntity.h
index 2e8db1a..fd66f47 100644
--- a/src/SlimeEntity.h
+++ b/src/SlimeEntity.h
@@ -1,38 +1,39 @@
#ifndef SLIMESPRITE_H
#define SLIMESPRITE_H
#include "EnnemyEntity.h"
#include "PlayerEntity.h"
class SlimeEntity : public EnnemyEntity
{
public:
- SlimeEntity(float x, float y);
+ SlimeEntity(float x, float y, bool invocated);
virtual void animate(float delay);
virtual void render(sf::RenderTarget* app);
virtual void calculateBB();
protected:
virtual bool collideWithMap(int direction);
virtual void collideMapRight();
virtual void collideMapLeft();
virtual void collideMapTop();
virtual void collideMapBottom();
virtual void collideWithEnnemy(GameEntity* collidingEntity);
virtual void dying();
virtual void prepareDying();
virtual bool canCollide();
virtual enumMovingStyle getMovingStyle();
private:
float jumpingDelay;
float h;
float hVelocity;
bool isJumping;
bool isFirstJumping;
+ bool invocated;
};
#endif // SLIMESPRITE_H
diff --git a/src/WitchBlastGame.cpp b/src/WitchBlastGame.cpp
index af5849e..502fb52 100644
--- a/src/WitchBlastGame.cpp
+++ b/src/WitchBlastGame.cpp
@@ -1,1542 +1,1548 @@
/** 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/>.
*/
#include "WitchBlastGame.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/TileMapEntity.h"
#include "DungeonMap.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "sfml_game/EntityManager.h"
#include "Constants.h"
#include "RatEntity.h"
#include "BlackRatEntity.h"
#include "GreenRatEntity.h"
#include "KingRatEntity.h"
+#include "GiantSlimeEntity.h"
#include "BatEntity.h"
#include "SlimeEntity.h"
#include "ChestEntity.h"
#include "EvilFlowerEntity.h"
#include "ItemEntity.h"
#include "ArtefactDescriptionEntity.h"
#include "PnjEntity.h"
#include "TextEntity.h"
#include <iostream>
#include <sstream>
#include <fstream>
namespace {
WitchBlastGame* gameptr;
}
WitchBlastGame::WitchBlastGame(): Game(SCREEN_WIDTH, SCREEN_HEIGHT)
{
gameptr = this;
app->setTitle(APP_NAME + " V" + APP_VERSION);
// loading resources
ImageManager::getImageManager()->addImage((char*)"media/player_base.png");
ImageManager::getImageManager()->addImage((char*)"media/player_equip.png");
ImageManager::getImageManager()->addImage((char*)"media/player_collar.png");
ImageManager::getImageManager()->addImage((char*)"media/bolt.png");
ImageManager::getImageManager()->addImage((char*)"media/tiles.png");
ImageManager::getImageManager()->addImage((char*)"media/rat.png");
ImageManager::getImageManager()->addImage((char*)"media/minimap.png");
ImageManager::getImageManager()->addImage((char*)"media/doors.png");
ImageManager::getImageManager()->addImage((char*)"media/items.png");
ImageManager::getImageManager()->addImage((char*)"media/items_equip.png");
ImageManager::getImageManager()->addImage((char*)"media/chest.png");
ImageManager::getImageManager()->addImage((char*)"media/bat.png");
ImageManager::getImageManager()->addImage((char*)"media/evil_flower.png");
ImageManager::getImageManager()->addImage((char*)"media/slime.png");
+ ImageManager::getImageManager()->addImage((char*)"media/giant_slime.png");
ImageManager::getImageManager()->addImage((char*)"media/king_rat.png");
ImageManager::getImageManager()->addImage((char*)"media/blood.png");
ImageManager::getImageManager()->addImage((char*)"media/corpses.png");
ImageManager::getImageManager()->addImage((char*)"media/corpses_big.png");
ImageManager::getImageManager()->addImage((char*)"media/star.png");
ImageManager::getImageManager()->addImage((char*)"media/star2.png");
ImageManager::getImageManager()->addImage((char*)"media/interface.png");
ImageManager::getImageManager()->addImage((char*)"media/hud_shots.png");
ImageManager::getImageManager()->addImage((char*)"media/pnj.png");
ImageManager::getImageManager()->addImage((char*)"media/fairy.png");
SoundManager::getSoundManager()->addSound((char*)"media/sound/step.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/blast00.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/blast01.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/door_closing.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/door_opening.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/chest_opening.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/impact.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/bonus.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/drink.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/eat.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/player_hit.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/player_die.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/ennemy_dying.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/coin.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/pay.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/wall_impact.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/big_wall_impact.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/king_rat_cry_1.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/king_rat_cry_2.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/king_rat_die.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/slime_jump.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/slime_impact.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/slime_impact_weak.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/ice_charge.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/select.ogg");
SoundManager::getSoundManager()->addSound((char*)"media/sound/heart.ogg");
if (font.loadFromFile("media/DejaVuSans-Bold.ttf"))
{
myText.setFont(font);
}
miniMap = NULL;
currentMap = NULL;
currentFloor = NULL;
xGameState = xGameStateNone;
isPausing = false;
- if (!mainTexture.create(GAME_WIDTH + OFFSET_X, GAME_HEIGHT + OFFSET_Y) )
- {
- // error
- }
-
- mainSprite.setTexture(mainTexture.getTexture());
- mainSprite.setTextureRect(sf::IntRect(0, GAME_HEIGHT + OFFSET_Y, GAME_WIDTH + OFFSET_X, -GAME_HEIGHT - OFFSET_Y));
-
shotsSprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_HUD_SHOTS));
configureFromFile();
}
WitchBlastGame::~WitchBlastGame()
{
// cleaning all entities
EntityManager::getEntityManager()->clean();
// cleaning data
if (miniMap != NULL) delete (miniMap);
if (currentFloor != NULL) delete (currentFloor);
}
DungeonMap* WitchBlastGame::getCurrentMap()
{
return currentMap;
}
PlayerEntity* WitchBlastGame::getPlayer()
{
return player;
}
Vector2D WitchBlastGame::getPlayerPosition()
{
return Vector2D(player->getX(), player->getY());
}
int WitchBlastGame::getLevel()
{
return level;
}
void WitchBlastGame::onUpdate()
{
float delta = getAbsolutTime() - lastTime;
lastTime = getAbsolutTime();
if (!isPausing)
{
EntityManager::getEntityManager()->animate(delta);
if (xGameState != xGameStateNone)
{
xGameTimer -= delta;
if (xGameTimer <= 0.0f)
{
if (xGameState == xGameStateFadeOut)
{
if (player->getPlayerStatus() == PlayerEntity::playerStatusGoingUp)
{
level++;
startNewLevel();
}
else
startNewGame(false);
}
else
xGameState = xGameStateNone;
}
}
if (isPlayerAlive)
{
if (player->getHp() <= 0)
{
isPlayerAlive = false;
playMusic(MusicEnding);
}
}
}
}
void WitchBlastGame::startNewGame(bool fromSaveFile)
{
gameState = gameStateInit;
level = 1;
// cleaning all entities
EntityManager::getEntityManager()->clean();
// cleaning data
if (miniMap != NULL) delete (miniMap);
if (currentFloor != NULL) delete (currentFloor);
miniMap = NULL;
currentFloor = NULL;
// current map (tiles)
currentTileMap = new TileMapEntity(ImageManager::getImageManager()->getImage(IMAGE_TILES), currentMap, 64, 64, 10);
currentTileMap->setX(OFFSET_X);
currentTileMap->setY(OFFSET_Y);
// the interface
SpriteEntity* interface = new SpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_INTERFACE));
interface->setZ(10000.0f);
interface->removeCenter();
interface->setType(0);
// key symbol on the interface
keySprite.setTexture(*ImageManager::getImageManager()->getImage(IMAGE_ITEMS_EQUIP));
keySprite.setTextureRect(sf::IntRect(ITEM_WIDTH * EQUIP_BOSS_KEY, 0, ITEM_WIDTH, ITEM_HEIGHT));
keySprite.setPosition(326, 616);
miniMap = new GameMap(FLOOR_WIDTH, FLOOR_HEIGHT);
// minimap on the interface
TileMapEntity* miniMapEntity = new TileMapEntity(ImageManager::getImageManager()->getImage(IMAGE_MINIMAP), miniMap, 15, 11, 10);
miniMapEntity->setTileBox(16, 12);
miniMapEntity->setX(407);
miniMapEntity->setY(614);
miniMapEntity->setZ(10001.0f);
// doors
doorEntity[0] = new DoorEntity(8);
doorEntity[1] = new DoorEntity(4);
doorEntity[2] = new DoorEntity(2);
doorEntity[3] = new DoorEntity(6);
if (fromSaveFile)
{
if (!loadGame())
fromSaveFile = false;
else
playLevel();
}
if (!fromSaveFile)
{
// the player
player = new PlayerEntity(OFFSET_X + (TILE_WIDTH * MAP_WIDTH * 0.5f),
OFFSET_Y + (TILE_HEIGHT * MAP_HEIGHT * 0.5f));
startNewLevel();
}
}
void WitchBlastGame::startNewLevel()
{
// create the new level
if (currentFloor != NULL) delete currentFloor;
currentFloor = new GameFloor(level);
currentFloor->createFloor();
// center it
floorX = FLOOR_WIDTH / 2;
floorY = FLOOR_HEIGHT / 2;
// move the player
if (level == 1)
player->moveTo(OFFSET_X + (TILE_WIDTH * MAP_WIDTH * 0.5f),
OFFSET_Y + (TILE_HEIGHT * MAP_HEIGHT * 0.5f));
else
player->moveTo(OFFSET_X + (TILE_WIDTH * MAP_WIDTH * 0.5f),
OFFSET_Y + (TILE_HEIGHT * MAP_HEIGHT - 3 * TILE_HEIGHT));
// the boss room is closed
bossRoomOpened = false;
playLevel();
}
void WitchBlastGame::playLevel()
{
isPlayerAlive = true;
player->setVelocity(Vector2D(0.0f, 0.0f));
player->setPlayerStatus(PlayerEntity::playerStatusPlaying);
// generate the map
refreshMap();
// items from save
currentMap->restoreMapObjects();
// first map is open
roomClosed = false;
// game time counter an state
lastTime = getAbsolutTime();
gameState = gameStatePlaying;
playMusic(MusicDungeon);
// fade in
xGameState = xGameStateFadeIn;
xGameTimer = FADE_IN_DELAY;
float x0 = OFFSET_X + MAP_WIDTH * 0.5f * TILE_WIDTH;
float y0 = OFFSET_Y + MAP_HEIGHT * 0.5f * TILE_HEIGHT + 40.0f;
std::ostringstream oss;
oss << "Level " << level;
TextEntity* text = new TextEntity(oss.str(), 30, x0, y0);
text->setAlignment(ALIGN_CENTER);
text->setLifetime(2.5f);
text->setWeight(-36.0f);
text->setZ(1000);
text->setColor(TextEntity::COLOR_FADING_WHITE);
}
void WitchBlastGame::startGame()
{
startNewGame(true);
// Start game loop
while (app->isOpen())
{
// Process events
sf::Event event;
while (app->pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
if (gameState == gameStatePlaying && !player->isDead() && currentMap->isCleared()) saveGame();
app->close();
}
if (event.type == sf::Event::MouseWheelMoved)
{
if (gameState == gameStatePlaying && !isPausing) player->selectNextShotType();
}
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Escape)
{
if (gameState == gameStatePlaying && !isPausing) isPausing = true;
else if (gameState == gameStatePlaying && isPausing) isPausing = false;
}
if (event.key.code == input[KeyFireSelect] || event.key.code == inputAlt[KeyFireSelect])
{
if (gameState == gameStatePlaying && !isPausing) player->selectNextShotType();
}
if (event.key.code == input[KeyFire] || event.key.code == inputAlt[KeyFire])
{
if (gameState == gameStatePlaying && !isPausing) firingDirection = player->getFacingDirection();
}
if (event.key.code == sf::Keyboard::X)
{
startNewGame(false);
}
}
if (event.type == sf::Event::LostFocus)
isPausing = true;
}
if (gameState == gameStatePlaying && !isPausing)
{
if (player->canMove()) player->setVelocity(Vector2D(0.0f, 0.0f));
if (sf::Keyboard::isKeyPressed(input[KeyLeft]) || sf::Keyboard::isKeyPressed(inputAlt[KeyLeft]))
{
if (sf::Keyboard::isKeyPressed(input[KeyUp]) || sf::Keyboard::isKeyPressed(inputAlt[KeyUp]))
player->move(7);
else if (sf::Keyboard::isKeyPressed(input[KeyDown]) || sf::Keyboard::isKeyPressed(inputAlt[KeyDown]))
player->move(1);
else
player->move(4);
}
else if (sf::Keyboard::isKeyPressed(input[KeyRight]) || sf::Keyboard::isKeyPressed(inputAlt[KeyRight]))
{
if (sf::Keyboard::isKeyPressed(input[KeyUp]) || sf::Keyboard::isKeyPressed(inputAlt[KeyUp]))
player->move(9);
else if (sf::Keyboard::isKeyPressed(input[KeyDown]) || sf::Keyboard::isKeyPressed(inputAlt[KeyDown]))
player->move(3);
else
player->move(6);
}
else if (sf::Keyboard::isKeyPressed(input[KeyUp]) || sf::Keyboard::isKeyPressed(inputAlt[KeyUp]))
{
player->move(8);
}
else if (sf::Keyboard::isKeyPressed(input[KeyDown]) || sf::Keyboard::isKeyPressed(inputAlt[KeyDown]))
{
player->move(2);
}
// normal 4 directions gameplay
if (sf::Keyboard::isKeyPressed(input[KeyFireLeft]) || sf::Keyboard::isKeyPressed(inputAlt[KeyFireLeft]))
player->fire(4);
else if (sf::Keyboard::isKeyPressed(input[KeyFireRight]) || sf::Keyboard::isKeyPressed(inputAlt[KeyFireRight]))
player->fire(6);
else if (sf::Keyboard::isKeyPressed(input[KeyFireUp]) || sf::Keyboard::isKeyPressed(inputAlt[KeyFireUp]))
player->fire(8);
else if (sf::Keyboard::isKeyPressed(input[KeyFireDown]) || sf::Keyboard::isKeyPressed(inputAlt[KeyFireDown]))
player->fire(2);
// alternative "one button" gameplay
else if (sf::Keyboard::isKeyPressed(input[KeyFire]) || sf::Keyboard::isKeyPressed(inputAlt[KeyFire]))
{
player->fire(firingDirection);
}
// alternative "firing with the mouse" gameplay
else if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
sf::Vector2i mousePosition = sf::Mouse::getPosition(*app);
int xm = mousePosition.x - player->getX();
int ym = mousePosition.y - player->getY();
if (abs(xm) >= abs(ym))
{
if (xm > 0) player->fire(6);
else player->fire(4);
}
else
{
if (ym > 0) player->fire(2);
else player->fire(8);
}
}
if (player->isDead() && xGameState == xGameStateNone && sf::Keyboard::isKeyPressed(sf::Keyboard::Return))
{
xGameState = xGameStateFadeOut;
xGameTimer = FADE_OUT_DELAY;
}
}
onUpdate();
EntityManager::getEntityManager()->sortByZ();
onRender();
verifyDoorUnlocking();
if (roomClosed)
{
if (getEnnemyCount() == 0)
{
currentMap->setCleared(true);
openDoors();
if (currentMap->getRoomType() == roomTypeBoss)
playMusic(MusicDungeon);
}
}
}
quitGame();
}
void WitchBlastGame::createFloor()
{
// TODO : extracts from createNewGame
}
void WitchBlastGame::closeDoors()
{
if (!currentMap->isCleared())
{
int i;
for(i = 0; i < MAP_WIDTH; i++)
{
if (currentMap->getTile(i, 0) < 4) currentMap->setTile(i, 0, MAP_DOOR);
if (currentMap->getTile(i, MAP_HEIGHT - 1) < 4) currentMap->setTile(i, MAP_HEIGHT - 1, MAP_DOOR);
}
for(i = 0; i < MAP_HEIGHT; i++)
{
if (currentMap->getTile(0, i) < 4) currentMap->setTile(0, i, MAP_DOOR);
if (currentMap->getTile(MAP_WIDTH - 1, i) < 4) currentMap->setTile(MAP_WIDTH - 1, i, MAP_DOOR);
}
roomClosed = true;
}
}
void WitchBlastGame::openDoors()
{
int i, j;
for(i = 0; i < MAP_WIDTH; i++)
for(j = 0; j < MAP_WIDTH; j++)
if (currentMap->getTile(i, j) == MAP_DOOR) currentMap->setTile(i, j, 0);
roomClosed = false;
SoundManager::getSoundManager()->playSound(SOUND_DOOR_OPENING);
if (currentMap->hasNeighbourUp() == 2 && !bossRoomOpened)
currentMap->setTile(MAP_WIDTH/2, 0, MAP_DOOR);
else
doorEntity[0]->openDoor();
if (currentMap->hasNeighbourLeft() == 2 && !bossRoomOpened)
currentMap->setTile(0, MAP_HEIGHT / 2, MAP_DOOR);
else
doorEntity[1]->openDoor();
if (currentMap->hasNeighbourDown() == 2 && !bossRoomOpened)
currentMap->setTile(MAP_WIDTH / 2, MAP_HEIGHT - 1, MAP_DOOR);
else
doorEntity[2]->openDoor();
if (currentMap->hasNeighbourRight() == 2 && !bossRoomOpened)
currentMap->setTile(MAP_WIDTH - 1, MAP_HEIGHT / 2, MAP_DOOR);
else
doorEntity[3]->openDoor();
}
int WitchBlastGame::getEnnemyCount()
{
int n=0;
EntityManager::EntityList* entityList =EntityManager::getEntityManager()->getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() >= 20)
{
n++;
- } // endif
- } // end for
+ }
+ }
return n;
}
void WitchBlastGame::refreshMap()
{
// clean the sprites from old map
EntityManager::getEntityManager()->partialClean(10);
// if new map, it has to be randomized
bool generateMap = !(currentFloor->getMap(floorX, floorY)->isVisited());
currentMap = currentFloor->getAndVisitMap(floorX, floorY);
// load the map
currentTileMap->setMap(currentMap);
player->setMap(currentMap, TILE_WIDTH, TILE_HEIGHT, OFFSET_X, OFFSET_Y);
refreshMinimap();
if(generateMap)
this->generateMap();
else
{
if (currentMap->getRoomType() == roomTypeMerchant)
new PnjEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2 - 2) * TILE_HEIGHT,
0);
}
// check doors
doorEntity[0]->setVisible(currentMap->hasNeighbourUp() > 0);
if (currentMap->hasNeighbourUp() == 1) doorEntity[0]->setDoorType(0);
if (currentMap->hasNeighbourUp() == 2 || currentMap->getRoomType()==roomTypeBoss) doorEntity[0]->setDoorType(1);
if (currentMap->hasNeighbourUp() == 2 && !bossRoomOpened)
{
doorEntity[0]->setOpen(false);
currentMap->setTile(MAP_WIDTH/2, 0, MAP_DOOR);
}
else
doorEntity[0]->setOpen(true);
doorEntity[3]->setVisible(currentMap->hasNeighbourRight() > 0);
if (currentMap->hasNeighbourRight() == 1) doorEntity[3]->setDoorType(0);
if (currentMap->hasNeighbourRight() == 2 || currentMap->getRoomType()==roomTypeBoss) doorEntity[3]->setDoorType(1);
if (currentMap->hasNeighbourRight() == 2 && !bossRoomOpened)
{
doorEntity[3]->setOpen(false);
currentMap->setTile(MAP_WIDTH - 1, MAP_HEIGHT / 2, MAP_DOOR);
}
else
doorEntity[3]->setOpen(true);
doorEntity[2]->setVisible(currentMap->hasNeighbourDown() > 0);
if (currentMap->hasNeighbourDown() == 1) doorEntity[2]->setDoorType(0);
if (currentMap->hasNeighbourDown() == 2 || currentMap->getRoomType()==roomTypeBoss) doorEntity[2]->setDoorType(1);
if (currentMap->hasNeighbourDown() == 2 && !bossRoomOpened)
{
doorEntity[2]->setOpen(false);
currentMap->setTile(MAP_WIDTH/2, MAP_HEIGHT - 1, MAP_DOOR);
}
else
doorEntity[2]->setOpen(true);
doorEntity[1]->setVisible(currentMap->hasNeighbourLeft() > 0);
if (currentMap->hasNeighbourLeft() == 1) doorEntity[1]->setDoorType(0);
if (currentMap->hasNeighbourLeft() == 2 || currentMap->getRoomType()==roomTypeBoss) doorEntity[1]->setDoorType(1);
if (currentMap->hasNeighbourLeft() == 2 && !bossRoomOpened)
{
doorEntity[1]->setOpen(false);
currentMap->setTile(0, MAP_HEIGHT / 2, MAP_DOOR);
}
else
doorEntity[1]->setOpen(true);
}
void WitchBlastGame::refreshMinimap()
{
for (int j=0; j < FLOOR_HEIGHT; j++)
for (int i=0; i < FLOOR_WIDTH; i++)
{
int n = currentFloor->getRoom(i, j);
if (n > 0 && currentFloor->getMap(i, j)->isVisited())
{
if (currentFloor->getRoom(i, j) == roomTypeStarting
|| currentFloor->getRoom(i, j) == roomTypeBonus
|| currentFloor->getRoom(i, j) == roomTypeKey)
miniMap->setTile(i, j, roomTypeStandard);
else
miniMap->setTile(i, j, currentFloor->getRoom(i, j));
}
else if (n > 0 && currentFloor->getMap(i, j)->isKnown())
{
if (currentFloor->getRoom(i, j) == roomTypeBoss)
miniMap->setTile(i, j, 7);
else
miniMap->setTile(i, j, 9);
}
else
miniMap->setTile(i, j, 0);
}
miniMap->setTile(floorX, floorY, 8);
}
void WitchBlastGame::checkEntering()
{
if (!currentMap->isCleared())
{
player->setEntering();
SoundManager::getSoundManager()->playSound(SOUND_DOOR_CLOSING);
for (int i=0; i<4; i++)
doorEntity[i]->closeDoor();
}
}
void WitchBlastGame::saveMapItems()
{
EntityManager::EntityList* entityList = EntityManager::getEntityManager()->getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity* e = *it;
it++;
ItemEntity* itemEntity = dynamic_cast<ItemEntity*>(e);
ChestEntity* chestEntity = dynamic_cast<ChestEntity*>(e);
if (itemEntity != NULL)
{
currentMap->addItem(itemEntity->getItemType(), itemEntity->getX(), itemEntity->getY(), itemEntity->getMerchandise());
} // endif
else if (chestEntity != NULL)
{
currentMap->addChest(chestEntity->getChestType(), chestEntity->getOpened(), chestEntity->getX(), chestEntity->getY());
} // endif
else
{
SpriteEntity* spriteEntity = dynamic_cast<SpriteEntity*>(e);
if (spriteEntity != NULL && (e->getType() == ENTITY_BLOOD || e->getType() == ENTITY_CORPSE ) )
{
int spriteFrame = spriteEntity->getFrame();
if (spriteEntity->getWidth() == 128) spriteFrame += FRAME_CORPSE_KING_RAT;
currentMap->addSprite(e->getType(), spriteFrame, e->getX(), e->getY(), spriteEntity->getScaleX());
}
}
} // end for
}
void WitchBlastGame::moveToOtherMap(int direction)
{
// stairs to next level
if (direction == 8 && currentMap->getRoomType() == roomTypeExit)
{
if (player->getPlayerStatus() != PlayerEntity::playerStatusGoingUp)
{
player->setLeavingLevel();
xGameState = xGameStateFadeOut;
xGameTimer = FADE_OUT_DELAY;
player->setVelocity(Vector2D(0.0f, - INITIAL_PLAYER_SPEED / 2));
}
}
// go to another room
else
{
saveMapItems();
switch (direction)
{
case (4): floorX--; player->moveTo((OFFSET_X + MAP_WIDTH * TILE_WIDTH), player->getY()); player->move(4); break;
case (6): floorX++; player->moveTo(OFFSET_X, player->getY()); player->move(6); break;
case (8): floorY--; player->moveTo(player->getX(), OFFSET_Y + MAP_HEIGHT * TILE_HEIGHT - 20); player->move(8); break;
case (2): floorY++; player->moveTo(player->getX(), OFFSET_Y); break;
}
refreshMap();
checkEntering();
currentMap->restoreMapObjects();
}
}
void WitchBlastGame::onRender()
{
// clear the view
app->clear(sf::Color(32, 32, 32));
+
if (xGameState == xGameStateShake)
{
- mainTexture.clear();
- EntityManager::getEntityManager()->renderUnder(&mainTexture, 5000);
- mainSprite.setPosition(-4 + rand() % 9, -4 + rand() % 9);
- app->draw(mainSprite);
+ sf::View view = app->getDefaultView();
+ sf::View viewSave = app->getDefaultView();
+ view.move(-4 + rand() % 9, -4 + rand() % 9);
+ app->setView(view);
+
+ EntityManager::getEntityManager()->renderUnder(app, 5000);
+
+ app->setView(viewSave);
EntityManager::getEntityManager()->renderAfter(app, 5000);
}
else
{
// render the game objects
EntityManager::getEntityManager()->render(app);
}
myText.setColor(sf::Color(255, 255, 255, 255));
myText.setCharacterSize(18);
std::ostringstream oss;
oss << player->getGold();
myText.setString(oss.str());
myText.setPosition(690, 612);
app->draw(myText);
myText.setColor(sf::Color(0, 0, 0, 255));
myText.setCharacterSize(16);
oss.str("");
oss << "Level " << level;
myText.setString(oss.str());
myText.setPosition(410, 692);
app->draw(myText);
sf::RectangleShape rectangle(sf::Vector2f(200, 25));
// life
if (gameState == gameStatePlaying)
{
// life and mana
rectangle.setFillColor(sf::Color(190, 20, 20));
rectangle.setPosition(sf::Vector2f(90, 622));
rectangle.setSize(sf::Vector2f(200.0f * (float)(player->getHpDisplay()) / (float)(player->getHpMax()) , 25));
app->draw(rectangle);
rectangle.setFillColor(sf::Color(255, 190, 190));
rectangle.setPosition(sf::Vector2f(90, 625));
rectangle.setSize(sf::Vector2f(200.0f * (float)(player->getHpDisplay()) / (float)(player->getHpMax()) , 2));
app->draw(rectangle);
rectangle.setFillColor(sf::Color(20, 20, 190));
rectangle.setPosition(sf::Vector2f(90, 658));
rectangle.setSize(sf::Vector2f(200.0f * player->getPercentFireDelay() , 25));
app->draw(rectangle);
rectangle.setFillColor(sf::Color(190, 190, 255));
rectangle.setPosition(sf::Vector2f(90, 661));
rectangle.setSize(sf::Vector2f(200.0f * player->getPercentFireDelay() , 2));
app->draw(rectangle);
// drawing the key on the interface
if (player->isEquiped(EQUIP_BOSS_KEY)) app->draw(keySprite);
// render the shots
renderHudShots(app);
if (isPausing)
{
rectangle.setFillColor(sf::Color(0, 0, 0, 160));
rectangle.setPosition(sf::Vector2f(OFFSET_X, OFFSET_Y));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH, MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
float x0 = OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2;
int fade = 50 + 205 * (1.0f + cos(3.0f * getAbsolutTime())) * 0.5f;
myText.setColor(sf::Color(255, 255, 255, fade));
myText.setCharacterSize(40);
myText.setString("PAUSE");
myText.setPosition(x0 - myText.getLocalBounds().width / 2, 300);
app->draw(myText);
}
if (player->isDead())
{
float x0 = OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2;
int fade = 255 * (1.0f + cos(2.0f * getAbsolutTime())) * 0.5f;
myText.setColor(sf::Color(255, 255, 255, 255));
myText.setCharacterSize(25);
myText.setString("GAME OVER");
myText.setPosition(x0 - myText.getLocalBounds().width / 2, 400);
app->draw(myText);
myText.setColor(sf::Color(255, 255, 255, fade));
myText.setCharacterSize(20);
myText.setString("Press [ENTER] to play again !");
myText.setPosition(x0 - myText.getLocalBounds().width / 2, 440);
app->draw(myText);
}
else if (currentMap->getRoomType() == roomTypeExit)
{
float x0 = OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2;
myText.setColor(sf::Color(255, 255, 255, 255));
myText.setCharacterSize(25);
myText.setString("CONGRATULATIONS !\nYou've challenged this demo and\nmanaged to kill the boss !\nSee you soon for new adventures !");
myText.setPosition(x0 - myText.getLocalBounds().width / 2, 220);
app->draw(myText);
}
if (xGameState == xGameStateFadeIn)
{
// fade in
rectangle.setFillColor(sf::Color(0, 0, 0, 255 - ((FADE_IN_DELAY - xGameTimer) / FADE_IN_DELAY) * 255));
rectangle.setPosition(sf::Vector2f(OFFSET_X, OFFSET_Y));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
}
else if (xGameState == xGameStateFadeOut)
{
// fade out
rectangle.setFillColor(sf::Color(0, 0, 0, ((FADE_IN_DELAY - xGameTimer) / FADE_IN_DELAY) * 255));
rectangle.setPosition(sf::Vector2f(OFFSET_X, OFFSET_Y));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
}
}
app->display();
}
void WitchBlastGame::renderHudShots(sf::RenderTarget* app)
{
int xHud = 640;
int yHud = 650;
int index = 0;
for (int i = 0; i < SPECIAL_SHOT_SLOTS; i++)
{
if (i == 0 || player->getShotType(i) != ShotTypeStandard)
{
int type_shot = player->getShotType(i);
shotsSprite.setPosition(xHud + 48 * index, yHud);
if (index == player->getShotIndex())
{
shotsSprite.setTextureRect(sf::IntRect(0, 0, 48, 48));
app->draw(shotsSprite);
}
shotsSprite.setTextureRect(sf::IntRect(48 * ( 1 + type_shot), 0, 48, 48));
app->draw(shotsSprite);
index++;
}
}
}
void WitchBlastGame::generateBlood(float x, float y, BaseCreatureEntity::enumBloodColor bloodColor)
{
// double blood if the "Blood Snake3 object is equipped
int nbIt;
if (player->isEquiped(EQUIP_BLOOD_SNAKE))
nbIt = 2;
else
nbIt = 1;
for (int i=0; i < nbIt; i++)
{
SpriteEntity* blood = new SpriteEntity(ImageManager::getImageManager()->getImage(IMAGE_BLOOD), x, y, 16, 16, 6);
blood->setZ(OFFSET_Y - 1);
int b0 = 0;
if (bloodColor == BaseCreatureEntity::bloodGreen) b0 += 6;
blood->setFrame(b0 + rand()%6);
blood->setType(ENTITY_BLOOD);
blood->setVelocity(Vector2D(rand()%250));
blood->setViscosity(0.95f);
float bloodScale = 1.0f + (rand() % 10) * 0.1f;
blood->setScale(bloodScale, bloodScale);
}
}
void WitchBlastGame::showArtefactDescription(enumItemType itemType)
{
new ArtefactDescriptionEntity(itemType); //, &font);
}
void WitchBlastGame::generateMap()
{
if (currentMap->getRoomType() == roomTypeStandard)
generateStandardMap();
else if (currentMap->getRoomType() == roomTypeBonus)
{
currentMap->setCleared(true);
Vector2D v = currentMap->generateBonusRoom();
int bonusType = getRandomEquipItem(false);
if (bonusType == EQUIP_FAIRY)
{
new ChestEntity(v.x, v.y, CHEST_FAIRY, false);
}
else
{
new ItemEntity( (enumItemType)(FirstEquipItem + bonusType), v.x ,v.y);
}
}
else if (currentMap->getRoomType() == roomTypeKey)
{
Vector2D v = currentMap->generateKeyRoom();
new ItemEntity( (enumItemType)(ItemBossKey), v.x ,v.y);
initMonsterArray();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
monsterArray[x0][y0] = true;
findPlaceMonsters(MONSTER_RAT, 5);
findPlaceMonsters(MONSTER_BAT, 5);
}
else if (currentMap->getRoomType() == roomTypeMerchant)
{
currentMap->generateMerchantRoom();
ItemEntity* item1 = new ItemEntity(
itemHealth,
OFFSET_X + (MAP_WIDTH / 2 - 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT);
item1->setMerchandise(true);
int bonusType = getRandomEquipItem(true);
ItemEntity* item2 = new ItemEntity(
(enumItemType)(FirstEquipItem + bonusType),
OFFSET_X + (MAP_WIDTH / 2 + 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT);
item2->setMerchandise(true);
new PnjEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2 - 2) * TILE_HEIGHT,
0);
currentMap->setCleared(true);
}
else if (currentMap->getRoomType() == roomTypeBoss)
{
currentMap->generateRoom(0);
- new KingRatEntity(OFFSET_X + (MAP_WIDTH / 2 - 2) * TILE_WIDTH + TILE_WIDTH / 2,
+ if (level == 1)
+ new GiantSlimeEntity(OFFSET_X + (MAP_WIDTH / 2 - 2) * TILE_WIDTH + TILE_WIDTH / 2,
+ OFFSET_Y + (MAP_HEIGHT / 2 - 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
+ else
+ new KingRatEntity(OFFSET_X + (MAP_WIDTH / 2 - 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2 - 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
playMusic(MusicBoss);
}
else if (currentMap->getRoomType() == roomTypeStarting)
{
currentMap->generateRoom(0);
currentMap->setCleared(true);
int bonusType = getRandomEquipItem(false);
if (level == 1)
{
if (bonusType == EQUIP_FAIRY)
{
new ChestEntity(OFFSET_X + (TILE_WIDTH * MAP_WIDTH * 0.5f),
OFFSET_Y + 120.0f + (TILE_HEIGHT * MAP_HEIGHT * 0.5f),
CHEST_FAIRY, false);
}
else
{
new ItemEntity( (enumItemType)(FirstEquipItem + bonusType),
OFFSET_X + (TILE_WIDTH * MAP_WIDTH * 0.5f),
OFFSET_Y + 120.0f + (TILE_HEIGHT * MAP_HEIGHT * 0.5f));
}
}
}
else if (currentMap->getRoomType() == roomTypeExit)
{
currentMap->generateExitRoom();
currentMap->setCleared(true);
}
else
currentMap->randomize(currentMap->getRoomType());
}
void WitchBlastGame::Write(std::string str, int size, float x, float y, int align, sf::Color color, sf::RenderTarget* app)
{
myText.setString(str);
myText.setCharacterSize(size);
myText.setColor(color);
if (align == ALIGN_CENTER)
myText.setPosition(x - myText.getLocalBounds().width / 2, y);
else
myText.setPosition(x, y);
app->draw(myText);
}
void WitchBlastGame::initMonsterArray()
{
for (int i = 0; i < MAP_WIDTH; i++)
for (int j = 0; j < MAP_HEIGHT; j++)
monsterArray[i][j] = false;
}
void WitchBlastGame::addMonster(monster_type_enum monsterType, float xm, float ym)
{
switch (monsterType)
{
case MONSTER_RAT: new RatEntity(xm, ym - 2); break;
case MONSTER_BLACK_RAT: new BlackRatEntity(xm, ym - 5); break;
case MONSTER_BAT: new BatEntity(xm, ym); break;
case MONSTER_EVIL_FLOWER: new EvilFlowerEntity(xm, ym - 2); break;
- case MONSTER_SLIME: new SlimeEntity(xm, ym); break;
+ case MONSTER_SLIME: new SlimeEntity(xm, ym, false); break;
case MONSTER_KING_RAT: new KingRatEntity(xm, ym); break;
}
}
void WitchBlastGame::findPlaceMonsters(monster_type_enum monsterType, int amount)
{
// find a suitable place
bool isMonsterFlying = monsterType == MONSTER_BAT;
bool bOk;
int xm, ym;
float xMonster, yMonster;
for (int index = 0; index < amount; index++)
{
bOk = false;
while (!bOk)
{
bOk = true;
xm = 1 +rand() % (MAP_WIDTH - 3);
ym = 1 +rand() % (MAP_HEIGHT - 3);
if (monsterArray[xm][ym])
{
bOk = false;
}
if (bOk && !isMonsterFlying && !currentMap->isWalkable(xm, ym))
{
bOk = false;
}
if (bOk)
{
xMonster = OFFSET_X + xm * TILE_WIDTH + TILE_WIDTH * 0.5f;
yMonster = OFFSET_Y + ym * TILE_HEIGHT+ TILE_HEIGHT * 0.5f;
float dist2 = (xMonster - player->getX())*(xMonster - player->getX()) + (yMonster - player->getY())*(yMonster - player->getY());
if ( dist2 < 75000.0f)
{
bOk = false;
}
else
{
addMonster(monsterType, xMonster, yMonster);
monsterArray[xm][ym] = true;
}
}
}
}
}
void WitchBlastGame::generateStandardMap()
{
initMonsterArray();
int random = rand() % (level == 1 ? 95 : 110);
if (random < 16)
{
currentMap->generateRoom(rand()%4);
findPlaceMonsters(MONSTER_RAT,4);
}
else if (random < 32)
{
currentMap->generateRoom(rand()%5);
findPlaceMonsters(MONSTER_BAT,4);
}
else if (random < 48)
{
currentMap->generateRoom(rand()%5);
findPlaceMonsters(MONSTER_EVIL_FLOWER,4);
}
else if (random < 64)
{
Vector2D v = currentMap->generateBonusRoom();
new ChestEntity(v.x, v.y, CHEST_BASIC, false);
currentMap->setCleared(true);
}
else if (random < 80)
{
currentMap->generateRoom(rand()%4);
findPlaceMonsters(MONSTER_RAT,3);
findPlaceMonsters(MONSTER_BAT,3);
}
else if (random < 95)
{
currentMap->generateRoom(4);
findPlaceMonsters(MONSTER_BLACK_RAT,6);
}
else
{
currentMap->generateRoom(rand()%4);
findPlaceMonsters(MONSTER_SLIME,8 + rand() % 5);
}
}
item_equip_enum WitchBlastGame::getRandomEquipItem(bool toSale = false)
{
std::vector<int> bonusSet;
int setSize = 0;
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++)
{
bool itemOk = true;
int eq = i + FirstEquipItem;
if (player->isEquiped(i)) itemOk = false;
// TODO item already in floor
if (itemOk && toSale && !items[eq].canBeSold) itemOk = false;
if (itemOk && !toSale && !items[eq].canBeFound) itemOk = false;
if (itemOk && items[eq].level > level) itemOk = false;
if (itemOk && items[eq].requirement >= FirstEquipItem
&& !player->isEquiped(i)) itemOk = false;
if (itemOk && player->getShotType(SPECIAL_SHOT_SLOTS_STANDARD) != ShotTypeStandard
&& (items[eq].specialShot != ShotTypeStandard && items[eq].level < 4))
itemOk = false;
if (itemOk)
{
int n = 0;
switch (items[eq].rarity)
{
case RarityCommon: n = 4; break;
case RarityUnommon: n = 2; break;
case RarityRare: n = 1; break;
}
- for (int j = 0; j < n; j++) bonusSet.push_back(i);
- setSize++;
+ for (int j = 0; j < n; j++)
+ {
+ bonusSet.push_back(i);
+ setSize++;
+ }
}
}
int bonusType = 0;
if (setSize > 0) bonusType = bonusSet[rand() % setSize];
return (item_equip_enum) bonusType;
}
void WitchBlastGame::verifyDoorUnlocking()
{
int collidingDirection = (player->getCollidingDirection());
if (collidingDirection > 0 && currentMap->isCleared() && !bossRoomOpened && player->isEquiped(EQUIP_BOSS_KEY))
{
int xt = (player->getX() - OFFSET_X) / TILE_WIDTH;
int yt = (player->getY() - OFFSET_Y) / TILE_HEIGHT;
if (yt <= 1 && xt >= MAP_WIDTH / 2 - 1 && xt <= MAP_WIDTH / 2 + 1 && currentMap->hasNeighbourUp() == 2)
{
doorEntity[0]->openDoor();
currentMap->setTile(MAP_WIDTH / 2, 0, 0);
SoundManager::getSoundManager()->playSound(SOUND_DOOR_OPENING);
player->useBossKey();
bossRoomOpened = true;
}
if (yt >= MAP_HEIGHT - 2 && xt >= MAP_WIDTH / 2 - 1 &&xt <= MAP_WIDTH / 2 + 1 && currentMap->hasNeighbourDown() == 2)
{
doorEntity[2]->openDoor();
currentMap->setTile(MAP_WIDTH / 2, MAP_HEIGHT - 1, 0);
SoundManager::getSoundManager()->playSound(SOUND_DOOR_OPENING);
player->useBossKey();
bossRoomOpened = true;
}
if (xt <= 1 && yt >= MAP_HEIGHT / 2 - 1 && yt <= MAP_HEIGHT / 2 + 1 && currentMap->hasNeighbourLeft() == 2)
{
doorEntity[1]->openDoor();
currentMap->setTile(0, MAP_HEIGHT / 2, 0);
SoundManager::getSoundManager()->playSound(SOUND_DOOR_OPENING);
player->useBossKey();
bossRoomOpened = true;
}
if (xt >= MAP_WIDTH - 2 && yt >= MAP_HEIGHT / 2 - 1 && yt <= MAP_HEIGHT / 2 + 1 && currentMap->hasNeighbourRight() == 2)
{
doorEntity[3]->openDoor();
currentMap->setTile(MAP_WIDTH - 1, MAP_HEIGHT / 2, 0);
SoundManager::getSoundManager()->playSound(SOUND_DOOR_OPENING);
player->useBossKey();
bossRoomOpened = true;
}
}
}
void WitchBlastGame::playMusic(musicEnum musicChoice)
{
music.stop();
music.setLoop(true);
bool ok = false;
switch (musicChoice)
{
case MusicDungeon:
ok = music.openFromFile("media/sound/track00.ogg");
music.setVolume(75);
break;
case MusicEnding:
ok = music.openFromFile("media/sound/track_ending.ogg");
music.setVolume(35);
break;
case MusicBoss:
ok = music.openFromFile("media/sound/track_boss.ogg");
music.setVolume(90);
break;
}
if (ok)
music.play();
}
void WitchBlastGame::makeShake(float duration)
{
xGameState = xGameStateShake;
xGameTimer = duration;
}
void WitchBlastGame::saveGame()
{
ofstream file("game.sav", ios::out | ios::trunc);
int i, j, k, l;
if (file)
{
// floor
file << level << std::endl;
int nbRooms = 0;
for (j = 0; j < FLOOR_HEIGHT; j++)
{
for (i = 0; i < FLOOR_WIDTH; i++)
{
file << currentFloor->getRoom(i,j) << " ";
if (currentFloor->getRoom(i,j) > 0) nbRooms++;
}
file << std::endl;
}
// maps
saveMapItems();
file << nbRooms << std::endl;
for (j = 0; j < FLOOR_HEIGHT; j++)
{
for (i = 0; i < FLOOR_WIDTH; i++)
{
if (currentFloor->getRoom(i,j) > 0)
{
file << i << " " << j << " "
<< currentFloor->getMap(i, j)->getRoomType() << " "
<< currentFloor->getMap(i, j)->isKnown() << " "
<< currentFloor->getMap(i, j)->isVisited() << " "
<< currentFloor->getMap(i, j)->isCleared() << std::endl;
if (currentFloor->getMap(i, j)->isVisited())
{
for (l = 0; l < MAP_HEIGHT; l++)
{
for (k = 0; k < MAP_WIDTH; k++)
{
file << currentFloor->getMap(i, j)->getTile(k, l) << " ";
}
file << std::endl;
}
// items, etc...
std::list<DungeonMap::itemListElement> itemList = currentFloor->getMap(i, j)->getItemList();
file << itemList.size() << std::endl;
std::list<DungeonMap::itemListElement>::iterator it;
for (it = itemList.begin (); it != itemList.end ();)
{
DungeonMap::itemListElement ilm = *it;
it++;
file << ilm.type << " " << ilm.x << " " << ilm.y << " " << ilm.merch << std::endl;
}
// chests
std::list<DungeonMap::chestListElement> chestList = currentFloor->getMap(i, j)->getChestList();
file << chestList.size() << std::endl;
std::list<DungeonMap::chestListElement>::iterator itc;
for (itc = chestList.begin (); itc != chestList.end ();)
{
DungeonMap::chestListElement ilm = *itc;
itc++;
file << ilm.type << " " << ilm.x << " " << ilm.y << " " << ilm.state << std::endl;
}
// sprites
std::list<DungeonMap::spriteListElement> spriteList = currentFloor->getMap(i, j)->getSpriteList();
file << spriteList.size() << std::endl;
std::list<DungeonMap::spriteListElement>::iterator its;
for (its = spriteList.begin (); its != spriteList.end ();)
{
DungeonMap::spriteListElement ilm = *its;
its++;
file << ilm.type << " " << ilm.frame << " " << ilm.x << " " << ilm.y << " " << ilm.scale << std::endl;
}
}
}
}
file << std::endl;
}
// game
file << floorX << " " << floorY << std::endl;
file << bossRoomOpened << std::endl;
// boss door !
// player
file << player->getHp() << " " << player->getHpMax() << " " << player->getGold() << std::endl;
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++) file << player->isEquiped(i) << " ";
file << std::endl;
file << player->getX() << " " << player->getY() << std::endl;
file << player->getShotIndex();
for (i = 0; i < SPECIAL_SHOT_SLOTS; i++) file << " " << player->getShotType(i);
file.close();
}
else
{
cerr << "[ERROR] Saving the game..." << endl;
}
}
bool WitchBlastGame::loadGame()
{
ifstream file("game.sav", ios::in);
if (file)
{
int i, j, k, n;
// floor
file >> level;
currentFloor = new GameFloor(level);
for (j = 0; j < FLOOR_HEIGHT; j++)
{
for (i = 0; i < FLOOR_WIDTH; i++)
{
int n;
file >> n;
currentFloor->setRoom(i, j, n);
}
}
// maps
int nbRooms;
file >> nbRooms;
for (k = 0; k < nbRooms; k++)
{
file >> i;
file >> j;
file >> n;
DungeonMap* iMap = new DungeonMap(currentFloor, i, j);
currentFloor->setMap(i, j, iMap);
iMap->setRoomType((roomTypeEnum)n);
bool flag;
file >> flag;
iMap->setKnown(flag);
file >> flag;
iMap->setVisited(flag);
file >> flag;
iMap->setCleared(flag);
if (iMap->isVisited())
{
for (j = 0; j < MAP_HEIGHT; j++)
{
for (i = 0; i < MAP_WIDTH; i++)
{
file >> n;
iMap->setTile(i, j, n);
}
}
// items int the map
file >> n;
for (i = 0; i < n; i++)
{
int t;
float x, y;
bool merc;
file >> t >> x >> y >> merc;
iMap->addItem(t, x, y, merc);
}
// chests in the map
file >> n;
for (i = 0; i < n; i++)
{
int t;
float x, y;
bool state;
file >> t >> x >> y >> state;
iMap->addChest(t, state, x, y);
}
// sprites in the map
file >> n;
for (i = 0; i < n; i++)
{
int t, f;
float x, y, scale;
file >> t >> f >> x >> y >> scale;
iMap->addSprite(t, f, x, y, scale);
}
}
}
// game
file >> floorX >> floorY;
currentMap = currentFloor->getMap(floorX, floorY);
file >> bossRoomOpened;
// player
int hp, hpMax, gold;
file >> hp >> hpMax >> gold;
player = new PlayerEntity(OFFSET_X + (TILE_WIDTH * MAP_WIDTH * 0.5f),
OFFSET_Y + (TILE_HEIGHT * MAP_HEIGHT * 0.5f));
player->setHp(hp);
player->setHpMax(hpMax);
player->setGold(gold);
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++)
{
bool eq;
file >> eq;
player->setEquiped(i, eq);
}
float x, y;
file >> x >> y;
player->moveTo(x, y);
file >> n;
player->setShotIndex(n);
for (i = 0; i < SPECIAL_SHOT_SLOTS; i++)
{
file >> n;
player->setShotType(i, (enumShotType)n);
}
file.close();
remove("game.sav");
}
else
{
return false;
}
return true;
}
void WitchBlastGame::addKey(int logicInput, std::string key, bool alt = false)
{
int iKey = config.findInt(key);
if (iKey >= 0)
{
sf::Keyboard::Key k = (sf::Keyboard::Key)iKey;
if (alt)
inputAlt[logicInput] = k;
else
input[logicInput] = k;
}
}
void WitchBlastGame::configureFromFile()
{
// default
input[KeyUp] = sf::Keyboard::Z;
input[KeyDown] = sf::Keyboard::S;
input[KeyLeft] = sf::Keyboard::Q;
input[KeyRight] = sf::Keyboard::D;
input[KeyFireUp] = sf::Keyboard::Up;
input[KeyFireDown] = sf::Keyboard::Down;
input[KeyFireLeft] = sf::Keyboard::Left;
input[KeyFireRight] = sf::Keyboard::Right;
input[KeyFire] = sf::Keyboard::Space;
input[KeyFireSelect] = sf::Keyboard::Tab;
inputAlt[KeyUp] = sf::Keyboard::W;
inputAlt[KeyDown] = sf::Keyboard::S;
inputAlt[KeyLeft] = sf::Keyboard::A;
inputAlt[KeyRight] = sf::Keyboard::D;
inputAlt[KeyFireUp] = sf::Keyboard::Up;
inputAlt[KeyFireDown] = sf::Keyboard::Down;
inputAlt[KeyFireLeft] = sf::Keyboard::Left;
inputAlt[KeyFireRight] = sf::Keyboard::Right;
inputAlt[KeyFire] = sf::Keyboard::Space;
inputAlt[KeyFireSelect] = sf::Keyboard::Tab;
// from file
addKey(KeyUp, "keyboard_move_up");
addKey(KeyDown, "keyboard_move_down");
addKey(KeyLeft, "keyboard_move_left");
addKey(KeyRight, "keyboard_move_right");
addKey(KeyFireUp, "keyboard_fire_up");
addKey(KeyFireDown, "keyboard_fire_down");
addKey(KeyFireLeft, "keyboard_fire_left");
addKey(KeyFireRight, "keyboard_fire_right");
addKey(KeyFire, "keyboard_fire");
addKey(KeyFireSelect, "keyboard_fire_select");
addKey(KeyUp, "keyboard_move_up_alt", true);
addKey(KeyDown, "keyboard_move_down_alt", true);
addKey(KeyLeft, "keyboard_move_left_alt", true);
addKey(KeyRight, "keyboard_move_right_alt", true);
addKey(KeyFireUp, "keyboard_fire_up_alt", true);
addKey(KeyFireDown, "keyboard_fire_down_alt", true);
addKey(KeyFireLeft, "keyboard_fire_left_alt", true);
addKey(KeyFireRight, "keyboard_fire_right_alt", true);
addKey(KeyFire, "keyboard_fire_alt", true);
addKey(KeyFireSelect, "keyboard_fire_select_alt", true);
}
WitchBlastGame &game()
{
return *gameptr;
}
diff --git a/src/WitchBlastGame.h b/src/WitchBlastGame.h
index 7bdc68f..12bad06 100644
--- a/src/WitchBlastGame.h
+++ b/src/WitchBlastGame.h
@@ -1,446 +1,444 @@
/** 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 WITCH_BLAST_GAME_H
#define WITCH_BLAST_GAME_H
#include "sfml_game/Game.h"
#include "sfml_game/TileMapEntity.h"
#include "PlayerEntity.h"
#include "EnnemyEntity.h"
#include "DoorEntity.h"
#include "GameFloor.h"
#include "Config.h"
const int ALIGN_LEFT = 0; /*!< Text alignment left */
const int ALIGN_RIGHT = 1; /*!< Text alignment right */
const int ALIGN_CENTER = 2; /*!< Text alignment centered */
/*! \class WitchBlastGame
* \brief Main class of the game
*
* WitchBlastGame load the game ressources and do a large part of the game logic (game loop...),
* watches the input, manages the game states, ...
*/
class WitchBlastGame : public Game
{
public:
/*!
* \brief Constructor
*
* Constructor of the WitchBlastGame class.
*/
WitchBlastGame();
/*!
* \brief Destructor
*
* Destructor of the WitchBlastGame class.
*/
virtual ~WitchBlastGame();
/*!
* \brief Accessor on the current dungeon map
*
* Accessor on the current dungeon map (room).
*
* \return a pointer to the current dungeon map
*/
DungeonMap* getCurrentMap();
/*!
* \brief Accessor on the player
*
* Accessor on the player.
*
* \return a pointer to the player
*/
PlayerEntity* getPlayer();
/*!
* \brief Accessor on the player's position
*
* Accessor on the player's position.
*
* \return a Vector2D of the player's position
*/
Vector2D getPlayerPosition();
/*!
* \brief accessor on the level
*
* Accessor on the level.
*
* \return : the level
*/
int getLevel();
/*!
* \brief Start the game and the game loop
*
* This method starts the game and the game loop.
* The game loop watches the events, the inputs, update and draw the game elements.
*/
virtual void startGame();
/*!
* \brief Move the player to another map (room)
*
* Moves the player to another room of the dungeon.
* It's called when a player walk through an opened door.
*
* \param direction : direction of the new map. 4 = left, 8 = north, 6 = right, 2 = south
*/
void moveToOtherMap(int direction);
/*!
* \brief Closes the doors of the room
*
* Closes the doors of the room.
* It's called when the player enter in an area with monsters.
*/
void closeDoors();
/*!
* \brief Opens the doors of the room
*
* Opens the doors of the room.
* It's called when the player destroy the last monster of a room.
*/
void openDoors();
/*!
* \brief Count the enemies in the room
*
* Count the enemies in the room.
* It's called when the room is closed : 0 enemy = room is cleared and doors shall open.
*
* \return amount of enemies
*/
int getEnnemyCount();
/*!
* \brief Generates blood
*
* Generates blood, it's called when someone is hurt or dies.
*
* \param x : x position of the blood
* \param y : y position of the blood
* \param bloodColor : color of the blood (red; green, ...)
*/
void generateBlood(float x, float y, BaseCreatureEntity::enumBloodColor bloodColor);
/*!
* \brief Show a "popup" with artefact's description
*
* Show a "popup" with artefact's description.
* Artefact's description consists of zoomed picture of the item, name and description.
* It's called when a player get an equipment item.
*
* \param itemType : item identifier
*/
void showArtefactDescription(enumItemType itemType);
/*!
* \brief Make a "shake" effet
* \param duration : duration of the effect
*/
void makeShake(float duration);
void Write(std::string str, int size, float x, float y, int align, sf::Color color, sf::RenderTarget* app);
/*!
* \brief Save the game
*
* Save the game to file : complete floor and maps, items and blood position, player current equipment and stats....
*/
void saveGame();
/*!
* \brief Load the game
*
* Load the game from file. After restoring the game, the file is destroy.
*
* \return true if succeeded
*/
bool loadGame();
protected:
/*!
* \brief Rendering method
*
* Render all the game objects to the screen.
* Called in the game loop.
*/
virtual void onRender();
/*!
* \brief Update method
*
* Update all the game objects to the screen.
* Called in the game loop.
*/
virtual void onUpdate();
/*!
* \brief render the HUD for shot types
*
* Render the HUD for shot types.
* Display the available shot types and highlight the current one.
*
* \param app : Rendering target
*/
void renderHudShots(sf::RenderTarget* app);
private:
Config config;
// game logic / data
GameMap* miniMap; /*!< Pointer to the logical minimap */
DungeonMap* currentMap; /*!< Pointer to the logical current map */
GameFloor* currentFloor; /*!< Pointer to the logical floor (level) */
// game play
int level; /*!< Level (floor) */
int floorX; /*!< X position of the room in the level */
int floorY; /*!< Y position of the room in the level */
bool roomClosed; /*!< True if the room is closed */
bool bossRoomOpened; /*!< True if the boss gate has been opened in this level */
bool isPausing; /*!< True if the game is currently pausing */
int firingDirection; /*!< Save the firing direction - for the "one button" gameplay */
bool isPlayerAlive; /*!< Dying sets this bool to false (trigger the ending music) */
bool monsterArray[MAP_WIDTH][MAP_HEIGHT]; /*!< use to remember if a case has a monster in monster spawn */
// game objects
PlayerEntity* player; /*!< Pointer to the player entity */
TileMapEntity* currentTileMap; /*!< TileMap of the room (main game board) */
// displaying objects
DoorEntity* doorEntity[4]; /*!< Pointers to the door graphical entity */
sf::Sprite keySprite; /*!< A simple sprite with the boss key (displayed on the HUD) */
sf::Sprite shotsSprite; /*!< A simple sprite for the available shot types (displayed on the HUD) */
sf::Font font; /*!< The font used for displaying text */
sf::Text myText; /*!< The text to be displayed */
- sf::RenderTexture mainTexture; /*!< The main game in a texture */
- sf::Sprite mainSprite; /*!< The main game in a sprite */
sf::Music music; /*!< Current game music */
/** Music enum
* Identify the various music tracks of the game.
*/
enum musicEnum
{
MusicDungeon, /**< Main game music - played when playing the game */
MusicEnding, /**< Ending music - played when the player has died */
MusicBoss /**< Boss music - for epic fights ! */
};
/** Game states enum
* Used for the different game states
*/
enum gameStateEnum
{
gameStateInit, /**< Game initialization */
gameStatePlaying, /**< Playing */
gameStateKeyConfig /**< Key config */
};
gameStateEnum gameState; /*!< Store the game state */
/** Special game states enum
* Used for effects such as fade in...
*/
enum xGameStateEnum
{
xGameStateNone, /**< No effect */
xGameStateFadeIn, /**< Fade in effect - usually when starting a level */
xGameStateFadeOut, /**< Fade out effect - usually when leaving a level */
xGameStateShake /**< Shake effect */
};
xGameStateEnum xGameState; /*!< Store the effect game state */
float xGameTimer; /*!< Effect game timer */
/** Input Keys enum
* Used for the input binding
*/
enum inputKeyEnum
{
KeyUp,
KeyDown,
KeyLeft,
KeyRight,
KeyFireUp,
KeyFireDown,
KeyFireLeft,
KeyFireRight,
KeyFire,
KeyFireSelect
};
sf::Keyboard::Key input[10]; /*!< Input key array */
sf::Keyboard::Key inputAlt[10]; /*!< Input key array (alternative) */
/*!
* \brief Starts the game
*
* Start a new game or load it from file.
*
* \param fromSaveFile : true if we want to try to load the game from a file
*/
void startNewGame(bool fromSaveFile);
/*!
* \brief Starts a new level
*
* Start a new level.
* Called for each level of the game.
*/
void startNewLevel();
/*!
* \brief Starts the level
*
* Starts the level.
* Called after loading the game or creating a new level.
*/
void playLevel();
/*!
* \brief Creates a level
*
* Creates a random level (a level is a floor that consists of rooms).
*/
void createFloor();
/*!
* \brief Create or refresh the room
*
* Create a room (if this is a new one) or refresh it.
* Called when the player changes room.
* Checks the visibility of the doors and close it if there are monsters.
* Loads the mas items and sprites.
*/
void refreshMap();
/*!
* \brief Refreshes the minimap
*
* Refresh the minimap.
* Called when the player changes room.
*/
void refreshMinimap();
/*!
* \brief Generates a room
*
* Generates a room.
* Called when the player moves to a room for the first time.
*/
void generateMap();
/*!
* \brief Generates a standard room
*
* Generates a standard room with monsters.
* Called during the generation when the map has no particular type.
*/
void generateStandardMap();
/*!
* \brief Checks if the room will be closed
*
* Checks if the room will be closed.
* Called when entering a room. If the room is not clear, closes the doors.
*/
void checkEntering();
/*!
* \brief Saves the map items
*
* Saves the map objects such as items, corpses, blood, chest.
* Called when leaving the door.
*/
void saveMapItems();
/*!
* \brief Initializes the monster array
*
* Initializes the monster array (to empty).
*/
void initMonsterArray();
/*!
* \brief Adds a monster
*
* Adds a monster to the room.
* \param monsterType : monster type
* \param xm : x position of the monster
* \param ym : y position of the monster
*/
void addMonster(monster_type_enum monsterType, float xm, float ym);
/*!
* \brief Adds monsters
*
* Adds monsters to the room in suitable places.
* \param monsterType : monster type
* \param amount : amount of monsters
*/
void findPlaceMonsters(monster_type_enum monsterType, int amount);
/*!
* \brief Returns a random equip object
*
* Returns a random equip object (not an object the player already possesses) .
* \param toSale : true if it's an item for sale
*
* \return the equipment item ID
*/
item_equip_enum getRandomEquipItem(bool toSale);
/*!
* \brief Checks if player opens a door
*
* Checks if player opens a door (collide with the door and gets the key).
* If positive, opens the door.
*/
void verifyDoorUnlocking();
/*!
* \brief Plays a music
*
* Plays a music.
*
* \param musicChoice : music track ID
*/
void playMusic(musicEnum musicChoice);
void addKey(int logicInput, std::string key, bool alt);
/*!
* \brief Configure with data from "config.dat"
*/
void configureFromFile();
};
/*!
* \brief Returns the game reference
*
* Returns the game reference.
*
* \return a reference to the game
*/
WitchBlastGame& game();
#endif // WITCH_BLAST_GAME_H

File Metadata

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

Event Timeline