如何使KeyListener为Java applet绘制一个Image

时间:2013-12-06 17:46:38

标签: java image applet keylistener

我正在尝试为类创建一个java applet游戏,允许用户上下移动来移动"播放器"拍摄"僵尸"使用空格键。我有一个"子弹"我正在尝试使用KeyListener,以便当用户按下空格键时," bullet"图像显示在屏幕上的玩家当前位置并在屏幕上移动。但是,当按下空格时,我会收到运行时错误,并且不会显示项目符号图像。如果有人能告诉我如何解决这个问题,我将非常感激!

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class ZombieAttackMain extends Applet implements Runnable, KeyListener{

    private Image background, normalZombie, fastZombie, tankyZombie,player,bullet, bloodSplat, cow;

    private Graphics bufferGraphics;
    private Graphics g;
    private Image offScreen;

    private final int POSITION_1_Y = 100;
    private final int POSITION_2_Y = 255;
    private final int POSITION_3_Y = 400;
    private final int POSITION_4_Y = 550;

    private final int PLAYER_X_POSITION = 250;
    private int playerYPosition = POSITION_3_Y;

    private int zombieStartingXPosition = 1000; //change to 1100 later
    private final int NORMAL_ZOMBIE_DX = -2;    //not final
    private final int FAST_ZOMBIE_DX = -3;      //not final
    private final int TANKY_ZOMBIE_DX = -1;     //not final
    private int zombieYPosition; //depends on the zombieYPositionRandom

    private int bulletStartingXPosition = 405;
    private int bulletYPosition;    //depends on player position
    private final int BULLET_DX = 5;    //not final

    private int bloodSplatX, bloodSplatY; //depend on dead zombie position

    //Called when applet starts
    public void init(){
        setSize(1100, 700);
        normalZombie = getImage(getCodeBase(), "NormalZombie.png");
        tankyZombie = getImage(getCodeBase(), "TankyZombie.png");
        fastZombie = getImage(getCodeBase(), "FastZombie.png");
        player = getImage(getCodeBase(), "Player.png");
        bullet = getImage(getCodeBase(), "Bullet.png");
        bloodSplat = getImage(getCodeBase(), "BloodSplat.png");
        background = getImage(getCodeBase(), "Background.jpg");
        cow = getImage(getCodeBase(), "Cow.png");
        addKeyListener(this);
    }
    //Called after init, sets up thread and starts it
    public void start() {
        Thread thread = new Thread(this);
        thread.start();
    }

    public void run() {
        while(true){
            repaint();
            try {
                Thread.sleep(17);     //about 60 fps
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public void update(Graphics g){
        if(offScreen == null){
            offScreen = createImage(this.getWidth(), this.getHeight());
            bufferGraphics = offScreen.getGraphics();
        }
        bufferGraphics.setColor(getBackground());
        bufferGraphics.fillRect(0,0,this.getWidth(),this.getHeight());

        bufferGraphics.setColor(getForeground());
        paint(bufferGraphics);

        g.drawImage(offScreen,0,0,this);
    }

    public void paint(Graphics g){
        g.drawImage(background,0,0,null);
        g.drawImage(cow,-15,115,null);
        g.drawImage(cow,-15,255,null);
        g.drawImage(cow,-15,400,null);
        g.drawImage(cow,-15,550,null);
        g.drawImage(normalZombie,zombieStartingXPosition,100,null);
        g.drawImage(tankyZombie,zombieStartingXPosition,400,null);
        g.drawImage(fastZombie,zombieStartingXPosition,255,null);
        g.drawImage(player,PLAYER_X_POSITION,playerYPosition, null);
        //g.drawImage(bullet,bulletStartingXPosition,336,this);
        g.drawImage(bloodSplat,bloodSplatX,bloodSplatY,null);
    }

    public void moveUp(Image player){
        if(playerYPosition == POSITION_2_Y){
            playerYPosition = POSITION_1_Y;
        }
        if(playerYPosition == POSITION_3_Y){
                playerYPosition = POSITION_2_Y;
        }
        if(playerYPosition == POSITION_4_Y){
            playerYPosition = POSITION_3_Y;
        }
    }

    public void moveDown(Image player){
        if(playerYPosition == POSITION_3_Y){
            playerYPosition = POSITION_4_Y;
        }
        if(playerYPosition == POSITION_2_Y){
            playerYPosition = POSITION_3_Y;
        }
        if(playerYPosition == POSITION_1_Y){
            playerYPosition = POSITION_2_Y;
        }

    }

    public void spawnBullet(){
        g.drawImage(bullet,bulletStartingXPosition, playerYPosition,null);
    }

    public void keyPressed(KeyEvent e) {
        switch(e.getKeyCode()){
        case KeyEvent.VK_UP:
            moveUp(player);
            break;
        case KeyEvent.VK_DOWN:
            moveDown(player);
            break;
        case KeyEvent.VK_SPACE:
            spawnBullet();
            break;
        } 
    }

    public void keyReleased(KeyEvent e) {

    }


    public void keyTyped(KeyEvent e) {

    }

    public void stop() {

    }

    public void destroy() {

    }
}

错误讯息:

Exception in thread "AWT-EventQueue-1" java.lang.NullPointerException
    at ZombieAttackMain.spawnBullet(ZombieAttackMain.java:118)
    at ZombieAttackMain.keyPressed(ZombieAttackMain.java:130)
    at java.awt.Component.processKeyEvent(Unknown Source)
    at java.awt.Component.processEvent(Unknown Source)
    at java.awt.Container.processEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.KeyboardFocusManager.redispatchEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(Unknown Source)
    at java.awt.DefaultKeyboardFocusManager.dispatchEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Container.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)

1 个答案:

答案 0 :(得分:1)

您的问题是您从未初始化private Graphics g。这可能一开始看起来不太明显,因为您的paint()update()方法使用g就好了,但在这些方法中,g是完全不同的,本地的{{1}对象这会使您的全局Graphics黯然失色。我的建议是删除g,因为实际上没有必要让另一个private Graphics g;对象浮动,并将Graphics更改为:

spawnBullet()

但是,因为每次更新都会清除整个屏幕,所以这不会显示子弹......仅使用public void spawnBullet(){ bufferGraphics.drawImage(bullet, bulletStartingXPosition, playerYPosition, null); } 方法绘制会更好,但这完全是另一个主题。

编辑:显示如何让子弹实际显示的示例

paint()