日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java衍生作用_java-如何从AffineTransform衍生的形状对象中“...

發布時間:2023/12/9 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java衍生作用_java-如何从AffineTransform衍生的形状对象中“... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

您可以使用AffineTransform.transform(Point2D, Point2D)變換多邊形上的單個點.

如果您不使用旋轉變換來移動船,而是將船的位置保持在一個(x,y)位置,那么事情就簡單得多.您可以在move()中移動飛船的位置,而不是嘗試平移多邊形.然后,當您想給船上油漆時,例如做:

// Optionally copying the Graphics so the

// transform doesn't 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();

}

@Override

public 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);

}

@Override

protected 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/second

rotationAngle = Math.PI * 3 / 2;

rotationRate = (2 * Math.PI) / 2; // radians/second

int 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 it's 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;

}

@Override

void 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);

}

}

@Override

void draw(Graphics2D g2) {

Graphics2D copy = (Graphics2D) g2.create();

copy.setColor(Color.RED);

// Translate to the ship's 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);

}

@Override

void update(double secondsElapsed) {

locX += secondsElapsed * velX;

locY += secondsElapsed * velY;

}

@Override

void 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.html

class 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() {

@Override

public 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();

@Override

void 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軸移動.明顯的側向移動是由于一系列旋轉串聯所致.)

總結

以上是生活随笔為你收集整理的java衍生作用_java-如何从AffineTransform衍生的形状对象中“...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。