简单的 Android 球类游戏






4.75/5 (41投票s)
关于使用 AndEngine 为 Android 创建精美球类游戏的教程。
引言
本教程将介绍如何在 Android 操作系统上开发一款弹球游戏。它将引导你使用 AndEngine(免费的 Android 2D 开源游戏引擎)来开发 Android 游戏。要理解本教程,你需要对 AndEngine 和 Java 编程有一定的基本了解。如果你对 AndEngine 不熟悉,请查阅此 链接。本教程的目标是教你如何制作自己的 Android 游戏。
游戏
这是一个经典的怀旧游戏创意,以现代的方式实现。你将通过加速度计传感器控制弹球,目标是收集所有“钻石”,躲避敌方弹球,并安全到达终点。




开始需要什么?
要开始开发你自己的 Android 游戏,你需要 SDK 和游戏引擎(这将使你的生活轻松很多!)。我使用的是 Eclipse SDK 和一个名为 AndEngine 的游戏引擎。你想知道如何将 Eclipse SDK 和 AndEngine 结合起来设置吗?点击此链接查看“AndEngine 入门”教程。
开始编码吧!
让我们来看看代码隐藏了什么!请注意,我没有在此处粘贴完整的源代码。我只粘贴了一些代码片段。你可以下载完整的项目以查看完整的源代码。
首先,我们将简要浏览一下 main
类。
public class GameLogicController extends BaseGameActivity
implements IAccelerometerListener{
public PlayerProfileManager playerProfileManager;
public LevelController levelController;
private Camera camera;
protected PhysicsWorld mPhysicsWorld;
public Texture mTexture;
public TextureRegion enemyTextureRegion;
private float mGravityX;
private float mGravityY;
private final Vector2 mTempVector = new Vector2();
public TiledTextureRegion mCircleFaceTextureRegion;
private RepeatingSpriteBackground mGrassBackground;
private Sound mGameOverSound;
...
}
GameLogicController
是我们游戏的基础类,BaseGameActivity
是 AndEngine 的基础类,而 IAccelerometerListener
是用于获取手机加速度计传感器数据的接口。PlayerProfileManager
和 LevelController
只是你稍后会了解的一些游戏类。
@Override
public Engine onLoadEngine() {
...
levelController.mCameraWidth = 460;
levelController.mCameraHeight = 320;
camera = new Camera(0, 0, levelController.mCameraWidth,
levelController.mCameraHeight);
return new Engine(new EngineOptions(true, ScreenOrientation.LANDSCAPE,
new RatioResolutionPolicy(levelController.mCameraWidth,
levelController.mCameraHeight), camera).setNeedsSound(true));
}
onLoadEngine
方法会创建一个新的游戏引擎。首先,我们需要创建一个 Camera
来声明屏幕分辨率。一个重要且非常有用的特性是,Camera
的分辨率与手机分辨率无关。这将为你节省大量关于图形位置的工作!例如,我们声明了 460x320 的屏幕分辨率。你无需关心手机的分辨率,因为你将始终使用 AndEngine 的分辨率(460x320),AndEngine 会自动将 AndEngine 分辨率重新计算为实际的手机分辨率。下一步是创建一个新的 Engine
。你只需要声明屏幕方向(横向或纵向)、屏幕分辨率和自定义选项。我们只使用了一个自定义选项,用于启用声音。
public Scene newGameLevelScene(int levelId){
Scene scene = new Scene(2);
this.mPhysicsWorld = new FixedStepPhysicsWorld(60, new Vector2(0, 0), false);
levelController.setScene(scene);
levelController.setmPhysicsWorld(mPhysicsWorld);
levelController.createFrame();
levelController.loadLevel(levelId);
this.enableAccelerometerSensor(this);
scene.registerUpdateHandler(this.mPhysicsWorld);
return scene;
}
在这里,你可以看到四件非常重要的事情。首先,我们需要创建一个新的显示 Scene
和 FixedStepPhysicWorld
。FixedStepPhysicWorld
是一个 2D 真实世界物理模型的模拟。它用于计算重力、碰撞检测等。让我们聚焦于 PhysicWorld
。它需要三个参数。第一个是帧率(每秒屏幕应该刷新多少次),第二个是重力向量,第三个是我们是否允许 PhysicWorld
睡眠。最后,我们需要设置 enableAccelerometerSensor
和 registerUpdateHandler
。
@Override
public void onAccelerometerChanged(AccelerometerData pAccelerometerData) {
this.mGravityX = pAccelerometerData.getY() * 2;
this.mGravityY = pAccelerometerData.getX() * 2;
if(this.mGravityX > con)
this.mGravityX = con;
if(this.mGravityY > con)
this.mGravityY = con;
if(this.mGravityX < con * (-1))
this.mGravityX = con * (-1);
if(this.mGravityY < con * (-1))
this.mGravityY = con * (-1);
this.mTempVector.set(this.mGravityX, this.mGravityY);
this.mPhysicsWorld.setGravity(this.mTempVector);
}
在 newGameScene
方法中,我们启用了 accelometerSensor
,它会控制 onAccelerometerChanged
方法。每当加速度计发生变化时,就会调用此方法。
protected Scene createQuitScene() {
Scene scene = new Scene(2);
scene.setBackground(this.mMenuBackground);
Sprite buttonLevel = new Sprite(100, 100, 250, 70, this.mMenuOkTextureRegion)
{
@Override
public boolean onAreaTouched
(TouchEvent pSceneTouchEvent,float pTouchAreaLocalX,
float pTouchAreaLocalY)
{
if(checkTouchTime())
GameLogicController.getInstance().finish();
return true;
}
};
scene.registerTouchArea(buttonLevel);
scene.getTopLayer().addEntity(buttonLevel);
...
}
Sprite
只是场景中的一个图形。更有趣的是 onAreaTouched
方法。它是一个回调函数,每当有人按下按钮(精灵)时,就会调用此方法。别忘了注册触摸区域(registerTouchArea
)并将按钮(addEntity
)添加到场景中!
我们已经完成了 main
类的编写,现在可以转到 LevelController
类了。
public class LevelController {
private ArrayList<Shape> enemyList;
private ArrayList<Shape> goodsList;
private ArrayList<Shape> endPointList;
...
public void createPlayer(TiledTextureRegion mCircleFaceTextureRegion, int x, int y){
//mPlayer = new Player(x, y, mCameraHeight/10,mCameraHeight/10,
mCircleFaceTextureRegion, this);
mPlayer = new Player(x, y, 30,30,mCircleFaceTextureRegion, this);
FixtureDef FIXTURE = PhysicsFactory.createFixtureDef(1, 0.5f, 0.5f);
Body body;
body = PhysicsFactory.createCircleBody(mPhysicsWorld, mPlayer,
BodyType.DynamicBody, FIXTURE);
mPhysicsWorld.registerPhysicsConnector(new PhysicsConnector
(mPlayer, body, true, true, false, false));
scene.getTopLayer().addEntity(mPlayer);
}
...
}
LevelController
类负责加载关卡和控制关卡事件。enemyList
、goodsList
和 endPointList
这三个 ArrayList 用于存储敌方弹球、物品(钻石)和终点(终点线)。createPlayer
方法会在 x,y 位置创建一个新的玩家,大小为 30x30,PhysicFactory.CreateFixtureDef
创建一个新的物理对象。物理对象应该被注册到 mPhysicsWorld
以进行碰撞检测。
public void callbackCollisionGoods(int i){
Shape goodShape = goodsList.get(i);
scene.getBottomLayer().removeEntity(goodShape);
goodsList.remove(i);
}
如果玩家收集了钻石,就会调用 callbackCollisionGoods
。在此方法中,我们从 goodsList
中移除钻石,并从 scene
中移除 goodShape
。
此类中的其他方法非常相似,我将不再详细描述。
下一个类是 PlayerProfileManager
。在这个类中,除了 WriteSettings
方法外,你只会找到基本的 Java 代码。
private void WriteSettings() {
String FILENAME = "settings2";
FileOutputStream fos = null;
DataOutputStream dos;
try {
fos = gameLogicController.openFileOutput(FILENAME, Context.MODE_PRIVATE);
} catch (FileNotFoundException e) {
}
try {
dos=new DataOutputStream(fos);
dos.writeInt(unlockedLevelId);
} catch (IOException e) {
}
try {
fos.close();
} catch (IOException e) {
}
}
在 WriteSettings
方法中,我们将关卡信息保存到手机中。这需要打开、写入和关闭文件。实际上,我们只保存了一个数字——最后一个解锁关卡的 ID。例如,如果关卡 ID 是 5,则表示关卡 1、2、3、4 和 5 都已解锁。
最后介绍的类是 Player
。
public class Player extends AnimatedSprite {
...
@Override
protected void onManagedUpdate(final float pSecondsElapsed) {
super.onManagedUpdate(pSecondsElapsed);
onBeforePositionChanged();
}
private boolean onBeforePositionChanged(){
//speed up
if(frameCount < 2){
frameCount++;
return true;
}
frameCount = 0;
int enemyListSize = levelController.getEnemyList().size();
for(int i = 0; i < enemyListSize; i++)
if(this.collidesWith(levelController.getEnemyList().get(i)))
{
levelController.callbackCollisionEnemy();
return false;
}
for(int i = 0; i < levelController.getGoodsList().size(); i++)
if(this.collidesWith(levelController.getGoodsList().get(i)))
{
levelController.callbackCollisionGoods(i);
return false;
}
for(int i = 0; i < levelController.getEndPointList().size(); i++)
if(this.collidesWith(levelController.getEndPointList().get(i)))
{
levelController.callbackCollisionWithEndPoint();
return false;
}
return true;
}
...
}
Player
类继承自 AnimatedSprite
。Sprite 和 AnimatedSprite 之间只有一个区别——AnimatedSprite 由更多图片组成(动画),而 Sprite 只由一张图片组成。OnManagedUpdate
是每隔“x”毫秒执行的回调。OnBeforePositionChanged
会检查玩家是否与敌人、钻石或终点发生碰撞。如果发生碰撞,则会执行相应的回调。
Android 游戏开发
我希望你看到 Android 游戏开发并不难。通过一些练习,你可以开发出你梦想中的 Android 游戏。教程的最后,我想感谢你的关注。这是我的第一篇文章,如果你能给我任何反馈,我将非常高兴。
历史
- 2011 年 4 月 29 日 - 文章上传