Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F629631
WitchBlastGame.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
212 KB
Referenced Files
None
Subscribers
None
WitchBlastGame.cpp
View Options
/** 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
"ObstacleEntity.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
"SausageEntity.h"
#include
<iostream>
#include
<sstream>
#include
<fstream>
#include
<ctime>
#include
<algorithm>
#define LEVEL_TEST_MODE
#ifdef ONLINE_MODE
#include
"OnlineScoring.h"
#endif
// ONLINE_MODE
const
float
PORTRAIT_DIAPLAY_TIME
=
5.0f
;
const
unsigned
int
ACHIEV_LINES
=
3
;
const
int
VolumeModifier
=
55
;
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
},
{
EventConsumable
,
MsgTutoConsumables
},
{
EventPotion
,
MsgTutoPotions
},
};
// 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
;
gameFromSaveFile
=
false
;
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
);
}
// init current music
currentStandardMusic
=
0
;
// loading resources
const
char
*
const
images
[]
=
{
"media/player_0.png"
,
"media/player_1.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/eyeball.png"
,
"media/witch.png"
,
"media/cauldron.png"
,
"media/snake.png"
,
"media/pumpkin.png"
,
"media/ghost.png"
,
"media/zombie.png"
,
"media/bogeyman.png"
,
"media/sausage.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/shadows_standard.png"
,
"media/shadows_corners.png"
,
"media/shadows_medium.png"
,
"media/shadows_small.png"
,
"media/doors.png"
,
"media/destroyable_objects.png"
,
"media/hall_of_fame.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_impact_boss.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"
,
"media/sound/barrel_hit.ogg"
,
"media/sound/barrel_smash.ogg"
,
"media/sound/secret.ogg"
,
"media/sound/scroll.ogg"
,
"media/sound/tic_tac.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
);
scoreState
=
ScoreOK
;
loopCounter
=
0
;
loadGameData
();
loadHiScores
();
receiveScoreFromServer
();
srand
(
time
(
NULL
));
fairySpriteOffsetY
=
0
;
if
(
isAdvanced
())
fairySpriteOffsetY
=
72
+
72
*
(
rand
()
%
4
);
}
void
WitchBlastGame
::
enableAA
(
bool
enable
)
{
for
(
int
i
=
0
;
i
<
NB_IMAGES
;
i
++
)
{
if
(
i
!=
IMAGE_TILES
&&
i
!=
IMAGE_DUNGEON_OBJECTS
&&
i
!=
IMAGE_TILES_SHADOW
&&
i
!=
IMAGE_TILES_SHADOW_CORNER
&&
i
!=
IMAGE_TILES_SHADOW_MEDIUM
&&
i
!=
IMAGE_MINIMAP
&&
i
!=
IMAGE_DOORS
&&
i
!=
IMAGE_FOG
&&
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
);
if
(
sendScoreThread
.
joinable
())
sendScoreThread
.
join
();
if
(
receiveScoreThread
.
joinable
())
receiveScoreThread
.
join
();
}
DungeonMap
*
WitchBlastGame
::
getCurrentMap
()
{
return
currentMap
;
}
GameFloor
*
WitchBlastGame
::
getCurrentFloor
()
{
return
currentFloor
;
}
int
WitchBlastGame
::
getFloorX
()
{
return
floorX
;
}
int
WitchBlastGame
::
getFloorY
()
{
return
floorY
;
}
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
;
}
float
WitchBlastGame
::
getGameTime
()
{
return
gameTime
;
}
void
WitchBlastGame
::
onUpdate
()
{
if
(
gameState
==
gameStatePlaying
)
{
if
(
isPlayerAlive
)
player
->
setItemToBuy
(
NULL
);
// time stop
if
(
player
->
isSpecialStateActive
(
SpecialStateTime
))
{
if
(
loopCounter
==
0
)
EntityManager
::
getInstance
().
animate
(
deltaTime
);
else
player
->
animate
(
deltaTime
);
loopCounter
++
;
if
(
loopCounter
>
3
)
loopCounter
=
0
;
SoundManager
::
getInstance
().
playSound
(
SOUND_CLOCK
,
false
);
}
else
{
EntityManager
::
getInstance
().
animate
(
deltaTime
);
if
(
isPressing
(
KeyTimeControl
,
false
))
{
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
,
1
);
}
}
}
}
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
,
int
startingLevel
)
{
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
{
gameFromSaveFile
=
true
;
playLevel
(
saveInFight
.
isFight
);
}
}
if
(
!
fromSaveFile
)
{
gameFromSaveFile
=
false
;
// the player
player
=
new
PlayerEntity
((
TILE_WIDTH
*
MAP_WIDTH
*
0.5f
),
(
TILE_HEIGHT
*
MAP_HEIGHT
*
0.5f
));
resetKilledEnemies
();
randomizePotionMap
();
if
(
startingLevel
>
1
)
{
for
(
int
i
=
1
;
i
<
startingLevel
;
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
);
if
(
startingLevel
>
2
)
{
player
->
loadDivinity
(
rand
()
%
NB_DIVINITY
,
(
startingLevel
-
2
)
*
200
,
1
,
0
);
}
}
startNewLevel
();
}
}
void
WitchBlastGame
::
startNewLevel
()
{
// reset floor items
player
->
resetFloorItem
();
// reset present items
resetPresentItems
();
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
)
{
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
);
/*new ItemEntity(ItemScrollRevelation, 100, 100);
new ItemEntity(ItemScrollRevelation, 150, 100);
new ItemEntity(ItemPotion02, 200, 100);
new ItemEntity(ItemPotion01, 250, 100);
new ItemEntity(ItemBag, 450, 100);
new ItemEntity(ItemFloorMap, 500, 100);*/
}
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
;
bool
stopDemo
=
false
;
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
::
Escape
)
stopDemo
=
true
;
}
}
if
(
isPressing
(
KeyFireDown
,
true
))
stopDemo
=
true
;
if
(
stopDemo
)
{
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
;
bool
escape
=
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
)
{
escape
=
true
;
}
if
(
event
.
key
.
code
==
sf
::
Keyboard
::
Return
&&
gameState
==
gameStatePlaying
)
{
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
==
sf
::
Keyboard
::
X
)
{
if
(
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
LShift
))
startNewGame
(
false
,
1
);
}
if
(
event
.
key
.
code
>=
sf
::
Keyboard
::
Num1
&&
event
.
key
.
code
<=
sf
::
Keyboard
::
Num8
)
{
#ifdef LEVEL_TEST_MODE
if
(
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
LAlt
)
&&
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
LControl
))
{
startNewGame
(
false
,
event
.
key
.
code
-
sf
::
Keyboard
::
Num1
+
1
);
}
else
#endif
if
(
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
LShift
))
{
player
->
dropConsumables
(
event
.
key
.
code
-
sf
::
Keyboard
::
Num1
);
}
else
{
player
->
tryToConsume
(
event
.
key
.
code
-
sf
::
Keyboard
::
Num1
);
}
}
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
,
2
);
findPlaceMonsters
(
EnemyTypeSpiderTarantula
,
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
)
{
if
(
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
LAlt
))
for
(
int
i
=
0
;
i
<
NUMBER_ITEMS
-
NUMBER_EQUIP_ITEMS
;
i
++
)
new
ItemEntity
((
enumItemType
)
i
,
100
+
(
i
%
14
)
*
58
,
100
+
(
i
/
14
)
*
60
);
else
for
(
int
i
=
NUMBER_ITEMS
-
NUMBER_EQUIP_ITEMS
;
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
;
// POST EVENT
if
(
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
(
player
->
isDead
()
&&
!
xGame
[
xGameTypeFade
].
active
&&
isPressing
(
KeyFireDown
,
true
))
{
if
(
player
->
getDeathAge
()
<
DEATH_CERTIFICATE_DELAY
)
player
->
setDeathAge
(
DEATH_CERTIFICATE_DELAY
);
else
backToMenu
=
true
;
}
else
if
(
gameState
==
gameStatePlayingPause
)
{
if
(
isPressing
(
KeyDown
,
true
))
{
menuInGame
.
index
++
;
if
(
menuInGame
.
index
==
menuInGame
.
items
.
size
())
menuInGame
.
index
=
0
;
SoundManager
::
getInstance
().
playSound
(
SOUND_SHOT_SELECT
);
}
else
if
(
isPressing
(
KeyUp
,
true
))
{
if
(
menuInGame
.
index
==
0
)
menuInGame
.
index
=
menuInGame
.
items
.
size
()
-
1
;
else
menuInGame
.
index
--
;
SoundManager
::
getInstance
().
playSound
(
SOUND_SHOT_SELECT
);
}
else
if
(
isPressing
(
KeyFireDown
,
true
))
{
switch
(
menuInGame
.
items
[
menuInGame
.
index
].
id
)
{
case
MenuStartNew
:
case
MenuStartOld
:
case
MenuKeys
:
case
MenuJoystick
:
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
;
}
}
}
else
if
(
gameState
==
gameStatePlaying
)
{
if
(
player
->
canMove
())
player
->
setVelocity
(
Vector2D
(
0.0f
,
0.0f
));
if
(
isPressing
(
KeyLeft
,
false
))
{
if
(
isPressing
(
KeyUp
,
false
))
player
->
move
(
7
);
else
if
(
isPressing
(
KeyDown
,
false
))
player
->
move
(
1
);
else
player
->
move
(
4
);
}
else
if
(
isPressing
(
KeyRight
,
false
))
{
if
(
isPressing
(
KeyUp
,
false
))
player
->
move
(
9
);
else
if
(
isPressing
(
KeyDown
,
false
))
player
->
move
(
3
);
else
player
->
move
(
6
);
}
else
if
(
isPressing
(
KeyUp
,
false
))
{
player
->
move
(
8
);
}
else
if
(
isPressing
(
KeyDown
,
false
))
{
player
->
move
(
2
);
}
if
(
isPressing
(
KeyInteract
,
true
))
{
if
(
!
player
->
isDead
()
&&
interaction
.
active
)
player
->
interact
(
interaction
.
type
,
interaction
.
id
);
}
if
(
isPressing
(
KeyFireSelect
,
true
))
{
if
(
gameState
==
gameStatePlaying
)
player
->
selectNextShotType
();
}
if
(
isPressing
(
KeySpell
,
true
))
{
if
(
gameState
==
gameStatePlaying
)
player
->
castSpell
();
}
player
->
resestFireDirection
();
if
(
isPressing
(
KeyFireLeft
,
false
))
player
->
fire
(
4
);
else
if
(
isPressing
(
KeyFireRight
,
false
))
player
->
fire
(
6
);
else
if
(
isPressing
(
KeyFireUp
,
false
))
player
->
fire
(
8
);
else
if
(
isPressing
(
KeyFireDown
,
false
))
player
->
fire
(
2
);
// alternative "one button" gameplay
else
if
(
isPressing
(
KeyFire
,
false
))
{
if
(
gameState
==
gameStatePlaying
&&
isPressing
(
KeyFire
,
true
))
firingDirection
=
player
->
getFacingDirection
();
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
();
}
}
}
else
if
(
gameState
==
gameStatePlayingDisplayBoss
)
{
if
(
isPressing
(
KeyFireDown
,
true
))
gameState
=
gameStatePlaying
;
}
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
;
#ifdef ONLINE_MODE
menuScoreIndex
=
0
;
#else
menuScoreIndex
=
2
;
#endif
}
else
{
prepareIntro
();
switchToMenu
();
menuState
=
MenuStateMain
;
}
}
}
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
();
// 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
(
player
->
isSpecialStateActive
(
SpecialStateTime
))
{
sf
::
RectangleShape
whiteLine
=
sf
::
RectangleShape
(
sf
::
Vector2f
(
GAME_WIDTH
,
2
));
whiteLine
.
setFillColor
(
sf
::
Color
(
255
,
255
,
255
,
32
));
for
(
int
i
=
0
;
i
<
8
;
i
++
)
{
whiteLine
.
setPosition
(
xOffset
,
yOffset
+
rand
()
%
GAME_HEIGHT
);
app
->
draw
(
whiteLine
);
}
}
if
(
isPressing
(
KeyTimeControl
,
false
)
&&
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
(
SpecialStateConfused
))
{
specialStateStuct
specialState
=
player
->
getSpecialState
(
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
);
// drawing the level items
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 the consumable
if
(
!
player
->
isEquiped
(
EQUIP_BAG
))
{
sf
::
RectangleShape
shadow
(
sf
::
Vector2f
(
70
,
33
));
shadow
.
setFillColor
(
sf
::
Color
(
0
,
0
,
0
,
128
));
shadow
.
setPosition
(
sf
::
Vector2f
(
386
,
614
));
app
->
draw
(
shadow
);
}
for
(
int
i
=
0
;
i
<
MAX_SLOT_CONSUMABLES
;
i
++
)
{
if
(
player
->
getConsumable
(
i
)
>
-1
)
{
int
n
=
player
->
getConsumable
(
i
);
sf
::
Sprite
consSprite
;
consSprite
.
setTexture
(
*
ImageManager
::
getInstance
().
getImage
(
IMAGE_ITEMS
));
consSprite
.
setTextureRect
(
sf
::
IntRect
(
ITEM_WIDTH
*
(
n
%
10
),
ITEM_HEIGHT
*
(
n
/
10
),
ITEM_WIDTH
,
ITEM_HEIGHT
));
consSprite
.
setPosition
(
315
+
37
*
i
,
615
);
app
->
draw
(
consSprite
);
}
}
// 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
>=
7
/*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
);
}
// achievements ?
if
(
!
achievementsQueue
.
empty
())
// && (currentMap->isCleared() || achievementsQueue.front().hasStarted) )
{
if
(
!
achievementsQueue
.
front
().
hasStarted
)
{
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
;
}
}
// show player effects
if
(
isPlayerAlive
)
{
float
x0
=
20
,
y0
=
540
,
yStep
=
-20
;
for
(
int
i
=
0
;
i
<
NB_SPECIAL_STATES
;
i
++
)
{
if
(
(
player
->
isSpecialStateActive
((
enumSpecialState
)
i
)
&&
player
->
getSpecialState
((
enumSpecialState
)
i
).
timer
>
0.35f
)
||
player
->
getSpecialState
((
enumSpecialState
)
i
).
waitUnclear
)
{
std
::
stringstream
oss
;
oss
<<
tools
::
getLabel
(
specialStateToLabel
[
i
])
<<
" : "
;
if
(
player
->
getSpecialState
((
enumSpecialState
)
i
).
waitUnclear
)
{
oss
<<
"waiting"
;
int
n
=
(
int
)(
getAbsolutTime
()
*
3
)
%
3
;
if
(
n
==
0
)
oss
<<
"."
;
else
if
(
n
==
1
)
oss
<<
".."
;
else
oss
<<
"..."
;
}
else
oss
<<
(
int
)(
player
->
getSpecialState
((
enumSpecialState
)
i
).
timer
);
write
(
oss
.
str
(),
12
,
x0
,
y0
,
ALIGN_LEFT
,
specialStateToColor
[
i
],
app
,
0
,
0
);
y0
+=
yStep
;
}
}
}
}
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"
;
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
(
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
();
lastScore
.
divinity
=
player
->
getDivinity
().
divinity
;
lastScore
.
killedBy
=
player
->
getLastHurtingEnemy
();
lastScore
.
time
=
(
int
)
gameTime
;
scores
.
push_back
(
lastScore
);
std
::
sort
(
scores
.
begin
(),
scores
.
end
(),
compareScores
);
saveHiScores
();
// Online
#ifdef ONLINE_MODE
if
(
!
gameFromSaveFile
)
{
sendScoreToServer
();
}
else
{
receiveScoreFromServer
();
}
#endif
// ONLINE_MODE
}
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
;
bool
noMenu
=
false
;
if
(
menuState
==
MenuStateMain
)
menu
=
&
menuMain
;
else
if
(
menuState
==
MenuStateConfig
)
menu
=
&
menuConfig
;
else
if
(
menuState
==
MenuStateFirst
)
menu
=
&
menuFirst
;
else
noMenu
=
true
;
bool
escape
=
false
;
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
(
menuState
==
MenuStateJoystick
)
{
bool
alreadyUsed
=
false
;
int
nbButtons
=
sf
::
Joystick
::
getButtonCount
(
0
);
bool
found
=
false
;
JoystickInputStruct
jInput
;
// Escape = out
if
(
event
.
key
.
code
==
sf
::
Keyboard
::
Escape
)
{
menuState
=
MenuStateConfig
;
saveConfigurationToFile
();
return
;
}
// button pressed ?
for
(
int
i
=
0
;
!
found
&&
i
<
nbButtons
;
i
++
)
{
if
(
sf
::
Joystick
::
isButtonPressed
(
0
,
i
))
{
jInput
.
isButton
=
true
;
jInput
.
value
=
i
;
jInput
.
axis
=
sf
::
Joystick
::
X
;
found
=
true
;
}
}
if
(
!
found
)
{
// axis ?
for
(
int
i
=
sf
::
Joystick
::
X
;
i
<=
sf
::
Joystick
::
PovY
;
i
++
)
{
if
(
sf
::
Joystick
::
hasAxis
(
0
,
(
sf
::
Joystick
::
Axis
)
i
))
{
if
(
sf
::
Joystick
::
getAxisPosition
(
0
,
(
sf
::
Joystick
::
Axis
)
i
)
<
-50
)
{
jInput
.
isButton
=
false
;
jInput
.
value
=
-1
;
jInput
.
axis
=
(
sf
::
Joystick
::
Axis
)
i
;
found
=
true
;
}
else
if
(
sf
::
Joystick
::
getAxisPosition
(
0
,
(
sf
::
Joystick
::
Axis
)
i
)
>
50
)
{
jInput
.
isButton
=
false
;
jInput
.
value
=
1
;
jInput
.
axis
=
(
sf
::
Joystick
::
Axis
)
i
;
found
=
true
;
}
}
}
}
if
(
found
)
{
// already exist ?
for
(
unsigned
int
i
=
0
;
i
<
menuKeyIndex
;
i
++
)
{
if
(
jInput
.
isButton
&&
joystickInput
[
i
].
isButton
&&
joystickInput
[
i
].
value
==
jInput
.
value
)
alreadyUsed
=
true
;
if
(
!
jInput
.
isButton
&&
!
joystickInput
[
i
].
isButton
&&
joystickInput
[
i
].
axis
==
jInput
.
axis
&&
joystickInput
[
i
].
value
==
jInput
.
value
)
alreadyUsed
=
true
;
}
if
(
!
alreadyUsed
)
{
joystickInput
[
menuKeyIndex
]
=
jInput
;
menuKeyIndex
++
;
if
(
menuKeyIndex
==
NumberKeys
)
{
menuState
=
MenuStateConfig
;
saveConfigurationToFile
();
}
}
}
}
else
{
if
(
event
.
type
==
sf
::
Event
::
KeyPressed
)
{
if
(
event
.
key
.
code
==
sf
::
Keyboard
::
F1
)
{
saveScreen
();
}
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
)
{
escape
=
true
;
}
}
}
}
// END EVENT PROCESSING
if
(
menuState
==
MenuStateAchievements
)
{
if
(
isPressing
(
KeyRight
,
true
))
{
if
(
menuAchIndex
%
8
<
7
)
menuAchIndex
++
;
}
else
if
(
isPressing
(
KeyLeft
,
true
))
{
if
(
menuAchIndex
%
8
>
0
)
menuAchIndex
--
;
}
else
if
(
isPressing
(
KeyDown
,
true
))
{
if
(
menuAchIndex
/
8
<
ACHIEV_LINES
)
menuAchIndex
+=
8
;
}
else
if
(
isPressing
(
KeyUp
,
true
))
{
if
(
menuAchIndex
/
8
>
0
)
menuAchIndex
-=
8
;
}
else
if
(
isPressing
(
KeyFireDown
,
true
))
{
if
(
menuAchIndex
/
8
>=
ACHIEV_LINES
)
menuState
=
MenuStateMain
;
}
if
(
escape
)
menuState
=
MenuStateMain
;
}
else
if
(
menuState
==
MenuStateCredits
)
{
if
(
escape
||
isPressing
(
KeyFireDown
,
true
))
menuState
=
MenuStateMain
;
}
else
if
(
menuState
==
MenuStateHiScores
)
{
if
(
escape
||
isPressing
(
KeyFireDown
,
true
))
{
menuScoreIndex
++
;
if
(
menuScoreIndex
>
2
)
{
menuState
=
MenuStateMain
;
if
(
lastScore
.
level
>
0
)
{
lastScore
.
level
=
0
;
lastScore
.
score
=
0
;
playMusic
(
MusicIntro
);
}
}
}
}
if
(
!
noMenu
)
{
if
(
escape
)
{
saveGameData
();
app
->
close
();
}
else
if
(
isPressing
(
KeyDown
,
true
))
{
menu
->
index
++
;
if
(
menu
->
index
==
menu
->
items
.
size
())
menu
->
index
=
0
;
SoundManager
::
getInstance
().
playSound
(
SOUND_SHOT_SELECT
);
}
else
if
(
isPressing
(
KeyUp
,
true
))
{
if
(
menu
->
index
==
0
)
menu
->
index
=
menu
->
items
.
size
()
-
1
;
else
menu
->
index
--
;
SoundManager
::
getInstance
().
playSound
(
SOUND_SHOT_SELECT
);
}
else
if
(
isPressing
(
KeyRight
,
true
))
{
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
(
isPressing
(
KeyLeft
,
true
))
{
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
(
isPressing
(
KeyFireDown
,
true
))
{
switch
(
menu
->
items
[
menu
->
index
].
id
)
{
case
MenuStartNew
:
startNewGame
(
false
,
1
);
remove
(
SAVE_FILE
.
c_str
());
break
;
case
MenuStartOld
:
startNewGame
(
true
,
1
);
break
;
case
MenuKeys
:
menuState
=
MenuStateKeys
;
menuKeyIndex
=
0
;
break
;
case
MenuJoystick
:
if
(
sf
::
Joystick
::
isConnected
(
0
))
{
buildMenu
(
true
);
menuState
=
MenuStateJoystick
;
menuKeyIndex
=
0
;
}
else
buildMenu
(
true
);
break
;
case
MenuCredits
:
menuState
=
MenuStateCredits
;
break
;
case
MenuHiScores
:
menuState
=
MenuStateHiScores
;
#ifdef ONLINE_MODE
menuScoreIndex
=
0
;
#else
menuScoreIndex
=
2
;
#endif
receiveScoreFromServer
();
//loadHiScoresOnline(false);
//loadHiScoresOnline(true);
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();
if
(
menuScoreIndex
==
0
)
renderScores
(
scoresOnline
,
"Best Players (ON-LINE)"
);
else
if
(
menuScoreIndex
==
1
)
renderScores
(
scoresOnlineDay
,
"Best TODAY Scores (ON-LINE)"
);
else
renderScores
(
scores
,
"Best Scores (local)"
);
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
if
(
menuState
==
MenuStateJoystick
)
{
// menu keys
if
(
config
.
configFileExists
())
write
(
tools
::
getLabel
(
"joystick_configuration"
),
18
,
xAlign
,
295
,
ALIGN_LEFT
,
sf
::
Color
(
255
,
255
,
255
,
255
),
app
,
1
,
1
);
else
write
(
tools
::
getLabel
(
"joystick_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
(
"joystick_configuration_insert"
);
else
if
(
menuKeyIndex
>
i
)
oss
<<
"OK"
;
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
),
fairySpriteOffsetY
,
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-2015 - "
<<
" 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
,
620
,
ALIGN_CENTER
,
sf
::
Color
(
255
,
255
,
255
,
255
),
app
,
1
,
1
);
}
else
{
write
(
tools
::
getLabel
(
"config_back"
),
17
,
485
,
620
,
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
<<
"
\n
UNLOCK: "
<<
tools
::
getLabel
(
items
[
achievements
[
achIndex
].
unlock
].
name
);
else
if
(
achievements
[
achIndex
].
unlockType
==
UnlockFunctionality
&&
achievements
[
achIndex
].
unlock
>
-1
)
oss
<<
"
\n
UNLOCK: "
<<
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
::
renderScores
(
std
::
vector
<
StructScore
>
scoresToRender
,
std
::
string
title
)
{
sf
::
Sprite
bgSprite
;
bgSprite
.
setTexture
(
*
ImageManager
::
getInstance
().
getImage
(
IMAGE_HALL_OF_FAME
));
app
->
draw
(
bgSprite
);
// hi-scores-title
write
(
title
,
30
,
485
,
60
,
ALIGN_CENTER
,
sf
::
Color
(
0
,
0
,
0
,
255
),
app
,
0
,
0
);
int
xEquip
=
540
;
//int yEquip = 360;
int
xPlayerLeft
=
60
;
int
xPlayerRight
=
850
;
int
xName
=
260
;
int
xTime
=
420
;
int
xLevel
=
480
;
int
xScore
=
180
;
int
y0
=
130
;
int
yStep
=
50
;
for
(
unsigned
int
i
=
0
;
i
<
scoresToRender
.
size
()
&&
i
<
SCORES_MAX
;
i
++
)
{
sf
::
Color
color
=
sf
::
Color
(
15
,
15
,
15
);
if
(
scoresToRender
[
i
].
score
==
lastScore
.
score
&&
scoresToRender
[
i
].
level
==
lastScore
.
level
&&
scoresToRender
[
i
].
name
==
lastScore
.
name
)
{
int
fade
=
1
+
cosf
(
getAbsolutTime
()
*
8
)
*
63
;
color
=
sf
::
Color
(
255
-
fade
,
128
,
255
-
fade
);
}
// equipment
int
n
=
0
;
for
(
auto
ii
:
scoreEquipement
)
if
(
ii
!=
EQUIP_BOSS_KEY
&&
scoresToRender
[
i
].
equip
[
ii
])
n
++
;
int
dx
=
30
;
if
(
n
>
14
)
dx
=
16
;
else
if
(
n
>
8
)
dx
=
20
;
n
=
0
;
for
(
auto
ii
:
scoreEquipement
)
{
if
(
ii
!=
EQUIP_BOSS_KEY
&&
scoresToRender
[
i
].
equip
[
ii
])
{
sf
::
Sprite
itemSprite
;
itemSprite
.
setTexture
(
*
ImageManager
::
getInstance
().
getImage
(
IMAGE_ITEMS_EQUIP
));
itemSprite
.
setPosition
(
xEquip
+
n
*
dx
,
y0
+
22
+
yStep
*
i
);
itemSprite
.
setTextureRect
(
sf
::
IntRect
((
ii
%
10
)
*
32
,
(
ii
/
10
)
*
32
,
32
,
32
));
app
->
draw
(
itemSprite
);
n
++
;
}
}
if
(
i
<
2
)
renderPlayer
((
i
%
2
==
0
)
?
xPlayerLeft
:
xPlayerRight
,
y0
-
14
+
yStep
*
i
,
scoresToRender
[
i
].
equip
,
scoresToRender
[
i
].
shotType
,
2
,
7
);
else
if
(
i
>=
8
)
renderPlayer
((
i
%
2
==
0
)
?
xPlayerLeft
:
xPlayerRight
,
y0
-
14
+
yStep
*
i
,
scoresToRender
[
i
].
equip
,
scoresToRender
[
i
].
shotType
,
0
,
8
);
else
renderPlayer
((
i
%
2
==
0
)
?
xPlayerLeft
:
xPlayerRight
,
y0
-
14
+
yStep
*
i
,
scoresToRender
[
i
].
equip
,
scoresToRender
[
i
].
shotType
,
1
,
0
);
write
(
scoresToRender
[
i
].
name
,
16
,
xName
,
y0
+
28
+
yStep
*
i
,
ALIGN_LEFT
,
color
,
app
,
0
,
0
);
std
::
stringstream
levelSS
;
levelSS
<<
"lvl "
<<
scoresToRender
[
i
].
level
;
write
(
levelSS
.
str
(),
16
,
xLevel
,
y0
+
28
+
yStep
*
i
,
ALIGN_LEFT
,
color
,
app
,
0
,
0
);
write
(
intToString
(
scoresToRender
[
i
].
score
),
17
,
xScore
,
y0
+
28
+
yStep
*
i
,
ALIGN_LEFT
,
color
,
app
,
0
,
0
);
std
::
stringstream
timeSS
;
if
(
scoresToRender
[
i
].
time
<
100
)
{
timeSS
<<
scoresToRender
[
i
].
time
<<
" s"
;
}
else
{
int
minutes
=
scoresToRender
[
i
].
time
/
60
;
if
(
minutes
<
1
)
minutes
=
1
;
timeSS
<<
minutes
<<
" m"
;
}
write
(
timeSS
.
str
(),
16
,
xTime
,
y0
+
28
+
yStep
*
i
,
ALIGN_LEFT
,
color
,
app
,
0
,
0
);
write
(
intToString
(
scoresToRender
[
i
].
score
),
17
,
xScore
,
y0
+
28
+
yStep
*
i
,
ALIGN_LEFT
,
color
,
app
,
0
,
0
);
}
// retrieving from DB ?
if
(
(
menuScoreIndex
==
0
&&
scoreState
==
ScoreLoading
)
||
(
menuScoreIndex
==
1
&&
((
scoreState
==
ScoreLoading
)
||
(
scoreState
==
ScoreLoadingDay
))))
{
std
::
stringstream
oss
;
oss
<<
"Loading"
;
int
n
=
(
int
)(
getAbsolutTime
()
*
3
)
%
3
;
if
(
n
==
0
)
oss
<<
"."
;
else
if
(
n
==
1
)
oss
<<
".."
;
else
oss
<<
"..."
;
write
(
oss
.
str
(),
15
,
20
,
20
,
ALIGN_LEFT
,
sf
::
Color
(
255
,
255
,
255
,
255
),
app
,
1
,
1
);
}
}
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
),
fairySpriteOffsetY
,
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
;
updateActionKeys
();
switch
(
gameState
)
{
case
gameStateInit
:
case
gameStateKeyConfig
:
case
gameStateJoystickConfig
:
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
->
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
->
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
if
(
currentMap
->
hasNeighbourUp
()
==
1
)
doorEntity
[
0
]
->
openDoor
();
if
(
currentMap
->
hasNeighbourLeft
()
==
2
&&
!
bossRoomOpened
)
currentMap
->
closeDoor
(
0
,
MAP_HEIGHT
/
2
);
else
if
(
currentMap
->
hasNeighbourLeft
()
==
1
)
doorEntity
[
1
]
->
openDoor
();
if
(
currentMap
->
hasNeighbourDown
()
==
2
&&
!
bossRoomOpened
)
currentMap
->
closeDoor
(
MAP_WIDTH
/
2
,
MAP_HEIGHT
-
1
);
else
if
(
currentMap
->
hasNeighbourDown
()
==
1
)
doorEntity
[
2
]
->
openDoor
();
if
(
currentMap
->
hasNeighbourRight
()
==
2
&&
!
bossRoomOpened
)
currentMap
->
closeDoor
(
MAP_WIDTH
-
1
,
MAP_HEIGHT
/
2
);
else
if
(
currentMap
->
hasNeighbourRight
()
==
1
)
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
::
setDoorVisible
(
int
n
)
{
if
(
n
>=
0
&&
n
<
4
)
doorEntity
[
n
]
->
setVisible
(
true
);
}
void
WitchBlastGame
::
checkDoor
(
int
doorId
,
roomTypeEnum
roomCurrent
,
roomTypeEnum
roomNeighbour
,
bool
isNeighbourKnown
)
{
if
(
roomNeighbour
==
roomTypeNULL
)
{
doorEntity
[
doorId
]
->
setVisible
(
false
);
return
;
}
doorEntity
[
doorId
]
->
setVisible
(
isNeighbourKnown
);
doorEntity
[
doorId
]
->
setDoorType
(
currentMap
->
getDoorType
(
doorId
));
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
(),
currentMap
->
hasKnownNeighbour
(
North
,
true
));
checkDoor
(
1
,
currentMap
->
getRoomType
(),
currentMap
->
getNeighbourLeft
(),
currentMap
->
hasKnownNeighbour
(
West
,
true
));
checkDoor
(
2
,
currentMap
->
getRoomType
(),
currentMap
->
getNeighbourDown
(),
currentMap
->
hasKnownNeighbour
(
South
,
true
));
checkDoor
(
3
,
currentMap
->
getRoomType
(),
currentMap
->
getNeighbourRight
(),
currentMap
->
hasKnownNeighbour
(
East
,
true
));
// pet slime
if
(
player
->
isEquiped
(
EQUIP_PET_SLIME
)
&&
currentMap
->
getRoomType
()
!=
roomTypeTemple
)
new
SlimePetEntity
();
// barrels
checkDestroyableObjects
();
}
void
WitchBlastGame
::
refreshMinimap
()
{
for
(
int
j
=
0
;
j
<
FLOOR_HEIGHT
;
j
++
)
for
(
int
i
=
0
;
i
<
FLOOR_WIDTH
;
i
++
)
{
int
roomType
=
currentFloor
->
getRoom
(
i
,
j
);
if
(
roomType
>
roomTypeNULL
&&
currentFloor
->
getMap
(
i
,
j
)
->
isVisited
()
&&
currentFloor
->
getMap
(
i
,
j
)
->
isKnown
())
{
if
(
roomType
==
roomTypeStarting
||
roomType
==
roomTypeChallenge
||
roomType
==
roomTypeBonus
||
roomType
==
roomTypeKey
||
roomType
==
roomTypeBoss
||
roomType
==
roomTypeStandard
||
roomType
==
roomTypeSecret
)
{
if
(
currentFloor
->
getMap
(
i
,
j
)
->
containsHealth
())
miniMap
->
setTile
(
i
,
j
,
5
);
else
miniMap
->
setTile
(
i
,
j
,
roomTypeStandard
);
}
else
{
if
(
roomType
==
roomTypeMerchant
)
miniMap
->
setTile
(
i
,
j
,
3
);
else
if
(
roomType
==
roomTypeTemple
)
miniMap
->
setTile
(
i
,
j
,
7
);
else
if
(
roomType
==
roomTypeSecret
)
miniMap
->
setTile
(
i
,
j
,
8
);
else
miniMap
->
setTile
(
i
,
j
,
currentFloor
->
getRoom
(
i
,
j
));
}
}
else
if
(
roomType
>
roomTypeNULL
&&
currentFloor
->
getMap
(
i
,
j
)
->
isKnown
())
{
switch
(
roomType
)
{
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
roomTypeSecret
:
miniMap
->
setTile
(
i
,
j
,
18
);
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
gameStateJoystickConfig
:
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
);
}
}
// consumable item
if
(
rand
()
%
3
==
0
)
// potion
{
ItemEntity
*
item5
=
new
ItemEntity
(
(
enumItemType
)(
ItemPotion01
+
rand
()
%
NUMBER_UNIDENTIFIED
),
(
MAP_WIDTH
/
2
-
2
)
*
TILE_WIDTH
+
TILE_WIDTH
/
2
,
(
MAP_HEIGHT
/
2
)
*
TILE_HEIGHT
+
5
);
item5
->
setMerchandise
(
true
);
}
else
// scroll
{
ItemEntity
*
item5
=
new
ItemEntity
(
(
enumItemType
)
ItemScrollRevelation
,
(
MAP_WIDTH
/
2
-
2
)
*
TILE_WIDTH
+
TILE_WIDTH
/
2
,
(
MAP_HEIGHT
/
2
)
*
TILE_HEIGHT
+
5
);
item5
->
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
);
new
CyclopsEntity
((
MAP_WIDTH
/
2
)
*
TILE_WIDTH
+
TILE_WIDTH
/
2
+
120
,
(
MAP_HEIGHT
/
2
)
*
TILE_HEIGHT
+
TILE_HEIGHT
/
2
);
new
CyclopsEntity
((
MAP_WIDTH
/
2
)
*
TILE_WIDTH
+
TILE_WIDTH
/
2
-
120
,
(
MAP_HEIGHT
/
2
)
*
TILE_HEIGHT
+
TILE_HEIGHT
/
2
);
}
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
if
(
currentMap
->
getRoomType
()
==
roomTypeSecret
)
{
currentMap
->
generateSecretRoom
();
if
(
rand
()
%
7
>
0
)
{
new
ChestEntity
((
TILE_WIDTH
*
MAP_WIDTH
*
0.5f
+
TILE_WIDTH
),
(
TILE_HEIGHT
*
MAP_HEIGHT
*
0.5f
),
ChestBasic
,
false
);
new
ChestEntity
((
TILE_WIDTH
*
MAP_WIDTH
*
0.5f
-
TILE_WIDTH
),
(
TILE_HEIGHT
*
MAP_HEIGHT
*
0.5f
),
ChestBasic
,
false
);
}
else
{
int
bonusType
=
getRandomEquipItem
(
false
,
false
);
if
(
items
[
FirstEquipItem
+
bonusType
].
familiar
>
FamiliarNone
)
{
new
ChestEntity
(
TILE_WIDTH
*
MAP_WIDTH
*
0.5f
,
TILE_HEIGHT
*
MAP_HEIGHT
*
0.5f
,
ChestFairy
+
items
[
FirstEquipItem
+
bonusType
].
familiar
,
false
);
}
else
{
new
ItemEntity
(
(
enumItemType
)(
FirstEquipItem
+
bonusType
),
TILE_WIDTH
*
MAP_WIDTH
*
0.5f
,
TILE_HEIGHT
*
MAP_HEIGHT
*
0.5f
);
}
}
currentMap
->
setCleared
(
true
);
// secret found text
TextEntity
*
text
=
new
TextEntity
(
tools
::
getLabel
(
"secret_found"
),
25
,
MAP_WIDTH
*
0.5f
*
TILE_WIDTH
,
MAP_HEIGHT
*
0.5f
*
TILE_HEIGHT
+
10.0f
);
text
->
setAlignment
(
ALIGN_CENTER
);
text
->
setLifetime
(
2.5f
);
text
->
setWeight
(
-36.0f
);
text
->
setZ
(
1200
);
text
->
setColor
(
TextEntity
::
COLOR_FADING_WHITE
);
SoundManager
::
getInstance
().
playSound
(
SOUND_SECRET
);
}
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
EnemyTypeSpiderEgg_invocated
:
new
SpiderEggEntity
(
xm
,
ym
,
true
);
break
;
case
EnemyTypeSpiderLittle
:
new
LittleSpiderEntity
(
xm
,
ym
,
SpiderTypeStandard
,
false
);
break
;
case
EnemyTypeSpiderTarantula
:
new
LittleSpiderEntity
(
xm
,
ym
,
SpiderTypeTarantula
,
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
EnemyTypeSausage
:
new
SausageEntity
(
xm
,
ym
,
false
);
break
;
case
EnemyTypeSpiderLittle_invocated
:
new
LittleSpiderEntity
(
xm
,
ym
,
SpiderTypeStandard
,
true
);
break
;
case
EnemyTypeSpiderTarantula_invocated
:
new
LittleSpiderEntity
(
xm
,
ym
,
SpiderTypeTarantula
,
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
;
}
}
}
}
}
bool
WitchBlastGame
::
isAdvanced
()
{
return
(
achievementState
[
AchievementVampire
]
==
AchievementDone
);
}
bool
WitchBlastGame
::
isAdvancedLevel
()
{
if
(
isAdvanced
())
{
return
(
rand
()
%
150
<
getAchievementsPercents
());
}
else
return
false
;
}
void
WitchBlastGame
::
generateStandardMap
()
{
initMonsterArray
();
saveInFight
.
monsters
.
clear
();
generateStandardRoom
(
level
,
isAdvancedLevel
());
}
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
;
if
(
itemOk
&&
presentItems
[
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
];
//addPresentItem(bonusType);
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
;
case
SpellTime
:
item
=
ItemSpellTime
;
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
!=
5
&&
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
*
VolumeModifier
/
100
);
bool
ok
=
false
;
switch
(
musicChoice
)
{
case
MusicDungeon
:
{
int
r
=
currentStandardMusic
;
while
(
r
==
currentStandardMusic
)
r
=
rand
()
%
3
;
switch
(
r
)
{
case
0
:
ok
=
music
.
openFromFile
(
"media/sound/WitchBlastTheme.ogg"
);
break
;
case
1
:
ok
=
music
.
openFromFile
(
"media/sound/SavageLife.ogg"
);
break
;
case
2
:
ok
=
music
.
openFromFile
(
"media/sound/HauntedLighthouse.ogg"
);
break
;
}
currentStandardMusic
=
r
;
}
break
;
case
MusicEnding
:
ok
=
music
.
openFromFile
(
"media/sound/AmbiantMedieval.ogg"
);
break
;
case
MusicBoss
:
ok
=
music
.
openFromFile
(
"media/sound/ShowMeThePower.ogg"
);
break
;
case
MusicChallenge
:
ok
=
music
.
openFromFile
(
"media/sound/HellsFire.ogg"
);
break
;
case
MusicIntro
:
ok
=
music
.
openFromFile
(
"media/sound/WitchBlastTheme.ogg"
);
break
;
}
if
(
ok
)
music
.
play
();
}
void
WitchBlastGame
::
pauseMusic
()
{
music
.
pause
();
}
void
WitchBlastGame
::
resumeMusic
()
{
music
.
play
();
}
void
WitchBlastGame
::
updateMusicVolume
()
{
if
(
music
.
getStatus
()
==
sf
::
Music
::
Playing
)
{
if
(
parameters
.
musicVolume
==
0
)
music
.
stop
();
else
music
.
setVolume
(
parameters
.
musicVolume
*
VolumeModifier
/
100
);
}
else
{
if
(
parameters
.
musicVolume
>
0
)
{
bool
ok
=
music
.
openFromFile
(
"media/sound/wb.ogg"
);
music
.
setVolume
(
parameters
.
musicVolume
*
VolumeModifier
/
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
;
// potions
for
(
auto
it
=
potionMap
.
begin
();
it
!=
potionMap
.
end
();
++
it
)
{
file
<<
it
->
first
<<
" "
<<
it
->
second
.
effect
<<
" "
<<
it
->
second
.
known
<<
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
)
->
isRevealed
()
<<
" "
<<
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
);
file
<<
tile
<<
" "
;
tile
=
currentFloor
->
getMap
(
i
,
j
)
->
getObjectTile
(
k
,
l
);
if
(
tile
==
MAPOBJ_DOOR_CLOSED
)
tile
=
MAPOBJ_DOOR_OPEN
;
file
<<
tile
<<
" "
;
file
<<
currentFloor
->
getMap
(
i
,
j
)
->
getLogicalTile
(
k
,
l
)
<<
" "
;
}
file
<<
std
::
endl
;
}
// style
file
<<
currentFloor
->
getMap
(
i
,
j
)
->
getFloorOffset
()
<<
" "
<<
currentFloor
->
getMap
(
i
,
j
)
->
getWallType
()
<<
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
;
}
// doors
for
(
int
k
=
0
;
k
<
4
;
k
++
)
file
<<
currentFloor
->
getMap
(
i
,
j
)
->
getDoorType
(
k
)
<<
" "
;
file
<<
std
::
endl
;
// random sprite
for
(
int
k
=
0
;
k
<
NB_RANDOM_TILES_IN_ROOM
;
k
++
)
{
file
<<
currentFloor
->
getMap
(
i
,
j
)
->
getRandomTileElement
(
k
).
type
<<
" "
<<
currentFloor
->
getMap
(
i
,
j
)
->
getRandomTileElement
(
k
).
x
<<
" "
<<
currentFloor
->
getMap
(
i
,
j
)
->
getRandomTileElement
(
k
).
y
<<
" "
<<
currentFloor
->
getMap
(
i
,
j
)
->
getRandomTileElement
(
k
).
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
()
<<
" "
<<
player
->
getDonation
()
<<
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
;
for
(
i
=
0
;
i
<
MAX_SLOT_CONSUMABLES
;
i
++
)
{
file
<<
player
->
getConsumable
(
i
)
<<
" "
;
}
file
<<
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
()
{
resetPresentItems
();
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
];
// potions
for
(
i
=
0
;
i
<
NUMBER_UNIDENTIFIED
*
2
;
i
++
)
{
int
source
,
effect
;
bool
known
;
file
>>
source
>>
effect
>>
known
;
addPotionToMap
((
enumItemType
)
source
,
(
enumItemType
)
effect
,
known
);
}
// 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
;
if
(
!
flag
)
iMap
->
setRevealed
(
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
->
setLogicalTile
(
i
,
j
,
(
logicalMapStateEnum
)
n
);
}
}
// style
file
>>
n
;
iMap
->
setFloorOffset
(
n
);
file
>>
n
;
iMap
->
setWallType
(
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
);
}
// doors
for
(
int
index
=
0
;
index
<
4
;
index
++
)
{
file
>>
n
;
iMap
->
setDoorType
(
index
,
(
doorEnum
)
n
);
}
// random sprite
for
(
int
index
=
0
;
index
<
NB_RANDOM_TILES_IN_ROOM
;
index
++
)
{
DungeonMap
::
RandomTileElement
rd
;
file
>>
rd
.
type
;
file
>>
rd
.
x
;
file
>>
rd
.
y
;
file
>>
rd
.
rotation
;
iMap
->
setRandomTileElement
(
index
,
rd
);
}
// random sprite
}
}
// 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
,
donation
;
file
>>
hp
>>
hpMax
>>
gold
>>
donation
;
player
=
new
PlayerEntity
((
TILE_WIDTH
*
MAP_WIDTH
*
0.5f
),
(
TILE_HEIGHT
*
MAP_HEIGHT
*
0.5f
));
player
->
setHp
(
hp
);
player
->
setHpMax
(
hpMax
);
player
->
setGold
(
gold
);
player
->
setDonation
(
donation
);
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
);
for
(
i
=
0
;
i
<
MAX_SLOT_CONSUMABLES
;
i
++
)
{
file
>>
n
;
player
->
setConsumable
(
i
,
n
);
}
// 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
]);
// Joystick
for
(
unsigned
int
i
=
0
;
i
<
NumberKeys
;
i
++
)
{
std
::
stringstream
oss_button
;
oss_button
<<
"joy_"
<<
inputKeyStr
[
i
]
<<
"_button"
;
std
::
stringstream
oss_value
;
oss_value
<<
"joy_"
<<
inputKeyStr
[
i
]
<<
"_value"
;
std
::
stringstream
oss_axis
;
oss_axis
<<
"joy_"
<<
inputKeyStr
[
i
]
<<
"_axis"
;
newMap
[
oss_button
.
str
()]
=
joystickInput
[
i
].
isButton
?
"1"
:
"0"
;
newMap
[
oss_value
.
str
()]
=
intToString
(
joystickInput
[
i
].
value
);
newMap
[
oss_axis
.
str
()]
=
intToString
(
joystickInput
[
i
].
axis
);
}
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
=
80
;
parameters
.
soundVolume
=
80
;
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
;
// Joystick
joystickInput
[
KeyUp
].
isButton
=
false
;
joystickInput
[
KeyUp
].
axis
=
sf
::
Joystick
::
Y
;
joystickInput
[
KeyUp
].
value
=
-1
;
joystickInput
[
KeyDown
].
isButton
=
false
;
joystickInput
[
KeyDown
].
axis
=
sf
::
Joystick
::
Y
;
joystickInput
[
KeyDown
].
value
=
1
;
joystickInput
[
KeyLeft
].
isButton
=
false
;
joystickInput
[
KeyLeft
].
axis
=
sf
::
Joystick
::
X
;
joystickInput
[
KeyLeft
].
value
=
-1
;
joystickInput
[
KeyRight
].
isButton
=
false
;
joystickInput
[
KeyRight
].
axis
=
sf
::
Joystick
::
X
;
joystickInput
[
KeyRight
].
value
=
1
;
for
(
unsigned
int
i
=
KeyFireUp
;
i
<
NumberKeys
;
i
++
)
{
joystickInput
[
i
].
isButton
=
true
;
joystickInput
[
i
].
axis
=
sf
::
Joystick
::
X
;
joystickInput
[
i
].
value
=
i
-
4
;
}
// 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
(
KeyInteract
,
"keyboard_interact"
);
addKey
(
KeyTimeControl
,
"keyboard_time_control"
);
addKey
(
KeyFireSelect
,
"keyboard_fire_select"
);
// Joystick
for
(
unsigned
int
i
=
0
;
i
<
NumberKeys
;
i
++
)
{
std
::
stringstream
oss_button
;
oss_button
<<
"joy_"
<<
inputKeyStr
[
i
]
<<
"_button"
;
std
::
stringstream
oss_value
;
oss_value
<<
"joy_"
<<
inputKeyStr
[
i
]
<<
"_value"
;
std
::
stringstream
oss_axis
;
oss_axis
<<
"joy_"
<<
inputKeyStr
[
i
]
<<
"_axis"
;
int
isButton
=
config
.
findInt
(
oss_button
.
str
());
if
(
isButton
>
-1000
)
joystickInput
[
i
].
isButton
=
isButton
;
int
n
=
config
.
findInt
(
oss_value
.
str
());
if
(
n
>
-1000
)
joystickInput
[
i
].
value
=
n
;
n
=
config
.
findInt
(
oss_axis
.
str
());
if
(
n
>=
sf
::
Joystick
::
Axis
::
X
&&
n
<=
sf
::
Joystick
::
Axis
::
PovY
)
joystickInput
[
i
].
axis
=
(
sf
::
Joystick
::
Axis
)
n
;
}
int
i
=
config
.
findInt
(
"language"
);
if
(
i
>=
0
&&
i
<
NB_LANGUAGES
)
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
itemJoystick
;
itemJoystick
.
label
=
tools
::
getLabel
(
"config_joystick"
);
if
(
sf
::
Joystick
::
isConnected
(
0
))
itemJoystick
.
description
=
tools
::
getLabel
(
"redef_joystick"
);
else
itemJoystick
.
description
=
tools
::
getLabel
(
"joystick_not_found"
);
itemJoystick
.
id
=
MenuJoystick
;
menuConfig
.
items
.
push_back
(
itemJoystick
);
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
==
EnemyTypeGhost
)
{
if
(
globalData
.
killedMonster
[
EnemyTypeGhost
]
>=
75
)
registerAchievement
(
AchievementGhostbuster
);
}
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
);
}
if
(
equip
[
EQUIP_FAIRY_STONE
])
{
sprite
.
setPosition
(
x
-
5
,
y
+
15
);
sprite
.
setTexture
(
*
ImageManager
::
getInstance
().
getImage
(
IMAGE_FAIRY
));
sprite
.
setTextureRect
(
sf
::
IntRect
(
0
,
360
,
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
;
case
EnemyTypeSausage_invocated
:
case
EnemyTypeSausage
:
value
=
"enemy_type_sausage"
;
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
EnemyTypeSpiderTarantula
:
case
EnemyTypeSpiderTarantula_invocated
:
value
=
"enemy_type_spider_tarantula"
;
break
;
case
EnemyTypeSpiderWeb
:
value
=
"enemy_type_spider_web"
;
break
;
case
EnemyTypeNone
:
value
=
"enemy_type_himself"
;
break
;
case
EnemyTypeDestroyable
:
value
=
""
;
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
;
}
std
::
string
WitchBlastGame
::
equipToString
(
bool
equip
[
NUMBER_EQUIP_ITEMS
])
{
std
::
stringstream
oss
;
for
(
int
i
=
0
;
i
<
NUMBER_EQUIP_ITEMS
;
i
++
)
oss
<<
(
equip
[
i
]
?
1
:
0
);
return
oss
.
str
();
}
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
<<
" "
;
file
<<
scores
[
i
].
divinity
<<
" "
;
file
<<
scores
[
i
].
killedBy
<<
" "
;
file
<<
scores
[
i
].
time
<<
" "
;
// 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
;
file
>>
score
.
divinity
;
file
>>
score
.
killedBy
;
file
>>
score
.
time
;
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
;
}
void
WitchBlastGame
::
renderDoors
()
{
for
(
int
i
=
0
;
i
<
4
;
i
++
)
doorEntity
[
i
]
->
renderDoors
(
app
);
}
void
WitchBlastGame
::
resetPresentItems
()
{
for
(
int
i
=
0
;
i
<
NUMBER_EQUIP_ITEMS
;
i
++
)
presentItems
[
i
]
=
false
;
}
bool
WitchBlastGame
::
isPresentItem
(
int
n
)
{
if
(
n
>=
0
&&
n
<
NUMBER_EQUIP_ITEMS
)
return
presentItems
[
n
];
else
return
false
;
}
void
WitchBlastGame
::
addPresentItem
(
int
n
)
{
if
(
n
>=
0
&&
n
<
NUMBER_EQUIP_ITEMS
)
presentItems
[
n
]
=
true
;
}
bool
WitchBlastGame
::
isPressing
(
inputKeyEnum
k
,
bool
oneShot
)
{
return
(
actionKey
[
k
].
isPressed
&&
(
!
oneShot
||
actionKey
[
k
].
isTriggered
));
}
bool
WitchBlastGame
::
getPressingState
(
inputKeyEnum
k
)
{
// arrows in menu
if
(
gameState
!=
gameStatePlaying
||
player
->
isDead
())
{
if
(
k
==
KeyLeft
&&
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
Left
))
return
true
;
if
(
k
==
KeyRight
&&
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
Right
))
return
true
;
if
(
k
==
KeyUp
&&
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
Up
))
return
true
;
if
(
k
==
KeyDown
&&
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
Down
))
return
true
;
if
(
k
==
KeyFireDown
&&
sf
::
Keyboard
::
isKeyPressed
(
sf
::
Keyboard
::
Return
))
return
true
;
}
// keyboard
if
(
sf
::
Keyboard
::
isKeyPressed
(
input
[
k
]))
return
true
;
if
(
!
sf
::
Joystick
::
isConnected
(
0
))
return
false
;
// joystick
if
(
joystickInput
[
k
].
isButton
)
{
// button
if
(
joystickInput
[
k
].
value
>=
0
)
if
(
sf
::
Joystick
::
isButtonPressed
(
0
,
joystickInput
[
k
].
value
))
return
true
;
}
else
{
// axis
if
(
joystickInput
[
k
].
value
<
0
&&
sf
::
Joystick
::
getAxisPosition
(
0
,
joystickInput
[
k
].
axis
)
<
-40
)
return
true
;
else
if
(
joystickInput
[
k
].
value
>
0
&&
sf
::
Joystick
::
getAxisPosition
(
0
,
joystickInput
[
k
].
axis
)
>
40
)
return
true
;
}
return
false
;
}
void
WitchBlastGame
::
updateActionKeys
()
{
for
(
unsigned
int
i
=
0
;
i
<
NumberKeys
;
i
++
)
{
bool
oldState
=
actionKey
[
i
].
isPressed
;
actionKey
[
i
].
isPressed
=
getPressingState
((
inputKeyEnum
)
i
);
actionKey
[
i
].
isTriggered
=
actionKey
[
i
].
isPressed
&&
!
oldState
;
}
}
void
WitchBlastGame
::
sendScoreToServer
()
{
if
(
sendScoreThread
.
joinable
())
sendScoreThread
.
join
();
sendScoreThread
=
std
::
thread
(
&
WitchBlastGame
::
sendScoreToServerThread
,
this
);
receiveScoreFromServer
();
}
void
WitchBlastGame
::
sendScoreToServerThread
()
{
#ifdef ONLINE_MODE
sendScore
(
lastScore
.
score
,
lastScore
.
level
,
lastScore
.
name
,
equipToString
(
lastScore
.
equip
),
lastScore
.
shotType
,
lastScore
.
divinity
,
lastScore
.
killedBy
,
lastScore
.
time
,
SCORE_VERSION
);
#endif
}
void
WitchBlastGame
::
receiveScoreFromServer
()
{
#ifdef ONLINE_MODE
scoreState
=
ScoreLoading
;
if
(
receiveScoreThread
.
joinable
())
receiveScoreThread
.
join
();
receiveScoreThread
=
std
::
thread
(
&
WitchBlastGame
::
receiveScoreFromServerThread
,
this
);
#endif
}
void
WitchBlastGame
::
receiveScoreFromServerThread
()
{
if
(
sendScoreThread
.
joinable
())
sendScoreThread
.
join
();
loadHiScoresOnline
(
false
);
scoreState
=
ScoreLoadingDay
;
loadHiScoresOnline
(
true
);
scoreState
=
ScoreOK
;
}
void
WitchBlastGame
::
loadHiScoresOnline
(
bool
fromDayOnly
)
{
#ifdef ONLINE_MODE
std
::
vector
<
StructScore
>
scoresTemp
;
std
::
vector
<
std
::
string
>
receivedScores
=
receiveScores
(
fromDayOnly
);
int
nbParameters
=
8
;
if
(
receivedScores
.
size
()
>
0
&&
receivedScores
.
size
()
%
nbParameters
==
0
&&
receivedScores
.
size
()
/
nbParameters
<=
10
)
{
int
nbScores
=
receivedScores
.
size
()
/
nbParameters
;
for
(
int
i
=
0
;
i
<
nbScores
;
i
++
)
{
StructScore
score
;
std
::
istringstream
scoreStr
(
receivedScores
[
i
*
nbParameters
]);
scoreStr
>>
score
.
score
;
score
.
name
=
receivedScores
[
i
*
nbParameters
+
1
];
std
::
istringstream
levelStr
(
receivedScores
[
i
*
nbParameters
+
2
]);
levelStr
>>
score
.
level
;
for
(
int
j
=
0
;
j
<
NUMBER_EQUIP_ITEMS
;
j
++
)
{
score
.
equip
[
j
]
=
(
receivedScores
[
i
*
nbParameters
+
3
])[
j
]
==
'1'
;
}
std
::
istringstream
shotStr
(
receivedScores
[
i
*
nbParameters
+
4
]);
shotStr
>>
score
.
shotType
;
std
::
istringstream
divStr
(
receivedScores
[
i
*
nbParameters
+
5
]);
divStr
>>
score
.
divinity
;
std
::
istringstream
killStr
(
receivedScores
[
i
*
nbParameters
+
6
]);
killStr
>>
score
.
killedBy
;
std
::
istringstream
timeStr
(
receivedScores
[
i
*
nbParameters
+
7
]);
timeStr
>>
score
.
time
;
scoresTemp
.
push_back
(
score
);
}
if
(
fromDayOnly
)
{
scoresOnlineDay
.
clear
();
scoresOnlineDay
=
scoresTemp
;
}
else
{
scoresOnline
.
clear
();
scoresOnline
=
scoresTemp
;
}
}
#endif
}
void
WitchBlastGame
::
checkDestroyableObjects
()
{
for
(
int
i
=
0
;
i
<
MAP_WIDTH
;
i
++
)
for
(
int
j
=
0
;
j
<
MAP_HEIGHT
;
j
++
)
{
if
(
currentMap
->
getObjectTile
(
i
,
j
)
>=
MAPOBJ_BARREL
/* && currentMap->getObjectTile(i, j) < MAPOBJ_BARREL_EXPL + 3*/
)
{
new
ObstacleEntity
(
i
*
TILE_WIDTH
+
TILE_WIDTH
/
2
,
j
*
TILE_HEIGHT
+
TILE_HEIGHT
/
2
,
currentMap
->
getObjectTile
(
i
,
j
));
}
}
}
void
WitchBlastGame
::
randomizePotionMap
()
{
potionMap
.
clear
();
std
::
vector
<
int
>
potionEffect
;
for
(
int
i
=
0
;
i
<
NUMBER_UNIDENTIFIED
;
i
++
)
potionEffect
.
push_back
(
i
);
for
(
int
i
=
0
;
i
<
NUMBER_UNIDENTIFIED
;
i
++
)
{
int
r
=
rand
()
%
potionEffect
.
size
();
addPotionToMap
((
enumItemType
)(
ItemPotion01
+
i
),
(
enumItemType
)(
ItemPotionHealth
+
potionEffect
[
r
]),
false
);
potionEffect
.
erase
(
potionEffect
.
begin
()
+
r
);
}
}
void
WitchBlastGame
::
acquireAlchemyBook
()
{
for
(
int
i
=
0
;
i
<
NUMBER_UNIDENTIFIED
;
i
++
)
{
if
(
rand
()
%
3
>
0
)
{
enumItemType
potion
=
(
enumItemType
)(
ItemPotion01
+
i
);
if
(
!
potionEffectKnown
(
potion
))
setPotionToKnown
(
potion
);
}
}
// drop potion
ItemEntity
*
potionItem
=
new
ItemEntity
(
(
enumItemType
)(
ItemPotion01
+
rand
()
%
NUMBER_UNIDENTIFIED
),
player
->
getX
(),
player
->
getY
());
potionItem
->
setVelocity
(
Vector2D
(
100.0f
+
rand
()
%
250
));
potionItem
->
setViscosity
(
0.96f
);
}
void
WitchBlastGame
::
addPotionToMap
(
enumItemType
source
,
enumItemType
effect
,
bool
known
)
{
potionMap
[
source
]
=
structPotionMap
{
effect
,
known
};
potionMap
[
effect
]
=
structPotionMap
{
source
,
known
};
}
enumItemType
WitchBlastGame
::
getPotion
(
enumItemType
source
)
{
return
potionMap
[
source
].
effect
;
}
bool
WitchBlastGame
::
potionEffectKnown
(
enumItemType
source
)
{
return
potionMap
[
source
].
known
;
}
void
WitchBlastGame
::
setPotionToKnown
(
enumItemType
source
)
{
potionMap
[
source
].
known
=
true
;
potionMap
[
potionMap
[
source
].
effect
].
known
=
true
;
// message
if
(
messagesQueue
.
empty
())
SoundManager
::
getInstance
().
playSound
(
SOUND_MESSAGE
);
messageStruct
msg
=
getMessage
(
MsgInfoPotionId
);
std
::
stringstream
ss
;
ss
<<
msg
.
message
[
1
];
ss
<<
" "
;
ss
<<
tools
::
getLabel
(
items
[
getPotion
(
source
)].
name
);
msg
.
message
[
1
]
=
ss
.
str
();
messagesQueue
.
push
(
msg
);
}
void
WitchBlastGame
::
forgetPotions
()
{
for
(
int
i
=
ItemPotion01
;
i
<
FirstEquipItem
;
i
++
)
{
potionMap
[(
enumItemType
)
i
].
known
=
false
;
potionMap
[
potionMap
[(
enumItemType
)
i
].
effect
].
known
=
false
;
}
}
void
WitchBlastGame
::
forget
()
{
// forget map
if
(
!
player
->
isEquiped
(
EQUIP_FLOOR_MAP
))
{
currentFloor
->
forget
(
floorX
,
floorY
);
refreshMinimap
();
}
// forget potions
if
(
!
player
->
isEquiped
(
EQUIP_BOOK_ALCHEMY
))
{
forgetPotions
();
}
}
WitchBlastGame
&
game
()
{
return
*
gameptr
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sun, Nov 15, 7:22 AM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
148845
Default Alt Text
WitchBlastGame.cpp (212 KB)
Attached To
Mode
R78 witchblast
Attached
Detach File
Event Timeline