您的位置:首页 > 移动开发 > Android开发

LGame(Android及J2SE游戏引擎)入门示例——如何构建一个游戏

2010-08-06 23:56 676 查看
较早前LGame示例下载地址:http://loon-simple.googlecode.com/files/LGame-Simple-0.2.5.7z

最新版LGame(0.2.6)下载地址:http://loon-simple.googlecode.com/files/LGame-0.2.6.rar



1、如何启动LGame



目前的LGame提供有J2SE以及Android两个开发版本,两版的主要类及函数虽然相同,但由于Android版对应于手机环境,而J2SE版对应于PC环境,所以依旧有少许的差别。

J2SE版:

在J2SE环境下,只需要在Main函数中构造如下内容即可。

public static void main(String[] args) {
		// 获得一个游戏窗体
		GameScene frame = new GameScene("窗体名",
				480, 320);
		// 得到此窗体所对应的游戏部署器
		Deploy deploy = frame.getDeploy();
		// 设定此游戏屏幕(在任何时候都可以通过Screen中的setScreen函数切换游戏屏幕)
		deploy.setScreen(new Game());
		// 是否显示FPS
		deploy.setShowFPS(true);
		// 是否显示框架logo
		deploy.setLogo(false);
		// 允许的最大刷新率
		deploy.setFPS(100);
		// 开始游戏主循环
		deploy.mainLoop();
		// 显示游戏画面
		frame.showFrame();
}




Android版:

而在Android版中,我们则需要分两步走,一是需要配置相关的AndroidManifest.xml

文档。

如下所示:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="org.loon.test"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Main"
                  android:configChanges="orientation|keyboardHidden" 
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="3" />
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>




而调用的方法如下:

package org.loon.test;  
import org.loon.framework.android.game.LAD;  
import org.loon.framework.android.game.LGameAndroid2DActivity;  
import org.loon.framework.android.game.core.LSystem;  
import android.os.Bundle;  
public class Main extends LGameAndroid2DActivity {  
     public void onCreate(Bundle icicle) {  
         // 有Admob广告,纵屏显示,广告居于屏幕下方,广告ID为“XXXXXXXX”,广告刷新速度为60秒  
         this.initialization(icicle,false,LAD.BOTTOM, "XXXXXXXX",60);  
         // 无Admob广告,纵屏显示  
         // this.initialization(icicle,false);  
         // 使用游戏窗体Game  
         this.setScreen(new Game());  
         // 设定FPS为60  
         this.setFPS(60);  
         // 不显示游戏Logo(设定Logo为setLogo)  
         this.setShowLogo(false);  
         // 显示FPS  
         this.setShowFPS(true);  
         // 显示游戏画面  
         this.showScreen();  
     }  
}




这时LGame框架就会根据我们所实现的不同Screen,来展示我们的游戏了(很简单吧)。

2、如何构建Screen类



Screen是一个抽象类,也是LGame框架所提供的游戏界面展示器,其中封装了基本的图形接口与相关的操作设备交互函数,在LGame框架中,可以直接作为游戏界面进行展示的Screen共有三种。

一、Screen

即最基本的Screen,包含了最基本的Screen函数,默认自动刷新游戏画面(根据FPS所设定的速度),不提供repaint以及getLGraphics方法,是提供LGame框架调用的最基本Screen形态。

J2SE版使用方式如下:

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import org.loon.framework.game.simple.core.graphics.Screen;
import org.loon.framework.game.simple.core.graphics.device.LGraphics;
public class ScreenExample extends Screen {
    
// draw中LGraphics会根据设定的FPS自动刷新,使用上与标准的J2SE Graphics以及J2ME Graphics接口没有区别(API为二者的综合)
	public void draw(LGraphics g) {
	}
	// 鼠标左键
	public void leftClick(MouseEvent e) {
	}
	// 鼠标中间键
	public void middleClick(MouseEvent e) {
	}
	// 鼠标右键
	public void rightClick(MouseEvent e) {
	}
	// 键盘按下
	public void onKey(KeyEvent e) {
	}
	// 键盘放开
	public void onKeyUp(KeyEvent e) {
	}
}




另外,在

Screen

中还有一个重要的

alter

函数,我们可以通过重载

alter

函数实现最简单的定时操作,譬如

:





//

设定计时器,每隔

1

秒允许执行一次

LTimer

timer

=

new



LTimer(LSystem.

SECOND

);



//

重载

alter

函数



public





void



alter(LTimerContext context){



if



(

timer

.action(context.getTimeSinceLastUpdate())){


}

}



Android版使用方式如下:

Android



Screen API

与使用方法基本等价于

J2SE

版,但由于手机与

PC

间功能有所差别,所以具体的

API

名及函数有所不同。

import org.loon.framework.android.game.core.graphics.Screen;
import android.view.KeyEvent;
import android.view.MotionEvent;
public class ScreenExample extends Screen{
	
	// 与J2SE版相同,draw中LGraphics会根据设定的FPS自动刷新,使用上与标准的J2SE Graphics以及J2MEGraphics接口没有区别(API为二者的综合)
	public void draw(LGraphics g) {
	}
	//键盘按下
	public boolean onKeyDown(int keyCode, KeyEvent e) {
		return true;
	}
	//键盘放开
	public boolean onKeyUp(int keyCode, KeyEvent e) {
		return true;
	}
	//触摸屏按下
	public boolean onTouchDown(MotionEvent e) {
		return true;
	}
	//手指在触摸屏上移动
	public boolean onTouchMove(MotionEvent e) {
		return true;
	}
	//触摸屏放开
	public boolean onTouchUp(MotionEvent e) {
		return true;
	}
}




关于

alter

函数部分完全一致。

二、ThreadScreen

J2SE版:

ThreadScreen

是一个实现了

Runnable

接口的

Screen

,它采用

double buffer

方式将绘图与业务线程分离,

gameLoop

函数中即是一个独立的线程。

import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import org.loon.framework.game.simple.core.graphics.ThreadScreen;
import org.loon.framework.game.simple.core.graphics.device.LGraphics;
public class ThreadScreenExample extends ThreadScreen {
	public ThreadScreenExample () {
		// ThreadScreen及CanvasScreen都允许变更游戏图形界面大小,下例重载参数为最初(实际)的界面大小。
		super(300, 450);
		// 设定显示时图像大小,此时游戏将以320x480的大小运行(视原有界面不同,会有不同程度的失真)
		resizeScreen(320, 480);
	}
	// ThreadScreen绘图器,为标准Screen中draw函数的封装,区别在于ThreadScreen的修改仅在repaint时生效,而且ThreadScreen不会自动清除原有的图像内容。
	public void drawScreen(LGraphics g) {
	}
// gameLoop的刷新速度可以通过setSynchroFPS函数调整。
	public void gameLoop() {
		
	}
	// 鼠标左键
	public void leftClick(MouseEvent e) {
	}
	// 鼠标中间键
	public void middleClick(MouseEvent e) {
	}
	// 鼠标右键
	public void rightClick(MouseEvent e) {
	}
	// 键盘按下
	public void onKey(KeyEvent e) {
	}
	// 键盘放开
	public void onKeyUp(KeyEvent e) {
	}
}




与标准

Screen

的其它区别在于,

ThreadScreen

可以通过

getLGraphics



getDraw



Draw

类为

LGraphics

的简化封装)函数直接获得对

LGraphics

的操作权,并非一定要通过

drawScreen

函数绘图。

Android版:

J2SE



Android

版的差别仅仅在于鼠标、键盘等设备函数上,其它细节相同。

import org.loon.framework.android.game.core.graphics.ThreadScreen;
import android.view.KeyEvent;
import android.view.MotionEvent;
public class ThreadScreenExample extends ThreadScreen {
	public ThreadScreenExample () {
		// ThreadScreen及CanvasScreen都允许变更游戏图形界面大小,下例重载参数为最初(实际)的界面大小。
		super(300, 450);
		// 设定显示时图像大小,此时游戏将以320x480的大小运行(视原有界面不同,会有不同程度的失真)
		resizeScreen(320, 480);
	}
	// ThreadScreen绘图器,为标准Screen中draw函数的封装,区别在于drawScreen的修改仅在repaint时生效,而且drawScreen不会自动清除原有的图像内容。
	public void drawScreen(LGraphics g) {
	}
// gameLoop的刷新速度可以通过setSynchroFPS函数调整。
	public void gameLoop() {
		
	}
	//键盘按下
	public boolean onKeyDown(int keyCode, KeyEvent e) {
		return true;
	}
	//键盘放开
	public boolean onKeyUp(int keyCode, KeyEvent e) {
		return true;
	}
	//触摸屏按下
	public boolean onTouchDown(MotionEvent e) {
		return true;
	}
	//手指在触摸屏上移动
	public boolean onTouchMove(MotionEvent e) {
		return true;
	}
	//触摸屏放开
	public boolean onTouchUp(MotionEvent e) {
		return true;
	}
}



三、CanvasScreen

CanvasScreen



0.2.6

版中最新提供的

Screen

实现,模拟

J2ME



Canvas

而成(也混合了

GameCanvas



API

),相关函数在

J2SE



Android

版中完全一致。

import org.loon.framework.game.simple.core.graphics.CanvasScreen;
import org.loon.framework.game.simple.core.graphics.device.LGraphics;
public class CanvasScreenExample extends CanvasScreen {
	public CanvasScreenExample(){
		//与ThreadScreen相同,CanvaScreen允许改变游戏图像大小。
		//以下参数分为别原始的图像宽与高(300x450),要求显示的宽与高(320x480)
		super(300,450,320,480);
	}
	// CanvasScreen绘图器,与标准Screen中draw函数的区别在于paint的修改仅在repaint时生效,而且paint不会自动清除原有的图像内容。
	public void paint(LGraphics g) {
   
	}
	// 键盘按下
	public void keyPressed(int keyCode) {
	}
	// 键盘放开
	public void keyReleased(int keyCode) {
	}
	// 触摸屏或鼠标移动
	public void pointerMove(double x, double y) {
	}
	// 触摸屏或鼠标按下
	public void pointerPressed(double x, double y) {
	}
	// 触摸屏或鼠标放开
	public void pointerReleased(double x, double y) {
	}
}




与标准

Screen

的其它区别在于,

CanvasScreen

可以通过

getLGraphics

函数直接获得对

LGraphics

的操作权,并非一定要通过

paint

函数绘图。另外,由于

CanvasScreen



Paint

函数并不直接关联父类的

draw

函数,所以

LGame

中提供的精灵或组件无法直接通过

add

函数加载显示,而是只能在

paint

中手动调用相应组件的绘图器进行绘制(关于这点,用惯

J2ME

的朋友应该没什么不习惯的。另外

LGame

提供有配套的

j2me

精灵类包可供使用,为

1



1

仿

J2ME

原有

API

实现)。


以下是一个CanvasScreen的使用示例:


//初始化时的精灵动画



//移动时的精灵动画



//背景图片





请注意,为了演示图像扩大机制,示例所用的精灵以及游戏背景图像都非常之小,而实际开发中并非一定要使用图像扩充,更不是只能使用此比例的图像。

下面我***一个

Sword.java

,这是一个自定义的精灵类,用以显示上图所示的“骷髅剑士”。(在不重新实现

ISprite

的基础上,我们也可以直接使用现成的

Sprite

类来完成此例。但是,关于动作细节部分就只能在精类外部设定或者重载

Sprite



update

函数来实现(和实现

ISprite

没什么区别了

|||

))。


import org.loon.framework.game.simple.action.map.RectBox;
import org.loon.framework.game.simple.action.sprite.Animation;
import org.loon.framework.game.simple.action.sprite.ISprite;
import org.loon.framework.game.simple.action.sprite.SpriteImage;
import org.loon.framework.game.simple.core.LObject;
import org.loon.framework.game.simple.core.LSystem;
import org.loon.framework.game.simple.core.graphics.device.LGraphics;
import org.loon.framework.game.simple.core.timer.LTimer;
public class Sword extends LObject implements ISprite {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	// 精灵移动范围的最大宽度(即背景图实际宽,为240)
	private static final int WIDTH = 240;
	private boolean init, right, flag, visible;
	private int randX;
	private Animation animation;
	private LTimer time;
	private static final String kName1 = "res/s1.png", kName2 = "res/s2.png";
	public Sword() {
		// 加载怪物剑士的“出土”动画(以下参数为图像所在地址、图像宽、图像高、播放间隔)
		this.animation = Animation.getDefaultAnimation(kName1, 18, 18, 150);
		// 设定计时器间隔为10豪秒
		this.time = new LTimer(10);
		// 设定精灵初始位置(x轴随机,y轴48(立于相对于背景视觉的“地面”上))
		this.setLocation(LSystem.random.nextInt(WIDTH), 48);
		// 随机决定精灵剑士向左或向右冲锋
		this.right = LSystem.random.nextInt(2) == 0 ? true : false;
		// 随机决定精灵剑士以匀速或两倍速前进
		this.flag = LSystem.random.nextInt(2) == 0 ? true : false;
		// 随机决定精灵剑士的“冲锋”停止点
		this.randX = LSystem.random.nextInt(70);
		// 当前精灵可见
		this.visible = true;
	}
	// 设定精灵绘图器内容
	public void createUI(LGraphics g) {
		if (animation != null) {
			// PS:Android版中没有提供序列化保存SpriteImage的方法,直接getImage即可,而没有serializablelImage。
			// 反转图像
			if (right) {
				g.drawMirrorImage(animation.getSpriteImage().serializablelImage
						.getImage(), x(), y());
				// 正向
			} else {
				g.drawImage(animation.getSpriteImage().serializablelImage
						.getImage(), x(), y());
			}
		}
	}
	// 当前精灵宽
	public int getWidth() {
		SpriteImage si = animation.getSpriteImage();
		if (si == null) {
			return -1;
		}
		return si.getWidth();
	}
	// 当前精灵高
	public int getHeight() {
		SpriteImage si = animation.getSpriteImage();
		if (si == null) {
			return -1;
		}
		return si.getHeight();
	}
	// 精灵计时器,用以在timer满足条件时变更精灵样式
	public void update(long timer) {
		if (time.action(timer)) {
			animation.update(timer);
			// 当动画没有播放时
			if (!animation.isRunning()) {
				// 初始化动画精灵(以下参数为图像所在地址、图像宽、图像高、播放间隔)
				animation = Animation.getDefaultAnimation(kName2, 26, 18, 50);
			} else if (animation.isRunning() && init) {
				// 向左
				if (!right && (x() + randX) > 0) {
					if (flag) {
						// 精灵向左移动
						move_left();
					} else {
						// 精灵向左移动(速度x2)
						move_left(2);
					}
					if ((x() - randX) <= 0) {
						right = true;
					}
					// 向右
				} else if (right
						&& (x() + animation.getSpriteImage().getWidth() - randX) <= WIDTH) {
					if (flag) {
						// 精灵向右移动(速度x2)
						move_right(2);
					} else {
						// 精灵向右移动
						move_right();
					}
					// 当达到屏幕边缘时,改变移动方向
					if ((x() + animation.getSpriteImage().getWidth() + randX) >= WIDTH) {
						right = false;
					}
				}
			}
			// 当精灵动画结束时,设定init=true(精灵动画播放完毕)
			if (!init
					&& animation.getTotalFrames() - 1 == animation
							.getCurrentFrameIndex()) {
				animation.setRunning(false);
				init = true;
			}
		}
	}
	// 透明度
	public float getAlpha() {
		return 0;
	}
	// 碰撞盒
	public RectBox getCollisionBox() {
		return new RectBox(Math.round(x()), Math.round(y()), getWidth(),
				getHeight());
	}
	// 显示状态
	public boolean isVisible() {
		return visible;
	}
	// 是否显示精灵
	public void setVisible(boolean visible) {
		this.visible = visible;
	}
}



设定一个

CanvasScreenExample.java

,用以继承

CanvasScreen




import org.loon.framework.game.simple.GameScene;
import org.loon.framework.game.simple.action.sprite.Sprites;
import org.loon.framework.game.simple.core.graphics.CanvasScreen;
import org.loon.framework.game.simple.core.graphics.Deploy;
import org.loon.framework.game.simple.core.graphics.LImage;
import org.loon.framework.game.simple.core.graphics.device.LGraphics;
public class CanvasScreenExample extends CanvasScreen implements Runnable {
	// 设定精灵组,显示范围为宽240,高80(此为实际背景图大小)
	private Sprites sprs = new Sprites(240, 80);
	// 设定背景图像
	private LImage background = LImage.createImage("res/background.png");
	// 是否允许线程运行
	private boolean running;
	// 刷新间隔
	private long speed = 30;
	public CanvasScreenExample() {
		// 重载游戏画面大小,将240x80的实际游戏图像大小,扩大为480x160的显示大小
		super(240, 80, 480, 160);
		// 创建五个骷髅剑士的精灵
		Sword[] sw = new Sword[5];
		//循环载入
		for (int i = 0; i < sw.length; i++) {
			// 将精灵载入精灵管理器
			sprs.add(sw[i] = new Sword());
		}
		// 允许线程运行
		this.running = true;
		// 启动线程
		this.callEvent(new Thread(this));
	}
	// 当切换不同的Screen,或者游戏结束时,会触发此函数
	public void dispose() {
		this.running = false;
	}
	// 在绘图器中绘制背景图以及相关精灵
	public void paint(LGraphics g) {
		// 绘制背景图像到位置(0,0)
		g.drawImage(background, 0, 0);
		// 绘图精灵组中所有精灵(默认位置(0,0),也允许通过setLocation或setViewWindow变更显示位置及显示范围)
		sprs.createUI(g);
	}
	public void run() {
		while (running) {
			// 刷新游戏画面
			this.repaint();
			// 间隔30豪秒
			this.pause(speed);
			// 刷新精灵组
			sprs.update(speed);
		}
	}
	public void keyPressed(int keyCode) {
	}
	public void keyReleased(int keyCode) {
	}
	public void pointerMove(double x, double y) {
	}
	public void pointerPressed(double x, double y) {
	}
	public void pointerReleased(double x, double y) {
	}
}




此时,我们只需要根据需要实例化相关的Screen(也就是setScreen),就会得到如下效果:
实际运行效果如下(

Android

版效果与此相同,

PC

版中窗体实际大小被设定为

480x320











PS:



CanvasScreen

中也允许完全照搬

J2ME



Canvas(GameCanvas)

与相关精灵(内置有

API 1:1

的精灵类相关实现)的构建方式,可以将任何

J2ME

游戏代码平移其中。简单的讲,您在只掌握

J2ME

技术的情况下也可以使用

LGame

,而无需单独学习任何

LGame

框架本身的构建方式。



较早前LGame示例(仅PC版)下载地址:http://loon-simple.googlecode.com/files/LGame-Simple-0.2.5.7z

最新版LGame(0.2.6)下载地址:http://loon-simple.googlecode.com/files/LGame-0.2.6.rar
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐