本文已参加【新人创作礼】活动,一起开启掘金创作之路。
📒博客首页:何名取 的个人主页 - 文章 - 掘金 (juejin.cn)
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
❤️期待一起交流!
🙏作者水平很有限,如果发现错误,求告知,多谢!
🌺有问题可私信交流!!!
创建屏幕
前言
上节已经对Maroon in Trouble小游戏进行了简单介绍,介绍游戏的玩法时可以明确地知道此游戏有三个背景界面,分别是游戏的开始界面、游戏中界面和游戏结束界面。本节先介绍一下游戏文件的整体结构,然后对游戏的开始界面、游戏中界面和游戏结束界面分解并研究学习。
文件结构
Maroon in Trouble由资源文件、js逻辑和qml组件组成。
其中资源文件中包含audio游戏音效和gfx图片文件。
qml部分的主文件是maroon.qml文件。游戏的开始界面、游戏中界面和游戏结束界面分别是:
- NewGameScreen.qml
- GameCanvas.qml
- GameOverScreen.qml
游戏开始界面
从图中我们可以看到有背景图片、阳光、暗流、气泡、logo、小黄鱼和一个按钮。背景、logo和开始按钮都是静态地,不需要动画或者粒子系统。从水底向上浮动的气泡是粒子系统发射的,而在气泡中游动的小黄鱼使用的是循环的动画效果,在它周围笼罩它的气泡也是一样的。
上浮的气泡
其中从海底向上浮动的气泡在整个游戏过程中也是持续存在的,因此将发射气泡的粒子系统放置在主文件中。在maroon.qml中编写代码:
ParticleSystem {
id: particles
anchors.fill: parent
ImageParticle {
id: bubble
anchors.fill: parent
source: "content/gfx/catch.png"
opacity: 0.25
}
Wander {
xVariance: 25;
pace: 25;
}
Emitter {
width: parent.width
height: 150
anchors.bottom: parent.bottom
anchors.bottomMargin: 3
startTime: 15000
emitRate: 2
lifeSpan: 15000
acceleration: PointDirection{ y: -6; xVariation: 2; yVariation: 2 }
size: 24
sizeVariation: 16
}
}
这里的气泡发射系统对QML中粒子系统的使用比较完整,将粒子系统的四个组成全部用到了,包括ParticleSystem粒子系统、ImageParticle渲染器、Emitter发射器和Wander影响器。
游动的小黄鱼
接下来是小黄鱼的游动动画:
Image {
source: "gfx/logo-fish.png"
anchors.top: parent.top
SequentialAnimation on x {
loops: Animation.Infinite
NumberAnimation { from: x + 148; to: x + 25; duration: 2000; easing.type: Easing.InOutQuad }
NumberAnimation { from: x + 25; to: x + 148; duration: 1600; easing.type: Easing.InOutQuad }
}
SequentialAnimation on anchors.topMargin {
loops: Animation.Infinite
NumberAnimation { from: 100; to: 60; duration: 1600; easing.type: Easing.InOutQuad }
NumberAnimation { from: 60; to: 100; duration: 2000; easing.type: Easing.InOutQuad }
}
}
小黄鱼的游动使用的是顺序动画,改变图片的x和锚的位置即可实现斜向的循环运动。
气泡的动画与小黄鱼的游动基本类似,与小黄鱼的区别在于图片本身的宽度也会产生变化。
Image {
source: "gfx/logo-bubble.png"
anchors.top: parent.top
SequentialAnimation on x {
loops: Animation.Infinite
NumberAnimation { from: x + 140; to: x + 40; duration: 2000; easing.type: Easing.InOutQuad }
NumberAnimation { from: x + 40; to: x + 140; duration: 1600; easing.type: Easing.InOutQuad }
}
SequentialAnimation on anchors.topMargin {
loops: Animation.Infinite
NumberAnimation { from: 100; to: 60; duration: 1600; easing.type: Easing.InOutQuad }
NumberAnimation { from: 60; to: 100; duration: 2000; easing.type: Easing.InOutQuad }
}
SequentialAnimation on width {
loops: Animation.Infinite
NumberAnimation { from: 140; to: 160; duration: 1000; easing.type: Easing.InOutQuad }
NumberAnimation { from: 160; to: 140; duration: 800; easing.type: Easing.InOutQuad }
}
SequentialAnimation on height {
loops: Animation.Infinite
NumberAnimation { from: 150; to: 140; duration: 800; easing.type: Easing.InOutQuad }
NumberAnimation { from: 140; to: 150; duration: 1000; easing.type: Easing.InOutQuad }
}
}
此时的游戏开始界面就已经有了上浮的气泡,游动的小黄鱼了,另外还需要一些照到海底的阳光和涌动的暗流。
海底阳光与暗流
暗流分为上下交错的两部分,使用Row横向排列来布局两个wave波浪图片,这样做的意义在于将两张图片拼接起来,在将波浪做成动画效果时无缝衔接,不会有突然的断隔。
Row {
height: childrenRect.height
Image {
id: wave
y: 30
source:"content/gfx/wave.png"
}
Image {
y: 30
source:"content/gfx/wave.png"
}
NumberAnimation on x { from: 0; to: -(wave.width); duration: 16000; loops: Animation.Infinite }
SequentialAnimation on y {
loops: Animation.Infinite
NumberAnimation { from: y - 2; to: y + 2; duration: 1600; easing.type: Easing.InOutQuad }
NumberAnimation { from: y + 2; to: y - 2; duration: 1600; easing.type: Easing.InOutQuad }
}
}
Row {
opacity: 0.5
Image {
id: wave2
y: 25
source: "content/gfx/wave.png"
}
Image {
y: 25
source: "content/gfx/wave.png"
}
NumberAnimation on x { from: -(wave2.width); to: 0; duration: 32000; loops: Animation.Infinite }
SequentialAnimation on y {
loops: Animation.Infinite
NumberAnimation { from: y + 2; to: y - 2; duration: 1600; easing.type: Easing.InOutQuad }
NumberAnimation { from: y - 2; to: y + 2; duration: 1600; easing.type: Easing.InOutQuad }
}
}
阳光同样使用两层图片形成交错效果,不同于暗流,阳光定位在整个显示区域的顶部正中,使用旋转角度的动画来形成阳光照射的效果。
Image {
source: "content/gfx/sunlight.png"
opacity: 0.02
y: 0
anchors.horizontalCenter: parent.horizontalCenter
transformOrigin: Item.Top
SequentialAnimation on rotation {
loops: Animation.Infinite
NumberAnimation { from: -10; to: 10; duration: 8000; easing.type: Easing.InOutSine }
NumberAnimation { from: 10; to: -10; duration: 8000; easing.type: Easing.InOutSine }
}
}
Image {
source: "content/gfx/sunlight.png"
opacity: 0.04
y: 20
anchors.horizontalCenter: parent.horizontalCenter
transformOrigin: Item.Top
SequentialAnimation on rotation {
loops: Animation.Infinite
NumberAnimation { from: 10; to: -10; duration: 8000; easing.type: Easing.InOutSine }
NumberAnimation { from: -10; to: 10; duration: 8000; easing.type: Easing.InOutSine }
}
}
Image {
source: "content/gfx/grid.png"
opacity: 0.5
}
此时,整个开始界面的动态效果已经完全做好了,只需将其余的静态部件加入即可完成一个完整的游戏开始界面。