Fix ray calculations by normalizing angles properly

Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
2026-09-10 21:10:27 +02:00
parent eaa6d76792
commit 2f6db48e4a
+19 -42
View File
@@ -24,8 +24,9 @@ const double gameWidth = 320;
const double gameHeight = 256;
extension GameValues on double {
/// Normalizes an angle back into [0, 2π].
double get normalize => (this % (2 * math.pi) + 2 * math.pi) % (2 * math.pi);
/// Normalizes an angle back into [0, 2π) from (-π, π].
double get normalizeAngle =>
(this % (2 * math.pi) + 2 * math.pi) % (2 * math.pi);
/// Returns the degree angle
double get radianToDegree {
@@ -52,14 +53,14 @@ extension GameValues on double {
// Flutter's coordinate system flips the y-axis, which is why we have -sin() -- to flip
// it back in the correct direction.
Offset get direction => Offset(
math.cos(normalize),
-math.sin(normalize),
math.cos(normalizeAngle),
math.sin(normalizeAngle),
);
/// Get the delta from the given angle
Offset get playerDelta => Offset(
math.cos(this) * Player.speed,
math.sin(this) * Player.speed,
direction.dx * Player.speed,
direction.dy * Player.speed,
);
}
@@ -191,7 +192,7 @@ class _PlayerState extends State<Player> {
widget.onRaysUpdated(
calculateRays(
widget.rayData.playerPosition,
widget.rayData.playerAngle.playerDelta,
widget.rayData.playerAngle,
),
);
@@ -243,28 +244,23 @@ class _PlayerState extends State<Player> {
// Where is the player now?
Offset playerPosition = widget.rayData.playerPosition;
double playerAngle = widget.rayData.playerAngle;
final Offset direction = playerAngle.direction;
// How many pixels away from a wall to stay
const double buffer = 8;
if (keys.contains(LogicalKeyboardKey.keyA)) {
// Move left
// Turn left
playerAngle -= 0.1;
if (playerAngle < 0) {
playerAngle += 2 * math.pi;
}
handled = true;
} else if (keys.contains(LogicalKeyboardKey.keyD)) {
// Move right
// Turn right
playerAngle += 0.1;
if (playerAngle > 2 * math.pi) {
playerAngle -= 2 * math.pi;
}
handled = true;
}
// Capture the direction *after* it's potentially mutated
final Offset direction = playerAngle.direction;
if (keys.contains(LogicalKeyboardKey.keyW)) {
if (safeDistanceToWall(playerPosition, direction) >
Player.speed + buffer) {
@@ -283,7 +279,7 @@ class _PlayerState extends State<Player> {
if (handled) {
widget.onRaysUpdated(
calculateRays(playerPosition, playerAngle.playerDelta),
calculateRays(playerPosition, playerAngle),
);
widget.onAngleUpdated(playerAngle);
widget.onPositionUpdated(playerPosition);
@@ -293,7 +289,7 @@ class _PlayerState extends State<Player> {
return false;
}
List<Ray> calculateRays(Offset offset, Offset delta) {
List<Ray> calculateRays(Offset offset, double playerAngle) {
const double dr = math.pi / 180;
final List<Ray> rays = [];
@@ -312,14 +308,7 @@ class _PlayerState extends State<Player> {
double rayY = 0;
double disT = 0;
double rayAngle = delta.direction - (dr * 30);
if (rayAngle < 0) {
rayAngle += 2 * math.pi;
}
if (rayAngle > 2 * math.pi) {
rayAngle -= 2 * math.pi;
}
double rayAngle = (playerAngle - (dr * 30)).normalizeAngle;
int r;
for (r = 0; r < 60; r++) {
@@ -492,14 +481,8 @@ class _PlayerState extends State<Player> {
}
// * Increase the ray angle to draw the next ray
rayAngle += dr;
if (rayAngle < 0) {
rayAngle += 2 * math.pi;
}
if (rayAngle > 2 * math.pi) {
rayAngle -= 2 * math.pi;
}
rayAngle =
(playerAngle.normalizeAngle - (dr * 30) + r * dr).normalizeAngle;
}
return rays;
@@ -608,13 +591,7 @@ class WallPainter extends CustomPainter {
const double dr = math.pi / 180;
final double rayAngle = playerAngle - (dr * 30) + (i * dr);
double correctedAngle = playerAngle - rayAngle;
if (correctedAngle < 0) {
correctedAngle += 2 * math.pi;
}
if (correctedAngle > 2 * math.pi) {
correctedAngle -= 2 * math.pi;
}
final double correctedAngle = (playerAngle - rayAngle).normalizeAngle;
final double disT = ray.distance * math.cos(correctedAngle);