AdvanceFrameCounter();
AdvanceGfxFrame();
+ if (PendingEscapeKeyEvent())
+ continue;
+
#ifdef DEBUG
if (setup.quick_doors)
continue;
return MM_MASK_CIRCLE;
}
+static int getPixelFromMask(int pos, int dx, int dy)
+{
+ return (mm_masks[pos][dy / 2][dx / 2] == 'X' ? 1 : 0);
+}
+
static int getLevelFromLaserX(int x)
{
return x / TILEX - (x < 0 ? 1 : 0); // correct negative values
{
int pos = getMaskFromElement(element);
- pixel = (mm_masks[pos][dy / 2][dx / 2] == 'X' ? 1 : 0);
+ pixel = getPixelFromMask(pos, dx, dy);
}
}
else
break;
}
- boolean diagonally_adjacent_hit = FALSE;
-
// handle special case of laser hitting two diagonally adjacent elements
// (with or without a third corner element behind these two elements)
if ((diag_1 || diag_2) && cross_x && cross_y)
{
- diagonally_adjacent_hit = TRUE;
-
// compare the two diagonally adjacent elements
int xoffset = 2;
int yoffset = 2 * (diag_1 ? -1 : +1);
break;
}
}
- else if (IS_DF_SLOPE(element))
- {
- if (diagonally_adjacent_hit)
- {
- laser.overloaded = TRUE;
-
- break;
- }
-
- if (hit_mask == HIT_MASK_LEFT ||
- hit_mask == HIT_MASK_RIGHT ||
- hit_mask == HIT_MASK_TOP ||
- hit_mask == HIT_MASK_BOTTOM)
- {
- if (HitReflectingWalls(element, hit_mask))
- break;
- }
- else
- {
- if (HitElement(element, hit_mask))
- break;
- }
- }
else
{
if (HitElement(element, hit_mask))
{
if (IS_DF_SLOPE(element))
{
+ // check if laser scan has crossed element boundaries (not just mini tiles)
+ boolean cross_x = (getLevelFromLaserX(LX) != getLevelFromLaserX(LX + 2));
+ boolean cross_y = (getLevelFromLaserY(LY) != getLevelFromLaserY(LY + 2));
+
+ // check if wall (horizontal or vertical) side of slope was hit
+ if (hit_mask == HIT_MASK_LEFT ||
+ hit_mask == HIT_MASK_RIGHT ||
+ hit_mask == HIT_MASK_TOP ||
+ hit_mask == HIT_MASK_BOTTOM)
+ {
+ return HitReflectingWalls(element, hit_mask);
+ }
+
+ // check if an edge was hit while crossing element borders
+ if (cross_x && cross_y && get_number_of_bits(hit_mask) == 1)
+ {
+ // check both sides of potentially diagonal side of slope
+ int dx1 = (LX + XS) % TILEX;
+ int dy1 = (LY + YS) % TILEY;
+ int dx2 = (LX + XS + 2) % TILEX;
+ int dy2 = (LY + YS + 2) % TILEY;
+ int pos = getMaskFromElement(element);
+
+ // check if we are entering empty space area after hitting edge
+ if (!getPixelFromMask(pos, dx1, dy1) &&
+ !getPixelFromMask(pos, dx2, dy2))
+ {
+ // we already know that we hit an edge, but use this function to go on
+ if (HitOnlyAnEdge(hit_mask))
+ return FALSE;
+ }
+ }
+
int mirrored_angle = get_mirrored_angle(laser.current_angle,
get_element_angle(element));
int opposite_angle = get_opposite_angle(laser.current_angle);
// check if laser is reflected by slope by 180°
if (mirrored_angle == opposite_angle)
{
- LX += XS;
- LY += YS;
-
AddDamagedField(LX / TILEX, LY / TILEY);
laser.overloaded = TRUE;
XS = 2 * Step[laser.current_angle].x;
YS = 2 * Step[laser.current_angle].y;
- if (!IS_22_5_ANGLE(laser.current_angle)) // 90° or 45° angle
- step_size = 8;
- else
- step_size = 4;
+ if (through_center)
+ {
+ // start from center position for all game elements but slope
+ if (!IS_22_5_ANGLE(laser.current_angle)) // 90° or 45° angle
+ step_size = 8;
+ else
+ step_size = 4;
- LX += step_size * XS;
- LY += step_size * YS;
+ LX += step_size * XS;
+ LY += step_size * YS;
+ }
+ else
+ {
+ // advance laser position until reaching the next tile (slopes)
+ while (LX / TILEX == ELX && (LX + 2) / TILEX == ELX &&
+ LY / TILEY == ELY && (LY + 2) / TILEY == ELY)
+ {
+ LX += XS;
+ LY += YS;
+ }
+ }
// draw sparkles on mirror
if ((IS_MIRROR(element) ||
{
int pos = getMaskFromElement(element_side);
- if (mm_masks[pos][dx / 2][dx / 2] == 'X')
+ if (getPixelFromMask(pos, dx, dy))
laser.overloaded = TRUE;
}
}