static int pacman_nr = -1;
// various game engine delay counters
-static unsigned int rotate_delay = 0;
-static unsigned int pacman_delay = 0;
-static unsigned int energy_delay = 0;
-static unsigned int overload_delay = 0;
+static DelayCounter rotate_delay = { AUTO_ROTATE_DELAY };
+static DelayCounter pacman_delay = { PACMAN_MOVE_DELAY };
+static DelayCounter energy_delay = { ENERGY_DELAY };
+static DelayCounter overload_delay = { 0 };
// element masks for scanning pixels of MM elements
static const char mm_masks[10][16][16 + 1] =
}
}
-static void InitField(int x, int y, boolean init_game)
+static void InitField(int x, int y)
{
int element = Tile[x][y];
Tile[x][y] = next_element;
- DrawField_MM(x, y);
game_mm.cycle[i].steps -= step;
}
}
CT = Ct = 0;
- rotate_delay = 0;
- pacman_delay = 0;
- energy_delay = 0;
- overload_delay = 0;
+ rotate_delay.count = 0;
+ pacman_delay.count = 0;
+ energy_delay.count = 0;
+ overload_delay.count = 0;
ClickElement(-1, -1, -1);
Frame[x][y] = 0;
Stop[x][y] = FALSE;
- InitField(x, y, TRUE);
+ InitField(x, y);
}
}
cycle_steps_done++;
}
+ AdvanceFrameCounter();
+ AdvanceGfxFrame();
+
+ DrawLevel_MM();
+
BackToFront();
ColorCycling();
SetTileCursorActive(TRUE);
}
+static void FadeOutLaser(boolean overloaded)
+{
+ int i;
+
+ for (i = 15; i >= 0; i--)
+ {
+ if (overloaded)
+ pen_ray = GetPixelFromRGB(window, 0x11 * i, 0x00, 0x00);
+ else
+ pen_ray = GetPixelFromRGB(window,
+ native_mm_level.laser_red * 0x11 * i,
+ native_mm_level.laser_green * 0x11 * i,
+ native_mm_level.laser_blue * 0x11 * i);
+
+ DrawLaser(0, DL_LASER_ENABLED);
+
+ BackToFront();
+ Delay_WithScreenUpdates(50);
+ }
+
+ DrawLaser(0, DL_LASER_DISABLED);
+
+ if (!overloaded)
+ StopSound_MM(SND_MM_GAME_HEALTH_CHARGING);
+}
+
+static void GameOver_MM(int game_over_cause)
+{
+ // do not handle game over if request dialog is already active
+ if (game.request_active)
+ return;
+
+ game_mm.game_over = TRUE;
+ game_mm.game_over_cause = game_over_cause;
+
+ if (setup.ask_on_game_over)
+ game.restart_game_message = (game_over_cause == GAME_OVER_BOMB ?
+ "Bomb killed Mc Duffin! Play it again?" :
+ game_over_cause == GAME_OVER_NO_ENERGY ?
+ "Out of magic energy! Play it again?" :
+ game_over_cause == GAME_OVER_OVERLOADED ?
+ "Magic spell hit Mc Duffin! Play it again?" :
+ NULL);
+
+ SetTileCursorActive(FALSE);
+}
+
void AddLaserEdge(int lx, int ly)
{
int clx = dSX + lx;
if (element == EL_EMPTY)
{
- if (!HitOnlyAnEdge(element, hit_mask))
+ if (!HitOnlyAnEdge(hit_mask))
break;
}
else if (element == EL_FUSE_ON)
boolean HitElement(int element, int hit_mask)
{
- if (HitOnlyAnEdge(element, hit_mask))
+ if (HitOnlyAnEdge(hit_mask))
return FALSE;
if (IS_MOVING(ELX, ELY) || IS_BLOCKED(ELX, ELY))
LX += step_size * XS;
LY += step_size * YS;
-#if 0
// draw sparkles on mirror
- if ((IS_MIRROR(element) || IS_MIRROR_FIXED(element)) &&
+ if ((IS_MIRROR(element) ||
+ IS_MIRROR_FIXED(element) ||
+ element == EL_PRISM) &&
current_angle != laser.current_angle)
{
- MoveSprite(vp, &Pfeil[2], 4 + 16 * ELX, 5 + 16 * ELY + 1);
+ MovDelay[ELX][ELY] = 11; // start animation
}
-#endif
if ((!IS_POLAR(element) && !IS_POLAR_CROSS(element)) &&
current_angle != laser.current_angle)
return TRUE;
}
-boolean HitOnlyAnEdge(int element, int hit_mask)
+boolean HitOnlyAnEdge(int hit_mask)
{
// check if the laser hit only the edge of an element and, if so, go on
boolean HitPolarizer(int element, int hit_mask)
{
- if (HitOnlyAnEdge(element, hit_mask))
+ if (HitOnlyAnEdge(hit_mask))
return FALSE;
if (IS_DF_GRID(element))
boolean HitLaserSource(int element, int hit_mask)
{
- if (HitOnlyAnEdge(element, hit_mask))
+ if (HitOnlyAnEdge(hit_mask))
return FALSE;
PlayLevelSound_MM(ELX, ELY, element, MM_ACTION_HITTING);
boolean HitLaserDestination(int element, int hit_mask)
{
- if (HitOnlyAnEdge(element, hit_mask))
+ if (HitOnlyAnEdge(hit_mask))
return FALSE;
if (element != EL_EXIT_OPEN &&
}
}
- if (!HitOnlyAnEdge(element, hit_mask))
+ if (!HitOnlyAnEdge(hit_mask))
{
laser.overloaded = TRUE;
boolean HitAbsorbingWalls(int element, int hit_mask)
{
- if (HitOnlyAnEdge(element, hit_mask))
+ if (HitOnlyAnEdge(hit_mask))
return FALSE;
if (ABS(XS) == 4 &&
}
}
+static void DrawFieldAnimated_MM(int x, int y)
+{
+ int element = Tile[x][y];
+
+ if (IS_BLOCKED(x, y))
+ return;
+
+ DrawField_MM(x, y);
+
+ if (IS_MIRROR(element) ||
+ IS_MIRROR_FIXED(element) ||
+ element == EL_PRISM)
+ {
+ if (MovDelay[x][y] != 0) // wait some time before next frame
+ {
+ MovDelay[x][y]--;
+
+ if (MovDelay[x][y] != 0)
+ {
+ int graphic = IMG_TWINKLE_WHITE;
+ int frame = getGraphicAnimationFrame(graphic, 10 - MovDelay[x][y]);
+
+ DrawGraphicThruMask_MM(SCREENX(x), SCREENY(y), graphic, frame);
+ }
+ }
+ }
+
+ laser.redraw = TRUE;
+}
+
static void Explode_MM(int x, int y, int phase, int mode)
{
int num_phase = 9, delay = 2;
Bang_MM(laser.start_edge.x, laser.start_edge.y);
Store[x][y] = EL_EMPTY;
- game_mm.game_over = TRUE;
- game_mm.game_over_cause = GAME_OVER_BOMB;
-
- SetTileCursorActive(FALSE);
+ GameOver_MM(GAME_OVER_DELAYED);
laser.overloaded = FALSE;
}
{
Store[x][y] = EL_EMPTY;
- game.restart_game_message = "Bomb killed Mc Duffin! Play it again?";
+ GameOver_MM(GAME_OVER_BOMB);
}
Tile[x][y] = Store[x][y];
Store[x][y] = Store2[x][y] = 0;
MovDir[x][y] = MovPos[x][y] = MovDelay[x][y] = 0;
- InitField(x, y, FALSE);
+ InitField(x, y);
DrawField_MM(x, y);
}
else if (!(phase % delay) && IN_SCR_FIELD(SCREENX(x), SCREENY(y)))
boolean ClickElement(int x, int y, int button)
{
- static unsigned int click_delay = 0;
- static int click_delay_value = CLICK_DELAY;
+ static DelayCounter click_delay = { CLICK_DELAY };
static boolean new_button = TRUE;
boolean element_clicked = FALSE;
int element;
if (button == -1)
{
// initialize static variables
- click_delay = 0;
- click_delay_value = CLICK_DELAY;
+ click_delay.count = 0;
+ click_delay.value = CLICK_DELAY;
new_button = TRUE;
return FALSE;
if (button == MB_RELEASED)
{
new_button = TRUE;
- click_delay_value = CLICK_DELAY;
+ click_delay.value = CLICK_DELAY;
// release eventually hold auto-rotating mirror
RotateMirror(x, y, MB_RELEASED);
return FALSE;
}
- if (!FrameReached(&click_delay, click_delay_value) && !new_button)
+ if (!FrameReached(&click_delay) && !new_button)
return FALSE;
if (button == MB_MIDDLEBUTTON) // middle button has no function
element_clicked = TRUE;
}
- click_delay_value = (new_button ? CLICK_DELAY_FIRST : CLICK_DELAY);
+ click_delay.value = (new_button ? CLICK_DELAY_FIRST : CLICK_DELAY);
new_button = FALSE;
return element_clicked;
LX, LY, laser.beamer_edge, laser.beamer[1].num);
#endif
+#if 0
laser.num_edges--;
+#endif
}
ScanLaser();
{
int x, y;
- if (!FrameReached(&rotate_delay, AUTO_ROTATE_DELAY))
+ if (!FrameReached(&rotate_delay))
return;
for (x = 0; x < lev_fieldx; x++)
}
}
-static void GameActions_MM_Ext(struct MouseActionInfo action, boolean warp_mode)
+static void GameActions_MM_Ext(void)
{
int element;
int x, y, i;
MeltIce(x, y);
else if (IS_WALL_CHANGING(element) && Store[x][y] == EL_WALL_AMOEBA)
GrowAmoeba(x, y);
+ else
+ DrawFieldAnimated_MM(x, y);
}
AutoRotateMirrors();
CT = FrameCounter;
- if (game_mm.num_pacman && FrameReached(&pacman_delay, PACMAN_MOVE_DELAY))
+ if (game_mm.num_pacman && FrameReached(&pacman_delay))
{
MovePacMen();
}
}
- if (FrameReached(&energy_delay, ENERGY_DELAY))
+ // skip all following game actions if game is over
+ if (game_mm.game_over)
+ return;
+
+ if (FrameReached(&energy_delay))
{
if (game_mm.energy_left > 0)
{
redraw_mask |= REDRAW_DOOR_1;
}
- else if (setup.time_limit && !game_mm.game_over)
+ else if (game.time_limit && !game_mm.game_over)
{
- int i;
-
- for (i = 15; i >= 0; i--)
- {
-#if 0
- SetRGB(pen_ray, 0x0000, 0x0000, i * color_scale);
-#endif
- pen_ray = GetPixelFromRGB(window,
- native_mm_level.laser_red * 0x11 * i,
- native_mm_level.laser_green * 0x11 * i,
- native_mm_level.laser_blue * 0x11 * i);
+ FadeOutLaser(FALSE);
- DrawLaser(0, DL_LASER_ENABLED);
- BackToFront();
- Delay_WithScreenUpdates(50);
- }
-
- StopSound_MM(SND_MM_GAME_HEALTH_CHARGING);
-#if 0
- FadeMusic();
-#endif
-
- DrawLaser(0, DL_LASER_DISABLED);
- game_mm.game_over = TRUE;
- game_mm.game_over_cause = GAME_OVER_NO_ENERGY;
-
- SetTileCursorActive(FALSE);
-
- game.restart_game_message = "Out of magic energy! Play it again?";
+ GameOver_MM(GAME_OVER_NO_ENERGY);
return;
}
!IS_WALL_AMOEBA(element))
return;
+ overload_delay.value = HEALTH_DELAY(laser.overloaded);
+
if (((laser.overloaded && laser.overload_value < MAX_LASER_OVERLOAD) ||
(!laser.overloaded && laser.overload_value > 0)) &&
- FrameReached(&overload_delay, HEALTH_DELAY(laser.overloaded)))
+ FrameReached(&overload_delay))
{
if (laser.overloaded)
laser.overload_value++;
if (laser.overload_value == MAX_LASER_OVERLOAD)
{
- int i;
-
UpdateAndDisplayGameControlValues();
- for (i = 15; i >= 0; i--)
- {
-#if 0
- SetRGB(pen_ray, i * color_scale, 0x0000, 0x0000);
-#endif
-
- pen_ray = GetPixelFromRGB(window, 0x11 * i, 0x00, 0x00);
-
- DrawLaser(0, DL_LASER_ENABLED);
- BackToFront();
- Delay_WithScreenUpdates(50);
- }
-
- DrawLaser(0, DL_LASER_DISABLED);
-
- game_mm.game_over = TRUE;
- game_mm.game_over_cause = GAME_OVER_OVERLOADED;
-
- SetTileCursorActive(FALSE);
+ FadeOutLaser(TRUE);
- game.restart_game_message = "Magic spell hit Mc Duffin! Play it again?";
+ GameOver_MM(GAME_OVER_OVERLOADED);
return;
}
return;
}
-void GameActions_MM(struct MouseActionInfo action, boolean warp_mode)
+void GameActions_MM(struct MouseActionInfo action)
{
boolean element_clicked = ClickElement(action.lx, action.ly, action.button);
boolean button_released = (action.button == MB_RELEASED);
- GameActions_MM_Ext(action, warp_mode);
+ GameActions_MM_Ext();
CheckSingleStepMode_MM(element_clicked, button_released);
}
// Mirror Magic game engine snapshot handling functions
// ----------------------------------------------------------------------------
-void SaveEngineSnapshotValues_MM(ListNode **buffers)
+void SaveEngineSnapshotValues_MM(void)
{
int x, y;