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

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               

较早前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函数中构造如下内容即可。

[java] view plain copy print ?
  1. public static void main(String[] args) {  
  2.         // 获得一个游戏窗体  
  3.         GameScene frame = new GameScene("窗体名",  
  4.                 480320);  
  5.         // 得到此窗体所对应的游戏部署器  
  6.         Deploy deploy = frame.getDeploy();  
  7.         // 设定此游戏屏幕(在任何时候都可以通过Screen中的setScreen函数切换游戏屏幕)  
  8.         deploy.setScreen(new Game());  
  9.         // 是否显示FPS  
  10.         deploy.setShowFPS(true);  
  11.         // 是否显示框架logo  
  12.         deploy.setLogo(false);  
  13.         // 允许的最大刷新率  
  14.         deploy.setFPS(100);  
  15.         // 开始游戏主循环  
  16.         deploy.mainLoop();  
  17.         // 显示游戏画面  
  18.         frame.showFrame();  
  19. }  
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文档。

如下所示:

[xhtml] view plain copy print ?
  1. xml version="1.0" encoding="utf-8"?>  
  2. <manifest xmlns:android="http://schemas.android.com/apk/res/android"  
  3.       package="org.loon.test"  
  4.       android:versionCode="1"  
  5.       android:versionName="1.0">  
  6.     <application android:icon="@drawable/icon" android:label="@string/app_name">  
  7.         <activity android:name=".Main"  
  8.                   android:configChanges="orientation|keyboardHidden"   
  9.             <intent-filter>  
  10.                 <action android:name="android.intent.action.MAIN" />  
  11.                 <category android:name="android.intent.category.LAUNCHER" />  
  12.             intent-filter>  
  13.         activity>  
  14.     application>  
  15.     <uses-sdk android:minSdkVersion="3" />  
  16.     <uses-permission android:name="android.permission.INTERNET"/>  
  17. manifest>   
                                                                             

而调用的方法如下:

[java] view plain copy print ?
  1. package org.loon.test;    
  2. import org.loon.framework.android.game.LAD;    
  3. import org.loon.framework.android.game.LGameAndroid2DActivity;    
  4. import org.loon.framework.android.game.core.LSystem;    
  5. import android.os.Bundle;    
  6. public class Main extends LGameAndroid2DActivity {    
  7.      public void onCreate(Bundle icicle) {    
  8.          // 有Admob广告,纵屏显示,广告居于屏幕下方,广告ID为“XXXXXXXX”,广告刷新速度为60秒    
  9.          this.initialization(icicle,false,LAD.BOTTOM, "XXXXXXXX",60);    
  10.          // 无Admob广告,纵屏显示    
  11.          // this.initialization(icicle,false);    
  12.          // 使用游戏窗体Game    
  13.          this.setScreen(new Game());    
  14.          // 设定FPS为60    
  15.          this.setFPS(60);    
  16.          // 不显示游戏Logo(设定Logo为setLogo)    
  17.          this.setShowLogo(false);    
  18.          // 显示FPS    
  19.          this.setShowFPS(true);    
  20.          // 显示游戏画面    
  21.          this.showScreen();    
  22.      }    
  23. }   
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版使用方式如下:

[java] view plain copy print ?
  1. import java.awt.event.KeyEvent;  
  2. import java.awt.event.MouseEvent;  
  3. import org.loon.framework.game.simple.core.graphics.Screen;  
  4. import org.loon.framework.game.simple.core.graphics.device.LGraphics;  
  5. public class ScreenExample extends Screen {  
  6.       
  7. // draw中LGraphics会根据设定的FPS自动刷新,使用上与标准的J2SE Graphics以及J2ME Graphics接口没有区别(API为二者的综合)  
  8.     public void draw(LGraphics g) {  
  9.     }  
  10.     // 鼠标左键  
  11.     public void leftClick(MouseEvent e) {  
  12.     }  
  13.     // 鼠标中间键  
  14.     public void middleClick(MouseEvent e) {  
  15.     }  
  16.     // 鼠标右键  
  17.     public void rightClick(MouseEvent e) {  
  18.     }  
  19.     // 键盘按下  
  20.     public void onKey(KeyEvent e) {  
  21.     }  
  22.     // 键盘放开  
  23.     public void onKeyUp(KeyEvent e) {  
  24.     }  
  25. }  
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版使用方式如下:

AndroidScreen API与使用方法基本等价于J2SE版,但由于手机与PC间功能有所差别,所以具体的API名及函数有所不同。

[java] view plain copy print ?
  1. import org.loon.framework.android.game.core.graphics.Screen;  
  2. import android.view.KeyEvent;  
  3. import android.view.MotionEvent;  
  4. public class ScreenExample extends Screen{  
  5.       
  6.     // 与J2SE版相同,draw中LGraphics会根据设定的FPS自动刷新,使用上与标准的J2SE Graphics以及J2MEGraphics接口没有区别(API为二者的综合)  
  7.     public void draw(LGraphics g) {  
  8.     }  
  9.     //键盘按下  
  10.     public boolean onKeyDown(int keyCode, KeyEvent e) {  
  11.         return true;  
  12.     }  
  13.     //键盘放开  
  14.     public boolean onKeyUp(int keyCode, KeyEvent e) {  
  15.         return true;  
  16.     }  
  17.     //触摸屏按下  
  18.     public boolean onTouchDown(MotionEvent e) {  
  19.         return true;  
  20.     }  
  21.     //手指在触摸屏上移动  
  22.     public boolean onTouchMove(MotionEvent e) {  
  23.         return true;  
  24.     }  
  25.     //触摸屏放开  
  26.     public boolean onTouchUp(MotionEvent e) {  
  27.         return true;  
  28.     }  
  29. }  
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函数中即是一个独立的线程。

[java] view plain copy print ?
  1. import java.awt.event.KeyEvent;  
  2. import java.awt.event.MouseEvent;  
  3. import org.loon.framework.game.simple.core.graphics.ThreadScreen;  
  4. import org.loon.framework.game.simple.core.graphics.device.LGraphics;  
  5. public class ThreadScreenExample extends ThreadScreen {  
  6.     public ThreadScreenExample () {  
  7.         // ThreadScreen及CanvasScreen都允许变更游戏图形界面大小,下例重载参数为最初(实际)的界面大小。  
  8.         super(300450);  
  9.         // 设定显示时图像大小,此时游戏将以320x480的大小运行(视原有界面不同,会有不同程度的失真)  
  10.         resizeScreen(320480);  
  11.     }  
  12.     // ThreadScreen绘图器,为标准Screen中draw函数的封装,区别在于ThreadScreen的修改仅在repaint时生效,而且ThreadScreen不会自动清除原有的图像内容。  
  13.     public void drawScreen(LGraphics g) {  
  14.     }  
  15. // gameLoop的刷新速度可以通过setSynchroFPS函数调整。  
  16.     public void gameLoop() {  
  17.           
  18.     }  
  19.     // 鼠标左键  
  20.     public void leftClick(MouseEvent e) {  
  21.     }  
  22.     // 鼠标中间键  
  23.     public void middleClick(MouseEvent e) {  
  24.     }  
  25.     // 鼠标右键  
  26.     public void rightClick(MouseEvent e) {  
  27.     }  
  28.     // 键盘按下  
  29.     public void onKey(KeyEvent e) {  
  30.     }  
  31.     // 键盘放开  
  32.     public void onKeyUp(KeyEvent e) {  
  33.     }  
  34. }  
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可以通过getLGraphicsgetDrawDraw类为LGraphics的简化封装)函数直接获得对LGraphics的操作权,并非一定要通过drawScreen函数绘图。

Android版:

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

[java] view plain copy print ?
  1. import org.loon.framework.android.game.core.graphics.ThreadScreen;  
  2. import android.view.KeyEvent;  
  3. import android.view.MotionEvent;  
  4. public class ThreadScreenExample extends ThreadScreen {  
  5.     public ThreadScreenExample () {  
  6.         // ThreadScreen及CanvasScreen都允许变更游戏图形界面大小,下例重载参数为最初(实际)的界面大小。  
  7.         super(300450);  
  8.         // 设定显示时图像大小,此时游戏将以320x480的大小运行(视原有界面不同,会有不同程度的失真)  
  9.         resizeScreen(320480);  
  10.     }  
  11.     // ThreadScreen绘图器,为标准Screen中draw函数的封装,区别在于drawScreen的修改仅在repaint时生效,而且drawScreen不会自动清除原有的图像内容。  
  12.     public void drawScreen(LGraphics g) {  
  13.     }  
  14. // gameLoop的刷新速度可以通过setSynchroFPS函数调整。  
  15.     public void gameLoop() {  
  16.           
  17.     }  
  18.     //键盘按下  
  19.     public boolean onKeyDown(int keyCode, KeyEvent e) {  
  20.         return true;  
  21.     }  
  22.     //键盘放开  
  23.     public boolean onKeyUp(int keyCode, KeyEvent e) {  
  24.         return true;  
  25.     }  
  26.     //触摸屏按下  
  27.     public boolean onTouchDown(MotionEvent e) {  
  28.         return true;  
  29.     }  
  30.     //手指在触摸屏上移动  
  31.     public boolean onTouchMove(MotionEvent e) {  
  32.         return true;  
  33.     }  
  34.     //触摸屏放开  
  35.     public boolean onTouchUp(MotionEvent e) {  
  36.         return true;  
  37.     }  
  38. }  
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

CanvasScreen0.2.6版中最新提供的Screen实现,模拟J2MECanvas而成(也混合了GameCanvasAPI),相关函数在J2SEAndroid版中完全一致。

[java] view plain copy print ?
  1. import org.loon.framework.game.simple.core.graphics.CanvasScreen;  
  2. import org.loon.framework.game.simple.core.graphics.device.LGraphics;  
  3. public class CanvasScreenExample extends CanvasScreen {  
  4.     public CanvasScreenExample(){  
  5.         //与ThreadScreen相同,CanvaScreen允许改变游戏图像大小。  
  6.         //以下参数分为别原始的图像宽与高(300x450),要求显示的宽与高(320x480)  
  7.         super(300,450,320,480);  
  8.     }  
  9.     // CanvasScreen绘图器,与标准Screen中draw函数的区别在于paint的修改仅在repaint时生效,而且paint不会自动清除原有的图像内容。  
  10.     public void paint(LGraphics g) {  
  11.      
  12.     }  
  13.     // 键盘按下  
  14.     public void keyPressed(int keyCode) {  
  15.     }  
  16.     // 键盘放开  
  17.     public void keyReleased(int keyCode) {  
  18.     }  
  19.     // 触摸屏或鼠标移动  
  20.     public void pointerMove(double x, double y) {  
  21.     }  
  22.     // 触摸屏或鼠标按下  
  23.     public void pointerPressed(double x, double y) {  
  24.     }  
  25.     // 触摸屏或鼠标放开  
  26.     public void pointerReleased(double x, double y) {  
  27.     }  
  28. }  
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函数绘图。另外,由于CanvasScreenPaint函数并不直接关联父类的draw函数,所以LGame中提供的精灵或组件无法直接通过add函数加载显示,而是只能在paint中手动调用相应组件的绘图器进行绘制(关于这点,用惯J2ME的朋友应该没什么不习惯的。另外LGame提供有配套的j2me精灵类包可供使用,为11仿J2ME原有API实现)。

 

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

 

//初始化时的精灵动画

01

//移动时的精灵动画

02

//背景图片

03

 

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


下面我制作一个Sword.java,这是一个自定义的精灵类,用以显示上图所示的“骷髅剑士”。(在不重新实现ISprite的基础上,我们也可以直接使用现成的Sprite类来完成此例。但是,关于动作细节部分就只能在精类外部设定或者重载Spriteupdate函数来实现(和实现ISprite没什么区别了|||))。

 

[java] view plain copy print ?
  1. import org.loon.framework.game.simple.action.map.RectBox;  
  2. import org.loon.framework.game.simple.action.sprite.Animation;  
  3. import org.loon.framework.game.simple.action.sprite.ISprite;  
  4. import org.loon.framework.game.simple.action.sprite.SpriteImage;  
  5. import org.loon.framework.game.simple.core.LObject;  
  6. import org.loon.framework.game.simple.core.LSystem;  
  7. import org.loon.framework.game.simple.core.graphics.device.LGraphics;  
  8. import org.loon.framework.game.simple.core.timer.LTimer;  
  9. public class Sword extends LObject implements ISprite {  
  10.     /** 
  11.      *  
  12.      */  
  13.     private static final long serialVersionUID = 1L;  
  14.     // 精灵移动范围的最大宽度(即背景图实际宽,为240)  
  15.     private static final int WIDTH = 240;  
  16.     private boolean init, right, flag, visible;  
  17.     private int randX;  
  18.     private Animation animation;  
  19.     private LTimer time;  
  20.     private static final String kName1 = "res/s1.png", kName2 = "res/s2.png";  
  21.     public Sword() {  
  22.         // 加载怪物剑士的“出土”动画(以下参数为图像所在地址、图像宽、图像高、播放间隔)  
  23.         this.animation = Animation.getDefaultAnimation(kName1, 1818150);  
  24.         // 设定计时器间隔为10豪秒  
  25.         this.time = new LTimer(10);  
  26.         // 设定精灵初始位置(x轴随机,y轴48(立于相对于背景视觉的“地面”上))  
  27.         this.setLocation(LSystem.random.nextInt(WIDTH), 48);  
  28.         // 随机决定精灵剑士向左或向右冲锋  
  29.         this.right = LSystem.random.nextInt(2) == 0 ? true : false;  
  30.         // 随机决定精灵剑士以匀速或两倍速前进  
  31.         this.flag = LSystem.random.nextInt(2) == 0 ? true : false;  
  32.         // 随机决定精灵剑士的“冲锋”停止点  
  33.         this.randX = LSystem.random.nextInt(70);  
  34.         // 当前精灵可见  
  35.         this.visible = true;  
  36.     }  
  37.     // 设定精灵绘图器内容  
  38.     public void createUI(LGraphics g) {  
  39.         if (animation != null) {  
  40.             // PS:Android版中没有提供序列化保存SpriteImage的方法,直接getImage即可,而没有serializablelImage。  
  41.             // 反转图像  
  42.             if (right) {  
  43.                 g.drawMirrorImage(animation.getSpriteImage().serializablelImage  
  44.                         .getImage(), x(), y());  
  45.                 // 正向  
  46.             } else {  
  47.                 g.drawImage(animation.getSpriteImage().serializablelImage  
  48.                         .getImage(), x(), y());  
  49.             }  
  50.         }  
  51.     }  
  52.     // 当前精灵宽  
  53.     public int getWidth() {  
  54.         SpriteImage si = animation.getSpriteImage();  
  55.         if (si == null) {  
  56.             return -1;  
  57.         }  
  58.         return si.getWidth();  
  59.     }  
  60.     // 当前精灵高  
  61.     public int getHeight() {  
  62.         SpriteImage si = animation.getSpriteImage();  
  63.         if (si == null) {  
  64.             return -1;  
  65.         }  
  66.         return si.getHeight();  
  67.     }  
  68.     // 精灵计时器,用以在timer满足条件时变更精灵样式  
  69.     public void update(long timer) {  
  70.         if (time.action(timer)) {  
  71.             animation.update(timer);  
  72.             // 当动画没有播放时  
  73.             if (!animation.isRunning()) {  
  74.                 // 初始化动画精灵(以下参数为图像所在地址、图像宽、图像高、播放间隔)  
  75.                 animation = Animation.getDefaultAnimation(kName2, 261850);  
  76.             } else if (animation.isRunning() && init) {  
  77.                 // 向左  
  78.                 if (!right && (x() + randX) > 0) {  
  79.                     if (flag) {  
  80.                         // 精灵向左移动  
  81.                         move_left();  
  82.                     } else {  
  83.                         // 精灵向左移动(速度x2)  
  84.                         move_left(2);  
  85.                     }  
  86.                     if ((x() - randX) <= 0) {  
  87.                         right = true;  
  88.                     }  
  89.                     // 向右  
  90.                 } else if (right  
  91.                         && (x() + animation.getSpriteImage().getWidth() - randX) <= WIDTH) {  
  92.                     if (flag) {  
  93.                         // 精灵向右移动(速度x2)  
  94.                         move_right(2);  
  95.                     } else {  
  96.                         // 精灵向右移动  
  97.                         move_right();  
  98.                     }  
  99.                     // 当达到屏幕边缘时,改变移动方向  
  100.                     if ((x() + animation.getSpriteImage().getWidth() + randX) >= WIDTH) {  
  101.                         right = false;  
  102.                     }  
  103.                 }  
  104.             }  
  105.             // 当精灵动画结束时,设定init=true(精灵动画播放完毕)  
  106.             if (!init  
  107.                     && animation.getTotalFrames() - 1 == animation  
  108.                             .getCurrentFrameIndex()) {  
  109.                 animation.setRunning(false);  
  110.                 init = true;  
  111.             }  
  112.         }  
  113.     }  
  114.     // 透明度  
  115.     public float getAlpha() {  
  116.         return 0;  
  117.     }  
  118.     // 碰撞盒  
  119.     public RectBox getCollisionBox() {  
  120.         return new RectBox(Math.round(x()), Math.round(y()), getWidth(),  
  121.                 getHeight());  
  122.     }  
  123.     // 显示状态  
  124.     public boolean isVisible() {  
  125.         return visible;  
  126.     }  
  127.     // 是否显示精灵  
  128.     public void setVisible(boolean visible) {  
  129.         this.visible = visible;  
  130.     }  
  131. }  
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

 

[java] view plain copy print ?
  1. import org.loon.framework.game.simple.GameScene;  
  2. import org.loon.framework.game.simple.action.sprite.Sprites;  
  3. import org.loon.framework.game.simple.core.graphics.CanvasScreen;  
  4. import org.loon.framework.game.simple.core.graphics.Deploy;  
  5. import org.loon.framework.game.simple.core.graphics.LImage;  
  6. import org.loon.framework.game.simple.core.graphics.device.LGraphics;  
  7. public class CanvasScreenExample extends CanvasScreen implements Runnable {  
  8.     // 设定精灵组,显示范围为宽240,高80(此为实际背景图大小)  
  9.     private Sprites sprs = new Sprites(24080);  
  10.     // 设定背景图像  
  11.     private LImage background = LImage.createImage("res/background.png");  
  12.     // 是否允许线程运行  
  13.     private boolean running;  
  14.     // 刷新间隔  
  15.     private long speed = 30;  
  16.     public CanvasScreenExample() {  
  17.         // 重载游戏画面大小,将240x80的实际游戏图像大小,扩大为480x160的显示大小  
  18.         super(24080480160);  
  19.         // 创建五个骷髅剑士的精灵  
  20.         Sword[] sw = new Sword[5];  
  21.         //循环载入  
  22.         for (int i = 0; i < sw.length; i++) {  
  23.             // 将精灵载入精灵管理器  
  24.             sprs.add(sw[i] = new Sword());  
  25.         }  
  26.         // 允许线程运行  
  27.         this.running = true;  
  28.         // 启动线程  
  29.         this.callEvent(new Thread(this));  
  30.  &nbs

    给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

    这里写图片描述

你可能感兴趣的:(LGame Android及J2SE游戏引擎 入门示例——如何构建一个游戏)