libgdx使用android控件,libgdx游戏引擎开发笔记(七)SuperJumper游戏例子的讲解(篇一)---- 游戏框架的搭建...

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

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

1.游戏介绍:

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

上个图:

c971214d8c6e22ff85759bf2971f90dc.png    8683f885d35a61da702cd4325719f5aa.png

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

f4a38a9a0e595f2a1a6801f69fc9397a.png

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

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

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

2.项目创建

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

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

6688d34084481f3a36466a36e3e48bbc.png

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

7763a657de335833bcb414c0b1bd8860.png

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

94534ade976e1086f058ef3d86f8cbda.png

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

fc44d9c60e231fd2b145f701521a141a.png

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

fe2e87bfba7bbefc87d987bf4ac647ff.png

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

8fde90b5e39273b301e6248c373db198.png

3.游戏代码框架搭建

SuperJumper类:启动入口

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类:

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类: 各种资源的读取

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类:主菜单界面

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类:

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;

}

}

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

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

5c4c4f9ac64e7d19431c50d5022a4fd1.png

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

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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值