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 sequenceprivate Rect sourceRect; // the rectangle to be drawn from the animation bitmapprivate int frameNr; // number of frames in animationprivate int currentFrame; // the current frameprivate long frameTicker; // the time of the last frame updateprivate int framePeriod; // milliseconds between each frame (1000/fps)private int spriteWidth; // the width of the sprite to calculate the cut out rectangleprivate int spriteHeight; // the height of the spriteprivate 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 framecurrentFrame++;if (currentFrame >= frameNr) {currentFrame = 0;}}// define the rectangle to cut out spritethis.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 spriteRect 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 bitmapelaine = 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 threadthread = 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 spriteRect 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游戏开发教程简介
- Android游戏开发–游戏创意
- Android游戏开发–创建项目
- Android游戏开发–基本游戏架构
- Android游戏开发–基本游戏循环
- Android游戏开发–使用Android显示图像
- Android游戏开发–在屏幕上移动图像
- Android游戏开发–游戏循环
- Android游戏开发–测量FPS
- Android游戏开发–粒子爆炸
- Android游戏开发–设计游戏实体–策略模式
- Android游戏开发–使用位图字体
- Android游戏开发–从Canvas切换到OpenGL ES
- Android游戏开发–使用OpenGL ES显示图形元素(原语)
- Android游戏开发– OpenGL纹理映射
- Android游戏开发–设计游戏实体–状态模式
- Android游戏文章系列
翻译自: https://www.javacodegeeks.com/2011/07/android-game-development-sprite.html
Android游戏开发–雪碧动画相关推荐
- 雪碧图 游戏开发_Android游戏开发–雪碧动画
雪碧图 游戏开发 如果到目前为止您仍然关注该系列 ,我们将在处理触摸,显示图像和移动它们方面广为人知. 但是,动态图像看起来很呆板,因为它看起来确实是假的和业余的. 为了给角色一些生活,我们将需要做更 ...
- Android游戏开发–粒子爆炸
有没有想过爆炸是如何产生的? 让我们绕个弯路,尝试实现基本的粒子爆炸. 爆炸不过是一堆散布在屏幕上的,源自单个点的粒子(无论是像素,小形状还是图像). 为了方便起见,并非总是如此,而是为了简洁起见,我 ...
- Android游戏开发–游戏循环
游戏循环是每个游戏的心跳. 到目前为止,我们仅使用了非常简单的一种(您可以在此处找到),无法控制我们更新游戏状态的速度或速度以及要渲染的帧. 概括地说,最基本的游戏循环是while循环,该循环一直执行 ...
- android游戏开发_Android游戏开发–游戏循环
android游戏开发 游戏循环是每个游戏的心跳. 到目前为止,我们仅使用了非常简单的一种(您可以在此处找到),无法控制我们更新游戏状态的速度或速度以及要渲染的帧. 概括地说,最基本的游戏循环是whi ...
- 【Android游戏开发二十二】(图文详解)游戏中灵活实现动画播放!简述J2me的游戏类库与Android游戏开发!
本站文章均为 李华明Himi 原创,转载务必在明显处注明:(作者新浪微博: @李华明Himi ) 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/andr ...
- 雪碧动画:吸血鬼凯蒂的生活
我一直很喜欢网页游戏: 它们只是制作有趣,易于编码(大多数情况下),并且当用户只需要单击一个链接即可开始玩游戏时,游戏的可访问性就非常不错. Ajax和移动的dom元素带来了一些乐趣,但是限制了您可以 ...
- 动画版雪碧_雪碧动画:吸血鬼凯蒂的生活
动画版雪碧 我一直很喜欢网页游戏: 它们只是制作有趣,易于编码(大多数情况下),并且当用户只需要单击一个链接即可开始玩游戏时,游戏的可访问性就非常不错. Ajax和移动的dom元素带来了一些乐趣,但是 ...
- Android 游戏开发必备的基础知识
Android游戏开发: View类开发框架 SurfaceView开发框架 Graphics类开发框架 Paint与Color类介绍 Canvas介绍 几何图形绘制 字符串绘制 图像的绘制 图像的旋 ...
- Android 游戏开发入门
Android 游戏开发入门 图书描述: Android系统已经红遍了大江南北,持有Android设备的人也在不断增长.看着大街上用手指划着手机玩游戏的人,你有没有一种自己做一个游戏的想法呢?然而,入 ...
最新文章
- Git忽略文件方法【转】
- 关于变量在循环内声明还是在循环外声明
- nginx+tomcat实现Windows系统下的负载均衡搭建教程
- 微服务访问安全设计方案全探索
- python把数据写入excel_Python向excel中写入数据的方法
- linux2.6驱动学习笔记之字符驱动
- pcap python 生成_python+pcap+dpkt 抓包小实例
- Spark团队开源新项目MLflow发布0.2版本,内置TensorFlow集成
- Element-UI学习笔记-安装
- Magisk升级Zygisk
- 对两个等长升序的序列查找中位数
- 高端风再起,小爱、小度、天猫精灵发新芽?
- escape JavaScript
- c语言程序设计迷宫问题,C语言迷宫问题
- Shiro教程 - 雁迟
- ybt1000:入门测试题目
- PhysicalDrive 只是Device\Harddisk%d\Partition0的符号连接,. 而Device\Harddisk0\Partition0是\Device\Harddisk0\D
- oracle 设置监听和服务,oracle服务端和客户端之间的网络监听设置
- mysql 获取上个月,这个月的第一天或最后一天
- 阿里云视频加解密VOD开发