java 游戏编程 (六)

现在来让Fly移动。上一节已经能够监听键盘。现在对监听键盘事件做进一步封装。
首先设计一个类:GameAction.主要处理所有的键盘与鼠标事件,能够保存事件,在需要的时候调出。并能够设置键贴图,键贴图在另一个类InputManager中实现。所谓键贴图就是将按下的键具备什么功能做一个映射。先来看GameAction:引用Brackeen。
package com.jsheng.game.util;

/**
 * function: company: jsheng
 * 
 * @author wanghn [email protected]
 */
public class GameAction {
	//标识一个正常行为
	public static final int NORMAL = 0;
	//按下键后返回值为1,放开喝再次按下也为1.
	public static final int DETECT_INITAL_PRESS_ONLY = 1;
	
	private static final int STATE_RELEASED = 0;
	private static final int STATE_PRESSED = 1;
	private static final int STATE_WAITING_FOR_RELEASE = 2;

	private String name;   	//动作名
	private int behavior;	//行为
	private int count;		//按下的次数
	private int state;		//状态

	public GameAction(String name) {
		this(name, NORMAL);
	}

	public GameAction(String name, int behavior) {
		this.name = name;
		this.behavior = behavior;
		reset();
	}

	public String getName() {
		return name;
	}

	public void reset() {
		state = STATE_RELEASED;
		count = 0;
	}

	
	public void tap() {
		press();
		release();
	}

	//表示键被按下
	public void press() {
		press(1);
	}

	public void press(int amount) {
		if (state != STATE_WAITING_FOR_RELEASE) {
			this.count += amount;
			state = STATE_PRESSED;
		}
	}

	public void release() {
		state = STATE_RELEASED;
	}

	public boolean isPressed() {
		return (getCount() != 0);
	}

	//检查按下的次数
	public int getCount() {
		int s = count;
		if (s != 0) {
			if (state == STATE_RELEASED) {
				count = 0;
			} else if (behavior == DETECT_INITAL_PRESS_ONLY) {
				state = STATE_WAITING_FOR_RELEASE;
				count = 0;
			}
		}
		return s;
	}
}


然后创建输入管理器这个类,代码比较长,但很简单:
package com.jsheng.game.util;

import java.awt.*;
import java.awt.event.*;
import java.util.List;
import java.util.ArrayList;
import javax.swing.SwingUtilities;

/** function:
 * company: jsheng
 * @author wanghn      [email protected]
 */
public class InputManager implements KeyListener, MouseListener,
    MouseMotionListener, MouseWheelListener
{
    public static final Cursor INVISIBLE_CURSOR =
        Toolkit.getDefaultToolkit().createCustomCursor(
            Toolkit.getDefaultToolkit().getImage(""),
            new Point(0,0),
            "invisible");

    public static final int MOUSE_MOVE_LEFT = 0;
    public static final int MOUSE_MOVE_RIGHT = 1;
    public static final int MOUSE_MOVE_UP = 2;
    public static final int MOUSE_MOVE_DOWN = 3;
    public static final int MOUSE_WHEEL_UP = 4;
    public static final int MOUSE_WHEEL_DOWN = 5;
    public static final int MOUSE_BUTTON_1 = 6;
    public static final int MOUSE_BUTTON_2 = 7;
    public static final int MOUSE_BUTTON_3 = 8;

    private static final int NUM_MOUSE_CODES = 9;

    private static final int NUM_KEY_CODES = 600;

    private GameAction[] keyActions =
        new GameAction[NUM_KEY_CODES];
    private GameAction[] mouseActions =
        new GameAction[NUM_MOUSE_CODES];

    private Point mouseLocation;
    private Point centerLocation;
    private Component comp;
    private Robot robot;
    private boolean isRecentering;

    public InputManager(Component comp) {
        this.comp = comp;
        mouseLocation = new Point();
        centerLocation = new Point();

        comp.addKeyListener(this);
        comp.addMouseListener(this);
        comp.addMouseMotionListener(this);
        comp.addMouseWheelListener(this);
        comp.setFocusTraversalKeysEnabled(false);
    }

    public void setCursor(Cursor cursor) {
        comp.setCursor(cursor);
    }


    public void setRelativeMouseMode(boolean mode) {
        if (mode == isRelativeMouseMode()) {
            return;
        }

        if (mode) {
            try {
                robot = new Robot();
                recenterMouse();
            }
            catch (AWTException ex) {
                // couldn't create robot!
                robot = null;
            }
        }
        else {
            robot = null;
        }
    }


    public boolean isRelativeMouseMode() {
        return (robot != null);
    }


    public void mapToKey(GameAction gameAction, int keyCode) {
        keyActions[keyCode] = gameAction;
    }


    public void mapToMouse(GameAction gameAction,
        int mouseCode)
    {
        mouseActions[mouseCode] = gameAction;
    }

    public void clearMap(GameAction gameAction) {
        for (int i=0; i<keyActions.length; i++) {
            if (keyActions[i] == gameAction) {
                keyActions[i] = null;
            }
        }

        for (int i=0; i<mouseActions.length; i++) {
            if (mouseActions[i] == gameAction) {
                mouseActions[i] = null;
            }
        }

        gameAction.reset();
    }

    public List<String> getMaps(GameAction gameCode) {
        ArrayList<String> list = new ArrayList<String>();

        for (int i=0; i<keyActions.length; i++) {
            if (keyActions[i] == gameCode) {
                list.add(getKeyName(i));
            }
        }

        for (int i=0; i<mouseActions.length; i++) {
            if (mouseActions[i] == gameCode) {
                list.add(getMouseName(i));
            }
        }
        return list;
    }

    public void resetAllGameActions() {
        for (int i=0; i<keyActions.length; i++) {
            if (keyActions[i] != null) {
                keyActions[i].reset();
            }
        }

        for (int i=0; i<mouseActions.length; i++) {
            if (mouseActions[i] != null) {
                mouseActions[i].reset();
            }
        }
    }

    public static String getKeyName(int keyCode) {
        return KeyEvent.getKeyText(keyCode);
    }


    public static String getMouseName(int mouseCode) {
        switch (mouseCode) {
            case MOUSE_MOVE_LEFT: return "Mouse Left";
            case MOUSE_MOVE_RIGHT: return "Mouse Right";
            case MOUSE_MOVE_UP: return "Mouse Up";
            case MOUSE_MOVE_DOWN: return "Mouse Down";
            case MOUSE_WHEEL_UP: return "Mouse Wheel Up";
            case MOUSE_WHEEL_DOWN: return "Mouse Wheel Down";
            case MOUSE_BUTTON_1: return "Mouse Button 1";
            case MOUSE_BUTTON_2: return "Mouse Button 2";
            case MOUSE_BUTTON_3: return "Mouse Button 3";
            default: return "Unknown mouse code " + mouseCode;
        }
    }

    public int getMouseX() {
        return mouseLocation.x;
    }

    public int getMouseY() {
        return mouseLocation.y;
    }

    private synchronized void recenterMouse() {
        if (robot != null && comp.isShowing()) {
            centerLocation.x = comp.getWidth() / 2;
            centerLocation.y = comp.getHeight() / 2;
            SwingUtilities.convertPointToScreen(centerLocation,
                comp);
            isRecentering = true;
            robot.mouseMove(centerLocation.x, centerLocation.y);
        }
    }


    private GameAction getKeyAction(KeyEvent e) {
        int keyCode = e.getKeyCode();
        if (keyCode < keyActions.length) {
            return keyActions[keyCode];
        }
        else {
            return null;
        }
    }

    public static int getMouseButtonCode(MouseEvent e) {
         switch (e.getButton()) {
            case MouseEvent.BUTTON1:
                return MOUSE_BUTTON_1;
            case MouseEvent.BUTTON2:
                return MOUSE_BUTTON_2;
            case MouseEvent.BUTTON3:
                return MOUSE_BUTTON_3;
            default:
                return -1;
        }
    }


    private GameAction getMouseButtonAction(MouseEvent e) {
        int mouseCode = getMouseButtonCode(e);
        if (mouseCode != -1) {
             return mouseActions[mouseCode];
        }
        else {
             return null;
        }
    }


    public void keyPressed(KeyEvent e) {
        GameAction gameAction = getKeyAction(e);
        if (gameAction != null) {
            gameAction.press();
        }
        e.consume();
    }


    public void keyReleased(KeyEvent e) {
        GameAction gameAction = getKeyAction(e);
        if (gameAction != null) {
            gameAction.release();
        }
        e.consume();
    }


    public void keyTyped(KeyEvent e) {
        e.consume();
    }


    public void mousePressed(MouseEvent e) {
        GameAction gameAction = getMouseButtonAction(e);
        if (gameAction != null) {
            gameAction.press();
        }
    }


    public void mouseReleased(MouseEvent e) {
        GameAction gameAction = getMouseButtonAction(e);
        if (gameAction != null) {
            gameAction.release();
        }
    }


    public void mouseClicked(MouseEvent e) {
    }


    public void mouseEntered(MouseEvent e) {
        mouseMoved(e);
    }


    public void mouseExited(MouseEvent e) {
        mouseMoved(e);
    }


    public void mouseDragged(MouseEvent e) {
        mouseMoved(e);
    }


    public synchronized void mouseMoved(MouseEvent e) {
        if (isRecentering &&
            centerLocation.x == e.getX() &&
            centerLocation.y == e.getY())
        {
            isRecentering = false;
        }
        else {
            int dx = e.getX() - mouseLocation.x;
            int dy = e.getY() - mouseLocation.y;
            mouseHelper(MOUSE_MOVE_LEFT, MOUSE_MOVE_RIGHT, dx);
            mouseHelper(MOUSE_MOVE_UP, MOUSE_MOVE_DOWN, dy);

            if (isRelativeMouseMode()) {
                recenterMouse();
            }
        }

        mouseLocation.x = e.getX();
        mouseLocation.y = e.getY();

    }


    public void mouseWheelMoved(MouseWheelEvent e) {
        mouseHelper(MOUSE_WHEEL_UP, MOUSE_WHEEL_DOWN,
            e.getWheelRotation());
    }

    private void mouseHelper(int codeNeg, int codePos,
        int amount)
    {
        GameAction gameAction;
        if (amount < 0) {
            gameAction = mouseActions[codeNeg];
        }
        else {
            gameAction = mouseActions[codePos];
        }
        if (gameAction != null) {
            gameAction.press(Math.abs(amount));
            gameAction.release();
        }
    }

}



有了这些还不够,我们还需要为我们的主角增加重力,保证跳跃后能回到地球上,呵呵。
我们在来一个类Player,直接继承Fly,给它增加重力。
package com.jsheng.game.util;

/** function:
 * company: jsheng
 * @author wanghn      [email protected]
 */
public class Player extends Fly {
	 public static final int STATE_NORMAL = 0;
	 public static final int STATE_JUMPING = 1;

	 public static final float SPEED = .3f;
	 public static final float GRAVITY = .002f;

	 private int floorY;
	 private int state;
	 public Player(Animation anim) {
	        super(anim);
	        state = STATE_NORMAL;
	    }
	    public int getState() {
	        return state;
	    }

	    public void setState(int state) {
	        this.state = state;
	    }

	    public void setFloorY(int floorY) {
	        this.floorY = floorY;
	        setY(floorY);
	    }

	    public void jump() {
	        setDy(-1);
	        state = STATE_JUMPING;
	    }

	    public void update(long elapsedTime) {
	        if (getState() == STATE_JUMPING) {
	            setDy(getDy() + GRAVITY * elapsedTime);
	        }
	        super.update(elapsedTime);
	        if (getState() == STATE_JUMPING && getY() >= floorY) {
	            setDy(0);
	            setY(floorY);
	            setState(STATE_NORMAL);
	        }

	    }
	}

有了这些,我们来做一个测试类:
package com.jsheng.game.test1;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Window;
import java.awt.event.KeyEvent;

import com.jsheng.game.util.Animation;
import com.jsheng.game.util.GameAction;
import com.jsheng.game.util.GameCore;
import com.jsheng.game.util.InputManager;
import com.jsheng.game.util.Player;

/** function:
 * company: jsheng
 * @author wanghn      [email protected]
 */
public class InputManagerTest extends GameCore {

    public static void main(String[] args) {
        new InputManagerTest().run();
    }

    protected GameAction jump;
    protected GameAction exit;
    protected GameAction moveLeft;
    protected GameAction moveRight;
    protected GameAction pause;
    protected InputManager inputManager;
    private Player player;
    private Image bgImage;
    private boolean paused;

    public void init() {
        super.init();
        Window window = screen.getFullScreenWindow();
        inputManager = new InputManager(window);
        createGameActions();
        createFly();
        paused = false;
    }
    public boolean isPaused() {
        return paused;
    }
    public void setPaused(boolean p) {
        if (paused != p) {
            this.paused = p;
            inputManager.resetAllGameActions();
        }
    }


    public void update(long elapsedTime) {
        checkSystemInput();

        if (!isPaused()) {
            checkGameInput();
            player.update(elapsedTime);
        }
    }

    public void checkSystemInput() {
        if (pause.isPressed()) {
            setPaused(!isPaused());
        }
        if (exit.isPressed()) {
            stop();
        }
    }
    public void checkGameInput() {
        float x = 0;
        if (moveLeft.isPressed()) {
            x-=Player.SPEED;
        }
        if (moveRight.isPressed()) {
            x+=Player.SPEED;
        }
        player.setDx(x);

        if (jump.isPressed() &&
            player.getState() != Player.STATE_JUMPING)
        {
            player.jump();
        }
    }


    public void draw(Graphics2D g) {
        g.drawImage(bgImage, 0, 0, null);
        g.drawImage(player.getImage(),
            Math.round(player.getX()),
            Math.round(player.getY()),
            null);
    }

    public void createGameActions() {
        jump = new GameAction("jump",
            GameAction.DETECT_INITAL_PRESS_ONLY);
        exit = new GameAction("exit",
            GameAction.DETECT_INITAL_PRESS_ONLY);
        moveLeft = new GameAction("moveLeft");
        moveRight = new GameAction("moveRight");
        pause = new GameAction("pause",
            GameAction.DETECT_INITAL_PRESS_ONLY);

        inputManager.mapToKey(exit, KeyEvent.VK_ESCAPE);
        inputManager.mapToKey(pause, KeyEvent.VK_P);

        inputManager.mapToKey(jump, KeyEvent.VK_SPACE);
        inputManager.mapToMouse(jump,
            InputManager.MOUSE_BUTTON_1);

        inputManager.mapToKey(moveLeft, KeyEvent.VK_LEFT);
        inputManager.mapToKey(moveRight, KeyEvent.VK_RIGHT);

        inputManager.mapToKey(moveLeft, KeyEvent.VK_A);
        inputManager.mapToKey(moveRight, KeyEvent.VK_D);

        inputManager.mapToMouse(moveLeft,
          InputManager.MOUSE_MOVE_LEFT);
        inputManager.mapToMouse(moveRight,
          InputManager.MOUSE_MOVE_RIGHT);

    }
    private void createFly() {
        bgImage = loadImage("images/bg.jpg");
        Image player1 = loadImage("images/1.jpg");
        Image player2 = loadImage("images/2.jpg");
        Image player3 = loadImage("images/3.jpg");
        Animation anim = new Animation();
        anim.addFrame(player1, 250);
        anim.addFrame(player2, 150);
        anim.addFrame(player1, 150);
        anim.addFrame(player2, 150);
        anim.addFrame(player3, 200);
        anim.addFrame(player2, 150);
        player = new Player(anim);
        player.setFloorY(screen.getHeight() - player.getHeight());
    }

}


wasd或箭头控制方向,空格为跳跃,P是暂停。也可以用鼠标控制跳跃与方向。
在暂停游戏后,控制动作的类GameAction要复位,保证暂停后按下的键失效。

你可能感兴趣的:(java,游戏,编程,swing,UP)