-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathStalactite.cpp
136 lines (124 loc) · 4.03 KB
/
Stalactite.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/*
* Implement the logic and drawing of Stalactite
*/
#include "RickArdurous.h"
#include "Stalactite.h"
#include "SpriteData.h"
#include "MapManager.h"
#include "Rick.h"
#include "Physics.h"
Stalactite::Stalactite() :
FallAnimSpeedIndex(Physics::INVALID_FALL_ID)
{
}
bool Stalactite::Update(UpdateStep step)
{
switch (step)
{
case UpdateStep::DRAW_LETHAL:
{
if (IsPropertySet(Item::PropertyFlags::ALIVE))
{
char shakeX = 0;
// use the special flag as an anim state: if special is set then the stalactite is falling,
// otherwise it is waiting
if (!IsPropertySet(Item::PropertyFlags::SPECIAL))
{
// check if the main character is triggering me
CheckTrigerer(Rick::IsAlive(), Rick::GetX(), Rick::GetY());
// check if the other trap trigerer is triggering me
MapManager::CallMeBackForEachTrapTriggerer(this, &CheckTrigererCallback);
// compute a shaking x variation
char shakingMove[] = {1, -1, 0, 1, 0, -1, 0};
for (unsigned char i = 0; i < sizeof(shakingMove); ++i)
if (arduboy.everyXFrames(SHAKING_SPEED + i))
{
shakeX = shakingMove[i];
break;
}
}
else
{
// make the stalactite fall
Physics::UpdateFall(FallAnimSpeedIndex, Y);
if (MapManager::IsThereStaticCollisionAt(X, Y + SpriteData::STALACTITE_SPRITE_HEIGHT))
ClearProperty(Item::PropertyFlags::ALIVE);
}
// draw the stalactite
Draw(shakeX);
}
break;
}
case UpdateStep::DRAW_IGNORED_BY_ENEMIES:
{
if (!IsPropertySet(Item::PropertyFlags::ALIVE))
{
// increase the sparks frame counter
if (arduboy.everyXFrames(SPARKS_ANIM_SPEED))
{
Y++;
SparksAnimFrameId++;
}
// remove from update once the sparks anim is finished
if (SparksAnimFrameId >= SpriteData::SPARKS_SPRITE_FRAME_COUNT)
{
// stop the fall
Physics::StopFall(FallAnimSpeedIndex);
return true;
}
// draw the Stalactite
if (SparksAnimFrameId < 3)
Draw(0);
// draw the sparks
for (unsigned char i = 0; i < 2; ++i)
arduboy.drawBitmapExtended(MapManager::GetXOnScreen(X + (i*4)),
MapManager::GetYOnScreen(Y + 2 - SparksAnimFrameId),
SpriteData::Sparks[SparksAnimFrameId],
SpriteData::SPARKS_SPRITE_WIDTH,
SpriteData::SPARKS_SPRITE_HEIGHT,
INVERT, false);
}
break;
}
case UpdateStep::RESPAWN:
{
ClearProperty(Item::PropertyFlags::SPECIAL);
SparksAnimFrameId = 0;
break;
}
}
return false;
}
void Stalactite::CheckTrigererCallback(Item * me, Item * trigerer)
{
((Stalactite *)me)->CheckTrigerer(trigerer->IsPropertySet(Item::PropertyFlags::ALIVE), trigerer->GetX(), trigerer->GetY());
}
void Stalactite::CheckTrigerer(bool isAlive, int trigererX, unsigned char trigererY)
{
// check if the trigerer is alive and inside the detection range,
// and that the stalactite is not alreay falling
if (isAlive &&
(X < trigererX + SpriteData::RICK_SPRITE_WIDTH) &&
(X + (SpriteData::STALACTITE_SPRITE_WIDTH * 3) > trigererX))
{
unsigned char yMap = (Y / SpriteData::LEVEL_SPRITE_HEIGHT) + 1;
unsigned char trigererYMap = trigererY / SpriteData::LEVEL_SPRITE_HEIGHT;
int middleX = X + (SpriteData::STALACTITE_SPRITE_WIDTH / 2);
for (unsigned char currentY = yMap; currentY <= trigererYMap; ++currentY)
if (MapManager::IsThereStaticCollisionAt(middleX, currentY * SpriteData::LEVEL_SPRITE_HEIGHT))
return;
// if we didnt find a collision, between me and the triggered, then start to fall
SetProperty(Item::PropertyFlags::SPECIAL);
FallAnimSpeedIndex = Physics::StartFall();
}
}
void Stalactite::Draw(char shakeX)
{
for (unsigned char i = 0; i < 2; ++i)
arduboy.drawBitmapExtended(
MapManager::GetXOnScreen(X + (i * (SpriteData::STALACTITE_SPRITE_WIDTH + 1)) + shakeX),
MapManager::GetYOnScreen(Y + i),
SpriteData::Stalactite,
SpriteData::STALACTITE_SPRITE_WIDTH, SpriteData::STALACTITE_SPRITE_HEIGHT,
WHITE, i);
}