Qt是一个跨平台框架,通常用作图形工具包,它不仅创建CLI应用程序中非常有用。而且它也可以在三种主要的台式机操作系统以及移动操作系统(如Symbian,Nokia Belle,Meego Harmattan,MeeGo或BB10)以及嵌入式设备,Android(Necessitas)和iOS的端口上运行。现在我们为你提供了免费的试用版。
Qt组件推荐:
- QtitanRibbon| 下载试用: 遵循Microsoft Ribbon UI Paradigm for Qt技术的Ribbon UI组件,致力于为Windows、Linux和Mac OS X提供功能完整的Ribbon组件。
- QtitanChart | 下载试用 :是一个C ++库,代表一组控件,这些控件使您可以快速地为应用程序提供漂亮而丰富的图表。并且支持所有主要的桌面。
- QtitanNavigation | 下载试用 :模拟Microsoft Dynamics CRM-2016/Office 365导航界面和一组控件改善Qt.C ++应用程序用户体验的QtitanNavigation组件。
通过前两章的讲解(创建游戏画布和块,填充游戏画布),现在我们已经拥有了所有游戏组件,可以添加游戏逻辑了,该逻辑规定玩家如何与积木互动以及如何玩游戏,直到赢或输。
为此,我们将以下功能添加到samegame.js:
- handleClick(x,y)
- floodFill(xIdx,yIdx,type)
- shuffleDown()
- victoryCheck()
- floodMoveCheck(xIdx, yIdx, type)
由于这是关于QML的教程,而不是游戏设计的教程,因此我们将仅在下面进行讨论handleClick(),victoryCheck()因为它们直接与QML类型交互。请注意,尽管此处的游戏逻辑是用JavaScript编写的。
启用鼠标单击交互
为了更方便的JavaScript代码接口与QML类型,我们增加了叫做项目gameCanvas来samegame.qml。它将背景替换为包含块的项目。它还接受来自用户的鼠标输入。这是商品代码:
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: SameGame.handleClick(mouse.x, mouse.y)
}
}
gameCanvas项是棋盘的精确尺寸,并有一个分数属性和一个MouseArea来处理鼠标点击。块现在被创建为它的子项目,它的尺寸被用来确定棋盘的大小,这样应用程序就可以根据可用的屏幕尺寸进行缩放。由于它的尺寸被绑定到blockSize的倍数上,blockSize被移出了samegame.js,作为一个QML属性移到了samegame.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如果游戏结束,则更新值并显示“ Game Over”对话框。
“游戏结束”对话框是使用Dialog中定义的类型创建的Dialog.qml。这是Dialog.qml代码。注意如何通过功能和信号从脚本文件中强制使用它:
import QtQuick 2.0
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
}
我们为对话框指定z值100,以确保将其显示在其他组件的顶部。项目的默认z值为0。
色彩冲刺
如果所有块都具有相同的颜色,玩“同一个游戏”并没有什么乐趣,因此我们修改了createBlock()函数,samegame.js以便每次调用时随机创建不同类型的块(用于红色,绿色或蓝色)。Block.qml还进行了更改,以便每个块包含一个不同的图像,具体取决于其类型:
import QtQuick 2.0
Item {
id: block
property int type: 0
Image {
id: img
anchors.fill: parent
source: {
if (type == 0)
return "../shared/pics/redStone.png";
else if (type == 1)
return "../shared/pics/blueStone.png";
else
return "../shared/pics/greenStone.png";
}
}
}
工作游戏
现在我们有了一款可以正常运行的游戏!可以单击块,玩家可以得分,游戏可以结束(然后您可以开始一个新的)。这是到目前为止已完成的屏幕截图:
这是现在的samegame.qml样子:
import QtQuick 2.0
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: "../shared/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: 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专家,则可以在第一次迭代中编写这些内容,但是在本教程中,我们将在下一章节中进行讲解----您的应用程序将在此活跃起来!
====================================================
Qt技术交流群现已开通,QQ搜索群号“765444821”或者扫描下方二维码即可加入