我不能让我的2D游戏对象移动

时间:2015-10-06 23:13:07

标签: java arrays swing

这是我的主要代码的代码。我尝试创建一个包含检查键盘操作的函数的包,但它不起作用。所以现在两个代码都在你看到的同一个文件下。到目前为止程序打开,我可以看到圆圈,但它不会向左或向右移动。我一直都在这,因为3小时相信与否。

编辑:我刚刚意识到更新函数从名为“input”的包中获取数据。那是在我将两个类放在相同的文件名之前,但即使有一个类名为“gamesample.input。*”的类,它仍然无效。

package gamesample;

import java.awt.*; 
import java.awt.event.KeyEvent; 
import java.awt.image.BufferedImage; 
import javax.swing.JFrame; 

 /** 
 * Main class for the game 
 */ 
public class GameSample extends JFrame 
{        
    boolean isRunning = true; 
    int fps = 30; 
    int windowWidth = 500; 
    int windowHeight = 500; 

    BufferedImage backBuffer; 
    Insets insets; 
    InputHandler input; 

    int x = 0; 

    public static void main(String[] args) 
    { 
            GameSample game = new GameSample(); 
            game.run(); 
            System.exit(0); 
    } 

    /** 
     * This method starts the game and runs it in a loop 
     */ 
    public void run() 
    { 
            initialize(); 

            while(isRunning) 
            { 
                    long time = System.currentTimeMillis(); 

                    update(); 
                    draw(); 

                    //  delay for each frame  -   time it took for one frame 
                    time = (1000 / fps) - (System.currentTimeMillis() - time); 

                    if (time > 0) 
                    { 
                            try 
                            { 
                                    Thread.sleep(time); 
                            } 
                            catch(Exception e){} 
                    } 
            } 

            setVisible(false); 
    } 

    /** 
     * This method will set up everything need for the game to run 
     */ 
    void initialize() 
    { 
            setTitle("Game Tutorial"); 
            setSize(windowWidth, windowHeight); 
            setResizable(false); 
            setDefaultCloseOperation(EXIT_ON_CLOSE); 
            setVisible(true); 

            insets = getInsets(); 
            setSize(insets.left + windowWidth + insets.right, 
                            insets.top + windowHeight + insets.bottom); 

            backBuffer = new BufferedImage(windowWidth, windowHeight, BufferedImage.TYPE_INT_RGB); 
            input = new InputHandler(this); 
    } 

    /** 
     * This method will check for input, move things 
     * around and check for win conditions, etc 
     */ 
    void update() 
    { 
            if (input.isKeyDown(KeyEvent.VK_RIGHT)) 
            { 
                    x += 5; 
            } 
            if (input.isKeyDown(KeyEvent.VK_LEFT)) 
            { 
                    x -= 5; 
            } 
    } 

    /** 
     * This method will draw everything 
     */ 
    void draw() 
    {               
            Graphics g = getGraphics(); 

            Graphics bbg = backBuffer.getGraphics(); 

            bbg.setColor(Color.WHITE); 
            bbg.fillRect(0, 0, windowWidth, windowHeight); 

            bbg.setColor(Color.BLACK); 
            bbg.drawOval(x, 10, 20, 20); 

            g.drawImage(backBuffer, insets.left, insets.top, this); 

    }
}

这是键盘代码

package gamesample;

import java.awt.Component; 
import java.awt.event.*; 

/** 
 * Makes handling input a lot simpler 
 */ 
public class InputHandler implements KeyListener 
 {        
 boolean keys[];
    /** 
     * Assigns the newly created InputHandler to a Component 
     * @param c Component to get input from 
     */ 


    public InputHandler(Component c) 
    { 
            c.addKeyListener(this); 
    } 

    /** 
     * Checks whether a specific key is down 
     * @param keyCode The key to check 
     * @return Whether the key is pressed or not 
     */ 
    public boolean isKeyDown(int keyCode) 
    { 


            if (keyCode > 0 && keyCode < 256) 
            {  keys = new boolean [256];
                    return keys[keyCode]; 
            } 

            return false; 
    } 

    /** 
     * Called when a key is pressed while the component is focused 
     * @param e KeyEvent sent by the component 
     */ 
    public void keyPressed(KeyEvent e) 
    { boolean keys[];
            if (e.getKeyCode() > 0 && e.getKeyCode() < 256) 
            { keys = new boolean [256];
                    keys[e.getKeyCode()] = true; 
            } 
    } 

    /** 
     * Called when a key is released while the component is focused 
     * @param e KeyEvent sent by the component 
     */ 
    public void keyReleased(KeyEvent e) 
    { boolean keys[];
            if (e.getKeyCode() > 0 && e.getKeyCode() < 256) 
            { keys = new boolean [256];
                    keys[e.getKeyCode()] = false; 
            } 
    } 

    /** 
     * Not used 
     */ 
    public void keyTyped(KeyEvent e){} 
} 

1 个答案:

答案 0 :(得分:1)

Graphics g = getGraphics();不是应该如何进行自定义绘画。 Swing使用被动渲染算法,这意味着您的UI可以随时重新绘制,原因有很多,其中许多原因是您无法控制的。默认情况下,Swing也是双缓冲的,所以如果您实际使用JPanel并覆盖它的paintComponent方法,您将免费获得双缓冲并且您​​将成为通知任何系统相关的油漆事件。

有关详细信息,请参阅Painting in AWT and SwingPerforming Custom Painting

不要使用KeyListener,它太麻烦了,而且键绑定API解决了它所遇到的所有问题。有关详细信息,请参阅How to Use Key Bindings

请记住,Swing是一个单线程框架,并不是线程安全的。这意味着你永远不应该以任何方式阻止事件调度线程(比如使用永无止境的循环),你应该只在EDT的上下文中更新UI。

你&#34;主循环&#34;两者都有危险。代码不会阻止EDT,这是JVM性质的侥幸,但这也意味着你违反了Swing的单线程特性。

有关详细信息,请参阅Concurrency in Swing

通常情况下,我会使用Swing Timer进行此类工作,因为它的回调会在EDT的上下文中同步,但您可以使用{{1} },但您必须手动将更新同步回EDT。

如果您希望完全控制绘画过程,则应使用Thread,有关详细信息,请参阅BufferStrategyBufferStrategy and BufferCapabilities

作为上述概念的basic example