libgdx游戏引擎开发笔记(十一)SuperJumper游戏例子的讲解(篇五)---- .游戏中的物体的创建

简介:

   游戏中物体比较多,这里源码里用了两个类封装了游戏中物体的主要属性,方便游戏中物体的封装。


1.GameObject类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package  com.zhf.mylibgdx;
import  com.badlogic.gdx.math.Rectangle;
import  com.badlogic.gdx.math.Vector2;
/**
  * 所有的游戏物体都会在一个平面内绘制(或者说在屏幕大小内绘制),那么所有的物体都应该包含一个位置(position) 和一个作用范围(bounds)
  * @author ZHF
  *
  */
public  class  GameObject {
     public  final  Vector2 position;   //位置
     public  final  Rectangle bounds;   //作用范围
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
     /**postion在这里是指游戏物体的中心点,而bounds中的x ,y 坐标是指这个游戏原素在屏幕坐标系中的作用起点,也就是矩形的左下角顶点**/
     public  GameObject( float  x,  float  y,  float  width,  float  height) {
         this .position =  new  Vector2(x, y);
         this .bounds =  new  Rectangle(x - width /  2 , y - height /  2 , width, height);
     }
}

2.DynamicGameObject类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package  com.zhf.mylibgdx;
import  com.badlogic.gdx.math.Vector2;
/**
  * 会移动的游戏物体
  * @author ZHF
  *
  */
public  class  DynamicGameObject  extends  GameObject {
     //包含了 x, y 轴方向相关的运动信息。
     public  final  Vector2 velocity;   //速度
     public  final  Vector2 accel;    //加速度
     public  DynamicGameObject ( float  x,  float  y,  float  width,  float  height) {
         super (x, y, width, height);
         velocity =  new  Vector2();
         accel =  new  Vector2();
     }
}


   接下来就是让游戏中的物体来分别根据自己的情况去继承它们:

Bob ------> 主角

               Castle -----> 城堡

               Coin -----> 金币

               Platform ------> 平台

               Spring -------> 弹簧

               Squirrel -------> 空中飞行的松鼠

这里我们先将这六个类写出来,待会实现一下跳板是如何显示出来,我们就大体知道了整个游戏的逻辑了。ok! 上代码!


1.Bob类:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package  com.zhf.mylibgdx;
/**
  * 主角
  * @author ZHF
  *
  */
public  class  Bob  extends  DynamicGameObject {
     //主角状态
     public  static  final  int  BOB_STATE_JUMP =  0 ;   //跳跃
     public  static  final  int  BOB_STATE_FALL =  1 ;   //下落
     public  static  final  int  BOB_STATE_HIT =  2 ;    //碰撞
     //速度
     public  static  final  float  BOB_JUMP_VELOCITY =  11 //跳跃的速度
     public  static  final  float  BOB_MOVE_VELOCITY =  20 ;   //移动的速度
     //宽和高
     public  static  final  float  BOB_WIDTH =  0 .8f;
     public  static  final  float  BOB_HEIGHT =  0 .8f;
                                                                                                                                                                                                                                                                                                                                                                      
     int  state;   //状态
     float  stateTime;  //状态持时间
     public  Bob( float  x,  float  y) {
         super (x, y, BOB_WIDTH, BOB_HEIGHT);
         //初始化状态
         state = BOB_STATE_FALL;
         stateTime =  0 ;
     }
                                                                                                                                                                                                                                                                                                                                                                      
     /**刷新**/
     public  void  update ( float  deltaTime) {
         //x,y轴速度的大小
         velocity.add(World.gravity.x * deltaTime, World.gravity.y * deltaTime);
         //主角当前移动的位置
         position.add(velocity.x * deltaTime, velocity.y * deltaTime);
         bounds.x = position.x - bounds.width /  2 ;
         bounds.y = position.y - bounds.height /  2 ;
         //跳跃状态
         if  (velocity.y >  0  && state != BOB_STATE_HIT) {
             if  (state != BOB_STATE_JUMP) {
                 state = BOB_STATE_JUMP;
                 stateTime =  0 ;
             }
         }
         //下落状态
         if  (velocity.y <  0  && state != BOB_STATE_HIT) {
             if  (state != BOB_STATE_FALL) {
                 state = BOB_STATE_FALL;
                 stateTime =  0 ;
             }
         }
         //边界限制
         if  (position.x <  0 ) position.x = World.WORLD_WIDTH;
         if  (position.x > World.WORLD_WIDTH) position.x =  0 ;
         //状态持续时间
         stateTime += deltaTime;
     }
     /**撞到松鼠**/
     public  void  hitSquirrel () {
         velocity.set( 0 0 );
         state = BOB_STATE_HIT;
         stateTime =  0 ;
     }
     /**撞到跳板**/
     public  void  hitPlatform () {
         velocity.y = BOB_JUMP_VELOCITY;
         state = BOB_STATE_JUMP;
         stateTime =  0 ;
     }
     /**撞到弹簧**/
     public  void  hitSpring () {
         velocity.y = BOB_JUMP_VELOCITY *  1 .5f;
         state = BOB_STATE_JUMP;
         stateTime =  0 ;
     }
}


2.Castle类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package  com.zhf.mylibgdx;
/**
  * 城堡
  * @author ZHF
  *
  */
public  class  Castle  extends  GameObject {
     //宽和高
     public  static  float  CASTLE_WIDTH =  1 .7f;
     public  static  float  CASTLE_HEIGHT =  1 .7f;
     public  Castle( float  x,  float  y) {
         super (x, y, CASTLE_WIDTH, CASTLE_HEIGHT);
     }
}


3.Coin类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package  com.zhf.mylibgdx;
/**
  * 金币
  * @author ZHF
  *
  */
public  class  Coin  extends  GameObject {
     // 宽和高
     public  static  final  float  COIN_WIDTH =  0 .5f;
     public  static  final  float  COIN_HEIGHT =  0 .8f;
     // 金币的分值
     public  static  final  int  COIN_SCORE =  10 ;
     float  stateTime;  // 状态持续时间
     public  Coin( float  x,  float  y) {
         super (x, y, COIN_WIDTH, COIN_HEIGHT);
         stateTime =  0 ;
     }
     /**刷新**/
     public  void  update( float  deltaTime) {
         stateTime += deltaTime;
     }
}


4.Platform类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package  com.zhf.mylibgdx;
/**
  * 跳板
  * @author ZHF
  *
  */
public  class  Platform  extends  DynamicGameObject {
     //宽和高
     public  static  final  float PLATFORM_WIDTH =  2 ;
     public  static  final  float PLATFORM_HEIGHT =  0 .5f;
     //跳板的类型
     public  static  final  int  PLATFORM_TYPE_STATIC =  0 ;   //静止
     public  static  final  int  PLATFORM_TYPE_MOVING =  1 ;   //运动
     //跳板的状态
     public  static  final  int  PLATFORM_STATE_NORMAL =  0 //正常
     public  static  final  int  PLATFORM_STATE_PULVERIZING =  1 //破碎
                                                                                                                                                                                                                                                                                                               
     public  static  final  float PLATFORM_PULVERIZE_TIME =  0 .2f *  4 ;   //破碎所需时间
     public  static  final  float PLATFORM_VELOCITY =  2 ;   //跳板移动速度
                                                                                                                                                                                                                                                                                                               
     int  type;   //类型 :静止、移动
     int  state;   //状态:正常、破碎
     float stateTime;   //状态持续时间
     public  Platform ( int  type, float x, float y) {
         super (x, y, PLATFORM_WIDTH, PLATFORM_HEIGHT);
         this .type = type;
         this .state = PLATFORM_STATE_NORMAL;  //正常状态
         this .stateTime =  0 ;
         //若为移动类型,赋值移动速度
         if  (type == PLATFORM_TYPE_MOVING) {
             velocity.x = PLATFORM_VELOCITY;
         }
     }
                                                                                                                                                                                                                                                                                                               
     /**刷新**/
     public  void  update (float deltaTime) {
         //移动跳板
         if  (type == PLATFORM_TYPE_MOVING) {
             //跳板移动位置
             position.add(velocity.x * deltaTime,  0 );
             bounds.x = position.x - PLATFORM_WIDTH /  2 ;
             bounds.y = position.y - PLATFORM_HEIGHT /  2 ;
             //左边界限制
             if  (position.x < PLATFORM_WIDTH /  2 ) {
                 velocity.x = -velocity.x;
                 position.x = PLATFORM_WIDTH /  2 ;
             }
             //右边界限制
             if  (position.x > World.WORLD_WIDTH - PLATFORM_WIDTH /  2 ) {
                 velocity.x = -velocity.x;
                 position.x = World.WORLD_WIDTH - PLATFORM_WIDTH /  2 ;
             }
         }
         //状态持续时间
         stateTime += deltaTime;
     }
     /**破碎**/
     public  void  pulverize () {
         state = PLATFORM_STATE_PULVERIZING;
         stateTime =  0 ;
         velocity.x =  0 ;
     }
}


5.Spring类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package  com.zhf.mylibgdx;
/**
  * 弹簧
  * @author ZHF
  *
  */
public  class  Spring  extends  GameObject {
     //宽和高
     public  static  float  SPRING_WIDTH =  0 .3f;
     public  static  float  SPRING_HEIGHT =  0 .3f;
     public  Spring( float  x,  float  y) {
         super (x, y, SPRING_WIDTH, SPRING_HEIGHT);
     }
}


6.Squirrel类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package  com.zhf.mylibgdx;
/**
  * 松鼠
  * @author ZHF
  *
  */
public  class  Squirrel  extends  DynamicGameObject {
     //宽和高
     public  static  final  float  SQUIRREL_WIDTH =  1 ;
     public  static  final  float  SQUIRREL_HEIGHT =  0 .6f;
     //速度
     public  static  final  float  SQUIRREL_VELOCITY = 3f;
                                                                                                                                                                                                                                                                                 
     float  stateTime =  0 ;   //状态持续时间
     public  Squirrel ( float  x,  float  y) {
         super (x, y, SQUIRREL_WIDTH, SQUIRREL_HEIGHT);
         //为松鼠x轴方向赋值
         velocity.set(SQUIRREL_VELOCITY,  0 );
     }
                                                                                                                                                                                                                                                                                 
     /**刷新**/
     public  void  update ( float  deltaTime) {
         //松鼠移动位置
         position.add(velocity.x * deltaTime, velocity.y * deltaTime);
         bounds.x = position.x - SQUIRREL_WIDTH /  2 ;
         bounds.y = position.y - SQUIRREL_HEIGHT /  2 ;
         //左边界限制
         if  (position.x < SQUIRREL_WIDTH /  2 ) {
             position.x = SQUIRREL_WIDTH /  2 ;
             velocity.x = SQUIRREL_VELOCITY;
         }
         //右边界限制
         if  (position.x > World.WORLD_WIDTH - SQUIRREL_WIDTH /  2 ) {
             position.x = World.WORLD_WIDTH - SQUIRREL_WIDTH /  2 ;
             velocity.x = -SQUIRREL_VELOCITY;
         }
         //状态持续时间
         stateTime += deltaTime;
     }
}


以上就是游戏中六个物体类的代码,都十分的相似,代码里都注释了,这里不再一一讲解,可能有些变量没有完全写出,大家还是以源码为主,接下来我们要干的工作就是如何在游戏界面里显示出跳板?

首先,在World类中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package  com.zhf.mylibgdx;
import  java.util.ArrayList;
import  java.util.List;
import  java.util.Random;
import  com.badlogic.gdx.math.Vector2;
/**
  * 统一管理世界中各个部分
  * @author ZHF
  *
  */
public  class  World {
     /**世界监听器接口**/
     public  interface  WorldListener {
         //跳跃
         public  void  jump ();
         //高跳
         public  void  highJump ();
         //碰撞
         public  void  hit ();
         //收集金币
         public  void  coin ();
     }
                                                                                                                                                                                                              
     //宽和高
     public  static  final  float  WORLD_WIDTH =  10 ;
     public  static  final  float  WORLD_HEIGHT =  15  20 ;
     //状态
     public  static  final  int  WORLD_STATE_RUNNING =  0 ;   //运行
     public  static  final  int  WORLD_STATE_NEXT_LEVEL =  1 ;   //下一关
     public  static  final  int  WORLD_STATE_GAME_OVER =  2 ;   //游戏结束
     //世界监听器
     public   WorldListener listener;
                                                                                                                                                                                                              
     //重力
     public  static  final  Vector2 gravity =  new  Vector2( 0 , - 12 );
     //随机数
     public  Random rand;
     //游戏中物体
     public  final  List<Platform> platforms;   //跳板
                                                                                                                                                                                                              
                                                                                                                                                                                                              
                                                                                                                                                                                                              
     public  World(WorldListener listener) {
         this .listener = listener;
         this .platforms =  new  ArrayList<Platform>();
                                                                                                                                                                                                                  
         rand =  new  Random();
         generateLevel();
     }
                                                                                                                                                                                                              
     /**生成关卡中除了Bob外所有的物体**/
     private  void  generateLevel() {
         float  y = Platform.PLATFORM_HEIGHT /  2 ;
         float  maxJumpHeight = Bob.BOB_JUMP_VELOCITY * Bob.BOB_JUMP_VELOCITY / ( 2  * -gravity.y);
                                                                                                                                                                                                                  
         while  (y < WORLD_HEIGHT - WORLD_WIDTH /  2 ) {
             int  type = rand.nextFloat() >  0 .8f ? Platform.PLATFORM_TYPE_MOVING : Platform.PLATFORM_TYPE_STATIC;
             float  x = rand.nextFloat() * (WORLD_WIDTH - Platform.PLATFORM_WIDTH) + Platform.PLATFORM_WIDTH /  2 ;
             Platform platform =  new  Platform(type, x, y);
             platforms.add(platform);
                                                                                                                                                                                                                      
             y += (maxJumpHeight -  0 .5f);
             y -= rand.nextFloat() * (maxJumpHeight /  3 );
         }
     }
     /**刷新界面**/
     public  void  update( float  deltaTime,  float  accelX) {
         updatePlatforms(deltaTime);
     }
     /**刷新跳板**/
     private  void  updatePlatforms( float  deltaTime) {
         int  len = platforms.size();
         for  ( int  i =  0 ; i < len; i++) {
             Platform platform = platforms.get(i);
             //取出集合中的跳板对象,调用其自身的刷新方法
             platform.update(deltaTime);
             //若状态为破碎状态,将该跳板对象移除出去
             if  (platform.state == Platform.PLATFORM_STATE_PULVERIZING && platform.stateTime > Platform.PLATFORM_PULVERIZE_TIME) {
                 platforms.remove(platform);
                 len = platforms.size();
             }
         }
     }
}


分析:这里我们还是在上一讲的代码的基础上,增加了platform对象及其实例化,还有与其相关的刷新方法。最重要的是在World的构造方法中,初始化跳板集合,并且调用了 generateLevel()方法来生成关卡中除了Bob外所有的物体。

   游戏中物体的创建主要是围绕Platform来生成的。在While循环内,通过不断增加y坐标的值,使用随机数rand 和 物体的内置属性来生成不同的游戏物体。比如,对于Playform 有移动和不移动两种,同时它内置的宽度为2(每单位为32个像素),高度为0.5,结合rand就能达到随机生成Playform的效果。


其次就是WorldRenderer类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package  com.zhf.mylibgdx;
import  com.badlogic.gdx.graphics.OrthographicCamera;
import  com.badlogic.gdx.graphics.g2d.SpriteBatch;
import  com.badlogic.gdx.graphics.g2d.TextureRegion;
/**
  * 用来把每个对象关联相应的图片资源,同时控制相机,实现动画。
  * @author ZHF
  *
  */
public  class  WorldRenderer {
     //宽和高
     static  final  float  FRUSTUM_WIDTH =  10 ;
     static  final  float  FRUSTUM_HEIGHT =  15 ;
                                                                                                                                       
     World world;   //世界
     OrthographicCamera cam;   //相机
     SpriteBatch batch;   //用于绘画
     TextureRegion background;   //背景图片
                                                                                                                                       
     public  WorldRenderer(SpriteBatch batch, World world) {
         this .world = world;
         //OrthographicCamera 被定义成 宽度为10,高度为15,同样的也把相机对准中心点。
         this .cam =  new  OrthographicCamera(FRUSTUM_WIDTH, FRUSTUM_HEIGHT);
         //它指定了和屏幕一样大小的 OrthographicCamera ,并把相机对准屏幕的中心。
         this .cam.position.set(FRUSTUM_WIDTH /  2 , FRUSTUM_HEIGHT /  2 0 );
         this .batch = batch;
     }
                                                                                                                                       
     /**渲染**/
     public  void  render () {
         cam.update();
         //它的作用都是通过把映射矩阵绑定给SpritBatch,告诉SpritBatch怎么去绘制图形
         batch.setProjectionMatrix(cam.combined);
         //渲染背景
         renderBackground();
         //渲染游戏中各种元素(Bob,跳板,松鼠,弹簧。。)下一讲中会具体讲到
         renderObjects();
     }
                                                                                                                                       
     /**渲染游戏中各种物体(Bob,跳板,松鼠,弹簧,城堡,金币)**/
     private  void  renderObjects() {
         batch.enableBlending();
         batch.begin();
         //绘制跳板
         renderPlatforms();
                                                                                                                                           
         batch.end();
     }
     /**渲染背景**/
     public  void  renderBackground () {
         batch.disableBlending();
         batch.begin();
         batch.draw(Assets.backgroundRegion, cam.position.x - FRUSTUM_WIDTH /  2 , cam.position.y - FRUSTUM_HEIGHT /  2 , FRUSTUM_WIDTH,
             FRUSTUM_HEIGHT);
         batch.end();
     }
                                                                                                                                       
     /**渲染跳板**/
     private  void  renderPlatforms () {
         int  len = world.platforms.size();
         for  ( int  i =  0 ; i < len; i++) {
             Platform platform = world.platforms.get(i);
             TextureRegion keyFrame = Assets.platform;
//          if (platform.state == Platform.PLATFORM_STATE_PULVERIZING) {
//              keyFrame = Assets.brakingPlatform.getKeyFrame(platform.stateTime, Animation.ANIMATION_NONLOOPING);
//          }
             batch.draw(keyFrame, platform.position.x -  1 , platform.position.y -  0 .25f,  2 0 .5f);
         }
     }
}

分析:

 1.在该类中,我们写了一个方法renderObjects()用于渲染游戏中各种物体(Bob,跳板,松鼠,弹簧,城堡,金币)

   2.渲染跳板renderPlatforms ()方法里我们取出集合中的跳板对象,对应加载资源,并将其绘制出来。


   最后,就是在Asset类中加载跳板资源

声明:

1
2
//游戏中各种物体
public  static  TextureRegion platform;   //跳板

实例化:

1
2
//游戏中各个物体
     platform =  new  TextureRegion(items,  64 160 64 16 );   //跳板


   运行一下,效果图:(每次运行起来跳板的位置都是随机的)


 目前游戏还是没有主人公哦,在下一讲中,我们会加上主人公,同时显示出其他游戏物体,当然还有最重要的游戏碰撞检测,以及场景的移动。


源码下载:http://down.51cto.com/data/896982








     本文转自zhf651555765 51CTO博客,原文链接:http://blog.51cto.com/smallwoniu/1263869,如需转载请自行联系原作者







相关文章
|
3月前
|
图形学 数据可视化 开发者
超实用Unity Shader Graph教程:从零开始打造令人惊叹的游戏视觉特效,让你的作品瞬间高大上,附带示例代码与详细步骤解析!
【8月更文挑战第31天】Unity Shader Graph 是 Unity 引擎中的强大工具,通过可视化编程帮助开发者轻松创建复杂且炫酷的视觉效果。本文将指导你使用 Shader Graph 实现三种效果:彩虹色渐变着色器、动态光效和水波纹效果。首先确保安装最新版 Unity 并启用 Shader Graph。创建新材质和着色器图谱后,利用节点库中的预定义节点,在编辑区连接节点定义着色器行为。
244 0
|
5月前
|
图形学
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(上)
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)
215 2
|
5月前
|
图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版6(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版6(附带项目源码)
70 1
|
5月前
|
图形学
【用unity实现100个游戏之17】从零开始制作一个类幸存者肉鸽(Roguelike)游戏5(附项目源码)(上)
【用unity实现100个游戏之17】从零开始制作一个类幸存者肉鸽(Roguelike)游戏5(附项目源码)
73 0
|
5月前
|
图形学
【用unity实现100个游戏之17】从零开始制作一个类幸存者肉鸽(Roguelike)游戏5(附项目源码)(下)
【用unity实现100个游戏之17】从零开始制作一个类幸存者肉鸽(Roguelike)游戏5(附项目源码)
86 0
|
5月前
|
存储 JSON 关系型数据库
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版13(完结,附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版13(完结,附带项目源码)
107 0
|
5月前
|
图形学
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(下)
【制作100个unity游戏之29】使用unity复刻经典游戏《愤怒的小鸟》(完结,附带项目源码)(下)
83 0
|
5月前
|
存储 图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版11(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版11(附带项目源码)
90 0
|
5月前
|
图形学 容器
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版9(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版9(附带项目源码)
44 0
|
5月前
|
图形学
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版7(附带项目源码)
【制作100个unity游戏之27】使用unity复刻经典游戏《植物大战僵尸》,制作属于自己的植物大战僵尸随机版和杂交版7(附带项目源码)
45 0