5、使用Libgdx设计一个简单的游戏------雨滴
在深入研究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="http://schemas.android.com/apk/res/android"
package="cn.libgdx.drop.android"
android:versionCode="1"
android:versionName="1.0" >
<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="cn.libgdx.drop.android.AndroidLauncher"
android:label="@string/app_name"
android:screenOrientation="landscape"
android:configChanges="keyboard|keyboardHidden|orientation|screenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</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版权所有,如需转载,注明出处)
5、使用Libgdx设计一个简单的游戏------雨滴的更多相关文章
- Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状)
Cocos2d-x-Lua 开发一个简单的游戏(记数字步进白色块状) 本篇博客来给大家介绍怎样使用Lua这门语言来开发一个简单的小游戏-记数字踩白块. 游戏的流程是这种:在界面上生成5个数1~5字并显 ...
- 设计一个简单的,低耗的能够区分红酒和白酒的感知器(sensor)
学习using weka in your javacode 主要学习两个部分的代码:1.过滤数据集 2 使用J48决策树进行分类.下面的例子没有对数据集进行分割,完全使用训练集作为测试集,所以不符合数 ...
- 用Python设计一个经典小游戏
这是关于Python的第9篇文章,介绍如何用Python设计一个经典小游戏:猜大小. 在这个游戏中,将用到前面我介绍过的所有内容:变量的使用.参数传递.函数设计.条件控制和循环等,做个整体的总结和复习 ...
- 180626-Spring之借助Redis设计一个简单访问计数器
文章链接:https://liuyueyi.github.io/hexblog/2018/06/26/180626-Spring之借助Redis设计一个简单访问计数器/ Spring之借助Redis设 ...
- Tomcat详解系列(1) - 如何设计一个简单的web容器
Tomcat - 如何设计一个简单的web容器 在学习Tomcat前,很多人先入为主的对它的认知是巨复杂的:所以第一步,在学习它之前,要打破这种观念,我们通过学习如何设计一个最基本的web容器来看它需 ...
- 【python免费代码】设计一个简单的学生信息管理系统
文章目录 前言 一.理解 二.部分截图展示 三.代码 四.总结 前言 设计一个简单的学生信息管理系统,实现以下功能(bug) : 录入学生信息,信息以文件方式存储 以学生学号或者学生姓名为条件查询该学 ...
- 一个简单的游戏开发框架(四.舞台Stage)
首先是StageManager类: class StageManager : public Singleton<StageManager> { friend class Singleton ...
- 怎样用HTML5 Canvas制作一个简单的游戏
原文连接: How To Make A Simple HTML5 Canvas Game 自从我制作了一些HTML5游戏(例如Crypt Run)后,我收到了很多建议,要求我写一篇关于怎样利用HTML ...
- JAVA课程设计——一个简单的教务人事管理系统
大三上学期期末总结,没错,上学期,写在下学期新学期开始,哈哈哈. 上学期学习了面向对象程序设计,课程设计的题目使用JAVA语言完成一个简单的教务人事管理系统,能够实现访问数据库的登录验证,分别按部门和 ...
随机推荐
- 深入浅出低功耗蓝牙(BLE)协议栈
深入浅出低功耗蓝牙(BLE)协议栈 BLE协议栈为什么要分层?怎么理解蓝牙"连接"?如果蓝牙协议只有ATT没有GATT会发生什么? 协议栈框架 一般而言,我们把某个协议的实现代码称 ...
- Linux shell爬虫实现树洞网自动回复Robot
奇怪的赞数 人生在世,不如意事十之八九,可与言者无二三人.幸好我们生在互联网时代,现实中找不到可以倾诉的人还可以在网络上寻找发情绪宣泄口,树洞这类产品就是提供一个让人在网络上匿名倾诉的平台. 我是偶然 ...
- MySQL 数学函数
MySQL 数学函数 所有的数学函数在发生错误的情况下,均返回 NULL. -元减.改变参数的符号 mysql> SELECT - 2; -> -2 注意,如果这个操作符被用于一个 BIG ...
- 硬盘存储计量单位KB、MB、GB大小换算
一. 预备知识 1. bit与byte 1. bit(简记为 b) 1 bit = 0 or 1 = one binary 2. byte(简记为 B) 1 byte = 8 bits 1字节,8个二 ...
- Redis之(三)管理命令
4.1键管理 通过学习五种数据类型的操作命令,可以发现,Redis对每种数据的处理之前,都要先指定该数据的key,然后再指定对该数据进行何种操作. Redis中的key有点类似于Java中的变量名,起 ...
- 在线看Android系统源码,那些相见恨晚的几种方案
请尊重分享成果,转载请注明出处,本文来自逆流的鱼yuiop,原文链接:http://blog.csdn.net/hejjunlin/article/details/53454514 前言:最近在研究M ...
- Android N(7.0) 被美翻的新特性!
Tamic 专注移动开发!更多文章请关注 Csdn: http://blog.csdn.net/sk719887916/article/details/52612444 $ http://www.ji ...
- Apache shiro集群实现 (三)shiro身份认证(Shiro Authentication)
Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...
- shell的追踪与调试选项
选项: -n :不执行shell脚本,只检查语法问题.没有问题则没有输出. -v :执行shell脚本前,现将shell脚本的命令输出到屏幕上.输出一段,执行一段. -x :将使用到的所有shell脚 ...
- 开源项目——小Q聊天机器人V1.3
小Q聊天机器人V1.0 http://blog.csdn.net/baiyuliang2013/article/details/51386281 小Q聊天机器人V1.1 http://blog.csd ...