使用libgdx进行Android游戏开发–动画,第2部分

这是使用LibGdx构建游戏系列的第二部分。 在开始第二部分之前,请确保已阅读第一部分 。 以下文章将涉及很多内容,因此我将尝试将其分解为更易消化的大小。 我们离开了一个基本的世界,鲍勃在使用箭头键或触摸屏幕时来回滑动。 让我们为运动添加一些真实感,并在角色移动时对其进行动画处理。

角色动画

要为Bob制作动画,我们将使用最简单的技术,称为Sprite animation 。 动画无非是按设定的时间间隔显示的一系列图像以创建
运动的错觉。 以下图像序列用于创建正在运行的动画。

鲍勃跑步雪碧表

。 我通过多次玩Star Guard并分析其运行顺序来使用Gimp来创建运行角色。 创建动画非常简单。 我们要在一定时间内显示每一帧,然后切换到下一张图像。 当我们到达序列的结尾时,我们再次开始。 这称为循环 。 我们需要确定帧持续时间 ,即显示帧的时间。 假设我们以60 FPS渲染游戏,这意味着我们每1/60 = 0.016 s渲染一帧。 我们只有5帧可以动画整步。 考虑到典型的运动员节奏为180,我们可以计算出每个帧显示多少时间才能使跑步更加逼真。

跑步的数学

节奏为180表示每分钟180步。 要计算每秒的步数,我们有180/60 =3。因此,我们每秒必须采取3步。 我们的5帧构成了整整一个步骤,因此我们需要每秒显示3 * 5 = 15帧以模拟职业运动员的跑步情况。 顺便说一下,这不是冲刺。 我们的帧持续时间将是1/15 = 0.066秒。 那是66毫秒。

优化图像

在将其添加到游戏中之前,我们将优化图像。 目前,该项目在star-assault-android项目中的assets/images目录下将图像作为单独的png文件assets/images 。 我们目前正在使用block.pngbob_01.png 。 还有更多图像,即bob_02 - 06.png 。 这些图像组成了动画序列。 因为libgdx在后台使用OpenGL,所以最好不要给框架提供大量图像作为纹理来使用。 我们将要做的是创建一个所谓的Texture Atlas 。 纹理图集只是一个足以容纳其上所有图像的图像,并且它具有一个描述符,其中包含每个单独图像的名称,在图集中的位置和大小。 单个图像在地图集中称为区域 。 它有很多图像,图集可以有多个页面 。 每个页面都作为单一图像加载到内存中,并且这些区域用作单独的图像。 不需要了解所有这一切,但这会使应用程序更加优化,加载速度更快,运行更​​流畅。 Libgdx具有一个名为TexturePacker2的实用程序来创建这些地图集。 它可以从命令行运行或以编程方式使用。 要从Java运行它,请使用以下程序:

package net.obviam.starassault.utils;

import com.badlogic.gdx.tools.imagepacker.TexturePacker2;

public class TextureSetup {

	public static void main(String[] args) {
		TexturePacker2.process('/path-to-star-guard-assets-images/', 'path-to-star-guard-assets-images', 'textures.pack');
	}
}

确保将gdx-tools.jar添加到您的libs目录中。 更改process方法的属性,使其指向资产所在的目录。

注意:

另外,还要对包含下划线“ _”字符的文件进行重命名,因为TexturePacker2会将其用作定界符,而我们目前不需要。 将下划线字符替换为连字符“-”。 处理目录中的图像应生成2个文件: textures.pngtextures.pack 。 纹理图集应类似于下图

纹理图集

我正在使用的目录结构如下: 资产目录结构

现在我们已经确定了动画的效果,帧持续时间并优化了资源,让我们将其添加到游戏中。 我们将首先修改Bob.java因为这是最小的位

public class Bob {

	// ... omitted ... //

	float		stateTime = 0;

	// ... omitted ... //

	public void update(float delta) {
		stateTime += delta;
		position.add(velocity.tmp().mul(delta)); 
	}
}

我们添加了一个名为stateTime的属性。 这将跟踪Bob在特定状态下的时间。 我们将使用它来提供Bob在游戏中花费的时间。 动画确定要显示的帧很重要。 现在不用担心。 如果您真的想了解,请将动画的每个帧都视为一个状态。 鲍勃经历了state_frame_1,state_frame_2等。 这些状态中的每个状态持续0.066秒。 一旦状态时间超过0.066秒,Bob便进入下一个状态。 动画类知道要为当前状态显示的图像。 也称为关键帧WorldRenderer.java遭受的更改最多。 以下代码段包含所有更改。

public class WorldRenderer {

	// ... omitted ... //

	private static final float RUNNING_FRAME_DURATION = 0.06f;

	/** Textures **/
	private TextureRegion bobIdleLeft;
	private TextureRegion bobIdleRight;
	private TextureRegion blockTexture;
	private TextureRegion bobFrame;

	/** Animations **/
	private Animation walkLeftAnimation;
	private Animation walkRightAnimation;

	// ... omitted ... //

	private void loadTextures() {
		TextureAtlas atlas = new TextureAtlas(Gdx.files.internal('images/textures/textures.pack'));
		bobIdleLeft = atlas.findRegion('bob-01');
		bobIdleRight = new TextureRegion(bobIdleLeft);
		bobIdleRight.flip(true, false);
		blockTexture = atlas.findRegion('block');
		TextureRegion[] walkLeftFrames = new TextureRegion[5];
		for (int i = 0; i < 5; i++) {
			walkLeftFrames[i] = atlas.findRegion('bob-0' + (i + 2));
		}
		walkLeftAnimation = new Animation(RUNNING_FRAME_DURATION, walkLeftFrames);

		TextureRegion[] walkRightFrames = new TextureRegion[5];

		for (int i = 0; i < 5; i++) {
			walkRightFrames[i] = new TextureRegion(walkLeftFrames[i]);
			walkRightFrames[i].flip(true, false);
		}
		walkRightAnimation = new Animation(RUNNING_FRAME_DURATION, walkRightFrames);
	}

	private void drawBob() {
		Bob bob = world.getBob();
		bobFrame = bob.isFacingLeft() ? bobIdleLeft : bobIdleRight;
		if(bob.getState().equals(State.WALKING)) {
			bobFrame = bob.isFacingLeft() ? walkLeftAnimation.getKeyFrame(bob.getStateTime(), true) : walkRightAnimation.getKeyFrame(bob.getStateTime(), true);
		}
		spriteBatch.draw(bobFrame, bob.getPosition().x * ppuX, bob.getPosition().y * ppuY, Bob.SIZE * ppuX, Bob.SIZE * ppuY);
	}
	// ... omitted ... //
}

#05 –声明RUNNING_FRAME_DURATION常数,该常数控制跑步/步行周期中帧的显示时间
#08 –#11 – Bob的不同状态的TextureRegionbobFrame –将保存将在当前循环中显示的区域。 #14-#15-两个Animation对象,用于在行走/跑步时为Bob设置动画。

TextureAtlas加载图像

#19 –新的loadTextures()方法
#20 –从内部文件中加载TextureAtlas。 这是TexturePacker2.pack文件。 #21 –分配名为“ bob-01?”的区域 (这是不带扩展名的实际png名称-请参见TexturePacker2)到bobIdleLeft变量。 #22 –#23 –创建一个新的TextureRegion (注意使用副本构造函数,我们需要一个副本,而不是引用),并在X轴上翻转它,以便我们具有相同的图像,但针对Bob的空闲状态进行镜像,但是当面对右侧时。 翻转非常有用,因为我们不需要加载额外的图像,而是从现有图像中创建一个。 #24 –将相应区域分配给块 #25 –#28 –我们创建一个TextureRegion数组,它们将组成动画。 我们知道有5个帧及其名称: bob-02, bob-03, bob-04, bob-05bob-06 。 为了方便起见,我们使用for循环。 #29 –在此处定义向左行走状态的动画。 第一个参数是序列中以秒(0.06)表示的序列中每个帧的持续时间,第二个参数采用组成动画的帧的有序列表。 #31 –#38 –为步行右状态创建动画。 它是左行走状态动画的副本,但每帧均被翻转。 重要的是要复制框架,而不要翻转框架,因为原稿也会翻转。 #40 –更改后的drawBob()方法。 #42 –根据Bob的朝向,将活动帧设置为空闲帧之一 #44 –如果Bob处于步行状态,则根据Bob的当前状态时间为步行序列之一提取相应的帧,并将其分配给将被绘制到屏幕上的bobFrame。 运行StarAssaultDesktop应用程序,我们应该看到Bob动画在StarAssaultDesktop 。 它看起来应该像这样:

该项目的源代码可以在这里找到: https : //github.com/obviam/star-assault 。 您需要检出分支part2 。 要使用git进行检查: git clone -b part2 git@github.com:obviam/star-assault.git 。 您也可以将其下载为zip文件

参考: 使用libgdx进行Android游戏开发–动画,来自JCG合作伙伴 Impaler的第2部分,网址Against the Grain博客。

翻译自: https://www.javacodegeeks.com/2013/02/android-game-development-with-libgdx-animation-part-2.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值