网页制作网站素材,jsp网站开发如何把自横批排,线上推广策略,网站建立需要多久您可以使用AffineTransform.transform(Point2D, Point2D)变换多边形上的单个点.如果您不使用旋转变换来移动船,而是将船的位置保持在一个(x,y)位置,那么事情就简单得多.您可以在move()中移动飞船的位置,而不是尝试平移多边形.然后,当您想给船上油漆时,例如做#xff1a;// Opt…您可以使用AffineTransform.transform(Point2D, Point2D)变换多边形上的单个点.如果您不使用旋转变换来移动船,而是将船的位置保持在一个(x,y)位置,那么事情就简单得多.您可以在move()中移动飞船的位置,而不是尝试平移多边形.然后,当您想给船上油漆时,例如做// Optionally copying the Graphics so the// transform doesnt affect later painting.Graphics2D temp (Graphics2D) g2d.create();temp.translate(ship.locX, ship.locY);temp.rotate(ship.angle);temp.draw(ship);要基于速度移动点,可以执行以下操作来找到运动向量double velX speed * Math.cos(angle);double velY speed * Math.sin(angle);locX timeElapsed * velX;locY timeElapsed * velY;这实质上是从极坐标到笛卡尔坐标的转换. x和y速度是三角形的边,其斜边为速度,已知角度为角度/|/ |/ |/ |speed / |/ |/ |velY/ angle |/)_______|velX对于您的评论Are you saying that, unlike my initial move function, just to make ship hold a single point, and thus I would only translate that instead?或多或少,是的.您仍然需要有一个多边形来保持船的形状,但是多边形上的点将相对于(0,0).假设以下定义多边形上的每个(x,y)点都是pi. (换句话说,p0,p1,p2和p3中的一个.)平移的(x,y)坐标为T然后,在转换Graphics2D之后,每个pi坐标在面板上变为piT.因此,如果您的多边形点是相对于(0,0)定义的,则平移到飞船的(locX,locY)会将多边形移动到相对于(locX,locY)的位置.然后,将多边形的尖端定义为(0,0)可能是最简单的,这样在平移之后,船的尖端就是船的位置// Your original points:int xPoints[] {800, 780, 800, 820};int yPoints[] {400, 460, 440, 460};// Become these points relative to (0,0):int xPoints[] {0, -20, 0, 20};int yPoints[] {0, 60, 40, 60};和例如在同一个地方开船,您将其位置初始化为(800,400).我又想了一下,意识到旋转有点复杂,因为您可能不想绕着尖端旋转船.您可能想绕船的中心旋转船.因此,这里有一个MCVE演示了如何进行所有这些操作.package mcve.game;import javax.swing.*;import java.awt.event.*;import java.awt.geom.*;import java.awt.Polygon;import java.awt.RenderingHints;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Color;import java.awt.Dimension;import java.awt.Rectangle;import java.awt.Insets;import java.awt.Toolkit;import java.awt.GraphicsConfiguration;import java.util.Set;import java.util.HashSet;import java.util.List;import java.util.ArrayList;public class MovementExample implements ActionListener {public static void main(String[] args) {SwingUtilities.invokeLater(MovementExample::new);}final int fps 60;final int period 1000 / fps;final JFrame frame;final GamePanel panel;final Controls controls;final Ship ship;final List bullets new ArrayList();MovementExample() {frame new JFrame(Movement Example);Dimension size getMaximumWindowSize(frame);size.width / 2;size.height / 2;frame.setPreferredSize(size);panel new GamePanel();frame.setContentPane(panel);frame.pack();frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setLocationRelativeTo(null);frame.setVisible(true);controls new Controls();ship new Ship(panel.getWidth() / 2,panel.getHeight() / 2);new Timer(period, this).start();}Overridepublic void actionPerformed(ActionEvent e) {double secondsElapsed 1.0 / fps;ship.update(secondsElapsed);bullets.forEach(b - b.update(secondsElapsed));Rectangle bounds panel.getBounds();bullets.removeIf(b - !bounds.contains(b.locX, b.locY));panel.repaint();}class GamePanel extends JPanel {GamePanel() {setBackground(Color.WHITE);}Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);Graphics2D g2 (Graphics2D) g.create();g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);if (ship ! null) {ship.draw(g2);}bullets.forEach(b - b.draw(g2));g2.dispose();}}abstract class AbstractGameObject {double maxSpeed;double rotationAngle;double locX;double locY;double velX;double velY;AbstractGameObject(double initialX, double initialY) {locX initialX;locY initialY;}abstract void update(double secondsElapsed);abstract void draw(Graphics2D g2);}class Ship extends AbstractGameObject {Polygon shape;double rotationRate;Ship(double initialX, double initialY) {super(initialX, initialY);maxSpeed 128; // pixels/secondrotationAngle Math.PI * 3 / 2;rotationRate (2 * Math.PI) / 2; // radians/secondint xPoints[] {0, -20, 0, 20};int yPoints[] {0, 60, 40, 60};shape new Polygon(xPoints, yPoints, 4);}Point2D.Double getTip() {Point2D.Double center getCenter();// The tip is at (0,0) and its already centered// on the x-axis origin, so the distance from the// tip to the center is just center.y.double distance center.y;// Then find the location of the tip, relative// to the center.double tipX distance * Math.cos(rotationAngle);double tipY distance * Math.sin(rotationAngle);// Now find the actual location of the center.center.x locX;center.y locY;// And return the actual location of the tip, relative// to the actual location of the center.return new Point2D.Double(tipX center.x, tipY center.y);}Point2D.Double getCenter() {// Returns the center point of the ship,// relative to (0,0).Point2D.Double center new Point2D.Double();for (int i 0; i shape.npoints; i) {center.x shape.xpoints[i];center.y shape.ypoints[i];}center.x / shape.npoints;center.y / shape.npoints;return center;}Overridevoid update(double secondsElapsed) {// See my answer here: https://stackoverflow.com/a/43692434/2891664// for a discussion of why this logic is the way it is.double speed 0;if (controls.isUpHeld()) {speed maxSpeed;}if (controls.isDownHeld()) {speed - maxSpeed;}velX speed * Math.cos(rotationAngle);velY speed * Math.sin(rotationAngle);locX secondsElapsed * velX;locY secondsElapsed * velY;double rotation 0;if (controls.isLeftHeld()) {rotation - rotationRate;}if (controls.isRightHeld()) {rotation rotationRate;}rotationAngle secondsElapsed * rotation;// Cap the angle so it can never e.g. get so// large that it loses precision.if (rotationAngle 2 * Math.PI) {rotationAngle - 2 * Math.PI;}if (controls.isFireHeld()) {Point2D.Double tipLoc getTip();Bullet bullet new Bullet(tipLoc.x, tipLoc.y, rotationAngle);bullets.add(bullet);}}Overridevoid draw(Graphics2D g2) {Graphics2D copy (Graphics2D) g2.create();copy.setColor(Color.RED);// Translate to the ships location.copy.translate(locX, locY);// Rotate the ship around its center.Point2D.Double center getCenter();// The PI/2 offset is necessary because the// polygon points are defined with the ship// already vertical, i.e. at an angle of -PI/2.copy.rotate(rotationAngle (Math.PI / 2), center.x, center.y);copy.fill(shape);}}class Bullet extends AbstractGameObject {Ellipse2D.Double shape new Ellipse2D.Double();Bullet(double initialX, double initialY, double initialRotation) {super(initialX, initialY);maxSpeed 512;rotationAngle initialRotation;velX maxSpeed * Math.cos(rotationAngle);velY maxSpeed * Math.sin(rotationAngle);double radius 3;shape.setFrame(-radius, -radius, 2 * radius, 2 * radius);}Overridevoid update(double secondsElapsed) {locX secondsElapsed * velX;locY secondsElapsed * velY;}Overridevoid draw(Graphics2D g2) {Graphics2D copy (Graphics2D) g2.create();copy.setColor(Color.BLACK);copy.translate(locX, locY);copy.fill(shape);}}// See https://docs.oracle.com/javase/tutorial/uiswing/misc/keybinding.htmlclass Controls {final Set keysHeld new HashSet();Controls() {bind(KeyEvent.VK_A, left);bind(KeyEvent.VK_D, right);bind(KeyEvent.VK_W, up);bind(KeyEvent.VK_S, down);bind(KeyEvent.VK_SPACE, fire);}boolean isLeftHeld() { return keysHeld.contains(KeyEvent.VK_A); }boolean isRightHeld() { return keysHeld.contains(KeyEvent.VK_D); }boolean isUpHeld() { return keysHeld.contains(KeyEvent.VK_W); }boolean isDownHeld() { return keysHeld.contains(KeyEvent.VK_S); }boolean isFireHeld() { return keysHeld.contains(KeyEvent.VK_SPACE); }void bind(int keyCode, String name) {bind(keyCode, name, true);bind(keyCode, name, false);}void bind(int keyCode, String name, boolean isOnRelease) {KeyStroke stroke KeyStroke.getKeyStroke(keyCode, 0, isOnRelease);name isOnRelease ? .released : .pressed;panel.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(stroke, name);panel.getActionMap().put(name, new AbstractAction() {Overridepublic void actionPerformed(ActionEvent e) {if (isOnRelease) {keysHeld.remove(keyCode);} else {keysHeld.add(keyCode);}}});}}// This returns the usable size of the display which// the JFrame resides in, as described here:// http://docs.oracle.com/javase/8/docs/api/java/awt/GraphicsEnvironment.html#getMaximumWindowBounds--static Dimension getMaximumWindowSize(JFrame frame) {GraphicsConfiguration config frame.getGraphicsConfiguration();Dimension size config.getBounds().getSize();Insets insets Toolkit.getDefaultToolkit().getScreenInsets(config);size.width - insets.left insets.right;size.height - insets.top insets.bottom;return size;}}还有其他方法可以计算出船的顶端,但是我在MCVE中做到的方式是获取相对于(0,0)的船的中心点.获取从中心点到尖端的距离.尖端在(0,0),因此这只是中心的y坐标.然后计算尖端相对于中心的(x,y)位置.速度和速度与上图非常相似,但是斜边是船的中心与船头之间的距离.将中心平移为相对于船的位置.将尖端的位置(相对于中心)转换为相对于船的位置.也可以使用AffineTransform完成所有操作,类似于您在问题代码中所做的操作,但是您需要在每次更新时进行设置.像这样AffineTransform transform new AffineTransform();Overridevoid update(double secondsElapsed) {...// Clear the previous translation and rotation.transform.setToIdentity();// Set to current.transform.translate(locX, locY);Point2D.Double center getCenter();transform.rotate(rotationAngle (Math.PI / 2), center.x, center.y);if (controls.isFireHeld()) {Point2D.Double tip new Point2D.Double(0, 0);transform.transform(tip, tip);Bullet bullet new Bullet(tip.x, tip.y, rotationAngle);bullets.add(bullet);}}您仍然可以通过这种方式使用变换来进行计算,但最终不会因依赖于移动而产生任何怪异. (在问题代码中,例如,船舶仅沿y轴移动.明显的侧向移动是由于一系列旋转串联所致.)