QML高级教程3 - 实现游戏逻辑
制作可玩游戏
现在我们已经拥有了所有的游戏组件,我们可以添加处理玩家如何与方块交互以及游戏如何赢得或输掉的条件逻辑。
为此,我们已在samegame.js
中添加了以下函数
handleClick(x,y)
floodFill(xIdx,yIdx,type)
shuffleDown()
victoryCheck()
floodMoveCheck(xIdx, yIdx, type)
由于这是一个有关QML而不是游戏设计的教程,以下只讨论handleClick()
和victoryCheck()
,因为它们直接与QML类型交互。请注意,尽管这里的游戏逻辑是用JavaScript编写的,但它本可以用C++编写然后暴露给QML。
启用鼠标点击交互
为了使JavaScript代码更容易与QML类型交互,我们在samegame.qml
中添加了一个名为gameCanvas
的Item。它替换了作为包含方块的背景的Item。它还接受用户的鼠标输入。以下是该项代码
Item { id: gameCanvas property int score: 0 property int blockSize: 40 width: parent.width - (parent.width % blockSize) height: parent.height - (parent.height % blockSize) anchors.centerIn: parent MouseArea { anchors.fill: parent onClicked: (mouse)=> SameGame.handleClick(mouse.x, mouse.y) } }
gameCanvas
项恰好与棋盘大小相同,并且具有score
属性和一个MouseArea来处理鼠标点击。方块现在作为其子项创建,并使用其尺寸来确定棋盘大小,以便应用程序缩放到屏幕大小。由于其大小绑定到blockSize
的倍数,因此将blockSize
从samegame.js
移动到samegame.qml
中作为QML属性。注意,它仍然可以从脚本中访问。
当点击时,MouseArea会调用samegame.js
中的handleClick()
,以确定玩家的点击是否会导致删除任何方块,并在必要时更新gameCanvas.score
。以下是handleClick()
函数
function handleClick(xPos, yPos) { var column = Math.floor(xPos / gameCanvas.blockSize); var row = Math.floor(yPos / gameCanvas.blockSize); if (column >= maxColumn || column < 0 || row >= maxRow || row < 0) return; if (board[index(column, row)] == null) return; //If it's a valid block, remove it and all connected (does nothing if it's not connected) floodFill(column, row, -1); if (fillFound <= 0) return; gameCanvas.score += (fillFound - 1) * (fillFound - 1); shuffleDown(); victoryCheck(); }
请注意,如果score
在samegame.js
文件中是全局变量,您就无法绑定它。您只能绑定到QML属性。
更新分数
当玩家点击一个方块并触发handleClick()
时,handleClick()
也会调用victoryCheck()
来更新分数并检查玩家是否完成了游戏。以下是victoryCheck()
代码
function victoryCheck() { //Award bonus points if no blocks left var deservesBonus = true; for (var column = maxColumn - 1; column >= 0; column--) if (board[index(column, maxRow - 1)] != null) deservesBonus = false; if (deservesBonus) gameCanvas.score += 500; //Check whether game has finished if (deservesBonus || !(floodMoveCheck(0, maxRow - 1, -1))) dialog.show("Game Over. Your score is " + gameCanvas.score); }
这更新了gameCanvas.score
值,并在游戏结束时显示“游戏结束”对话框。
游戏结束对话框是使用在Dialog.qml
中定义的Dialog
类型创建的。以下是Dialog.qml
的代码。注意它是如何被设计成可以通过脚本文件中的函数和信号使用命令式方式的。
import QtQuick Rectangle { id: container function show(text) { dialogText.text = text; container.opacity = 1; } function hide() { container.opacity = 0; } width: dialogText.width + 20 height: dialogText.height + 20 opacity: 0 Text { id: dialogText anchors.centerIn: parent text: "" } MouseArea { anchors.fill: parent onClicked: hide(); } }
这是它在主samegame.qml
文件中的用法。
Dialog { id: dialog anchors.centerIn: parent z: 100 }
我们给对话框赋予了一个
一点色彩
如果所有方块都是相同的颜色,那么玩同样的游戏不是很有趣。因此,我们已经修改了
import QtQuick Item { id: block property int type: 0 Image { id: img anchors.fill: parent source: { if (type == 0) return "pics/redStone.png"; else if (type == 1) return "pics/blueStone.png"; else return "pics/greenStone.png"; } } }
一个有效的游戏
现在我们已经有一个有效的游戏了!方块可以被点击,玩家可以获得分数,游戏可以结束(然后您可以开始一个新游戏)。以下是到目前为止所完成的内容的截图
这是现在的
import QtQuick import "samegame.js" as SameGame Rectangle { id: screen width: 490; height: 720 SystemPalette { id: activePalette } Item { width: parent.width anchors { top: parent.top; bottom: toolBar.top } Image { id: background anchors.fill: parent source: "pics/background.jpg" fillMode: Image.PreserveAspectCrop } Item { id: gameCanvas property int score: 0 property int blockSize: 40 width: parent.width - (parent.width % blockSize) height: parent.height - (parent.height % blockSize) anchors.centerIn: parent MouseArea { anchors.fill: parent onClicked: (mouse)=> SameGame.handleClick(mouse.x, mouse.y) } } } Dialog { id: dialog anchors.centerIn: parent z: 100 } Rectangle { id: toolBar width: parent.width; height: 30 color: activePalette.window anchors.bottom: screen.bottom Button { anchors { left: parent.left; verticalCenter: parent.verticalCenter } text: "New Game" onClicked: SameGame.startNewGame() } Text { id: score anchors { right: parent.right; verticalCenter: parent.verticalCenter } text: "Score: Who knows?" } } }
游戏正在运行,但目前有点无聊。平滑的动画转换在哪里?高分在哪里?如果您是一位QML专家,您可以在首次迭代中写入这些内容,但在本教程中,这些内容被保存到了下一章——此时您的应用程序变得生动起来!
© 2024 Qt公司 Ltd. 所包含的文档贡献是各自所有者的版权。此处提供的文档根据自由软件基金会发布的版本1.3的GNU自由文档许可证的条款进行授权。Qt及其标志是芬兰和/或其他国家的Qt公司的商标。所有其他商标都是其各自所有者的财产。