java - Rotating Coordinates (Java and Geometry)
问题描述
I am working on a 2D java game engine using AWT canvas as a basis. Part of this game engine is that it needs to have hitboxes with collision. Not just the built in rectangles (tried that system already) but I need my own Hitbox class because I need more functionality. So I made one, supports circular and 4-sided polygon shaped hitboxes. The way the hitbox class is setup is that it uses four coordinate points to serve as the 4 corner vertices that connect to form a rectangle. Lines are draw connecting the points and these are the lines that are used to detect intersections with other hitboxes. But I now have a problem: rotation.
There are two possibilities for a box hitbox, it can just be four coordinate points, or it can be 4 coordinate points attached to a gameobject. The difference is that the former is just 4 coordinates based on 0,0 as the ordin while the attached to gameobject stores offsets in the coordinates rather than raw location data, so (-100,-100) for example represents the location of the host gameobject but 100 pixels to the left, and 100 pixels up.
Online I found a formula for rotating points about the origin. Since Gameobject based hitboxes were centered around a particular point, I figured that would be the best option to try it on. This code runs each tick to update a player character's hitbox
//creates a rectangle hitbox around this gameobject
int width = getWidth();
int height = getHeight();
Coordinate[] verts = new Coordinate[4]; //corners of hitbox. topLeft, topRight, bottomLeft, bottomRight
verts[0] = new Coordinate(-width / 2, -height / 2);
verts[1] = new Coordinate(width / 2, -height / 2);
verts[2] = new Coordinate(-width / 2, height / 2);
verts[3] = new Coordinate(width / 2, height / 2);
//now go through each coordinate and adjust it for rotation
for(Coordinate c : verts){
if(!name.startsWith("Player"))return; //this is here so only the player character is tested
double theta = Math.toRadians(rotation);
c.x = (int)(c.x*Math.cos(theta)-c.y*Math.sin(theta));
c.y = (int)(c.x*Math.sin(theta)+c.y*Math.cos(theta));
}
getHitbox().vertices = verts;
I appologize for poor video quality but this is what the results of the above are: https://www.youtube.com/watch?v=dF5k-Yb4hvE
All related classes are found here: https://github.com/joey101937/2DTemplate/tree/master/src/Framework
edit: The desired effect is for the box outline to follow the character in a circle while maintaining aspect ratio as seen here: https://www.youtube.com/watch?v=HlvXQrfazhA . The current system uses the code above, the effect of which can be seen above in the previous video link. How should I modify the four 2D coordinates to maintain relative aspect ratio throughout a rotation about a point?
current rotation system is the following:
- x = x*Cos(theta) - y *Sin(theta)
- y = x*Sin(theta) + y *Cos(theta)
where theta is degree of rotation in raidians
解决方案
你犯了经典错误:
c.x = (int)(c.x*Math.cos(theta)-c.y*Math.sin(theta));
c.y = (int)(c.x*Math.sin(theta)+c.y*Math.cos(theta));
在第二行中,您使用的修改值c.x
。只记得tempx = c.x
在计算之前并使用它。
tempx = c.x;
c.x = (int)(tempx*Math.cos(theta)-c.y*Math.sin(theta));
c.y = (int)(tempx*Math.sin(theta)+c.y*Math.cos(theta));
另一个问题:每次旋转后舍入坐标会导致扭曲和旋转后收缩。将坐标存储在浮点数中并将它们舍入仅用于输出是明智的,或者记住起始值并通过累积角度对其应用旋转。
推荐阅读
- javascript - 我如何向所有具有特定角色的人发送私人消息?(discord.js)
- python - 功能记录器在 Pytest 中引发 FileNotFoundError
- xml - 使用 Go 解析时如何检查输入 XML 中的错误?
- python - 如何使用用户名和密码的特定变量发送发布请求身份验证?
- flutter - 如何在颤动中保存图像?无法使用 .copy 方法。颤抖?
- sql - 试图让 python sqlite 与 DATE 而不是实际的 DATETIME 字段进行比较
- github - 使用 Gtihub Actions 通过 SFTP 部署时,获取“进程 '/usr/bin/git' 失败,退出代码为 5”。有谁知道这是什么意思?
- python - 字典理解从具有重复键值的元组列表中获取每个键项的平均值
- python - “setup.py sdist bdist_wheel”打包时出错
- node.js - Heroku github 推送失败,无法检测到默认语言