您的位置:首页 > 其它

LGame-0.2.9版二次修正(LGame-0.2.95,新增塔防示例,已提供下载)

2011-01-25 22:07 204 查看
2011-02-01

http://loon-simple.googlecode.com/files/LGame-0.2.95%28Graphics%20Optimization%29.7z

农历新年前做一个额外更新,此文件中附带了目前最新的LGame打包jar及源码(累计不足15行代码的小修正),主要修正了一个对于Android环境来说不合理的图像刷新方法(JavaSE版无此问题),此修正能让标准Screen(即最基础的,自动刷新模式的那个Screen) 显示速度获得约3 ~ 7 fps 的上升(视真机而定)。

另外,此次附带的最新LGame-Core-0.2.95(指Android与JavaSE两版)基本等价于0.3版LGame主体(剩下那0.5是独立的SLG模块,以及一个webview的内部封装),非必要不会再有变动,至多会改进一些旧有的低效实现,添加两三个新的ActionEvent。当然,假如获得新的BUG反馈小弟也会及时修正。

最后,祝愿大家农历新年快乐,宏“兔”大展,万事如意~

PS:有网友要下面这个塔防示例的JavaSE版,小弟这次也顺便加上了(源码在jar中),解压后可以看到代码除输入接口API及启动程序部分外与Android版完全一致。



_________________________________________

下载地址(内含示例,源码及jar):

http://loon-simple.googlecode.com/files/LGame-0.2.95.7z

此版继续修正0.2.9版(及0.2.94)中所发现的问题并有所扩展。

为Screen增加了runFirstScreen、runLastScreen、runPreviousScreen、runNextScreen、runIndexScreen、addScreen、getScreens、getScreenCount等Screen管理接口,以简化多Screen运行时的处理流程。

增加ActionEvent管理器,并提供了MoveTo、FireTo、JumpTo、FadeTo、RotateTo、CircleTo等自动化事件类,它们是对常用角色行为的封装(就是处理一些固定的事件执行,比如用MoveTo随便指定一个坐标就可以让角色八方向或四方向行走到该处,用FireTo可以直接让角色向指定位置如子弹一样发射出去,以此类推),具体使用方式可见下例。

修正了所有获得用户反馈的前版BUG(准确的说,是小弟上上周来博客所看到的那些……),对一些函数的具体实现有所改进。

下面有一个非常简单的塔防示例,演示了LGame-0.2.95改进后的Layer及新增的ActionEvent机制使用。



示例代码如下(直接拖拽Layer即可显示不同区域画面):


package org.loon.test;
import java.util.HashMap;
import java.util.List;
import org.loon.framework.android.game.action.ActionListener;
import org.loon.framework.android.game.action.FadeTo;
import org.loon.framework.android.game.action.MoveTo;
import org.loon.framework.android.game.action.map.Field2D;
import org.loon.framework.android.game.action.sprite.StatusBar;
import org.loon.framework.android.game.core.LSystem;
import org.loon.framework.android.game.core.graphics.LColor;
import org.loon.framework.android.game.core.graphics.LImage;
import org.loon.framework.android.game.core.graphics.Screen;
import org.loon.framework.android.game.core.graphics.device.LGraphics;
import org.loon.framework.android.game.core.graphics.window.LPaper;
import org.loon.framework.android.game.core.graphics.window.actor.Actor;
import org.loon.framework.android.game.core.graphics.window.actor.ActorLayer;
import org.loon.framework.android.game.core.graphics.window.actor.Layer;
import android.view.MotionEvent;
public class TD extends Screen {
private int selectTurret = -1;
private Field2D field;
private String[] turrets = new String[] { "assets/bulletTurret.png",
"assets/bombTurret.png", "assets/poisonTurret.png",
"assets/laserTurret.png", "assets/bullet.png" };
/**
* 子弹用类
*
*/
class Bullet extends Actor {
private int dir;
private int damage;
private double x, y;
private boolean removeFlag;
public Bullet(String fileName, int dir, int damage) {
this.dir = dir;
this.damage = damage;
this.setImage(fileName);
this.setDelay(50);
}
protected void addLayer(ActorLayer layer) {
this.x = this.getX();
this.y = this.getY();
}
public void action(long t) {
if (removeFlag) {
return;
}
Object o = null;
for (int i = 0; i < 12; i++) {
// 矫正弹道位置
double angle = Math.toRadians((double) this.dir);
this.x += Math.cos(angle);
this.y += Math.sin(angle);
this.setLocation((int) this.x
+ (field.getTileWidth() - this.getWidth()) / 2,
(int) this.y
+ (field.getTileHeight() - this.getHeight())
/ 2);
o = this.getOnlyCollisionObject(Enemy.class);
}
// 当与敌相撞时
if (o != null) {
Enemy e = (Enemy) o;
// 减少敌方HP
e.hp -= this.damage;
e.hpBar.setUpdate(e.hp);
removeFlag = true;
// 从Layer中删除自身
getLayer().removeObject(this);
return;
// 超出游戏画面时删除自身
} else if (this.getX() <= 12
|| this.getX() >= this.getLayer().getWidth() - 96
|| this.getY() <= 12
|| this.getY() >= this.getLayer().getHeight() - 96) {
removeFlag = true;
this.getLayer().removeObject(this);
}
}
}
/**
* 炮塔用类
*
*/
class Turret extends Actor {
private int range = 50;
private int delay = 10;
boolean selected;
public Turret(String fileName) {
setImage(fileName);
setDelay(100);
setAlpha(0);
}
public void addLayer(ActorLayer layer) {
// 让角色渐进式出现
FadeTo fade = fadeOut();
// 监听渐进淡出事件
fade.setActionListener(new ActionListener() {
public void process(Actor o) {
}
public void start(Actor o) {
}
// 当渐进完毕时
public void stop(Actor o) {
// 旋转90度
rotateTo(90);
}
});
}
public void draw(LGraphics g) {
if (selected) {
g.setColor(255, 0, 0, 100);
g.fillOval(-(range*2-field.getTileWidth())/2, -(range*2-field.getTileHeight())/2, this.range * 2 - 1, this.range * 2 - 1);
g.setColor(LColor.red);
g.drawOval(-(range*2-field.getTileWidth())/2,-(range*2-field.getTileHeight())/2, this.range * 2 - 1, this.range * 2 - 1);
}
}
public void action(long t) {
// 遍历指定半径内所有Enemy类
List<?> es = this.getCollisionObjects(this.range, Enemy.class);
// 当敌人存在
if (!es.isEmpty()) {
Enemy target = (Enemy) es.get(0);
// 旋转炮台对准Enemy坐标
setRotation((int) Math.toDegrees(Math.atan2(
(target.getY() - this.getY()), (target.getX() - this
.getX()))));
}
// 延迟炮击
if (this.delay > 0) {
--this.delay;
} else if (!es.isEmpty()) {
// 构造炮弹
Bullet bullet = new Bullet(turrets[4], this.getRotation(), 2);
// 计算炮击点
int x = (int) Math.round(Math.cos(Math.toRadians(this
.getRotation()))
* (double) bullet.getWidth() * 2)
+ this.getX();
int y = (int) Math.round(Math.sin(Math.toRadians(this
.getRotation()))
* (double) bullet.getHeight() * 2)
+ this.getY();
// 注入炮弹到Layer
this.getLayer().addObject(bullet, x, y);
this.delay = 10;
}
}
}
/**
* 敌兵用类
*
*/
class Enemy extends Actor {
private int startX, startY;
private int endX, endY;
private int speed, hp;
private boolean removeFlag;
// 使用精灵StatusBar充当血槽
protected StatusBar hpBar;
public Enemy(String fileName, int sx, int sy, int ex, int ey,
int speed, int hp) {
this.setDelay(300);
this.setImage(fileName);
this.hpBar = new StatusBar(hp, hp, -5, 18, 25, 5);
this.startX = sx;
this.startY = sy;
this.endX = ex;
this.endY = ey;
this.speed = speed;
this.hp = hp;
}
public void draw(LGraphics g) {
// 绘制精灵
hpBar.createUI(g);
}
public void action(long t) {
// 触发精灵事件
hpBar.update(t);
if (hp <= 0 && !removeFlag) {
// 设定死亡时渐变
FadeTo fade = fadeIn();
// 渐变时间为30毫秒
fade.setSpeed(30);
// 监听渐变过程
fade.setActionListener(new ActionListener() {
public void process(Actor o) {
}
public void start(Actor o) {
}
public void stop(Actor o) {
Enemy.this.removeActionEvents();
Enemy.this.getLayer().removeObject(Enemy.this);
}
});
this.removeFlag = true;
}
}
// 首次注入Layer时调用此函数
public void addLayer(final ActorLayer layer) {
// 坐标矫正,用以让角色居于瓦片中心
final int offsetX = (getLayer().getField2D().getTileWidth() - this
.getWidth()) / 2;
final int offsetY = (getLayer().getField2D().getTileWidth() - this
.getHeight()) / 2;
// 初始化角色在Layer中坐标
setLocation(startX + offsetX, startY + offsetY);
// 命令角色向指定坐标(参数为false为四方向寻径,为true时八方向)自动移动,并返回移动控制器
// PS:endX与endY非显示位置,所以不必矫正
final MoveTo move = moveTo(endX, endY, false);
// 启动角色事件监听
move.setActionListener(new ActionListener() {
// 截取事件进行中数据
public void process(Actor o) {
// 矫正坐标,让角色居中
o.setLocation(o.getX() + offsetX, o.getY() + offsetY);
// 获得角色移动方向
switch (move.getDirection()) {
case Field2D.TUP:
// 根据当前移动方向,变更角色旋转方向(以下同)
o.setRotation(270);
break;
case Field2D.TLEFT:
o.setRotation(180);
break;
case Field2D.TRIGHT:
o.setRotation(0);
break;
case Field2D.TDOWN:
o.setRotation(90);
break;
default:
break;
}
}
public void start(Actor o) {
}
// 当角色移动完毕时
public void stop(Actor o) {
// 从Layer中删除此角色
layer.removeObject(o);
}
});
// 设定移动速度
move.setSpeed(speed);
}
}
// 起始点
class Begin extends Actor {
public Begin(String fileName) {
setImage(fileName);
}
}
// 结束点
class End extends Actor {
public End(String fileName) {
setImage(fileName);
}
}
/**
* 拖拽用菜单
*
*/
class Menu extends Layer {
public Menu() {
super(128, 240);
// 设定menu层级高于MapLayer
setLayer(101);
// 不锁定menu移动
setLocked(false);
setLimitMove(false);
// 锁定Actor拖拽
setActorDrag(false);
setDelay(500);
// 设定Menu背景
LImage image = LImage.createImage(this.getWidth(),
this.getHeight(), false);
LGraphics g = image.getLGraphics();
g.setColor(LColor.black);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(LColor.white);
g.setFont(15);
g.drawString("我是可拖拽菜单", 12, 25);
g.dispose();
setBackground(image);
LPaper bulletTurret = new LPaper(turrets[0]) {
// 当选中当前按钮时,为按钮绘制选中框(以下同)
public void paint(LGraphics g) {
if (selectTurret == 0) {
g.setColor(LColor.red);
g.drawRect(0, 0, this.getWidth() - 2,
this.getHeight() - 2);
}
}
public void downClick() {
selectTurret = 0;
}
};
bulletTurret.setLocation(18, 64);
LPaper bombTurret = new LPaper(turrets[1]) {
public void paint(LGraphics g) {
if (selectTurret == 1) {
g.setColor(LColor.red);
g.drawRect(0, 0, this.getWidth() - 2,
this.getHeight() - 2);
}
}
public void downClick() {
selectTurret = 1;
}
};
bombTurret.setLocation(78, 64);
LPaper poisonTurret = new LPaper(turrets[2]) {
public void paint(LGraphics g) {
if (selectTurret == 2) {
g.setColor(LColor.red);
g.drawRect(0, 0, this.getWidth() - 2,
this.getHeight() - 2);
}
}
public void downClick() {
selectTurret = 2;
}
};
poisonTurret.setLocation(18, 134);
LPaper laserTurret = new LPaper(turrets[3]) {
public void paint(LGraphics g) {
if (selectTurret == 3) {
g.setColor(LColor.red);
g.drawRect(0, 0, this.getWidth() - 2,
this.getHeight() - 2);
}
}
public void downClick() {
selectTurret = 3;
}
};
laserTurret.setLocation(78, 134);
// 用LPaper制作敌人增加按钮
LPaper button = new LPaper("assets/button.png") {
public void paint(LGraphics g) {
g.setColor(LColor.white);
g.drawString("增加敌人", 15, 15);
}
public void downClick() {
// 获得MapLayer
MapLayer layer = (MapLayer) getBottomLayer();
// 开始游戏演算
layer.doStart();
}
};
button.setLocation(27, 196);
// 复合LPaper到Layer
add(bulletTurret);
add(bombTurret);
add(poisonTurret);
add(laserTurret);
add(button);
setAlpha(0.5F);
}
public void downClick(int x, int y) {
selectTurret = -1;
}
}
/**
* 大地图用Layer
*/
class MapLayer extends Layer {
private boolean start;
private int startX, startY, endX, endY;
private int index, count;
@SuppressWarnings("unchecked")
public MapLayer() {
super(576, 480, true);
// 不锁定MapLayer拖拽
setLocked(false);
// 锁定MapLayer中角色拖拽
setActorDrag(false);
// 设置MapLayer背景元素(键值需要与map.txt文件中标识相对应)
HashMap pathMap = new HashMap(10);
pathMap.put(new Integer(0), new LImage("assets/sand.png"));
pathMap.put(new Integer(1), new LImage("assets/sandTurn1.png"));
pathMap.put(new Integer(2), new LImage("assets/sandTurn2.png"));
pathMap.put(new Integer(3), new LImage("assets/sandTurn3.png"));
pathMap.put(new Integer(4), new LImage("assets/sandTurn4.png"));
pathMap.put(new Integer(5), new Begin("assets/base.png"));
pathMap.put(new Integer(6), new End("assets/castle.png"));
// 为Layer加入简单的2D地图背景,瓦片大小32x32,以rock图片铺底
setField2DBackground(new Field2D("assets/map.txt", 32, 32),
pathMap, "assets/rock.png");
TD.this.field = getField2D();
// 敌人出现坐标
this.startX = 64;
this.startY = 416;
// 敌人消失坐标
this.endX = 480;
this.endY = 416;
// 设定MapLayer每隔2秒执行一次内部Action
setDelay(LSystem.SECOND * 2);
}
public void action(long t) {
// 当启动标识为true时执行以下操作
if (start) {
if (index < 3) {
Enemy enemy = null;
// 根据点击next(增加敌人)的次数变换敌人样式
switch (count) {
case 0:
enemy = new Enemy("assets/enemy.png", startX, startY,
endX, endY, 2, 4);
break;
case 1:
enemy = new Enemy("assets/fastEnemy.png", startX,
startY, endX, endY, 4, 6);
break;
case 2:
enemy = new Enemy("assets/smallEnemy.png", startX,
startY, endX, endY, 3, 10);
break;
case 3:
enemy = new Enemy("assets/bigEnemy.png", startX,
startY, endX, endY, 1, 16);
break;
default:
count = 0;
enemy = new Enemy("assets/enemy.png", startX, startY,
endX, endY, 2, 2);
break;
}
addObject(enemy);
index++;
// 否则复位
} else {
start = false;
index = 0;
count++;
}
}
}
private Actor o = null;
public void downClick(int x, int y) {
// 转换鼠标点击区域为数组地图坐标
int newX = x / field.getTileWidth();
int newY = y / field.getTileHeight();
// 当选中炮塔(参数不为-1)且数组地图参数为-1(不可通过)并且无其它角色在此时
if ((o = getOnlyCollisionObjectsAt(x, y)) == null
&& selectTurret != -1 && field.getType(newY, newX) == -1) {
// 添加炮塔
addObject(new Turret(turrets[selectTurret]), newX
* field.getTileWidth(), newY * field.getTileHeight());
}
if (o != null) {
((Turret) o).selected = true;
}
}
public void upClick(int x, int y) {
if (o != null) {
((Turret) o).selected = false;
}
}
public void doStart() {
this.start = true;
}
}
public void onLoad() {
// 构建地图用Layer
MapLayer layer = new MapLayer();
// 居中
centerOn(layer);
// 添加MapLayer到Screen
add(layer);
// 构建菜单用Layer
Menu menu = new Menu();
// 让menu居于屏幕右侧
rightOn(menu);
menu.setY(0);
// 添加menu到Screen
add(menu);
}
public void draw(LGraphics g) {
}
public void onTouchDown(MotionEvent e) {
}
public void onTouchMove(MotionEvent e) {
}
public void onTouchUp(MotionEvent e) {
}
}


运行画面如下所示:







以上已实现部分待0.3版发布时还会有更进一步的改进,不过目前最主要的还是修订SLG模块,另外在0.2.95遇到BUG的话希望大家能吼一声,小弟争取在0.3中全部改好。

下载地址(内含示例,源码及jar):

http://loon-simple.googlecode.com/files/LGame-0.2.95.7z

——————————————

2011-01-27

不好意思让大家久等了,小弟保险起见等Google维护过了才上传(以前吃过一次亏,那次害小弟倒时差的邮件联系了管理员两天,后来变得不见维护结束不踏实|||),此版本是针对LGame-0.2.9的最终修订版,绝大部分0.2.9的BUG在此版中已不复存在(好吧,小弟承认刚才看留言又发现两个漏网BUG,不过对程序主干没有影响,都是一、二行搞定的细节问题,且不是常用项……)。

应该说0.2.95版至少在易用性上又上了一个台阶,不是小弟自夸,单就开发效率和学习难度而言,绝大多数Android游戏引擎都应该从此版起被Loon甩在了后面——包括某些引擎的Android移植版在内。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: