Page MenuHomePhabricator (Chris)

No OneTemporary

Authored By
Unknown
Size
315 KB
Referenced Files
None
Subscribers
None
This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/media/dungeon_objects.png b/media/dungeon_objects.png
index 2778b13..05ba674 100644
Binary files a/media/dungeon_objects.png and b/media/dungeon_objects.png differ
diff --git a/media/tiles.png b/media/tiles.png
new file mode 100644
index 0000000..90ecb32
Binary files /dev/null and b/media/tiles.png differ
diff --git a/media/tiles01.png b/media/tiles01.png
deleted file mode 100644
index ead999c..0000000
Binary files a/media/tiles01.png and /dev/null differ
diff --git a/media/tiles02.png b/media/tiles02.png
deleted file mode 100644
index c39e70b..0000000
Binary files a/media/tiles02.png and /dev/null differ
diff --git a/media/tiles03.png b/media/tiles03.png
deleted file mode 100644
index 4355326..0000000
Binary files a/media/tiles03.png and /dev/null differ
diff --git a/media/tiles04.png b/media/tiles04.png
deleted file mode 100644
index 90fd658..0000000
Binary files a/media/tiles04.png and /dev/null differ
diff --git a/media/tiles05.png b/media/tiles05.png
deleted file mode 100644
index 6caa929..0000000
Binary files a/media/tiles05.png and /dev/null differ
diff --git a/media/tiles06.png b/media/tiles06.png
deleted file mode 100644
index 11fd216..0000000
Binary files a/media/tiles06.png and /dev/null differ
diff --git a/media/tiles07.png b/media/tiles07.png
deleted file mode 100644
index 8698f19..0000000
Binary files a/media/tiles07.png and /dev/null differ
diff --git a/src/DungeonMap.cpp b/src/DungeonMap.cpp
index 6ed0806..2d75797 100644
--- a/src/DungeonMap.cpp
+++ b/src/DungeonMap.cpp
@@ -1,1519 +1,1528 @@
#include "DungeonMap.h"
#include "GameFloor.h"
#include "ItemEntity.h"
#include "ChestEntity.h"
#include "sfml_game/ImageManager.h"
#include <cstdlib>
#include <stdio.h>
#include <iostream>
#include "WitchBlastGame.h"
DungeonMap::DungeonMap(int width, int height) : GameMap(width, height)
{
}
DungeonMap::DungeonMap(GameFloor* gameFloor, int x, int y) : GameMap(MAP_WIDTH, MAP_HEIGHT)
{
this->gameFloor = gameFloor;
this->x = x;
this->y = y;
cleared = false;
visited = false;
known = false;
randomTileElement.type = -1;
randomTileElement.x = 0;
randomTileElement.y = 0;
randomTileElement.rotation = 0;
}
DungeonMap::~DungeonMap()
{
}
bool DungeonMap::isVisited()
{
return visited;
}
void DungeonMap::setVisited(bool b)
{
visited = b;
}
bool DungeonMap::isKnown()
{
return known;
}
void DungeonMap::setKnown(bool b)
{
known = b;
}
bool DungeonMap::isCleared()
{
return cleared;
}
void DungeonMap::setCleared(bool b)
{
cleared = b;
}
roomTypeEnum DungeonMap::getRoomType()
{
return roomType;
}
void DungeonMap::setRoomType(roomTypeEnum roomType)
{
this->roomType = roomType;
}
int DungeonMap::getObjectTile(int x, int y)
{
return objectsMap[x][y];
}
int DungeonMap::getShadowTile(int x, int y)
{
return shadowMap[x][y];
}
bool DungeonMap::getLogicalTile(int x, int y)
{
return logicalMap[x][y];
}
void DungeonMap::setObjectTile(int x, int y, int n)
{
objectsMap[x][y] = n;
}
void DungeonMap::setShadowTile(int x, int y, int n)
{
shadowMap[x][y] = n;
}
void DungeonMap::setLogicalTile(int x, int y, logicalMapStateEnum state)
{
logicalMap[x][y] = state;
}
std::list<DungeonMap::itemListElement> DungeonMap::getItemList()
{
return (itemList);
}
std::list<DungeonMap::chestListElement> DungeonMap::getChestList()
{
return (chestList);
}
std::list<DungeonMap::spriteListElement> DungeonMap::getSpriteList()
{
return (spriteList);
}
DungeonMap::RandomTileElement DungeonMap::getRandomTileElement()
{
return randomTileElement;
}
void DungeonMap::setRandomTileElement (RandomTileElement rt)
{
randomTileElement = rt;
hasChanged = true;
}
void DungeonMap::displayToConsole()
{
for (int j=0; j < MAP_HEIGHT; j++)
{
for (int i=0; i < MAP_WIDTH; i++)
{
printf("%d", map[i][j]);
}
printf("\n");
}
printf("\n");
}
bool DungeonMap::isDownBlocking(int x, int y)
{
if (!inMap(x, y)) return false;
return (logicalMap[x][y] != LogicalFloor);
}
bool DungeonMap::isUpBlocking(int x, int y)
{
if (!inMap(x, y)) return false;
return (logicalMap[x][y] != LogicalFloor);
}
bool DungeonMap::isLeftBlocking(int x, int y)
{
if (!inMap(x, y)) return false;
return (logicalMap[x][y] != LogicalFloor);
}
bool DungeonMap::isRightBlocking(int x, int y)
{
if (!inMap(x, y)) return false;
return (logicalMap[x][y] != LogicalFloor);
}
bool DungeonMap::isWalkable(int x, int y)
{
if (!inMap(x, y)) return true;
if (roomType == roomTypeKey && !cleared)
{
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
if (x >= x0 - 1 && x <= x0 +1 && y >= y0 - 1 && y <= y0 + 1)
return false;
}
return (logicalMap[x][y] == LogicalFloor);
}
bool DungeonMap::isFlyable(int x, int y)
{
if (x < 0) return true;
if (x > MAP_WIDTH - 1) return true;
if (y < 0) return true;
if (y > MAP_HEIGHT - 1) return true;
return (logicalMap[x][y] != LogicalWall);
}
bool DungeonMap::isShootable(int x, int y)
{
if (!inMap(x, y)) return true;
return (logicalMap[x][y] != LogicalWall && logicalMap[x][y] != LogicalObstacle);
}
bool DungeonMap::containsHealth()
{
ItemList::iterator it;
for (it = itemList.begin (); it != itemList.end ();)
{
itemListElement ilm = *it;
it++;
if (ilm.type >= ItemHealthVerySmall && ilm.type <= ItemHealthVerySmallPoison)
return true;
}
return false;
}
void DungeonMap::randomize(int n)
{
int i, j;
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
initRoom();
// bonus
if (n == 5)
{
roomType = roomTypeBonus;
}
// others
else if (n > 0)
{
int r = rand() % 4;
if (r == 0) // corner blocks
{
map[1][1] = 4;
map[1][MAP_HEIGHT -2] = 4;
map[MAP_WIDTH - 2][1] = 4;
map[MAP_WIDTH - 2][MAP_HEIGHT -2] = 4;
}
else if (r == 1) // bloc in the middle
{
for (i = x0-1; i <= x0+1; i++)
for (j = y0-1; j <= y0+1; j++)
map[i][j] = 4;
}
else if (r == 2) // checker
{
for (i = 2; i < MAP_WIDTH - 2; i = i + 2)
for (j = 2; j < MAP_HEIGHT - 2; j = j + 2)
map[i][j] = 4;
}
cleared = false;
roomType = (roomTypeEnum)(rand() % 3);
}
else
{
cleared = true;
}
}
int DungeonMap::hasNeighbourLeft()
{
if (x > 0 && gameFloor->getRoom(x-1, y) > 0)
{
if (gameFloor->getRoom(x-1, y) == roomTypeBoss) return 2;
else return 1;
}
return 0;
}
int DungeonMap::hasNeighbourRight()
{
if (x < MAP_WIDTH -1 && gameFloor->getRoom(x+1, y) > 0)
{
if (gameFloor->getRoom(x+1, y) == roomTypeBoss) return 2;
else return 1;
}
return 0;
}
int DungeonMap::hasNeighbourUp()
{
if (y > 0 && gameFloor->getRoom(x, y-1) > 0)
{
if (gameFloor->getRoom(x, y-1) == roomTypeBoss) return 2;
else return 1;
}
return 0;
}
int DungeonMap::hasNeighbourDown()
{
if (y < MAP_HEIGHT -1 && gameFloor->getRoom(x, y+1) > 0)
{
if (gameFloor->getRoom(x, y+1) == roomTypeBoss) return 2;
else return 1;
}
return 0;
}
roomTypeEnum DungeonMap::getNeighbourLeft()
{
if (x > 0) return gameFloor->getRoom(x - 1, y);
else return roomTypeNULL;
}
roomTypeEnum DungeonMap::getNeighbourRight()
{
if (x < MAP_WIDTH - 1) return gameFloor->getRoom(x + 1, y);
else return roomTypeNULL;
}
roomTypeEnum DungeonMap::getNeighbourUp()
{
if (y > 0) return gameFloor->getRoom(x, y - 1);
else return roomTypeNULL;
}
roomTypeEnum DungeonMap::getNeighbourDown()
{
if (y < MAP_HEIGHT - 1) return gameFloor->getRoom(x, y + 1);
else return roomTypeNULL;
}
int DungeonMap::getDivinity(int x, int y)
{
if (x <= 0 || (x >= MAP_WIDTH - 1) || y <= 0 || (y >= MAP_HEIGHT - 1)) return -1;
if (map[x][y] >= MAP_TEMPLE && map[x][y] < MAP_TEMPLE + NB_DIVINITY)
return (map[x][y] - MAP_TEMPLE);
else
return -1;
}
void DungeonMap::initRoom()
{
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
int i, j;
+ // outer walls
map[0][0] = MAP_WALL_7;
for ( i = 1 ; i < width -1 ; i++)
{
if (i == width / 2)
{
map[i][0] = MAP_WALL_8;
- map[i][height - 1] = MAP_WALL_2;
+ map[i][height - 1] = MAP_WALL_8;
}
else if (i < width / 2)
{
map[i][0] = MAP_WALL_87;
- map[i][height - 1] = MAP_WALL_21;
+ map[i][height - 1] = MAP_WALL_87;
}
else
{
- map[i][0] = MAP_WALL_89;
- map[i][height - 1] = MAP_WALL_23;
+ map[i][0] = MAP_WALL_87;
+ map[i][height - 1] = MAP_WALL_87;
}
}
- map[width - 1][0] = MAP_WALL_9;
+ map[width - 1][0] = MAP_WALL_7;
for ( int i = 1 ; i < height -1 ; i++)
{
if (i == height / 2)
{
- map[0][i] = MAP_WALL_4;
- map[width - 1][i] = MAP_WALL_6;
+ map[0][i] = MAP_WALL_8;
+ map[width - 1][i] = MAP_WALL_8;
}
else if (i < height / 2)
{
- map[0][i] = MAP_WALL_47;
- map[width - 1][i] = MAP_WALL_69;
+ map[0][i] = MAP_WALL_87;
+ map[width - 1][i] = MAP_WALL_87;
}
else
{
- map[0][i] = MAP_WALL_41;
- map[width - 1][i] = MAP_WALL_63;
+ map[0][i] = MAP_WALL_87;
+ map[width - 1][i] = MAP_WALL_87;
}
}
- map[0][height - 1] = MAP_WALL_1;
- map[width - 1][height - 1] = MAP_WALL_3;
-
+ map[0][height - 1] = MAP_WALL_7;
+ map[width - 1][height - 1] = MAP_WALL_7;
+ // floor
+ // TODO others
+ int floorOffset = (game().getLevel() - 1) * 24;
for ( j = 1 ; j < height - 1 ; j++)
+ {
for ( i = 1 ; i < width - 1 ; i++)
{
- map[i][j] = rand()%(MAP_NORMAL_FLOOR + 1);
+ map[i][j] = floorOffset + rand()%(MAP_NORMAL_FLOOR);
while (map[i][j] == map[i - 1][j] || map[i][j] == map[i][j - 1] || map[i][j] == map[i - 1][j - 1] || map[i][j] == map[i + 1][j - 1])
- map[i][j] = rand()%(MAP_NORMAL_FLOOR + 1);
+ map[i][j] = floorOffset + rand()%(MAP_NORMAL_FLOOR);
}
+ }
- for ( j = 0 ; j < height; j++)
- for ( i = 0 ; i < width; i++)
- {
- objectsMap[i][j] = 0;
- shadowMap[i][j] = MAPSHAD_EMPTY;
- if (i == 0 || j == 0 || i == width - 1 || j == height - 1)
- logicalMap[i][j] = LogicalWall;
- else
- logicalMap[i][j] = LogicalFloor;
- }
+ // objects
+ for ( j = 0 ; j < height; j++)
+ {
+ for ( i = 0 ; i < width; i++)
+ {
+ objectsMap[i][j] = 0;
+ shadowMap[i][j] = MAPSHAD_EMPTY;
+ if (i == 0 || j == 0 || i == width - 1 || j == height - 1)
+ logicalMap[i][j] = LogicalWall;
+ else
+ logicalMap[i][j] = LogicalFloor;
+ }
+ }
+ // doors ?
if (gameFloor != NULL)
{
if (x > 0 && gameFloor->getRoom(x-1, y) > 0)
openDoor(0, y0);
if (x < MAP_WIDTH -1 && gameFloor->getRoom(x+1, y) > 0)
openDoor(MAP_WIDTH -1, y0);
if (y > 0 && gameFloor->getRoom(x, y-1) > 0)
openDoor(x0, 0);
if (y < MAP_HEIGHT -1 && gameFloor->getRoom(x, y+1) > 0)
openDoor(x0, MAP_HEIGHT -1);
}
// alternative floor
for (i = 0; i < 8; i++)
{
if (rand() % 2 > 0)
{
- map[1 + rand() % (MAP_WIDTH - 2)][1 + rand() % (MAP_HEIGHT - 2)] = 20 + i;
+ map[1 + rand() % (MAP_WIDTH - 2)][1 + rand() % (MAP_HEIGHT - 2)] = floorOffset + 16 + i;
}
}
// alternative walls
for (i = 0; i < 9; i++)
{
if (rand() % 2 > 0)
{
int xTile = 0;
int yTile = 0;
int horizontal = rand() % 2;
if (horizontal == 0)
{
yTile = rand() % 2 == 0 ? 0 : MAP_HEIGHT - 1;
xTile = 1 + rand() % 12;
if (xTile > 6) xTile++;
}
else
{
xTile = rand() % 2 == 0 ? 0 : MAP_WIDTH - 1;
yTile = 1 + rand() % 6;
if (yTile > 3) yTile++;
}
map[xTile][yTile] = i + MAP_WALL_ALTERN;
}
}
if (hasNeighbourUp() && rand() % 3 == 0)
{
map[x0 - 2][0] = 9 + MAP_WALL_ALTERN;
map[x0 + 2][0] = 9 + MAP_WALL_ALTERN;
}
if (hasNeighbourDown() && rand() % 3 == 0)
{
map[x0 - 2][MAP_HEIGHT - 1] = 9 + MAP_WALL_ALTERN;
map[x0 + 2][MAP_HEIGHT - 1] = 9 + MAP_WALL_ALTERN;
}
if (hasNeighbourLeft() && rand() % 3 == 0)
{
map[0][y0 - 2] = 9 + MAP_WALL_ALTERN;
map[0][y0 + 2] = 9 + MAP_WALL_ALTERN;
}
if (hasNeighbourRight() && rand() % 3 == 0)
{
map[MAP_WIDTH - 1][y0 - 2] = 9 + MAP_WALL_ALTERN;
map[MAP_WIDTH - 1][y0 + 2] = 9 + MAP_WALL_ALTERN;
}
// shadows
for (int i = 0; i < MAP_WIDTH; i++)
{
if (i == 0)
{
shadowMap[i][0] = MAPSHAD_7;
shadowMap[i][MAP_HEIGHT - 1] = MAPSHAD_1;
}
else if (i == 1)
{
shadowMap[i][0] = MAPSHAD_87;
shadowMap[i][MAP_HEIGHT - 1] = MAPSHAD_21;
shadowMap[i][1] = MAPSHAD_GROUND_7;
shadowMap[i][MAP_HEIGHT - 2] = MAPSHAD_GROUND_1;
}
else if (i == MAP_WIDTH - 1)
{
shadowMap[i][0] = MAPSHAD_9;
shadowMap[i][MAP_HEIGHT - 1] = MAPSHAD_3;
}
else if (i == MAP_WIDTH - 2)
{
shadowMap[i][0] = MAPSHAD_89;
shadowMap[i][MAP_HEIGHT - 1] = MAPSHAD_23;
shadowMap[i][1] = MAPSHAD_GROUND_9;
shadowMap[i][MAP_HEIGHT - 2] = MAPSHAD_GROUND_3;
}
else
{
shadowMap[i][0] = MAPSHAD_8;
shadowMap[i][MAP_HEIGHT - 1] = MAPSHAD_2;
shadowMap[i][1] = MAPSHAD_GROUND_8;
shadowMap[i][MAP_HEIGHT - 2] = MAPSHAD_GROUND_2;
}
}
for (int i = 1; i < MAP_HEIGHT - 1; i++)
{
if (i == 1)
{
shadowMap[0][i] = MAPSHAD_47;
shadowMap[MAP_WIDTH - 1][i] = MAPSHAD_69;
}
else if (i == MAP_HEIGHT - 2)
{
shadowMap[0][i] = MAPSHAD_41;
shadowMap[MAP_WIDTH - 1][i] = MAPSHAD_63;
}
else
{
shadowMap[0][i] = MAPSHAD_4;
shadowMap[MAP_WIDTH - 1][i] = MAPSHAD_6;
shadowMap[1][i] = MAPSHAD_GROUND_4;
shadowMap[MAP_WIDTH - 2][i] = MAPSHAD_GROUND_6;
}
}
}
void DungeonMap::openDoor(int x, int y)
{
objectsMap[x][y] = MAPOBJ_DOOR_OPEN;
logicalMap[x][y] = LogicalFloor;
}
void DungeonMap::closeDoor(int x, int y)
{
objectsMap[x][y] = MAPOBJ_DOOR_CLOSED;
logicalMap[x][y] = LogicalWall;
}
bool DungeonMap::isDoor(int x, int y)
{
return objectsMap[x][y] == MAPOBJ_DOOR_OPEN || objectsMap[x][y] == MAPOBJ_DOOR_CLOSED;
}
void DungeonMap::makePatternTile(int x, int y)
{
- if (map[x][y] < 10) map[x][y] += 10;
- else map[x][y] = 10;
+ if (map[x][y] < 24 * 8 && (map[x][y] % 24) < 8) map[x][y] += 8;
+ else map[x][y] = (game().getLevel() - 1) * 24 + 8;
}
void DungeonMap::initPattern(patternEnum n)
{
int i, j;
if (n == PatternSmallChecker)
{
for ( i = 2 ; i < width - 2 ; i++)
for ( j = 2 ; j < height - 2 ; j++)
{
if ((i + j) % 2 == 1) makePatternTile(i, j);
}
}
if (n == PatternBigChecker)
{
for ( i = 1 ; i < width - 1 ; i++)
for ( j = 1 ; j < height - 1 ; j++)
{
if ((i + j) % 2 == 1) makePatternTile(i, j);
}
}
if (n == PatternBorder)
{
for ( i = 1 ; i < width - 1 ; i++)
for ( j = 1 ; j < height - 1 ; j++)
{
if (i == 1 || j == 1 || i == width - 2 || j == height - 2)
makePatternTile(i, j);
}
}
if (n == PatternBigCircle)
{
for ( i = 2 ; i < width - 2 ; i++)
for ( j = 2 ; j < height - 2 ; j++)
{
if (i == 2 || j == 2 || i == width - 3 || j == height - 3)
makePatternTile(i, j);
}
}
if (n == PatternSmallCircle || n == PatternSmallStar)
{
for ( i = 5 ; i < 10 ; i++)
for ( j = 2 ; j < height - 2 ; j++)
{
if (i == 5 || i == 9 || j == 2 || j == height - 3)
makePatternTile(i, j);
}
}
if (n == PatternSmallStar)
{
makePatternTile(7, 1);
makePatternTile(7, height - 2);
makePatternTile(4, 4);
makePatternTile(10, 4);
}
if (n == PatternSmallDisc)
{
for ( i = 5 ; i < 10 ; i++)
for ( j = 2 ; j < height - 2 ; j++)
{
makePatternTile(i, j);
}
}
}
Vector2D DungeonMap::generateBonusRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
if (rand() % 3 == 0)
{
if (rand() % 2 == 0) initPattern(PatternSmallDisc);
else initPattern(PatternSmallStar);
}
objectsMap[x0 - 1][y0 - 1] = MAPOBJ_WALL_SPECIAL;
objectsMap[x0 - 1][y0 + 1] = MAPOBJ_WALL_SPECIAL + 2;
objectsMap[x0 + 1][y0 - 1] = MAPOBJ_WALL_SPECIAL + 1;
objectsMap[x0 + 1][y0 + 1] = MAPOBJ_WALL_SPECIAL + 3;
logicalMap[x0 - 1][y0 - 1] = LogicalObstacle;
logicalMap[x0 - 1][y0 + 1] = LogicalObstacle;
logicalMap[x0 + 1][y0 - 1] = LogicalObstacle;
logicalMap[x0 + 1][y0 + 1] = LogicalObstacle;
generateRandomTile();
return (Vector2D(x0 * TILE_WIDTH + TILE_WIDTH / 2, y0 * TILE_HEIGHT + TILE_HEIGHT / 2));
}
void DungeonMap::generateTemple(int x, int y, enumDivinityType type)
{
map[x][y] = MAP_TEMPLE + (int)type;
addHole(x - 1, y - 2);
addHole(x - 1, y - 1);
addHole(x - 1, y);
addHole(x + 1, y - 2);
addHole(x + 1, y - 1);
addHole(x + 1, y );
objectsMap[x][y - 2] = MAPOBJ_TEMPLE_WALL + (int)type;
objectsMap[x][y - 1] = MAPOBJ_TEMPLE_WALL + 10 + (int)type;
logicalMap[x][y - 2] = LogicalObstacle;
logicalMap[x][y - 1] = LogicalObstacle;
}
void DungeonMap::generateTempleRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = 1 + MAP_HEIGHT / 2;
if (rand() % 3 == 0)
{
if (rand() % 2 == 0) initPattern(PatternSmallDisc);
else initPattern(PatternSmallStar);
}
int d0, d1, d2;
d0 = rand() % NB_DIVINITY;
d1 = d0;
while (d0 == d1) d1 = rand() % NB_DIVINITY;
if (rand() % 2 == 0)
{
// three temple
d2 = d0;
while (d0 == d2 || d1 == d2) d2 = rand() % NB_DIVINITY;
generateTemple(x0 - 2, y0, (enumDivinityType)d0);
generateTemple(x0 + 2, y0, (enumDivinityType)d1);
generateTemple(x0, y0, (enumDivinityType)d2);
}
else
{
// two temples
generateTemple(x0 - 1, y0, (enumDivinityType)d0);
generateTemple(x0 + 1, y0, (enumDivinityType)d1);
}
generateRandomTile();
}
void DungeonMap::generateCarpet(int x0, int y0, int w, int h, int n)
{
int xf = x0 + w - 1;
int yf = y0 + h - 1;
map[x0][y0] = n;
map[x0][yf] = n + 6;
map[xf][y0] = n + 2;
map[xf][yf] = n + 8;
int i, j;
for (i = x0 + 1; i <= xf - 1; i++)
{
map[i][y0] = n + 1;
map[i][yf] = n + 7;
for (j = y0 + 1; j <= yf - 1; j++)
map[i][j] = n + 4;
}
for (j = y0 + 1; j <= yf - 1; j++)
{
map[x0][j] = n + 3;
map[xf][j] = n + 5;
}
}
void DungeonMap::generateTable(int x0, int y0, int w, int h, int n)
{
int xf = x0 + w - 1;
int yf = y0 + h - 1;
objectsMap[x0][y0] = n;
objectsMap[x0][yf] = n + 6;
objectsMap[xf][y0] = n + 2;
objectsMap[xf][yf] = n + 8;
int i, j;
for (i = x0 + 1; i <= xf - 1; i++)
{
objectsMap[i][y0] = n + 1;
objectsMap[i][yf] = n + 7;
for (j = y0 + 1; j <= yf - 1; j++)
objectsMap[i][j] = n + 4;
}
for (j = y0 + 1; j <= yf - 1; j++)
{
objectsMap[x0][j] = n + 3;
objectsMap[xf][j] = n + 5;
}
for (i = x0; i <= xf; i++)
for (j = y0; j <= yf; j++)
logicalMap[i][j] = LogicalObstacle;
}
Vector2D DungeonMap::generateMerchantRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
for (int i = x0 - 3; i <= x0 + 3; i++)
{
if (i == x0 - 3) objectsMap[i][y0] = MAPOBJ_SHOP_LEFT;
else if (i == x0 + 3) objectsMap[i][y0] = MAPOBJ_SHOP_RIGHT;
else objectsMap[i][y0] = MAPOBJ_SHOP;
logicalMap[i][y0] = LogicalObstacle;
}
if (!hasNeighbourUp())
{
- map[x0 - 1][0] = MAP_WALL_SHOP;
- map[x0][0] = MAP_WALL_SHOP + 1;
- map[x0 + 1][0] = MAP_WALL_SHOP + 2;
+ objectsMap[x0 - 1][0] = MAPOBJ_PNW;
+ objectsMap[x0][0] = MAPOBJ_PNW + 1;
+ objectsMap[x0 + 1][0] = MAPOBJ_PNW + 2;
}
else
{
- map[x0 - 1][MAP_HEIGHT - 1] = MAP_WALL_SHOP +3;
- map[x0][MAP_HEIGHT - 1] = MAP_WALL_SHOP + 4;
- map[x0 + 1][MAP_HEIGHT - 1] = MAP_WALL_SHOP + 5;
+ objectsMap[x0 - 1][MAP_HEIGHT - 1] = MAPOBJ_PNW +3;
+ objectsMap[x0][MAP_HEIGHT - 1] = MAPOBJ_PNW + 4;
+ objectsMap[x0 + 1][MAP_HEIGHT - 1] = MAPOBJ_PNW + 5;
}
generateRandomTile();
return (Vector2D(x0 * TILE_WIDTH + TILE_WIDTH / 2, y0 * TILE_HEIGHT + TILE_HEIGHT / 2));
}
Vector2D DungeonMap::generateKeyRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
objectsMap[x0 - 1][y0 - 1] = MAPOBJ_WALL_SPECIAL;
objectsMap[x0 - 1][y0 + 1] = MAPOBJ_WALL_SPECIAL + 2;
objectsMap[x0 + 1][y0 - 1] = MAPOBJ_WALL_SPECIAL + 1;
objectsMap[x0 + 1][y0 + 1] = MAPOBJ_WALL_SPECIAL + 3;
logicalMap[x0 - 1][y0 - 1] = LogicalObstacle;
logicalMap[x0 - 1][y0 + 1] = LogicalObstacle;
logicalMap[x0 + 1][y0 - 1] = LogicalObstacle;
logicalMap[x0 + 1][y0 + 1] = LogicalObstacle;
if (rand() % 3 == 0)
{
if (rand() % 2 == 0) initPattern(PatternSmallCircle);
else initPattern(PatternSmallStar);
}
generateRandomTile();
return (Vector2D(x0 * TILE_WIDTH + TILE_WIDTH / 2, y0 * TILE_HEIGHT + TILE_HEIGHT / 2));
}
void DungeonMap::generateExitRoom()
{
initRoom();
int x0 = MAP_WIDTH / 2;
map[x0][0] = MAP_STAIRS_UP;
map[x0 - 1][0] = MAP_WALL_EXIT_L;
map[x0 + 1][0] = MAP_WALL_EXIT_R;
logicalMap[x0][0] = LogicalFloor;
if (rand() % 3 == 0) initPattern(PatternBorder);
generateRandomTile();
}
void DungeonMap::generateRoomRandom(int type)
{
if (rand() % 3 == 0) generateRoomWithHoles(type);
else generateRoomWithoutHoles(type);
}
void DungeonMap::generateRoomWithoutHoles(int type)
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
int i, j, r;
if (type <= 0) // empty room
{
if (roomType == roomTypeStarting)
{
- generateCarpet(5, 3, 5, 3, 30);
+ generateCarpet(5, 3, 5, 3, MAP_CARPET);
if (game().getLevel() > 1)
{
map[x0 - 1][MAP_HEIGHT - 1] = MAP_WALL_START_L;
map[x0][MAP_HEIGHT - 1] = MAP_WALL_START_M;
map[x0 + 1][MAP_HEIGHT - 1] = MAP_WALL_START_R;
}
}
else if (roomType == roomTypeBoss && (game().getLevel() == 2 || game().getLevel() > 5) ) // giant slime
{
- map[1][1] = MAP_GRID;
- map[1][MAP_HEIGHT -2] = MAP_GRID;
- map[MAP_WIDTH - 2][1] = MAP_GRID;
- map[MAP_WIDTH - 2][MAP_HEIGHT -2] = MAP_GRID;
+ map[1][1] = MAP_GRID + 1;
+ map[1][MAP_HEIGHT -2] = MAP_GRID + 1;
+ map[MAP_WIDTH - 2][1] = MAP_GRID + 1;
+ map[MAP_WIDTH - 2][MAP_HEIGHT -2] = MAP_GRID + 1;
}
if (roomType == roomTypeStandard)
{
if (rand() % 3 > 0 && gameFloor->neighboorCount(x, y) > 1)
{
if (type == 0 && game().getLevel() < 6) generateCorridors();
}
else
{
if (rand() % 3 == 0) initPattern((patternEnum)(rand() % 4));
}
}
}
if (type == 1) // corner block
{
if (rand() % 3 == 0) initPattern(PatternSmallChecker);
map[0][0] = MAP_WALL_X;
map[0][1] = MAP_WALL_7;
- map[1][1] = MAP_WALL_33;
+ map[1][1] = MAP_WALL_77;
map[1][0] = MAP_WALL_7;
shadowMap[0][0] = MAPSHAD_EMPTY;
shadowMap[0][1] = MAPSHAD_7;
shadowMap[0][2] = MAPSHAD_47;
shadowMap[1][0] = MAPSHAD_7;
shadowMap[2][0] = MAPSHAD_87;
shadowMap[1][1] = MAPSHAD_77;
shadowMap[1][2] = MAPSHAD_GROUND_47;
shadowMap[2][1] = MAPSHAD_GROUND_78;
logicalMap[1][1] = LogicalWall;
map[0][MAP_HEIGHT - 1] = MAP_WALL_X;
- map[0][MAP_HEIGHT - 2] = MAP_WALL_1;
- map[1][MAP_HEIGHT - 2] = MAP_WALL_99;
- map[1][MAP_HEIGHT - 1] = MAP_WALL_1;
+ map[0][MAP_HEIGHT - 2] = MAP_WALL_7;
+ map[1][MAP_HEIGHT - 2] = MAP_WALL_77;
+ map[1][MAP_HEIGHT - 1] = MAP_WALL_7;
shadowMap[0][MAP_HEIGHT - 1] = MAPSHAD_EMPTY;
shadowMap[0][MAP_HEIGHT - 2] = MAPSHAD_1;
shadowMap[0][MAP_HEIGHT - 3] = MAPSHAD_41;
shadowMap[1][MAP_HEIGHT - 1] = MAPSHAD_1;
shadowMap[2][MAP_HEIGHT - 1] = MAPSHAD_21;
shadowMap[1][MAP_HEIGHT - 2] = MAPSHAD_11;
shadowMap[1][MAP_HEIGHT - 3] = MAPSHAD_GROUND_41;
shadowMap[2][MAP_HEIGHT - 2] = MAPSHAD_GROUND_12;
logicalMap[1][MAP_HEIGHT -2] = LogicalWall;
map[MAP_WIDTH - 1][0] = MAP_WALL_X;
- map[MAP_WIDTH - 1][1] = MAP_WALL_9;
- map[MAP_WIDTH - 2][1] = MAP_WALL_11;
- map[MAP_WIDTH - 2][0] = MAP_WALL_9;
+ map[MAP_WIDTH - 1][1] = MAP_WALL_7;
+ map[MAP_WIDTH - 2][1] = MAP_WALL_77;
+ map[MAP_WIDTH - 2][0] = MAP_WALL_7;
shadowMap[MAP_WIDTH - 1][0] = MAPSHAD_EMPTY;
shadowMap[MAP_WIDTH - 1][1] = MAPSHAD_9;
shadowMap[MAP_WIDTH - 1][2] = MAPSHAD_69;
shadowMap[MAP_WIDTH - 2][0] = MAPSHAD_9;
shadowMap[MAP_WIDTH - 3][0] = MAPSHAD_89;
shadowMap[MAP_WIDTH - 2][1] = MAPSHAD_99;
shadowMap[MAP_WIDTH - 2][2] = MAPSHAD_GROUND_69;
shadowMap[MAP_WIDTH - 3][1] = MAPSHAD_GROUND_98;
logicalMap[MAP_WIDTH - 2][1] = LogicalWall;
map[MAP_WIDTH - 1][MAP_HEIGHT -1] = MAP_WALL_X;
- map[MAP_WIDTH - 1][MAP_HEIGHT -2] = MAP_WALL_3;
+ map[MAP_WIDTH - 1][MAP_HEIGHT -2] = MAP_WALL_7;
map[MAP_WIDTH - 2][MAP_HEIGHT -2] = MAP_WALL_77;
- map[MAP_WIDTH - 2][MAP_HEIGHT -1] = MAP_WALL_3;
+ map[MAP_WIDTH - 2][MAP_HEIGHT -1] = MAP_WALL_7;
shadowMap[MAP_WIDTH - 1][MAP_HEIGHT - 1] = MAPSHAD_EMPTY;
shadowMap[MAP_WIDTH - 1][MAP_HEIGHT - 2] = MAPSHAD_3;
shadowMap[MAP_WIDTH - 1][MAP_HEIGHT - 3] = MAPSHAD_63;
shadowMap[MAP_WIDTH - 2][MAP_HEIGHT - 1] = MAPSHAD_3;
shadowMap[MAP_WIDTH - 3][MAP_HEIGHT - 1] = MAPSHAD_23;
shadowMap[MAP_WIDTH - 2][MAP_HEIGHT - 2] = MAPSHAD_33;
shadowMap[MAP_WIDTH - 2][MAP_HEIGHT - 3] = MAPSHAD_GROUND_63;
shadowMap[MAP_WIDTH - 3][MAP_HEIGHT - 2] = MAPSHAD_GROUND_32;
logicalMap[MAP_WIDTH - 2][MAP_HEIGHT -2] = LogicalWall;
}
if (type == 2) // blocks in the middle
{
if (rand() % 3 == 0) initPattern(PatternBorder);
r = 1 + rand() % 3;
generateTable(x0 - r, y0 - 1, 1 + 2 * r, 3, MAPOBJ_BIG_OBSTACLE);
}
if (type == 3)
{
// big blocks in the corners
generateTable(2, 2, 2, 2, MAPOBJ_BIG_OBSTACLE);
generateTable(2, MAP_HEIGHT - 4, 2, 2, MAPOBJ_BIG_OBSTACLE);
generateTable(MAP_WIDTH - 4, MAP_HEIGHT - 4, 2, 2, MAPOBJ_BIG_OBSTACLE);
generateTable(MAP_WIDTH - 4, 2, 2, 2, MAPOBJ_BIG_OBSTACLE);
}
if (type == 4)
{
// objects
//if (rand() % 2 == 0)
{
// type 1
if (rand() % 3 == 0) initPattern(PatternSmallChecker);
bool leftOriented = rand() % 2 == 0;
int bankType = rand() % 3;
int x0 = leftOriented ? 5 : 3;
if (leftOriented)
{
objectsMap[2][4] = MAPOBJ_OBSTACLE;
logicalMap[2][4] = LogicalObstacle;
}
else
{
objectsMap[12][4] = MAPOBJ_OBSTACLE;
logicalMap[12][4] = LogicalObstacle;
}
for (int i = 0; i < 3; i++)
{
int xPos = x0 + i * 3;
switch (bankType)
{
case 0:
objectsMap[xPos][2] = MAPOBJ_BANK_TOP;
objectsMap[xPos][3] = MAPOBJ_BANK_BOTTOM;
objectsMap[xPos][5] = MAPOBJ_BANK_TOP;
objectsMap[xPos][6] = MAPOBJ_BANK_BOTTOM;
for (int j = 2; j <= 6; j++) if (j != 4) logicalMap[xPos][j] = LogicalObstacle;
break;
case 1:
objectsMap[xPos][2] = MAPOBJ_BANK_TOP;
objectsMap[xPos][3] = MAPOBJ_BANK;
objectsMap[xPos][4] = MAPOBJ_BANK;
objectsMap[xPos][5] = MAPOBJ_BANK;
objectsMap[xPos][6] = MAPOBJ_BANK_BOTTOM;
for (int j = 2; j <= 6; j++) logicalMap[xPos][j] = LogicalObstacle;
break;
case 2:
objectsMap[xPos][1] = MAPOBJ_BANK_TOP;
objectsMap[xPos][2] = MAPOBJ_BANK;
objectsMap[xPos][3] = MAPOBJ_BANK_BOTTOM;
objectsMap[xPos][5] = MAPOBJ_BANK_TOP;
objectsMap[xPos][6] = MAPOBJ_BANK;
objectsMap[xPos][7] = MAPOBJ_BANK_BOTTOM;
for (int j = 1; j <= 7; j++) if (j != 4) logicalMap[xPos][j] = LogicalObstacle;
break;
}
}
}
/*else
{
map[2][2] = MAP_LONG_LEFT;
map[3][2] = MAP_LONG;
map[4][2] = MAP_LONG_RIGHT;
map[2][6] = MAP_LONG_LEFT;
map[3][6] = MAP_LONG;
map[4][6] = MAP_LONG_RIGHT;
map[10][2] = MAP_LONG_LEFT;
map[11][2] = MAP_LONG;
map[12][2] = MAP_LONG_RIGHT;
map[10][6] = MAP_LONG_LEFT;
map[11][6] = MAP_LONG;
map[12][6] = MAP_LONG_RIGHT;
}*/
}
if (type == ROOM_TYPE_CHECKER)
{
// "checker"
if (rand() % 3 == 0) initPattern(PatternSmallChecker);
for (i = 2; i < MAP_WIDTH - 2; i = i + 2)
for (j = 2; j < MAP_HEIGHT - 2; j = j + 2)
{
objectsMap[i][j] = game().getLevel() >= 6 ? MAPOBJ_TOMB : MAPOBJ_OBSTACLE;
logicalMap[i][j] = LogicalObstacle;
}
}
generateRandomTile();
}
void DungeonMap::addHole(int x, int y)
{
int n = MAPOBJ_HOLE;
if (y > 0 && (objectsMap[x][y - 1] == MAPOBJ_HOLE || objectsMap[x][y - 1] == MAPOBJ_HOLE_BOTTOM))
n = MAPOBJ_HOLE_BOTTOM;
objectsMap[x][y] = n;
logicalMap[x][y] = LogicalHole;
}
void DungeonMap::generateRoomWithHoles(int type)
{
initRoom();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
int i, j, r;
if (type == 0)
{
if (roomType == roomTypeStarting)
{
- generateCarpet(5, 3, 5, 3, 30);
+ generateCarpet(5, 3, 5, 3, MAP_CARPET);
if (game().getLevel() > 1)
{
map[x0 - 1][MAP_HEIGHT - 1] = 62;
map[x0][MAP_HEIGHT - 1] = 63;
map[x0 + 1][MAP_HEIGHT - 1] = 64;
}
}
if (roomType == roomTypeBoss && game().getLevel() == 2) // giant slime
{
map[1][1] = MAP_GRID;
map[1][MAP_HEIGHT -2] = MAP_GRID;
map[MAP_WIDTH - 2][1] = MAP_GRID;
map[MAP_WIDTH - 2][MAP_HEIGHT -2] = MAP_GRID;
}
}
else if (type == 1)
{
// corner hole
if (rand() % 3 == 0) initPattern(PatternSmallChecker);
addHole(1, 1);
addHole(MAP_WIDTH - 2, MAP_HEIGHT -2);
addHole(1, MAP_HEIGHT -2);
addHole(MAP_WIDTH - 2, 1);
}
else if (type == 2)
{
// blocks in the middle
if (rand() % 3 == 0) initPattern(PatternBorder);
r = 1 + rand() % 2;
for (i = x0 - r; i <= x0 + r; i++)
for (j = y0 - 1; j <= y0 + 1; j++)
{
addHole(i, j);
}
}
else if (type == 3)
{
// 4 holes
addHole(2, 2);
addHole(2, 3);
addHole(3, 2);
addHole(3, 3);
addHole(MAP_WIDTH - 4, 2);
addHole(MAP_WIDTH - 4, 3);
addHole(MAP_WIDTH - 3, 2);
addHole(MAP_WIDTH - 3, 3);
addHole(2, MAP_HEIGHT - 4);
addHole(2, MAP_HEIGHT - 3);
addHole(3, MAP_HEIGHT - 4);
addHole(3, MAP_HEIGHT - 3);
addHole(MAP_WIDTH - 4, MAP_HEIGHT - 4);
addHole(MAP_WIDTH - 4, MAP_HEIGHT - 3);
addHole(MAP_WIDTH - 3, MAP_HEIGHT - 4);
addHole(MAP_WIDTH - 3, MAP_HEIGHT - 3);
}
else if (type == 4)
{
if (rand() % 3 == 0) initPattern(PatternBigCircle);
int r = 6 + rand()% 5;
int obstacleType = rand() % 2;
for (int i = 0; i < r; i++)
{
int rx = 1 + rand() % (MAP_WIDTH - 3);
int ry = 1 + rand() % (MAP_HEIGHT - 3);
bool ok = true;
bool isObstacle = (obstacleType == 1) && rand() % 2 == 0;
if ( (rx == 1 && ry == MAP_HEIGHT / 2)
|| (rx == MAP_WIDTH - 2 && ry == MAP_HEIGHT / 2)
|| (rx == MAP_WIDTH /2 && ry == MAP_HEIGHT - 2)
|| (rx == MAP_WIDTH /2 && ry == 1) )
{
ok = false;
}
else
{
for (int ix = -1; ix <= 1; ix++)
for (int iy = -1; iy <= 1; iy++)
{
ok = ok && logicalMap[rx + ix][ry + iy] != LogicalHole;
ok = ok && logicalMap[rx + ix][ry + iy] != LogicalObstacle;
}
}
if (ok)
{
if (!isObstacle)
{
addHole(rx, ry);
}
else
{
objectsMap[rx][ry] = MAPOBJ_OBSTACLE;
logicalMap[rx][ry] = LogicalObstacle;
}
}
else
{
i--;
}
}
}
else //if (type == 5)
{
// "checker"
for (i = 2; i < MAP_WIDTH - 2; i = i + 2)
for (j = 2; j < MAP_HEIGHT - 2; j = j + 2)
{
addHole(i, j);
}
}
generateRandomTile();
}
void DungeonMap::addItem(int itemType, float x, float y, bool merch)
{
itemListElement ilm;
ilm.type = itemType;
ilm.x = x;
ilm.y = y;
ilm.merch = merch;
itemList.push_back(ilm);
}
void DungeonMap::addSprite(int spriteType, int frame, float x, float y, float scale)
{
spriteListElement slm;
slm.type = spriteType;
slm.frame = frame;
slm.x = x;
slm.y = y;
slm.scale = scale;
spriteList.push_back(slm);
}
void DungeonMap::addChest(int chestType, bool state, float x, float y)
{
chestListElement clm;
clm.type = chestType;
clm.state = state;
clm.x = x;
clm.y = y;
chestList.push_back(clm);
}
void DungeonMap::restoreItems()
{
ItemList::iterator it;
for (it = itemList.begin (); it != itemList.end ();)
{
itemListElement ilm = *it;
it++;
ItemEntity* itemEntity = new ItemEntity((enumItemType)(ilm.type), ilm.x, ilm.y);
itemEntity->setMerchandise(ilm.merch);
}
}
void DungeonMap::restoreSprites()
{
SpriteList::iterator it;
for (it = spriteList.begin (); it != spriteList.end ();)
{
spriteListElement ilm = *it;
it++;
if (ilm.type == ENTITY_BLOOD)
game().getCurrentMapEntity()->addBlood(ilm.x, ilm.y, ilm.frame, ilm.scale);
else if (ilm.type == ENTITY_CORPSE)
game().getCurrentMapEntity()->addCorpse(ilm.x, ilm.y, ilm.frame);
}
}
void DungeonMap::restoreChests()
{
ChestList::iterator it;
for (it = chestList.begin (); it != chestList.end ();)
{
chestListElement clm = *it;
it++;
new ChestEntity(clm.x, clm.y, clm.type, clm.state);
}
}
void DungeonMap::restoreMapObjects()
{
restoreItems();
restoreSprites();
restoreChests();
cleanMapObjects();
}
void DungeonMap::cleanMapObjects()
{
itemList.clear();
spriteList.clear();
chestList.clear();
}
void DungeonMap::addRandomGrids(int n)
{
int counter = n;
while (counter > 0)
{
int rx = 1 + rand() % (MAP_WIDTH - 2);
int ry = 1 + rand() % (MAP_HEIGHT - 2);
- if (map[rx][ry] < 5)
+ if (logicalMap[rx][ry] == LogicalFloor)
{
- map[rx][ry] = MAP_GRID;
+ map[rx][ry] = MAP_GRID + game().getLevel() - 1;
counter--;
}
}
}
void DungeonMap::castShadows(int x0, int y0, int xf, int yf)
{
// init shadows
int i, j;
for ( j = 0 ; j < height; j++)
for ( i = 0 ; i < width; i++)
shadowMap[i][j] = MAPSHAD_EMPTY;
// shadows
for (int i = x0; i <= xf; i++)
{
if (i == x0)
{
shadowMap[i][y0] = MAPSHAD_7;
shadowMap[i][yf] = MAPSHAD_1;
}
else if (i == x0 + 1)
{
shadowMap[i][y0] = MAPSHAD_87;
shadowMap[i][yf] = MAPSHAD_21;
shadowMap[i][y0 + 1] = MAPSHAD_GROUND_7;
shadowMap[i][yf - 1] = MAPSHAD_GROUND_1;
}
else if (i == xf)
{
shadowMap[i][y0] = MAPSHAD_9;
shadowMap[i][yf] = MAPSHAD_3;
}
else if (i == xf - 1)
{
shadowMap[i][y0] = MAPSHAD_89;
shadowMap[i][yf] = MAPSHAD_23;
shadowMap[i][y0 + 1] = MAPSHAD_GROUND_9;
shadowMap[i][yf - 1] = MAPSHAD_GROUND_3;
}
else
{
shadowMap[i][y0] = MAPSHAD_8;
shadowMap[i][yf] = MAPSHAD_2;
shadowMap[i][y0 + 1] = MAPSHAD_GROUND_8;
shadowMap[i][yf - 1] = MAPSHAD_GROUND_2;
}
}
for (int i = y0 + 1; i < yf; i++)
{
if (i == y0 + 1)
{
shadowMap[x0][i] = MAPSHAD_47;
shadowMap[xf][i] = MAPSHAD_69;
}
else if (i == yf - 1)
{
shadowMap[x0][i] = MAPSHAD_41;
shadowMap[xf][i] = MAPSHAD_63;
}
else
{
shadowMap[x0][i] = MAPSHAD_4;
shadowMap[xf][i] = MAPSHAD_6;
shadowMap[x0 + 1][i] = MAPSHAD_GROUND_4;
shadowMap[xf - 1][i] = MAPSHAD_GROUND_6;
}
}
}
void DungeonMap::generateCorridors()
{
int xCor = 1 + rand()% 4;
int yCor = 1 + rand()% 1;
int x0 = 0, xf = MAP_WIDTH - 1, y0 = 0, yf = MAP_HEIGHT - 1;
if (!hasNeighbourLeft())
{
for (int i = 0; i < xCor; i++)
for (int j = 0; j < MAP_HEIGHT; j++)
{
map[i][j] = MAP_WALL_X;
logicalMap[i][j] = LogicalWall;
x0 = xCor;
}
}
if (!hasNeighbourRight())
{
for (int i = MAP_WIDTH - 1; i > MAP_WIDTH - 1 - xCor; i--)
for (int j = 0; j < MAP_HEIGHT; j++)
{
map[i][j] = MAP_WALL_X;
logicalMap[i][j] = LogicalWall;
xf = MAP_WIDTH - 1 - xCor;
}
}
if (!hasNeighbourUp())
{
for (int i = 0; i < MAP_WIDTH; i++)
for (int j = 0; j < yCor; j++)
{
map[i][j] = MAP_WALL_X;
logicalMap[i][j] = LogicalWall;
y0 = yCor;
}
}
if (!hasNeighbourDown())
{
for (int i = 0; i < MAP_WIDTH; i++)
for (int j = MAP_HEIGHT - 1; j > MAP_HEIGHT - 1 - yCor; j--)
{
map[i][j] = MAP_WALL_X;
logicalMap[i][j] = LogicalWall;
yf = MAP_HEIGHT - 1 - yCor;
}
}
//
for (int i = 0; i < MAP_WIDTH; i++)
{
for (int j = 0; j < MAP_HEIGHT; j++)
{
if (map[i][j] != MAP_WALL_X)
{
if (getTile(i - 1, j) == MAP_WALL_X)
{
if (j == 0 || getTile(i, j - 1) == MAP_WALL_X)
{
map[i][j] = MAP_WALL_7;
}
else if (j == MAP_HEIGHT - 1 || getTile(i, j + 1) == MAP_WALL_X)
{
- map[i][j] = MAP_WALL_1;
+ map[i][j] = MAP_WALL_7;
}
else
{
- if (j < MAP_HEIGHT / 2) map[i][j] = MAP_WALL_47;
- else if (j > MAP_HEIGHT / 2) map[i][j] = MAP_WALL_41;
- else map[i][j] = MAP_WALL_4;
+ if (j < MAP_HEIGHT / 2) map[i][j] = MAP_WALL_87;
+ else if (j > MAP_HEIGHT / 2) map[i][j] = MAP_WALL_87;
+ else map[i][j] = MAP_WALL_8;
logicalMap[i][j] = LogicalWall;
}
}
else if (getTile(i + 1, j) == MAP_WALL_X)
{
if (j == 0 || getTile(i, j - 1) == MAP_WALL_X)
{
- map[i][j] = MAP_WALL_9;
- map[i][j] = MAP_WALL_9;
+ map[i][j] = MAP_WALL_7;
+ map[i][j] = MAP_WALL_7;
}
- else if (j == MAP_HEIGHT - 1 || getTile(i, j + 1) == MAP_WALL_X) map[i][j] = MAP_WALL_3;
+ else if (j == MAP_HEIGHT - 1 || getTile(i, j + 1) == MAP_WALL_X) map[i][j] = MAP_WALL_7;
else
{
- if (j < MAP_HEIGHT / 2) map[i][j] = MAP_WALL_69;
- else if (j > MAP_HEIGHT / 2) map[i][j] = MAP_WALL_63;
- else map[i][j] = MAP_WALL_6;
+ if (j < MAP_HEIGHT / 2) map[i][j] = MAP_WALL_87;
+ else if (j > MAP_HEIGHT / 2) map[i][j] = MAP_WALL_87;
+ else map[i][j] = MAP_WALL_8;
logicalMap[i][j] = LogicalWall;
}
}
else if (getTile(i, j - 1) == MAP_WALL_X)
{
if (i == 0) map[i][j] = MAP_WALL_7;
- else if (i == MAP_WIDTH - 1) map[i][j] = MAP_WALL_9;
+ else if (i == MAP_WIDTH - 1) map[i][j] = MAP_WALL_7;
else
{
if (i < MAP_WIDTH / 2) map[i][j] = MAP_WALL_87;
- else if (i > MAP_WIDTH / 2) map[i][j] = MAP_WALL_89;
+ else if (i > MAP_WIDTH / 2) map[i][j] = MAP_WALL_87;
else map[i][j] = MAP_WALL_8;
logicalMap[i][j] = LogicalWall;
}
}
else if (getTile(i, j + 1) == MAP_WALL_X)
{
- if (i == 0) map[i][j] = MAP_WALL_1;
- else if (i == MAP_WIDTH - 1) map[i][j] = MAP_WALL_3;
+ if (i == 0) map[i][j] = MAP_WALL_7;
+ else if (i == MAP_WIDTH - 1) map[i][j] = MAP_WALL_7;
else
{
- if (i < MAP_WIDTH / 2) map[i][j] = MAP_WALL_21;
- else if (i > MAP_WIDTH / 2) map[i][j] = MAP_WALL_23;
- else map[i][j] = MAP_WALL_2;
+ if (i < MAP_WIDTH / 2) map[i][j] = MAP_WALL_87;
+ else if (i > MAP_WIDTH / 2) map[i][j] = MAP_WALL_87;
+ else map[i][j] = MAP_WALL_8;
logicalMap[i][j] = LogicalWall;
}
}
}
}
}
castShadows(x0, y0, xf, yf);
}
void DungeonMap::generateRandomTile()
{
bool ok = false;
for (int i = 0; !ok && i < NB_RANDOM_TILE_TRY; i++)
{
int n = rand() % NB_RANDOM_TILES;
int xTile, yTile;
if (randomDungeonTiles[n].totalRandom)
{
xTile = rand() % (GAME_WIDTH - randomDungeonTiles[n].width);
yTile = rand() % (GAME_HEIGHT - randomDungeonTiles[n].height);
}
else
{
xTile = TILE_WIDTH + rand() % (GAME_WIDTH - 2 * TILE_WIDTH - randomDungeonTiles[n].width);
yTile = TILE_HEIGHT + rand() % (GAME_HEIGHT - 2 * TILE_HEIGHT - randomDungeonTiles[n].height);
}
int x0 = xTile / TILE_WIDTH;
int xf = (xTile + randomDungeonTiles[n].width) / TILE_WIDTH;
int y0 = yTile / TILE_HEIGHT;
int yf = (yTile + randomDungeonTiles[n].height) / TILE_HEIGHT;
ok = true;
if (!randomDungeonTiles[n].totalRandom)
{
for (int ix = x0; ix <= xf; ix++)
for (int iy = y0; iy <= yf; iy++)
{
ok = ok && isWalkable(ix, iy);
}
}
if (ok)
{
randomTileElement.type = n;
randomTileElement.x = xTile;
randomTileElement.y = yTile;
if (randomDungeonTiles[n].totalRandom)
randomTileElement.rotation = rand()% 360;
else
randomTileElement.rotation = 0;
}
}
}
diff --git a/src/DungeonMap.h b/src/DungeonMap.h
index 295f43a..94ac680 100644
--- a/src/DungeonMap.h
+++ b/src/DungeonMap.h
@@ -1,313 +1,279 @@
#ifndef MAGICMAP_H
#define MAGICMAP_H
#include "sfml_game/GameMap.h"
#include "sfml_game/MyTools.h"
#include "Constants.h"
#include <list>
const int MAPOBJ_NONE = 0;
const int MAPOBJ_DOOR_OPEN = 1;
const int MAPOBJ_DOOR_CLOSED = 2;
const int MAPOBJ_OBSTACLE = 10;
const int MAPOBJ_BIG_OBSTACLE = 40;
const int MAPOBJ_TOMB = 49;
const int MAPOBJ_WALL_SPECIAL = 14;
const int MAPOBJ_BANK_TOP = 18;
const int MAPOBJ_BANK = 28;
const int MAPOBJ_BANK_BOTTOM = 38;
const int MAPOBJ_LONG_LEFT = 50;
const int MAPOBJ_LONG = 51;
const int MAPOBJ_LONG_RIGHT = 52;
+const int MAPOBJ_PNW = 60;
const int MAPOBJ_HOLE = 3;
const int MAPOBJ_HOLE_TOP = MAPOBJ_HOLE;
const int MAPOBJ_HOLE_BOTTOM = MAPOBJ_HOLE + 1;
const int MAPOBJ_TEMPLE_WALL = 20;
const int MAPOBJ_SHOP_BEGIN = 11;
const int MAPOBJ_SHOP_LEFT = 0 + MAPOBJ_SHOP_BEGIN;
const int MAPOBJ_SHOP = 1 + MAPOBJ_SHOP_BEGIN;
const int MAPOBJ_SHOP_RIGHT = 2 + MAPOBJ_SHOP_BEGIN;
const int MAPSHAD_7 = 0;
const int MAPSHAD_87 = 1;
const int MAPSHAD_8 = 2;
const int MAPSHAD_89 = 3;
const int MAPSHAD_9 = 4;
const int MAPSHAD_1 = 10;
const int MAPSHAD_21 = 11;
const int MAPSHAD_2 = 12;
const int MAPSHAD_23 = 13;
const int MAPSHAD_3 = 14;
const int MAPSHAD_47 = 5;
const int MAPSHAD_4 = 15;
const int MAPSHAD_41 = 25;
const int MAPSHAD_69 = 6;
const int MAPSHAD_6 = 16;
const int MAPSHAD_63 = 26;
const int MAPSHAD_77 = 20;
const int MAPSHAD_99 = 21;
const int MAPSHAD_11 = 30;
const int MAPSHAD_33 = 31;
const int MAPSHAD_EMPTY = 18;
const int MAPSHAD_GROUND_7 = 7;
const int MAPSHAD_GROUND_8 = 8;
const int MAPSHAD_GROUND_9 = 9;
const int MAPSHAD_GROUND_4 = 17;
const int MAPSHAD_GROUND_6 = 19;
const int MAPSHAD_GROUND_1 = 27;
const int MAPSHAD_GROUND_2 = 28;
const int MAPSHAD_GROUND_3 = 29;
const int MAPSHAD_GROUND_78 = 22;
const int MAPSHAD_GROUND_98 = 23;
const int MAPSHAD_GROUND_12 = 32;
const int MAPSHAD_GROUND_32 = 33;
const int MAPSHAD_GROUND_47 = 34;
const int MAPSHAD_GROUND_69 = 35;
const int MAPSHAD_GROUND_41 = 36;
const int MAPSHAD_GROUND_63 = 37;
-const int MAP_NORMAL_FLOOR = 7;
-const int MAP_STAIRS_UP = 39;
-const int MAP_DOOR_OPEN = 49;
-const int MAP_WALL = 70;
-const int MAP_DOOR = 71;
-const int MAP_BIG_OBSTACLE = 100;
-const int MAP_TOMB = 109;
-const int MAP_WALL_SPECIAL = 74;
-const int MAP_BANK_TOP = 78;
-const int MAP_BANK = 88;
-const int MAP_BANK_BOTTOM = 98;
-const int MAP_LONG_LEFT = 79;
-const int MAP_LONG = 89;
-const int MAP_LONG_RIGHT = 99;
-
-// temple
-const int MAP_TEMPLE = 50;
-const int MAP_TEMPLE_WALL = 80;
-
-// shop
-const int MAP_SHOP_BEGIN = 71;
-const int MAP_SHOP_LEFT = 0 + MAP_SHOP_BEGIN;
-const int MAP_SHOP = 1 + MAP_SHOP_BEGIN;
-const int MAP_SHOP_RIGHT = 2 + MAP_SHOP_BEGIN;
+const int MAP_WALL_BEGIN = 264;
+
+const int MAP_NORMAL_FLOOR = 8;
+const int MAP_TEMPLE = 192;
+const int MAP_CARPET = 200;
+const int MAP_GRID = 240;
+const int MAP_STAIRS_UP = 2 + MAP_WALL_BEGIN;
// walls
-const int MAP_WALL_BEGIN = 110;
-const int MAP_WALL_7 = 6 + MAP_WALL_BEGIN;
-const int MAP_WALL_77 = 8 + MAP_WALL_BEGIN;
-const int MAP_WALL_8 = 0 + MAP_WALL_BEGIN;
-const int MAP_WALL_9 = 7 + MAP_WALL_BEGIN;
-const int MAP_WALL_99 = 9 + MAP_WALL_BEGIN;
-const int MAP_WALL_4 = 2 + MAP_WALL_BEGIN;
-const int MAP_WALL_6 = 3 + MAP_WALL_BEGIN;
-const int MAP_WALL_1 = 16 + MAP_WALL_BEGIN;
-const int MAP_WALL_11 = 18 + MAP_WALL_BEGIN;
-const int MAP_WALL_2 = 1 + MAP_WALL_BEGIN;
-const int MAP_WALL_3 = 17 + MAP_WALL_BEGIN;
-const int MAP_WALL_33 = 19 + MAP_WALL_BEGIN;
-const int MAP_WALL_87 = 10 + MAP_WALL_BEGIN;
-const int MAP_WALL_89 = 11 + MAP_WALL_BEGIN;
-const int MAP_WALL_21 = 12 + MAP_WALL_BEGIN;
-const int MAP_WALL_23 = 13 + MAP_WALL_BEGIN;
-const int MAP_WALL_47 = 4 + MAP_WALL_BEGIN;
-const int MAP_WALL_41 = 14 + MAP_WALL_BEGIN;
-const int MAP_WALL_69 = 5 + MAP_WALL_BEGIN;
-const int MAP_WALL_63 = 15 + MAP_WALL_BEGIN;
-const int MAP_WALL_EXIT_L = 20 + MAP_WALL_BEGIN;
-const int MAP_WALL_EXIT_R = 21 + MAP_WALL_BEGIN;
-const int MAP_WALL_START_L = 22 + MAP_WALL_BEGIN;
-const int MAP_WALL_START_M = 23 + MAP_WALL_BEGIN;
-const int MAP_WALL_START_R = 24 + MAP_WALL_BEGIN;
-const int MAP_WALL_X = 29 + MAP_WALL_BEGIN;
-const int MAP_WALL_ALTERN = 30 + MAP_WALL_BEGIN;
-const int MAP_WALL_SHOP = 40 + MAP_WALL_BEGIN;
-
-const int MAP_GRID = 29;
-const int MAP_HOLE = 160;
-const int MAP_HOLE_TOP = MAP_HOLE;
-const int MAP_HOLE_BOTTOM = MAP_HOLE + 1;
+const int MAP_WALL_X = 0 + MAP_WALL_BEGIN;
+const int MAP_WALL_EXIT_L = 1 + MAP_WALL_BEGIN;
+const int MAP_WALL_EXIT_R = 3 + MAP_WALL_BEGIN;
+const int MAP_WALL_START_L = 4 + MAP_WALL_BEGIN;
+const int MAP_WALL_START_M = 5 + MAP_WALL_BEGIN;
+const int MAP_WALL_START_R = 6 + MAP_WALL_BEGIN;
+
+const int MAP_WALL_8 = 7 + MAP_WALL_BEGIN;
+const int MAP_WALL_7 = 8 + MAP_WALL_BEGIN;
+const int MAP_WALL_87 = 9 + MAP_WALL_BEGIN;
+const int MAP_WALL_77 = 10 + MAP_WALL_BEGIN;
+const int MAP_WALL_ALTERN = 11 + MAP_WALL_BEGIN;
+
+//const int MAP_WALL_SHOP = 40 + MAP_WALL_BEGIN;
+
+
const int ROOM_TYPE_CHECKER = 5;
const int ROOM_TYPE_ALL = 6;
enum logicalMapStateEnum
{
LogicalFloor,
LogicalWall,
LogicalObstacle,
LogicalHole,
};
class GameFloor;
enum roomTypeEnum
{
roomTypeNULL,
roomTypeStandard,
roomTypeBoss,
roomTypeMerchant,
roomTypeKey,
roomTypeBonus,
roomTypeExit,
roomTypeStarting,
roomTypeChallenge,
roomTypeTemple
};
struct randomDungeonTileStruct
{
int width;
int height;
int xOffset;
int yOffset;
bool totalRandom;
};
const int NB_RANDOM_TILES = 16;
const int NB_RANDOM_TILE_TRY = 40;
/** Array with all the items and data */
const randomDungeonTileStruct randomDungeonTiles[NB_RANDOM_TILES] =
{
{ 192, 192, 0, 0, true },
{ 192, 192, 192, 0, true },
{ 192, 192, 384, 0, true },
{ 192, 192, 576, 0, true },
{ 256, 256, 0, 192, true },
{ 512, 256, 256, 192, true },
{ 128, 128, 0, 448, true },
{ 128, 128, 128, 448, true },
{ 128, 128, 256, 448, true },
{ 128, 128, 384, 448, true },
{ 128, 128, 512, 448, false },
{ 128, 128, 640, 448, false },
{ 192, 192, 0, 576, true },
{ 192, 192, 192, 576, true },
{ 192, 192, 384, 576, true },
{ 192, 192, 576, 576, true },
};
class DungeonMap : public GameMap
{
public:
DungeonMap(int width, int height);
DungeonMap(GameFloor* gameFloor, int x, int y);
virtual ~DungeonMap();
void displayToConsole();
bool isVisited();
void setVisited(bool b);
bool isKnown();
void setKnown(bool b);
bool isCleared();
void setCleared(bool b);
bool isWalkable(int x, int y);
bool isFlyable(int x, int y);
bool isShootable(int x, int y);
int getObjectTile(int x, int y);
int getShadowTile(int x, int y);
bool getLogicalTile(int x, int y);
void setObjectTile(int x, int y, int n);
void setShadowTile(int x, int y, int n);
void setLogicalTile(int x, int y, logicalMapStateEnum state);
int getDivinity(int x, int y);
bool containsHealth();
roomTypeEnum getNeighbourLeft();
roomTypeEnum getNeighbourRight();
roomTypeEnum getNeighbourUp();
roomTypeEnum getNeighbourDown();
// 0 == no, 1 == yes, 2 == boss
int hasNeighbourLeft();
int hasNeighbourRight();
int hasNeighbourUp();
int hasNeighbourDown();
virtual bool isDownBlocking(int x, int y);
virtual bool isUpBlocking(int x, int y);
virtual bool isLeftBlocking(int x, int y);
virtual bool isRightBlocking(int x, int y);
virtual void randomize(int n);
void initRoom();
enum patternEnum { PatternSmallChecker, PatternBigChecker, PatternBorder, PatternBigCircle, PatternSmallCircle, PatternSmallStar, PatternSmallDisc};
void initPattern(patternEnum n);
void generateCarpet(int x0, int y0, int w, int h, int n);
void generateTable(int x0, int y0, int w, int h, int n);
void generateRoomRandom(int type);
void generateRoomWithoutHoles(int type);
void generateRoomWithHoles(int type);
void generateExitRoom();
Vector2D generateBonusRoom();
Vector2D generateMerchantRoom();
Vector2D generateKeyRoom();
void generateTemple(int x, int y, enumDivinityType type);
void generateTempleRoom();
void addRandomGrids(int n);
void addItem(int itemType, float x, float y, bool merch);
void addSprite(int spriteType, int frame, float x, float y, float scale);
void addChest(int chestType, bool state, float x, float y);
void restoreMapObjects();
void cleanMapObjects();
roomTypeEnum getRoomType();
void setRoomType(roomTypeEnum roomType);
struct itemListElement { int type; float x; float y; bool merch; };
typedef std::list<itemListElement> ItemList;
struct spriteListElement { int type; int frame; float x; float y; float scale;};
typedef std::list<spriteListElement> SpriteList;
struct chestListElement { int type; bool state; float x; float y;};
typedef std::list<chestListElement> ChestList;
std::list<itemListElement> getItemList();
std::list<chestListElement> getChestList();
std::list<spriteListElement> getSpriteList();
struct RandomTileElement { int type; float x; float y; float rotation;};
RandomTileElement getRandomTileElement();
void setRandomTileElement (RandomTileElement rt);
void openDoor(int x, int y);
void closeDoor(int x, int y);
bool isDoor(int x, int y);
protected:
private:
GameFloor* gameFloor;
int x, y;
bool visited;
bool known;
bool cleared;
int objectsMap[MAP_WIDTH][MAP_HEIGHT];
int shadowMap[MAP_WIDTH][MAP_HEIGHT];
logicalMapStateEnum logicalMap[MAP_WIDTH][MAP_HEIGHT];
roomTypeEnum roomType;
ItemList itemList;
SpriteList spriteList;
ChestList chestList;
RandomTileElement randomTileElement;
void generateCorridors();
void generateRandomTile();
void restoreItems();
void restoreSprites();
void restoreChests();
void makePatternTile(int x, int y);
void addHole(int x, int y);
void castShadows(int x0, int y0, int xf, int yf);
};
#endif // MAGICMAP_H
diff --git a/src/DungeonMapEntity.cpp b/src/DungeonMapEntity.cpp
index fbdbeff..f67105e 100644
--- a/src/DungeonMapEntity.cpp
+++ b/src/DungeonMapEntity.cpp
@@ -1,771 +1,831 @@
#include <iostream>
#include <sstream>
#include "WitchBlastGame.h"
#include "DungeonMapEntity.h"
#include "Constants.h"
#include "sfml_game/ImageManager.h"
DungeonMapEntity::DungeonMapEntity() : GameEntity (0.0f, 0.0f)
{
this->z = -1.0f;
type = 0;
hasChanged = true;
DungeonMapEntityPost* post = new DungeonMapEntityPost(this);
post->setZ(-0.2f);
post->setType(0);
DungeonMapEntityOverlay* over = new DungeonMapEntityOverlay(this);
over->setZ(1000);
over->setType(0);
overlaySprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_OVERLAY));
roomType = roomTypeStarting;
keyRoomEffect.delay = -1.0f;
randomSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_RANDOM_DUNGEON));
}
void DungeonMapEntity::animate(float delay)
{
age += delay;
bool needCompute = getChanged() || game().getCurrentMap()->getChanged();
if (needCompute)
{
computeVertices();
computeOverVertices();
computeShadowVertices();
}
// blood
bool moving = false;
for (unsigned int i = 0; i < blood.size(); i++)
{
if (blood[i].moving)
{
moving = true;
if (checkFalling(blood[i], 16, 16))
{
SpriteEntity* spriteEntity
= new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_BLOOD),
blood[i].x + 8,
blood[i].y + 8,
16, 16, 6);
spriteEntity->setAge(0.0f);
spriteEntity->setLifetime(3.0f);
spriteEntity->setShrinking(true);
spriteEntity->setFading(true);
spriteEntity->setFrame(blood[i].frame);
spriteEntity->setScale(blood[i].scale, blood[i].scale);
blood.erase(blood.begin() + i);
}
else
{
animateParticle(blood[i], delay, 0.95f);
if ((game().getParameters().bloodSpread && blood[i].frame < 12) || blood[i].frame >= 36)
{
if (blood[i].velocity.x * blood[i].velocity.x + blood[i].velocity.y * blood[i].velocity.y > 80
&& rand() % 4 == 0)
{
addBlood(blood[i].x, blood[i].y, blood[i].frame, blood[i].scale);
blood[i].scale *= 0.85f;
bool xPos = blood[i].velocity.x > 0;
bool yPos = blood[i].velocity.y > 0;
float norm = sqrtf(blood[i].velocity.x * blood[i].velocity.x + blood[i].velocity.y * blood[i].velocity.y);
blood[i].velocity = Vector2D(norm);
if (xPos && blood[i].velocity.x < 0) blood[i].velocity.x = - blood[i].velocity.x;
else if (!xPos && blood[i].velocity.x > 0) blood[i].velocity.x = - blood[i].velocity.x;
if (yPos && blood[i].velocity.y < 0) blood[i].velocity.y = - blood[i].velocity.y;
else if (!yPos && blood[i].velocity.y > 0) blood[i].velocity.y = - blood[i].velocity.y;
}
}
}
}
}
if (moving) computeBloodVertices();
// corpses
int CorpsesBox = 38, CorpsesLargeBox = 76;
moving = false;
for (unsigned int i = 0; i < corpses.size(); i++)
{
if (corpses[i].moving)
{
moving = true;
if (corpses[i].frame != FRAME_CORPSE_SLIME_VIOLET
&& collideWithWall(corpses[i], CorpsesBox, CorpsesBox))
{
if (checkFalling(corpses[i], 48, 48))
{
SpriteEntity* spriteEntity
= new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_CORPSES),
corpses[i].x,
corpses[i].y,
64, 64, 10);
spriteEntity->setAge(0.0f);
spriteEntity->setLifetime(3.0f);
spriteEntity->setShrinking(true);
spriteEntity->setFading(true);
spriteEntity->setFrame(corpses[i].frame);
corpses.erase(corpses.begin() + i);
}
else
{
if (corpses[i].velocity.x < 15.0f && corpses[i].velocity.x > -15.0f
&& corpses[i].velocity.y < 15.0f && corpses[i].velocity.y > -15.0f)
autoSpeed(corpses[i], 200);
animateParticle(corpses[i], delay, 1.0f);
}
}
else
{
float oldx = corpses[i].x;
float oldy = corpses[i].y;
animateParticle(corpses[i], delay, 0.8f);
if (corpses[i].frame != FRAME_CORPSE_SLIME_VIOLET
&& collideWithWall(corpses[i], CorpsesBox, CorpsesBox))
{
corpses[i].x = oldx;
corpses[i].y = oldy;
moving = false;
}
}
}
}
for (unsigned int i = 0; i < corpsesLarge.size(); i++)
{
if (corpsesLarge[i].moving)
{
moving = true;
if (collideWithWall(corpsesLarge[i], CorpsesLargeBox, CorpsesLargeBox))
{
if (corpsesLarge[i].velocity.x < 15.0f && corpsesLarge[i].velocity.x > -15.0f
&& corpsesLarge[i].velocity.y < 15.0f && corpsesLarge[i].velocity.y > -15.0f)
autoSpeed(corpsesLarge[i], 200);
animateParticle(corpsesLarge[i], delay, 1.0f);
}
else
{
float oldx = corpsesLarge[i].x;
float oldy = corpsesLarge[i].y;
animateParticle(corpsesLarge[i], delay, 0.8f);
if (collideWithWall(corpsesLarge[i], CorpsesLargeBox, CorpsesLargeBox))
{
corpsesLarge[i].x = oldx;
corpsesLarge[i].y = oldy;
moving = false;
}
}
}
}
for (unsigned int i = 0; i < corpsesLarge.size(); i++)
{
if (corpsesLarge[i].moving)
{
moving = true;
animateParticle(corpsesLarge[i], delay, 0.95f);
}
}
if (moving) computeCorpsesVertices();
if (game().getCurrentMap()->getRoomType() == roomTypeKey && !game().getCurrentMap()->isCleared())
{
keyRoomEffect.delay -= delay;
if (keyRoomEffect.delay <= 0.0f)
{
keyRoomEffect.delay = KeyRoomFXDelay;
keyRoomEffect.amplitude = 120 + rand() % 100;
keyRoomEffect.isBlinking = false;
}
}
}
void DungeonMapEntity::animateParticle(displayEntityStruct &particle, float delay, float viscosity)
{
particle.velocity.x *= viscosity;
particle.velocity.y *= viscosity;
if (particle.velocity.x < -5 || particle.velocity.x > 5
|| particle.velocity.y < -5 || particle.velocity.y > 5)
{
particle.x += delay * particle.velocity.x;
particle.y += delay * particle.velocity.y;
}
else
particle.moving = false;
}
bool DungeonMapEntity::collideWithWall(displayEntityStruct &particle, int boxWidth, int boxHeight)
{
float x0 = particle.x - boxWidth / 2;
float xf = particle.x + boxWidth / 2;
float y0 = particle.y - boxHeight / 2;
float yf = particle.y + boxHeight / 2;
if (particle.x < TILE_WIDTH && particle.velocity.x < -1.0f) particle.velocity.x = -particle.velocity.x;
else if (particle.x > TILE_WIDTH * (MAP_WIDTH - 2) && particle.velocity.x > 1.0f) particle.velocity.x = -particle.velocity.x;
if (particle.y < TILE_HEIGHT && particle.velocity.y < -1.0f) particle.velocity.y = -particle.velocity.y;
else if (particle.y > TILE_HEIGHT * (MAP_HEIGHT - 2) && particle.velocity.y > 1.0f) particle.velocity.y = -particle.velocity.y;
collide[NordWest] = !game().getCurrentMap()->isWalkable(x0 / TILE_WIDTH, y0 / TILE_HEIGHT);
collide[SudWest] = !game().getCurrentMap()->isWalkable(x0 / TILE_WIDTH, yf / TILE_HEIGHT);
collide[NordEast] = !game().getCurrentMap()->isWalkable(xf / TILE_WIDTH, y0 / TILE_HEIGHT);
collide[SudEast] = !game().getCurrentMap()->isWalkable(xf / TILE_WIDTH, yf / TILE_HEIGHT);
return collide[NordWest] || collide[SudWest] || collide[NordEast] || collide[SudEast];
}
bool DungeonMapEntity::checkFalling(displayEntityStruct &particle, int boxWidth, int boxHeight)
{
int tilex = (particle.x + boxWidth / 2) / TILE_WIDTH;
int tiley = (particle.y + boxHeight / 2) / TILE_HEIGHT;
- if (game().getCurrentMap()->getTile(tilex, tiley) < MAP_HOLE) return false;
+ if (game().getCurrentMap()->getLogicalTile(tilex, tiley) != LogicalHole) return false;
tilex = (particle.x + boxWidth / 2 - boxWidth / 3) / TILE_WIDTH;
tiley = (particle.y + boxHeight / 2 - boxHeight / 3) / TILE_HEIGHT;
- if (game().getCurrentMap()->getTile(tilex, tiley) < MAP_HOLE) return false;
+ if (game().getCurrentMap()->getLogicalTile(tilex, tiley) != LogicalHole) return false;
tilex = (particle.x + boxWidth / 2 + boxWidth / 3) / TILE_WIDTH;
tiley = (particle.y + boxHeight / 2 + boxHeight / 3) / TILE_HEIGHT;
- if (game().getCurrentMap()->getTile(tilex, tiley) < MAP_HOLE) return false;
+ if (game().getCurrentMap()->getLogicalTile(tilex, tiley) != LogicalHole) return false;
return true;
}
void DungeonMapEntity::autoSpeed(displayEntityStruct &particle, float speed)
{
if (!collide[NordWest] && !collide[NordEast])
{
particle.velocity.x = 0;
particle.velocity.y = -speed;
}
else if (!collide[SudWest] && !collide[SudEast])
{
particle.velocity.x = 0;
particle.velocity.y = speed;
}
else if (!collide[SudWest] && !collide[NordWest])
{
particle.velocity.x = -speed;
particle.velocity.y = 0;
}
else if (!collide[SudEast] && !collide[NordEast])
{
particle.velocity.x = speed;
particle.velocity.y = 0;
}
else if (!collide[NordWest])
{
particle.velocity.x = -speed * 0.7f;
particle.velocity.y = -speed * 0.7f;
}
else if (!collide[NordEast])
{
particle.velocity.x = speed * 0.7f;
particle.velocity.y = -speed * 0.7f;
}
else if (!collide[SudWest])
{
particle.velocity.x = -speed * 0.7f;
particle.velocity.y = speed * 0.7f;
}
else if (!collide[SudEast])
{
particle.velocity.x = speed * 0.7f;
particle.velocity.y = speed * 0.7f;
}
else
particle.velocity = Vector2D(speed);
}
bool DungeonMapEntity::getChanged()
{
bool result = hasChanged;
hasChanged = false;
return result;
}
void DungeonMapEntity::render(sf::RenderTarget* app)
{
app->draw(vertices, ImageManager::getInstance().getImage(IMAGE_TILES));
if (game().getCurrentMap()->getRoomType() == roomTypeTemple)
{
for (int i = 1; i < MAP_WIDTH - 2 ; i++)
for (int j = 1; j < MAP_WIDTH - 2 ; j++)
if (game().getCurrentMap()->getTile(i, j) >= MAP_TEMPLE
&& game().getCurrentMap()->getTile(i, j) < MAP_TEMPLE + 10)
{
sf::Sprite tile;
tile.setTexture(*ImageManager::getInstance().getImage(IMAGE_TILES));
tile.setPosition(i * TILE_WIDTH, j * TILE_HEIGHT);
- tile.setTextureRect(sf::IntRect((game().getCurrentMap()->getTile(i, j) % 10) * TILE_WIDTH,
- (1 + game().getCurrentMap()->getTile(i, j) / 10) * TILE_HEIGHT,
+ tile.setTextureRect(sf::IntRect((game().getCurrentMap()->getTile(i, j) % 24) * TILE_WIDTH,
+ (1 + game().getCurrentMap()->getTile(i, j) / 24) * TILE_HEIGHT,
TILE_WIDTH, TILE_HEIGHT));
int fade = 127 + 127 * (cosf(6.0f * game().getAbsolutTime()));
tile.setColor(sf::Color(255, 255, 255, fade));
app->draw(tile);
}
}
else if (game().getCurrentMap()->getRoomType() == roomTypeKey && !game().getCurrentMap()->isCleared())
{
int fade = 0;
if (keyRoomEffect.isBlinking)
{
fade = (int)(25.0f * game().getAbsolutTime()) % 2 == 0 ? 0 : 255;
}
else
{
if (keyRoomEffect.delay > KeyRoomFXDelay / 2)
fade = keyRoomEffect.amplitude - keyRoomEffect.amplitude * (keyRoomEffect.delay - KeyRoomFXDelay / 2) / KeyRoomFXDelay * 2;
else
fade = keyRoomEffect.amplitude - keyRoomEffect.amplitude * (KeyRoomFXDelay / 2 - keyRoomEffect.delay) / KeyRoomFXDelay * 2;
}
sf::Sprite tiles;
tiles.setTexture(*ImageManager::getInstance().getImage(IMAGE_KEY_AREA));
tiles.setPosition((MAP_WIDTH / 2 - 1) * TILE_WIDTH, (MAP_HEIGHT / 2 - 1) * TILE_HEIGHT);
tiles.setTextureRect(sf::IntRect(0, 0, 3 * TILE_WIDTH, 3 * TILE_HEIGHT));
app->draw(tiles);
tiles.setColor(sf::Color(255, 255, 255, fade));
tiles.setTextureRect(sf::IntRect(3 * TILE_WIDTH, 0, 3 * TILE_WIDTH, 3 * TILE_HEIGHT));
app->draw(tiles);
}
// random tile
if ( game().getCurrentMap()->getRandomTileElement().type > -1) app->draw(randomSprite);
// over tiles
app->draw(overVertices, ImageManager::getInstance().getImage(IMAGE_DUNGEON_OBJECTS));
}
void DungeonMapEntity::renderPost(sf::RenderTarget* app)
{
displayBlood(app);
displayCorpses(app);
app->draw(shadowVertices, ImageManager::getInstance().getImage(IMAGE_TILES_SHADOW));
}
void DungeonMapEntity::renderOverlay(sf::RenderTarget* app)
{
app->draw(overlaySprite);
}
std::vector <displayEntityStruct> DungeonMapEntity::getBlood()
{
return blood;
}
std::vector <displayEntityStruct> DungeonMapEntity::getCorpses()
{
auto result = corpses;
result.insert( result.end(), corpsesLarge.begin(), corpsesLarge.end() );
return result;
}
void DungeonMapEntity::displayBlood(sf::RenderTarget* app)
{
app->draw(bloodVertices, ImageManager::getInstance().getImage(IMAGE_BLOOD));
}
void DungeonMapEntity::displayCorpses(sf::RenderTarget* app)
{
app->draw(corpsesVertices, ImageManager::getInstance().getImage(IMAGE_CORPSES));
app->draw(corpsesLargeVertices, ImageManager::getInstance().getImage(IMAGE_CORPSES_BIG));
}
void DungeonMapEntity::refreshMap()
{
hasChanged = true;
blood.clear();
corpses.clear();
corpsesLarge.clear();
computeBloodVertices();
computeCorpsesVertices();
}
void DungeonMapEntity::computeVertices()
{
GameMap* gameMap = game().getCurrentMap();
- int tilesProLine = 10;
+ int tilesProLine = 24;
int tileWidth = 64;
int tileHeight = 64;
int tileBoxWidth = 64;
int tileBoxHeight = 64;
vertices.setPrimitiveType(sf::Quads);
vertices.resize(gameMap->getWidth() * gameMap->getHeight() * 4);
for (int i = 0; i < gameMap->getWidth(); i++)
for (int j = 0; j < gameMap->getHeight(); j++)
{
int nx = gameMap->getTile(i, j) % tilesProLine;
int ny = gameMap->getTile(i, j) / tilesProLine;
sf::Vertex* quad = &vertices[(i + j * gameMap->getWidth()) * 4];
- if (gameMap->getTile(i, j) >= MAP_WALL_ALTERN && gameMap->getTile(i, j) < 10 + MAP_WALL_ALTERN)
+ if ((gameMap->getTile(i, j) >= MAP_WALL_ALTERN && gameMap->getTile(i, j) < 10 + MAP_WALL_ALTERN)
+ || gameMap->getTile(i, j) == MAP_WALL_7
+ || gameMap->getTile(i, j) == MAP_WALL_8
+ || gameMap->getTile(i, j) == MAP_WALL_87
+ || gameMap->getTile(i, j) == MAP_WALL_77)
{
- if (j == 0 && i < MAP_WIDTH / 2)
+ if (j == 0 && i <= MAP_WIDTH / 2)
{
quad[0].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[3].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
else if (j == 0 && i > MAP_HEIGHT / 2)
{
quad[1].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[0].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[3].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[2].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
- else if (j == MAP_HEIGHT - 1 && i < MAP_WIDTH / 2)
+ else if (j == MAP_HEIGHT - 1 && i <= MAP_WIDTH / 2)
{
quad[3].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[0].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
else if (j == MAP_HEIGHT - 1 && i > MAP_WIDTH / 2)
{
quad[2].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[3].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[0].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[1].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
- else if (i == 0 && j < MAP_HEIGHT / 2)
+ else if (i == 0 && j <= MAP_HEIGHT / 2)
{
quad[0].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[3].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[1].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
- else if (i == MAP_WIDTH - 1 && j < MAP_HEIGHT / 2)
+ else if (i == MAP_WIDTH - 1 && j <= MAP_HEIGHT / 2)
{
quad[3].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[0].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[2].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
else if (i == MAP_WIDTH - 1 && j > MAP_HEIGHT / 2)
{
quad[2].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[0].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[3].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
else if (i == 0 && j > MAP_HEIGHT / 2)
{
quad[1].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[3].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[0].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
+ // corridors
+ else if (i < MAP_WIDTH / 2 && j <= MAP_HEIGHT / 2 && gameMap->getTile(i, j - 1) != MAP_WALL_X)
+ {
+ quad[0].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
+ quad[3].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
+ quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ quad[1].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ }
+ else if (i < MAP_WIDTH / 2 && j > MAP_HEIGHT / 2 && gameMap->getTile(i, j + 1) != MAP_WALL_X)
+ {
+ quad[1].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
+ quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
+ quad[3].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ quad[0].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ }
+ else if (i > MAP_WIDTH / 2 && j <= MAP_HEIGHT / 2 && gameMap->getTile(i, j - 1) != MAP_WALL_X)
+ {
+ quad[3].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
+ quad[0].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
+ quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ quad[2].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ }
+ else if (i > MAP_WIDTH / 2 && j > MAP_HEIGHT / 2 && gameMap->getTile(i, j + 1) != MAP_WALL_X)
+ {
+ quad[2].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
+ quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
+ quad[0].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ quad[3].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ }
+ else if (j < MAP_HEIGHT / 2 && i <= MAP_WIDTH / 2)
+ {
+ quad[0].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
+ quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
+ quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ quad[3].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ }
+ else if (j < MAP_HEIGHT / 2 && i > MAP_HEIGHT / 2)
+ {
+ quad[1].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
+ quad[0].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
+ quad[3].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ quad[2].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ }
+ else if (j > MAP_HEIGHT / 2 && i <= MAP_WIDTH / 2)
+ {
+ quad[3].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
+ quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
+ quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ quad[0].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ }
+ else if (j > MAP_HEIGHT / 2 && i > MAP_WIDTH / 2)
+ {
+ quad[2].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
+ quad[3].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
+ quad[0].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ quad[1].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
+ }
}
else
{
quad[0].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[3].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
-
quad[0].texCoords = sf::Vector2f(nx * tileBoxWidth, ny * tileBoxHeight);
quad[1].texCoords = sf::Vector2f((nx + 1) * tileBoxWidth, ny * tileBoxHeight);
quad[2].texCoords = sf::Vector2f((nx + 1) * tileBoxWidth, (ny + 1) * tileBoxHeight);
quad[3].texCoords = sf::Vector2f(nx * tileBoxWidth, (ny + 1) * tileBoxHeight);
}
if (roomType != game().getCurrentMap()->getRoomType())
{
std::stringstream ss;
roomType = game().getCurrentMap()->getRoomType();
switch (roomType)
{
case roomTypeChallenge:
ImageManager::getInstance().getImage(IMAGE_OVERLAY)->loadFromFile("media/overlay_boss_01.png");
break;
case roomTypeTemple:
ImageManager::getInstance().getImage(IMAGE_OVERLAY)->loadFromFile("media/overlay_temple.png");
break;
case roomTypeMerchant:
ImageManager::getInstance().getImage(IMAGE_OVERLAY)->loadFromFile("media/overlay_shop.png");
break;
case roomTypeBoss:
ss << "media/overlay_boss_0" << game().getLevel() << ".png";
ImageManager::getInstance().getImage(IMAGE_OVERLAY)->loadFromFile(ss.str());
break;
default:
ImageManager::getInstance().getImage(IMAGE_OVERLAY)->loadFromFile("media/overlay_00.png");
break;
}
overlaySprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_OVERLAY));
}
int n = game().getCurrentMap()->getRandomTileElement().type;
if ( n > -1)
{
randomSprite.setPosition(game().getCurrentMap()->getRandomTileElement().x + randomDungeonTiles[n].width / 2,
game().getCurrentMap()->getRandomTileElement().y + randomDungeonTiles[n].height / 2);
randomSprite.setOrigin(randomDungeonTiles[n].width / 2, randomDungeonTiles[n].height / 2);
randomSprite.setTextureRect(sf::IntRect(randomDungeonTiles[n].xOffset, randomDungeonTiles[n].yOffset, randomDungeonTiles[n].width, randomDungeonTiles[n].height));
randomSprite.setRotation(game().getCurrentMap()->getRandomTileElement().rotation);
}
}
void DungeonMapEntity::computeOverVertices()
{
DungeonMap* gameMap = game().getCurrentMap();
int tilesProLine = 10;
int tileWidth = 64;
int tileHeight = 64;
int tileBoxWidth = 64;
int tileBoxHeight = 64;
overVertices.setPrimitiveType(sf::Quads);
overVertices.resize(gameMap->getWidth() * gameMap->getHeight() * 4);
for (int i = 0; i < gameMap->getWidth(); i++)
for (int j = 0; j < gameMap->getHeight(); j++)
{
//if (gameMap->getObjectTile(i, j) > 2)
{
int nx = gameMap->getObjectTile(i, j) % tilesProLine;
int ny = gameMap->getObjectTile(i, j) / tilesProLine;
sf::Vertex* quad = &overVertices[(i + j * gameMap->getWidth()) * 4];
{
quad[0].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[3].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
quad[0].texCoords = sf::Vector2f(nx * tileBoxWidth, ny * tileBoxHeight);
quad[1].texCoords = sf::Vector2f((nx + 1) * tileBoxWidth, ny * tileBoxHeight);
quad[2].texCoords = sf::Vector2f((nx + 1) * tileBoxWidth, (ny + 1) * tileBoxHeight);
quad[3].texCoords = sf::Vector2f(nx * tileBoxWidth, (ny + 1) * tileBoxHeight);
}
}
}
void DungeonMapEntity::computeShadowVertices()
{
DungeonMap* gameMap = game().getCurrentMap();
int tilesProLine = 10;
int tileWidth = 64;
int tileHeight = 64;
int tileBoxWidth = 64;
int tileBoxHeight = 64;
shadowVertices.setPrimitiveType(sf::Quads);
shadowVertices.resize(gameMap->getWidth() * gameMap->getHeight() * 4);
for (int i = 0; i < gameMap->getWidth(); i++)
for (int j = 0; j < gameMap->getHeight(); j++)
{
//if (gameMap->getShadowTile(i, j) != MAPSHAD_EMPTY)
{
int nx = gameMap->getShadowTile(i, j) % tilesProLine;
int ny = gameMap->getShadowTile(i, j) / tilesProLine;
sf::Vertex* quad = &shadowVertices[(i + j * gameMap->getWidth()) * 4];
{
quad[0].position = sf::Vector2f(x + i * tileWidth, y + j * tileHeight);
quad[1].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + j * tileHeight);
quad[2].position = sf::Vector2f(x + (i + 1) * tileWidth + (tileBoxWidth -tileWidth), y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
quad[3].position = sf::Vector2f(x + i * tileWidth, y + (j + 1) * tileHeight + (tileBoxHeight - tileHeight));
}
quad[0].texCoords = sf::Vector2f(nx * tileBoxWidth, ny * tileBoxHeight);
quad[1].texCoords = sf::Vector2f((nx + 1) * tileBoxWidth, ny * tileBoxHeight);
quad[2].texCoords = sf::Vector2f((nx + 1) * tileBoxWidth, (ny + 1) * tileBoxHeight);
quad[3].texCoords = sf::Vector2f(nx * tileBoxWidth, (ny + 1) * tileBoxHeight);
}
}
}
void DungeonMapEntity::computeBloodVertices()
{
bloodVertices.setPrimitiveType(sf::Quads);
bloodVertices.resize(blood.size() * 4);
for (unsigned int i = 0; i < blood.size(); i++)
{
auto particle = blood[i];
sf::Vertex* quad = &bloodVertices[i * 4];
float middle = 8.0f * particle.scale;
int nx = particle.frame % 6;
int ny = particle.frame / 6;
quad[0].position = sf::Vector2f(particle.x - middle, particle.y - middle);
quad[1].position = sf::Vector2f(particle.x + middle, particle.y - middle);
quad[2].position = sf::Vector2f(particle.x + middle, particle.y + middle);
quad[3].position = sf::Vector2f(particle.x - middle, particle.y + middle);
quad[0].texCoords = sf::Vector2f(nx * 16, ny * 16);
quad[1].texCoords = sf::Vector2f((nx + 1) * 16, ny * 16);
quad[2].texCoords = sf::Vector2f((nx + 1) * 16, (ny + 1) * 16);
quad[3].texCoords = sf::Vector2f(nx * 16, (ny + 1) * 16);
}
}
void DungeonMapEntity::computeCorpsesVertices()
{
corpsesVertices.setPrimitiveType(sf::Quads);
corpsesVertices.resize(corpses.size() * 4);
for (unsigned int i = 0; i < corpses.size(); i++)
{
auto particle = corpses[i];
sf::Vertex* quad = &corpsesVertices[i * 4];
float middle = 32;
int nx = particle.frame % 10;
int ny = particle.frame / 10;
quad[0].position = sf::Vector2f(particle.x - middle, particle.y - middle);
quad[1].position = sf::Vector2f(particle.x + middle, particle.y - middle);
quad[2].position = sf::Vector2f(particle.x + middle, particle.y + middle);
quad[3].position = sf::Vector2f(particle.x - middle, particle.y + middle);
quad[0].texCoords = sf::Vector2f(nx * 64, ny * 64);
quad[1].texCoords = sf::Vector2f((nx + 1) * 64, ny * 64);
quad[2].texCoords = sf::Vector2f((nx + 1) * 64, (ny + 1) * 64);
quad[3].texCoords = sf::Vector2f(nx * 64, (ny + 1) * 64);
}
corpsesLargeVertices.setPrimitiveType(sf::Quads);
corpsesLargeVertices.resize(corpsesLarge.size() * 4);
for (unsigned int i = 0; i < corpsesLarge.size(); i++)
{
auto particle = corpsesLarge[i];
sf::Vertex* quad = &corpsesLargeVertices[i * 4];
float middle = 64;
int nx = (particle.frame - FRAME_CORPSE_KING_RAT) % 8;
int ny = (particle.frame - FRAME_CORPSE_KING_RAT) / 8;
quad[0].position = sf::Vector2f(particle.x - middle, particle.y - middle);
quad[1].position = sf::Vector2f(particle.x + middle, particle.y - middle);
quad[2].position = sf::Vector2f(particle.x + middle, particle.y + middle);
quad[3].position = sf::Vector2f(particle.x - middle, particle.y + middle);
quad[0].texCoords = sf::Vector2f(nx * 128, ny * 128);
quad[1].texCoords = sf::Vector2f((nx + 1) * 128, ny * 128);
quad[2].texCoords = sf::Vector2f((nx + 1) * 128, (ny + 1) * 128);
quad[3].texCoords = sf::Vector2f(nx * 128, (ny + 1) * 128);
}
}
displayEntityStruct& DungeonMapEntity::generateBlood(float x, float y, BaseCreatureEntity::enumBloodColor bloodColor)
{
displayEntityStruct bloodEntity;
int b0 = 0 + 6 * (int)bloodColor;
bloodEntity.frame = b0 + rand()%6;
bloodEntity.velocity = Vector2D(rand()%250);
bloodEntity.x = x;
bloodEntity.y = y;
bloodEntity.scale = /*bloodColor == 0 ?*/ 1.0f + (rand() % 10) * 0.1f /*: 1.0f*/;
bloodEntity.moving = true;
blood.push_back(bloodEntity);
return blood[blood.size() - 1];
}
void DungeonMapEntity::addBlood(float x, float y, int frame, float scale)
{
displayEntityStruct bloodEntity;
bloodEntity.frame = frame;
bloodEntity.x = x;
bloodEntity.y = y;
bloodEntity.velocity.x = 0;
bloodEntity.velocity.y = 0;
bloodEntity.scale = scale;
bloodEntity.moving = true;
blood.push_back(bloodEntity);
}
void DungeonMapEntity::addCorpse(float x, float y, int frame)
{
displayEntityStruct corpseEntity;
corpseEntity.frame = frame;
corpseEntity.x = x;
corpseEntity.y = y;
corpseEntity.velocity.x = 0;
corpseEntity.velocity.y = 0;
corpseEntity.scale = 0.0f;
corpseEntity.moving = true;
if (frame >= FRAME_CORPSE_KING_RAT)
{
corpsesLarge.push_back(corpseEntity);
}
else
{
corpses.push_back(corpseEntity);
}
}
void DungeonMapEntity::activateKeyRoomEffect()
{
keyRoomEffect.isBlinking = true;
keyRoomEffect.delay = 1.0f;
}
/////////////////////////////////////////////////////////////////////////
DungeonMapEntityPost::DungeonMapEntityPost(DungeonMapEntity* parent) : GameEntity (0.0f, 0.0f)
{
this->parent = parent;
}
void DungeonMapEntityPost::animate(float delay)
{
}
void DungeonMapEntityPost::render(sf::RenderTarget* app)
{
parent->renderPost(app);
}
/////////////////////////////////////////////////////////////////////////
DungeonMapEntityOverlay::DungeonMapEntityOverlay(DungeonMapEntity* parent) : GameEntity (0.0f, 0.0f)
{
this->parent = parent;
}
void DungeonMapEntityOverlay::animate(float delay)
{
}
void DungeonMapEntityOverlay::render(sf::RenderTarget* app)
{
parent->renderOverlay(app);
}
diff --git a/src/SlimePetEntity.cpp b/src/SlimePetEntity.cpp
index e578b34..0620166 100644
--- a/src/SlimePetEntity.cpp
+++ b/src/SlimePetEntity.cpp
@@ -1,307 +1,307 @@
#include "SlimePetEntity.h"
#include "PlayerEntity.h"
#include "EnemyBoltEntity.h"
#include "ExplosionEntity.h"
#include "sfml_game/SpriteEntity.h"
#include "sfml_game/ImageManager.h"
#include "sfml_game/SoundManager.h"
#include "Constants.h"
#include "WitchBlastGame.h"
SlimePetEntity::SlimePetEntity()
: BaseCreatureEntity (ImageManager::getInstance().getImage(IMAGE_SLIME), 200, 200, 64, 64)
{
creatureSpeed = 0.0f;
velocity = Vector2D(0.0f, 0.0f);
hp = SLIME_HP;
jumpingDelay = 0.6f + 0.1f * (rand() % 20);
type = ENTITY_FAMILIAR_LOCAL;
frame = 0;
shadowFrame = 3;
imagesProLine = 4;
isJumping = false;
h = 0.0f;
attackDelay = -1.0f;
viscosity = 0.98f;
sprite.setOrigin(32, 44);
h = 1300;
hVelocity = 0.0f;
isJumping = true;
isFirstJumping = true;
age = 0.0f;
x = GAME_WIDTH * 0.5f;
y = GAME_HEIGHT * 0.5f;
if (game().getPlayer()->getX() < 2 * TILE_WIDTH) x = 2.5f * TILE_WIDTH;
else if (game().getPlayer()->getX() > GAME_WIDTH - 2 * TILE_WIDTH) x = GAME_WIDTH - 2.5f * TILE_WIDTH;
else if (game().getPlayer()->getY() < 2 * TILE_HEIGHT) y = 2.5f * TILE_HEIGHT;
else if (game().getPlayer()->getY() > GAME_HEIGHT - 2 * TILE_HEIGHT) y = GAME_HEIGHT - 2.5f * TILE_HEIGHT;
}
void SlimePetEntity::animate(float delay)
{
if (age < 0.0f)
{
age += delay;
}
else
{
attackDelay -= delay;
if (isJumping)
{
hVelocity -= 700.0f * delay;
h += hVelocity * delay;
bool firstTimeGround = false;
if (h <= 0.0f)
{
h = 0.0f;
if (isFalling())
{
fall();
}
else
{
if (isFirstJumping)
{
isFirstJumping = false;
firstTimeGround = true;
hVelocity = 160.0f;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT);
}
else
{
jumpingDelay = 0.3f + 0.1f * (rand() % 15);
isJumping = false;
SoundManager::getInstance().playSound(SOUND_SLIME_IMAPCT_WEAK);
}
}
}
if (firstTimeGround) frame = 0;
else if (hVelocity > -190.0f) frame = 2;
else frame = 1;
}
else if (isFalling())
{
fall();
}
else
{
jumpingDelay -= delay;
if (jumpingDelay < 0.0f)
{
SoundManager::getInstance().playSound(SOUND_SLIME_JUMP);
hVelocity = 300.0f + rand() % 250;
isJumping = true;
isFirstJumping = true;
float randVel = 250.0f + rand() % 250;
setVelocity(Vector2D(x, y).vectorTo(game().getPlayerPosition(), randVel ));
}
else if (jumpingDelay < 0.1f)
frame = 1;
else frame = 0;
}
BaseCreatureEntity::animate(delay);
if (canCollide()) testSpriteCollisions();
}
z = y + 14;
}
void SlimePetEntity::readCollidingEntity(CollidingSpriteEntity* entity)
{
if (canCollide() && collideWithEntity(entity))
{
if (entity->getType() >= ENTITY_ENEMY && entity->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
EnemyEntity* enemyEntity = static_cast<EnemyEntity*>(entity);
if (enemyEntity->canCollide())
{
if (attackDelay <= 0.0f)
{
enemyEntity->hurt(getHurtParams(12, ShotTypeStandard,0, false, SourceTypeMelee, EnemyTypeNone,false));
attackDelay = 0.65f;
float xs = (x + enemyEntity->getX()) / 2;
float ys = (y + enemyEntity->getY()) / 2;
SpriteEntity* star = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_HURT_IMPACT), xs, ys);
star->setFading(true);
star->setZ(y+ 100);
star->setLifetime(0.7f);
star->setType(ENTITY_EFFECT);
star->setSpin(400.0f);
}
if (enemyEntity->getMovingStyle() == movWalking)
{
Vector2D vel = Vector2D(enemyEntity->getX(), enemyEntity->getY()).vectorTo(Vector2D(x, y), 100.0f );
giveRecoil(false, vel, 0.3f);
}
}
}
}
}
void SlimePetEntity::render(sf::RenderTarget* app)
{
// shadow
if (h < 1055)
{
int fade = 255;
if (h > 800)
fade = - (h - 1055);
sprite.setColor(sf::Color(255, 255, 255, fade));
sprite.setPosition(x, y);
sprite.setTextureRect(sf::IntRect(shadowFrame * width, 0, width, height));
app->draw(sprite);
sprite.setColor(sf::Color(255, 255, 255, 255));
}
// sprite
sprite.setPosition(x, y - h);
sprite.setTextureRect(sf::IntRect(frame * width, 4 * height, width, height));
app->draw(sprite);
if (game().getShowLogical())
{
displayBoundingBox(app);
displayCenterAndZ(app);
}
}
void SlimePetEntity::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 - 15;
boundingBox.height = height - SLIME_BB_HEIGHT_DIFF;
}
void SlimePetEntity::collideMapRight()
{
velocity.x = -velocity.x * 0.8f;
}
void SlimePetEntity::collideMapLeft()
{
velocity.x = -velocity.x * 0.8f;
}
void SlimePetEntity::collideMapTop()
{
velocity.y = -velocity.y * 0.8f;
}
void SlimePetEntity::collideMapBottom()
{
velocity.y = -velocity.y * 0.8f;
}
void SlimePetEntity::changeRoom()
{
h = 1500;
hVelocity = 0.0f;
isJumping = true;
isFirstJumping = true;
x = 300;
y = 250;
}
bool SlimePetEntity::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 (!game().getCurrentMap()->isFlyable(xTile, yTile))
{
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;
}
bool SlimePetEntity::canCollide()
{
return h <= 70.0f;
}
bool SlimePetEntity::isFalling()
{
int tilex0 = boundingBox.left / TILE_WIDTH;
int tiley0 = boundingBox.top / TILE_HEIGHT;
int tilexf = (boundingBox.left + boundingBox.width) / TILE_WIDTH;
int tileyf = (boundingBox.top + boundingBox.height) / TILE_HEIGHT;
- return (game().getCurrentMap()->getTile(tilex0, tiley0) >= MAP_HOLE
- && game().getCurrentMap()->getTile(tilex0, tileyf) >= MAP_HOLE
- && game().getCurrentMap()->getTile(tilexf, tileyf) >= MAP_HOLE
- && game().getCurrentMap()->getTile(tilexf, tiley0) >= MAP_HOLE);
+ return (game().getCurrentMap()->getLogicalTile(tilex0, tiley0) == LogicalHole
+ && game().getCurrentMap()->getLogicalTile(tilex0, tileyf) == LogicalHole
+ && game().getCurrentMap()->getLogicalTile(tilexf, tileyf) == LogicalHole
+ && game().getCurrentMap()->getLogicalTile(tilexf, tiley0) == LogicalHole);
}
void SlimePetEntity::fall()
{
SpriteEntity* spriteEntity
= new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_SLIME),
x,
y + 6,
64, 64, 4);
spriteEntity->setAge(0.0f);
spriteEntity->setLifetime(3.0f);
spriteEntity->setShrinking(true);
spriteEntity->setFading(true);
spriteEntity->setFrame(16);
isDying = true;
SlimePetEntity* newSlime = new SlimePetEntity();
newSlime->setAge(-4.0f);
}
BaseCreatureEntity::enumMovingStyle SlimePetEntity::getMovingStyle()
{
if (h <= 70.0f)
return movWalking;
else
return movFlying;
}
diff --git a/src/WitchBlastGame.cpp b/src/WitchBlastGame.cpp
index 4bbcde3..6287e4e 100644
--- a/src/WitchBlastGame.cpp
+++ b/src/WitchBlastGame.cpp
@@ -1,6251 +1,6261 @@
/** 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 "CyclopsEntity.h"
#include "GiantSpiderEntity.h"
#include "GiantSlimeEntity.h"
#include "ButcherEntity.h"
#include "BatEntity.h"
#include "ImpEntity.h"
#include "SlimeEntity.h"
#include "LargeSlimeEntity.h"
#include "PumpkinEntity.h"
#include "ChestEntity.h"
#include "EvilFlowerEntity.h"
#include "BubbleEntity.h"
#include "ItemEntity.h"
#include "WitchEntity.h"
#include "CauldronEntity.h"
#include "SnakeEntity.h"
#include "GhostEntity.h"
#include "ZombieEntity.h"
#include "ZombieDarkEntity.h"
#include "BogeymanEntity.h"
#include "LittleSpiderEntity.h"
#include "SpiderEggEntity.h"
#include "FranckyEntity.h"
#include "VampireEntity.h"
#include "ArtefactDescriptionEntity.h"
#include "PnjEntity.h"
#include "TextEntity.h"
#include "StandardRoomGenerator.h"
#include "Scoring.h"
#include "MessageGenerator.h"
#include "TextMapper.h"
#include "SlimePetEntity.h"
#include <iostream>
#include <sstream>
#include <fstream>
#include <ctime>
#include <algorithm>
-//#define START_LEVEL 2
+//#define START_LEVEL 3
const float PORTRAIT_DIAPLAY_TIME = 5.0f;
const unsigned int ACHIEV_LINES = 2;
static std::string intToString(int n)
{
std::ostringstream oss;
oss << n;
return oss.str();
}
static std::string keyToString(sf::Keyboard::Key key)
{
std::string s = "Unknown";
if (key >= sf::Keyboard::A && key <= sf::Keyboard::Z)
{
char c = 'A' + key - sf::Keyboard::A;
std::ostringstream oss;
oss << c;
s = oss.str();
}
else if (key >= sf::Keyboard::Num0 && key <= sf::Keyboard::Num9)
{
char c = '0' + key - sf::Keyboard::Num0;
std::ostringstream oss;
oss << c;
s = oss.str();
}
else if (key >= sf::Keyboard::Numpad0 && key <= sf::Keyboard::Numpad9)
{
char c = '0' + key - sf::Keyboard::Num0;
std::ostringstream oss;
oss << c << " (numpad)";
s = oss.str();
}
else if (key >= sf::Keyboard::F1 && key <= sf::Keyboard::F15)
{
std::ostringstream oss;
oss << "F" << (int)key - (int)sf::Keyboard::F1;
s = oss.str();
}
else if (key == sf::Keyboard::Escape) s = "Escape";
else if (key == sf::Keyboard::LControl) s = "Left Control";
else if (key == sf::Keyboard::LShift) s = "Left Shift";
else if (key == sf::Keyboard::LAlt) s = "Left Alt";
else if (key == sf::Keyboard::LSystem) s = "Left System";
else if (key == sf::Keyboard::RControl) s = "Right Control";
else if (key == sf::Keyboard::RShift) s = "Right Shift";
else if (key == sf::Keyboard::RAlt) s = "Right Alt";
else if (key == sf::Keyboard::RSystem) s = "Right System";
else if (key == sf::Keyboard::Space) s = "Space";
else if (key == sf::Keyboard::Tab) s = "Tab";
else if (key == sf::Keyboard::Left) s = "Left arrow";
else if (key == sf::Keyboard::Right) s = "Right arrow";
else if (key == sf::Keyboard::Up) s = "Up arrow";
else if (key == sf::Keyboard::Down) s = "Down arrow";
else if (key == sf::Keyboard::LBracket) s = "[";
else if (key == sf::Keyboard::RBracket) s = "]";
else if (key == sf::Keyboard::SemiColon) s = ";";
else if (key == sf::Keyboard::Comma) s = ",";
else if (key == sf::Keyboard::Period) s = ".";
else if (key == sf::Keyboard::Quote) s = "Quote";
else if (key == sf::Keyboard::Slash) s = "/";
else if (key == sf::Keyboard::BackSlash) s = "\\";
else if (key == sf::Keyboard::Tilde) s = "~";
else if (key == sf::Keyboard::Equal) s = "=";
else if (key == sf::Keyboard::Dash) s = "_";
else if (key == sf::Keyboard::Return) s = "Return";
else if (key == sf::Keyboard::BackSpace) s = "BackSpace";
else if (key == sf::Keyboard::PageUp) s = "Page Up";
else if (key == sf::Keyboard::PageDown) s = "Page Down";
else if (key == sf::Keyboard::End) s = "End";
else if (key == sf::Keyboard::Home) s = "Home";
else if (key == sf::Keyboard::Insert) s = "Insert";
else if (key == sf::Keyboard::Delete) s = "Delete";
else if (key == sf::Keyboard::Add) s = "+";
else if (key == sf::Keyboard::Subtract) s = "-";
else if (key == sf::Keyboard::Multiply) s = "*";
else if (key == sf::Keyboard::Divide) s = "/";
else if (key == sf::Keyboard::Pause) s = "Pause";
else if (key == sf::Keyboard::KeyCount) s = "Key Count";
return s;
}
std::map<EnumWorldEvents, EnumMessages> eventToMessage =
{
{ EventMeetRatsOrBats, MsgInfoRatsBats },
{ EventMeetSnakes, MsgInfoSnakes },
{ EventMeetWitches, MsgInfoWitches },
{ EventGetCoin, MsgInfoGold },
{ EventGetFamiliar, MsgInfoFamiliar },
{ EventBeingHurted, MsgTutoHeal },
{ EventFindShop, MsgTutoShops },
{ EventFindBossDoor, MsgTutoBossDoor },
{ EventFindChallengeDoor, MsgTutoChallengeDoor },
{ EventFindTemple, MsgTutoTemple },
{ EventGetItem, MsgTutoItems },
{ EventGetSpecialShot, MsgTutoShots },
{ EventGetSpell, MsgTutoSpell },
{ EventAchievement, MsgTutoAchievements },
};
// author: AFS
// source: https://github.com/LaurentGomila/SFML/wiki/Source:-Letterbox-effect-using-a-view
static sf::View getLetterboxView(sf::View view, int windowWidth, int windowHeight)
{
// Compares the aspect ratio of the window to the aspect ratio of the view,
// and sets the view's viewport accordingly in order to archieve a letterbox effect.
// A new view (with a new viewport set) is returned.
float windowRatio = windowWidth / (float) windowHeight;
float viewRatio = view.getSize().x / (float) view.getSize().y;
float sizeX = 1;
float sizeY = 1;
float posX = 0;
float posY = 0;
bool horizontalSpacing = true;
if (windowRatio < viewRatio)
horizontalSpacing = false;
// If horizontalSpacing is true, the black bars will appear on the left and right side.
// Otherwise, the black bars will appear on the top and bottom.
if (horizontalSpacing)
{
sizeX = viewRatio / windowRatio;
posX = (1 - sizeX) / 2.0;
}
else
{
sizeY = windowRatio / viewRatio;
posY = (1 - sizeY) / 2.0;
}
view.setViewport( sf::FloatRect(posX, posY, sizeX, sizeY) );
return view;
}
static sf::View getFullScreenLetterboxView(sf::View view, int clientWidth, int clientHeight)
{
sf::View returnView(sf::FloatRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT));
float clientRatio = clientWidth / (float) clientHeight;
float viewRatio = view.getSize().x / (float) view.getSize().y;
float sizeX = 1;
float sizeY = 1;
float posX = 0;
float posY = 0;
bool horizontalSpacing = true;
if (clientRatio > viewRatio)
horizontalSpacing = false;
// If horizontalSpacing is true, the black bars will appear on the left and right side.
// Otherwise, the black bars will appear on the top and bottom.
if (horizontalSpacing)
{
sizeX = clientRatio / viewRatio;
posX = (1 - sizeX) / 2.0;
}
else
{
sizeY = viewRatio / clientRatio;
posY = (1 - sizeY) / 2.0;
}
returnView.setViewport( sf::FloatRect(posX, posY, sizeX, sizeY) );
return returnView;
}
namespace
{
WitchBlastGame* gameptr;
}
WitchBlastGame::WitchBlastGame()
{
gameptr = this;
configureFromFile();
if (parameters.vsync == false)
{
//app->setVerticalSyncEnabled(false);
app->setFramerateLimit(60);
}
// Fullscreen ?
if (parameters.fullscreen)
{
create(SCREEN_WIDTH, SCREEN_HEIGHT, APP_NAME + " V" + APP_VERSION, true, parameters.vsync);
sf::View view = app->getDefaultView();
view = getFullScreenLetterboxView( view, SCREEN_WIDTH, SCREEN_HEIGHT );
app->setView(view);
}
else
{
create(SCREEN_WIDTH, SCREEN_HEIGHT, APP_NAME + " V" + APP_VERSION, false, parameters.vsync);
}
// loading resources
const char *const images[] =
{
"media/player_0.png", "media/player_1.png",
- "media/bolt.png", "media/tiles01.png",
+ "media/bolt.png", "media/tiles.png",
"media/rat.png", "media/minimap.png",
"media/map_background.png",
"media/items.png", "media/items_equip.png",
"media/items.png", "media/items_equip.png",
"media/chest.png", "media/bat.png",
"media/evil_flower.png", "media/slime.png",
"media/imp.png", "media/spider_egg.png",
"media/spider_web.png", "media/little_spider.png",
"media/bubble.png", "media/witch.png",
"media/cauldron.png", "media/snake.png",
"media/pumpkin.png", "media/ghost.png",
"media/zombie.png", "media/bogeyman.png",
"media/butcher.png", "media/giant_slime.png",
"media/king_rat.png", "media/cyclops.png",
"media/giant_spider.png", "media/francky.png",
"media/vampire.png", "media/vampire_bat.png",
"media/vampire_part.png",
"media/blood.png",
"media/corpses.png", "media/corpses_big.png",
"media/star.png", "media/star2.png",
"media/hurt_impact.png",
"media/interface.png", "media/hud_shots.png",
"media/explosion.png", "media/keys_qwer.png",
"media/keys_azer.png", "media/message_icons.png",
"media/night.png", "media/title.png",
"media/overlay_00.png", "media/light_cone.png",
"media/divinity.png",
"media/pnj.png", "media/fairy.png",
"media/key_area.png",
"media/ui_life.png", "media/ui_mana.png",
"media/ui_spells.png", "media/ui_message.png",
"media/ui_top_layer.png", "media/ui_achiev.png",
"media/fog.png", "media/title_animation.png",
"media/splatter.png", "media/witch_intro.png",
"media/item_description.png", "media/death_certificate.png",
"media/achievements.png", "media/boss_pictures.png",
"media/portrait_part.png", "media/dungeon_random.png",
"media/dungeon_objects.png", "media/tiles_shadow.png",
};
for (const char *const filename : images)
ImageManager::getInstance().addImage(filename);
const char *const sounds[] =
{
"media/sound/blast00.ogg", "media/sound/blast01.ogg",
"media/sound/blast_elec.ogg", "media/sound/blast_fire.ogg",
"media/sound/blast_ice.ogg", "media/sound/blast_illusion.ogg",
"media/sound/blast_poison.ogg", "media/sound/blast_stone.ogg",
"media/sound/door_closing.ogg", "media/sound/door_opening.ogg",
"media/sound/chest_opening.ogg", "media/sound/impact.ogg",
"media/sound/bonus.ogg", "media/sound/drink.ogg",
"media/sound/eat.ogg", "media/sound/player_hit.ogg",
"media/sound/player_die.ogg", "media/sound/ennemy_dying.ogg",
"media/sound/coin.ogg", "media/sound/pay.ogg",
"media/sound/wall_impact.ogg", "media/sound/big_wall_impact.ogg",
"media/sound/king_rat_cry_1.ogg", "media/sound/king_rat_cry_2.ogg",
"media/sound/king_rat_die.ogg", "media/sound/slime_jump.ogg",
"media/sound/slime_impact.ogg", "media/sound/slime_impact_weak.ogg",
"media/sound/slime_smash.ogg", "media/sound/ice_charge.ogg",
"media/sound/electric.ogg", "media/sound/select.ogg",
"media/sound/heart.ogg", "media/sound/rat_die.ogg",
"media/sound/bat_die.ogg", "media/sound/imp_hurt.ogg",
"media/sound/imp_die.ogg", "media/sound/rock_impact.ogg",
"media/sound/rock_impact_medium.ogg", "media/sound/rock_impact_heavy.ogg",
"media/sound/throw.ogg", "media/sound/cyclop00.ogg",
"media/sound/cyclop_die.ogg", "media/sound/cyclops_impact.ogg",
"media/sound/butcher_00.ogg", "media/sound/butcher_01.ogg",
"media/sound/butcher_hurt.ogg", "media/sound/butcher_die.ogg",
"media/sound/vib.ogg",
"media/sound/boom_00.ogg", "media/sound/clang_00.ogg",
"media/sound/bubble_00.ogg", "media/sound/bubble_01.ogg",
"media/sound/trap.ogg", "media/sound/egg_smash_00.ogg",
"media/sound/egg_smash_01.ogg", "media/sound/spider_walking.ogg",
"media/sound/spider_web.ogg", "media/sound/spider_hurt.ogg",
"media/sound/spider_die.ogg", "media/sound/little_spider_die.ogg",
"media/sound/witch_00.ogg", "media/sound/witch_01.ogg",
"media/sound/witch_die_00.ogg", "media/sound/witch_die_01.ogg",
"media/sound/witch_02.ogg", "media/sound/invoke.ogg",
"media/sound/cauldron.ogg", "media/sound/cauldron_die.ogg",
"media/sound/snake_die.ogg", "media/sound/pumpkin_00.ogg",
"media/sound/pumpkin_01.ogg", "media/sound/pumpkin_die.ogg",
"media/sound/critical.ogg",
"media/sound/gong.ogg", "media/sound/teleport.ogg",
"media/sound/spell_charge.ogg", "media/sound/fireball.ogg",
"media/sound/message.ogg", "media/sound/earthquake.ogg",
"media/sound/spell_freeze.ogg", "media/sound/spell_shield.ogg",
"media/sound/heavy_step_00.ogg", "media/sound/heavy_step_01.ogg",
"media/sound/night.ogg", "media/sound/grumble.ogg",
"media/sound/zombie_00.ogg", "media/sound/zombie_01.ogg",
"media/sound/zombie_attack.ogg", "media/sound/zombie_die.ogg",
"media/sound/ghost.ogg", "media/sound/ghost_die.ogg",
"media/sound/electricity.ogg",
"media/sound/electric_blast.ogg", "media/sound/francky_00.ogg",
"media/sound/francky_01.ogg", "media/sound/francky_02.ogg",
"media/sound/francky_die.ogg", "media/sound/om.ogg",
"media/sound/glass.ogg", "media/sound/hiccup.ogg",
"media/sound/splatch.ogg", "media/sound/intro_witch.ogg",
"media/sound/force_field.ogg", "media/sound/door_opening_boss.ogg",
"media/sound/achievement.ogg",
"media/sound/vampire_flying.ogg", "media/sound/vampire_flap.ogg",
"media/sound/vampire_sonic.ogg", "media/sound/vampire_laughing.ogg",
"media/sound/vampire_transform_bolt.ogg", "media/sound/vampire_transform_bat.ogg",
"media/sound/vampire_hypnosis.ogg", "media/sound/vampire_cry.ogg",
"media/sound/vampire_dying.ogg", "media/sound/ice_block.ogg",
"media/sound/bogeyman_die.ogg", "media/sound/bogeyman_attack.ogg",
"media/sound/bogeyman_vortex_00.ogg", "media/sound/bogeyman_vortex_01.ogg",
};
// AA in fullscreen
if (parameters.fullscreen) enableAA(true);
// game main client position in the UI
xOffset = OFFSET_X;
yOffset = OFFSET_Y;
SoundManager::getInstance().setVolume(parameters.soundVolume);
for (const char *const filename : sounds)
{
SoundManager::getInstance().addSound(filename);
}
if (font.loadFromFile("media/DejaVuSans-Bold.ttf"))
{
myText.setFont(font);
}
miniMap = NULL;
currentMap = NULL;
currentFloor = NULL;
lastScore.score = 0;
lastScore.name = "";
lastScore.level = 0;
int i;
for (i = 0; i < NB_X_GAME; i++) xGame[i].active = false;
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++) equipNudeToDisplay[i] = false;
for (i = 0; i < NB_MESSAGES; i++) gameMessagesToSkip[i] = false;
for (i = 0; i < NB_ACHIEVEMENTS; i++) achievementState[i] = AchievementUndone;
for (i = 0; i < NB_ENEMY; i++) globalData.killedMonster[i] = 0;
saveInFight.monsters.clear();
showLogical = false;
showGameTime = false;
uiSprites.shotsSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_HUD_SHOTS));
uiSprites.topLayer.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_TOP_LAYER));
uiSprites.topLayer.setPosition(0, 602);
uiSprites.msgBoxSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_MESSAGE));
uiSprites.iconSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_MESSAGE_ICONS));
uiSprites.iconSprite.setPosition(12, 614);
uiSprites.mapBgSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_MAP_BACKGROUND));
uiSprites.mapBgSprite.setPosition(342, 23);
introScreenSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_INTRO));
titleSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_TITLE));
titleSprite.setOrigin(titleSprite.getTextureRect().width / 2, titleSprite.getTextureRect().height / 2);
loadGameData();
loadHiScores();
srand(time(NULL));
}
void WitchBlastGame::enableAA(bool enable)
{
for (int i = 0; i < NB_IMAGES; i++)
{
if (i != IMAGE_TILES && i != IMAGE_MINIMAP && i != IMAGE_ITEMS_PRES && i != IMAGE_ITEMS_EQUIP_PRES && i != IMAGE_CORPSES
&& i != IMAGE_CORPSES_BIG)
ImageManager::getInstance().getImage(i)->setSmooth(enable);
}
}
WitchBlastGame::~WitchBlastGame()
{
// cleaning all entities
EntityManager::getInstance().clean();
// cleaning data
if (miniMap != NULL) delete (miniMap);
if (currentFloor != NULL) delete (currentFloor);
}
DungeonMap* WitchBlastGame::getCurrentMap()
{
return currentMap;
}
DungeonMapEntity* WitchBlastGame::getCurrentMapEntity()
{
return dungeonEntity;
}
PlayerEntity* WitchBlastGame::getPlayer()
{
return player;
}
Vector2D WitchBlastGame::getPlayerPosition()
{
return Vector2D(player->getX(), player->getY());
}
int WitchBlastGame::getLevel()
{
return level;
}
int WitchBlastGame::getChallengeLevel()
{
return challengeLevel;
}
bool WitchBlastGame::getShowLogical()
{
return showLogical;
}
float WitchBlastGame::getDeltaTime()
{
return deltaTime;
}
void WitchBlastGame::onUpdate()
{
if (gameState == gameStatePlaying)
{
if (isPlayerAlive) player->setItemToBuy(NULL);
EntityManager::getInstance().animate(deltaTime);
if (sf::Keyboard::isKeyPressed(input[KeyTimeControl]))
{
EntityManager::getInstance().animate(deltaTime);
SoundManager::getInstance().playSound(SOUND_VIB, false);
}
if (isPlayerAlive) gameTime += deltaTime;
for (int i = 0; i < NB_X_GAME; i++)
{
if (xGame[i].active)
{
xGame[i].timer -= deltaTime;
if (xGame[i].timer <= 0.0f)
{
xGame[i].active = false;
if (i == (int)xGameTypeFade && xGame[i].param == X_GAME_FADE_OUT)
{
if (player->getPlayerStatus() == PlayerEntity::playerStatusGoingNext)
{
level++;
startNewLevel();
}
else
startNewGame(false);
}
}
}
}
if (isPlayerAlive)
{
if (player->getHp() <= 0)
{
isPlayerAlive = false;
playMusic(MusicEnding);
}
}
}
else if (gameState == gameStatePlayingDisplayBoss)
{
bossDisplayTimer += deltaTime;
if (bossDisplayTimer >= PORTRAIT_DIAPLAY_TIME) gameState = gameStatePlaying;
}
}
void WitchBlastGame::startNewGame(bool fromSaveFile)
{
gameState = gameStateInit;
level = 1;
challengeLevel = 1;
gameTime = 0.0f;
initEvents();
scoreSaveFile = "";
interaction.active = false;
// cleaning all entities
EntityManager::getInstance().clean();
SoundManager::getInstance().stopSound(SOUND_NIGHT);
// cleaning the message queue
std::queue<messageStruct> empty;
std::swap( messagesQueue, empty );
// cleaning the achievements queue
std::queue<achievementStruct> empty2;
std::swap( achievementsQueue, empty2 );
// cleaning data
if (miniMap != NULL) delete (miniMap);
if (currentFloor != NULL) delete (currentFloor);
miniMap = NULL;
currentFloor = NULL;
// init in game menu
buildInGameMenu();
dungeonEntity = new DungeonMapEntity();
// the interface
uiSprites.gui.setTexture(*ImageManager::getInstance().getImage(IMAGE_INTERFACE));
// key symbol on the interface
uiSprites.keySprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
uiSprites.keySprite.setTextureRect(sf::IntRect(ITEM_WIDTH * EQUIP_BOSS_KEY, 0, ITEM_WIDTH, ITEM_HEIGHT));
uiSprites.keySprite.setPosition(737, 612);
miniMap = new GameMap(FLOOR_WIDTH, FLOOR_HEIGHT);
// minimap on the interface
miniMapEntity = new TileMapEntity(ImageManager::getInstance().getImage(IMAGE_MINIMAP), miniMap, 19, 15, 10);
miniMapEntity->setTileBox(20, 16);
miniMapEntity->setX(800);
miniMapEntity->setY(645);
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);
saveInFight.isFight = false;
if (fromSaveFile)
{
if (!loadGame())
fromSaveFile = false;
else
playLevel(saveInFight.isFight);
}
if (!fromSaveFile)
{
// the player
player = new PlayerEntity((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f));
resetKilledEnemies();
#ifdef START_LEVEL
for (int i = 1; i < START_LEVEL; i++)
{
level = i;
if (level == 3)
{
player->acquireItem(getItemSpell());
player->acquireItemAfterStance();
}
player->setHpMax(player->getHpMax() + 2 + rand() % 4);
item_equip_enum item = getRandomEquipItem(false, false);
player->acquireItem((enumItemType)(item + FirstEquipItem));
player->acquireItemAfterStance();
item = getRandomEquipItem(true, true);
player->acquireItem((enumItemType)(item + FirstEquipItem));
player->acquireItemAfterStance();
if (i % 2 == 0)
{
item = getRandomEquipItem(false, false);
player->acquireItem((enumItemType)(item + FirstEquipItem));
player->acquireItemAfterStance();
}
}
level++;
player->setHp(player->getHpMax());
player->setGold(8 + rand() % 45);
#endif // START_LEVEL
startNewLevel();
}
}
void WitchBlastGame::startNewLevel()
{
// reset floor items
player->resetFloorItem();
bool needShop = false;
// create the new level
if (currentFloor != NULL)
{
if (level > 1)
{
if (!currentFloor->hasRoomOfType(roomTypeMerchant)) needShop = true;
}
delete currentFloor;
}
currentFloor = new GameFloor(level);
if (needShop) currentFloor->setForceShop();
currentFloor->createFloor();
// center it
floorX = FLOOR_WIDTH / 2;
floorY = FLOOR_HEIGHT / 2;
// move the player
if (level == 1)
player->moveTo((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f));
else
player->moveTo((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT - 2 * TILE_HEIGHT));
// the boss room is closed
bossRoomOpened = false;
if (level <= 7) testAndAddMessageToQueue((EnumMessages)(MsgInfoLevel1 + level - 1));
if (level == 1)
{
testAndAddMessageToQueue(MsgTutoBasics);
testAndAddMessageToQueue(MsgTutoTips);
}
playLevel(false);
}
void WitchBlastGame::playLevel(bool isFight)
{
- if (level == 1)
- ImageManager::getInstance().getImage(IMAGE_TILES)->loadFromFile("media/tiles01.png");
- else if (level == 2)
- ImageManager::getInstance().getImage(IMAGE_TILES)->loadFromFile("media/tiles02.png");
- else if (level == 3)
- ImageManager::getInstance().getImage(IMAGE_TILES)->loadFromFile("media/tiles03.png");
- else if (level == 4)
- ImageManager::getInstance().getImage(IMAGE_TILES)->loadFromFile("media/tiles04.png");
- else if (level == 5)
- ImageManager::getInstance().getImage(IMAGE_TILES)->loadFromFile("media/tiles05.png");
- else if (level == 6)
- ImageManager::getInstance().getImage(IMAGE_TILES)->loadFromFile("media/tiles06.png");
- else
- ImageManager::getInstance().getImage(IMAGE_TILES)->loadFromFile("media/tiles07.png");
-
isPlayerAlive = true;
if (!isFight)
{
player->setVelocity(Vector2D(0.0f, 0.0f));
player->setPlayerStatus(PlayerEntity::playerStatusPlaying);
}
// first map is open
roomClosed = false;
// generate the map
refreshMap();
// items from save
currentMap->restoreMapObjects();
if (isFight)
{
checkEntering();
saveMapItems();
}
// populate with monsters
if (isFight)
{
auto monsters_save = saveInFight.monsters;
saveInFight.monsters.clear();
for (auto monster: monsters_save)
addMonster(monster.id, monster.x, monster.y);
if (currentMap->getRoomType() == roomTypeBoss) playMusic(MusicBoss);
else if (currentMap->getRoomType() == roomTypeChallenge) playMusic(MusicChallenge);
else playMusic(MusicDungeon);
}
else
playMusic(MusicDungeon);
// game time counter an state
lastTime = getAbsolutTime();
gameState = gameStatePlaying;
// fade in
xGame[xGameTypeFade].active = true;
xGame[xGameTypeFade].param = X_GAME_FADE_IN;
xGame[xGameTypeFade].timer = FADE_IN_DELAY;
float x0 = MAP_WIDTH * 0.5f * TILE_WIDTH;
float y0 = MAP_HEIGHT * 0.5f * TILE_HEIGHT + 40.0f;
std::ostringstream oss;
oss << tools::getLabel("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::prepareIntro()
{
EntityManager::getInstance().clean();
introSprites[0] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_FOG));
introSprites[0]->setX(SCREEN_WIDTH / 2);
introSprites[0]->setY(SCREEN_HEIGHT - 202);
introSprites[1] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_FOG));
introSprites[1]->setX(SCREEN_WIDTH / 2 + 970);
introSprites[1]->setY(SCREEN_HEIGHT - 202);
gameState = gameStateIntro;
gameTime = 0.0f;
introState = 0;
introSoundState = 0;
SoundManager::getInstance().playSound(SOUND_NIGHT);
}
void WitchBlastGame::updateIntro()
{
gameTime += deltaTime;
bool toMenu = false;
for (int i = 0; i < 2; i++)
{
introSprites[i]->setX(introSprites[i]->getX() - deltaTime * 35);
if (introSprites[i]->getX() < - SCREEN_WIDTH / 2) introSprites[i]->setX(introSprites[i]->getX() + 2 * SCREEN_WIDTH);
}
if (gameTime > 2.0f && introSoundState == 0)
{
SoundManager::getInstance().playSound(SOUND_INTRO_WITCH);
introSoundState++;
}
else if (gameTime > 7.0f && introSoundState == 1)
{
playMusic(MusicIntro);
introSoundState++;
}
if (introState == 0 && gameTime > 2.5f)
{
introState = 1;
introSprites[2] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_TITLE_ANIM),
SCREEN_WIDTH / 2,
SCREEN_HEIGHT / 2,
310, 278, 3);
introSprites[2]->setZ(50);
}
else if (introState == 1)
{
int frame = (gameTime - 2.5f) * 8.0f;
if (frame > 16)
{
frame = 16;
introState = 2;
introSprites[3] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_WITCH_INTRO));
introSprites[3]->setX(368 + 1000);
introSprites[3]->setY(424 - 480);
introSprites[3]->setZ(40);
EntityManager::getInstance().sortByZ();
}
introSprites[2]->setFrame(frame);
}
else if (introState == 2)
{
float xSprite = introSprites[3]->getX() - deltaTime * 800;
float ySprite = introSprites[3]->getY() + deltaTime * 400;
if (xSprite < 368)
{
introState = 3;
introSprites[3]->setDying(true);
EntityManager::getInstance().animate(deltaTime);
xSprite = 368;
ySprite = 424;
introSprites[4] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_SPLATTER));
introSprites[4]->setX(368);
introSprites[4]->setY(424);
introSprites[4]->setZ(45);
introSprites[4]->setScale(0.5f, 0.5f);
EntityManager::getInstance().sortByZ();
SoundManager::getInstance().stopSound(SOUND_INTRO_WITCH);
SoundManager::getInstance().playSound(SOUND_SPLATCH);
}
else
{
introSprites[3]->setX(xSprite);
introSprites[3]->setY(ySprite);
introSprites[3]->setAngle(gameTime * 500);
}
}
else if (introState == 3)
{
float scale = introSprites[4]->getScaleX();
scale += deltaTime * 5.0f;
if (scale > 1.0f) scale = 1.0f;
introSprites[4]->setScale(scale, scale);
if (gameTime > 8.0f)
{
introState = 4;
introSprites[2]->setDying(true);
introSprites[4]->setDying(true);
EntityManager::getInstance().animate(deltaTime);
toMenu = true;
}
}
sf::Event event;
while (app->pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
//saveGameData();
app->close();
}
if (event.type == sf::Event::Resized)
{
enableAA(true);
sf::View view = app->getDefaultView();
view = getLetterboxView( view, event.size.width, event.size.height );
app->setView(view);
}
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Return
|| event.key.code == sf::Keyboard::Space
|| event.key.code == sf::Keyboard::Escape)
{
if (introState < 4)
{
if (introState > 0) introSprites[2]->setDying(true);
if (introState == 2) introSprites[3]->setDying(true);
if (introState > 2) introSprites[4]->setDying(true);
EntityManager::getInstance().animate(deltaTime);
if (introState < 3)
{
SoundManager::getInstance().stopSound(SOUND_INTRO_WITCH);
SoundManager::getInstance().playSound(SOUND_SPLATCH);
}
}
toMenu = true;
}
}
}
if (toMenu)
{
if (introSoundState <= 1) playMusic(MusicIntro);
switchToMenu();
}
}
void WitchBlastGame::renderIntro()
{
app->draw(introScreenSprite);
titleSprite.setPosition(SCREEN_WIDTH / 2 - 15, 371);
if (introState == 4) app->draw(titleSprite);
EntityManager::getInstance().render(app);
}
void WitchBlastGame::updateRunningGame()
{
bool backToMenu = false;
// Process events
sf::Event event;
while (app->pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
if (gameState == gameStatePlaying && !player->isDead()) saveGame();
saveGameData();
app->close();
}
if (event.type == sf::Event::Resized)
{
enableAA(true);
sf::View view = app->getDefaultView();
view = getLetterboxView( view, event.size.width, event.size.height );
app->setView(view);
}
if (event.type == sf::Event::MouseWheelMoved)
{
if (gameState == gameStatePlaying) player->selectNextShotType();
}
if (event.type == sf::Event::KeyPressed)
{
if (event.key.code == sf::Keyboard::Escape)
{
if (player->isDead()) backToMenu = true;
else if (gameState == gameStatePlaying) gameState = gameStatePlayingPause;
else if (gameState == gameStatePlayingPause) gameState = gameStatePlaying;
else if (gameState == gameStatePlayingDisplayBoss) gameState = gameStatePlaying;
}
if (event.key.code == input[KeyFireSelect])
{
if (gameState == gameStatePlaying) player->selectNextShotType();
}
if (event.key.code == input[KeySpell])
{
if (gameState == gameStatePlaying) player->castSpell();
}
if (event.key.code == input[KeyDown] || event.key.code == sf::Keyboard::Down)
{
// in game menu ?
if (gameState == gameStatePlayingPause)
{
menuInGame.index++;
if (menuInGame.index == menuInGame.items.size()) menuInGame.index = 0;
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
}
else if (event.key.code == input[KeyUp] || event.key.code == sf::Keyboard::Up)
{
// in game menu ?
if (gameState == gameStatePlayingPause)
{
if (menuInGame.index == 0) menuInGame.index = menuInGame.items.size() - 1;
else menuInGame.index--;
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
}
else if (event.key.code == sf::Keyboard::Return)
{
// MENU
if (gameState == gameStatePlayingPause)
{
switch (menuInGame.items[menuInGame.index].id)
{
case MenuStartNew:
case MenuStartOld:
case MenuKeys:
case MenuConfig:
case MenuTutoReset:
case MenuConfigBack:
case MenuLanguage:
case MenuCredits:
case MenuHiScores:
case MenuPlayerName:
case MenuVolumeMusic:
case MenuVolumeSound:
case MenuAchievements:
std::cout << "[ERROR] Bad Menu ID\n";
break;
case MenuExit:
backToMenu = true;
remove(SAVE_FILE.c_str());
break;
case MenuContinue:
gameState = gameStatePlaying;
break;
case MenuSaveAndQuit:
saveGame();
backToMenu = true;
break;
}
}
}
if (event.key.code == input[KeyFire])
{
if (gameState == gameStatePlaying) firingDirection = player->getFacingDirection();
}
if (event.key.code == sf::Keyboard::Return)
{
if (player->isDead() && !xGame[xGameTypeFade].active && sf::Keyboard::isKeyPressed(sf::Keyboard::Return))
{
if (player->getDeathAge() < DEATH_CERTIFICATE_DELAY)
player->setDeathAge(DEATH_CERTIFICATE_DELAY);
else
backToMenu = true;
}
else if (gameState == gameStatePlayingDisplayBoss)
{
gameState = gameStatePlaying;
}
else if (!achievementsQueue.empty())
{
if (achievementsQueue.front().timer > 1.0f)
achievementsQueue.front().timer = 1.0f;
}
else if (!messagesQueue.empty())
{
if (messagesQueue.front().timer > 0.5f)
messagesQueue.front().timer = 0.5f;
}
}
if (event.key.code == input[KeyInteract])
{
if (!player->isDead() && interaction.active)
player->interact(interaction.type, interaction.id);
}
if (event.key.code == sf::Keyboard::X)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LShift)) startNewGame(false);
}
if (event.key.code == sf::Keyboard::F1)
{
if (!isPlayerAlive && player->getDeathAge() > 3.5f)
{
if (scoreSaveFile.compare("") == 0) saveDeathScreen();
}
+ else
+ {
+ saveScreen();
+ }
}
if (event.key.code == sf::Keyboard::F2)
{
showLogical = !showLogical;
}
if (event.key.code == sf::Keyboard::F3)
{
showGameTime = !showGameTime;
}
// DEBUG
#ifdef TEST_MODE
/*if (event.key.code == sf::Keyboard::Delete)
{
StructHurt hurt;
hurt.critical = false;
hurt.damage = 1;
hurt.enemyType = EnemyTypeGhost; //EnemyTypeNone;
hurt.goThrough = false;
hurt.hurtingType = ShotTypeStandard;
hurt.level = 0;
hurt.sourceType = SourceTypeMelee;
player->hurt(hurt);
}*/
if (event.key.code == sf::Keyboard::F5)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new BubbleEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 + 70,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2, BubbleTriple, 0);
new BubbleEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 - 70,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2, BubbleIce, 0);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeRat, 1);
findPlaceMonsters(EnemyTypeRatBlack, 1);
findPlaceMonsters(EnemyTypeRatGreen, 1);
findPlaceMonsters(EnemyTypeRatHelmet, 1);
findPlaceMonsters(EnemyTypeRatBlackHelmet, 1);
}
}
if (event.key.code == sf::Keyboard::F6)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new ButcherEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeBat, 1);
findPlaceMonsters(EnemyTypeBatSkeleton, 2);
findPlaceMonsters(EnemyTypeImpBlue, 1);
findPlaceMonsters(EnemyTypeImpRed, 1);
}
}
if (event.key.code == sf::Keyboard::F7)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new GiantSlimeEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeEvilFlower, 1);
findPlaceMonsters(EnemyTypeEvilFlowerIce, 1);
findPlaceMonsters(EnemyTypeEvilFlowerFire, 1);
findPlaceMonsters(EnemyTypePumpkin, 1);
}
}
if (event.key.code == sf::Keyboard::F8)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new CyclopsEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeSlime, 1);
findPlaceMonsters(EnemyTypeSlimeBlue, 1);
findPlaceMonsters(EnemyTypeSlimeRed, 1);
findPlaceMonsters(EnemyTypeSlimeViolet, 1);
}
}
if (event.key.code == sf::Keyboard::F9)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new KingRatEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeSnake, 2);
findPlaceMonsters(EnemyTypeSnakeBlood, 2);
}
}
if (event.key.code == sf::Keyboard::F10)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new GiantSpiderEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeWitch, 1);
findPlaceMonsters(EnemyTypeWitchRed, 1);
findPlaceMonsters(EnemyTypeCauldron, 1);
findPlaceMonsters(EnemyTypeCauldronElemental, 1);
}
}
if (event.key.code == sf::Keyboard::F11)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new FranckyEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeSpiderEgg_invocated, 2);
findPlaceMonsters(EnemyTypeSpiderLittle_invocated, 2);
}
}
if (event.key.code == sf::Keyboard::F12)
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt))
{
new VampireEntity(OFFSET_X + (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
OFFSET_Y + (MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
initMonsterArray();
findPlaceMonsters(EnemyTypeZombie, 2);
findPlaceMonsters(EnemyTypeZombieDark, 2);
findPlaceMonsters(EnemyTypeGhost, 2);
findPlaceMonsters(EnemyTypeBogeyman, 2);
}
}
if (event.key.code == sf::Keyboard::F4)
{
for (int i = 0; i < NUMBER_ITEMS; i++)
new ItemEntity((enumItemType)i, 100 + (i % 14) * 58, 100 + (i / 14) * 60);
}
#endif // TEST_MODE
}
if (event.type == sf::Event::LostFocus && !player->isDead())
gameState = gameStatePlayingPause;
}
if (gameState == gameStatePlaying)
{
if (player->canMove()) player->setVelocity(Vector2D(0.0f, 0.0f));
if (sf::Keyboard::isKeyPressed(input[KeyLeft]))
{
if (sf::Keyboard::isKeyPressed(input[KeyUp]))
player->move(7);
else if (sf::Keyboard::isKeyPressed(input[KeyDown]))
player->move(1);
else
player->move(4);
}
else if (sf::Keyboard::isKeyPressed(input[KeyRight]))
{
if (sf::Keyboard::isKeyPressed(input[KeyUp]))
player->move(9);
else if (sf::Keyboard::isKeyPressed(input[KeyDown]))
player->move(3);
else
player->move(6);
}
else if (sf::Keyboard::isKeyPressed(input[KeyUp]))
{
player->move(8);
}
else if (sf::Keyboard::isKeyPressed(input[KeyDown]))
{
player->move(2);
}
player->resestFireDirection();
if (sf::Keyboard::isKeyPressed(input[KeyFireLeft]))
player->fire(4);
else if (sf::Keyboard::isKeyPressed(input[KeyFireRight]))
player->fire(6);
else if (sf::Keyboard::isKeyPressed(input[KeyFireUp]))
player->fire(8);
else if (sf::Keyboard::isKeyPressed(input[KeyFireDown]))
player->fire(2);
// alternative "one button" gameplay
else if (sf::Keyboard::isKeyPressed(input[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);
}
}
// spell (right click)
if (sf::Mouse::isButtonPressed(sf::Mouse::Right) && (gameState == gameStatePlaying))
{
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->setFacingDirection(6);
else player->setFacingDirection(4);
}
else
{
if (ym > 0) player->setFacingDirection(2);
else player->setFacingDirection(8);
}
player->castSpell();
}
// message queue
if (!messagesQueue.empty())
{
messagesQueue.front().timer -= deltaTime;
if (messagesQueue.front().timer < 0.0f)
{
messagesQueue.pop();
if (!messagesQueue.empty()) SoundManager::getInstance().playSound(SOUND_MESSAGE);
}
}
// achievement queue
if (!achievementsQueue.empty() && achievementsQueue.front().hasStarted)
{
achievementsQueue.front().timer -= deltaTime;
if (achievementsQueue.front().timer < 0.0f)
{
achievementsQueue.pop();
if (achievementsQueue.empty()) music.play();
}
}
}
onUpdate();
verifyDoorUnlocking();
checkInteraction();
if (roomClosed)
{
if (getEnemyCount() == 0)
{
currentMap->setCleared(true);
if (currentMap->getRoomType() == roomTypeKey)
new ItemEntity( (enumItemType)(ItemBossKey),
MAP_WIDTH / 2 * TILE_WIDTH + TILE_WIDTH / 2,
MAP_HEIGHT / 2 * TILE_HEIGHT + TILE_HEIGHT / 2);
player->onClearRoom();
openDoors();
remove(SAVE_FILE.c_str());
if (currentMap->getRoomType() == roomTypeBoss)
{
playMusic(MusicDungeon);
}
else if (currentMap->getRoomType() == roomTypeChallenge && !player->isDead())
{
ChestEntity* chest = new ChestEntity((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f),
ChestChallenge, false);
chest->makeAppear();
// sound
SoundManager::getInstance().playSound(SOUND_GONG);
playMusic(MusicDungeon);
// text
float x0 = MAP_WIDTH * 0.5f * TILE_WIDTH;
float y0 = MAP_HEIGHT * 0.5f * TILE_HEIGHT + 40.0f;
TextEntity* text = new TextEntity("COMPLETE !", 30, x0, y0);
text->setAlignment(ALIGN_CENTER);
text->setLifetime(2.5f);
text->setWeight(-36.0f);
text->setZ(1200);
text->setColor(TextEntity::COLOR_FADING_WHITE);
challengeLevel++;
if (challengeLevel == 5) registerAchievement(AchievementChallenges);
player->offerChallenge();
}
}
}
if (backToMenu)
{
if (player->isDead())
{
EntityManager::getInstance().clean();
introSprites[0] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_FOG));
introSprites[0]->setX(SCREEN_WIDTH / 2);
introSprites[0]->setY(SCREEN_HEIGHT - 202);
introSprites[1] = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_FOG));
introSprites[1]->setX(SCREEN_WIDTH / 2 + 970);
introSprites[1]->setY(SCREEN_HEIGHT - 202);
switchToMenu();
menuState = MenuStateHiScores;
}
else
{
prepareIntro();
}
}
}
void WitchBlastGame::addLifeBarToDisplay(std::string label, int hp, int hpMax)
{
lifeBar.toDisplay = true;
lifeBar.label = label;
lifeBar.hp = hp;
lifeBar.hpMax = hpMax;
}
void WitchBlastGame::renderBossPortrait()
{
if (gameState == gameStatePlayingDisplayBoss)
{
float transitionTime = 2.5f;
float endTime = PORTRAIT_DIAPLAY_TIME;
int xBoss = GAME_WIDTH / 2 - 267;
int fade = 255;
if (bossDisplayTimer < 0.25f)
{
xBoss += (0.25f - bossDisplayTimer) * 3000;
//fade = 255 - (0.25f - bossDisplayTimer) * 1000;
}
else if (bossDisplayTimer > endTime - 0.75f)
{
fade = (endTime - bossDisplayTimer) * 333;
if (fade < 0) fade = 0;
}
// background
sf::RectangleShape rectangle;
rectangle.setFillColor(sf::Color(0, 0, 0, fade));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH, MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
// boss
if (bossDisplayTimer > transitionTime) // + 1.0f)
{
EnemyEntity* boss = getBoss();
if (boss)
{
sf::View view = app->getView();
view.move(-5, -5);
app->setView(view);
boss->render(app);
view.move(5, 5);
app->setView(view);
}
/*if (bossDisplayTimer < transitionTime + 1.5f)
{
rectangle.setFillColor(sf::Color(0, 0, 0, (1.5 - (bossDisplayTimer - transitionTime)) * 510));
app->draw(rectangle);
std::cout << 1.5 - (bossDisplayTimer - transitionTime) << " ";
}*/
//if (bossDisplayTimer < transitionTime + 2.0f)
{
//rectangle.setFillColor(sf::Color(0, 0, 0, (2.0 - (bossDisplayTimer - transitionTime)) * 255));
//app->draw(rectangle);
//std::cout << 1.5 - (bossDisplayTimer - transitionTime) << " ";
}
}
// boss portrait
if (bossDisplayTimer < transitionTime)
{
sf::Sprite bossSprite;
bossSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_BOSS_PICTURES));
bossSprite.setPosition(xBoss, 0);
app->draw(bossSprite);
}
else
{
if (bossDisplayState == 0)
{
SoundManager::getInstance().playSound(SOUND_BOOM_00);
for (int i = 0; i < 250; i++)
{
SpriteEntity* spriteStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_PORTRAIT_PART),
GAME_WIDTH / 2 - 150 + rand() % 300, GAME_HEIGHT / 2 - 150 + rand() % 300);
spriteStar->setScale(5.0f, 5.0f);
spriteStar->setZ(7000.0f);
spriteStar->setSpin(-100 + rand()%200);
spriteStar->setVelocity(Vector2D(400 + rand()%800));
spriteStar->setFading(true);
spriteStar->setLifetime(4.1f + (rand() % 100) * 0.003f );
spriteStar->setColor(sf::Color(rand() % 255, rand() % 255, 255, 128));
spriteStar->setColor(sf::Color(40, 4, 40, 128));
spriteStar->setType(ENTITY_EFFECT);
if (rand()% 2 == 0) spriteStar->setRenderAdd();
}
bossDisplayState = 1;
}
else if (bossDisplayState == 1 && bossDisplayTimer > transitionTime + 0.2f)
{
bossDisplayState = 2;
for (int i = 0; i < 50; i++)
{
SpriteEntity* spriteStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_PORTRAIT_PART),
GAME_WIDTH / 2 - 150 + rand() % 300, GAME_HEIGHT / 2 - 150 + rand() % 300);
spriteStar->setScale(4.0f, 4.0f);
spriteStar->setZ(7000.0f);
spriteStar->setSpin(-100 + rand()%200);
spriteStar->setVelocity(Vector2D(400 + rand()%800));
spriteStar->setFading(true);
spriteStar->setLifetime(4.1f + (rand() % 100) * 0.003f );
spriteStar->setColor(sf::Color(rand() % 255, rand() % 255, 255, 128));
spriteStar->setColor(sf::Color(20, 2, 20, 128));
spriteStar->setType(ENTITY_EFFECT);
spriteStar->setRenderAdd();
}
}
else if (bossDisplayState == 2 && bossDisplayTimer > transitionTime + 0.4f)
{
bossDisplayState = 3;
for (int i = 0; i < 50; i++)
{
SpriteEntity* spriteStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_PORTRAIT_PART),
GAME_WIDTH / 2 - 150 + rand() % 300, GAME_HEIGHT / 2 - 150 + rand() % 300);
spriteStar->setScale(3.0f, 3.0f);
spriteStar->setZ(7000.0f);
spriteStar->setSpin(-100 + rand()%200);
spriteStar->setVelocity(Vector2D(400 + rand()%800));
spriteStar->setFading(true);
spriteStar->setLifetime(4.1f + (rand() % 100) * 0.003f );
spriteStar->setColor(sf::Color(rand() % 255, rand() % 255, 255, 128));
spriteStar->setColor(sf::Color(20, 2, 20, 128));
spriteStar->setType(ENTITY_EFFECT);
spriteStar->setRenderAdd();
}
}
animateEffects();
}
}
}
void WitchBlastGame::renderGame()
{
lifeBar.toDisplay = false;
EntityManager::getInstance().renderUnder(app, 5000);
EntityManager::getInstance().renderUnder(app, 5000);
}
void WitchBlastGame::generateUiParticle(float x, float y)
{
SpriteEntity* particle = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_BOLT),
x, y, BOLT_WIDTH, BOLT_HEIGHT);
particle->setFading(true);
particle->setImagesProLine(BOLT_PRO_LINE);
particle->setZ(10000);
particle->setLifetime(0.5f);
particle->setVelocity(Vector2D(30 + rand() % 50));
particle->setWeight(200);
particle->setType(ENTITY_EFFECT);
//particle->setFrame(BOLT_PRO_LINE + 2);
particle->setFrame(BOLT_PRO_LINE * 2 + 6);
particle->setRenderAdd();
particle->setScale(0.35f, 0.35f);
particle->setFading(true);
}
void WitchBlastGame::renderHud()
{
// boss life bar ?
if (lifeBar.toDisplay && gameState != gameStatePlayingDisplayBoss) renderLifeBar();
renderBossPortrait();
// achievements ?
if (!achievementsQueue.empty() && (currentMap->isCleared() || achievementsQueue.front().hasStarted) )
{
if (!achievementsQueue.front().hasStarted)
{
music.pause();
SoundManager::getInstance().playSound(SOUND_ACHIEVEMENT);
achievementsQueue.front().hasStarted = true;
achievementState[achievementsQueue.front().type] = AchievementDone;
saveGameData();
proceedEvent(EventAchievement);
// text
float x0 = MAP_WIDTH * 0.5f * TILE_WIDTH;
float y0 = MAP_HEIGHT * 0.5f * TILE_HEIGHT + 40.0f;
TextEntity* text = new TextEntity(tools::getLabel("achievement_complete"), 30, x0, y0);
text->setAlignment(ALIGN_CENTER);
text->setLifetime(2.5f);
text->setWeight(-36.0f);
text->setZ(1200);
text->setColor(TextEntity::COLOR_FADING_WHITE);
}
int xPos = 560;
int yPos = 4;
int opening = 384;
float achievAge = ACHIEVEMENT_DELAY_MAX - achievementsQueue.front().timer;
sf::Sprite spriteScroll;
if (achievAge < 1.0f)
opening = 32;
else if (achievAge < 2.0f)
opening = 32 + (achievAge - 1.0f) * (384 - 32);
else if (achievAge > ACHIEVEMENT_DELAY_MAX - 1.0f)
opening = 32 + (ACHIEVEMENT_DELAY_MAX - achievAge) * (384 - 32);
if (achievAge < 0.5f)
spriteScroll.setColor(sf::Color(255, 255, 255, 500 * achievAge));
else if (achievAge > ACHIEVEMENT_DELAY_MAX - 0.5f)
spriteScroll.setColor(sf::Color(255, 255, 255, 500 * (ACHIEVEMENT_DELAY_MAX - achievAge)));
spriteScroll.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_ACHIEV));
spriteScroll.setTextureRect(sf::IntRect(128 + 384 - opening, 0, opening, 64));
spriteScroll.setPosition(xPos + 384 - opening, yPos);
app->draw(spriteScroll);
if ((achievAge > 1.0f && achievAge < 2.0f) || achievAge > ACHIEVEMENT_DELAY_MAX - 1.0f)
spriteScroll.setTextureRect(sf::IntRect(32 * ((int)(achievAge * 8) % 4), 0, 32, 64));
else
spriteScroll.setTextureRect(sf::IntRect(0, 0, 32, 64));
spriteScroll.setPosition(xPos + 394 - opening - 16, yPos);
app->draw(spriteScroll);
if (achievAge > 2.0f && achievAge < ACHIEVEMENT_DELAY_MAX - 1.0f)
{
sf::Sprite icon;
icon.setTexture(*ImageManager::getInstance().getImage(IMAGE_ACHIEVEMENTS));
icon.setTextureRect(sf::IntRect( ((achievementsQueue.front().type + 1) % 10) * 64,
((achievementsQueue.front().type + 1) / 10) * 64, 64, 64));
icon.setPosition(xPos + 308, yPos + 9);
icon.setScale(0.7f, 0.7f);
app->draw(icon);
icon.setColor(sf::Color(255, 255, 255, 50 + 50 * cosf(getAbsolutTime() * 4)));
app->draw(icon, sf::BlendAdd);
game().write(achievementsQueue.front().message, 13, xPos + 34, yPos + 10, ALIGN_LEFT, sf::Color::Black, app, 0, 0);
if (achievements[achievementsQueue.front().type].unlockType == UnlockItem)
{
game().write(tools::getLabel(items[achievements[achievementsQueue.front().type].unlock].name),
13, xPos + 70, yPos + 34, ALIGN_LEFT, sf::Color::Black, app, 0, 0);
}
else if (achievements[achievementsQueue.front().type].unlockType == UnlockFunctionality)
{
game().write(tools::getLabel(functionalityLabel[achievements[achievementsQueue.front().type].unlock]),
13, xPos + 70, yPos + 34, ALIGN_LEFT, sf::Color::Black, app, 0, 0);
}
}
//if (achievAge < 1.0f)
{
int i = achievementsQueue.front().counter;
if (i < 64)
{
for (int j = 0; j < 2; j++)
{
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40, yPos - i + 64);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40, yPos - i + 64 + 1);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40, yPos - i + 64 + 2);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40, yPos - i + 64 + 3);
}
}
else if (i < 40 + 64)
{
for (int j = 0; j < 2; j++)
{
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40 + i - 64, yPos);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40 + i - 63, yPos);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40 + i - 62, yPos);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - 40 + i - 61, yPos);
}
}
else if (i < 40 + 64 + 64)
{
for (int j = 0; j < 2; j++)
{
generateUiParticle(xPos + 394 + 16 + 4 - opening, yPos + i - 40 - 64);
generateUiParticle(xPos + 394 + 16 + 4 - opening, yPos + i - 40 - 64 + 1);
generateUiParticle(xPos + 394 + 16 + 4 - opening, yPos + i - 40 - 64 + 2);
generateUiParticle(xPos + 394 + 16 + 4 - opening, yPos + i - 40 - 64 + 3);
}
}
else if (i < 40 + 64 + 40 + 64)
{
for (int j = 0; j < 2; j++)
{
generateUiParticle(xPos + 394 + 16 + 4 - 32 - i + 144, yPos + 64);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - i + 144 + 1, yPos + 64);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - i + 144 + 2, yPos + 64);
generateUiParticle(xPos + 394 + 16 + 4 - 32 - i + 144 + 3, yPos + 64);
}
}
achievementsQueue.front().counter += 4;
}
}
// interaction text ?
if (interaction.active)
{
if (interaction.type == InteractionTypeTemple)
write(interaction.label, 20, GAME_WIDTH / 2, 480, ALIGN_CENTER,sf::Color::White, app, 2, 2);
else if (interaction.type == InteractionTypeMerchandise)
write(interaction.label, 20, GAME_WIDTH / 2, 480, ALIGN_CENTER,sf::Color::White, app, 2, 2);
}
// light cone ?
float fade = player->getLightCone();
if (fade > 0.0f)
{
sf::Sprite cone;
cone.setTexture(*ImageManager::getInstance().getImage(IMAGE_LIGHT_CONE));
cone.setPosition(player->getX() - 64, player->getY() - 580);
cone.setColor(sf::Color(255, 255, 255, 255 * fade));
app->draw(cone, sf::BlendAdd);
}
app->draw(uiSprites.gui);
EntityManager::getInstance().renderAfter(app, 5000);
if (gameState == gameStatePlayingDisplayBoss)
{
// boss name
int fade = 255;
if (bossDisplayTimer < 0.25f)
{
fade = 255 - (0.25f - bossDisplayTimer) * 1000;
}
else if (bossDisplayTimer > PORTRAIT_DIAPLAY_TIME - 0.25f)
{
fade = (PORTRAIT_DIAPLAY_TIME - bossDisplayTimer) * 1000;
if (fade < 0) fade = 0;
}
write("THE COOK", 27, GAME_WIDTH / 2, 540, ALIGN_CENTER, sf::Color(255, 255, 255, fade), app, 0, 0);
}
}
void WitchBlastGame::renderLifeBar()
{
if (lifeBar.toDisplay)
{
float l = lifeBar.hp * ((MAP_WIDTH - 1) * TILE_WIDTH) / lifeBar.hpMax;
int label_dy = 0;
sf::RectangleShape rectangle(sf::Vector2f((MAP_WIDTH - 1) * TILE_WIDTH, 25));
rectangle.setFillColor(sf::Color(0, 0, 0,128));
rectangle.setPosition(sf::Vector2f(TILE_WIDTH / 2, label_dy + 22));
rectangle.setOutlineThickness(1);
rectangle.setOutlineColor(sf::Color(200, 200, 200, 200));
app->draw(rectangle);
rectangle.setSize(sf::Vector2f(l, 25));
rectangle.setFillColor(sf::Color(190, 20, 20));
rectangle.setOutlineThickness(0);
rectangle.setPosition(sf::Vector2f(TILE_WIDTH / 2, label_dy + 22));
app->draw(rectangle);
game().write( lifeBar.label,
18,
TILE_WIDTH / 2 + 10.0f,
label_dy + 23,
ALIGN_LEFT,
sf::Color(255, 255, 255),
app, 0 , 0);
}
}
void WitchBlastGame::renderRunningGame()
{
EntityManager::getInstance().sortByZ();
if (!isPlayerAlive)
{
sf::View view = app->getView();
sf::View viewSave = app->getView();
if (!parameters.zoom || player->getDeathAge() > 4.0f)
{
// do nothing
}
else if (player->getDeathAge() > 3.0f)
{
view.zoom(1.0f - 0.75f * (4.0f - player->getDeathAge()));
float xDiff = view.getCenter().x - player->getX();
float yDiff = view.getCenter().y - player->getY();
view.setCenter(view.getCenter().x - xDiff * (4.0f - player->getDeathAge()),
view.getCenter().y - yDiff * (4.0f - player->getDeathAge()));
}
else if (player->getDeathAge() > 1.0f)
{
view.zoom(0.25f);
view.setCenter(player->getX(), player->getY());
}
else
{
view.zoom(1.0f - 0.75f * (player->getDeathAge()));
float xDiff = view.getCenter().x - player->getX();
float yDiff = view.getCenter().y - player->getY();
view.setCenter(view.getCenter().x - xDiff * player->getDeathAge(),
view.getCenter().y - yDiff * player->getDeathAge());
}
view.move(-5, -5);
app->setView(view);
renderGame();
app->setView(viewSave);
renderHud();
}
else if (parameters.zoom && gameTime < 1.0f)
{
sf::View view = app->getView();
sf::View viewSave = app->getView();
view.zoom(0.25f + 0.75f * (gameTime));
view.move(-5, -5);
app->setView(view);
renderGame();
app->setView(viewSave);
renderHud();
}
else if (xGame[xGameTypeShake].active)
{
sf::View view = app->getView();
sf::View viewSave = app->getView();
view.move(-4 + rand() % 9, -4 + rand() % 9);
app->setView(view);
renderGame();
app->setView(viewSave);
renderHud();
}
else
{
sf::View view = app->getView();
sf::View viewSave = app->getView();
view.move(-OFFSET_X, -OFFSET_Y);
app->setView(view);
renderGame();
app->setView(viewSave);
renderHud();
}
sf::RectangleShape rectangle(sf::Vector2f(200, 25));
// effects
if (sf::Keyboard::isKeyPressed(input[KeyTimeControl]) && gameState == gameStatePlaying)
{
// effect
int effectFade = 10 + 20 * (1.0f + cos(12.0f * getAbsolutTime())) * 0.5f;
rectangle.setFillColor(sf::Color(0, 255, 255, effectFade));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
sf::RenderStates r;
r.blendMode = sf::BlendAlpha ;
app->draw(rectangle, r);
}
if (xGame[xGameTypeFade].active && xGame[xGameTypeFade].param == X_GAME_FADE_IN)
{
// fade in
rectangle.setFillColor(sf::Color(0, 0, 0, 255 - ((FADE_IN_DELAY - xGame[xGameTypeFade].timer) / FADE_IN_DELAY) * 255));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
}
else if (xGame[xGameTypeFade].active && xGame[xGameTypeFade].param == X_GAME_FADE_OUT)
{
// fade out
rectangle.setFillColor(sf::Color(0, 0, 0, ((FADE_IN_DELAY - xGame[xGameTypeFade].timer) / FADE_IN_DELAY) * 255));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
}
if (player->isSpecialStateActive(BaseCreatureEntity::SpecialStateConfused))
{
BaseCreatureEntity::specialStateStuct specialState = player->getSpecialState(BaseCreatureEntity::SpecialStateConfused);
// effect
int effectFade = 150 + cos(3.0f * getAbsolutTime()) * 100;
// fade
int fade = 55;
if (specialState.timer < 0.4f)
fade = 55 - (0.4f - specialState.timer) / 0.4f * 55;
else if (specialState.timer > specialState.param1 - 0.4f)
fade = (specialState.param1 - specialState.timer) / 0.4f * 55;
if (fade < 0) fade = 0;
else if (fade > 55) fade = 55;
fade *= 1.5f;
rectangle.setFillColor(sf::Color(255 - effectFade, 0, effectFade, fade));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
sf::RenderStates r;
r.blendMode = sf::BlendAlpha ;
app->draw(rectangle, r);
}
else if (xGame[xGameTypeFadeColor].active)
{
// color fade
unsigned int r = 0, g = 0, b = 0;
switch (xGame[xGameTypeFadeColor].param)
{
case X_GAME_COLOR_RED:
r = 255;
g = 100;
break;
case X_GAME_COLOR_GREEN:
g = 255;
break;
case X_GAME_COLOR_BLUE:
b = 255;
break;
case X_GAME_COLOR_VIOLET:
r = 255;
b = 200;
break;
case X_GAME_COLOR_BROWN:
r = 200;
b = 100;
g = 150;
break;
case X_GAME_COLOR_WHITE:
r = 255;
b = 255;
g = 255;
break;
}
int alpha = xGame[xGameTypeFadeColor].timer * 200.0f / xGame[xGameTypeFadeColor].duration;
rectangle.setFillColor(sf::Color(r, g, b, alpha));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle, sf::BlendAdd);
}
if (gameState != gameStatePlayingDisplayBoss) renderMessages();
app->draw(uiSprites.topLayer);
std::ostringstream oss;
oss << player->getGold();
write(oss.str(), 18, 518, 619, ALIGN_CENTER, sf::Color::White, app, 0, 0);
myText.setColor(sf::Color(0, 0, 0, 255));
myText.setCharacterSize(16);
oss.str("");
oss << tools::getLabel("level") << " " << level;
write(oss.str(), 16, 880, 610, ALIGN_CENTER, sf::Color::Black, app, 0, 0);
//if (gameState == gameStatePlaying)
{
// life
// if (player->isPoisoned()) TODO
sf::Sprite hpSprite;
hpSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_LIFE));
int hpFade = 88.0f * (float)player->getHpDisplay() / (float)player->getHpMax();
if (hpFade < 0) hpFade = 0;
else if (hpFade > 88) hpFade = 88;
hpSprite.setPosition(170, 619 + 88 - hpFade);
hpSprite.setTextureRect(sf::IntRect(0, 88 - hpFade, 88, hpFade));
app->draw(hpSprite);
oss.str("");
oss << player->getHp() << "/" << player->getHpMax();
write(oss.str(), 16, 210, 654, ALIGN_CENTER, sf::Color::White, app, 0, 0);
// mana
sf::Sprite manaSprite;
manaSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_MANA));
int manaFade = player->getPercentFireDelay() * 98;
manaSprite.setPosition(558, 614 + 98 - manaFade);
manaSprite.setTextureRect(sf::IntRect(0, 98 - manaFade, 98, manaFade));
app->draw(manaSprite);
if (player->getActiveSpell().spell != SpellNone)
{
//oss.str("");
//oss << tools::getLabel(spellLabel[player->getActiveSpell().spell]);
//if (player->isEquiped(EQUIP_BOOK_MAGIC_II)) oss << "+";
//write(oss.str(), 14, 95, 663, ALIGN_LEFT, sf::Color::White, app, 0, 0);
// TODO
sf::Sprite spellSprite;
spellSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_UI_SPELLS));
spellSprite.setPosition(568, 624);
int frame = player->getActiveSpell().spell;
spellSprite.setTextureRect(sf::IntRect(frame * 78, 78, 78, 78));
//spellSprite.scale(2.0f, 2.0f);
app->draw(spellSprite);
int spellFade = player->getPercentSpellDelay() * 78;
spellSprite.setPosition(568, 624 + 78 - spellFade);
spellSprite.setTextureRect(sf::IntRect(frame * 78, 78 - spellFade, 78, spellFade));
app->draw(spellSprite);
if (player->canCastSpell())
{
float fade = (cos(8.0f * getAbsolutTime()) + 1.0f) * 0.5f;
spellSprite .setColor(sf::Color(255, 255, 255, 255 * fade));
app->draw(spellSprite, sf::BlendAdd);
}
}
// drawing the key on the interface
if (player->isEquiped(EQUIP_BOSS_KEY)) app->draw(uiSprites.keySprite);
if (player->isEquiped(EQUIP_FLOOR_MAP))
{
sf::Sprite mapSprite;
mapSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
mapSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * 3, ITEM_HEIGHT * 4, ITEM_WIDTH, ITEM_HEIGHT));
mapSprite.setPosition(737, 648);
app->draw(mapSprite);
}
if (player->isEquiped(EQUIP_ALCOHOL))
{
sf::Sprite alcSprite;
alcSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
alcSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * 4, ITEM_HEIGHT * 4, ITEM_WIDTH, ITEM_HEIGHT));
alcSprite.setPosition(737, 681);
app->draw(alcSprite);
}
if (player->isEquiped(EQUIP_LUCK))
{
sf::Sprite alcSprite;
alcSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
alcSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * 5, ITEM_HEIGHT * 4, ITEM_WIDTH, ITEM_HEIGHT));
alcSprite.setPosition(704, 681);
app->draw(alcSprite);
}
if (player->isEquiped(EQUIP_FAIRY_POWDER))
{
sf::Sprite alcSprite;
alcSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
alcSprite.setTextureRect(sf::IntRect(ITEM_WIDTH * 6, ITEM_HEIGHT * 4, ITEM_WIDTH, ITEM_HEIGHT));
alcSprite.setPosition(671, 681);
app->draw(alcSprite);
}
// drawing message icon
if (!messagesQueue.empty())
{
int fade = 255;
if (messagesQueue.front().timer < 0.5f)
{
fade = (2 * messagesQueue.front().timer) * 255;
}
else if (messagesQueue.front().timerMax - messagesQueue.front().timer < 0.5f)
{
fade = (2 * (messagesQueue.front().timerMax - messagesQueue.front().timer)) * 255;
}
uiSprites.iconSprite.setColor(sf::Color(255, 255, 255, fade));
uiSprites.iconSprite.setTextureRect(sf::IntRect((messagesQueue.front().icon % 10) * 72, (messagesQueue.front().icon / 10) * 96, 72, 96));
app->draw(uiSprites.iconSprite);
}
// drawing the divinity
if (player->getDivinity().divinity >= 0)
{
sf::Sprite divSprite;
divSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_DIVINITY));
divSprite.setPosition(100, 614);
divSprite.setTextureRect(sf::IntRect(player->getDivinity().divinity * 48, 0, 48, 85));
app->draw(divSprite);
float fade = player->getLightCone();
if (fade > 0.0f && player->getPlayerStatus() != PlayerEntity::playerStatusPraying)
{
divSprite.setTextureRect(sf::IntRect(player->getDivinity().divinity * 48, 85, 48, 85));
divSprite.setColor(sf::Color(255, 255, 255, 255 * fade));
app->draw(divSprite);
}
rectangle.setOutlineThickness(0);
if (player->getDivinity().interventions + 1 < player->getDivinity().level)
{
int fade = 50 + 50 * cosf(game().getAbsolutTime() * 8);
rectangle.setFillColor(sf::Color(100 + fade, 100 + fade, 200 + fade / 2, 255));
}
else
rectangle.setFillColor(sf::Color(100, 100, 200, 255));
rectangle.setPosition(sf::Vector2f(101, 689));
rectangle.setSize(sf::Vector2f(46 * player->getDivinity().percentsToNextLevels, 9));
app->draw(rectangle);
std::ostringstream oss;
if (player->getDivinity().level == MAX_DIVINITY_LEVEL + 1) oss << "MAX";
else oss << "lvl " << player->getDivinity().level;
write(oss.str(), 11, 122, 702, ALIGN_CENTER, sf::Color::White, app, 0, 0);
}
// render the shots
renderHudShots(app);
if (gameState == gameStatePlayingPause)
{
// background
rectangle.setFillColor(sf::Color(0, 0, 0, 200));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH, MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
// minimap
int mapx = 350;
int mapy = 30;
// background
app->draw(rectangle);
app->draw(uiSprites.mapBgSprite);
// map
float miniX = miniMapEntity->getX();
float miniY = miniMapEntity->getY();
miniMapEntity->setX(mapx);
miniMapEntity->setY(mapy);
miniMapEntity->computeVertices();
miniMapEntity->render(app);
miniMapEntity->setX(miniX);
miniMapEntity->setY(miniY);
miniMapEntity->computeVertices();
float x = 200;
float y = 480;
// items
write(tools::getLabel("inventory"), 16, x, y, ALIGN_LEFT, sf::Color::White, app, 0, 0);
int n = 0;
for (auto i: sortedEquipement)
{
if (i != EQUIP_BOSS_KEY && player->isEquiped(i))
{
sf::Sprite itemSprite;
itemSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
itemSprite.setPosition(x + n * 32, y + 20);
itemSprite.setTextureRect(sf::IntRect((i % 10) * 32, (i / 10) * 32, 32, 32));
app->draw(itemSprite);
n++;
}
}
renderInGameMenu();
}
if (player->isDead())
{
float deathAge = player->getDeathAge();
if (deathAge > DEATH_CERTIFICATE_DELAY)
{
rectangle.setFillColor(sf::Color(0, 0, 0, 180));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
renderDeathScreen(80, 110);
if (scoreSaveFile.compare("") == 0)
{
write(tools::getLabel("certificate_capture"), 16, 80, 430, ALIGN_LEFT, sf::Color::White, app, 0, 0);
}
else
{
std::stringstream ss;
ss << tools::getLabel("certificate_saved") << " " << scoreSaveFile;
write(ss.str(), 16, 80, 430, ALIGN_LEFT, sf::Color::White, app, 0, 0);
}
}
else if (deathAge > DEATH_CERTIFICATE_DELAY - 1.0f)
{
rectangle.setFillColor(sf::Color(0, 0, 0, 180 * (deathAge - 2.5f)));
rectangle.setPosition(sf::Vector2f(xOffset, yOffset));
rectangle.setSize(sf::Vector2f(MAP_WIDTH * TILE_WIDTH , MAP_HEIGHT * TILE_HEIGHT));
app->draw(rectangle);
renderDeathScreen(80 + (DEATH_CERTIFICATE_DELAY - deathAge) * 1000, 110);
}
}
else if (currentMap->getRoomType() == roomTypeExit && level >= LAST_LEVEL)
{
float x0 = (MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2;
write(tools::getLabel("congratulations_1"), 25, x0, 220, ALIGN_CENTER, sf::Color::White, app, 2, 2);
write(tools::getLabel("congratulations_2"), 23, x0, 250, ALIGN_CENTER, sf::Color::White, app, 2, 2);
write(tools::getLabel("congratulations_3"), 23, x0, 280, ALIGN_CENTER, sf::Color::White, app, 2, 2);
registerAchievement(AchievementWin);
}
}
// show game time
if (showGameTime)
{
int minutes = (int)gameTime / 60;
int secondes = (int)gameTime % 60;
std::stringstream ss;
if (minutes < 10) ss << "0";
ss << minutes;
ss << ":";
if (secondes < 10) ss << "0";
ss << secondes;
write(ss.str(), 14, 4, 4, ALIGN_LEFT, sf::Color::Green, app, 0,0);
}
}
void WitchBlastGame::renderMessages()
{
// message queue
if (!messagesQueue.empty())
{
int dy = 30;
if (messagesQueue.front().timer < 0.5f)
{
dy *= (2 * messagesQueue.front().timer);
}
else if (messagesQueue.front().timerMax - messagesQueue.front().timer < 0.5f)
{
dy *= (2 * (messagesQueue.front().timerMax - messagesQueue.front().timer));
}
uiSprites.msgBoxSprite.setPosition(0, 590 - dy);
app->draw(uiSprites.msgBoxSprite);
std::stringstream ss;
ss << messagesQueue.front().message[0];
ss << ": ";
ss << messagesQueue.front().message[1];
ss << std::endl;
ss << messagesQueue.front().message[2];
write(ss.str(), 16, 10, 592 - dy, ALIGN_LEFT, sf::Color::White, app, 0,0);
}
}
void WitchBlastGame::saveDeathScreen()
{
std::stringstream ss;
ss << "rip_";
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
ss << (now->tm_year + 1900);
if (now->tm_mon < 9) ss << "0";
ss << (now->tm_mon + 1);
if (now->tm_mday < 9) ss << "0";
ss << now->tm_mday;
if (now->tm_hour <= 9) ss << "0";
ss << (now->tm_hour);
if (now->tm_min <= 9) ss << "0";
ss << (now->tm_min);
if (now->tm_sec <= 9) ss << "0";
ss << (now->tm_sec);
ss << ".png";
- scoreSaveFile = ss.str();
int width = 810, height = 300, border = 4;
int x = 80, y = 110;
sf::Image screenShot(app->capture());
sf::Image savedImage;
savedImage.create(width + border * 2, height + border * 2);
savedImage.copy(screenShot,0 , 0, sf::IntRect( x - border, y - border, width + border * 2, height + border * 2));
- savedImage.saveToFile(scoreSaveFile);
+ savedImage.saveToFile(ss.str());
+}
+
+void WitchBlastGame::saveScreen()
+{
+ std::stringstream ss;
+ ss << "screenshot_";
+ time_t t = time(0); // get time now
+ struct tm * now = localtime( & t );
+
+ ss << (now->tm_year + 1900);
+ if (now->tm_mon < 9) ss << "0";
+ ss << (now->tm_mon + 1);
+ if (now->tm_mday < 9) ss << "0";
+ ss << now->tm_mday;
+ if (now->tm_hour <= 9) ss << "0";
+ ss << (now->tm_hour);
+ if (now->tm_min <= 9) ss << "0";
+ ss << (now->tm_min);
+ if (now->tm_sec <= 9) ss << "0";
+ ss << (now->tm_sec);
+ ss << ".png";
+
+ sf::Image screenShot(app->capture());
+ screenShot.saveToFile(ss.str());
}
void WitchBlastGame::renderDeathScreen(float x, float y)
{
int xRect = 810;
sf::Sprite rectangle;
rectangle.setTexture(*ImageManager::getInstance().getImage(IMAGE_DEATH_CERTIFICATE));
rectangle.setPosition(x - 4, y - 4);
app->draw(rectangle);
std::stringstream ss;
ss << parameters.playerName << " - " << tools::getLabel("dc_certificate");
write(ss.str(), 18, x + xRect / 2, y + 5, ALIGN_CENTER, sf::Color::Black, app, 0, 0);
ss.str(std::string());
ss.clear();
ss << tools::getLabel("dc_killed_by") << " " << sourceToString(player->getLastHurtingSource(), player->getLastHurtingEnemy()) << "." << std::endl;
int minutes = (int)gameTime / 60;
if (minutes < 1) minutes = 1;
ss << tools::getLabel("dc_died_level") << " " << level << " " << tools::getLabel("dc_after") << " " << minutes << " " << tools::getLabel("dc_minutes") << "." << std::endl;
ss << tools::getLabel("dc_killed_monsters") << ": " << bodyCount << std::endl;
ss << tools::getLabel("dc_gold") << ": " << player->getGold() << std::endl;
ss << tools::getLabel("dc_challenges") << ": " << challengeLevel - 1 << std::endl;
write(ss.str(), 16, x + 112, y + 50, ALIGN_LEFT, sf::Color::Black, app, 0, 0);
// player
renderPlayer(x + 40, y + 48, player->getEquipment(), player->getShotType(), 1, 0);
// items
write(tools::getLabel("inventory"), 16, x + 14, y + 165, ALIGN_LEFT, sf::Color::Black, app, 0, 0);
int n = 0;
for (auto i: sortedEquipement)
{
if (i != EQUIP_BOSS_KEY && player->isEquiped(i))
{
sf::Sprite itemSprite;
itemSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ITEMS_EQUIP));
itemSprite.setPosition(x + 14 + n * 32, y + 183);
itemSprite.setTextureRect(sf::IntRect((i % 10) * 32, (i / 10) * 32, 32, 32));
app->draw(itemSprite);
n++;
}
}
ss.str("");
ss.clear();
ss << "Score: " << score;
write(ss.str(), 24, x + xRect / 2, y + 240, ALIGN_CENTER, sf::Color::Black, app, 0, 0);
}
bool compareScores(WitchBlastGame::StructScore s1, WitchBlastGame::StructScore s2)
{
return s1.score > s2.score;
}
void WitchBlastGame::calculateScore()
{
score = 0;
bodyCount = 0;
for (int enemyType = EnemyTypeBat; enemyType < EnemyTypeRockFalling; enemyType++)
{
bodyCount += killedEnemies[enemyType];
score += killedEnemies[enemyType] * getMonsterScore((enemyTypeEnum)enemyType);
}
score += getChallengeScore(challengeLevel);
score += getGoldScore(player->getGold());
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++)
{
if (player->isEquiped(i)) score += getItemScore((item_equip_enum)i);
lastScore.equip[i] = player->isEquiped(i);
}
// to save
lastScore.name = parameters.playerName;
lastScore.score = score;
lastScore.level = level;
lastScore.shotType = player->getShotType();
scores.push_back(lastScore);
std::sort (scores.begin(), scores.end(), compareScores);
saveHiScores();
}
void WitchBlastGame::switchToMenu()
{
gameState = gameStateMenu;
buildMenu(false);
if (!config.configFileExists())
{
menuState = MenuStateFirst;
menuFirst.index = 0;
menuKeyIndex = 0;
}
}
void WitchBlastGame::updateMenu()
{
SoundManager::getInstance().playSound(SOUND_NIGHT, false);
menuStuct* menu = NULL;
if (menuState == MenuStateMain)
menu = &menuMain;
else if (menuState == MenuStateConfig)
menu = &menuConfig;
else if (menuState == MenuStateFirst)
menu = &menuFirst;
EntityManager::getInstance().animate(deltaTime);
for (int i = 0; i < 2; i++)
{
introSprites[i]->setX(introSprites[i]->getX() - deltaTime * 35);
if (introSprites[i]->getX() < - SCREEN_WIDTH / 2) introSprites[i]->setX(introSprites[i]->getX() + 2 * SCREEN_WIDTH);
}
// Process events
sf::Event event;
while (app->pollEvent(event))
{
// Close window : exit
if (event.type == sf::Event::Closed)
{
saveGameData();
app->close();
}
if (event.type == sf::Event::Resized)
{
enableAA(true);
sf::View view = app->getDefaultView();
view = getLetterboxView( view, event.size.width, event.size.height );
app->setView(view);
}
if (event.type == sf::Event::TextEntered)
{
if (menuState == MenuStateChangeName)
{
if (event.text.unicode < 128)
{
char c = static_cast<char>(event.text.unicode);
if ( (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_')
parameters.playerName += static_cast<char>(event.text.unicode);
}
}
}
if (event.type == sf::Event::KeyPressed && menuState == MenuStateKeys)
{
bool alreadyUsed = false;
if (event.key.code == sf::Keyboard::Escape) alreadyUsed = true;
for (unsigned int i = 0; i < menuKeyIndex; i++)
if (input[i] == event.key.code) alreadyUsed = true;
// TODO more tests
if (!alreadyUsed)
{
input[menuKeyIndex] = event.key.code;
menuKeyIndex++;
if (menuKeyIndex == NumberKeys)
{
menuState = MenuStateConfig;
saveConfigurationToFile();
}
}
}
else if (event.type == sf::Event::KeyPressed)
{
if (menuState == MenuStateCredits)
{
if (event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::Return)
menuState = MenuStateMain;
}
else if (menuState == MenuStateAchievements)
{
if (event.key.code == sf::Keyboard::Escape)
menuState = MenuStateMain;
else if (event.key.code == sf::Keyboard::Return)
{
if (menuAchIndex / 8 >= ACHIEV_LINES) menuState = MenuStateMain;
}
else if (event.key.code == sf::Keyboard::Right || event.key.code == input[KeyRight])
{
if (menuAchIndex % 8 < 7) menuAchIndex++;
}
else if (event.key.code == sf::Keyboard::Left || event.key.code == input[KeyLeft])
{
if (menuAchIndex % 8 > 0) menuAchIndex--;
}
else if (event.key.code == sf::Keyboard::Down || event.key.code == input[KeyDown])
{
if (menuAchIndex / 8 < ACHIEV_LINES) menuAchIndex += 8;
}
else if (event.key.code == sf::Keyboard::Up || event.key.code == input[KeyUp])
{
if (menuAchIndex / 8 > 0) menuAchIndex -= 8;
}
}
else if (menuState == MenuStateHiScores)
{
if (parameters.playerName.size() > 0
&& (event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::Return))
{
menuState = MenuStateMain;
if (lastScore.level > 0)
{
lastScore.level = 0;
lastScore.score = 0;
playMusic(MusicIntro);
}
}
}
else if (menuState == MenuStateChangeName)
{
if (event.key.code == sf::Keyboard::Escape || event.key.code == sf::Keyboard::Return)
{
saveConfigurationToFile();
menuState = MenuStateMain;
}
else if (event.key.code == sf::Keyboard::BackSpace)
{
if (parameters.playerName.size() > 0)
parameters.playerName.erase(parameters.playerName.size() - 1);
}
}
else if (event.key.code == sf::Keyboard::Escape)
{
if (menuState == MenuStateConfig) menuState = MenuStateMain;
else
{
saveGameData();
app->close();
}
}
else if (event.key.code == input[KeyDown] || event.key.code == sf::Keyboard::Down)
{
menu->index++;
if (menu->index == menu->items.size()) menu->index = 0;
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (event.key.code == input[KeyUp] || event.key.code == sf::Keyboard::Up)
{
if (menu->index == 0) menu->index = menu->items.size() - 1;
else menu->index--;
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (event.key.code == input[KeyRight] || event.key.code == sf::Keyboard::Right)
{
if (menu->items[menu->index].id == MenuLanguage)
{
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
parameters.language++;
if (parameters.language >= NB_LANGUAGES) parameters.language = 0;
if (menuState == MenuStateConfig) saveConfigurationToFile();
tools::setLanguage(languageString[parameters.language]);
buildMenu(true);
}
else if (menu->items[menu->index].id == MenuVolumeSound)
{
parameters.soundVolume = (parameters.soundVolume / 10) * 10 + 10;
if (parameters.soundVolume > 100) parameters.soundVolume = 100;
saveConfigurationToFile();
SoundManager::getInstance().setVolume(parameters.soundVolume);
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (menu->items[menu->index].id == MenuVolumeMusic)
{
parameters.musicVolume = (parameters.musicVolume / 10) * 10 + 10;
if (parameters.musicVolume > 100) parameters.musicVolume = 100;
saveConfigurationToFile();
updateMusicVolume();
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
}
else if (event.key.code == input[KeyLeft] || event.key.code == sf::Keyboard::Left)
{
if (menu->items[menu->index].id == MenuLanguage)
{
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
parameters.language--;
if (parameters.language < 0) parameters.language = NB_LANGUAGES - 1;
if (menuState == MenuStateConfig) saveConfigurationToFile();
tools::setLanguage(languageString[parameters.language]);
buildMenu(true);
}
else if (menu->items[menu->index].id == MenuVolumeSound)
{
parameters.soundVolume = (parameters.soundVolume / 10) * 10 - 10;
if (parameters.soundVolume < 0) parameters.soundVolume = 0;
saveConfigurationToFile();
SoundManager::getInstance().setVolume(parameters.soundVolume);
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
else if (menu->items[menu->index].id == MenuVolumeMusic)
{
parameters.musicVolume = (parameters.musicVolume / 10) * 10 - 10;
if (parameters.musicVolume < 0) parameters.musicVolume = 0;
saveConfigurationToFile();
updateMusicVolume();
SoundManager::getInstance().playSound(SOUND_SHOT_SELECT);
}
}
else if (event.key.code == sf::Keyboard::Return)
{
switch (menu->items[menu->index].id)
{
case MenuStartNew:
startNewGame(false);
remove(SAVE_FILE.c_str());
break;
case MenuStartOld:
startNewGame(true);
break;
case MenuKeys:
menuState = MenuStateKeys;
menuKeyIndex = 0;
break;
case MenuCredits:
menuState = MenuStateCredits;
break;
case MenuHiScores:
menuState = MenuStateHiScores;
break;
case MenuAchievements:
menuState = MenuStateAchievements;
menuAchIndex = 0;
break;
case MenuPlayerName:
menuState = MenuStateChangeName;
break;
case MenuConfig:
menuState = MenuStateConfig;
break;
case MenuTutoReset:
for (int i = 0; i < NB_MESSAGES; i++) gameMessagesToSkip[i] = false;
SoundManager::getInstance().playSound(SOUND_SPELL_FREEZE);
saveGameData();
break;
case MenuConfigBack:
menuState = MenuStateMain;
break;
case MenuLanguage:
if (menuState == MenuStateFirst)
{
registerLanguage();
if (parameters.playerName.compare("") == 0 )
{
menuMain.index = 0;
menuState = MenuStateChangeName;
}
else
menuState = MenuStateMain;
}
break;
case MenuExit:
saveGameData();
app->close();
break;
case MenuVolumeSound:
case MenuVolumeMusic:
break;
case MenuContinue:
case MenuSaveAndQuit:
std::cout << "[ERROR] Bad Menu ID\n";
break;
}
}
}
}
}
void WitchBlastGame::renderMenu()
{
if (menuState == MenuStateCredits)
{
renderCredits();
return;
}
else if (menuState == MenuStateHiScores)
{
renderHiScores();
return;
}
else if (menuState == MenuStateAchievements)
{
renderAchievements();
return;
}
app->draw(introScreenSprite);
if (titleSprite.getPosition().y > 160) titleSprite.move(0, -8);
else if (titleSprite.getPosition().y < 160) titleSprite.setPosition(SCREEN_WIDTH / 2 - 15, 160);
app->draw(titleSprite);
EntityManager::getInstance().render(app);
menuStuct* menu = nullptr;
if (menuState == MenuStateMain || menuState == MenuStateChangeName)
menu = &menuMain;
else if (menuState == MenuStateConfig)
menu = &menuConfig;
else if (menuState == MenuStateFirst)
menu = &menuFirst;
int xAlign = 290;
int yTop = 320;
int yStep = 40;
if (menuState == MenuStateKeys)
{
// menu keys
if (config.configFileExists())
write(tools::getLabel("key_configuration"), 18, xAlign, 295, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1);
else
write(tools::getLabel("key_configuration_desc"), 18, xAlign, 295, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1);
for (unsigned int i = 0; i < NumberKeys; i++)
{
sf::Color itemColor;
if (menuKeyIndex == i) itemColor = sf::Color(255, 255, 255, 255);
else itemColor = sf::Color(180, 180, 180, 255);
std::ostringstream oss;
oss << tools::getLabel(inputKeyString[i]) << ": ";
if (menuKeyIndex == i) oss << tools::getLabel("key_configuration_insert");
else if (menuKeyIndex > i) oss << keyToString(input[i]);
write(oss.str(), 16, xAlign, 330 + i * 25, ALIGN_LEFT, itemColor, app, 1, 1);
}
}
else
{
// menu
for (unsigned int i = 0; i < menu->items.size(); i++)
{
sf::Color itemColor;
if (menu->index == i)
{
itemColor = sf::Color(255, 255, 255, 255);
sf::Sprite fairySprite;
fairySprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
fairySprite.setTextureRect(sf::IntRect( 48 * ((int)(20 *getAbsolutTime()) % 2), 0, 48, 48));
fairySprite.setPosition(xAlign - 60, yTop - 10 + i * yStep + 5 * cos( 6 * getAbsolutTime()));
app->draw(fairySprite);
}
else itemColor = sf::Color(120, 120, 120, 255);
std::string label = menu->items[i].label;
if (menu->items[i].id == MenuLanguage)
{
std::ostringstream oss;
oss << label << " : " << tools::getLabel(languageString[parameters.language]);
label = oss.str();
}
else if (menu->items[i].id == MenuPlayerName)
{
std::ostringstream oss;
oss << label << " : " << parameters.playerName;
if (menuState == MenuStateChangeName && (int)(getAbsolutTime() * 3) % 2 == 0) oss << "_";
label = oss.str();
}
else if (menu->items[i].id == MenuVolumeSound)
{
std::ostringstream oss;
oss << label << " : ";
if (parameters.soundVolume == 0) oss << "OFF";
else oss << parameters.soundVolume;
label = oss.str();
}
else if (menu->items[i].id == MenuVolumeMusic)
{
std::ostringstream oss;
oss << label << " : ";
if (parameters.musicVolume == 0) oss << "OFF";
else oss << parameters.musicVolume;
label = oss.str();
}
write(label, 21, xAlign, yTop + i * yStep, ALIGN_LEFT, itemColor, app, 1, 1);
}
write(menu->items[menu->index].description, 18, xAlign,
yTop + menu->items.size() * yStep + 8, ALIGN_LEFT, sf::Color(60, 80, 220), app, 0, 0);
// Keys
if (menuState == MenuStateFirst)
{
// displaying the standard key configuration
int xKeys = 270;
int yKeys = 380;
sf::Sprite keysSprite;
if (parameters.language == 1) // french
keysSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_KEYS_AZER));
else
keysSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_KEYS_QWER));
keysSprite.setPosition(xKeys, yKeys);
app->draw(keysSprite);
// legend
write(tools::getLabel("keys_move"), 16, xKeys + 190, yKeys + 10, ALIGN_LEFT, sf::Color::White, app, 1, 1);
write(tools::getLabel("keys_time"), 16, xKeys + 295, yKeys + 14, ALIGN_LEFT, sf::Color::White, app, 1, 1);
write(tools::getLabel("keys_fire"), 16, xKeys + 360, yKeys + 54, ALIGN_LEFT, sf::Color::White, app, 1, 1);
write(tools::getLabel("key_spell"), 16, xKeys + 148, yKeys + 184, ALIGN_CENTER, sf::Color::White, app, 1, 1);
// TODO key interact
std::ostringstream oss;
oss << tools::getLabel("keys_select_1") << std::endl << tools::getLabel("keys_select_2");
write(oss.str(), 16, xKeys + 4, yKeys + 100, ALIGN_LEFT, sf::Color::White, app, 1, 1);
}
}
std::ostringstream oss;
oss << APP_NAME << " v" << APP_VERSION << " - 2014 - " << " Seby (code), Pierre \"dejam0rt\" Baron (2D art)";
write(oss.str(), 17, 5, 680, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1);
}
void WitchBlastGame::renderAchievements()
{
app->draw(introScreenSprite);
if (titleSprite.getPosition().y > 160) titleSprite.move(0, -8);
else if (titleSprite.getPosition().y < 160) titleSprite.setPosition(SCREEN_WIDTH / 2 - 15, 180);
app->draw(titleSprite);
// achievements
write(tools::getLabel("menu_achievements"), 30, 485, 280, ALIGN_CENTER, sf::Color(255, 255, 255, 255), app, 1, 1);
int achWidth = 64, achHeight = 64, x0 = 180, y0 = 380, xStep = 16, yStep = 16, nbProLine = 8;
if (menuAchIndex / 8 < ACHIEV_LINES)
{
sf::RectangleShape rectangle(sf::Vector2f(achWidth, achHeight));
rectangle.setPosition(x0 + (menuAchIndex % nbProLine) * (achWidth + xStep), y0 + (menuAchIndex / nbProLine) * (achHeight + yStep));
rectangle.setOutlineThickness(3);
rectangle.setOutlineColor(sf::Color(50, 255, 50));
app->draw(rectangle);
}
sf::Sprite sprite;
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_ACHIEVEMENTS));
for (int k : sortedAchievements)
{
int i = sortedAchievements[k];
sprite.setPosition(x0 + (k % nbProLine) * (achWidth + xStep), y0 + (k / nbProLine) * (achHeight + yStep));
if (achievementState[i] == AchievementDone)
{
sprite.setTextureRect(sf::IntRect( ((i + 1) % 10) * achWidth, ((i + 1) / 10) * achHeight, achWidth, achHeight));
}
else
{
sprite.setTextureRect(sf::IntRect(0, 0, achWidth, achHeight));
}
app->draw(sprite);
}
if (menuAchIndex / 8 >= ACHIEV_LINES)
{
write(tools::getLabel("config_back"), 17, 485, 550, ALIGN_CENTER, sf::Color(255, 255, 255, 255), app, 1, 1);
}
else
{
write(tools::getLabel("config_back"), 17, 485, 550, ALIGN_CENTER, sf::Color(180, 180, 180, 255), app, 1, 1);
sf::Color fontColor = sf::Color::White;
std::stringstream oss;
int achIndex = sortedAchievements[menuAchIndex];
if (!achievementState[achIndex] == AchievementDone && (
achIndex == AchievementGiantSlime
|| achIndex == AchievementCyclops
|| achIndex == AchievementRatKing
|| achIndex == AchievementGiantSpider
|| achIndex == AchievementFrancky
|| achIndex == AchievementVampire)
)
oss << "???";
else
oss << tools::getLabel(achievements[achIndex].label);
oss << ": ";
if (achievementState[achIndex] == AchievementDone)
{
oss << tools::getLabel(achievements[achIndex].label + "_desc");
if (achievements[achIndex].unlockType == UnlockItem && achievements[achIndex].unlock > -1)
oss << "\nUNLOCK: " << tools::getLabel(items[achievements[achIndex].unlock].name);
else if (achievements[achIndex].unlockType == UnlockFunctionality && achievements[achIndex].unlock > -1)
oss << "\nUNLOCK: " << tools::getLabel(functionalityLabel[achievements[achIndex].unlock]);
}
else
{
if (isFunctionalityLocked(FunctionalityAllAchievements))
oss << "???";
else
oss << tools::getLabel(achievements[achIndex].label + "_desc");
fontColor = sf::Color(150, 150, 150);
}
write(oss.str(), 19, 100, 650, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 1, 1);
}
}
void WitchBlastGame::renderCredits()
{
app->draw(introScreenSprite);
if (titleSprite.getPosition().y > 160) titleSprite.move(0, -8);
else if (titleSprite.getPosition().y < 160) titleSprite.setPosition(SCREEN_WIDTH / 2 - 15, 180);
app->draw(titleSprite);
// credits
write(tools::getLabel("credits"), 30, 485, 275, ALIGN_CENTER, sf::Color(255, 255, 255, 255), app, 1, 1);
int yCursorInit = 365;
int yStep = 30;
int xLeft = 30;
int xRight = 470;
int xMarging = 20;
int yCursor = yCursorInit;
write("Code", 22, xLeft, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0,0);
yCursor += yStep;
int i = 0;
while (creditsCode[i] != "END")
{
write(creditsCode[i], 19, xLeft + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0,0);
yCursor += yStep;
i++;
}
yCursor += yStep;
write("2D Art", 22, xLeft, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0,0);
yCursor += yStep;
i = 0;
while (credits2D[i] != "END")
{
write(credits2D[i], 19, xLeft + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0,0);
yCursor += yStep;
i++;
}
yCursor += yStep;
write("Sound", 22, xLeft, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0,0);
yCursor += yStep;
i = 0;
while (creditsSound[i] != "END")
{
write(creditsSound[i], 19, xLeft + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0,0);
yCursor += yStep;
i++;
}
yCursor += yStep;
////// RIGHT
yCursor = yCursorInit - yStep;
write("Music", 22, xRight, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0,0);
yCursor += yStep;
i = 0;
while (creditsMusic[i] != "END")
{
write(creditsMusic[i], 19, xRight + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0,0);
yCursor += yStep;
i++;
}
yCursor += yStep;
write("Translation", 22, xRight, yCursor, ALIGN_LEFT, sf::Color(210, 210, 255, 255), app, 0,0);
yCursor += yStep;
i = 0;
while (creditsTranslate[i] != "END")
{
write(creditsTranslate[i], 19, xRight + xMarging, yCursor, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0,0);
yCursor += yStep;
i++;
}
yCursor += yStep;
}
void WitchBlastGame::renderHiScores()
{
sf::Sprite bgSprite;
bgSprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_INTRO));
app->draw(bgSprite);
// hi-scores-title
write(tools::getLabel("hi_scores"), 30, 485, 20, ALIGN_CENTER, sf::Color(255, 255, 255, 255), app, 1, 1);
int x0 = 25;
int x1 = 70;
int x2 = 125;
int x3 = 430;
int y0 = 130;
int yStep = 100;
int xRight = SCREEN_WIDTH / 2;
sf::RectangleShape line(sf::Vector2f(2, 600));
line.setPosition(SCREEN_WIDTH / 2, 80);
app->draw(line);
for (unsigned int i = 0; i < scores.size() && i < SCORES_MAX; i++)
{
int index = i < SCORES_MAX / 2 ? i : i - SCORES_MAX / 2;
sf::Color color = sf::Color( 220, 220, 220);
if (scores[i].score == lastScore.score && scores[i].level == lastScore.level && scores[i].name == lastScore.name)
{
int fade = 1 + cosf(getAbsolutTime() * 8) * 63;
color = sf::Color(255, 128 + fade, 255);
}
renderPlayer(x1 + (i / 5) * xRight, y0 + yStep * index, scores[i].equip, scores[i].shotType, 1, 0);
write(intToString(i + 1), 24, x0 + (i / 5) * xRight, y0 + 30 + yStep * index, ALIGN_CENTER, color, app, 1, 1);
std::stringstream ss;
ss << scores[i].name << " (" << scores[i].level << ")";
write(ss.str(), 17, x2 + (i / 5) * xRight, y0 + 30 + yStep * index, ALIGN_LEFT, color, app, 1, 1);
write(intToString(scores[i].score), 17, x3 + (i / 5) * xRight, y0 + 30 + yStep * index, ALIGN_RIGHT, color, app, 1, 1);
}
}
void WitchBlastGame::renderInGameMenu()
{
menuStuct* menu = &menuInGame;
int xAlign = 290;
int yAlign = 200;
{
// menu
for (unsigned int i = 0; i < menu->items.size(); i++)
{
sf::Color itemColor;
if (menu->index == i)
{
itemColor = sf::Color(255, 255, 255, 255);
sf::Sprite fairySprite;
fairySprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
fairySprite.setTextureRect(sf::IntRect( 48 * ((int)(8 *getAbsolutTime()) % 2), 0, 48, 48));
fairySprite.setPosition(xAlign - 60, yAlign + i * 90 + 5 * cos( 6 * getAbsolutTime()));
app->draw(fairySprite);
}
else itemColor = sf::Color(120, 120, 120, 255);
std::string label = menu->items[i].label;
write(label, 23, xAlign, yAlign + 10 + i * 90, ALIGN_LEFT, itemColor, app, 1, 1);
write(menu->items[i].description, 15, xAlign, yAlign + i * 90 + 50, ALIGN_LEFT, itemColor, app, 0, 0);
}
}
}
void WitchBlastGame::startGame()
{
lastTime = getAbsolutTime();
prepareIntro();
// Start game loop
while (app->isOpen())
{
deltaTime = getAbsolutTime() - lastTime;
if (deltaTime < 0.008f)
{
float sleepTime = 1.0f / 60.0f - deltaTime;
sf::sleep(sf::seconds(sleepTime));
deltaTime = getAbsolutTime() - lastTime;
}
lastTime = getAbsolutTime();
if (deltaTime > 0.05f) deltaTime = 0.05f;
switch (gameState)
{
case gameStateInit:
case gameStateKeyConfig:
case gameStateMenu:
updateMenu();
break;
case gameStateIntro:
updateIntro();
break;
case gameStatePlaying:
case gameStatePlayingPause:
case gameStatePlayingDisplayBoss:
updateRunningGame();
break;
}
onRender();
}
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);
if (currentMap->isDoor(i, 0)) currentMap->closeDoor(i, 0);
if (currentMap->isDoor(i, MAP_HEIGHT - 1)) currentMap->closeDoor(i, MAP_HEIGHT - 1);
}
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);
if (currentMap->isDoor(0, i)) currentMap->closeDoor(0, i);
if (currentMap->isDoor(MAP_WIDTH - 1, i)) currentMap->closeDoor(MAP_WIDTH - 1, i);
}
roomClosed = true;
}
}
void WitchBlastGame::openDoors()
{
int i;
for(i = 0; i < MAP_WIDTH; i++)
{
if (currentMap->isDoor(i, 0)) currentMap->openDoor(i, 0);
if (currentMap->isDoor(i, MAP_HEIGHT - 1)) currentMap->openDoor(i, MAP_HEIGHT - 1);
}
for(i = 0; i < MAP_HEIGHT; i++)
{
if (currentMap->isDoor(0, i)) currentMap->openDoor(0, i);
if (currentMap->isDoor(MAP_WIDTH - 1, i)) currentMap->openDoor(MAP_WIDTH - 1, i);
}
roomClosed = false;
SoundManager::getInstance().playSound(SOUND_DOOR_OPENING);
if (currentMap->hasNeighbourUp() == 2 && !bossRoomOpened)
currentMap->closeDoor(MAP_WIDTH/2, 0);
else
doorEntity[0]->openDoor();
if (currentMap->hasNeighbourLeft() == 2 && !bossRoomOpened)
currentMap->closeDoor(0, MAP_HEIGHT / 2);
else
doorEntity[1]->openDoor();
if (currentMap->hasNeighbourDown() == 2 && !bossRoomOpened)
currentMap->closeDoor(MAP_WIDTH / 2, MAP_HEIGHT - 1);
else
doorEntity[2]->openDoor();
if (currentMap->hasNeighbourRight() == 2 && !bossRoomOpened)
currentMap->closeDoor(MAP_WIDTH - 1, MAP_HEIGHT / 2);
else
doorEntity[3]->openDoor();
}
EnemyEntity* WitchBlastGame::getBoss()
{
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() == ENTITY_ENEMY_BOSS) return static_cast<EnemyEntity*> (e);
}
return NULL;
}
int WitchBlastGame::getEnemyCount()
{
int n=0;
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() >= ENTITY_ENEMY && e->getType() <= ENTITY_ENEMY_MAX_COUNT) n++;
}
return n;
}
int WitchBlastGame::getUndeadCount()
{
int n=0;
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() >= ENTITY_ENEMY && e->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
EnemyEntity* enemy = dynamic_cast<EnemyEntity*>(e);
if (enemy->canCollide() && (enemy->getEnemyType() == EnemyTypeZombie || enemy->getEnemyType() == EnemyTypeZombieDark
|| enemy->getEnemyType() == EnemyTypeGhost || enemy->getEnemyType() == EnemyTypeVampire || enemy->getEnemyType() == EnemyTypeBat_invocated) )
n++;
}
}
return n;
}
void WitchBlastGame::killArtefactDescription()
{
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() == ENTITY_ARTIFACT_DESCRIPTION)
{
e->setDying(true);
}
}
}
void WitchBlastGame::animateEffects()
{
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() == ENTITY_EFFECT)
e->animate(deltaTime);
}
}
void WitchBlastGame::destroyUndead(int damage)
{
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() >= ENTITY_ENEMY && e->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
EnemyEntity* enemy = dynamic_cast<EnemyEntity*>(e);
if (enemy->canCollide() && (enemy->getEnemyType() == EnemyTypeZombie || enemy->getEnemyType() == EnemyTypeZombieDark
|| enemy->getEnemyType() == EnemyTypeGhost || enemy->getEnemyType() == EnemyTypeVampire || enemy->getEnemyType() == EnemyTypeBat_invocated) )
{
enemy->hurt(BaseCreatureEntity::getHurtParams(damage, ShotTypeStandard, 0, false, SourceTypeMelee, EnemyTypeNone, false));
SpriteEntity* spriteCone = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_LIGHT_CONE),
enemy->getX(), enemy->getZ() - 290);
spriteCone->setZ(1000.0f);
spriteCone->setFading(true);
spriteCone->setAge(-1.2f);
spriteCone->setLifetime(2.4f);
spriteCone->setRenderAdd();
}
}
}
}
int WitchBlastGame::getItemsCount()
{
int n=0;
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() == ENTITY_ITEM) n++;
}
return n;
}
Vector2D WitchBlastGame::getNearestEnemy(float x, float y)
{
Vector2D target(-100.0f, -100.0f);
float distanceMin = -1.0f;
EntityManager::EntityList* entityList =EntityManager::getInstance().getList();
EntityManager::EntityList::iterator it;
for (it = entityList->begin (); it != entityList->end ();)
{
GameEntity *e = *it;
it++;
if (e->getType() >= ENTITY_ENEMY && e->getType() <= ENTITY_ENEMY_MAX_COUNT)
{
// enemy
EnemyEntity* enemy = dynamic_cast<EnemyEntity*>(e);
if (enemy->canCollide())
{
float d2 = (x - enemy->getX()) * (x - enemy->getX()) + (y - enemy->getY()) * (y - enemy->getY());
if (target.x < -1.0f || d2 < distanceMin)
{
distanceMin = d2;
target.x = enemy->getX();
target.y = enemy->getY();
}
}
}
}
return target;
}
void WitchBlastGame::checkDoor(int doorId, roomTypeEnum roomCurrent, roomTypeEnum roomNeighbour)
{
if (roomNeighbour == roomTypeNULL)
{
doorEntity[doorId]->setVisible(false);
return;
}
doorEntity[doorId]->setVisible(true);
doorEntity[doorId]->setDoorType(DoorStandard);
if (roomNeighbour == roomTypeBoss || roomCurrent == roomTypeBoss)
doorEntity[doorId]->setDoorType(DoorBoss);
if (roomNeighbour == roomTypeChallenge || roomCurrent == roomTypeChallenge)
doorEntity[doorId]->setDoorType(DoorChallenge);
if (roomNeighbour == roomTypeBoss && !bossRoomOpened)
{
doorEntity[doorId]->setOpen(false);
switch (doorId)
{
case 0:
currentMap->closeDoor(MAP_WIDTH/2, 0);
break;
case 1:
currentMap->closeDoor(0, MAP_HEIGHT / 2);
break;
case 2:
currentMap->closeDoor(MAP_WIDTH/2, MAP_HEIGHT - 1);
break;
case 3:
currentMap->closeDoor(MAP_WIDTH - 1, MAP_HEIGHT / 2);
break;
}
}
else
doorEntity[doorId]->setOpen(true);
}
void WitchBlastGame::refreshMap()
{
// clean the sprites from old map
EntityManager::getInstance().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
dungeonEntity->refreshMap();
player->setMap(currentMap, TILE_WIDTH, TILE_HEIGHT, 0, 0);
refreshMinimap();
if(generateMap)
this->generateMap();
else
{
if (currentMap->getRoomType() == roomTypeMerchant)
{
new PnjEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2 - 1) * TILE_HEIGHT,
0);
}
}
// check doors
checkDoor(0, currentMap->getRoomType(), currentMap->getNeighbourUp());
checkDoor(1, currentMap->getRoomType(), currentMap->getNeighbourLeft());
checkDoor(2, currentMap->getRoomType(), currentMap->getNeighbourDown());
checkDoor(3, currentMap->getRoomType(), currentMap->getNeighbourRight());
// keystones
if (currentMap->getNeighbourUp() || currentMap->getRoomType() == roomTypeExit)
{
SpriteEntity* keystoneEntity = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_TILES),
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
TILE_HEIGHT / 2, 192, 64, 1);
keystoneEntity->setZ(1000);
keystoneEntity->setFrame(24);
keystoneEntity->setType(ENTITY_EFFECT);
}
if (currentMap->getNeighbourDown())
{
SpriteEntity* keystoneEntity = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_TILES),
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
MAP_HEIGHT * TILE_WIDTH - TILE_HEIGHT / 2, 192, 64, 1);
keystoneEntity->setZ(1000);
keystoneEntity->setAngle(180);
keystoneEntity->setFrame(24);
keystoneEntity->setType(ENTITY_EFFECT);
}
if (currentMap->getNeighbourLeft())
{
SpriteEntity* keystoneEntity = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_TILES),
TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2, 192, 64, 1);
keystoneEntity->setZ(1000);
keystoneEntity->setAngle(270);
keystoneEntity->setFrame(24);
keystoneEntity->setType(ENTITY_EFFECT);
}
if (currentMap->getNeighbourRight())
{
SpriteEntity* keystoneEntity = new SpriteEntity(ImageManager::getInstance().getImage(IMAGE_TILES),
MAP_WIDTH * TILE_WIDTH - TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2, 192, 64, 1);
keystoneEntity->setZ(1000);
keystoneEntity->setAngle(90);
keystoneEntity->setFrame(24);
keystoneEntity->setType(ENTITY_EFFECT);
}
// pet slime
if (player->isEquiped(EQUIP_PET_SLIME) && currentMap->getRoomType() != roomTypeTemple) new SlimePetEntity();
}
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) == roomTypeChallenge
|| currentFloor->getRoom(i, j) == roomTypeBonus
|| currentFloor->getRoom(i, j) == roomTypeKey
|| currentFloor->getRoom(i, j) == roomTypeBoss
|| currentFloor->getRoom(i, j) == roomTypeStandard)
{
if ( currentFloor->getMap(i, j)->containsHealth())
miniMap->setTile(i, j, 5);
else
miniMap->setTile(i, j, roomTypeStandard);
}
else
{
if (currentFloor->getRoom(i, j) == roomTypeMerchant)
miniMap->setTile(i, j, 3);
else if (currentFloor->getRoom(i, j) == roomTypeTemple)
miniMap->setTile(i, j, 7);
else
miniMap->setTile(i, j, currentFloor->getRoom(i, j));
}
}
else if (n > 0 && currentFloor->getMap(i, j)->isKnown())
{
switch (currentFloor->getRoom(i, j))
{
case roomTypeBoss:
miniMap->setTile(i, j, 12);
proceedEvent(EventFindBossDoor);
break;
case roomTypeChallenge:
miniMap->setTile(i, j, 15);
proceedEvent(EventFindBossDoor);
break;
case roomTypeMerchant:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 13 : 11 );
break;
case roomTypeKey:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 14 : 11 );
break;
case roomTypeExit:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 16 : 11 );
break;
case roomTypeTemple:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 17 : 11 );
break;
case roomTypeBonus:
miniMap->setTile(i, j,
game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP) ? 2 : 11 );
break;
case roomTypeStandard:
case roomTypeStarting:
miniMap->setTile(i, j, 11);
break;
case roomTypeNULL:
miniMap->setTile(i, j, 0);
break;
}
}
else
miniMap->setTile(i, j, 0);
}
miniMap->setTile(floorX, floorY, 10);
int xMap = 760 + (6 - floorX) * 19;
if (xMap < 710) xMap = 710;
else if (xMap > 795) xMap = 795;
int yMap = 620 + (3 - floorY) * 15;
if (yMap < 596) yMap = 596;
else if (yMap > 640) yMap = 640;
miniMapEntity->setX(xMap);
miniMapEntity->setY(yMap);
}
void WitchBlastGame::checkEntering()
{
if (!currentMap->isCleared())
{
player->setEntering();
SoundManager::getInstance().playSound(SOUND_DOOR_CLOSING);
for (int i=0; i<4; i++)
doorEntity[i]->closeDoor();
}
}
void WitchBlastGame::saveMapItems()
{
currentMap->cleanMapObjects();
// blood
std::vector <displayEntityStruct> blood = dungeonEntity->getBlood();
for (auto particle: blood)
currentMap->addSprite(ENTITY_BLOOD, particle.frame, particle.x, particle.y, particle.scale);
// corpses
std::vector <displayEntityStruct> corpses = dungeonEntity->getCorpses();
for (auto particle: corpses)
currentMap->addSprite(ENTITY_CORPSE, particle.frame, particle.x, particle.y, particle.scale);
EntityManager::EntityList* entityList = EntityManager::getInstance().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 && !itemEntity->getDying())
{
currentMap->addItem(itemEntity->getItemType(), itemEntity->getX(), itemEntity->getY(), itemEntity->getMerchandise());
} // endif
else if (chestEntity != NULL && !chestEntity->getDying())
{
currentMap->addChest(chestEntity->getChestType(), chestEntity->getOpened(), chestEntity->getX(), chestEntity->getY());
} // endif
} // end for
}
void WitchBlastGame::moveToOtherMap(int direction)
{
// stairs to next level
if (direction == 8 && currentMap->getRoomType() == roomTypeExit)
{
if (player->getPlayerStatus() != PlayerEntity::playerStatusGoingNext)
{
player->setLeavingLevel();
xGame[xGameTypeFade].active = true;
xGame[xGameTypeFade].param = X_GAME_FADE_OUT;
xGame[xGameTypeFade].timer = 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((MAP_WIDTH * TILE_WIDTH), player->getY());
player->move(4);
break;
case (6):
floorX++;
player->moveTo(0, player->getY());
player->move(6);
break;
case (8):
floorY--;
player->moveTo(player->getX(), MAP_HEIGHT * TILE_HEIGHT);
player->move(8);
break;
case (2):
floorY++;
player->moveTo(player->getX(), 0);
break;
}
refreshMap();
checkEntering();
currentMap->restoreMapObjects();
saveInFight.x = player->getX();
saveInFight.y = player->getY();
saveInFight.direction = direction;
saveMapItems();
if (!currentMap->isCleared())
{
saveGame();
}
}
}
void WitchBlastGame::onRender()
{
// clear the view
app->clear(sf::Color::Black);
switch (gameState)
{
case gameStateInit:
case gameStateKeyConfig:
case gameStateMenu:
renderMenu();
break;
case gameStatePlaying:
case gameStatePlayingPause:
case gameStatePlayingDisplayBoss:
renderRunningGame();
break;
case gameStateIntro:
renderIntro();
break;
}
app->display();
}
void WitchBlastGame::renderHudShots(sf::RenderTarget* app)
{
int xHud = 277;
int yHud = 655;
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);
uiSprites.shotsSprite.setPosition(xHud + 55 * index, yHud);
if (index == player->getShotIndex())
{
uiSprites.shotsSprite.setTextureRect(sf::IntRect(0, 0, 48, 48));
app->draw(uiSprites.shotsSprite);
}
uiSprites.shotsSprite.setTextureRect(sf::IntRect(48 * ( 1 + type_shot), 0, 48, 48));
app->draw(uiSprites.shotsSprite);
// level
if (i > 0)
{
std::ostringstream oss;
oss << "lvl " << player->getShotLevel(i) + 1;
write(oss.str(), 10, xHud + 55 * index + 10, yHud + 48, ALIGN_LEFT, sf::Color(255, 255, 255, 255), app, 0, 0);
}
index++;
}
}
}
void WitchBlastGame::generateBlood(float x, float y, BaseCreatureEntity::enumBloodColor bloodColor)
{
dungeonEntity->generateBlood(x, y, bloodColor);
// double blood if the "Blood Snake" object is equipped
if (player->isEquiped(EQUIP_BLOOD_SNAKE)) dungeonEntity->generateBlood(x, y, bloodColor);
}
void WitchBlastGame::addCorpse(float x, float y, int frame)
{
dungeonEntity->addCorpse(x, y, frame);
}
void WitchBlastGame::showArtefactDescription(enumItemType itemType)
{
killArtefactDescription();
new ArtefactDescriptionEntity(itemType);
}
void WitchBlastGame::generateMap()
{
saveInFight.monsters.clear();
if (currentMap->getRoomType() == roomTypeStandard)
generateStandardMap();
else if (currentMap->getRoomType() == roomTypeBonus)
{
currentMap->setCleared(true);
Vector2D v = currentMap->generateBonusRoom();
int bonusType = getRandomEquipItem(false, false);
if (items[FirstEquipItem + bonusType].familiar > FamiliarNone)
{
new ChestEntity(v.x, v.y, ChestFairy + items[FirstEquipItem + bonusType].familiar, false);
}
else
{
new ItemEntity( (enumItemType)(FirstEquipItem + bonusType), v.x ,v.y);
}
}
else if (currentMap->getRoomType() == roomTypeKey)
{
currentMap->generateKeyRoom();
initMonsterArray();
int x0 = MAP_WIDTH / 2;
int y0 = MAP_HEIGHT / 2;
monsterArray[x0][y0] = true;
if (level == 1)
{
findPlaceMonsters(EnemyTypeRat, 2);
findPlaceMonsters(EnemyTypeBat, 2);
}
else if (level < 6)
{
findPlaceMonsters(EnemyTypeRat, 5);
findPlaceMonsters(EnemyTypeBat, 5);
for (int i = 2; i < level; i++)
{
if (rand()%2 == 0)findPlaceMonsters(EnemyTypeImpBlue, 1);
else findPlaceMonsters(EnemyTypeImpRed, 1);
}
}
else
{
findPlaceMonsters(EnemyTypeZombie, 5);
findPlaceMonsters(EnemyTypeBat, 5);
for (int i = 5; i < level; i++)
{
if (rand()%2 == 0)findPlaceMonsters(EnemyTypeImpBlue, 1);
else findPlaceMonsters(EnemyTypeImpRed, 1);
}
}
}
else if (currentMap->getRoomType() == roomTypeMerchant)
{
currentMap->generateMerchantRoom();
ItemEntity* item1 = new ItemEntity(
ItemHealth,
(MAP_WIDTH / 2 - 1) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item1->setMerchandise(true);
ItemEntity* item3 = new ItemEntity(
ItemHealthSmall,
(MAP_WIDTH / 2 + 1) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item3->setMerchandise(true);
int bonusType = getRandomEquipItem(true, true);
ItemEntity* item2 = new ItemEntity(
(enumItemType)(FirstEquipItem + bonusType),
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item2->setMerchandise(true);
// level item ?
if (rand() % 3 == 0)
{
int r = rand() % 4;
int item4Type = -1;
switch (r)
{
case 0:
if (!game().getPlayer()->isEquiped(EQUIP_FLOOR_MAP)) item4Type = ItemFloorMap;
break;
case 1:
if (!game().getPlayer()->isEquiped(EQUIP_ALCOHOL)) item4Type = ItemAlcohol;
break;
case 2:
if (!game().getPlayer()->isEquiped(EQUIP_LUCK)) item4Type = ItemLuck;
break;
default:
if (!game().getPlayer()->isEquiped(EQUIP_FAIRY_POWDER) && player->getFairieNumber() > 0) item4Type = ItemFairyPowder;
break;
}
if (item4Type > -1)
{
ItemEntity* item4 = new ItemEntity(
(enumItemType)(item4Type),
(MAP_WIDTH / 2 + 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + 5);
item4->setMerchandise(true);
}
}
new PnjEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2 - 1) * TILE_HEIGHT,
0);
currentMap->setCleared(true);
proceedEvent(EventFindShop);
}
else if (currentMap->getRoomType() == roomTypeChallenge)
{
currentMap->generateRoomWithoutHoles(0);
if (challengeLevel == 1)
{
addMonster(EnemyTypeBubble,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
else
{
addMonster(challengeLevel >= 3 ? EnemyTypeBubbleIce : EnemyTypeBubble,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 - 80,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
addMonster(challengeLevel >= 4 ? EnemyTypeBubbleGreater : EnemyTypeBubble,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 + 80,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
}
playMusic(MusicChallenge);
}
else if (currentMap->getRoomType() == roomTypeBoss)
{
currentMap->generateRoomWithoutHoles(0);
if (level == 1)
{
findPlaceMonsters(EnemyTypeRat, 2);
addMonster(EnemyTypeButcher,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoButcher);
}
else if (level == 2)
{
addMonster(EnemyTypeSlimeBoss,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoGiantSlime);
}
else if (level == 3)
{
addMonster(EnemyTypeCyclops,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoCyclops);
}
else if (level == 4)
{
addMonster(EnemyTypeRatKing,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoWererat);
}
else if (level == 5)
{
addMonster(EnemyTypeSpiderGiant,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoGiantSpiderBefore);
}
else if (level == 6)
{
addMonster(EnemyTypeFrancky,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoFranky);
}
else if (level == 7)
{
addMonster(EnemyTypeVampire,
(MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
testAndAddMessageToQueue(MsgInfoVampire);
}
else if (level == 8)
{
// TODO
GiantSpiderEntity* b1 = new GiantSpiderEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 - 100,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b1->setLabelDy(10);
FranckyEntity* b2 = new FranckyEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b2->setLabelDy(-530);
KingRatEntity* b3 = new KingRatEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 + 100,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b3->setLabelDy(-20);
}
else // level > 6
{
GiantSpiderEntity* b1 = new GiantSpiderEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 - 100,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b1->setLabelDy(10);
GiantSlimeEntity* b2 = new GiantSlimeEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b2->setLabelDy(-510);
KingRatEntity* b3 = new KingRatEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2 + 100,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b3->setLabelDy(-20);
CyclopsEntity* b4 = new CyclopsEntity((MAP_WIDTH / 2) * TILE_WIDTH + TILE_WIDTH / 2,
(MAP_HEIGHT / 2) * TILE_HEIGHT + TILE_HEIGHT / 2);
b4->setLabelDy(-540);
findPlaceMonsters(EnemyTypeCauldron, 2);
findPlaceMonsters(EnemyTypeImpBlue, 4);
}
playMusic(MusicBoss);
// boss screen
if (parameters.displayBossPortrait)
{
gameState = gameStatePlayingDisplayBoss;
bossDisplayTimer = 0.0f;
bossDisplayState = 0;
dungeonEntity->animate(0.0f);
}
}
else if (currentMap->getRoomType() == roomTypeStarting)
{
currentMap->generateRoomWithoutHoles(0);
currentMap->setCleared(true);
}
else if (currentMap->getRoomType() == roomTypeExit)
{
currentMap->generateExitRoom();
currentMap->setCleared(true);
new ChestEntity((TILE_WIDTH * MAP_WIDTH * 0.5f),
(TILE_HEIGHT * MAP_HEIGHT * 0.5f),
ChestExit, false);
}
else if (currentMap->getRoomType() == roomTypeTemple)
{
currentMap->generateTempleRoom();
currentMap->setCleared(true);
proceedEvent(EventFindTemple);
}
else // "normal" room
currentMap->randomize(currentMap->getRoomType());
}
void WitchBlastGame::write(std::string str, int size, float x, float y, int align, sf::Color color, sf::RenderTarget* app, int xShadow = 0, int yShadow = 0)
{
myText.setString(str);
myText.setString(sf::String::fromUtf8(str.begin(), str.end()));
myText.setCharacterSize(size);
float xFont = x;
if (align == ALIGN_CENTER)
xFont = x - myText.getLocalBounds().width / 2;
else if (align == ALIGN_RIGHT)
xFont = x - myText.getLocalBounds().width;
if (xShadow != 0 && yShadow != 0)
{
myText.setPosition(xFont + xShadow, y + yShadow);
myText.setColor(sf::Color(0, 0, 0, 255));
app->draw(myText);
}
myText.setPosition(xFont, y);
myText.setColor(color);
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(enemyTypeEnum monsterType, float xm, float ym)
{
StructMonster monster;
monster.id = monsterType;
monster.x = xm;
monster.y = ym;
saveInFight.monsters.push_back(monster);
switch (monsterType)
{
case EnemyTypeRat:
new RatEntity(xm, ym - 2, RatEntity::RatTypeNormal, false);
proceedEvent(EventMeetRatsOrBats);
break;
case EnemyTypeRatGreen:
new GreenRatEntity(xm, ym - 2);
proceedEvent(EventMeetRatsOrBats);
break;
case EnemyTypeRatBlack:
new BlackRatEntity(xm, ym - 5, BlackRatEntity::RatBlackTypeNormal);
break;
case EnemyTypeRatHelmet:
new RatEntity(xm, ym - 2, RatEntity::RatTypeHelmet, false);
break;
case EnemyTypeRatBlackHelmet:
new BlackRatEntity(xm, ym - 5, BlackRatEntity::RatBlackTypeHelmet);
break;
case EnemyTypeBat:
new BatEntity(xm, ym, BatStandard, false);
proceedEvent(EventMeetRatsOrBats);
break;
case EnemyTypeBatSkeleton:
new BatEntity(xm, ym, BatSkeleton, false);
break;
case EnemyTypeSnake:
new SnakeEntity(xm, ym, SnakeEntity::SnakeTypeNormal, false);
proceedEvent(EventMeetSnakes);
break;
case EnemyTypeSnakeBlood:
new SnakeEntity(xm, ym, SnakeEntity::SnakeTypeBlood, false);
proceedEvent(EventMeetSnakes);
break;
case EnemyTypeEvilFlower:
new EvilFlowerEntity(xm, ym - 2, FlowerTypeStandard);
break;
case EnemyTypeEvilFlowerIce:
new EvilFlowerEntity(xm, ym - 2, FlowerTypeIce);
break;
case EnemyTypeEvilFlowerFire:
new EvilFlowerEntity(xm, ym - 2, FlowerTypeFire);
break;
case EnemyTypeSlime:
new SlimeEntity(xm, ym, SlimeTypeStandard, false);
break;
case EnemyTypeImpRed:
new ImpEntity(xm, ym, ImpEntity::ImpTypeRed);
break;
case EnemyTypeImpBlue:
new ImpEntity(xm, ym, ImpEntity::ImpTypeBlue);
break;
case EnemyTypeSlimeRed:
new SlimeEntity(xm, ym, SlimeTypeRed, false);
break;
case EnemyTypeSlimeBlue:
new SlimeEntity(xm, ym, SlimeTypeBlue, false);
break;
case EnemyTypeSlimeViolet:
new SlimeEntity(xm, ym, SlimeTypeViolet, false);
break;
case EnemyTypePumpkin:
new PumpkinEntity(xm, ym, false);
break;
case EnemyTypeWitch:
new WitchEntity(xm, ym, WitchEntity::WitchTypeNormal);
proceedEvent(EventMeetWitches);
break;
case EnemyTypeWitchRed:
new WitchEntity(xm, ym, WitchEntity::WitchTypeRed);
proceedEvent(EventMeetWitches);
break;
case EnemyTypeCauldron:
new CauldronEntity(xm, ym, CauldronTypeStandard);
break;
case EnemyTypeCauldronElemental:
new CauldronEntity(xm, ym, CauldronTypeElemental);
break;
case EnemyTypeSpiderEgg:
new SpiderEggEntity(xm, ym, false);
break;
case EnemyTypeSpiderLittle:
new LittleSpiderEntity(xm, ym, false);
break;
case EnemyTypeGhost:
new GhostEntity(xm, ym);
break;
case EnemyTypeZombie:
new ZombieEntity(xm, ym, false);
break;
case EnemyTypeZombieDark:
new ZombieDarkEntity(xm, ym);
break;
case EnemyTypeBogeyman:
new BogeymanEntity(xm, ym);
break;
case EnemyTypeSpiderEgg_invocated:
new SpiderEggEntity(xm, ym, true);
break;
case EnemyTypeSpiderLittle_invocated:
new LittleSpiderEntity(xm, ym, true);
break;
case EnemyTypeBubble:
new BubbleEntity(xm, ym, BubbleStandard, 0);
break;
case EnemyTypeBubbleIce:
new BubbleEntity(xm, ym, BubbleIce, 0);
break;
case EnemyTypeBubbleGreater:
new BubbleEntity(xm, ym, BubbleTriple, 0);
break;
case EnemyTypeSlimeLarge:
new LargeSlimeEntity(xm, ym, SlimeTypeStandard);
break;
case EnemyTypeSlimeBlueLarge:
new LargeSlimeEntity(xm, ym, SlimeTypeBlue);
break;
case EnemyTypeSlimeRedLarge:
new LargeSlimeEntity(xm, ym, SlimeTypeRed);
break;
case EnemyTypeSlimeVioletLarge:
new LargeSlimeEntity(xm, ym, SlimeTypeViolet);
break;
case EnemyTypeButcher:
new ButcherEntity(xm, ym);
break;
case EnemyTypeSlimeBoss:
new GiantSlimeEntity(xm, ym);
break;
case EnemyTypeCyclops:
new CyclopsEntity(xm, ym);
break;
case EnemyTypeRatKing:
new KingRatEntity(xm, ym);
break;
case EnemyTypeSpiderGiant:
new GiantSpiderEntity(xm, ym);
break;
case EnemyTypeFrancky:
new FranckyEntity(xm, ym);
break;
case EnemyTypeVampire:
new VampireEntity(xm, ym);
break;
default:
std::cout << "[WARNING] Enemy (" << monsterType << ") not handled in switch.\n";
}
}
void WitchBlastGame::findPlaceMonsters(enemyTypeEnum monsterType, int amount)
{
// find a suitable place
bool isMonsterFlying = monsterType == EnemyTypeBat
|| monsterType == EnemyTypeImpBlue
|| monsterType == EnemyTypeImpRed;
bool isMonsterLarge = monsterType == EnemyTypeSlimeLarge
|| monsterType == EnemyTypeSlimeBlueLarge
|| monsterType == EnemyTypeSlimeRedLarge
|| monsterType == EnemyTypeSlimeVioletLarge;
bool bOk;
int xm, ym;
float xMonster, yMonster;
for (int index = 0; index < amount; index++)
{
bOk = false;
int watchdog = 200;
while (!bOk && watchdog > 0)
{
bOk = true;
watchdog--;
if (isMonsterLarge)
{
xm = 2 +rand() % (MAP_WIDTH - 5);
ym = 2 +rand() % (MAP_HEIGHT - 5);
}
else
{
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 && isMonsterFlying && !currentMap->isFlyable(xm, ym))
{
bOk = false;
}
if (bOk)
{
xMonster = xm * TILE_WIDTH + TILE_WIDTH * 0.5f;
yMonster = 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();
saveInFight.monsters.clear();
generateStandardRoom(level);
}
item_equip_enum WitchBlastGame::getRandomEquipItem(bool toSale = false, bool noFairy = 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 && isItemLocked((enumItemType)eq)) itemOk = false;
if (itemOk && items[eq].requirement >= FirstEquipItem
&& !player->isEquiped(items[eq].requirement - FirstEquipItem)) itemOk = false;
if (itemOk && toSale && level == 1 && items[eq].price > 25) itemOk = false;
if (itemOk && toSale && level == 2 && items[eq].price > 35) itemOk = false;
if (itemOk && (items[eq].specialShot != ShotTypeStandard && items[eq].level < 3) && player->canGetNewShot(false))
itemOk = false;
if (itemOk && (items[eq].specialShot != ShotTypeStandard && items[eq].level >= 3) && player->canGetNewShot(true))
itemOk = false;
if (itemOk && i == EQUIP_BOOK_DUAL && (player->isEquiped(EQUIP_BOOK_DUAL_QUICK) || player->isEquiped(EQUIP_RAPID_SHOT)))
itemOk = false;
if (itemOk && i == EQUIP_BOOK_DUAL_QUICK && (player->isEquiped(EQUIP_BOOK_DUAL) || player->isEquiped(EQUIP_RAPID_SHOT)))
itemOk = false;
if (itemOk && i == EQUIP_RAPID_SHOT && (player->isEquiped(EQUIP_BOOK_DUAL_QUICK) || player->isEquiped(EQUIP_BOOK_DUAL)))
itemOk = false;
if (itemOk && noFairy && items[eq].familiar != FamiliarNone) itemOk = false;
if (itemOk)
{
int n = 0;
switch (items[eq].rarity)
{
case RarityCommon:
n = 8;
break;
case RarityUncommon:
n = 4;
break;
case RarityRare:
n = 2;
break;
case RarityVeryRare:
n = 1;
break;
}
//if (itemOk && eq == ItemPetSlime) n = 15000;
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;
}
enumItemType WitchBlastGame::getItemSpell()
{
bool ok = false;
enumItemType item = ItemMagicianHat;
while (!ok)
{
enumCastSpell n = (enumCastSpell)(rand() % SPELL_MAX);
if (player->getActiveSpell().spell != n) ok = true;
if (ok)
{
switch (n)
{
case SpellNone:
case SpellTeleport:
item = ItemSpellTeleport;
break;
case SpellSlimeExplode:
item = ItemSpellSlimeExplode;
break;
case SpellFireball:
item = ItemSpellFireball;
break;
case SpellFreeze:
item = ItemSpellFreeze;
break;
case SpellEarthquake:
item = ItemSpellEarthquake;
break;
case SpellProtection:
item = ItemSpellProtection;
break;
case SpellWeb:
item = ItemSpellWeb;
break;
case SpellFlower:
item = ItemSpellFlower;
break;
case SpellFairy:
item = ItemSpellFairy;
break;
}
ok = !isItemLocked(item);
}
}
return item;
}
void WitchBlastGame::generateChallengeBonus(float x, float y)
{
// loot
if (player->getActiveSpell().spell == SpellNone || rand() % 2 == 0)
{
enumItemType spell1 = getItemSpell();
ItemEntity* spellItem = new ItemEntity(spell1, x, y);
spellItem->setVelocity(Vector2D(100.0f + rand()% 250));
if (spellItem->getVelocity().y < 0.0f) spellItem->setVelocity(Vector2D(spellItem->getVelocity().x, -spellItem->getVelocity().y));
spellItem->setViscosity(0.96f);
if (!isFunctionalityLocked(FunctionalityDoubleSpellDrop))
{
enumItemType spell2 = spell1;
while (spell2 == spell1) spell2 = getItemSpell();
ItemEntity* spellItem2 = new ItemEntity(spell2, x, y);
spellItem2->setVelocity(Vector2D(100.0f + rand()% 250));
if (spellItem2->getVelocity().y < 0.0f) spellItem2->setVelocity(Vector2D(spellItem2->getVelocity().x, -spellItem2->getVelocity().y));
spellItem2->setViscosity(0.96f);
}
ItemEntity* healthItem1 = new ItemEntity(ItemHealthVerySmall, x, y);
healthItem1->setVelocity(Vector2D(100.0f + rand()% 250));
healthItem1->setViscosity(0.96f);
ItemEntity* healthItem2 = new ItemEntity(ItemHealthVerySmallPoison, x, y);
healthItem2->setVelocity(Vector2D(100.0f + rand()% 250));
healthItem2->setViscosity(0.96f);
}
else
{
ItemEntity* newItem;
if (challengeLevel < 4 || rand() % (player->isEquiped(EQUIP_LUCK) ? 5 : 8) > 0)
newItem = new ItemEntity(ItemBonusHealth, x, y);
else
newItem = new ItemEntity((enumItemType)(FirstEquipItem + getRandomEquipItem()), x, y);
if (newItem->getVelocity().y < 0.0f) newItem->setVelocity(Vector2D(newItem->getVelocity().x, -newItem->getVelocity().y));
newItem->setVelocity(Vector2D(100.0f + rand()% 250));
newItem->setViscosity(0.96f);
int gold = 2 + rand() % (player->isEquiped(EQUIP_LUCK) ? 9 : 14);
for (int i = 0; i < gold; i++)
{
ItemEntity* newItem = new ItemEntity(ItemCopperCoin, x, y);
newItem->setVelocity(Vector2D(90.0f + rand()% 150));
newItem->setViscosity(0.96f);
}
}
}
void WitchBlastGame::checkInteraction()
{
interaction.active = false;
if (player->getPlayerStatus() != PlayerEntity::playerStatusPlaying) return;
if (currentMap->getRoomType() == roomTypeTemple)
{
int divinity = currentMap->getDivinity(player->getX() / TILE_WIDTH, player->getZ() / TILE_HEIGHT);
if (divinity > -1)
{
interaction.active = true;
interaction.type = InteractionTypeTemple;
interaction.id = divinity;
std::stringstream ss;
ss << "[" << keyToString(input[KeyInteract]) << "] - ";
if (player->getDivinity().divinity == divinity)
{
ss << tools::getLabel("interact_donate");
if (player->getGold() < 10)
{
ss << " ";
ss << tools::getLabel("interact_donate_fail");
}
}
else
{
ss << tools::getLabel("interact_worship");
ss << " ";
ss << tools::getLabel(divinityLabel[divinity] + "_0");
}
interaction.label = ss.str();
}
}
else if (player->getItemToBuy() != NULL)
{
interaction.active = true;
interaction.type = InteractionTypeMerchandise;
interaction.id = player->getItemToBuy()->getItemType();
std::stringstream ss;
ss << tools::getLabel(items[interaction.id].name);
ss << ": ";
ss << tools::getLabel(items[interaction.id].description);
if (player->getItemToBuy()->canBePickedUp())
{
ss << std::endl;
ss << "[" << keyToString(input[KeyInteract]) << "] - ";
ss << tools::getLabel("interact_shop");
}
interaction.label = ss.str();
}
}
void WitchBlastGame::verifyDoorUnlocking()
{
int collidingDirection = (player->getCollidingDirection());
if (collidingDirection > 0 && currentMap->isCleared() && !bossRoomOpened && player->isEquiped(EQUIP_BOSS_KEY))
{
int xt = (player->getX()) / TILE_WIDTH;
int yt = (player->getY()) / TILE_HEIGHT;
if (yt <= 1 && xt >= MAP_WIDTH / 2 - 1 && xt <= MAP_WIDTH / 2 + 1 && currentMap->hasNeighbourUp() == 2)
{
doorEntity[0]->openDoor();
currentMap->openDoor(MAP_WIDTH / 2, 0);
SoundManager::getInstance().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->openDoor(MAP_WIDTH / 2, MAP_HEIGHT - 1);
SoundManager::getInstance().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->openDoor(0, MAP_HEIGHT / 2);
SoundManager::getInstance().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->openDoor(MAP_WIDTH - 1, MAP_HEIGHT / 2);
SoundManager::getInstance().playSound(SOUND_DOOR_OPENING);
player->useBossKey();
bossRoomOpened = true;
}
}
}
void WitchBlastGame::playMusic(musicEnum musicChoice)
{
music.stop();
if (parameters.musicVolume <= 0) return;
music.setLoop(true);
music.setVolume(parameters.musicVolume);
bool ok = false;
switch (musicChoice)
{
case MusicDungeon:
if (rand() % 2 == 0)
{
ok = music.openFromFile("media/sound/game_Fantasy_Theme_Of_Elvarim.ogg");
}
else
{
ok = music.openFromFile("media/sound/game_Marching_United.ogg");
}
break;
case MusicEnding:
ok = music.openFromFile("media/sound/ending_Music_Is_His_Only_Friend.ogg");
music.setVolume(parameters.musicVolume * 50 / 100);
break;
case MusicBoss:
if (rand() % 2 == 0)
{
ok = music.openFromFile("media/sound/boss_The_Spider_Machine.ogg");
}
else
{
ok = music.openFromFile("media/sound/boss_Pub_Stomp_Deluxe.ogg");
}
break;
case MusicChallenge:
ok = music.openFromFile("media/sound/challenge_Under_Siege.ogg");
break;
case MusicIntro:
ok = music.openFromFile("media/sound/menu_Our_Ship_To_Candletown.ogg");
music.setVolume(parameters.musicVolume * 60 / 100);
break;
}
if (ok)
music.play();
}
void WitchBlastGame::updateMusicVolume()
{
if (music.getStatus() == sf::Music::Playing)
{
if (parameters.musicVolume == 0)
music.stop();
else
music.setVolume(parameters.musicVolume * 60 / 100);
}
else
{
if (parameters.musicVolume > 0)
{
bool ok = music.openFromFile("media/sound/menu_Our_Ship_To_Candletown.ogg");
music.setVolume(parameters.musicVolume * 60 / 100);
if (ok) music.play();
}
}
}
void WitchBlastGame::makeShake(float duration)
{
xGame[xGameTypeShake].active = true;
xGame[xGameTypeShake].timer = duration;
}
void WitchBlastGame::makeColorEffect(int color, float duration)
{
xGame[xGameTypeFadeColor].active = true;
xGame[xGameTypeFadeColor].param = color;
xGame[xGameTypeFadeColor].timer = duration;
xGame[xGameTypeFadeColor].duration = duration;
}
void WitchBlastGame::saveGame()
{
if (player->getPlayerStatus() == PlayerEntity::playerStatusAcquire)
player->acquireItemAfterStance();
std::ofstream file(SAVE_FILE.c_str(), std::ios::out | std::ios::trunc);
int i, j, k, l;
if (file)
{
// version (for compatibility check)
file << SAVE_VERSION << std::endl;
time_t t = time(0); // get time now
struct tm * now = localtime( & t );
file << (now->tm_year + 1900) << '-';
if (now->tm_mon < 9) file << "0";
file << (now->tm_mon + 1) << '-';
if (now->tm_mday < 9) file << "0";
file << now->tm_mday
<< std::endl;
if (now->tm_hour <= 9) file << "0";
file << (now->tm_hour) << ':';
if (now->tm_min <= 9) file << "0";
file << (now->tm_min) << std::endl;
// floor
file << level << " " << challengeLevel << std::endl;
// game age
file << (int)gameTime << std::endl;
// player equip
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++) file << player->isEquiped(i) << " ";
file << std::endl;
file << player->getShotType() << 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;
}
// kill stats
for (i = 0; i < NB_ENEMY; i++) file << killedEnemies[i] << " ";
file << std::endl;
// maps
if (currentMap->isCleared())
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++)
{
int tile = currentFloor->getMap(i, j)->getTile(k, l);
- if (tile == MAP_DOOR && !(k > 0 && k < MAP_WIDTH - 1 && l > 0 && l < MAP_HEIGHT - 1)) tile = 0;
file << tile << " ";
- // ADD other maps
file << currentFloor->getMap(i, j)->getObjectTile(k, l) << " ";
file << currentFloor->getMap(i, j)->getShadowTile(k, l) << " ";
file << currentFloor->getMap(i, j)->getLogicalTile(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;
}
// random sprite
file << currentFloor->getMap(i, j)->getRandomTileElement().type
<< " " <<currentFloor->getMap(i, j)->getRandomTileElement().x
<< " " << currentFloor->getMap(i, j)->getRandomTileElement().y
<< " " << currentFloor->getMap(i, j)->getRandomTileElement().rotation << std::endl;
}
}
}
file << std::endl;
}
// game
file << floorX << " " << floorY << std::endl;
file << bossRoomOpened << std::endl;
// boss door !
// fight ?
if (currentMap->isCleared())
{
file << false << std::endl;
}
else
{
file << true << std::endl;
file << saveInFight.x << " " << saveInFight.y << " " << saveInFight.direction << std::endl;
file << saveInFight.monsters.size();
for (auto monster : saveInFight.monsters)
file << " " << monster.id << " " << monster.x << " " << monster.y;
file << std::endl;
}
// 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) << std::endl;
file << player->getActiveSpell().spell << std::endl;
// divinity
file << player->getDivinity().divinity << " " << player->getDivinity().piety << " "
<< player->getDivinity().level << " " << player->getDivinity().interventions << std::endl;
// events
for (i = 0; i < NB_EVENTS; i++) file << worldEvent[i] << " ";
file.close();
}
else
{
std::cerr << "[ERROR] Saving the game..." << std::endl;
}
}
bool WitchBlastGame::loadGame()
{
saveInFight.monsters.clear();
std::ifstream file(SAVE_FILE.c_str(), std::ios::in);
if (file)
{
int i, j, k, n;
// version
std::string v;
file >> v;
if (v != SAVE_VERSION)
{
file.close();
remove(SAVE_FILE.c_str());
return false;
}
// date an time
file >> v;
file >> v;
// floor
file >> level;
file >> challengeLevel;
file >> gameTime;
for (i = 0; i < NUMBER_EQUIP_ITEMS; i++)
{
bool eq;
file >> eq;
}
file >> n;
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, (roomTypeEnum)n);
}
}
// kill stats
for (int i = 0; i < NB_ENEMY; i++) file >> killedEnemies[i];
// 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);
file >> n;
iMap->setObjectTile(i, j, n);
file >> n;
iMap->setShadowTile(i, j, n);
file >> n;
iMap->setLogicalTile(i, j, (logicalMapStateEnum)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);
}
// random sprite
DungeonMap::RandomTileElement rd;
file >> rd.type;
file >> rd.x;
file >> rd.y;
file >> rd.rotation;
iMap->setRandomTileElement(rd);
}
}
// game
file >> floorX >> floorY;
currentMap = currentFloor->getMap(floorX, floorY);
file >> bossRoomOpened;
// fight ?
file >> saveInFight.isFight;
if (saveInFight.isFight)
{
currentMap->setCleared(false);
file >> saveInFight.x;
file >> saveInFight.y;
file >> saveInFight.direction;
file >> n;
for (i = 0; i < n; i++)
{
StructMonster monster;
file >> j;
monster.id = (enemyTypeEnum)j;
file >> monster.x;
file >> monster.y;
saveInFight.monsters.push_back(monster);
}
}
// player
int hp, hpMax, gold;
file >> hp >> hpMax >> gold;
player = new PlayerEntity((TILE_WIDTH * MAP_WIDTH * 0.5f),
(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;
if (saveInFight.isFight)
{
x = saveInFight.x;
y = saveInFight.y;
player->move(saveInFight.direction);
player->setEntering();
}
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 >> n;
player->setActiveSpell((enumCastSpell)n, saveInFight.isFight);
// divinity
{
int divinityId, piety, divLevel, interventions;
file >> divinityId;
file >> piety;
file >> divLevel;
file >> interventions;
player->loadDivinity(divinityId, piety, divLevel, interventions);
}
// events
for (i = 0; i < NB_EVENTS; i++)
{
bool event;
file >> event;
worldEvent[i] = event;
}
player->computePlayer();
file.close();
remove(SAVE_FILE.c_str());
}
else
{
return false;
}
return true;
}
WitchBlastGame::saveHeaderStruct WitchBlastGame::loadGameHeader()
{
saveHeaderStruct saveHeader;
saveHeader.ok = true;
std::ifstream file(SAVE_FILE.c_str(), std::ios::in);
if (file)
{
// version
std::string v;
file >> v;
if (v != SAVE_VERSION)
{
file.close();
remove(SAVE_FILE.c_str());
saveHeader.ok = false;
}
else
{
// date an time
file >> saveHeader.date;
file >> saveHeader.time;
// floor
file >> saveHeader.level;
int challengeLevel;
file >> challengeLevel;
file >> saveHeader.gameTime;
for (int i = 0; i < NUMBER_EQUIP_ITEMS; i++)
file >> equipToDisplay[i];
file >> saveHeader.shotType;
}
}
else
{
saveHeader.ok = false;
}
return saveHeader;
}
void WitchBlastGame::saveGameData()
{
// TODO
std::ofstream file(SAVE_DATA_FILE.c_str(), std::ios::out | std::ios::trunc);
if (file)
{
// version (for compatibility check)
file << SAVE_VERSION << std::endl;
int i;
// tuto
for (i = 0; i < NB_MESSAGES; i++)
{
messageStruct msg = getMessage((EnumMessages)i);
if (msg.messageType == MessageTypeTutorial)
{
file << gameMessagesToSkip[i] << " ";
}
else file << "0 ";
}
file << std::endl;
// achievements
for (i = 0; i < NB_ACHIEVEMENTS; i++)
{
if (achievementState[i] == AchievementDone) file << "1 ";
else file << "0 ";
}
file << std::endl;
// monsters
for (i = 0; i < NB_ENEMY; i++)
{
file << globalData.killedMonster[i] << " ";
}
file << std::endl;
file.close();
}
else
{
std::cout << "[ERROR] Impossible to open save data file.\n";
}
}
void WitchBlastGame::loadGameData()
{
std::ifstream file(SAVE_DATA_FILE.c_str(), std::ios::in);
int i;
if (file)
{
// version
std::string v;
file >> v;
if (v != SAVE_VERSION)
{
file.close();
remove(SAVE_DATA_FILE.c_str());
return;
}
// tuto
for (i = 0; i < NB_MESSAGES; i++)
{
file >> gameMessagesToSkip[i];
}
}
// Achievements
for (i = 0; i < NB_ACHIEVEMENTS; i++)
{
int n;
file >> n;
if (n == 1) achievementState[i] = AchievementDone;
else achievementState[i] = AchievementUndone;
}
// Monsters
for (i = 0; i < NB_ENEMY; i++)
file >> globalData.killedMonster[i];
}
void WitchBlastGame::addKey(int logicInput, std::string key)
{
int iKey = config.findInt(key);
if (iKey >= 0)
{
sf::Keyboard::Key k = (sf::Keyboard::Key)iKey;
input[logicInput] = k;
}
}
void WitchBlastGame::saveConfigurationToFile()
{
std::map<std::string, std::string> newMap;
// parameters
newMap["language"] = intToString(parameters.language);
newMap["player_name"] = parameters.playerName;
// audio volume
newMap["volume_sound"] = intToString(parameters.soundVolume);
newMap["volume_music"] = intToString(parameters.musicVolume);
newMap["zoom_enabled"] = parameters.zoom ? "1" : "0";
newMap["vsync_enabled"] = parameters.vsync ? "1" : "0";
newMap["blood_spreading"] = parameters.bloodSpread ? "1" : "0";
newMap["fullscreen"] = parameters.fullscreen ? "1" : "0";
newMap["display_boss_portrait"] = parameters.displayBossPortrait ? "1" : "0";
// Keys
newMap["keyboard_move_up"] = intToString(input[KeyUp]);
newMap["keyboard_move_down"] = intToString(input[KeyDown]);
newMap["keyboard_move_left"] = intToString(input[KeyLeft]);
newMap["keyboard_move_right"] = intToString(input[KeyRight]);
newMap["keyboard_fire_up"] = intToString(input[KeyFireUp]);
newMap["keyboard_fire_down"] = intToString(input[KeyFireDown]);
newMap["keyboard_fire_left"] = intToString(input[KeyFireLeft]);
newMap["keyboard_fire_right"] = intToString(input[KeyFireRight]);
newMap["keyboard_spell"] = intToString(input[KeySpell]);
newMap["keyboard_interact"] = intToString(input[KeyInteract]);
newMap["keyboard_fire"] = intToString(input[KeyFire]);
newMap["keyboard_time_control"] = intToString(input[KeyTimeControl]);
newMap["keyboard_fire_select"] = intToString(input[KeyFireSelect]);
config.saveToFile(CONFIG_FILE, newMap);
}
void WitchBlastGame::configureFromFile()
{
// default
parameters.language = 0; // english
parameters.zoom = true;
parameters.vsync = true;
parameters.bloodSpread = true;
parameters.fullscreen = false;
parameters.musicVolume = 60;
parameters.soundVolume = 100;
parameters.playerName = "";
parameters.displayBossPortrait = false;
input[KeyUp] = sf::Keyboard::W;
input[KeyDown] = sf::Keyboard::S;
input[KeyLeft] = sf::Keyboard::A;
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::RControl;
input[KeySpell] = sf::Keyboard::Space;
input[KeyInteract] = sf::Keyboard::E;
input[KeyFireSelect] = sf::Keyboard::Tab;
input[KeyTimeControl] = sf::Keyboard::RShift;
// 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(KeySpell, "keyboard_spell");
addKey(KeyTimeControl, "keyboard_time_control");
addKey(KeyFireSelect, "keyboard_fire_select");
int i = config.findInt("language");
if (i >= 0) parameters.language = i;
i = config.findInt("volume_sound");
if (i >= 0) parameters.soundVolume = i;
i = config.findInt("volume_music");
if (i >= 0) parameters.musicVolume = i;
i = config.findInt("vsync_enabled");
if (i >= 0) parameters.vsync = i;
i = config.findInt("zoom_enabled");
if (i >= 0) parameters.zoom = i;
i = config.findInt("blood_spreading");
if (i >= 0) parameters.bloodSpread = i;
i = config.findInt("fullscreen");
if (i >= 0) parameters.fullscreen = i;
i = config.findInt("display_boss_portrait");
if (i >= 0) parameters.displayBossPortrait = i;
std::string playerName = config.findString("player_name");
if (playerName.size() > 0) parameters.playerName = playerName;
tools::setLanguage(languageString[parameters.language]);
}
parameterStruct WitchBlastGame::getParameters()
{
return parameters;
}
void WitchBlastGame::buildMenu(bool rebuild)
{
menuMain.items.clear();
menuConfig.items.clear();
menuFirst.items.clear();
if (!rebuild)
{
menuState = MenuStateMain;
menuMain.age = 0.0f;
menuConfig.age = 0.0f;
menuConfig.index = 0;
}
saveHeader = loadGameHeader();
menuItemStuct itemName;
itemName.label = tools::getLabel("player_name");
itemName.description = tools::getLabel("player_name_desc");
itemName.id = MenuPlayerName;
menuMain.items.push_back(itemName);
if (saveHeader.ok)
{
menuItemStuct itemStart;
itemStart.label = tools::getLabel("start_new_game");
itemStart.description = tools::getLabel("start_desc");
itemStart.id = MenuStartNew;
menuMain.items.push_back(itemStart);
menuItemStuct itemLoad;
itemStart.label = tools::getLabel("restore");
std::ostringstream oss;
oss << saveHeader.date << " " << tools::getLabel("at") << " " << saveHeader.time << " - " << tools::getLabel("level") << " " << saveHeader.level;
itemStart.description = oss.str();
itemStart.id = MenuStartOld;
menuMain.items.push_back(itemStart);
if (!rebuild) menuMain.index = 2;
}
else
{
menuItemStuct itemStart;
itemStart.label = tools::getLabel("start_new_game");
itemStart.description = tools::getLabel("begin_journey");
itemStart.id = MenuStartNew;
menuMain.items.push_back(itemStart);
if (!rebuild) menuMain.index = 1;
}
if (parameters.playerName.compare("") == 0 && menuState == MenuStateMain)
{
menuMain.index = 0;
menuState = MenuStateChangeName;
}
menuItemStuct itemConfig;
itemConfig.label = tools::getLabel("configure_game");
itemConfig.description = tools::getLabel("configure_game_desc");
itemConfig.id = MenuConfig;
menuMain.items.push_back(itemConfig);
if (!isFunctionalityLocked(FunctionalityAchievementsScreen))
{
menuItemStuct itemAchiev;
std::ostringstream oss;
oss << tools::getLabel("menu_achievements");
oss << " (" << getAchievementsPercents() << "%)";
itemAchiev.label = oss.str();
itemAchiev.description = tools::getLabel("menu_achievements_desc");
itemAchiev.id = MenuAchievements;
menuMain.items.push_back(itemAchiev);
}
if (scores.size() > 0)
{
menuItemStuct itemHiScores;
itemHiScores.label = tools::getLabel("hi_scores");
itemHiScores.description = tools::getLabel("hi_scores_desc");
itemHiScores.id = MenuHiScores;
menuMain.items.push_back(itemHiScores);
}
menuItemStuct itemCredits;
itemCredits.label = tools::getLabel("credits");
itemCredits.description = tools::getLabel("credits_desc");
itemCredits.id = MenuCredits;
menuMain.items.push_back(itemCredits);
menuItemStuct itemExit;
itemExit.label = tools::getLabel("exit_game");
itemExit.description = tools::getLabel("return_to_desktop");
itemExit.id = MenuExit;
menuMain.items.push_back(itemExit);
// configuration
menuItemStuct itemKeys;
itemKeys.label = tools::getLabel("config_keys");
itemKeys.description = tools::getLabel("redef_input");
itemKeys.id = MenuKeys;
menuConfig.items.push_back(itemKeys);
menuItemStuct itemLanguage;
itemLanguage.label = tools::getLabel("config_lang");
itemLanguage.description = tools::getLabel("config_lang_desc");
itemLanguage.id = MenuLanguage;
menuConfig.items.push_back(itemLanguage);
menuItemStuct itemVolumeSound;
itemVolumeSound.label = tools::getLabel("volume_sound");
itemVolumeSound.description = tools::getLabel("volume_sound_desc");
itemVolumeSound.id = MenuVolumeSound;
menuConfig.items.push_back(itemVolumeSound);
menuItemStuct itemVolumeMusic;
itemVolumeMusic.label = tools::getLabel("volume_music");
itemVolumeMusic.description = tools::getLabel("volume_sound_desc");
itemVolumeMusic.id = MenuVolumeMusic;
menuConfig.items.push_back(itemVolumeMusic);
menuItemStuct itemTutoReset;
itemTutoReset.label = tools::getLabel("tuto_reset");
itemTutoReset.description = tools::getLabel("tuto_reset_desc");
itemTutoReset.id = MenuTutoReset;
menuConfig.items.push_back(itemTutoReset);
menuItemStuct itemConfigBack;
itemConfigBack.label = tools::getLabel("config_back");
itemConfigBack.description = tools::getLabel("config_back_desc");
itemConfigBack.id = MenuConfigBack;
menuConfig.items.push_back(itemConfigBack);
//first time screen
menuFirst.items.push_back(itemLanguage);
}
void WitchBlastGame::buildInGameMenu()
{
menuInGame.items.clear();
menuItemStuct itemContinue;
itemContinue.label = tools::getLabel("menu_continue");
itemContinue.description = tools::getLabel("menu_continue_desc");
itemContinue.id = MenuContinue;
menuInGame.items.push_back(itemContinue);
menuItemStuct itemSaveQuit;
itemSaveQuit.label = tools::getLabel("menu_save_quit");
itemSaveQuit.description = tools::getLabel("menu_save_quit_desc");
itemSaveQuit.id = MenuSaveAndQuit;
menuInGame.items.push_back(itemSaveQuit);
menuItemStuct itemQuit;
itemQuit.label = tools::getLabel("menu_quit");
itemQuit.description = tools::getLabel("menu_quit_desc");
itemQuit.id = MenuExit;
menuInGame.items.push_back(itemQuit);
menuInGame.index = 0;
}
void WitchBlastGame::resetKilledEnemies()
{
for (int i = 0; i < NB_ENEMY; i++) killedEnemies[i] = 0;
}
void WitchBlastGame::addKilledEnemy(enemyTypeEnum enemyType, enumShotType hurtingType)
{
if(!player->isDead())
{
if (enemyType == NB_ENEMY)
std::cout << "[ERROR] No enemy type";
else
{
killedEnemies[enemyType]++;
globalData.killedMonster[enemyType]++;
player->offerMonster(enemyType, hurtingType);
// achievements
if (enemyType == EnemyTypeButcher) registerAchievement(AchievementButcher);
else if (enemyType == EnemyTypeSlimeBoss) registerAchievement(AchievementGiantSlime);
else if (enemyType == EnemyTypeCyclops) registerAchievement(AchievementCyclops);
else if (enemyType == EnemyTypeRatKing) registerAchievement(AchievementRatKing);
else if (enemyType == EnemyTypeSpiderGiant) registerAchievement(AchievementGiantSpider);
else if (enemyType == EnemyTypeFranckyHead) registerAchievement(AchievementFrancky);
else if (enemyType == EnemyTypeVampire) registerAchievement(AchievementVampire);
else if ((enemyType == EnemyTypeRat || enemyType == EnemyTypeRatHelmet || enemyType == EnemyTypeRat_invocated
|| enemyType == EnemyTypeRatBlack || enemyType == EnemyTypeRatBlackHelmet))
{
if (globalData.killedMonster[EnemyTypeRat] + globalData.killedMonster[EnemyTypeRatHelmet] + globalData.killedMonster[EnemyTypeRat_invocated]
+ globalData.killedMonster[EnemyTypeRatBlack] + globalData.killedMonster[EnemyTypeRatBlackHelmet] >= 250)
registerAchievement(AchievementRats);
}
else if (enemyType == EnemyTypeWitch || enemyType == EnemyTypeWitchRed)
{
if (globalData.killedMonster[EnemyTypeWitch] + globalData.killedMonster[EnemyTypeWitchRed] >= 50)
registerAchievement(AchievementWitches);
}
else if (enemyType == EnemyTypeSpiderEgg || enemyType == EnemyTypeSpiderEgg_invocated)
{
if (globalData.killedMonster[EnemyTypeSpiderEgg] + globalData.killedMonster[EnemyTypeSpiderEgg_invocated] >= 100)
registerAchievement(AchievementEggs);
}
}
}
}
void WitchBlastGame::registerLanguage()
{
// default keys
if (parameters.language == 1)
{
// french keyboard
input[KeyUp] = sf::Keyboard::Z;
input[KeyLeft] = sf::Keyboard::Q;
}
else
{
// QWERT / QWERTZ keyboard
input[KeyUp] = sf::Keyboard::W;
input[KeyLeft] = sf::Keyboard::A;
}
input[KeyDown] = sf::Keyboard::S;
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::RControl;
input[KeyFireSelect] = sf::Keyboard::Tab;
input[KeyTimeControl] = sf::Keyboard::RShift;
input[KeySpell] = sf::Keyboard::Space;
saveConfigurationToFile();
}
int WitchBlastGame::getAchievementsPercents()
{
int n = 0;
for (int i = 0; i < NB_ACHIEVEMENTS; i++)
if (achievementState[i] == AchievementDone) n++;
return (n * 100) / NB_ACHIEVEMENTS;
}
void WitchBlastGame::testAndAddMessageToQueue(EnumMessages type)
{
if (gameMessagesToSkip[type] == false)
{
if (messagesQueue.empty()) SoundManager::getInstance().playSound(SOUND_MESSAGE);
messageStruct msg = getMessage(type);
if (type == MsgInfoDivGift || type == MsgInfoDivIntervention)
{
std::stringstream ss;
ss << tools::getLabel(divinityLabel[player->getDivinity().divinity] + "_0");
ss << " ";
if (type == MsgInfoDivGift)
ss << tools::getLabel("divinity_gift_1");
else // (type == MsgInfoDivIntervention)
ss << tools::getLabel("divinity_intervention_1");
msg.message[1] = ss.str();
msg.icon = 2 + player->getDivinity().divinity;
}
messagesQueue.push(msg);
if (msg.messageType == MessageTypeTutorial)
{
gameMessagesToSkip[type] = true;
saveGameData();
}
}
}
void WitchBlastGame::addDivLevelMessageToQueue(std::string label)
{
if (label.compare("") == 0) return;
if (messagesQueue.empty()) SoundManager::getInstance().playSound(SOUND_MESSAGE);
messageStruct msg = getMessage(MsgInfoDivLevel);
std::stringstream ss;
ss << tools::getLabel(divinityLabel[player->getDivinity().divinity] + "_0");
ss << " ";
ss << tools::getLabel(label);
msg.message[1] = ss.str();
msg.icon = 2 + player->getDivinity().divinity;
messagesQueue.push(msg);
}
void WitchBlastGame::initEvents()
{
for (int i = 0; i < NB_EVENTS; i++)
worldEvent[i] = false;
}
void WitchBlastGame::proceedEvent(EnumWorldEvents event)
{
// achievements
if (event == EventGetCoin)
{
if (achievementState[Achievement100] == AchievementUndone && player->getGold() > 100)
registerAchievement(Achievement100);
}
else if (event == EventPietyMax)
{
if (achievementState[AchievementPietyMax] == AchievementUndone) registerAchievement(AchievementPietyMax);
}
else if (event == Event4Hits)
{
if (achievementState[Achievement4Hits] == AchievementUndone) registerAchievement(Achievement4Hits);
}
// message ?
if (worldEvent[event]) return;
worldEvent[event] = true;
testAndAddMessageToQueue(eventToMessage[event]);
}
void WitchBlastGame::renderPlayer(float x, float y,
bool equip[NUMBER_EQUIP_ITEMS], int shotType,
int frame, int spriteDy)
{
bool isMirroring = false;
sf::Sprite sprite;
if (equip[EQUIP_FAIRY_FIRE])
{
sprite.setPosition(x - 35, y - 25);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 144, 48, 60));
app->draw(sprite);
}
if (equip[EQUIP_FAIRY_ICE])
{
sprite.setPosition(x - 5, y - 25);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 216, 48, 60));
app->draw(sprite);
}
if (equip[EQUIP_FAIRY])
{
sprite.setPosition(x - 40, y);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 0, 48, 60));
app->draw(sprite);
}
if (equip[EQUIP_FAIRY_TARGET])
{
sprite.setPosition(x - 10, y);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 72, 48, 60));
app->draw(sprite);
}
if (equip[EQUIP_FAIRY_POISON])
{
sprite.setPosition(x + 20, y);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_FAIRY));
sprite.setTextureRect(sf::IntRect( 0, 288, 48, 60));
app->draw(sprite);
}
// slime
if (equip[EQUIP_PET_SLIME])
{
sprite.setPosition(x - 20, y + 24);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_SLIME));
sprite.setTextureRect(sf::IntRect( 64, 256, 64, 64));
app->draw(sprite);
}
sprite.setPosition(x, y);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
int width = 64;
int height = 96;
// body
if (isMirroring)
sprite.setTextureRect(sf::IntRect( frame * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( frame * width, spriteDy * height, width, height));
app->draw(sprite);
// boots
if (equip[EQUIP_BOOTS_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (21 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (21 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_LEATHER_BOOTS])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (9 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (9 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_ROBE_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (12 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (12 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_MAGICIAN_ROBE])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (12 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (12 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_GLOVES_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (24 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (24 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_DISPLACEMENT_GLOVES])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (21 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (21 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_CRITICAL_ADVANCED])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (24 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (24 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
else if (equip[EQUIP_CRITICAL])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (18 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (18 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
if (equip[EQUIP_RAGE_AMULET])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (18 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (18 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_LEATHER_BELT])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (15 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (15 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
// hat
if (equip[EQUIP_HAT_ADVANCED])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (9 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (9 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
else if (equip[EQUIP_MAGICIAN_HAT])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (6 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (6 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
// staff
int frameDx = equip[EQUIP_MAHOGANY_STAFF] ? 6 : 3;
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (frameDx + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (frameDx + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
if (equip[EQUIP_BLOOD_SNAKE])
{
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (27 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (27 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
}
if (equip[EQUIP_REAR_SHOT])
{
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
// shot type
if (shotType != ShotTypeStandard)
{
switch (shotType)
{
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;
case ShotTypeFire:
sprite.setColor(sf::Color(255, 180, 0, 255));
break;
default:
break;
}
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_1));
if (isMirroring)
sprite.setTextureRect(sf::IntRect( (3 + frame) * width + width, spriteDy * height, -width, height));
else
sprite.setTextureRect(sf::IntRect( (3 + frame) * width, spriteDy * height, width, height));
app->draw(sprite);
sprite.setTexture(*ImageManager::getInstance().getImage(IMAGE_PLAYER_0));
}
}
std::string WitchBlastGame::enemyToString(enemyTypeEnum enemyType)
{
std::string value = "unknown";
switch (enemyType)
{
case EnemyTypeBat_invocated:
case EnemyTypeBat:
value = "enemy_type_bat";
break;
case EnemyTypeBatSkeleton_invocated:
case EnemyTypeBatSkeleton:
value = "enemy_type_bat_skeleton";
break;
case EnemyTypeRat_invocated:
case EnemyTypeRat:
value = "enemy_type_rat";
break;
case EnemyTypeRatBlack:
value = "enemy_type_rat_black";
break;
case EnemyTypeRatHelmet_invocated:
case EnemyTypeRatHelmet:
value = "enemy_type_rat_helmet";
break;
case EnemyTypeRatBlackHelmet:
value = "enemy_type_rat_black_helmet";
break;
case EnemyTypeEvilFlower:
value = "enemy_type_evil_flower";
break;
case EnemyTypeEvilFlowerIce:
value = "enemy_type_evil_flower_ice";
break;
case EnemyTypeEvilFlowerFire:
value = "enemy_type_evil_flower_fire";
break;
case EnemyTypeSnake_invocated:
case EnemyTypeSnake:
value = "enemy_type_snake";
break;
case EnemyTypeSnakeBlood_invocated:
case EnemyTypeSnakeBlood:
value = "enemy_type_snake_blood";
break;
case EnemyTypeSlime_invocated:
case EnemyTypeSlime:
value = "enemy_type_slime";
break;
case EnemyTypeSlimeRed_invocated:
case EnemyTypeSlimeRed:
value = "enemy_type_slime_red";
break;
case EnemyTypeSlimeBlue_invocated:
case EnemyTypeSlimeBlue:
value = "enemy_type_slime_blue";
break;
case EnemyTypeSlimeViolet_invocated:
case EnemyTypeSlimeViolet:
value = "enemy_type_slime_violet";
break;
case EnemyTypeImpBlue:
value = "enemy_type_imp_blue";
break;
case EnemyTypeImpRed:
value = "enemy_type_imp_red";
break;
case EnemyTypePumpkin_invocated:
case EnemyTypePumpkin:
value = "enemy_type_pumpkin";
break;
case EnemyTypeWitch:
value = "enemy_type_witch";
break;
case EnemyTypeWitchRed:
value = "enemy_type_witch_red";
break;
case EnemyTypeCauldron:
value = "enemy_type_cauldron";
break;
case EnemyTypeCauldronElemental:
value = "enemy_type_cauldron_elemental";
break;
case EnemyTypeGhost:
value = "enemy_type_ghost";
break;
case EnemyTypeZombie_invocated:
case EnemyTypeZombie:
value = "enemy_type_zombie";
break;
case EnemyTypeZombieDark:
value = "enemy_type_zombie_dark";
break;
case EnemyTypeBogeyman:
value = "enemy_type_bogeyman";
break;
// mini boss
case EnemyTypeBubble:
value = "enemy_type_bubble";
break;
case EnemyTypeBubbleIce:
value = "enemy_type_bubble_ice";
break;
case EnemyTypeBubbleGreater:
value = "enemy_type_bubble_greater";
break;
case EnemyTypeSlimeLarge:
value = "enemy_type_slime_large";
break;
case EnemyTypeSlimeBlueLarge:
value = "enemy_type_slime_blue_large";
break;
case EnemyTypeSlimeRedLarge:
value = "enemy_type_slime_red_large";
break;
case EnemyTypeSlimeVioletLarge:
value = "enemy_type_slime_violet_large";
break;
// boss
case EnemyTypeButcher:
value = "enemy_type_boss_butcher";
break;
case EnemyTypeSlimeBoss:
value = "enemy_type_boss_slime_giant";
break;
case EnemyTypeCyclops:
value = "enemy_type_boss_cyclops";
break;
case EnemyTypeRatKing:
value = "enemy_type_boss_rat_king";
break;
case EnemyTypeSpiderGiant:
value = "enemy_type_boss_spider_giant";
break;
case EnemyTypeFranckyHand:
case EnemyTypeFranckyHead:
case EnemyTypeFranckyFoot:
case EnemyTypeFrancky:
value = "enemy_type_francky";
break;
case EnemyTypeVampire:
case EnemyTypeVampireDead:
value = "enemy_type_vampire";
break;
// invocated
case EnemyTypeRatGreen:
value = "enemy_type_green_rat";
break;
case EnemyTypeRockFalling:
value = "enemy_type_rock_falling";
break;
case EnemyTypeRockMissile:
value = "enemy_type_rock_missile";
break;
case EnemyTypeSpiderEgg:
case EnemyTypeSpiderEgg_invocated:
value = "enemy_type_spider_egg";
break;
case EnemyTypeSpiderLittle:
case EnemyTypeSpiderLittle_invocated:
value = "enemy_type_spider_little";
break;
case EnemyTypeSpiderWeb:
value = "enemy_type_spider_web";
break;
case EnemyTypeNone:
value = "enemy_type_himself";
break;
case NB_ENEMY:
break;
}
return value;
}
std::string WitchBlastGame::sourceToString(sourceTypeEnum sourceType, enemyTypeEnum enemyType)
{
std::string value = "unknown";
switch (sourceType)
{
case SourceTypeBolt:
case SourceTypeMelee:
value = tools::getLabel(enemyToString(enemyType));
break;
case SourceTypeExplosion:
value = tools::getLabel("source_explosion");
break;
case SourceTypePoison:
value = tools::getLabel("source_poison");
}
return value;
}
void WitchBlastGame::saveHiScores()
{
std::ofstream file(HISCORES_FILE.c_str(), std::ios::out | std::ios::trunc);
if (file)
{
// version (for compatibility check)
file << SAVE_VERSION << std::endl;
file << scores.size() << std::endl;
// tuto
for (unsigned int i = 0; i < scores.size() && i < SCORES_MAX; i++)
{
file << scores[i].name << " ";
file << scores[i].level << " ";
file << scores[i].score << " ";
file << scores[i].shotType << " ";
// player equip
for (int j = 0; j < NUMBER_EQUIP_ITEMS; j++)
file << scores[i].equip[j] << " ";
file << std::endl;
}
file << std::endl;
file.close();
}
else
{
std::cout << "[ERROR] Impossible to open hi-scores file.\n";
}
}
void WitchBlastGame::loadHiScores()
{
scores.clear();
std::ifstream file(HISCORES_FILE.c_str(), std::ios::in);
if (file)
{
// version
std::string v;
file >> v;
if (v != SAVE_VERSION)
{
file.close();
remove(SAVE_DATA_FILE.c_str());
return;
}
int nbScores;
file >> nbScores;
for (int i = 0; i < nbScores; i++)
{
StructScore score;
file >> score.name;
file >> score.level;
file >> score.score;
file >> score.shotType;
for (int j = 0; j < NUMBER_EQUIP_ITEMS; j++)
file >> score.equip[j];
scores.push_back(score);
}
}
}
void WitchBlastGame::revealFloor()
{
currentFloor->reveal();
refreshMinimap();
}
void WitchBlastGame::activateKeyRoomEffect(bool withColorEffect)
{
dungeonEntity->activateKeyRoomEffect();
if (withColorEffect) makeColorEffect(X_GAME_COLOR_VIOLET, 0.35f);
SoundManager::getInstance().playSound(SOUND_FORCE_FIELD);
}
void WitchBlastGame::generateStar(sf::Color starColor, float xStar, float yStar)
{
SpriteEntity* spriteStar = new SpriteEntity(
ImageManager::getInstance().getImage(IMAGE_STAR_2),
xStar, yStar);
spriteStar->setScale(0.8f, 0.8f);
spriteStar->setZ(1000.0f);
spriteStar->setSpin(-100 + rand()%200);
spriteStar->setVelocity(Vector2D(10 + rand()%40));
spriteStar->setWeight(-150);
spriteStar->setFading(true);
spriteStar->setAge(-0.8f);
spriteStar->setLifetime(0.1f + (rand() % 100) * 0.003f );
spriteStar->setColor(starColor);
spriteStar->setType(ENTITY_EFFECT);
}
void WitchBlastGame::registerAchievement(enumAchievementType achievement)
{
if (achievementState[achievement] == AchievementUndone)
{
achievementState[achievement] = AchievementPending;
achievementStruct ach;
ach.type = achievement;
ach.message = tools::getLabel(achievements[achievement].label);
ach.timer = ACHIEVEMENT_DELAY_MAX;
ach.counter = 0;
ach.hasStarted = false;
achievementsQueue.push(ach);
}
}
bool WitchBlastGame::isItemLocked(enumItemType item)
{
for (int i = 0; i < NB_ACHIEVEMENTS; i++)
{
if (achievementState[i] == AchievementUndone)
{
if (achievements[i].unlockType == UnlockItem)
if (achievements[i].unlock == (int)item) return true;
}
}
return false;
}
bool WitchBlastGame::isFunctionalityLocked(enumFunctionalityType func)
{
for (int i = 0; i < NB_ACHIEVEMENTS; i++)
{
if (achievementState[i] == AchievementUndone)
{
if (achievements[i].unlockType == UnlockFunctionality)
if (achievements[i].unlock == (int)func) return true;
}
}
return false;
}
WitchBlastGame &game()
{
return *gameptr;
}
diff --git a/src/WitchBlastGame.h b/src/WitchBlastGame.h
index 1913ab5..b46ae05 100644
--- a/src/WitchBlastGame.h
+++ b/src/WitchBlastGame.h
@@ -1,976 +1,977 @@
/** 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 "DungeonMapEntity.h"
#include "EnemyEntity.h"
#include "DoorEntity.h"
#include "GameFloor.h"
#include "Config.h"
#include "Achievements.h"
#include <queue>
// for tests
//#define TEST_MODE
const int ALIGN_LEFT = 0; /*!< Text alignment left */
const int ALIGN_RIGHT = 1; /*!< Text alignment right */
const int ALIGN_CENTER = 2; /*!< Text alignment centered */
const int X_GAME_FADE_IN = 0; /*!< Fade In effect ID */
const int X_GAME_FADE_OUT = 1; /*!< Fade out effect ID */
const int X_GAME_COLOR_RED = 0; /*!< Red light color effect ID */
const int X_GAME_COLOR_GREEN = 1; /*!< Green light color effect ID */
const int X_GAME_COLOR_BLUE = 2; /*!< Blue light color effect ID */
const int X_GAME_COLOR_VIOLET = 3; /*!< Violet light color effect ID */
const int X_GAME_COLOR_BROWN = 4; /*!< Brown light color effect ID */
const int X_GAME_COLOR_WHITE = 5; /*!< White light color effect ID */
unsigned const int NumberKeys = 13; /*!< Number of input keys on the game */
/** Input key string
* Keys in the config file.
*/
const std::string inputKeyString[NumberKeys] =
{
"key_move_up",
"key_move_down",
"key_move_left",
"key_move_right",
"key_fire_up",
"key_fire_down",
"key_fire_left",
"key_fire_right",
"key_fire_select",
"key_spell",
"key_interact",
"key_time",
"key_fire"
};
/** Credits: coder */
const std::string creditsCode[] =
{
"Seby",
"END"
};
/** Credits: 2D artists */
const std::string credits2D[] =
{
"Pierre \"dejam0rt\" Baron",
"END"
};
/** Credits: Sound */
const std::string creditsSound[] =
{
"www.freesound.org/",
"www.freesfx.co.uk/",
"www.universal-soundbank.com/",
"END"
};
/** Credits: Music */
const std::string creditsMusic[] =
{
"Michael Ghelfi",
"JappeJ",
"SteveSyz",
"CinTer",
"cazok",
"ET16",
"END"
};
/** Credits: Translation */
const std::string creditsTranslate[] =
{
"achpile (russian)",
"AFS (spanish)",
"Geheim (german)",
"END"
};
/** Struct for game parameters */
struct parameterStruct
{
int language; /*!< Language ID (english = 0) */
int musicVolume; /*!< music volume (0 to 100) */
int soundVolume; /*!< sound volume (0 to 100) */
bool zoom; /*!< zoom effect (false = disabled) */
bool vsync; /*!< monitor vsync (false = disabled) */
bool bloodSpread; /*!< blood spread (false = disabled) */
bool fullscreen; /*!< full screen (false = disabled) */
bool displayBossPortrait;
std::string playerName; /*!< player name */
};
/*! \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:
// DATA TYPES
/** Savegame header data */
struct saveHeaderStruct
{
bool ok; /**< Save game OK ? */
int level; /**< Level the save game */
float gameTime; /**< How long it has been played */
int shotType; /**< Current special shot type */
std::string date; /**< Date of the save game */
std::string time; /**< Time of the save game */
};
// PUBLIC METHODS
/*!
* \brief Constructor
*/
WitchBlastGame();
/*!
* \brief Destructor
*/
virtual ~WitchBlastGame();
/*!
* \brief Accessor on the current dungeon map
* \return a pointer to the current dungeon map
*/
DungeonMap* getCurrentMap();
/*!
* \brief Accessor on the current dungeon map entity
* \return a pointer to the current dungeon map entity
*/
DungeonMapEntity* getCurrentMapEntity();
/*!
* \brief Accessor on the player
* \return a pointer to the player
*/
PlayerEntity* getPlayer();
/*!
* \brief Accessor on the player's position
* \return a Vector2D of the player's position
*/
Vector2D getPlayerPosition();
/*!
* \brief accessor on the level
* \return : the level
*/
int getLevel();
/*!
* \brief accessor on the level
* \return : the challenge level
*/
int getChallengeLevel();
/*!
* \brief accessor on showLogical flag
* \return : the value of the flag
*/
bool getShowLogical();
float getDeltaTime();
/*!
* \brief accessor on the parameters
* \return : the parameters
*/
parameterStruct getParameters();
/*!
* \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 getEnemyCount();
int getUndeadCount();
void animateEffects();
EnemyEntity* getBoss();
void destroyUndead(int damage);
int getItemsCount();
/*!
* \brief Return the position of the nearest enemy
* \param x : x position of the source
* \param y : y position of the source
* \return position of the nearest enemy (negative position when no enemy found)
*/
Vector2D getNearestEnemy(float x, float y);
/*!
* \brief Generates blood
* \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 Add a corpse on the map
* \param x : x position of the corpse
* \param y : y position of the corpse
* \param frame : frame of the corpse in the spritesheet
*/
void addCorpse(float x, float y, int frame);
/*!
* \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);
/*!
* \brief Make a "color fade" effet
* \param color : the color of the effect
* \param duration : duration of the effect
*/
void makeColorEffect(int color, float duration);
/*!
* \brief Write a string on screen
* \param str : the string
* \param size : the character size
* \param x : x position
* \param y : y position
* \param align : alignment (ALIGN_LEFT, ALIGN_CENTER or ALIGN_RIGHT)
* \param color : color of the string
* \param app : the rendering target
* \param xShadow : offset of the shadow (x)
* \param yShadow : offset of the shadow (y)
*/
void write(std::string str, int size, float x, float y, int align, sf::Color color, sf::RenderTarget* app, int xShadow, int yShadow);
/*!
* \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();
/*!
* \brief Save the game data (general)
*/
void saveGameData();
/*!
* \brief Load the game data (general)
*/
void loadGameData();
/*!
* \brief Load the savegame data
* \return the savegame data
*/
saveHeaderStruct loadGameHeader();
/*!
* \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, bool noFairy);
/*!
* \brief Returns a random spell object
*/
enumItemType getItemSpell();
/*!
* \brief Generate a random challenge loot
*
* \param x : x position of the bonus
* \param y : y position of the bonus
*/
void generateChallengeBonus(float x, float y);
/*!
* \brief Adds monsters
*
* Adds monsters to the room in suitable places.
* \param monsterType : monster type
* \param amount : amount of monsters
*/
void findPlaceMonsters(enemyTypeEnum monsterType, int amount);
/*!
* \brief Add a monster to the "killed monsters" table
* \param enemyType : ID of the monster
*/
void addKilledEnemy(enemyTypeEnum enemyType, enumShotType damageType);
/*!
* \brief Proceed an event
* \param event : ID of the event
*/
void proceedEvent(EnumWorldEvents event);
/*!
* \brief Proceed a message
* \param event : ID of the message
*/
void testAndAddMessageToQueue(EnumMessages type);
/*!
* \brief Proceed a divinity level up message
* \param label : the message to proceed
*/
void addDivLevelMessageToQueue(std::string label);
std::string enemyToString(enemyTypeEnum enemyType);
std::string sourceToString(sourceTypeEnum sourceType, enemyTypeEnum enemyType);
+ void saveScreen();
void saveDeathScreen();
struct StructScore
{
std::string name;
int score;
int level;
int shotType;
bool equip[NUMBER_EQUIP_ITEMS];
};
void calculateScore();
void addLifeBarToDisplay(std::string label, int hp, int hpMax);
void revealFloor();
void activateKeyRoomEffect(bool withColorEffect);
void generateStar(sf::Color starColor, float xStar, float yStar);
void registerAchievement(enumAchievementType achievement);
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);
void killArtefactDescription();
private:
Config config;
float deltaTime;
// 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) */
bool showLogical; /*!< True if showing bounding boxes, z and center */
bool showGameTime; /*!< True if showing the game time */
// game play
int level; /*!< Level (floor) */
int score; /*!< score (calculated at the end of the game) */
int bodyCount; /*!< killed monsters (calculated at the end of the game) */
int challengeLevel; /*!< Level (challenge) */
float gameTime; /*!< "age" of the current game */
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 */
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 */
int killedEnemies[NB_ENEMY];
// game objects
PlayerEntity* player; /*!< Pointer to the player entity */
DungeonMapEntity* dungeonEntity; /*!< TileMap of the room (main game board) + blood, items, etc...*/
TileMapEntity* miniMapEntity;
// displaying objects
DoorEntity* doorEntity[4]; /*!< Pointers to the door graphical entity */
sf::Font font; /*!< The font used for displaying text */
sf::Text myText; /*!< The text to be displayed */
sf::Sprite introScreenSprite;
sf::Sprite titleSprite;
struct uiSpritesStruct
{
sf::Sprite gui;
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::Sprite topLayer;
sf::Sprite msgBoxSprite;
sf::Sprite iconSprite;
sf::Sprite mapBgSprite;
} uiSprites;
struct lifeBarStruct
{
bool toDisplay;
std::string label;
int hp;
int hpMax;
} lifeBar;
float xOffset, yOffset; /*!< Main game client position in the GUI */
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 ! */
MusicIntro, /**< Main menu music */
MusicChallenge /**< Challenge music - for epic fights ! */
};
/** Game states enum
* Used for the different game states
*/
enum gameStateEnum
{
gameStateInit, /**< Game initialization */
gameStateIntro, /** < Intro animation */
gameStateMenu, /**< Menu */
gameStateKeyConfig, /**< Key config */
gameStatePlaying, /**< Playing */
gameStatePlayingPause, /**< Playing / Pause */
gameStatePlayingDisplayBoss, /**< Playing / DisplayBoss */
};
gameStateEnum gameState; /*!< Store the game state */
float bossDisplayTimer;
int bossDisplayState;
/** Special game states enum
* Used for effects such as fade in...
*/
enum xGameTypeEnum
{
xGameTypeFade, /**< Fade effect */
xGameTypeShake, /**< Shake effect */
xGameTypeFadeColor, /**< Color fade effect */
NB_X_GAME
};
struct xGameStruct
{
bool active;
int param;
float timer;
float duration;
} xGame[NB_X_GAME];
/** Input Keys enum
* Used for the input binding
*/
enum inputKeyEnum
{
KeyUp,
KeyDown,
KeyLeft,
KeyRight,
KeyFireUp,
KeyFireDown,
KeyFireLeft,
KeyFireRight,
KeyFireSelect,
KeySpell,
KeyInteract,
KeyTimeControl,
KeyFire
};
sf::Keyboard::Key input[NumberKeys]; /*!< Input key array */
std::string scoreSaveFile;
/*!
* \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.
* \param isFight : true if loading in fight
*/
void playLevel(bool isFight);
/*!
* \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 map items and sprites.
*/
void refreshMap();
/*!
* \brief Check if a door is present, and its style
*
* \param doorId : index of the door
* \param roomCurrent : type of the current door
* \param roomNeighbour : type of the neighbour door
*/
void checkDoor(int doorId, roomTypeEnum roomCurrent, roomTypeEnum roomNeighbour);
/*!
* \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(enemyTypeEnum monsterType, float xm, float ym);
/*!
* \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 Checks if player can interact with something
*/
void checkInteraction();
/*!
* \brief Plays a music
*
* Plays a music.
*
* \param musicChoice : music track ID
*/
void playMusic(musicEnum musicChoice);
/*!
* \brief Update the music volume (with parameters.volumeMusic)
*/
void updateMusicVolume();
/*!
* \brief Add a key to the player input map from a string key (from file)
* \param logicInput : input function (move left, fire up, etc...)
* \param key : Key as string
*/
void addKey(int logicInput, std::string key);
/*!
* \brief Save configuration to "config.dat"
*/
void saveConfigurationToFile();
/*!
* \brief Configure with data from "config.dat"
*/
void configureFromFile();
/*!
* \brief Update the game
*/
void updateRunningGame();
/*!
* \brief Render the game
*/
void renderRunningGame();
void renderGame();
void renderHud();
void renderLifeBar();
void renderMessages();
void renderBossPortrait();
/*!
* \brief Update the menu
*/
void updateMenu();
/*!
* \brief Render the menu
*/
void renderMenu();
/*!
* \brief Render the menu
*/
void renderInGameMenu();
/*!
* \brief initialize the intro
*/
void prepareIntro();
/*!
* \brief Update the intro
*/
void updateIntro();
/*!
* \brief Render the intro
*/
void renderIntro();
/*!
* \brief Render the credits screen
*/
void renderCredits();
/*!
* \brief Render the achievements screen
*/
void renderAchievements();
/*!
* \brief Render the scores screen
*/
void renderHiScores();
/** Menu keys enum
* Identify the various keys of the menu.
*/
enum menuItemEnum
{
MenuStartNew, /**< When starting the game */
MenuStartOld, /**< When restoring the game */
MenuConfig, /**< When configuring the game */
MenuKeys, /**< When configuring keys */
MenuConfigBack, /**< Back to the main menu */
MenuTutoReset, /**< Reset the tutorials */
MenuLanguage, /**< When configuring the language */
MenuExit, /**< When exiting the game */
MenuAchievements, /**< Display the Achievements */
MenuCredits, /**< Display the credits screen */
MenuHiScores, /**< Display the hi-scores screen */
MenuPlayerName, /**< To enter/change the player name */
MenuVolumeSound,
MenuVolumeMusic,
MenuContinue, /**< Continue the game */
MenuSaveAndQuit, /**< Save and return to main */
};
/** Menu states enum
* Identify the various states of the menu.
*/
enum menuStateEnum
{
MenuStateMain,
MenuStateConfig,
MenuStateKeys,
MenuStateHiScores,
MenuStateChangeName,
MenuStateCredits,
MenuStateAchievements,
MenuStateFirst /**< First time, we choose language and keyboard */
};
menuStateEnum menuState;
/*!
* \brief Menu item structure
*/
struct menuItemStuct
{
menuItemEnum id; /**< Id of the action */
std::string label; /**< Label of the menu item */
std::string description; /**< Description of the menu item */
};
/*!
* \brief Menu structure
*/
struct menuStuct
{
std::vector<menuItemStuct> items; /**< Menu items */
unsigned int index; /**< Position int the menu */
float age; /**< Age of the menu */
};
menuStuct menuMain;
menuStuct menuFirst;
menuStuct menuConfig;
menuStuct menuInGame;
unsigned int menuKeyIndex;
unsigned int menuAchIndex;
/*!
* \brief Build the menu items
*/
void buildMenu(bool rebuild);
/*!
* \brief Build the menu items (in game)
*/
void buildInGameMenu();
/*!
* \brief Switch to the menu
*/
void switchToMenu();
/*!
* \brief Save language config and default keys configuration
*/
void registerLanguage();
parameterStruct parameters;
void resetKilledEnemies();
std::queue <messageStruct> messagesQueue;
bool worldEvent[NB_EVENTS];
void initEvents();
bool gameMessagesToSkip[NB_MESSAGES];
struct achievementStruct
{
enumAchievementType type;
std::string message;
float timer;
bool hasStarted;
int counter;
};
std::queue <achievementStruct> achievementsQueue;
void renderPlayer(float x, float y, bool equip[NUMBER_EQUIP_ITEMS], int shotType,
int frame, int spriteDy);
void renderDeathScreen(float x, float y);
bool equipToDisplay[NUMBER_EQUIP_ITEMS];
bool equipNudeToDisplay[NUMBER_EQUIP_ITEMS];
saveHeaderStruct saveHeader;
struct StructMonster
{
enemyTypeEnum id;
float x;
float y;
};
/*!
* \brief Data for "in fight" game saving
*/
struct StructSaveInFight
{
bool isFight; /**< True if loading during a fight */
float x; /**< Player x position */
float y; /**< Player y position */
int direction; /**< Player direction */
std::vector<StructMonster> monsters; /**< Monsters */
};
StructSaveInFight saveInFight; /**< Data for "in fight" game saving */
SpriteEntity* introSprites[8];
int introState;
int introSoundState;
std::vector <StructScore> scores;
StructScore lastScore;
void loadHiScores();
void saveHiScores();
struct StructInteraction
{
bool active;
EnumInteractionType type;
int id;
std::string label;
} interaction;
void enableAA(bool enable);
enum achievementStatus { AchievementDone, AchievementUndone, AchievementPending};
achievementStatus achievementState[NB_ACHIEVEMENTS];
bool isItemLocked(enumItemType item);
bool isFunctionalityLocked(enumFunctionalityType func);
int getAchievementsPercents();
struct globalDataStruct
{
int killedMonster[NB_ENEMY];
} globalData;
void generateUiParticle(float x, float y);
};
/*!
* \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 18, 12:20 AM (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
70459
Default Alt Text
(315 KB)

Event Timeline