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