如何在Java中复刻Game Maker Studio的point_angle函数及应用
Let's tackle this two-part problem step by step—first replicating GameMaker's point_angle function in Java, then integrating it with your movement logic.
point_angle in Java GameMaker's point_angle(x1, y1, x2, y2) returns a clockwise angle (in degrees) from the point (x1,y1) to (x2,y2), with 0° pointing right, 90° pointing down, 180° left, and 270° up. Java's Math.atan2 uses a standard mathematical coordinate system (y-axis up, counterclockwise angles), so we need to adjust for the differences.
Here's a Java method that matches GameMaker's behavior exactly:
public static double pointAngle(double x1, double y1, double x2, double y2) { // Calculate the distance between points double deltaX = x2 - x1; double deltaY = y2 - y1; // Calculate counterclockwise angle in standard coordinates (y-up) // We invert deltaY to account for GameMaker's y-down system double mathAngleDegrees = Math.toDegrees(Math.atan2(-deltaY, deltaX)); // Convert to GameMaker's clockwise 0-360° range double gameMakerAngle = (360 - mathAngleDegrees) % 360; // Ensure non-negative result (mod can return negative values for negative inputs) if (gameMakerAngle < 0) { gameMakerAngle += 360; } return gameMakerAngle; }
How it works:
- We first calculate the horizontal (
deltaX) and vertical (deltaY) differences between the two points. Math.atan2(-deltaY, deltaX)adjusts for GameMaker's downward-pointing y-axis, giving us a counterclockwise angle in radians.- Convert radians to degrees, then flip the angle to get a clockwise value, and wrap it to the 0-360° range.
Your existing tick() method handles position updates using velX and velY—we just need to convert a target angle into these velocity components. First, let's clean up and expand your class for better functionality (using double for velocities makes movement smoother than int):
public class GameObject { public double x; public double y; public double velX = 0.0; public double velY = 0.0; public void tick() { x += velX; y += velY; } // Reuse the pointAngle method we created earlier public static double pointAngle(double x1, double y1, double x2, double y2) { double deltaX = x2 - x1; double deltaY = y2 - y1; double mathAngleDegrees = Math.toDegrees(Math.atan2(-deltaY, deltaX)); double gameMakerAngle = (360 - mathAngleDegrees) % 360; if (gameMakerAngle < 0) { gameMakerAngle += 360; } return gameMakerAngle; } // Set velocity to move towards a target point at a given speed public void setVelocityTowards(double targetX, double targetY, double speed) { double angle = pointAngle(x, y, targetX, targetY); setVelocityAtAngle(angle, speed); } // Set velocity to move at a specific GameMaker-style angle public void setVelocityAtAngle(double angle, double speed) { // Convert angle from degrees to radians for trigonometric functions double radians = Math.toRadians(angle); // Calculate velocity components using cosine (x-axis) and sine (y-axis) velX = speed * Math.cos(radians); velY = speed * Math.sin(radians); } }
Usage Example:
public class GameLoopExample { public static void main(String[] args) { GameObject player = new GameObject(); player.x = 100.0; player.y = 100.0; // Make the player move towards (300, 200) at a speed of 5 units per tick player.setVelocityTowards(300.0, 200.0, 5.0); // Simulate 10 ticks of the game loop for (int i = 0; i < 10; i++) { player.tick(); System.out.printf("Player Position: (%.1f, %.1f)%n", player.x, player.y); } } }
Key Notes:
- Using
doubleforvelX,velY,x, andyavoids the choppy movement that comes with integer-based positioning/velocity. setVelocityTowardscalculates the angle to your target point automatically, whilesetVelocityAtAnglelets you specify a fixed direction (like 90° for straight down).- The
tick()method stays simple—it just applies the velocity to the position each frame, which fits perfectly into a standard game loop.
内容的提问来源于stack exchange,提问作者404 Name Not Found

