java 游戏编程 (六)

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

/**
* function: company: jsheng
*
* @author wanghn wanghaining9999@sina.com
*/
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 wanghaining9999@sina.com
*/
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 wanghaining9999@sina.com
*/
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 wanghaining9999@sina.com
*/
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要复位,保证暂停后按下的键失效。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值