📄 playfield.cpp
字号:
for (j = 0; j < max_cols; j++) {
visited[i][j] = false;
map[i][j] = Empty;
}
}
for (i = 0; i < m_actors; i++) {
int x = m_actor[i].m_x / 30;
int y = m_actor[i].m_y / 30;
if (x < 0 || x >= max_cols || y < 0 || y >= max_rows) {
return false;
}
map[y][x] = m_actor[i].m_type;
}
/* second, set all field to "visited" that can be reached from x=0/y=0 */
check_field(map, visited, 0, 0);
/* third, check if all coins are on a visited field */
for (i = 0; i < max_rows; i++) {
for (j = 0; j < max_cols; j++) {
if (map[i][j] == BlockCoin && visited[i][j] == false) {
return false;
}
}
}
return true;
}
void PlayField::clearField(void)
{
#pragma message("Clear bitmap field")
QPainter painter_pixmap(m_pixgc);
QColor black(0, 0, 0);
int max_y = m_pixmap->height();
int offs_y = (max_y - 240);
int i;
for (i = 0; i < m_actors; i++) {
if (m_actor[i].m_type != Wall) {
painter_pixmap.fillRect((KMajorPart*m_actor[i].m_x)/KDividor, m_actor[i].m_y + offs_y,
KBlockWidth, 30, black);
}
}
}
void PlayField::animateActors(void)
{
int i;
for (i = 0; i < m_actors; i++) {
if (m_actor[i].m_type == Player || m_actor[i].m_type == Flame
|| m_actor[i].m_type == Points) {
m_actor[i].m_counter++;
}
}
}
void PlayField::moveActors(void)
{
int x;
int y;
int i;
int j;
/* first, move the blocks - they just move until they crash
* into another object, but they kill all flames on their way...
*/
for (i = 1; i < m_actors; i++) {
if (m_actor[i].m_type == Block || m_actor[i].m_type == BlockCoin) {
switch (m_actor[i].m_act_dir) {
case Up:
x = m_actor[i].m_x;
y = m_actor[i].m_y - m_actor[i].m_speed;
while ((j = detectCollisionFlame(i, x, y)) >= 0) {
killFlame(j);
}
if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
y = (m_actor[i].m_y / 30) * 30;
m_actor[i].m_act_dir = Stop;
m_actor[i].m_req_dir = Stop;
}
m_actor[i].m_x = x;
m_actor[i].m_y = y;
break;
case Down:
x = m_actor[i].m_x;
y = m_actor[i].m_y + m_actor[i].m_speed;
while ((j = detectCollisionFlame(i, x, y)) >= 0) {
killFlame(j);
}
if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
y = ((m_actor[i].m_y + 29) / 30) * 30;
m_actor[i].m_act_dir = Stop;
m_actor[i].m_req_dir = Stop;
}
m_actor[i].m_x = x;
m_actor[i].m_y = y;
break;
case Left:
x = m_actor[i].m_x - m_actor[i].m_speed;
y = m_actor[i].m_y;
while ((j = detectCollisionFlame(i, x, y)) >= 0) {
killFlame(j);
}
if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
x = (m_actor[i].m_x / 30) * 30;
m_actor[i].m_act_dir = Stop;
m_actor[i].m_req_dir = Stop;
}
m_actor[i].m_x = x;
m_actor[i].m_y = y;
break;
case Right:
x = m_actor[i].m_x + m_actor[i].m_speed;
y = m_actor[i].m_y;
while ((j = detectCollisionFlame(i, x, y)) >= 0) {
killFlame(j);
}
if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
x = ((m_actor[i].m_x + 29) / 30) * 30;
m_actor[i].m_act_dir = Stop;
m_actor[i].m_req_dir = Stop;
}
m_actor[i].m_x = x;
m_actor[i].m_y = y;
break;
default:
break;
}
}
}
/* then, calculate the directions of the flames (always towards the player) */
for (i = 1; i < m_actors; i++) {
if (m_actor[i].m_type == Flame) {
/* default: move in a random direction */
int xdiff = m_actor[i].m_x - m_actor[0].m_x;
int ydiff = m_actor[i].m_y - m_actor[0].m_y;
switch (rand() % 5) {
case 0:
m_actor[i].m_req_dir = Stop;
break;
case 1:
m_actor[i].m_req_dir = Up;
break;
case 2:
m_actor[i].m_req_dir = Down;
break;
case 3:
m_actor[i].m_req_dir = Left;
break;
case 4:
m_actor[i].m_req_dir = Right;
break;
}
/* if the player is too far away, the flame doesn't see him */
if (abs(xdiff) > 150 || abs(ydiff) > 150) {
continue;
}
/* if the flame is in line of sight, it chases the player */
if (abs(xdiff) < 15) {
if (lineOfSight(i, 0, (ydiff > 0) ? Up : Down)) {
m_actor[i].m_req_dir = (ydiff > 0) ? Up : Down;
continue;
}
} else if (abs(ydiff) < 15) {
if (lineOfSight(i, 0, (xdiff > 0) ? Left : Right)) {
m_actor[i].m_req_dir = (xdiff > 0) ? Left : Right;
continue;
}
}
/* if the player is too far away, the flame doesn't see him */
if (abs(xdiff) > 90 || abs(ydiff) > 90) {
continue;
}
/* move in the direction with the smaller difference if we have
* to go both horizontal or vertical
*/
if (xdiff != 0 && ydiff != 0) {
if (abs(xdiff) > abs(ydiff)) {
xdiff = 0;
} else {
ydiff = 0;
}
}
if (xdiff != 0) {
m_actor[i].m_req_dir = (xdiff > 0) ? Left : Right;
} else if (ydiff != 0) {
m_actor[i].m_req_dir = (ydiff > 0) ? Up : Down;
}
}
}
/* at last, move the player and the flames. note: if the requested direction
* differs from the actual one, the player or flame is moved to the next tile
* position before actually changing the direction (or stopping).
*/
for (i = 0; i < m_actors; i++) {
if (m_actor[i].m_type != Player && m_actor[i].m_type != Flame) {
continue;
}
#ifdef CAN_TELEPORT
if (i == 0 && m_teleport) {
/* if teleport() works, the act/req_dir members will be reset! */
teleport();
m_teleport = false;
}
#endif
if (m_actor[i].m_act_dir == Stop) {
m_actor[i].m_act_dir = m_actor[i].m_req_dir;
}
switch (m_actor[i].m_act_dir) {
case Up:
x = m_actor[i].m_x;
y = m_actor[i].m_y - m_actor[i].m_speed;
if (m_actor[i].m_req_dir != Up) {
if ((m_actor[i].m_y % 30) < m_actor[i].m_speed) {
m_actor[i].m_act_dir = m_actor[i].m_req_dir;
y = (m_actor[i].m_y / 30) * 30;
}
} else if (i == 0) {
if ((j = detectCollisionFlame(i, x, y)) >= 0) {
killPlayer();
} else if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
if (m_actor[j].m_type == Block || m_actor[j].m_type == BlockCoin) {
moveOrCrushBlock(j, m_actor[i].m_act_dir);
} else {
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
}
y = (m_actor[i].m_y / 30) * 30;
}
} else {
if (( j = detectCollisionPlayer(x, y)) >= 0) {
killPlayer();
} else if ((j = detectCollisionMovingBlock(i, x, y)) >= 0) {
killFlame(i);
y = (m_actor[i].m_y / 30) * 30;
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
} else if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
y = (m_actor[i].m_y / 30) * 30;
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
}
}
if (i == 0 && hasReachedClickPosition(x, y)) {
m_actor[i].m_req_dir = Stop;
}
m_actor[i].m_x = x;
m_actor[i].m_y = y;
break;
case Down:
x = m_actor[i].m_x;
y = m_actor[i].m_y + m_actor[i].m_speed;
if (i == 0 && hasReachedClickPosition(x, y)) {
m_actor[i].m_req_dir = Stop;
}
if (m_actor[i].m_req_dir != Down) {
if ((y % 30) <= m_actor[i].m_speed) {
m_actor[i].m_act_dir = m_actor[i].m_req_dir;
y = (y / 30) * 30;
}
} else if (i == 0) {
if ((j = detectCollisionFlame(i, x, y)) >= 0) {
killPlayer();
} else if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
if (m_actor[j].m_type == Block || m_actor[j].m_type == BlockCoin) {
moveOrCrushBlock(j, m_actor[i].m_act_dir);
} else {
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
}
y = ((m_actor[i].m_y + 29) / 30) * 30;
}
} else {
if (( j = detectCollisionPlayer(x, y)) >= 0) {
killPlayer();
} else if ((j = detectCollisionMovingBlock(i, x, y)) >= 0) {
killFlame(i);
y = ((m_actor[i].m_y + 29) / 30) * 30;
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
} else if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
y = ((m_actor[i].m_y + 29) / 30) * 30;
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
}
}
m_actor[i].m_x = x;
m_actor[i].m_y = y;
break;
case Left:
x = m_actor[i].m_x - m_actor[i].m_speed;
y = m_actor[i].m_y;
if (m_actor[i].m_req_dir != Left) {
if ((m_actor[i].m_x % 30) < m_actor[i].m_speed) {
m_actor[i].m_act_dir = m_actor[i].m_req_dir;
x = (m_actor[i].m_x / 30) * 30;
}
} else if (i == 0) {
if ((j = detectCollisionFlame(i, x, y)) >= 0) {
killPlayer();
} else if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
if (m_actor[j].m_type == Block || m_actor[j].m_type == BlockCoin) {
moveOrCrushBlock(j, m_actor[i].m_act_dir);
} else {
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
}
x = (m_actor[i].m_x / 30) * 30;
}
} else {
if (( j = detectCollisionPlayer(x, y)) >= 0) {
killPlayer();
} else if ((j = detectCollisionMovingBlock(i, x, y)) >= 0) {
killFlame(i);
x = (m_actor[i].m_x / 30) * 30;
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
} else if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
x = (m_actor[i].m_x / 30) * 30;
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
}
}
if (i == 0 && hasReachedClickPosition(x, y)) {
m_actor[i].m_req_dir = Stop;
}
m_actor[i].m_x = x;
m_actor[i].m_y = y;
break;
case Right:
x = m_actor[i].m_x + m_actor[i].m_speed;
y = m_actor[i].m_y;
if (i == 0 && hasReachedClickPosition(x, y)) {
m_actor[i].m_req_dir = Stop;
}
if (m_actor[i].m_req_dir != Right) {
if ((x % 30) <= m_actor[i].m_speed) {
m_actor[i].m_act_dir = m_actor[i].m_req_dir;
x = (x / 30) * 30;
}
} else if (i == 0) {
if ((j = detectCollisionFlame(i, x, y)) >= 0) {
killPlayer();
} else if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
if (m_actor[j].m_type == Block || m_actor[j].m_type == BlockCoin) {
moveOrCrushBlock(j, m_actor[i].m_act_dir);
} else {
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
}
x = ((m_actor[i].m_x + 29) / 30) * 30;
}
} else {
if (( j = detectCollisionPlayer(x, y)) >= 0) {
killPlayer();
} else if ((j = detectCollisionMovingBlock(i, x, y)) >= 0) {
killFlame(i);
x = ((m_actor[i].m_x + 29) / 30) * 30;
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
} else if ((j = detectCollisionBlockOrWall(i, x, y)) >= 0) {
x = ((m_actor[i].m_x + 29) / 30) * 30;
m_actor[i].m_req_dir = Stop;
m_actor[i].m_act_dir = Stop;
}
}
m_actor[i].m_x = x;
m_actor[i].m_y = y;
break;
case Stop:
break;
}
}
}
void PlayField::recreateFlames(void)
{
int i;
for (i = 1; i < m_actors; i++) {
if (m_actor[i].m_type == Points && m_actor[i].m_counter >= 36) {
/* first, set the position of the flame to the tile position */
m_actor[i].m_x = ((m_actor[i].m_x + 15) / 30) * 30;
m_actor[i].m_y = ((m_actor[i].m_y + 15) / 30) * 30;
m_actor[i].m_counter = 0;
m_actor[i].m_type = Flame;
/* then, move the flame if it is too near to the player */
int nloops = 0;
while (++nloops < 1000) {
int xdiff = abs(m_actor[i].m_x - m_actor[0].m_x);
int ydiff = abs(m_actor[i].m_y - m_actor[0].m_y);
if (xdiff >= 90 && ydiff >= 90
&& detectCollision(i, m_actor[i].m_x, m_actor[i].m_y) < 0) {
break;
}
m_actor[i].m_x = (rand() % max_cols) * 30;
m_actor[i].m_y = (rand() % max_rows) * 30;
}
}
}
}
void PlayField::recreatePlayer(void)
{
int i;
/* first, set the position of the player to the tile position */
m_actor[0].m_x = ((m_actor[0].m_x + 15) / 30) * 30;
m_actor[0].m_y = ((m_actor[0].m_y + 15) / 30) * 30;
m_actor[0].m_counter = 0;
/* actually, we don't recreate or move the player, but we move all flames
* that are too near to an other position.
*/
for (i = 1; i < m_actors; i++) {
if (m_actor[i].m_type == Flame) {
int nloops = 0;
while (++nloops < 1000) {
int xdiff = abs(m_actor[i].m_x - m_actor[0].m_x);
int ydiff = abs(m_actor[i].m_y - m_actor[0].m_y);
if (xdiff >= 90 && ydiff >= 90
&& detectCollision(i, m_actor[i].m_x, m_actor[i].m_y) < 0) {
break;
}
m_actor[i].m_x = (rand() % max_cols) * 30;
m_actor[i].m_y = (rand() % max_rows) * 30;
m_actor[i].m_counter = 0;
}
}
}
}
void PlayField::killFlame(int actor)
{
if (actor < 0 || actor >= m_actors || m_actor[actor].m_type != Flame) {
}
m_flames_killed++;
m_score = m_score + 50;
m_soundHandler->PlaySampleL(m_SoundEffects[EKillFireFx]);
if (m_flames_killed % 10 == 0 && m_lives < max_lives) {
m_lives++;
}
m_actor[actor].m_type = Points;
m_actor[actor].m_counter = 0;
m_actor[actor].m_req_dir = Stop;
m_actor[actor].m_act_dir = Stop;
}
void PlayField::killPlayer(void)
{
m_soundHandler->PlaySampleL(m_SoundEffects[EGameOverFx]);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -