Java的Paint方法出现问题,可笑的刷新速度
我正在开发R-Type的一个非常简单的版本作为大学的工作,但尽pipe它的工作,手艺速度是很慢,所以运动是丑陋和笨拙。 我用刷新的方法刷新屏幕,还有其他的方法或方法最好吗?
运动video
在主面板上绘制方法
@Override public void paint(Graphics g) { super.paint(g); Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2.drawImage(fondo, 0, 0,1200,600,this); pj.paint(g2); g2D=g2; }
PJ的油漆方法
public void paint(Graphics2D g) { g.drawImage(imagen,x,y,this); }
PJ的移动方法
public void move (KeyEvent e) { int dx = 0; int dy = 0; int code = e.getKeyCode(); switch (code) { case KeyEvent.VK_Q: dy-=1; break; case KeyEvent.VK_A: dy+=1; break; case KeyEvent.VK_P: dx+=1; break; case KeyEvent.VK_O: dx-=1; break; } int x = (getX()<maxX&&getX()!=0) ? getX()+dx : getX(); int y = (getY()<maxY&&getY()!=0) ? getY()+dy : getY(); if (getY()>=maxY||getY()==0) { if (dy==+1) y=y+1; } setPosicion(x, y); }
- 图片
fondo
应该已经被缩放到1200×600。 - 我不确定,但是需要
super.paint(g)
吗? 你也可以使用paintComponent
。
事件处理(你似乎在键上移动1个像素),必须正确完成。 我会设置方向和速度(1px),并让它摆动定时器来做连续移动。
重新涂刷最好做弹性/弹性: repaint(20L)
涂漆repaint(20L)
(每秒50帧); EventQueue.invokeLater(new Runnable() { ... });
。
特别是您可能会使用重新绘制已更改的区域。
你可以在这里find一个类似程序的好例子。 这个例子演示了如何创build一个新的线程,让这个线程在主循环中进行每一次迭代。
下面是关于在Java中加载游戏图像的另一个问题。
它看起来像挥杆本身是非常糟糕的游戏中使用的图像。 你可能想考虑使用更合适的库。
下面是使用背景作为简单游戏循环的简单示例。 它更新游戏对象的状态并计算所需的延迟以保持所需的fps。
游戏对象( Ship
)能够在短时间内加速/减速
import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.awt.geom.Path2D; 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.UIManager; import javax.swing.UnsupportedLookAndFeelException; public class AnimationTest { public static void main(String[] args) { new AnimationTest(); } public AnimationTest() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new GamePane()); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } public class GamePane extends JPanel { private Ship ship; public GamePane() { ship = new Ship(); Thread thread = new Thread(new MainLoop(this)); thread.setDaemon(true); thread.start(); InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW); ActionMap am = getActionMap(); // Key controls... im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "upPressed"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "downPressed"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "upReleased"); im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "downReleased"); am.put("upPressed", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { // Change the direction... ship.setDirection(-1); // Accelerate by 1 per frame ship.setVelocity(1); } }); am.put("downPressed", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { // Change direction ship.setDirection(1); // Accelerate by 1 per frame ship.setVelocity(1); } }); am.put("upReleased", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { // Deccelerate by 1 per frame ship.setVelocity(-1); } }); am.put("downReleased", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { // Deccelerate by 1 per frame ship.setVelocity(-1); } }); } @Override public Dimension getPreferredSize() { return new Dimension(200, 200); } public void updateState() { // Update the state of the game objects. // This would typically be better done in // some kind of model ship.update(getWidth(), getHeight()); } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); // Paint the game state... Graphics2D g2d = (Graphics2D) g.create(); ship.paint(g2d); g2d.dispose(); } } public class MainLoop implements Runnable { private GamePane pane; private int fps = 25; public MainLoop(GamePane pane) { this.pane = pane; } @Override public void run() { // Wait until the screen is ready while (pane.getHeight() <= 0) { try { Thread.sleep(125); } catch (InterruptedException ex) { } } // Main loop while (true) { // Start time loop long startTime = System.currentTimeMillis(); // Update the game state pane.updateState(); // Calculate the amount of time it took to update long elasped = System.currentTimeMillis() - startTime; // Calculate the number of milliseconds we need to sleep long sleep = Math.round((1000f / fps) - elasped); pane.repaint(); if (sleep > 0) { try { Thread.sleep(sleep); } catch (InterruptedException ex) { } } } } } public static class Ship { public static int MAX_SPEED = 8; private int direction = 0; private int velocity = 0; private int x; private int y; private int speed = 0; private Path2D shape; private boolean initState; public Ship() { shape = new Path2D.Float(); shape.moveTo(0, 0); shape.lineTo(5, 5); shape.lineTo(0, 10); shape.lineTo(0, 0); shape.closePath(); initState = true; } public void setDirection(int direction) { this.direction = direction; } public void setVelocity(int velocity) { this.velocity = velocity; } public void update(int width, int height) { if (initState) { y = (height - 10) / 2; initState = false; } else { // Add the velocity to the speed speed += velocity; // Don't over accelerate if (speed > MAX_SPEED) { speed = MAX_SPEED; } else if (speed < 0) { speed = 0; } // Adjust out position if we're moving if (speed > 0) { y += (direction * speed); } // Bounds check... if (y - 5 < 0) { y = 5; } else if (y + 5 > height) { y = height - 5; } } } public void paint(Graphics2D g2d) { int yPos = y - 5; g2d.translate(10, yPos); g2d.fill(shape); g2d.translate(-10, -yPos); } } }