Page Menu
Home
Phabricator (Chris)
Search
Configure Global Search
Log In
Files
F628662
Player.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
24 KB
Referenced Files
None
Subscribers
None
Player.cpp
View Options
/****************************************************************************
** Copyright (C) 2011 Luka Horvat <redreaper132 at gmail.com>
** Copyright (C) 2011 Edward Lii <edward_iii at myway.com>
** Copyright (C) 2011 O. Bahri Gordebak <gordebak at gmail.com>
**
**
** This file may be used under the terms of the GNU General Public
** License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of
** this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
**
****************************************************************************/
#include
"Player.h"
#include
"Game.h"
#include
"Functions.h"
#include
"FileManager.h"
#include
"Globals.h"
#include
"Objects.h"
#include
<iostream>
#include
<SDL/SDL_mixer.h>
#include
<SDL/SDL.h>
#include
<SDL/SDL_ttf.h>
using
namespace
std
;
Player
::
Player
(
Game
*
objParent
)
:
xVelBase
(
0
),
yVelBase
(
0
),
objParent
(
objParent
){
//Set the dimensions of the player.
//The size of the player is 21x40.
box
.
x
=
0
;
box
.
y
=
0
;
box
.
w
=
21
;
box
.
h
=
40
;
//Set his velocity to zero.
xVel
=
0
;
yVel
=
0
;
//Set the start position.
fx
=
0
;
fy
=
0
;
//Check if sound is enabled.
if
(
getSettings
()
->
getBoolValue
(
"sound"
)
==
true
){
//It is so load the sounds.
jumpSound
=
Mix_LoadWAV
((
getDataPath
()
+
"sfx/jump.wav"
).
c_str
());
hitSound
=
Mix_LoadWAV
((
getDataPath
()
+
"sfx/hit.wav"
).
c_str
());
saveSound
=
Mix_LoadWAV
((
getDataPath
()
+
"sfx/checkpoint.wav"
).
c_str
());
swapSound
=
Mix_LoadWAV
((
getDataPath
()
+
"sfx/swap.wav"
).
c_str
());
toggleSound
=
Mix_LoadWAV
((
getDataPath
()
+
"sfx/toggle.wav"
).
c_str
());
}
//Set some default values.
inAir
=
true
;
isJump
=
false
;
onGround
=
true
;
shadowCall
=
false
;
shadow
=
false
;
canMove
=
true
;
holdingOther
=
false
;
dead
=
false
;
record
=
false
;
//Some default values for animation variables.
frame
=
0
;
animation
=
0
;
direction
=
0
;
jumpTime
=
0
;
state
=
0
;
//xVelSaved is used to store if there's a state saved or not.
xVelSaved
=
0x80000000
;
}
Player
::~
Player
(){
//We only need to clean up the sounds if they were loaded.
if
(
getSettings
()
->
getBoolValue
(
"sound"
)
==
true
){
Mix_FreeChunk
(
jumpSound
);
Mix_FreeChunk
(
hitSound
);
Mix_FreeChunk
(
saveSound
);
Mix_FreeChunk
(
swapSound
);
Mix_FreeChunk
(
toggleSound
);
}
}
void
Player
::
handleInput
(
class
Shadow
*
shadow
){
//Get the current keystate.
Uint8
*
keyState
=
SDL_GetKeyState
(
NULL
);
//Reset horizontal velocity.
xVel
=
0
;
if
(
keyState
[
SDLK_RIGHT
]){
//Walking to the right.
xVel
+=
7
;
}
if
(
keyState
[
SDLK_LEFT
]){
//Walking to the left.
xVel
-=
7
;
}
//Check if a key has been released.
if
(
event
.
type
==
SDL_KEYUP
){
//It has so downKeyPressed can't be true.
downKeyPressed
=
false
;
}
//Check if a key is pressed (down).
if
(
event
.
type
==
SDL_KEYDOWN
){
//Switch which key is pressed.
switch
(
event
.
key
.
keysym
.
sym
){
case
SDLK_UP
:
//The up key, if we aren't in the air we start jumping.
if
(
inAir
==
false
){
isJump
=
true
;
}
break
;
case
SDLK_SPACE
:
//Start recording or stop, depending on the recording state.
if
(
record
==
false
){
//We start recording.
if
(
shadow
->
called
==
true
){
//The shadow is still busy so first stop him before we can start recording.
shadowCall
=
false
;
shadow
->
called
=
false
;
shadow
->
playerButton
.
clear
();
}
else
if
(
!
dead
){
//The shadow isn't moving and we aren't dead so start recording.
record
=
true
;
}
}
else
{
//The player is recording so stop recording and call the shadow.
record
=
false
;
shadowCall
=
true
;
}
break
;
case
SDLK_DOWN
:
//Downkey is pressed.
downKeyPressed
=
true
;
break
;
case
SDLK_F2
:
//F2 only works in the level editor.
if
(
!
(
dead
||
shadow
->
dead
)
&&
stateID
==
STATE_LEVEL_EDITOR
){
//Save the state.
if
(
objParent
)
objParent
->
saveState
();
}
break
;
case
SDLK_F3
:
//F3 is used to load the last state.
if
(
objParent
)
objParent
->
loadState
();
break
;
case
SDLK_F4
:
//F4 will swap the player and the shadow, but only in the level editor.
if
(
!
(
dead
||
shadow
->
dead
)
&&
stateID
==
STATE_LEVEL_EDITOR
){
swapState
(
shadow
);
}
break
;
case
SDLK_F12
:
//F12 is suicide and only works in the leveleditor.
if
(
stateID
==
STATE_LEVEL_EDITOR
){
die
();
shadow
->
die
();
}
default
:
break
;
}
}
}
void
Player
::
setPosition
(
int
x
,
int
y
){
box
.
x
=
x
;
box
.
y
=
y
;
}
void
Player
::
move
(
vector
<
GameObject
*>
&
levelObjects
){
//Pointer to a checkpoint.
GameObject
*
objCheckPoint
=
NULL
;
//Pointer to a swap.
GameObject
*
objSwap
=
NULL
;
//Boolean if the player can teleport.
bool
canTeleport
=
true
;
//Set the object the player is currently standing to NULL.
objCurrentStand
=
NULL
;
//Check if the player is still alive.
if
(
dead
==
false
){
//Add gravity
if
(
inAir
==
true
){
yVel
+=
1
;
//Cap fall speed to 13.
if
(
yVel
>
13
){
yVel
=
13
;
}
}
//Check if the player can move.
if
(
canMove
==
true
){
//Check if the player is moving or not.
if
(
xVel
>
0
){
direction
=
0
;
onGround
=
false
;
}
else
if
(
xVel
<
0
){
direction
=
1
;
onGround
=
false
;
}
else
if
(
xVel
==
0
){
onGround
=
true
;
}
//Move the player.
box
.
x
+=
xVel
;
//Loop through the levelobjects.
for
(
unsigned
int
o
=
0
;
o
<
levelObjects
.
size
();
o
++
){
//Check if the player can walk on the object.
if
(
levelObjects
[
o
]
->
queryProperties
(
GameObjectProperty_PlayerCanWalkOn
,
this
)){
//Get the collision box of the levelobject.
SDL_Rect
r
=
levelObjects
[
o
]
->
getBox
();
//Check collision with the player.
if
(
checkCollision
(
box
,
r
)){
//We have collision, get the velocity of the box.
SDL_Rect
v
=
levelObjects
[
o
]
->
getBox
(
BoxType_Delta
);
//Check on which side of the box the player is.
if
(
box
.
x
+
box
.
w
/
2
<=
r
.
x
+
r
.
w
/
2
){
if
(
xVel
+
xVelBase
>
v
.
x
){
if
(
box
.
x
>
r
.
x
-
box
.
w
)
box
.
x
=
r
.
x
-
box
.
w
;
}
}
else
{
if
(
xVel
+
xVelBase
<
v
.
x
){
if
(
box
.
x
<
r
.
x
+
r
.
w
)
box
.
x
=
r
.
x
+
r
.
w
;
}
}
}
}
}
}
//Now apply the yVel. (gravity, jumping, etc..)
box
.
y
+=
yVel
;
//Pointer to the object the player standed on.
GameObject
*
lastStand
=
NULL
;
//???
inAir
=
true
;
canMove
=
true
;
//Loop through all the levelObjects.
for
(
unsigned
int
o
=
0
;
o
<
levelObjects
.
size
();
o
++
){
//Check if the object is solid.
if
(
levelObjects
[
o
]
->
queryProperties
(
GameObjectProperty_PlayerCanWalkOn
,
this
)){
SDL_Rect
r
=
levelObjects
[
o
]
->
getBox
();
if
(
checkCollision
(
r
,
box
)
==
true
){
//TODO:fix some bug
SDL_Rect
v
=
levelObjects
[
o
]
->
getBox
(
BoxType_Delta
);
if
(
box
.
y
+
box
.
h
/
2
<=
r
.
y
+
r
.
h
/
2
){
if
(
yVel
>=
v
.
y
||
yVel
>=
0
){
inAir
=
false
;
box
.
y
=
r
.
y
-
box
.
h
;
yVel
=
1
;
//???
lastStand
=
levelObjects
[
o
];
lastStand
->
onEvent
(
GameObjectEvent_PlayerIsOn
);
}
}
else
{
if
(
yVel
<=
v
.
y
+
1
){
yVel
=
v
.
y
>
0
?
v
.
y
:
0
;
if
(
box
.
y
<
r
.
y
+
r
.
h
)
box
.
y
=
r
.
y
+
r
.
h
;
}
}
}
}
//Check if the object is a checkpoint.
if
(
levelObjects
[
o
]
->
type
==
TYPE_CHECKPOINT
&&
checkCollision
(
box
,
levelObjects
[
o
]
->
getBox
())){
//If we're not the shadow set the gameTip to Checkpoint.
if
(
!
shadow
&&
objParent
!=
NULL
)
objParent
->
gameTipIndex
=
TYPE_CHECKPOINT
;
//And let objCheckPoint point to this object.
objCheckPoint
=
levelObjects
[
o
];
}
//Check if the object is a swap.
if
(
levelObjects
[
o
]
->
type
==
TYPE_SWAP
&&
checkCollision
(
box
,
levelObjects
[
o
]
->
getBox
())){
//If we're not the shadow set the gameTip to swap.
if
(
!
shadow
&&
objParent
!=
NULL
)
objParent
->
gameTipIndex
=
TYPE_SWAP
;
//And let objSwap point to this object.
objSwap
=
levelObjects
[
o
];
}
//Check if the object is an exit.
//This doesn't work if the state is Level editor.
if
(
levelObjects
[
o
]
->
type
==
TYPE_EXIT
&&
stateID
!=
STATE_LEVEL_EDITOR
&&
checkCollision
(
box
,
levelObjects
[
o
]
->
getBox
())){
//Goto the next level.
levels
.
nextLevel
();
//Check if the level exists.
if
(
levels
.
getLevel
()
<
levels
.
getLevelCount
()){
//It does so unlock the levels.
levels
.
setLocked
(
levels
.
getLevel
());
//And enter the GameState to start the new level.
setNextState
(
STATE_GAME
);
}
else
{
//Show the congratulations messagebox.
if
(
!
levels
.
congratulationText
.
empty
()){
msgBox
(
levels
.
congratulationText
,
MsgBoxOKOnly
,
"Congratulations"
);
}
else
{
msgBox
(
"You have finished the levelpack!"
,
MsgBoxOKOnly
,
"Congratulations"
);
}
//Go to the level select menu.
setNextState
(
STATE_LEVEL_SELECT
);
}
}
//Check if the object is a portal.
if
(
levelObjects
[
o
]
->
type
==
TYPE_PORTAL
&&
checkCollision
(
box
,
levelObjects
[
o
]
->
getBox
())){
//Check if the teleport id isn't empty.
if
((
dynamic_cast
<
Block
*>
(
levelObjects
[
o
]))
->
id
.
empty
()){
cerr
<<
"Warning: Invalid teleport id!"
<<
endl
;
canTeleport
=
false
;
}
//If we're not the shadow set the gameTip to portal.
if
(
!
shadow
&&
objParent
!=
NULL
)
objParent
->
gameTipIndex
=
TYPE_PORTAL
;
//Check if we can teleport and should (downkey -or- auto).
if
(
canTeleport
&&
(
downKeyPressed
||
(
levelObjects
[
o
]
->
queryProperties
(
GameObjectProperty_Flags
,
this
)
&
1
))){
canTeleport
=
false
;
if
(
downKeyPressed
||
levelObjects
[
o
]
!=
objLastTeleport
){
downKeyPressed
=
false
;
//Loop the levelobjects again to find the destination.
for
(
unsigned
int
oo
=
o
+
1
;;){
//We started at our index+1.
//Meaning that if we reach the end of the vector then we need to start at the beginning.
if
(
oo
>=
levelObjects
.
size
())
oo
-=
(
int
)
levelObjects
.
size
();
//It also means that if we reach the same index we need to stop.
if
(
oo
==
o
)
break
;
//Check if the second (oo) object is a portal.
if
(
levelObjects
[
oo
]
->
type
==
TYPE_PORTAL
){
//Check the id against the destination of the first portal.
if
((
dynamic_cast
<
Block
*>
(
levelObjects
[
o
]))
->
destination
==
(
dynamic_cast
<
Block
*>
(
levelObjects
[
oo
]))
->
id
){
//Call the event.
levelObjects
[
o
]
->
onEvent
(
GameObjectEvent_OnToggle
);
objLastTeleport
=
levelObjects
[
oo
];
//Get the destination location and teleport the player.
SDL_Rect
r
=
levelObjects
[
oo
]
->
getBox
();
box
.
x
=
r
.
x
+
5
;
box
.
y
=
r
.
y
+
2
;
//Check if music/sound is enabled.
if
(
getSettings
()
->
getBoolValue
(
"sound"
)){
Mix_PlayChannel
(
-1
,
swapSound
,
0
);
}
break
;
}
}
//Increase oo.
oo
++
;
}
}
}
}
//Check if the object is a switch.
if
(
levelObjects
[
o
]
->
type
==
TYPE_SWITCH
&&
checkCollision
(
box
,
levelObjects
[
o
]
->
getBox
())){
//If we're not the shadow set the gameTip to switch.
if
(
!
shadow
&&
objParent
!=
NULL
)
objParent
->
gameTipIndex
=
TYPE_SWITCH
;
//If the down key is pressed then invoke an event.
if
(
downKeyPressed
){
//Play the animation.
levelObjects
[
o
]
->
playAnimation
(
1
);
//Check if sound is enabled, if so play the toggle sound.
if
(
getSettings
()
->
getBoolValue
(
"sound"
)
==
true
){
Mix_PlayChannel
(
-1
,
toggleSound
,
0
);
}
if
(
objParent
!=
NULL
){
//Make sure that the id isn't emtpy.
if
(
!
(
dynamic_cast
<
Block
*>
(
levelObjects
[
o
]))
->
id
.
empty
()){
objParent
->
broadcastObjectEvent
(
0x10000
|
(
levelObjects
[
o
]
->
queryProperties
(
GameObjectProperty_Flags
,
this
)
&
3
),
-1
,(
dynamic_cast
<
Block
*>
(
levelObjects
[
o
]))
->
id
.
c_str
());
}
else
{
cerr
<<
"Warning: invalid switch id!"
<<
endl
;
}
}
}
}
//Check if the object is a notification block.
if
(
levelObjects
[
o
]
->
type
==
TYPE_NOTIFICATION_BLOCK
&&
checkCollision
(
box
,
levelObjects
[
o
]
->
getBox
())){
//If we're not the shadow set the gameTip to notification block.
if
(
!
shadow
&&
objParent
!=
NULL
)
objParent
->
gameTipIndex
=
TYPE_NOTIFICATION_BLOCK
;
//If the down key is pressed then invoke an event.
if
(
downKeyPressed
==
true
)
(
dynamic_cast
<
Block
*>
(
levelObjects
[
o
]))
->
onEvent
(
GameObjectEvent_OnSwitchOn
);
}
//Check if the object is deadly.
if
(
levelObjects
[
o
]
->
queryProperties
(
GameObjectProperty_IsSpikes
,
this
)){
//It is so get the collision box.
SDL_Rect
r
=
levelObjects
[
o
]
->
getBox
();
//TODO: pixel-accuracy hit test.
//For now we shrink the box.
r
.
x
+=
2
;
r
.
y
+=
2
;
r
.
w
-=
4
;
r
.
h
-=
4
;
//Check collision, if the player collides then let him die.
if
(
checkCollision
(
box
,
r
))
die
();
}
}
//Check if the player fell of the level.
if
(
box
.
y
>
LEVEL_HEIGHT
)
die
();
//Check if the player changed blocks, meaning stepped onto a block.
objCurrentStand
=
lastStand
;
if
(
lastStand
!=
objLastStand
){
objLastStand
=
lastStand
;
if
(
lastStand
){
//Call the walk on event of the laststand.
lastStand
->
onEvent
(
GameObjectEvent_PlayerWalkOn
);
//Bugfix for Fragile blocks.
if
(
lastStand
->
type
==
TYPE_FRAGILE
&&
!
lastStand
->
queryProperties
(
GameObjectProperty_PlayerCanWalkOn
,
this
)){
inAir
=
true
;
onGround
=
false
;
isJump
=
false
;
}
}
}
//Check if the player can teleport.
if
(
canTeleport
)
objLastTeleport
=
NULL
;
//Check the checkpoint pointer only if the downkey is pressed.
if
(
objParent
!=
NULL
&&
downKeyPressed
&&
objCheckPoint
!=
NULL
){
//Checkpoint thus save the state.
if
(
objParent
->
saveState
())
objParent
->
objLastCheckPoint
=
objCheckPoint
;
}
//Check the swap pointer only if the down key is pressed.
if
(
objSwap
!=
NULL
&&
downKeyPressed
&&
objParent
!=
NULL
){
if
(
shadow
){
if
(
!
(
dead
||
objParent
->
player
.
dead
)){
objParent
->
player
.
swapState
(
this
);
objSwap
->
playAnimation
(
1
);
}
}
else
{
if
(
!
(
dead
||
objParent
->
shadow
.
dead
)){
swapState
(
&
objParent
->
shadow
);
objSwap
->
playAnimation
(
1
);
}
}
}
}
//Finally we reset some stuff.
downKeyPressed
=
false
;
xVelBase
=
0
;
yVelBase
=
0
;
}
void
Player
::
jump
(){
//Check if the player is dead or not.
if
(
dead
==
true
){
//The player can't jump if he's dead.
isJump
=
false
;
}
//Check if the player can jump.
if
(
isJump
==
true
&&
inAir
==
false
){
//Set the jump velocity.
yVel
=
-13
;
inAir
=
true
;
isJump
=
false
;
jumpTime
++
;
//Check if sound is enabled, if so play the jump sound.
if
(
getSettings
()
->
getBoolValue
(
"sound"
)
==
true
){
Mix_PlayChannel
(
-1
,
jumpSound
,
0
);
}
}
}
void
Player
::
show
(){
//Check if we should render the recorded line.
//Only do this when we're recording and we're not the shadow.
if
(
shadow
==
false
&&
record
==
true
){
//FIXME: Adding an entry not in update but in render?
line
.
push_back
(
SDL_Rect
());
line
[
line
.
size
()
-1
].
x
=
box
.
x
+
11
;
line
[
line
.
size
()
-1
].
y
=
box
.
y
+
20
;
//Loop through the line dots and draw them.
for
(
int
l
=
0
;
l
<
(
signed
)
line
.
size
();
l
++
){
appearance
.
drawState
(
"line"
,
screen
,
line
[
l
].
x
-
camera
.
x
,
line
[
l
].
y
-
camera
.
y
,
NULL
);
}
}
//Make sure the player is still alive.
if
(
dead
==
false
){
//Update the frame.
frame
++
;
if
(
frame
>=
5
){
//Frame is higher or equal to five thus increase animation.
animation
++
;
if
(
animation
>=
2
){
//Animation is two or higher but there are only two frames.
//So we set it to the first frame.
animation
=
0
;
}
//And reset frame.
frame
=
0
;
}
//Check if the player is in the air.
if
(
inAir
==
false
){
//Check which direction.
if
(
direction
==
0
){
//Check if onGround is true or not.
if
(
onGround
==
false
){
//It isn't so the player is walking.
char
state
[
64
];
sprintf
(
state
,
"%s%d"
,
"walkright"
,
animation
);
appearance
.
drawState
(
state
,
screen
,
box
.
x
-
camera
.
x
,
box
.
y
-
camera
.
y
,
NULL
);
}
else
{
//Check if the player is holding the other.
if
(
holdingOther
==
true
){
appearance
.
drawState
(
"holding"
,
screen
,
box
.
x
-
camera
.
x
,
box
.
y
-
camera
.
y
,
NULL
);
}
else
{
//Not walking and nothing holding the other thus standing still.
appearance
.
drawState
(
"standright"
,
screen
,
box
.
x
-
camera
.
x
,
box
.
y
-
camera
.
y
,
NULL
);
}
}
}
else
if
(
direction
==
1
){
//Check if onGround is true or not.
if
(
onGround
==
false
){
//It isn't so the player is walking.
char
state
[
64
];
sprintf
(
state
,
"%s%d"
,
"walkleft"
,
animation
);
appearance
.
drawState
(
state
,
screen
,
box
.
x
-
camera
.
x
,
box
.
y
-
camera
.
y
,
NULL
);
}
else
{
//Check if the player is holding the other.
if
(
holdingOther
==
true
){
appearance
.
drawState
(
"holding"
,
screen
,
box
.
x
-
camera
.
x
,
box
.
y
-
camera
.
y
,
NULL
);
}
else
{
//Not walking and nothing holding the other thus standing still.
appearance
.
drawState
(
"standleft"
,
screen
,
box
.
x
-
camera
.
x
,
box
.
y
-
camera
.
y
,
NULL
);
}
}
}
}
else
{
//The player is in the air so check which direction.
if
(
direction
==
0
){
//We're going right.
appearance
.
drawState
(
"jumpright"
,
screen
,
box
.
x
-
camera
.
x
,
box
.
y
-
camera
.
y
,
NULL
);
}
if
(
direction
==
1
){
//Left.
appearance
.
drawState
(
"jumpleft"
,
screen
,
box
.
x
-
camera
.
x
,
box
.
y
-
camera
.
y
,
NULL
);
}
}
}
}
void
Player
::
shadowSetState
(){
//Only add an entry if the player is recording.
if
(
record
){
int
currentKey
=
0
;
//Check for xvelocity.
if
(
xVel
>
0
)
currentKey
|=
PlayerButtonRight
;
if
(
xVel
<
0
)
currentKey
|=
PlayerButtonLeft
;
//Check for jumping.
if
(
isJump
)
currentKey
|=
PlayerButtonJump
;
//Check if the downbutton is pressed.
if
(
downKeyPressed
)
currentKey
|=
PlayerButtonDown
;
//Add the action.
playerButton
.
push_back
(
currentKey
);
//Change the state.
state
++
;
}
}
void
Player
::
shadowGiveState
(
Shadow
*
shadow
){
//Check if the player calls the shadow.
if
(
shadowCall
==
true
){
//Clear any recording still with the shadow.
shadow
->
playerButton
.
clear
();
//Loop the recorded moves and add them to the one of the shadow.
for
(
unsigned
int
s
=
0
;
s
<
playerButton
.
size
();
s
++
){
shadow
->
playerButton
.
push_back
(
playerButton
[
s
]);
}
//Reset the state of both the player and the shadow.
stateReset
();
shadow
->
stateReset
();
//Clear the recording at the player's side.
playerButton
.
clear
();
line
.
clear
();
//Set shadowCall false
shadowCall
=
false
;
//And let the shadow know that the player called him.
shadow
->
meCall
();
}
}
void
Player
::
stateReset
(){
//Reset the state by setting it to 0.
state
=
0
;
}
void
Player
::
otherCheck
(
class
Player
*
other
){
//Check if the player is standing on the shadow, or vice versa.
//First make sure the player isn't dead.
if
(
!
dead
){
if
(
objCurrentStand
!=
NULL
){
//Now get the velocity of the object the player is standing.
SDL_Rect
v
=
objCurrentStand
->
getBox
(
BoxType_Velocity
);
//Set the base velocity to the velocity of the object.
xVelBase
=
v
.
x
;
yVelBase
=
v
.
y
;
//Already move the player box.
box
.
x
+=
v
.
x
;
box
.
y
+=
v
.
y
;
}
//Make sure the other isn't dead.
if
(
!
other
->
dead
){
//Get the box of the shadow.
SDL_Rect
boxShadow
=
other
->
getBox
();
//Check collision between the shadow and the player.
if
(
checkCollision
(
box
,
boxShadow
)
==
true
){
//We have collision now check if the other is standing on top of you.
if
(
box
.
y
+
box
.
h
<=
boxShadow
.
y
+
13
&&
!
other
->
inAir
){
int
yVelocity
=
yVel
-1
;
if
(
yVelocity
>
0
){
box
.
y
-=
yVel
;
box
.
y
+=
boxShadow
.
y
-
(
box
.
y
+
box
.
h
);
inAir
=
false
;
canMove
=
false
;
onGround
=
true
;
other
->
holdingOther
=
true
;
}
}
}
else
{
other
->
holdingOther
=
false
;
}
}
}
objCurrentStand
=
NULL
;
}
SDL_Rect
Player
::
getBox
(){
return
box
;
}
void
Player
::
setMyCamera
(){
//Only change the camera when the player isn't dead.
if
(
dead
)
return
;
//TODO: Perhaps make it possible to center the camera on the shadow by pressing a key.
//Shift maybe?
//Check if the player is halfway pass the halfright of the screen.
if
(
box
.
x
>
camera
.
x
+
450
){
//It is so ease the camera to the right.
camera
.
x
+=
(
box
.
x
-
camera
.
x
-400
)
>>
4
;
//Check if the camera isn't going too far.
if
(
box
.
x
<
camera
.
x
+
450
){
camera
.
x
=
box
.
x
-450
;
}
}
//Check if the player is halfway pass the halfleft of the screen.
if
(
box
.
x
<
camera
.
x
+
350
){
//It is so ease the camera to the left.
camera
.
x
+=
(
box
.
x
-
camera
.
x
-400
)
>>
4
;
//Check if the camera isn't going too far.
if
(
box
.
x
>
camera
.
x
+
350
){
camera
.
x
=
box
.
x
-350
;
}
}
//If the camera is too far to the left we set it to 0.
if
(
camera
.
x
<
0
){
camera
.
x
=
0
;
}
//If the camera is too far to the right we set it to the max right.
if
(
camera
.
x
+
camera
.
w
>
LEVEL_WIDTH
){
camera
.
x
=
LEVEL_WIDTH
-
camera
.
w
;
}
//Check if the player is halfway pass the lower half of the screen.
if
(
box
.
y
>
camera
.
y
+
350
){
//Ir is so ease the camera down.
camera
.
y
+=
(
box
.
y
-
camera
.
y
-300
)
>>
4
;
//Check if the camera isn't going too far.
if
(
box
.
y
<
camera
.
y
+
350
){
camera
.
y
=
box
.
y
-350
;
}
}
//Check if the player is halfway pass the upper half of the screen.
if
(
box
.
y
<
camera
.
y
+
250
){
//It is so ease the camera up.
camera
.
y
+=
(
box
.
y
-
camera
.
y
-300
)
>>
4
;
//Check if the camera isn't going too far.
if
(
box
.
y
>
camera
.
y
+
250
){
camera
.
y
=
box
.
y
-250
;
}
}
//If the camera is too far up we set it to 0.
if
(
camera
.
y
<
0
){
camera
.
y
=
0
;
}
//If the camera is too far down we set it to the max down.
if
(
camera
.
y
+
camera
.
h
>
LEVEL_HEIGHT
){
camera
.
y
=
LEVEL_HEIGHT
-
camera
.
h
;
}
}
void
Player
::
reset
(){
//Set the location of the player to it's initial state.
box
.
x
=
fx
;
box
.
y
=
fy
;
//Reset back to default value.
inAir
=
true
;
isJump
=
false
;
onGround
=
true
;
shadowCall
=
false
;
canMove
=
true
;
holdingOther
=
false
;
dead
=
false
;
record
=
false
;
//Some animation variables.
frame
=
0
;
animation
=
0
;
direction
=
0
;
state
=
0
;
yVel
=
0
;
objCurrentStand
=
NULL
;
//Clear the recording.
line
.
clear
();
playerButton
.
clear
();
//xVelSaved is used to indicate if there's a state saved or not.
xVelSaved
=
0x80000000
;
}
void
Player
::
saveState
(){
//We can only save the state when the player isn't dead.
if
(
!
dead
){
boxSaved
.
x
=
box
.
x
;
boxSaved
.
y
=
box
.
y
;
xVelSaved
=
xVel
;
yVelSaved
=
yVel
;
inAirSaved
=
inAir
;
isJumpSaved
=
isJump
;
onGroundSaved
=
onGround
;
canMoveSaved
=
canMove
;
holdingOtherSaved
=
holdingOther
;
//Only play the sound when it's enabled.
if
(
getSettings
()
->
getBoolValue
(
"sound"
)
==
true
){
//To prevent playing the sound twice, only the player can cause the sound.
if
(
!
shadow
)
Mix_PlayChannel
(
-1
,
saveSound
,
0
);
}
}
}
void
Player
::
loadState
(){
//Check with xVelSaved if there's a saved state.
if
(
xVelSaved
==
0x80000000
){
//There isn't so reset the game to load the first initial state.
reset
();
return
;
}
//Restore the saved values.
box
.
x
=
boxSaved
.
x
;
box
.
y
=
boxSaved
.
y
;
//xVel is set to 0 since it's saved counterpart is used to indicate a saved state.
xVel
=
0
;
yVel
=
yVelSaved
;
//Restore teh saved values.
inAir
=
inAirSaved
;
isJump
=
isJumpSaved
;
onGround
=
onGroundSaved
;
canMove
=
canMoveSaved
;
holdingOther
=
holdingOtherSaved
;
dead
=
false
;
record
=
false
;
shadowCall
=
false
;
stateReset
();
//Clear any recorded stuff.
line
.
clear
();
playerButton
.
clear
();
}
void
Player
::
swapState
(
Player
*
other
){
//We need to swap the values of the player with the ones of the given player.
swap
(
box
.
x
,
other
->
box
.
x
);
swap
(
box
.
y
,
other
->
box
.
y
);
//NOTE: xVel isn't there since it's used for something else.
swap
(
yVel
,
other
->
yVel
);
swap
(
inAir
,
other
->
inAir
);
swap
(
isJump
,
other
->
isJump
);
swap
(
onGround
,
other
->
onGround
);
swap
(
canMove
,
other
->
canMove
);
swap
(
holdingOther
,
other
->
holdingOther
);
swap
(
dead
,
other
->
dead
);
record
=
false
;
shadowCall
=
false
;
stateReset
();
//Now remove the current line and the player buttons.
//FIXME: Is this needed, couldn't it be used for complicated puzzles?
line
.
clear
();
playerButton
.
clear
();
//Also reset the state of the other.
other
->
stateReset
();
//Play the swap sound.
if
(
getSettings
()
->
getBoolValue
(
"sound"
)
==
true
){
Mix_PlayChannel
(
-1
,
swapSound
,
0
);
}
}
bool
Player
::
canSaveState
(){
//We can only save the state if the player isn't dead.
return
!
dead
;
}
bool
Player
::
canLoadState
(){
//We use xVelSaved to indicate if a state is saved or not.
return
xVelSaved
!=
0x80000000
;
}
void
Player
::
die
(){
//Make sure the player isn't already dead.
if
(
!
dead
){
dead
=
true
;
//If sound is enabled run the hit sound.
if
(
getSettings
()
->
getBoolValue
(
"sound"
)
==
true
){
Mix_PlayChannel
(
-1
,
hitSound
,
0
);
}
}
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sun, Nov 15, 4:43 AM (1 d, 22 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
149193
Default Alt Text
Player.cpp (24 KB)
Attached To
Mode
R79 meandmyshadow
Attached
Detach File
Event Timeline