如何使用libgdxjava编写简单计算器一个简单的游戏

你正在使用的浏览器版本过低,将不能正常浏览和使用知乎。1640人阅读
Libgdx(79)
(原文:)
在深入研究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.
import com.badlogic.gdx.backends.lwjgl.LwjglA
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationC
import cn.libgdx.drop.D
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&;
package=&cn.libgdx.drop.android&
android:versionCode=&1&
&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& &
android:label=&@string/app_name&
android:screenOrientation=&landscape&
android:configChanges=&keyboard|keyboardHidden|orientation|screenSize&&
&intent-filter&
&action&; /&
&category&; /&
&/intent-filter&
&/activity&
&/application&
&/manifest&
其实是用GDX-setup生成的项目android:screenOrientation默认值为landscape,所以无需改动。
接下来需要禁用加速度计和罗盘,这需要改动Android项目AndroidLauncher.java文件,代码如下:
package cn.libgdx.drop.
import android.os.B
import com.badlogic.gdx.G
import com.badlogic.gdx.backends.android.AndroidA
import com.badlogic.gdx.backends.android.AndroidApplicationC
import cn.libgdx.drop.D
public class AndroidLauncher extends AndroidApplication {
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
config.useAccelerometer=
config.useCompass=
initialize(new Drop(), config);
我们不能定义Activity的分辨率,这个是由Android操作系统来定。就像我们之前定义的,设置所有平台分辨率为800*480。
开始编写代码
现在将代码分成几个部分来分析,为了保持项目的可移植性,我们需要将代码写到core项目下。
载入Assets
我们第一个任务就是载入assets文件和保存参数。Assets通常在ApplicationListener.create()方法中载入,代码如下:
package cn.libgdx.
import com.badlogic.gdx.ApplicationA
import com.badlogic.gdx.G
import com.badlogic.gdx.audio.M
import com.badlogic.gdx.audio.S
import com.badlogic.gdx.graphics.GL200;
import com.badlogic.gdx.graphics.T
import com.badlogic.gdx.graphics.g2d.SpriteB
public class Drop extends ApplicationAdapter {
private Texture dropI
private Texture bucketI
private Sound dropS
private Music rainM
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();
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 OrthographicC
private SpriteB
在create()方法中添加如下语句,创建camera:
camera = new OrthographicCamera();
camera.setToOrtho(false, 800, 480);
这将确保camera总是显示800*480的范围。可以视作一个虚拟窗口。这样可以让应用可移植性增强。
接下来,在create()方法中创建SpriteBatch:
batch=new SpriteBatch();
最后添加桶和雨滴,它们需要以下的条件:
桶和雨滴在800*480中需要一个位置信息。
桶和雨滴需要宽和高。
为了展现桶和雨滴,我们需要保存它们的位置和大小。在Libgdx中可以通过Rectangle实现。代码如下:
在create()方法中我们需要实例化并且设置他的只。这里设置在屏幕底部,并且水平居中。代码如下:
bucket = new Rectangle();
bucket.x = 800 / 2 - 64 / 2;
bucket.y = 20;
bucket.width = 64;
bucket.height = 64;
需要注意的是,在libgdx中,坐标系原点在左下角。
接下来需要渲染我们的桶,首先需要设置屏幕的背景色,在render()方法中添加如下代码:
public void render () {
Gdx.gl.glClearColor(0, 0, 0.2f, 1).2f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
为了使用顶层的类,像Texture和SpriteBatch。首先需要调用清除屏幕并设置为蓝色。第一句的意思是设置清屏颜色,第二句才执行清屏操作。
接下来我们需要告诉camera确保它更新。接下来我们设置camera在每一帧中都更新。
接下来我们需要渲染桶。
batch.bined);
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()FT)) bucket.x -= 200 * Gdx.graphics.getDeltaTime();
if(Gdx.input.isKeyPressed(Keys.RIGHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime()GHT)) bucket.x += 200 * Gdx.graphics.getDeltaTime();
当键盘按下时,Gdx.input.isKeyPressed()方法用来判断是否为指定按键。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&
这个Array类是一个libgdx的工具类,用来代替java的ArrayList。后者将在很多情况下产生垃圾。Array尽量减少垃圾的产生。
我们同样需要记录上一次掉落的雨滴的时间,所以我们添加:
private long lastDropT
我们将存储纳秒,这就是我们为什么使用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 & ) spawnRaindrop();
我们同样需要雨点移动,一下是代码:
Iterator&Rectangle& iter = raindrops.iterator();
while(iter.hasNext()) {
Rectangle raindrop = iter.next();
raindrop.y -= 200 * 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();
最后需要清理。代码如下:
public void dispose() {
dropImage.dispose();
bucketImage.dispose();
dropSound.dispose();
rainMusic.dispose();
batch.dispose();
(版权所有,如需转载,注明出处)
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:289893次
积分:4508
积分:4508
排名:第6234名
原创:158篇
评论:78条
文章:31篇
阅读:111912
文章:12篇
阅读:14988
文章:43篇
阅读:38391
(1)(7)(30)(1)(2)(2)(6)(8)(4)(1)(19)(10)(1)(17)(3)(6)(6)(4)(25)(5)libGDX游戏的生命周期
来源:博客园
一,ApplicationListener和ApplicationAdapter 提及到libGDX的游戏生命周期,那么不得不提一个非常重要的接口ApplicationListener,这个接口位于com.badlogic.gdx包里,ApplicationListener的主要职责是创建和显示窗口。下图为ApplicationListener里的函数:
既然ApplicationListener是接口,那么就一定是需要去实现才能使用了,但是每次使用都要去实现这么多个方法,似乎有点吃力不讨好,而且好未必都用得上。看回之前创建的项目原来ApplicationListener已经有个实现的类ApplicationAdapter了:
二,生命周期图 看到了ApplicationListener里的这些函数,虽然都有一句话的解释,但是我觉得对照官方的生命周期图来看会更加清晰明了,以下是官方的生命周期图:
三,程序中看生命周期 为了清楚了解游戏的生命周期,下面我们使用log来打印下日志: 1,在core 中的主类中重写父类ApplicationAdapter的方法: package com.stephen.

import com.badlogic.gdx.ApplicationA
import com.badlogic.gdx.G
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.T
import com.badlogic.gdx.graphics.g2d.SpriteB

public class MyGdxGame extends ApplicationAdapter {
SpriteB
@Override
public void create () {
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
@Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
@Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
super.resize(width, height);
@Override
public void pause() {
// TODO Auto-generated method stub
super.pause();
@Override
public void resume() {
// TODO Auto-generated method stub
super.resume();
@Override
public void dispose() {
// TODO Auto-generated method stub
super.dispose();
}
}
2,添加打印日志的语句:
package com.stephen.

import com.badlogic.gdx.ApplicationA
import com.badlogic.gdx.G
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.T
import com.badlogic.gdx.graphics.g2d.SpriteB

public class MyGdxGame extends ApplicationAdapter {
SpriteB
private String tag = "TAG";
private boolean isRender = false;
@Override
public void create () {
Gdx.app.log(tag, "create");
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
@Override
public void render () {
if(!isRender){
//此处由于render会不断执行,所以加上个标志
Gdx.app.log(tag, "render");
isRender = true;
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, 0, 0);
batch.end();
@Override
public void resize(int width, int height) {
// TODO Auto-generated method stub
super.resize(width, height);
Gdx.app.log(tag, "resize");
@Override
public void pause() {
// TODO Auto-generated method stub
super.pause();
Gdx.app.log(tag, "pause");
@Override
public void resume() {
// TODO Auto-generated method stub
super.resume();
Gdx.app.log(tag, "resume");
@Override
public void dispose() {
// TODO Auto-generated method stub
super.dispose();
Gdx.app.log(tag, "dispose");
}
}
3,运行程序,查看日志:
(1)游戏启动时:

(2)按Home键:

(3)按Home键后点击游戏图标:

(4)按返回键:

(5)再次回到游戏:

(6)从任务管理处直接关闭游戏:

四,总结
通过以上官方api的说明、官方的生命周期图和我们程序所打印的日志,可以总结如下:
create ():游戏首次创建时调用,在这个函数里可以初始化我们自己的一些信息。
resize():当create方法执行完毕后调用,另外当游戏处于活跃状态下屏幕尺寸改变时也会调用调用。
render ():这个函数在resize执行完毕后开始运行,而且是不断运行渲染游戏图像界面。
pause():游戏进入后台的时候调用,此时游戏处于非活跃状态,但是游戏还存在。
resume():游戏从非活跃状态到活跃状态时调用。
dispose():游戏被销毁时调用。
免责声明:本站部分内容、图片、文字、视频等来自于互联网,仅供大家学习与交流。相关内容如涉嫌侵犯您的知识产权或其他合法权益,请向本站发送有效通知,我们会及时处理。反馈邮箱&&&&。
学生服务号
在线咨询,奖学金返现,名师点评,等你来互动如何使用libgdx编写一个简单的游戏(一)— 雏形
写这几篇文章主要是看了这个系列的文章:
这个系列主要讲述了如何使用Cocos2D编写简单的游戏。稍微读读感觉不错,所以想写个libgdx版本的。
本篇文章主要讲述基本内容的编写,包括显示人物、怪兽和飞镖。
最终效果如下图:
获取libgdx
你可以从libgdx的下载打包好的代码,我下载的是0.98版本。
当然,你也可以从git代码仓库获取最新的版本的,或者你习惯使用的以前版本,比如0.97。
libgdx项目的创建可以有多种方式,我推荐使用setup-ui。方便易用还可以省去很多麻烦,特别是ADT升级以后的ClassNotFound问题。
如果是下载打包好的,那么就默认包含了gdx-setup-ui,双击就可以打开。
填写一些基本信息,然后选中你下载的0.98.zip那个压缩文件。这里我只生成一个桌面项目和Android项目。
桌面项目是方便调试,而Android项目是最后发布的。在整个开发中我始终用桌面项目调试,因为速度快,容易排错。同时周期性的在Android真机上测试。
点击生成项目,然后在Eclipse中导入。
一般导入进去以后Android项目会有一些问题,修改project.properties文件和AndroidManifest.xml配置文件。
运行效果如下:
本例子中用到的图片如下:
用gdx-texturepacker打包成一张大图。
我整个例子都是用的是Stage模式。所以它的坐标原点在左下角,如果是一般用Spirte直接绘制,那么原点在右上角。
首先将打包好的图册复制到assets中新建的pack文件夹。
然后我们开始动工了,首先删除setup-ui生成的多余代码,整理DartsShaSha.java文件如下:
import com.badlogic.gdx.ApplicationA
import com.badlogic.gdx.G
import com.badlogic.gdx.graphics.GL10;
import com.badlogic.gdx.scenes.scene2d.S
public class DartsShaSha extends ApplicationAdapter {
public void create() {
stage = new Stage(480, 320, true);
public void dispose() {
stage.dispose();
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
stage.act();
stage.draw();
这时候运行效果是一个白茫茫的画面。
注意一下这句
stage = new Stage(480, 320, true);
因为我希望屏幕的自适应有Stage自动完成,所以坐标基本可以写死。
先不着急开工,我们先添加一个现实FPS的标签。我希望这个标签显示在屏幕右下角。
在create方法中添加
LabelStyle labelStyle = new LabelStyle(new BitmapFont(), Color.BLACK); //创建一个Label样式,使用默认黑色字体
Label label = new Label(&FPS:&, labelStyle); //创建标签,显示的文字是FPS:
label.setName(&fpsLabel&); //设置标签名称为fpsLabel
label.setY(0); //设置Y为0,即显示在最下面
label.setX(480 - label.getTextBounds().width); //设置X值,显示为最后一个字紧靠屏幕最右侧
stage.addActor(label); //将标签添加到舞台
在render方法中更新fps的值
Label label = (Label) stage.getRoot().findActor(&fpsLabel&); //获取名为fpsLabel的标签
label.setText(&FPS:& + Gdx.graphics.getFramesPerSecond());
label.setX(480 - label.getTextBounds().width); //更新X值以保证显示位置正确性
效果如下:
现在来添加我们的主角,我希望主角显示在屏幕左侧中央。所以它的x值必然是0,但是它的y值并不是320的一半,而是160减去图片高度的一半。
因为我们指定的x、y值其实相对图片的左下角的。所以要补上多余或者不足的部分。
主角其实就是一张图片,并没有太多特别的效果,所以我使用Image类。
首先获取图册
TextureAtlas atlas = new TextureAtlas(&pack/default.pack&);
在从图册中获取Player.png并创建Image对象。
Image man = new Image(atlas.findRegion(&Player&)); //获取图册中的Player.png并创建image对象
man.setX(0);
man.setY(160 - man.getHeight() / 2); //设置Y值,以让图片在中间显示
stage.addActor(man); //将主角添加到舞台
效果如下:
然后我们来添加几只怪兽。怪兽应该是随机从屏幕右侧出现,并直线移动到屏幕左侧。
同时我们还要检测怪兽的生命值什么的,或者其他效果,所以为了方便处理,我们专门建立一个Group来管理怪兽。
新建类TargetGroup,并集成Group类。
import com.badlogic.gdx.graphics.g2d.TextureAtlas.AtlasR
import com.badlogic.gdx.scenes.scene2d.G
import com.badlogic.gdx.scenes.scene2d.ui.I
public class TargetGroup extends Group {
public TargetGroup(AtlasRegion region) {
因为还需要传入怪兽的图片,所以我们的创建方法保留参数AtlasRegion region。
怪兽的Y值因为是随机的,但是又不能超出屏幕。所以用随机数来生成。libgdx的MathUtils提供了相关方法。
int minY = 0;
int maxY = (int) (320 - region.getRegionHeight());
int tempY = MathUtils.random(minY, maxY);
这里还有一个问题需要注意,就是怪兽之间不应该出现遮挡,所以对于生成的Y值还需要进行判断。
假设我们要生成3只怪兽,那么代码应该如下:
int tempY = 0;
for (int i = 0; i & 3; i++) {
Image image = new Image(region);
image.setX(480 - image.getWidth());
// 开始判断Y值是否符合要求
boolean flag =
tempY = MathUtils.random(minY, maxY); // 生成Y值
Actor[] actors = this.getChildren().begin(); // 获取当前已有的怪兽对象
for (int j = 0; j & this.getChildren(). j++) {
Actor tempActor = actors[j];
if (tempY == tempActor.getY()) { // 如果Y值相等,比如重合,所以舍弃,重新生成
} else if (tempY & tempActor.getY()) { // 如果生成的Y值小于当前怪兽的Y值,则判断生成的Y值加上高度后是否合适
if ((tempY + region.getRegionHeight()) &= tempActor
.getY()) {
} else { // 如果生成的Y值大于当前怪兽的Y值,则判断当前怪兽的Y值加上高度后是否合适
if (tempY &= (tempActor.getY() + region
.getRegionHeight())) {
} while (flag);
image.setY(tempY);
this.addActor(image); //添加到组中
在主类的create方法中添加
TargetGroup group = new TargetGroup(atlas.findRegion(&Target&));
stage.addActor(group);
效果如下:
目前怪兽还不能移动,这里需要一个简单的动画效果,libgdx中的Action可以办到。
考虑到怪兽是水平移动,即Y值不变,X值变小。
所以添加一个方法
public void AddMove(Actor actor, float time) {
actor.addAction(Actions.moveTo(0, actor.getY(), time));
怪兽的移动速度也随机一下,代码如下
image.setY(tempY);
this.AddMove(image, MathUtils.random(3f, 8f)); //怪兽移动效果
this.addActor(image); //添加到组中
效果如下:
我们的主角自然不能赤手空拳和怪兽进行搏斗,现在添加一些飞镖。
假定用户触摸屏幕以后,主角就向触摸位置发射一个飞镖。
因为飞镖的数量不一定,所以我这里创建一个专门的类ProjectileFactory来处理。
首先是飞镖的创建,和怪兽群一样的原因,我还是希望一个专门的组来管理。
创建一个专门的方法来创建飞镖
public static Image createProjectile(AtlasRegion region, Actor man,
Vector3 target) {
Image image = new Image(region);
image.setX(man.getX() + man.getWidth() / 2);
image.setY(man.getY() + man.getHeight() / 2);
image.addAction(Actions.moveTo(target.x, target.y, 2f)); //设置飞镖的移动
在主类进行一些修改以便其可以获取屏幕的触摸。
首先修改类声明为
public class DartsShaSha extends InputAdapter implements ApplicationListener
其实具体也可以两个都实现接口,主要是我觉得看着不舒服。
重写touchDown方法为
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
Vector3 vector3 = new Vector3(screenX, screenY, 0);
stage.getCamera().unproject(vector3); // 坐标转化
projectiles.addActor(ProjectileFactory.createProjectile(
atlas.findRegion(&Projectile&), man, vector3)); // 添加新飞镖到飞镖组
在create方法中添加新的Group并设置Input响应。
stage.addActor(projectiles); //添加飞镖组到舞台
InputMultiplexer multiplexer = new InputMultiplexer(); //多输入接收器
multiplexer.addProcessor(this); //添加自身作为接收
multiplexer.addProcessor(stage); //添加舞台
Gdx.input.setInputProcessor(multiplexer); //设置多输入接收器为接收器
效果如下:
更完善的飞镖
飞镖虽然添加出来了,但是飞镖没有转动…而且飞镖没有在到达目的地后自动消失。
现在先来添加旋转效果,libgdx提供了rotateBy方法。
在创建飞镖的createProjectile方法中添加
image.addAction(Actions.repeat(50, Actions.rotateBy(360, 0.5f))); //设置飞镖的旋转
这个不方便截图,就不展示效果了。
现在来考虑如何让飞镖到达目的后消失。首先来看看我们的Image对象,它包含了两个Action,一个是旋转Action,另外一个移动Action。
我们可以检测Action的数量,如果只有一个Action,我们可以断定飞镖只是在旋转而已经到达目的地了。这个时候就可以把它删除了。
添加一个专门的方法来判断飞镖是否应该移除了
public static Boolean checkAlive(Actor projectile) {
if (projectile.getActions().size == 1) {
在render方法中添加处理代码
// 飞镖的移除判
Actor[] projectile = projectiles.getChildren().begin(); //获取Actor数组
for (int j = 0; j & projectiles.getChildren(). j++) { //移除判断
Actor actor = projectile[j];
if (!ProjectileFactory.checkAlive(actor)) {
projectiles.removeActor(actor);
效果如下:
现在飞镖可以自动消失了,并且也在旋转了。不过旋转效果很奇怪,它并不是沿中心旋转,而是沿着左下角旋转的。
重新设置中心
image.setOrigin(image.getWidth() / 2, image.getHeight() / 2);
现在一切正常了。
碰撞检测和杀敌
当然,发出飞镖的目的自然是杀敌,现在马上来添加这个功能。
我们可以把怪兽看着一个矩形,即飞镖击中任何位置都算作有效。而飞镖就以其中心为代表。
创建方法attackAlive
public static Boolean attackAlive(Actor target, Actor projectile) {
Rectangle rectangle = new Rectangle(target.getX(), target.getY(),
target.getWidth(), target.getHeight()); // 创建一个矩形
return rectangle.contains(
projectile.getX() + projectile.getWidth() / 2,
projectile.getY() + projectile.getHeight() / 2); //判断是否在矩阵中,即是否击中
在render方法中修改
// 开始处理飞镖
Actor[] projectile = projectiles.getChildren().begin();
Actor[] targets = targetGroup.getChildren().begin();
for (int i = 0; i & projectiles.getChildren(). i++) {
Actor actor = projectile[i];
for (int j = 0; j & targetGroup.getChildren(). j++) {
Actor target = targets[j];
if (ProjectileFactory.attackAlive(target, actor)) {
targetGroup.removeActor(target);
projectiles.removeActor(actor);
// 如果飞镖已经飞到则刪除
projectile = projectiles.getChildren().begin();
for (int j = 0; j & projectiles.getChildren(). j++) {
Actor actor = projectile[j];
if (!ProjectileFactory.checkAlive(actor)) {
projectiles.removeActor(actor);
效果如下:
虽然实现了个大概,但是仔细看看其实问题还是很多的,后面的文章会提到进一步的修改。包括逻辑上的完善,声音效果,预加载,背景绘制,集成第三方社交和广告等等。
这片文章对应demo可以从这里下载来试试。
我用的2.2的sdk编译的,低版本没有测试。我的手机是ZTE V880,fps50上下。
ps:testin的测试结果是通过率&100.00%
ps: 代码上传到github上了,地址&
文章对应的代码的tag为page 1。原文链接:

我要回帖

更多关于 用vb编写简单小游戏 的文章

 

随机推荐