Java 使用组件方法进行慢速运动
我决定用Swing的绘画技巧paintComponent()方法重新编写我的游戏(有人告诉我使用这个方法)。我决定使用JPanel作为游戏的基础,而不是画布。我以前编写的游戏使用画布,但该游戏无法显示在我的64位桌面上,但可以显示在我的32位labtop上,这就是为什么必须重新编写该游戏的原因 现在的问题是,当飞船运动正常时,绘图速度似乎非常慢(除非是我的笔记本电脑问题?),而我之前使用的是AWT的双缓冲绘图技术。我花了一整天的时间,但不知道是什么能使船跑得更快Java 使用组件方法进行慢速运动,java,graphics,paintcomponent,paint,Java,Graphics,Paintcomponent,Paint,我决定用Swing的绘画技巧paintComponent()方法重新编写我的游戏(有人告诉我使用这个方法)。我决定使用JPanel作为游戏的基础,而不是画布。我以前编写的游戏使用画布,但该游戏无法显示在我的64位桌面上,但可以显示在我的32位labtop上,这就是为什么必须重新编写该游戏的原因 现在的问题是,当飞船运动正常时,绘图速度似乎非常慢(除非是我的笔记本电脑问题?),而我之前使用的是AWT的双缓冲绘图技术。我花了一整天的时间,但不知道是什么能使船跑得更快 public class
public class Ship extends JLabel implements KeyListener{
private Image image;
private boolean turnRight;
private int x;
private int y;
private int speed = 5;
private boolean turnLeft;
public Ship(int x, int y)
{
this.x = x;
this.y = y;
try {
image = ImageIO.read(new File("Ship/Ship.PNG"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
addKeyListener(this);
}
public Image getImage()
{
return image;
}
@Override
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if(e.getKeyCode() == KeyEvent.VK_RIGHT)
{
x += speed;
setTurnRight(true);
setTurnLeft(false);
}
else if(e.getKeyCode() == KeyEvent.VK_LEFT)
{
x -= speed;
setTurnLeft(true);
setTurnRight(false);
}
// redraw yourself
repaint();
}
private void setTurnLeft(boolean turnLeft) {
// TODO Auto-generated method stub
this.turnLeft = turnLeft;
}
// swing custom painting
public void paintComponent(Graphics g)
{
if(x <= 0)
{
x = 0;
}
else if(x >= 610)
{
x = 610;
}
g.drawImage(getImage(), x, y, null);
}
public void setTurnRight(boolean turnRight)
{
this.turnRight = turnRight;
}
public boolean getTurnLeft()
{
return turnLeft;
}
public boolean getTurnRight()
{
return turnRight;
}
@Override
public void keyReleased(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
}
public-class-Ship-extends-JLabel实现KeyListener{
私有图像;
私有布尔右转;
私人INTX;
私营企业;
私人内部速度=5;
私人布尔左转;
公共船舶(国际x、国际y)
{
这个.x=x;
这个。y=y;
试一试{
image=ImageIO.read(新文件(“Ship/Ship.PNG”);
}捕获(IOE异常){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
addKeyListener(此);
}
公共映像getImage()
{
返回图像;
}
@凌驾
按下公共无效键(按键事件e){
//TODO自动生成的方法存根
if(e.getKeyCode()==KeyEvent.VK_RIGHT)
{
x+=速度;
setTurnRight(正确);
设置左转(假);
}
else if(e.getKeyCode()==KeyEvent.VK_LEFT)
{
x-=速度;
设置左转(真);
setTurnRight(错误);
}
//重画你自己
重新油漆();
}
私有void设置左转(布尔左转){
//TODO自动生成的方法存根
this.turnlight=左转;
}
//秋千定制绘画
公共组件(图形g)
{
如果(x=610)
{
x=610;
}
g、 drawImage(getImage(),x,y,null);
}
公共void setTurnRight(布尔turnRight)
{
this.turnRight=turnRight;
}
公共布尔getTurnLeft()
{
左转返回;
}
公共布尔getTurnRight()
{
回程右转;
}
@凌驾
公共无效密钥已释放(密钥事件e){
//TODO自动生成的方法存根
}
@凌驾
public void keyTyped(KeyEvent e){
//TODO自动生成的方法存根
}
}
我建议使用一个扩展JPanel的类,在其中使用javax.swing.Timer,定义1000/fps和ActionListener,在其中使用一个repaint()函数,该函数使用一个paintComponent函数,该函数将调用船上的draw方法,现在称为paintComponent
由于这种解释很糟糕,下面是一些代码:
public class Class_Name extends JPanel()
{
Ship ship = new Ship(0,0);
javax.swing.Timer timer = new javax.swing.Timer(1000/60, new ActionListener(){
repaint();
});
public void paintComponent(Graphics g)
{
super.paintComponent();
ship.draw(g);
}
}
and the draw is, what is now called paintComponent.
如果这没有回答您的问题,请告诉我。通常,我会创建一个可渲染元素的概念。我将维护这些元素的列表,并在我的主循环中相应地更新它们 至少,每个都有一个位置、方向和旋转的概念(如果需要的话),它们也可以被绘制 在我的主要组件中,我将简单地循环所有这些元素并“绘制”它们,偏移
图形
上下文以允许在游戏空间中有位置
但那不是你正在做的
请记住,组件已经有了位置感和大小感,您不应该试图重新实现此要求,相反,您应该找到利用它的方法…(即,不要维护对x/y值的引用;)
下面是一个简单的例子。它使用JPanel
渲染主图像。主循环(在本例中是一个javax.swing.Timer
)告诉组件它应该根据需要更新它的移动
船舶本身通过改变给定的可变增量的旋转值来响应关键事件。这可以让你根据需要控制旋转的速度(我故意先把它设置得很低,所以就用它玩吧)
您应该抵制的是更改帧速率;)
导入java.awt.BorderLayout;
导入java.awt.Color;
导入java.awt.Dimension;
导入java.awt.EventQueue;
导入java.awt.Graphics;
导入java.awt.Graphics2D;
导入java.awt.GridBagLayout;
导入java.awt.event.ActionEvent;
导入java.awt.event.ActionListener;
导入java.awt.event.KeyEvent;
导入java.awt.geom.AffineTransform;
导入java.awt.image.buffereImage;
导入java.io.File;
导入java.io.IOException;
导入javax.imageio.imageio;
导入javax.swing.AbstractAction;
导入javax.swing.ActionMap;
导入javax.swing.InputMap;
导入javax.swing.JFrame;
导入javax.swing.JPanel;
导入javax.swing.KeyStroke;
导入javax.swing.Timer;
导入javax.swing.UIManager;
导入javax.swing.UnsupportedLookAndFeelException;
导入javax.swing.border.LineBorder;
公共级战舰游戏{
公共静态void main(字符串[]args){
新战舰游戏();
}
公共战舰游戏(){
invokeLater(新的Runnable(){
@凌驾
公开募捐{
试一试{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}catch(ClassNotFoundException |实例化Exception | IllegalacessException |不支持ookandfeelException ex){
}
JFrame=新JFrame(“测试”);
frame.setDefaultC
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
public class BattleShipGame {
public static void main(String[] args) {
new BattleShipGame();
}
public BattleShipGame() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new OceanPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class OceanPane extends JPanel {
private BattleShip ship;
public OceanPane() {
setLayout(new GridBagLayout());
ship = new BattleShip();
add(ship);
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ship.move();
revalidate();
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
}
public static class BattleShip extends JPanel {
protected static final int MAX_TURN_RATE = 5;
private BufferedImage ship;
private float angle;
private float angleDelta;
public BattleShip() {
setOpaque(false);
try {
ship = ImageIO.read(new File("BattleShip.png"));
} catch (IOException ex) {
ex.printStackTrace();
}
setFocusable(true);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0), "leftTurn");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0), "rightTurn");
am.put("leftTurn", new TurnAction(-0.1f));
am.put("rightTurn", new TurnAction(0.1f));
}
public void move() {
angle += angleDelta;
}
public void setAngle(float angle) {
this.angle = angle;
}
public float getAngle() {
return angle;
}
@Override
public Dimension getPreferredSize() {
Dimension size = new Dimension(0, 0);
if (ship != null) {
double rads = Math.toRadians(getAngle());
double sin = Math.abs(Math.sin(rads)), cos = Math.abs(Math.cos(rads));
int w = ship.getWidth();
int h = ship.getHeight();
size.width = (int) Math.floor(w * cos + h * sin);
size.height = (int) Math.floor(h * cos + w * sin);
}
return size;
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (ship != null) {
Graphics2D g2d = (Graphics2D) g.create();
double rads = Math.toRadians(getAngle());
double sin = Math.abs(Math.sin(rads)), cos = Math.abs(Math.cos(rads));
int w = ship.getWidth();
int h = ship.getHeight();
int newWidth = (int) Math.floor(w * cos + h * sin);
int newHeight = (int) Math.floor(h * cos + w * sin);
AffineTransform at = new AffineTransform();
at.translate((newWidth - w) / 2, (newHeight - h) / 2);
at.rotate(Math.toRadians(getAngle()), w / 2, h / 2);
g2d.drawImage(ship, at, this);
g2d.dispose();
}
}
protected class TurnAction extends AbstractAction {
protected float delta;
public TurnAction(float delta) {
this.delta = delta;
}
@Override
public void actionPerformed(ActionEvent e) {
angleDelta += delta;
if (angleDelta > MAX_TURN_RATE) {
angleDelta = MAX_TURN_RATE;
} else if (angleDelta < (MAX_TURN_RATE * -1)) {
angleDelta = (MAX_TURN_RATE * -1);
}
}
}
}
}