Android游戏开发–雪碧动画

如果到目前为止您仍然关注该系列,我们将在处理触摸,显示图像和移动它们方面广为人知。

但是,动态图像看起来很呆板,因为它看起来确实是假的和业余的。 为了给角色一些生活,我们将需要做更多的事情。 这就是动画的全部内容。 岩石是无生命的物体,即使被扔掉,它的形状也不会改变。 另一方面,人类非常活跃。 尝试扔一个,您会看到四肢抽搐,甚至在空中尖叫。

让我们仅依靠检查本身很复杂的步行即可。 想象一个人横穿您的道路(仅在2D模式下)。 您会注意到身体的不同显示。 左脚在前,右手在前,相反的四肢在后。 这种变化缓慢,因此左脚留在后面,而右脚则与身体一起前进。 但在某一点上,循环会重复。 如果你不闭上眼睛,你会看到这个人进展顺利。 如果您闭上眼睛并保持闭合状态再打开一次,则该人已经继续前进并且处于不同的位置。 尝试快速眨眼,您会看到类似黑白喜剧的东西。 那就是低帧率。 有关FPS的更多信息,请点击此处

实际上,对于本教程,我们确实希望以较低的帧速率行走,就像这样。

上面介绍的行走有点狡猾,但这是猴子岛精灵的翻版。 她是Elaine Marley。这称为Sprite 。 它是简单的二维图像或动画。为了能够重新创建上述动画,我们需要步行周期中的每一帧。

它是一个150像素宽的图像,每帧为30像素宽。为了更好地说明它,请检查以下图像。

要在android(或iPhone或其他任何程序)中获得上述动画,我们需要将每一帧加载为单独的图像,并以规则的间隔依次显示它们。 或者,我们可以加载包含所有帧的大图像,并使用android提供的方法对它们进行切片和切块,并仅显示相关帧。做到这一点是微不足道的。 我们知道我们有5帧,每帧为30像素宽。 我们定义一个矩形(将是我们的选择),该矩形具有一帧的宽度和图像的高度。下图显示了如何裁剪前两帧。 其余的您应该填写。

了解所有这些之后,我们就可以创建项目了。 我们将使用前几章中的知识,尤其是有关游戏循环和有关图像显示的知识(在这里,我们设置了每帧触发图形项绘制的线程)。

我们将需要一个对象进行动画处理。 我们使用猴子岛的Elaine,所以我将使用类ElaineAnimated.java

public class ElaineAnimated {

	private static final String TAG = ElaineAnimated.class.getSimpleName();

	private Bitmap bitmap;		// the animation sequence
	private Rect sourceRect;	// the rectangle to be drawn from the animation bitmap
	private int frameNr;		// number of frames in animation
	private int currentFrame;	// the current frame
	private long frameTicker;	// the time of the last frame update
	private int framePeriod;	// milliseconds between each frame (1000/fps)

	private int spriteWidth;	// the width of the sprite to calculate the cut out rectangle
	private int spriteHeight;	// the height of the sprite

	private int x;				// the X coordinate of the object (top left of the image)
	private int y;				// the Y coordinate of the object (top left of the image)

}

私有属性已注释,但值得一提。

  • 位图是包含所有帧的png文件。 本文的第二张图片。
  • sourceRect是选择矩形。 这是上图中的蓝色窗口。 矩形将每一帧移到下一帧。
  • frameTicker这是行走序列中最后一个帧更改的java时间戳。 请注意,这不是游戏FPS,而是步行FPS。 如果我们希望Elaine在1秒钟内执行完整的步行周期,则将步行的帧频设置为5,因为我们有5帧。 要获得真正流畅的动画,我们需要30帧,但这不是重点。
  • framePeriod是时间(以毫秒为单位),表示显示帧的时间段。 如果周期在1秒钟内完成,则意味着持续5帧,周期为0.2秒。 即,每帧将显示0.2秒。

构造函数如下:

public ElaineAnimated(Bitmap bitmap, int x, int y, int width, int height, int fps, int frameCount) {
		this.bitmap = bitmap;
		this.x = x;
		this.y = y;
		currentFrame = 0;
		frameNr = frameCount;
		spriteWidth = bitmap.getWidth() / frameCount;
		spriteHeight = bitmap.getHeight();
		sourceRect = new Rect(0, 0, spriteWidth, spriteHeight);
		framePeriod = 1000 / fps;
		frameTicker = 0l;
	}

我假设帧的宽度相同,所以我通过将图像的宽度除以帧数来计算矩形的宽度。 我还传递了fps ,这也是步行周期每秒的帧数而不是游戏FPS。

Elaine将拥有自己的更新方法,因为她是动画对象,并且她需要看起来很好并且负责拖动脚。 因为游戏更新周期的时间段和Elaine的周期可能不同(在这种情况下),所以我们将实际游戏时间作为变量传递,因此我们知道何时需要显示下一帧。例如,游戏运行非常快,每20毫秒调用一次更新,因此我们需要每200毫秒更新一次帧,然后每进行10次游戏更新就会发生一次帧的进行。

这是代码:

public void update(long gameTime) {
	if (gameTime > frameTicker + framePeriod) {
		frameTicker = gameTime;
		// increment the frame
		currentFrame++;
		if (currentFrame >= frameNr) {
			currentFrame = 0;
		}
	}
	// define the rectangle to cut out sprite
	this.sourceRect.left = currentFrame * spriteWidth;
	this.sourceRect.right = this.sourceRect.left + spriteWidth;
}

从主游戏面板调用此更新(检查以前的输入如何工作)。 这是MainGamePanel类的更新方法。

public void update() {
	elaine.update(System.currentTimeMillis());
}

更新方法很简单(Elaine's)。 如果传入的时间(这是调用update方法的系统时间)大于上一次更新帧的时间(一个帧时间)加上下一次更新的时间,则它将递增帧。如果下一帧超出最后一帧,我们将重置循环。

将所有要从中剪切图像的区域定义为sourceRect 。而已。 现在让我们继续显示它。

public void draw(Canvas canvas) {
		// where to draw the sprite
		Rect destRect = new Rect(getX(), getY(), getX() + spriteWidth, getY() + spriteHeight);
		canvas.drawBitmap(bitmap, sourceRect, destRect, null);
	}

就这些。 我们将目标矩形设置为在何处绘制剪切出的图像。 它位于Elaine的位置(在构造函数中设置了X和Y)。

canvas.drawBitmap(bitmap, sourceRect, destRect, null);

告诉android从位图包含的图像中切出sourceRect定义的图像,并将它绘制到destRect定义的画布上的矩形中。

从游戏循环触发的游戏面板的渲染方法中调用绘制(请检查先前的条目)。

MainGamePanel.java与前几章略有不同。 我摆脱了所有的机器人,只添加了伊莱恩。

private ElaineAnimated elaine;

	public MainGamePanel(Context context) {
		//* ... removed ... */

		// create Elaine and load bitmap
		elaine = new ElaineAnimated(
				BitmapFactory.decodeResource(getResources(), R.drawable.walk_elaine)
				, 10, 50	// initial position
				, 30, 47	// width and height of sprite
				, 5, 5);	// FPS and number of frames in the animation

		// create the game loop thread
		thread = new MainThread(getHolder(), this);

		//* ... removed ... */
	}

Elaine在面板的构造函数中实例化,并且初始位置为(X = 10,Y = 50)。 我也传入了精灵的宽度和高度,但是无论如何都会忽略它,但是您可以修改代码。FPS非常重要,帧数也很重要。 FPS表示一秒钟要显示多少帧。 最后一个参数是循环中的帧数。

线程和活动类完全没有改变。 您可以在下载中找到它们,因为它们粘贴的时间很长。 该图像名为walk_elaine.png ,它已复制到/ res / drawable-mdpi /,因此android可以自动将其拾取。

如果运行该应用程序,您应该会发现Elaine在一个地方执行步行周期。 我们应该使用跳跃,因为可以在一个地方进行跳跃,但是您明白了。

伊莱恩步行

增强功能

为了进行一些巧妙的修改,请修改Elaine的draw方法,使其显示原始图像,其中包含从中提取帧的精灵。

public void draw(Canvas canvas) {
	// where to draw the sprite
	Rect destRect = new Rect(getX(), getY(), getX() + spriteWidth, getY() + spriteHeight);
	canvas.drawBitmap(bitmap, sourceRect, destRect, null);
	canvas.drawBitmap(bitmap, 20, 150, null);
	Paint paint = new Paint();
	paint.setARGB(50, 0, 255, 0);
	canvas.drawRect(20 + (currentFrame * destRect.width()), 150, 20 + (currentFrame * destRect.width()) + destRect.width(), 150 + destRect.height(),  paint);
}

这仅显示(20,150)处的图像并创建一个新的绘画对象,因此我们可以在原始图像的当前帧上绘画。setARGB方法创建半透明的绿色涂料。 第一个值是50 ,表示其透明度为75%。 0是完全透明的,而255是完全不透明的。绘制完所有内容后,我们将一帧大小的矩形绘制到原始图像上,以便查看运动中正在显示的帧。

行走与当前画框

而已。 运行它,您将拥有第一个精灵动画。

此处下载源代码(animation_walk.tar.gz)

参考:来自我们的JCG合作伙伴Tamas Jano的Android版Sprite动画,来自“ Against The Grain ”博客。

不要忘记查看我们的新Android游戏ArkDroid (以下屏幕截图) 。 您的反馈将大有帮助!
相关文章:

翻译自: https://www.javacodegeeks.com/2011/07/android-game-development-sprite.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值