http://blog.csdn.net/cping1982/archive/2009/10/25/4725076.aspx
动作游戏(ACT),作为在N早以前的红白机时代,便已经大量普及的经典游戏类型,它强调玩家的反应能力和手眼的配合,属于快节奏游戏的典型。相对而言,动作游戏的剧情一般也比较简单,主要通过熟悉操作技巧就可以进行游戏,多以2D为主潮流。在游戏中,玩家控制的角色不仅可以走、跑、跳,甚至可以俯身、爬行、翻滚、飞行、甚至爬墙(见附图:《忍者龙剑传》)。
ACT游戏的武器也多种多样,近程、远程、定时,还可以使用大量的辅助道具,譬如:吊索(例如《蜘蛛侠》)。加之种种场景的地形效果,流沙、冰地、履带、齿轮等等,配合场景中的种种机关,如墙上的开关、灯控、钉板等等,使游戏过程千变万化。即使是3D仿真技术发达的今天,相信仍有不少玩家流连这类ACT游戏吧?
任何一款ACT游戏,从根本上说,都会设定有自己的游戏背景。策划人员在设计这部分内容时,可以充分发挥自己的想象力。游戏的背景可以为数千年前的原始神话时代的《火之鸟》、《彩虹岛》,也可以是神秘奇幻的中世纪《圆桌武士》、《恶魔城》、《波斯王子》,甚至回到雄壮激荡的中国古代,作出《天地吞食》、《杨家将》,乃至于未来时代的《魂斗罗》,或者以著名故事、漫画为原型的《蜘蛛侠》、《梦幻岛》等,乃至于从来没有过的时间、空间、物种。故事需要尽可能的离奇或是感人,这样才能有效地抓住玩家,事实证明,在这样的游戏中,完全可以在游戏过程中加入情节的,譬如《恶魔城·月夜狂想曲》就是一个非常好的例子,在ACT为主的游戏过程中,角色会遇到很多人,为他提供信息,在一定条件下给予其道具,可以中途买卖物品。相信随着游戏的发展,这类多元化游戏将会越来越受欢迎。
而在游戏设计中,操作感也非常重要,矛头直指游戏的上手性。在PC或Android上玩这类游戏,更是对操作要求极高,游戏玩家玩的是否舒服,也全在这一步。举个例子,如我们控制一个角色去跳过一个很宽的沟。步骤应该为:跑——>快跑——>跳跃。初步设定“跑”“加速”“跳跃”必须设到“S”“D”“F”三个键上,通常情况就应该依次把“S”“D”“F”三个相邻的键设为“加速”“跑” “跳跃”。这样,平时玩家在游戏过程中,可以始终按住“D”键不放,需要加速时,无名指按着“S”,过沟大跳跃时,只需要食指点下“F”键就可以了,除此之外,其它的排列都将很别扭,可自己一试。
另外从键盘和鼠标的功能来说,有的东西已经是成规范性的东西了。对应相关的游戏软件我们也可以找到规律,并力图靠近它。做为策划,永远也不要霸道的要求玩家去适应你的规律,找到大众都喜欢都适应的规律才是为策划之正道。
牵扯到ACT游戏,自然免不了会有关卡的概念,所谓关卡就是游戏过程中一个又一个的小节。在这里也是同样可以发挥策划的想象力的好地方,每一关可以设计不同的特色,我想大家一定不会忘记古旧而精典的ACT游戏《魂斗罗》吧,记得履带+下砸钉锤那一关么?记得最后一关会飞起来的毒蝎么?这就是有特色而让人难忘的精典呀。
这一部分可以说是ACT游戏的核心。
至于游戏的规则设定,比如在什么情况下,角色会死亡?在什么情况下,敌NPC会OVER?角色在什么状态下可以躲过敌人飞行道具?角色在情况下会飞行?每一种道具的作用?都是需要设计者费心的,比如有的游戏,在规则上会设计一些独创的内容,如上面提到的《天地吞食》,某角色击打时如果同时按着“下”,就会把击打对象举起来并抛出。
而说起ACT游戏的代表作,那么便首推《超级马里奥》,这款家喻户晓的动作游戏,不但在当时,甚至对后世游戏界产生了无法估量的巨大影响。
截止到2008年,马里奥游戏分别在不同的机种上发布了116种,当中包括马力奥自己为主角的游戏和其他如任天堂大乱斗等游戏上,成为了吉尼斯世界纪录大全中,发行最多款电子游戏的电子游戏角色。
那么,对于这款地球人都知道的游戏,我们可不可以将它移植到Android之上,甚至再加上少许变化,令它成为一款全新的游戏呢?答案是肯定的。
相关知识点说了很多。下面,我将分别给出PC以及Android两个版本的马里奥类游戏实现,让大家对基本业务流程有一个初步了解。
源码下载地址:http://code.google.com/p/loon-simple/downloads/list
PC版实现:
view plaincopy to clipboardprint?
package org.loon.game.test;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.Iterator;
import java.util.LinkedList;
import org.loon.framework.game.simple.GameScene;
import org.loon.framework.game.simple.core.Deploy;
import org.loon.framework.game.simple.core.LTimer;
import org.loon.framework.game.simple.core.LTimerContext;
import org.loon.framework.game.simple.core.Screen;
/**
*
* Copyright 2008 - 2009
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loonframework
* @author chenpeng
* @email:[email protected]
* @version 0.1
*/
public class Main extends Screen {
public static final int WIDTH = 320;
public static final int HEIGHT = 480;
private LTimer delay;
private Map map;
private Hero hero;
private ActionKey goLeftKey;
private ActionKey goRightKey;
private ActionKey jumpKey;
private double x, y;
// 键盘事件记录器
class ActionKey {
static final int PRESS_ONLY = 1, STATE_RELEASED = 0, STATE_PRESSED = 1,
STATE_WAITING_FOR_RELEASE = 2;
int mode, amount, state;
public ActionKey() {
this(0);
}
public ActionKey(int mode) {
this.mode = mode;
reset();
}
public void reset() {
state = STATE_RELEASED;
amount = 0;
}
public void press() {
if (state != STATE_WAITING_FOR_RELEASE) {
amount++;
state = STATE_PRESSED;
}
}
public void release() {
state = STATE_RELEASED;
}
public boolean isPressed() {
if (amount != 0) {
if (state == STATE_RELEASED) {
amount = 0;
} else if (mode == PRESS_ONLY) {
state = STATE_WAITING_FOR_RELEASE;
amount = 0;
}
return true;
}
return false;
}
}
public Main() {
delay = new LTimer(20);
goLeftKey = new ActionKey();
goRightKey = new ActionKey();
jumpKey = new ActionKey(ActionKey.PRESS_ONLY);
initialize();
}
private void initialize() {
map = new Map("map.txt");
hero = new Hero("hero.gif", 192, 32, 40, 40, map);
}
public void alter(LTimerContext timer) {
if (delay.action(timer.getTimeSinceLastUpdate())) {
if (goLeftKey.isPressed()) {
// 向左移动
hero.left();
} else if (goRightKey.isPressed()) {
// 向右移动
hero.right();
} else {
// 暂停
hero.stop();
}
if (jumpKey.isPressed()) {
// 跳跃
hero.jump();
}
// 更新角色状态
hero.update(timer.getTimeSinceLastUpdate());
// 遍历精灵集合
LinkedList sprites = map.getSprites();
for (Iterator it = sprites.iterator(); it.hasNext();) {
Sprite sprite = (Sprite) it.next();
// 更新所有精灵状态
sprite.update(timer.getTimeSinceLastUpdate());
// 碰撞测试
if (hero.isCollision(sprite)) {
// 遇敌
if (sprite instanceof Enemy) {
Enemy e = (Enemy) sprite;
// 踩踏敌人
if ((int) hero.getY() < (int) e.getY()) {
sprites.remove(e);
hero.setForceJump(true);
hero.jump();
break;
} else {
// 重新开始
initialize();
}
// 食物
} else if (sprite instanceof Food) {
Food f = (Food) sprite;
sprites.remove(f);
break;
// 加速宝物
} else if (sprite instanceof Speed) {
sprites.remove(sprite);
Speed speedUp = (Speed) sprite;
speedUp.use(hero);
break;
// 跳跃宝物
} else if (sprite instanceof Jump) {
sprites.remove(sprite);
Jump jump = (Jump) sprite;
jump.use(hero);
break;
}
}
}
}
}
/**
* 绘制游戏界面
*/
public void draw(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
int offsetX = Main.WIDTH / 2 - (int) hero.getX();
offsetX = Math.min(offsetX, 0);
offsetX = Math.max(offsetX, Main.WIDTH - map.getWidth());
int offsetY = Main.HEIGHT / 2 - (int) hero.getY();
offsetY = Math.min(offsetY, 0);
offsetY = Math.max(offsetY, Main.HEIGHT - map.getHeight());
map.draw(g, offsetX, offsetY);
hero.draw(g, offsetX, offsetY);
LinkedList sprites = map.getSprites();
for (Iterator it = sprites.iterator(); it.hasNext();) {
Sprite sprite = (Sprite) it.next();
x = Map.pixelsToTiles(sprite.getX());
y = Map.pixelsToTiles(sprite.getY());
// 精灵绘制限制在可见区域内
if (x > map.getFirstTileX() && x < map.getLastTileX()
&& y > map.getFirstTileY() && y < map.getLastTileY()) {
sprite.draw(g, offsetX, offsetY);
}
}
}
public void leftClick(MouseEvent arg0) {
}
public void middleClick(MouseEvent arg0) {
}
public void rightClick(MouseEvent arg0) {
}
public void onKey(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
goLeftKey.press();
}
if (key == KeyEvent.VK_RIGHT) {
goRightKey.press();
}
if (key == KeyEvent.VK_UP) {
jumpKey.press();
}
}
public void onKeyUp(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
goLeftKey.release();
}
if (key == KeyEvent.VK_RIGHT) {
goRightKey.release();
}
if (key == KeyEvent.VK_UP) {
jumpKey.release();
}
}
public static void main(String[] args) {
GameScene frame = new GameScene("火影忍者", WIDTH, HEIGHT);
Deploy deploy = frame.getDeploy();
deploy.setScreen(new Main());
deploy.setShowFPS(true);
deploy.setLogo(false);
deploy.setFPS(100);
deploy.mainLoop();
frame.showFrame();
}
}
package org.loon.game.test;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.util.Iterator;
import java.util.LinkedList;
import org.loon.framework.game.simple.GameScene;
import org.loon.framework.game.simple.core.Deploy;
import org.loon.framework.game.simple.core.LTimer;
import org.loon.framework.game.simple.core.LTimerContext;
import org.loon.framework.game.simple.core.Screen;
/**
*
* Copyright 2008 - 2009
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*
* @project loonframework
* @author chenpeng
* @email:[email protected]
* @version 0.1
*/
public class Main extends Screen {
public static final int WIDTH = 320;
public static final int HEIGHT = 480;
private LTimer delay;
private Map map;
private Hero hero;
private ActionKey goLeftKey;
private ActionKey goRightKey;
private ActionKey jumpKey;
private double x, y;
// 键盘事件记录器
class ActionKey {
static final int PRESS_ONLY = 1, STATE_RELEASED = 0, STATE_PRESSED = 1,
STATE_WAITING_FOR_RELEASE = 2;
int mode, amount, state;
public ActionKey() {
this(0);
}
public ActionKey(int mode) {
this.mode = mode;
reset();
}
public void reset() {
state = STATE_RELEASED;
amount = 0;
}
public void press() {
if (state != STATE_WAITING_FOR_RELEASE) {
amount++;
state = STATE_PRESSED;
}
}
public void release() {
state = STATE_RELEASED;
}
public boolean isPressed() {
if (amount != 0) {
if (state == STATE_RELEASED) {
amount = 0;
} else if (mode == PRESS_ONLY) {
state = STATE_WAITING_FOR_RELEASE;
amount = 0;
}
return true;
}
return false;
}
}
public Main() {
delay = new LTimer(20);
goLeftKey = new ActionKey();
goRightKey = new ActionKey();
jumpKey = new ActionKey(ActionKey.PRESS_ONLY);
initialize();
}
private void initialize() {
map = new Map("map.txt");
hero = new Hero("hero.gif", 192, 32, 40, 40, map);
}
public void alter(LTimerContext timer) {
if (delay.action(timer.getTimeSinceLastUpdate())) {
if (goLeftKey.isPressed()) {
// 向左移动
hero.left();
} else if (goRightKey.isPressed()) {
// 向右移动
hero.right();
} else {
// 暂停
hero.stop();
}
if (jumpKey.isPressed()) {
// 跳跃
hero.jump();
}
// 更新角色状态
hero.update(timer.getTimeSinceLastUpdate());
// 遍历精灵集合
LinkedList sprites = map.getSprites();
for (Iterator it = sprites.iterator(); it.hasNext();) {
Sprite sprite = (Sprite) it.next();
// 更新所有精灵状态
sprite.update(timer.getTimeSinceLastUpdate());
// 碰撞测试
if (hero.isCollision(sprite)) {
// 遇敌
if (sprite instanceof Enemy) {
Enemy e = (Enemy) sprite;
// 踩踏敌人
if ((int) hero.getY() < (int) e.getY()) {
sprites.remove(e);
hero.setForceJump(true);
hero.jump();
break;
} else {
// 重新开始
initialize();
}
// 食物
} else if (sprite instanceof Food) {
Food f = (Food) sprite;
sprites.remove(f);
break;
// 加速宝物
} else if (sprite instanceof Speed) {
sprites.remove(sprite);
Speed speedUp = (Speed) sprite;
speedUp.use(hero);
break;
// 跳跃宝物
} else if (sprite instanceof Jump) {
sprites.remove(sprite);
Jump jump = (Jump) sprite;
jump.use(hero);
break;
}
}
}
}
}
/**
* 绘制游戏界面
*/
public void draw(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
int offsetX = Main.WIDTH / 2 - (int) hero.getX();
offsetX = Math.min(offsetX, 0);
offsetX = Math.max(offsetX, Main.WIDTH - map.getWidth());
int offsetY = Main.HEIGHT / 2 - (int) hero.getY();
offsetY = Math.min(offsetY, 0);
offsetY = Math.max(offsetY, Main.HEIGHT - map.getHeight());
map.draw(g, offsetX, offsetY);
hero.draw(g, offsetX, offsetY);
LinkedList sprites = map.getSprites();
for (Iterator it = sprites.iterator(); it.hasNext();) {
Sprite sprite = (Sprite) it.next();
x = Map.pixelsToTiles(sprite.getX());
y = Map.pixelsToTiles(sprite.getY());
// 精灵绘制限制在可见区域内
if (x > map.getFirstTileX() && x < map.getLastTileX()
&& y > map.getFirstTileY() && y < map.getLastTileY()) {
sprite.draw(g, offsetX, offsetY);
}
}
}
public void leftClick(MouseEvent arg0) {
}
public void middleClick(MouseEvent arg0) {
}
public void rightClick(MouseEvent arg0) {
}
public void onKey(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
goLeftKey.press();
}
if (key == KeyEvent.VK_RIGHT) {
goRightKey.press();
}
if (key == KeyEvent.VK_UP) {
jumpKey.press();
}
}
public void onKeyUp(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
goLeftKey.release();
}
if (key == KeyEvent.VK_RIGHT) {
goRightKey.release();
}
if (key == KeyEvent.VK_UP) {
jumpKey.release();
}
}
public static void main(String[] args) {
GameScene frame = new GameScene("火影忍者", WIDTH, HEIGHT);
Deploy deploy = frame.getDeploy();
deploy.setScreen(new Main());
deploy.setShowFPS(true);
deploy.setLogo(false);
deploy.setFPS(100);
deploy.mainLoop();
frame.showFrame();
}
}
Android版实现:
view plaincopy to clipboardprint?
package org.loon.framework.android.game.act;
import java.util.Iterator;
import java.util.LinkedList;
import org.loon.framework.android.game.LAGraphics;
import org.loon.framework.android.game.LAScreen;
import org.loon.framework.android.game.LTimerContext;
import android.graphics.Color;
import android.view.KeyEvent;
import android.view.MotionEvent;
/**
*
* Copyright 2008 - 2009
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*
* @project loonframework
* @author chenpeng
* @email:[email protected]
* @version 0.1
*/
public class ScreenTest3 extends LAScreen {
public static final int WIDTH = 320;
public static final int HEIGHT = 480;
// private LTimer delay;
private Map map;
private Hero hero;
private ActionKey goLeftKey;
private ActionKey goRightKey;
private ActionKey jumpKey;
private double x, y;
// 键盘事件记录器
class ActionKey {
static final int PRESS_ONLY = 1, STATE_RELEASED = 0, STATE_PRESSED = 1,
STATE_WAITING_FOR_RELEASE = 2;
int mode, amount, state;
public ActionKey() {
this(0);
}
public ActionKey(int mode) {
this.mode = mode;
reset();
}
public void reset() {
state = STATE_RELEASED;
amount = 0;
}
public void press() {
if (state != STATE_WAITING_FOR_RELEASE) {
amount++;
state = STATE_PRESSED;
}
}
public void release() {
state = STATE_RELEASED;
}
public boolean isPressed() {
if (amount != 0) {
if (state == STATE_RELEASED) {
amount = 0;
} else if (mode == PRESS_ONLY) {
state = STATE_WAITING_FOR_RELEASE;
amount = 0;
}
return true;
}
return false;
}
}
public ScreenTest3() {
// delay = new LTimer(20);
goLeftKey = new ActionKey();
goRightKey = new ActionKey();
jumpKey = new ActionKey(ActionKey.PRESS_ONLY);
initialize();
}
private void initialize() {
map = new Map("map.txt");
hero = new Hero("hero.gif", 192, 32, 40, 40, map);
}
public void alter(LTimerContext timer) {
// PS:虚拟机速度较慢,实机需要开放此部分,否则动作过快
// if (delay.action(timer.getTimeSinceLastUpdate())) {
if (goLeftKey.isPressed()) {
// 向左移动
hero.left();
} else if (goRightKey.isPressed()) {
// 向右移动
hero.right();
} else {
// 暂停
hero.stop();
}
if (jumpKey.isPressed()) {
// 跳跃
hero.jump();
}
// 更新角色状态
hero.update(timer.getTimeSinceLastUpdate());
// 遍历精灵集合
LinkedList<Sprite> sprites = map.getSprites();
Iterator<Sprite> it = sprites.iterator();
while (it.hasNext()) {
Sprite sprite = it.next();
// 更新所有精灵状态
sprite.update(timer.getTimeSinceLastUpdate());
// 碰撞测试
if (hero.isCollision(sprite)) {
// 遇敌
if (sprite instanceof Enemy) {
Enemy e = (Enemy) sprite;
// 踩踏敌人
if ((int) hero.getY() < (int) e.getY()) {
sprites.remove(e);
hero.setForceJump(true);
hero.jump();
break;
} else {
// 重新开始
initialize();
}
// 食物
} else if (sprite instanceof Food) {
Food f = (Food) sprite;
sprites.remove(f);
break;
// 加速宝物
} else if (sprite instanceof Speed) {
sprites.remove(sprite);
Speed speedUp = (Speed) sprite;
speedUp.use(hero);
break;
// 跳跃宝物
} else if (sprite instanceof Jump) {
sprites.remove(sprite);
Jump jump = (Jump) sprite;
jump.use(hero);
break;
}
}
}
// }
}
public void draw(LAGraphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
int offsetX = WIDTH / 2 - (int) hero.getX();
offsetX = Math.min(offsetX, 0);
offsetX = Math.max(offsetX, WIDTH - map.getWidth());
int offsetY = HEIGHT / 2 - (int) hero.getY();
offsetY = Math.min(offsetY, 0);
offsetY = Math.max(offsetY, HEIGHT - map.getHeight());
map.draw(g, offsetX, offsetY);
hero.draw(g, offsetX, offsetY);
LinkedList<Sprite> sprites = map.getSprites();
for (Iterator<Sprite> it = sprites.iterator(); it.hasNext();) {
Sprite sprite = it.next();
x = Map.pixelsToTiles(sprite.getX());
y = Map.pixelsToTiles(sprite.getY());
// 精灵绘制限制在可见区域内
if (x > map.getFirstTileX() && x < map.getLastTileX()
&& y > map.getFirstTileY() && y < map.getLastTileY())
sprite.draw(g, offsetX, offsetY);
}
}
public boolean onKeyDown(int keyCode, KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.KEYCODE_DPAD_LEFT) {
goLeftKey.press();
}
if (key == KeyEvent.KEYCODE_DPAD_RIGHT) {
goRightKey.press();
}
if (key == KeyEvent.KEYCODE_DPAD_UP) {
jumpKey.press();
}
return false;
}
public boolean onKeyUp(int keyCode, KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.KEYCODE_DPAD_LEFT) {
goLeftKey.release();
}
if (key == KeyEvent.KEYCODE_DPAD_RIGHT) {
goRightKey.release();
}
if (key == KeyEvent.KEYCODE_DPAD_UP) {
jumpKey.release();
}
return false;
}
public boolean onTouchDown(MotionEvent e) {
return false;
}
public boolean onTouchMove(MotionEvent e) {
return false;
}
public boolean onTouchUp(MotionEvent e) {
return false;
}
}
package org.loon.framework.android.game.act;
import java.util.Iterator;
import java.util.LinkedList;
import org.loon.framework.android.game.LAGraphics;
import org.loon.framework.android.game.LAScreen;
import org.loon.framework.android.game.LTimerContext;
import android.graphics.Color;
import android.view.KeyEvent;
import android.view.MotionEvent;
/**
*
* Copyright 2008 - 2009
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*
* @project loonframework
* @author chenpeng
* @email:[email protected]
* @version 0.1
*/
public class ScreenTest3 extends LAScreen {
public static final int WIDTH = 320;
public static final int HEIGHT = 480;
// private LTimer delay;
private Map map;
private Hero hero;
private ActionKey goLeftKey;
private ActionKey goRightKey;
private ActionKey jumpKey;
private double x, y;
// 键盘事件记录器
class ActionKey {
static final int PRESS_ONLY = 1, STATE_RELEASED = 0, STATE_PRESSED = 1,
STATE_WAITING_FOR_RELEASE = 2;
int mode, amount, state;
public ActionKey() {
this(0);
}
public ActionKey(int mode) {
this.mode = mode;
reset();
}
public void reset() {
state = STATE_RELEASED;
amount = 0;
}
public void press() {
if (state != STATE_WAITING_FOR_RELEASE) {
amount++;
state = STATE_PRESSED;
}
}
public void release() {
state = STATE_RELEASED;
}
public boolean isPressed() {
if (amount != 0) {
if (state == STATE_RELEASED) {
amount = 0;
} else if (mode == PRESS_ONLY) {
state = STATE_WAITING_FOR_RELEASE;
amount = 0;
}
return true;
}
return false;
}
}
public ScreenTest3() {
// delay = new LTimer(20);
goLeftKey = new ActionKey();
goRightKey = new ActionKey();
jumpKey = new ActionKey(ActionKey.PRESS_ONLY);
initialize();
}
private void initialize() {
map = new Map("map.txt");
hero = new Hero("hero.gif", 192, 32, 40, 40, map);
}
public void alter(LTimerContext timer) {
// PS:虚拟机速度较慢,实机需要开放此部分,否则动作过快
// if (delay.action(timer.getTimeSinceLastUpdate())) {
if (goLeftKey.isPressed()) {
// 向左移动
hero.left();
} else if (goRightKey.isPressed()) {
// 向右移动
hero.right();
} else {
// 暂停
hero.stop();
}
if (jumpKey.isPressed()) {
// 跳跃
hero.jump();
}
// 更新角色状态
hero.update(timer.getTimeSinceLastUpdate());
// 遍历精灵集合
LinkedList<Sprite> sprites = map.getSprites();
Iterator<Sprite> it = sprites.iterator();
while (it.hasNext()) {
Sprite sprite = it.next();
// 更新所有精灵状态
sprite.update(timer.getTimeSinceLastUpdate());
// 碰撞测试
if (hero.isCollision(sprite)) {
// 遇敌
if (sprite instanceof Enemy) {
Enemy e = (Enemy) sprite;
// 踩踏敌人
if ((int) hero.getY() < (int) e.getY()) {
sprites.remove(e);
hero.setForceJump(true);
hero.jump();
break;
} else {
// 重新开始
initialize();
}
// 食物
} else if (sprite instanceof Food) {
Food f = (Food) sprite;
sprites.remove(f);
break;
// 加速宝物
} else if (sprite instanceof Speed) {
sprites.remove(sprite);
Speed speedUp = (Speed) sprite;
speedUp.use(hero);
break;
// 跳跃宝物
} else if (sprite instanceof Jump) {
sprites.remove(sprite);
Jump jump = (Jump) sprite;
jump.use(hero);
break;
}
}
}
// }
}
public void draw(LAGraphics g) {
g.setColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
int offsetX = WIDTH / 2 - (int) hero.getX();
offsetX = Math.min(offsetX, 0);
offsetX = Math.max(offsetX, WIDTH - map.getWidth());
int offsetY = HEIGHT / 2 - (int) hero.getY();
offsetY = Math.min(offsetY, 0);
offsetY = Math.max(offsetY, HEIGHT - map.getHeight());
map.draw(g, offsetX, offsetY);
hero.draw(g, offsetX, offsetY);
LinkedList<Sprite> sprites = map.getSprites();
for (Iterator<Sprite> it = sprites.iterator(); it.hasNext();) {
Sprite sprite = it.next();
x = Map.pixelsToTiles(sprite.getX());
y = Map.pixelsToTiles(sprite.getY());
// 精灵绘制限制在可见区域内
if (x > map.getFirstTileX() && x < map.getLastTileX()
&& y > map.getFirstTileY() && y < map.getLastTileY())
sprite.draw(g, offsetX, offsetY);
}
}
public boolean onKeyDown(int keyCode, KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.KEYCODE_DPAD_LEFT) {
goLeftKey.press();
}
if (key == KeyEvent.KEYCODE_DPAD_RIGHT) {
goRightKey.press();
}
if (key == KeyEvent.KEYCODE_DPAD_UP) {
jumpKey.press();
}
return false;
}
public boolean onKeyUp(int keyCode, KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.KEYCODE_DPAD_LEFT) {
goLeftKey.release();
}
if (key == KeyEvent.KEYCODE_DPAD_RIGHT) {
goRightKey.release();
}
if (key == KeyEvent.KEYCODE_DPAD_UP) {
jumpKey.release();
}
return false;
}
public boolean onTouchDown(MotionEvent e) {
return false;
}
public boolean onTouchMove(MotionEvent e) {
return false;
}
public boolean onTouchUp(MotionEvent e) {
return false;
}
}
源码下载地址:http://code.google.com/p/loon-simple/downloads/list
——————————————————————————————
搞Java的同僚们,有空想着去http://www.java.com/en/store/intl-contact.jsp 申请2010年开通中国区的商店服务吧,别最后搞得和Android Market似的,只能托人“洗钱”……
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cping1982/archive/2009/10/25/4725076.aspx