LGame-0 2 9版二次修正 LGame-0 2 95,新增塔防示例,已提供下载

               

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版完全一致。

 

JavaSE版塔防示例

_________________________________________

 

下载地址(内含示例,源码及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) { }}



运行画面如下所示:

 

00

 

01

 


以上已实现部分待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移植版在内。

 

 

 

 

           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值