(原文:http://www.libgdx.cn/topic/49/5-%E4%BD%BF%E7%94%A8libgdx%E8%AE%BE%E8%AE%A1%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E6%B8%B8%E6%88%8F-%E9%9B%A8%E6%BB%B4

在深入研究Libgdx提供的API之前,我们先来创建一个简单的游戏来感受一下libgdx各个功能。这里将简单的对一些功能做介绍。

使用的技术:

  • 文件访问

  • 清除屏幕

  • 渲染图片

  • 使用相机

  • 基本的输入

  • 播放音效

项目设置

首先创建一个libgdx项目,移步到这里

  • 应用名称(Application name):drop

  • 包名(Package name):cn.libgdx.drop

  • 游戏类(Game class):Drop

生成项目之后,将其导入到eclipse中(需要记住,是Gradle项目)。

游戏设计思路

游戏思路很简单:

  • 使用一个桶雨滴

  • 桶在屏幕底部

  • 雨滴随机从屏幕顶部下载,加速下落

  • 玩家可以水平拖动桶

  • 游戏没有结束

Assets文件

点击下载资源文件

我们需要一些图片和音效来让游戏变得更好。对于图像来说我们需要设置分辨率为800*480像素(在Android中要设置为横向(landscape ))。如果设备没有这个分辨率,我们需要设置适用屏幕。

为了让资源文件在游戏中可用,我们必须将资源文件放到Android项目的assets文件夹下。一共四个文件:drop.wav,rain.mp3,droplet.png和bucket.png。把他们放到drop-android/assets/文件夹下。

配置启动类

准备完之前的配置后,我们需要修改desktop项目的启动类。打开drop-desktop项目下的DesktopLauncher.java文件。我们需要设置窗口为800*480,设置窗口标题为“雨滴”。代码如下:

package cn.libgdx.drop.desktop;

import com.badlogic.gdx.backends.lwjgl.LwjglApplication;

import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration;

import cn.libgdx.drop.Drop;

public class DesktopLauncher {

public static void main (String[] arg) {

LwjglApplicationConfiguration config = new LwjglApplicationConfiguration();

config.title="雨滴";

config.width=800;

config.height=480;

new LwjglApplication(new Drop(), config);

}

}

找到Android项目(即drop-android),需要设置应用的屏幕方向,所以需要修改项目根目录AndroidManifest.xml文件,设置android:screenOrientation="landscape"。代码如下:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;

package="cn.libgdx.drop.android"

android:versionCode="1"

android:versionName=&quot;1.0&quot; >

<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" />

<application

android:allowBackup="true"

android:icon="@drawable/ic_launcher"

android:label="@string/app_name"

android:theme="@style/GdxTheme" >

<activity

android:name=&quot;cn.libgdx.drop.android.AndroidLauncher&quot;

android:label="@string/app_name"

android:screenOrientation="landscape"

android:configChanges="keyboard|keyboardHidden|orientation|screenSize">

<intent-filter>

<action android:name=&quot;android.intent.action.MAIN&quot; />

<category android:name=&quot;android.intent.category.LAUNCHER&quot; />

</intent-filter>

</activity>

</application>

</manifest>

其实是用GDX-setup生成的项目android:screenOrientation默认值为landscape,所以无需改动。

接下来需要禁用加速度计和罗盘,这需要改动Android项目AndroidLauncher.java文件,代码如下:

package cn.libgdx.drop.android;

import android.os.Bundle;

import com.badlogic.gdx.Gdx;

import com.badlogic.gdx.backends.android.AndroidApplication;

import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;

import cn.libgdx.drop.Drop;

public class AndroidLauncher extends AndroidApplication {

@Override

protected void onCreate (Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();

config.useAccelerometer=false;

config.useCompass=false;

initialize(new Drop(), config);

}

}

我们不能定义Activity的分辨率,这个是由Android操作系统来定。就像我们之前定义的,设置所有平台分辨率为800*480。

开始编写代码

现在将代码分成几个部分来分析,为了保持项目的可移植性,我们需要将代码写到core项目下。

载入Assets

我们第一个任务就是载入assets文件和保存参数。Assets通常在ApplicationListener.create()方法中载入,代码如下:

package cn.libgdx.drop;

import com.badlogic.gdx.ApplicationAdapter;

import com.badlogic.gdx.Gdx;

import com.badlogic.gdx.audio.Music;

import com.badlogic.gdx.audio.Sound;

import com.badlogic.gdx.graphics.GL20http://com.badlogic.gdx.graphics.GL200;

import com.badlogic.gdx.graphics.Texturehttp://com.badlogic.gdx.graphics.Texturee;

import com.badlogic.gdx.graphics.g2d.SpriteBatchhttp://com.badlogic.gdx.graphics.g2d.SpriteBatchh;

public class Drop extends ApplicationAdapter {

private Texture dropImage;

private Texture bucketImage;

private Sound dropSound;

private Music rainMusic;

@Override

public void create () {

//将资源载入到GPU中。

dropImage=new Texture(Gdx.files.internal("droplet.png"));

bucketImage=new Texture(Gdx.files.internal("bucket.png"));

//载入雨滴音效和下雨背景音乐

dropSound=Gdx.audio.newSound(Gdx.files.internal("drop.wav"));

rainMusic=Gdx.audio.newMusic(Gdx.files.internal("rain.mp3"));

//开始播放背景音乐

rainMusic.setLooping(true);

rainMusic.play();

}

@Override

public void render () {

}

}

在create()方法中前两行载入雨滴和桶。Texture是指将图像载入并保存到缓存。Texture通过一个文件句柄(FileHandle)。FileHandle通过Gdx.files获取。这里有不同的文件,如果是调用Android下assets文件夹下的资源,使用internal。

接下来是载入音效和背景音乐。libgdx分音效和音乐,音效是保存到内存中,音乐是从保存的地方直接载入的音乐。音乐文件一般比较大不能全部载入内存。如果声音低于10秒,最好使用音效;如果超过10秒,就使用音乐。

载入音效通过Gdx.audio.newSound()方法,载入音乐使用Gdx.audio.newMusic()方法。两种方法都需要传递一个文件句柄(FileHandle),就行上面的Texture。

接下来就是播放音乐并且设置循环。如果你这是运行程序,会听到下雨声。

Camera和SpriteBatch

接下来需要创建相机(camera)和SpriteBatch。我们使用相机的目的是在所有的平台都使用800*480分辨率,无论它的真实屏幕的大小。SpriteBatch是绘制2D图像的特殊类,跟texture差不多。

我们添加两个变量到类中,如下:

private OrthographicCamera camera;

private SpriteBatch batch;

在create()方法中添加如下语句,创建camera:

camera = new OrthographicCamera();

camera.setToOrtho(false, 800, 480);

这将确保camera总是显示800*480的范围。可以视作一个虚拟窗口。这样可以让应用可移植性增强。

接下来,在create()方法中创建SpriteBatch:

batch=new SpriteBatch();

添加桶

最后添加桶和雨滴,它们需要以下的条件:

  • 桶和雨滴在800*480中需要一个位置信息。

  • 桶和雨滴需要宽和高。

  • Texture

为了展现桶和雨滴,我们需要保存它们的位置和大小。在Libgdx中可以通过Rectangle实现。代码如下:

private Rectangle bucket;

在create()方法中我们需要实例化并且设置他的只。这里设置在屏幕底部,并且水平居中。代码如下:

bucket = new Rectangle();

bucket.x = 800 / 2 - 64 / 2;

bucket.y = 20;

bucket.width = 64;

bucket.height = 64;

需要注意的是,在libgdx中,坐标系原点在左下角。

渲染桶

接下来需要渲染我们的桶,首先需要设置屏幕的背景色,在render()方法中添加如下代码:

@Override

public void render () {

Gdx.gl.glClearColor(0, 0, 0.2f, 1)http://Gdx.gl.glClearColor(0.2f, 1);

Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)http://Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)

}

为了使用顶层的类,像Texture和SpriteBatch。首先需要调用清除屏幕并设置为蓝色。第一句的意思是设置清屏颜色,第二句才执行清屏操作。

接下来我们需要告诉camera确保它更新。接下来我们设置camera在每一帧中都更新。

接下来我们需要渲染桶。

batch.setProjectionMatrix(camera.combined);

batch.begin();

batch.draw(bucketImage, bucket.x, bucket.y);

batch.end();

第一句设置batch的坐标系统为相机,batch.end();会立即提交我们的绘制请求。

让桶可以移动

接下来我们控制桶。在设计游戏时,我们的设想是桶可以拖动。如果触摸屏幕或者鼠标按钮。我们想让桶进行水平移动。

if(Gdx.input.isTouched()) {

touchPos = new Vector3();

touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);

camera.unproject(touchPos);

bucket.x = touchPos.x - 64 / 2;

}

首先我们询问input模块通过Gdx.input.isTouched()来判断是否被触摸。接下来我们将触摸或者鼠标点击的卫士传递到camera的坐标系统。Gdx.input.getX()和Gdx.input.getY()方法用于返回当前触摸和鼠标的位置。为了转换当前坐标系统为camera的坐标系统我们需要使用camera.uproject()方法,调用这个方法需要一个Vector3,一个三维向量。我们创建这个向量,设置当前触摸或者鼠标的当前坐标,调用方法。

需要注意的是touchPos需要在类中声明,如果在if语句中,每次执行这个语句就会创建一个变量,这就会导致Android的垃圾处理产生异常。

touchPos是一个三维向量,你可能想知道为什么我们用2D界面需要一个三维向量。事实上,OrthographicCamera是一个三维相机(camera)。

让桶移动(键盘)

在桌面和浏览器环境我们同样需要获取键盘输入。让我们通过设置可以通过键盘来操作桶。

if(Gdx.input.isKeyPressed(Keys.LEFT)) bucket.x -= 200 * Gdx.graphics.getDeltaTime()http://Gdx.graphics.getDeltaTime()FT)) bucket.x -= 200 * Gdx.graphics.getDeltaTime();

if(Gdx.input.isKeyPressed(Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime()http://Gdx.graphics.getDeltaTime()GHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime();

当键盘按下时,Gdx.input.isKeyPressed()方法用来判断是否为指定按键。Gdx.graphics.getDeltaTime()返回一帧的时间http://Gdx.graphics.getDeltaTime()用来判断是否为指定按键。Gdx.graphics.getDeltaTime()返回一帧的时间。

我们同样需要设置桶不要越界:

if(bucket.x < 0) bucket.x = 0;

if(bucket.x > 800 - 64) bucket.x = 800 - 64;

添加雨滴

对于雨滴来说我们需要使用一个Rectangle数组,每个保存雨滴的位置和大小。让我们添加一个变量:

private Array<Rectangle> raindrops;

这个Array类是一个libgdx的工具类,用来代替java的ArrayList。后者将在很多情况下产生垃圾。Array尽量减少垃圾的产生。

我们同样需要记录上一次掉落的雨滴的时间,所以我们添加:

private long lastDropTime;

我们将存储纳秒,这就是我们为什么使用long。

下面方法用来随机产生雨点:

private void spawnRaindrop() {

Rectangle raindrop = new Rectangle();

raindrop.x = MathUtils.random(0, 800-64);

raindrop.y = 480;

raindrop.width = 64;

raindrop.height = 64;

raindrops.add(raindrop);

lastDropTime = TimeUtils.nanoTime();

}

我们需要在create()方法中进行实例化:

raindrops = new Array<Rectangle>();

spawnRaindrop();

接下来我们需要在render()方法中检测雨点的时间间隔,并生成新雨点:

if(TimeUtils.nanoTime() - lastDropTime > 1000000000) spawnRaindrop();

我们同样需要雨点移动,一下是代码:

Iterator<Rectangle> iter = raindrops.iterator();

while(iter.hasNext()) {

Rectangle raindrop = iter.next();

raindrop.y -= 200 * Gdx.graphics.getDeltaTime()http://Gdx.graphics.getDeltaTime()getDeltaTime();

if(raindrop.y + 64 < 0) iter.remove();

}

雨点需要被渲染,所以需要SpriteBatch来进行渲染:

batch.begin();

batch.draw(bucketImage, bucket.x, bucket.y);

for(Rectangle raindrop: raindrops) {

batch.draw(dropImage, raindrop.x, raindrop.y);

}

batch.end();

最后需要判断雨滴和桶是否重叠,如果重叠,就删除雨滴:

if(raindrop.overlaps(bucket)) {

dropSound.play();

iter.remove();

}

退出清理

最后需要清理。代码如下:

@Override

public void dispose() {

dropImage.dispose();

bucketImage.dispose();

dropSound.dispose();

rainMusic.dispose();

batch.dispose();

}

点击下载源码

www.libgdx.cn版权所有,如需转载,注明出处)

最新文章

  1. 在C#中该如何阻止虚方法的覆写
  2. 后缀名“.dll .obj .lib”和“ .so .o .a”文件的区别含义
  3. 含大量行的订单创建时候creditlimit校验最耗时间
  4. JS手动触发事件,转载
  5. layoutSubviews,setNeedsDisplay
  6. hdu 4965 Fast Matrix Calculation
  7. mysql sys table
  8. 移动金融APP分析
  9. zendserver 安装 ZendDebugger
  10. 应用git(SSH设置)
  11. Objective-c知识小结
  12. jacksonall的使用,解析json
  13. jq实现图像旋转木马:轮焦点+关于控制+自己主动旋转木马
  14. 坑爹的 Hardware Reserved Memory (查看内存等)
  15. 让人头疼的CSS兼容
  16. Juel 表达式使用
  17. ruby调用Office Jet引擎压缩access数据库
  18. knockoutjs复杂对象的可观察性
  19. An overview of gradient descent optimization algorithms
  20. 在Windows下为PHP安装redis扩展

热门文章

  1. 如何joomla修改版权信息
  2. Python中什么是变量Python中定义字符串
  3. CF | Alyona and Numbers
  4. Git 常用命令速查表(图文+表格)
  5. CRM客户关系管理系统(八)
  6. 剑指Offer——知识点储备-J2EE基础
  7. 给定一个实数数组,按序排列(从小到大),从数组从找出若干个数,使得这若干个数的和与M最为接近,描述一个算法,并给出算法的复杂度。
  8. Android必知必会-Android Studio下配置和使用Lambda
  9. Redis 4.0新功能介绍
  10. Android逆向工程