Qt开发案例实战:QML高级教程3-实施游戏逻辑

现在我们已经拥有了所有游戏组件,可以添加游戏逻辑了,该逻辑规定玩家如何与积木互动以及如何玩游戏,直到赢或输。

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”对话框。

import QtQuick 2.0Rectangle {    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.0Item {    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";        }    }}

工作游戏

现在我们有了一款可以正常运行的游戏!可以单击块,玩家可以得分,游戏可以结束(然后您可以开始一个新的)。这是到目前为止已完成的屏幕截图:

Qt开发案例实战:QML高级教程3-实施游戏逻辑

这是现在的samegame.qml样子:

import QtQuick 2.0import "samegame.js" as SameGameRectangle {    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正版授权的朋友,欢迎咨询官方客服

Qt技术交流群现已开通,QQ搜索“765444821或者扫描下方二维码即可加入

Qt开发案例实战:QML高级教程3-实施游戏逻辑

标签:

声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2021年1月20日
下一篇 2021年1月20日

相关推荐

发表回复

登录后才能评论