libgdx游戏引擎开发笔记(七)SuperJumper游戏例子的讲解(篇一)---- 游戏框架的搭建

简介:

   最近几天没有更新博客,是因为我这两天在学习Libgdx的一个游戏源码,毕竟再怎么研究libgdx游戏引擎的原理,如果不去实践一下,掌握起来还是比较费劲的。(我个人对于一个新的东西的掌握,都是先从HelloWorld开始,然后开始写一些例子,从各个方位去了解他,其中自然有很多底层原理性的东西,不懂是肯定的!但我不会去深究它,因为这样太浪费时间,而且很容易走偏,我会在学完基本上如何使用和了解了它的大体以后,再去慢慢深入其原理,这样的一来一回,学习效率会倍增!)


   好了不多说了,在以后的几篇博客里我会逐步分版本的讲解一下SuperJumper这款游戏,让大家(当然还有我,毕竟我也是初学者嘛! 嘿嘿!)逐渐掌握libgdx这款游戏引擎(框架)的使用方法。


1.游戏介绍:

  这是一款跳跃型的游戏,主人物会一直往上跳,我们只需控制左右移动让其踩在适当的跳台上即可继续的往上跳,最终加到的金币越多, 到达城堡就胜利了。(貌似有点无聊哈,不过我们是来学习它的框架和使用方法的,相信大家学习完之后,自己也能做一个更好玩的游戏哦!)

上个图:

115016556.png    115018651.png

这里游戏源码我们可以从官网提供的SVN上下载(http://libgdx.googlecode.com/svn),我试过了可以的!连接成功后直接检出即可

115629305.png

  当然,这里蜗牛已经将superjumper检出,同时也为大家配置好环境,直接使用即可。下载地址:http://down.51cto.com/data/893457


  这里,我想说一下,因为本人也是初学者,第一次看到源码后不知道从何下手,所以每讲我会将每个版本的源码放出来,方便初学者循序渐进的学习它,相信这样的效率会更高!

   

  好了不多说了,我们一步一步的开始吧!


2.项目创建

  2.1为了方便测试起见,我们整个项目都在desktop上开发运行,大家也可以在android模拟器上试试,真机上就不行了(因为这款游戏需要左右按键的哦)


   步骤:1.点击libgdx文件夹中的gdx-setup-ui.jar

121921403.png


           2.在弹出的窗体中我们来新建项目:

122459777.png

   

      3.下一步,点击launch即可,

122701914.png

   

   4.这样我们的项目已经建立成功,接下来就是找到刚才我们建立项目的文件目录下,用eclipse将其导入到工程下。

122918595.png

导入成功!(第一个:源代码; 第二个:Android版本;第三个: 桌面版本)

123109994.png

 

   ok! 项目已经创建成功!现在我们点击desktop版本右击运行 Java Application 进行测试,弹出一个窗体说明框架正常!以后我们的代码都在第一个MySuperJumper中编写,在desktop中进行测试!!

132819376.png


3.游戏代码框架搭建

   SuperJumper类:启动入口

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
package  com.zhf.mylibgdx;
import  com.badlogic.gdx.Game;
import  com.badlogic.gdx.graphics.FPSLogger;
/**
  * 启动入口
  * @author ZHF
  *
  */
public  class  MySuperJumper  extends  Game{
     boolean  firstTimeCreate =  true ;   //是否是第一次创建
     FPSLogger fps;   //帧频
     @Override
     public  void  create () {
         Settings.load();
         Assets.load();
         setScreen( new  MainMenuScreen( this ));
         fps =  new  FPSLogger();
     }
                                                                                                                                                                                                                                                                                                                           
     @Override
     public  void  render() {
         super .render();
         fps.log();
     }
                                                                                                                                                                                                                                                                                                                           
     @Override
     public  void  dispose () {
         super .dispose();
         getScreen().dispose();   //销毁
     }
}


   Settings类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package  com.zhf.mylibgdx;
/**
  * 设置类:三个方法: 1.load()读取声音开关和最高分.  2.save()保存配置     3.addScore()最高分排行榜,对数组赋值。
  * @author ZHF
  *
  */
public  class  Settings {
     //记录声音开起与关闭
     public  static  boolean  soundEnabled =  true ;
     /**加载配置文件**/
     public  static  void  load (){
                                                                                                                                                                                                                                                                                                    
     }
}


   Assets类: 各种资源的读取

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
package  com.zhf.mylibgdx;
import  com.badlogic.gdx.Gdx;
import  com.badlogic.gdx.audio.Music;
import  com.badlogic.gdx.audio.Sound;
import  com.badlogic.gdx.graphics.Texture;
import  com.badlogic.gdx.graphics.g2d.TextureRegion;
/**
  * 各种资源的读取(这里TextureRegion的用法可以学习,还有Music类,Sound类的使用方法)
  * @author ZHF
  *
  */
public  class  Assets {
                                                                                                                                                                                                                                                             
     public  static  Texture background;
     public  static  TextureRegion backgroundRegion;   //背景
                                                                                                                                                                                                                                                             
     public  static  Texture items;     //一系列的图片
     public  static  TextureRegion mainMenu;    //主菜单
     public  static  TextureRegion logo;
     public  static  TextureRegion soundOn;   //声音按钮
     public  static  TextureRegion soundOff;
                                                                                                                                                                                                                                                             
     public  static  Sound clickSound;  //按下音效
     public  static  Music music;   //背景音乐
                                                                                                                                                                                                                                                             
     /**通过资源名获取资源**/
     public  static  Texture loadTexture (String file) {
         return  new  Texture(Gdx.files.internal(file));
     }
                                                                                                                                                                                                                                                             
     /**加载各种资源**/
     public  static  void  load () {
         //背景
          loadTexture( "data /background.png" );
         backgroundRegion =  new  TextureRegion(background,  0 0 320 480 );
         //主画面中的UI控件
         items = loadTexture( "data/items.png" );
         logo =  new  TextureRegion(items,  0 352 274 142 );
         mainMenu =  new  TextureRegion(items,  0 224 300 110 );
         soundOff =  new  TextureRegion(items,  0 0 64 64 );
         soundOn =  new  TextureRegion(items,  64 0 64 64 );
         //点击音效
         clickSound = Gdx.audio.newSound(Gdx.files.internal( "data/click.ogg" ));
         //背景音乐
         music = Gdx.audio.newMusic(Gdx.files.internal( "data/music.mp3" ));
         music.setLooping( true );  //循环
         music.setVolume( 0 .5f);   //大小
         if  (Settings.soundEnabled) music.play();
     }
                                                                                                                                                                                                                                                             
     /**播放游戏音效**/
     public  static  void  playSound (Sound sound) {
         if  (Settings.soundEnabled) sound.play( 1 );
     }
}


   MainMenuScreen类:主菜单界面

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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package  com.zhf.mylibgdx;
import  com.badlogic.gdx.Game;
import  com.badlogic.gdx.Gdx;
import  com.badlogic.gdx.Screen;
import  com.badlogic.gdx.graphics.GL10;
import  com.badlogic.gdx.graphics.GLCommon;
import  com.badlogic.gdx.graphics.OrthographicCamera;
import  com.badlogic.gdx.graphics.g2d.SpriteBatch;
import  com.badlogic.gdx.math.Rectangle;
import  com.badlogic.gdx.math.Vector3;
/**
  * 主菜单界面
  * @author ZHF
  *
  */
public  class  MainMenuScreen  implements  Screen{
     Game game;
                                                                                                                                                                                                                           
     OrthographicCamera guiCam;
     SpriteBatch batch;
                                                                                                                                                                                                                           
     Rectangle soundBounds;
     Rectangle playBounds;
     Rectangle highscoresBounds;
     Rectangle helpBounds;
                                                                                                                                                                                                                           
     Vector3 touchPoint;
                                                                                                                                                                                                                           
     public  MainMenuScreen(Game game) {
         // TODO Auto-generated constructor stub
         //得到Game对象,以便能调用Game切换到下一个画面,目前无用
         this .game = game;
         //相机,大小是320*480像素,这里作者把像素都按屏幕分辨率320*480写死了,等下会介绍如何适配到不同像素
         guiCam =  new  OrthographicCamera( 320 480 );
         //相机位置
         guiCam.position.set( 320  2 480  2 0 );
         //渲染器
         batch =  new  SpriteBatch();
         //喇叭图标
         soundBounds =  new  Rectangle( 0 0 64 64 );
         playBounds =  new  Rectangle( 160  150 200  18 300 36 );
         highscoresBounds =  new  Rectangle( 160  150 200  18 300 36 );
         helpBounds =  new  Rectangle( 160  150 200  18  36 300 36 );
         //点击点向量(就是用于记录用户点击的位置)
         touchPoint =  new  Vector3();
                                                                                                                                                                                                                                
                                                                                                                                                                                                                                
     }
     /**刷新**/
     public  void  update ( float  deltaTime) {
         //如果屏幕有被点击
         if  (Gdx.input.justTouched()) {
               //此句是难点,重点分析
              //touchPoint.set(Gdx.input.getX(), Gdx.input.getY(), 0)是把得到的点击坐标弄成touchPoint向量
              //unproject函数查看源码,得出两部分信息,
              //第一,把得到的点击坐标,由左上为(0,0)的坐标系--》左下为(0,0)的坐标系。
              //(呃,还是详细说下吧,真实的设备的坐标起点都是左上角,而本游戏的矩形框是以左下角为起点弄的坐标)
              //第二调用了vec.prj(invProjectionView);这么一个语句
              //invProjectionView这个参数的意思是结合了“视图”和“投影”矩阵的逆矩阵,vec就是touchPoint向量
              //大家其实可以结合刚才draw中重点将的语句来理解,
              //理想像素(320*480)---经过矩阵(“视图”和“投影”矩阵)----实际像素(x*x)
              //实际像素(x*x)-----经过矩阵(“视图”和“投影”逆矩阵)----理想像素(320*480)
             //这样拉伸和压缩的变换以后便能适应大多数设备
             guiCam.unproject(touchPoint.set(Gdx.input.getX(), Gdx.input.getY(),  0 ));
             //调用辅助类OverlapTester,检测已经转换成理想像素的touchPoint向量是否在理想的playBounds矩形框内
             if  (OverlapTester.pointInRectangle(playBounds, touchPoint.x, touchPoint.y)) {
                 //播放点击音效
                 Assets.playSound(Assets.clickSound);
                 //game.setScreen(new GameScreen(game));
                  return ;
             }
             if  (OverlapTester.pointInRectangle(highscoresBounds, touchPoint.x, touchPoint.y)) {
                 Assets.playSound(Assets.clickSound);
                 //game.setScreen(new HighscoresScreen(game));
                 return ;
             }
             if  (OverlapTester.pointInRectangle(helpBounds, touchPoint.x, touchPoint.y)) {
                 Assets.playSound(Assets.clickSound);
                 //game.setScreen(new HelpScreen(game));
                 return ;
             }
             if  (OverlapTester.pointInRectangle(soundBounds, touchPoint.x, touchPoint.y)) {
                 Assets.playSound(Assets.clickSound);
                 //依据Settings类中的成员变量决定声音的开关
                 Settings.soundEnabled = !Settings.soundEnabled;
                 if  (Settings.soundEnabled)
                     Assets.music.play();
                 else
                     Assets.music.pause();
             }
         }
     }
     public  void  draw ( float  deltaTime) {
         //清空画面
         GLCommon gl = Gdx.gl;
         gl.glClearColor( 1 0 0 1 );
         gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
         //更新照相机位置(此处多余,因为这个照相机位置压根没动过)
         guiCam.update();
         //此句是难点,详细分析
         //guiCam.combined参数是一个矩阵,兼具“投影”和“视图”矩阵的功能
         //“投影”矩阵的作用是改变照相机的大小
         //“视图”矩阵的作用是改变照相机的位置
         //setProjectionMatrix函数的作用是把矩阵送给batcher计算
         //这整个语句可以理解为,batcher这个本来是320*480像素的渲染范围的渲染器,
         //在经过矩阵的计算后可以batcher的渲染范围可以适应当前像素
         batch.setProjectionMatrix(guiCam.combined);
         //关闭混合(这个貌似是作者为了节约GPU多加的一句,只在渲染背景的时候加)
         batch.disableBlending();
         batch.begin();
         batch.draw(Assets.backgroundRegion,  0 0 320 480 );
         batch.end();
         //关闭混合
         batch.enableBlending();
         batch.begin();
                                                                                                                                                                                                                               
         batch.draw(Assets.logo,  160  274  2 480  10  142 274 142 );
         //这里注意是将3个选项(“play”“HighscoresScreen”"help")只用一个图片表达
         batch.draw(Assets.mainMenu,  10 200  110  2 300 110 );
         batch.draw(Settings.soundEnabled ? Assets.soundOn : Assets.soundOff,  0 0 64 64 );
         batch.end();
     }
                                                                                                                                                                                                                           
     @Override
     public  void  render( float  delta) {
         //这里系统会开一个线程不断地调用此方法的
         update(delta);
         draw(delta);
     }
     @Override
     public  void  resize( int  width,  int  height) {
         // TODO Auto-generated method stub
     }
     @Override
     public  void  show() {
         // TODO Auto-generated method stub
     }
     @Override
     public  void  hide() {
         // TODO Auto-generated method stub
     }
     @Override
     public  void  pause() {
         // TODO Auto-generated method stub
     }
     @Override
     public  void  resume() {
         // TODO Auto-generated method stub
     }
     @Override
     public  void  dispose() {
         // TODO Auto-generated method stub
     }
}


   OverlapTester类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package  com.zhf.mylibgdx;
import  com.badlogic.gdx.math.Rectangle;
/**
  * 工具类:检测各种碰撞
  * @author ZHF
  *
  */
public  class  OverlapTester {
     /**检测输入的X,Y是否在输入的矩形框r内**/
     public  static  boolean  pointInRectangle(Rectangle r,  float  x,  float  y) {
         return  r.x <= x && r.x + r.width >= x && r.y <= y
                 && r.y + r.height >= y;
     }
}


   恩,注解都写得很清楚,我想可能还是有初学者还是不太明白其中的细节,其实我有的也不太懂,还是第一段的话,不影响大家整体思路的情况下,我们继续前进,有些东西到后面你就会有整体的把握!


     经过上面的代码框架的搭建,运行起来的的效果:

142724656.png

   点击“play”“HighscoresScreen”"help"会有音效,点击喇叭会关闭和开启背景音乐


 ok ! 第一讲就到这里! 下一讲我们继续学习一下,屏幕之间的切换!


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




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







相关文章
|
4月前
|
开发工具 图形学 计算机视觉
微信小游戏制作工具跟其它游戏引擎有什么区别?该怎么选?
微信小游戏制作工具跟其它游戏引擎有什么区别?该怎么选?
68 0
|
7月前
|
编解码 芯片
实战贴:开源GUI STemWin在小熊派上的移植(显示很漂亮、很细腻,棒!)
实战贴:开源GUI STemWin在小熊派上的移植(显示很漂亮、很细腻,棒!)
280 2
|
11月前
|
开发工具 图形学 计算机视觉
微信小游戏制作工具与其它游戏引擎的区别
这是不少人在正式上手学习做游戏之前的疑问,就跟我们购买某个商品是一样的,那么多同类型的商品,到底我应该买哪个呢?答案就是选择最适合你的那个。 这个问题表面上来看问的是应该选择哪个游戏开发工具,但实际上这个问题的答案却在另一个问题之中,你到底想要做一个什么样的游戏,你的目的是什么?这个才是真正的问题。
266 0
|
编解码 缓存 开发工具
Unity跨平台UI解决方案:可能是最全的FairyGUI系列教程-第三天
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
530 0
|
API 图形学 Android开发
Unity跨平台UI解决方案:可能是最全的FairyGUI系列教程-第七天
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
917 0
|
XML JSON 缓存
Unity跨平台UI解决方案:可能是最全的FairyGUI系列教程-第四天
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
1195 0
|
XML 前端开发 图形学
Unity跨平台UI解决方案:可能是最全的FairyGUI系列教程-第五天
众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!
389 0
|
编解码 定位技术 图形学
Unity 之 手把手教你实现自己Unity2D游戏寻路逻辑
还在看别人的寻路逻辑?保姆级教程,一步步教你实现网格寻路逻辑。
658 0
Unity 之 手把手教你实现自己Unity2D游戏寻路逻辑