qml做的一个Memory Game 其中动画效果值得参考。
main.qml Code:
import QtQuick 1.1 import "Functions.js" as Script Rectangle { id: mainScreen width: 800 height: 600 Component.onCompleted: mainScreen.state = "MainMenu" /*Main Menu*/ Rectangle{ id: startGame width: parent.width height: parent.height anchors.left: parent.left color: "#08FC39" Text{ id: mainTitle text: "Memory Game" color: "#FF7417" font{bold: true; family: "Segoe UI Bold"; pointSize: 30} anchors{ top: parent.top topMargin: 200 horizontalCenter: parent.horizontalCenter } } Text{ id: txtStartGame text: "Start Game" anchors{ horizontalCenter: parent.horizontalCenter verticalCenter: parent.verticalCenter } color: "White" font{bold: true; family: "Segoe UI Bold"; pointSize: 15} MouseArea{ id: maStartGame anchors.fill: parent hoverEnabled: true onEntered: txtStartGame.color = "#6017FF" onExited: txtStartGame.color = "white" onClicked: { Script.randomPict(); mainScreen.state="StartGame" } } } Text{ id: exit text: "X" anchors{ top: parent.top right: parent.right rightMargin: 10 } font{bold: true; pointSize: 30} MouseArea{ anchors.fill: parent onClicked: Qt.quit() } } } /*------------------------------*/ /*StartGame*/ Text{ id: startGameTitle visible: false anchors{ top: mainScreen.top topMargin: 30 horizontalCenter: mainScreen.horizontalCenter } text: "Choose This Picture" color: "white" font{bold:true; family: "Segoe UI Bold"; pointSize: 20} } Image{ id: thePicture visible: false width: 70 height: 70 anchors{ left: startGameTitle.right leftMargin: 20 verticalCenter: startGameTitle.verticalCenter } source: "" } Flipable{ id:card1 width: 150 height: width visible: false x:-width y:100 enabled: false transform: Rotation { id: rot1 origin.x: card1.width/2 origin.y: 0 axis.x: 0; axis.y: 1; axis.z: 0; angle: 0 onAngleChanged: img1.source = "../../images/models/"+Script.getPict(0)+".jpg"; Behavior on angle {PropertyAnimation{}} } front: Rectangle { color: "#FAFF70" width: 150 height: width MouseArea { anchors.fill: parent; onClicked: { cekPict1.start(); } } } back: Image { id: img1 width: 150 height: width } } Flipable{ id:card2 width: 150 height: width visible: false x: mainScreen.width y: 100 enabled: false transform: Rotation { id: rot2 origin.x: card2.width/2 origin.y: 0 axis.x: 0; axis.y: 1; axis.z: 0; angle: 0 onAngleChanged: img2.source = "../../images/models/"+Script.getPict(1)+".jpg"; Behavior on angle {PropertyAnimation{}} } front: Rectangle { color: "#FAFF70" width: 150 height: width MouseArea { anchors.fill: parent; onClicked: { cekPict2.start(); } } } back: Image { id: img2 width: 150 height: width } } Flipable{ id:card3 width: 150 height: width visible: false x: -width y: mainScreen.height - width - 50 enabled: false transform: Rotation { id: rot3 origin.x: card3.width/2 origin.y: 0 axis.x: 0; axis.y: 1; axis.z: 0; angle: 0 onAngleChanged: img3.source = "../../images/models/"+Script.getPict(2)+".jpg"; Behavior on angle {PropertyAnimation{}} } front: Rectangle { color: "#FAFF70" width: 150 height: width MouseArea { anchors.fill: parent; onClicked: { cekPict3.start(); } } } back: Image { id: img3 width: 150 height: width } } Flipable{ id:card4 width: 150 height: width visible: false x: mainScreen.width y: mainScreen.height - width - 50 enabled: false transform: Rotation { id: rot4 origin.x: card4.width/2 origin.y: 0 axis.x: 0; axis.y: 1; axis.z: 0; angle: 0 onAngleChanged: img4.source = "../../images/models/"+Script.getPict(3)+".jpg"; Behavior on angle {PropertyAnimation{}} } front: Rectangle { color: "#FAFF70" width: 150 height: width MouseArea { anchors.fill: parent; onClicked: { cekPict4.start(); } } } back: Image { id: img4 width: 150 height: width } } /*------------------------------*/ /*End Game*/ Rectangle{ id: blackRect visible: false opacity: 0 color: "black" width: mainScreen.width height: mainScreen.height } Text{ id: blackRectText color: "#FF7417" visible: false anchors{ horizontalCenter: blackRect.horizontalCenter verticalCenter: blackRect.verticalCenter } font{bold:true; family: "Segoe UI Bold"; pointSize:50} } Text{ id: playAgain color: "white" visible: false text: "Play Again" anchors{ horizontalCenter: blackRect.horizontalCenter top: blackRectText.bottom topMargin: 20 } font{bold:true; family: "Segoe UI Bold"; pointSize:30} MouseArea{ anchors.fill: parent hoverEnabled: true; onEntered: playAgain.color = "#6017FF" onExited: playAgain.color = "white" onClicked: mainScreen.state = "MainMenu" } } /*------------------------------*/ states:[ State{ name: "MainMenu" PropertyChanges{ target: startGame width: mainScreen.width } PropertyChanges{ target: mainTitle visible: true } PropertyChanges{ target: blackRect visible: false } PropertyChanges{ target: blackRectText visible: false } PropertyChanges{ target: playAgain visible: false } PropertyChanges { target: thePicture visible: false } }, State{ name: "StartGame" PropertyChanges{ target: rot1 angle: 0 } PropertyChanges{ target: rot2 angle: 0 } PropertyChanges{ target: rot3 angle: 0 } PropertyChanges{ target: rot4 angle: 0 } PropertyChanges{ target: thePicture visible: false } PropertyChanges { target: blackRect visible: false } PropertyChanges { target: blackRectText visible: false } PropertyChanges { target: playAgain visible: false } PropertyChanges { target: startGame width: mainScreen.width } PropertyChanges { target: mainTitle visible: false } PropertyChanges { target: startGameTitle visible: true } PropertyChanges { target: txtStartGame visible: false } PropertyChanges{ target: maStartGame enabled: false } PropertyChanges { target: card4 visible: true x: 550 } PropertyChanges { target: card2 visible: true x: 550 } PropertyChanges { target: card3 visible: true x: 100 } PropertyChanges { target: card1 visible: true x: 100 } } ] transitions:[ Transition { from: "MainMenu" to: "StartGame" SequentialAnimation{ PropertyAnimation{ properties: "x" duration: 500 } PauseAnimation { duration: 200 } ParallelAnimation{ PropertyAnimation{target: rot1; property: "angle"; from:0; to: 180; duration: 1000} PropertyAnimation{target: rot2; property: "angle"; from:0; to: 180; duration: 1000} PropertyAnimation{target: rot3; property: "angle"; from:0; to: 180; duration: 1000} PropertyAnimation{target: rot4; property: "angle"; from:0; to: 180; duration: 1000} } PauseAnimation { duration: 5000 } ParallelAnimation{ PropertyAnimation{target: rot1; property: "angle"; from:180; to: 0; duration: 1000} PropertyAnimation{target: rot2; property: "angle"; from:180; to: 0; duration: 1000} PropertyAnimation{target: rot3; property: "angle"; from:180; to: 0; duration: 1000} PropertyAnimation{target: rot4; property: "angle"; from:180; to: 0; duration: 1000} } PauseAnimation { duration: 1000 } ScriptAction{ script: Script.randomAnimation(); } PauseAnimation { duration: 2000 } ScriptAction{ script: Script.randomAnimation(); } PauseAnimation { duration: 2000 } ScriptAction{ script: Script.randomAnimation(); } PauseAnimation { duration: 2000 } ScriptAction{ script: Script.randomAnimation(); } PauseAnimation { duration: 2000 } ScriptAction{ script: Script.randomAnimation(); } PauseAnimation { duration: 1000 } ScriptAction{ script: { card1.enabled = true; card2.enabled = true; card3.enabled = true; card4.enabled = true; thePicture.source = "../../images/models/"+Script.getRandPict()+".jpg"; thePicture.visible = true; } } } } ] ParallelAnimation{ id: anim1 PropertyAnimation{ target: card1 property: "x" to: card1.x==100?550:100 duration: 700 } PropertyAnimation{ target: card3 properties: "x" to: card3.x==100?550:100 duration: 700 } PropertyAnimation{ target: card2 properties: "x" to: card2.x==100?550:100 duration: 700 } PropertyAnimation{ target: card4 properties: "x" to: card4.x==100?550:100 duration: 700 } } ParallelAnimation{ id: anim2 PropertyAnimation{ target: card1 property: "y" to: card1.y==100?400:100 duration: 700 } PropertyAnimation{ target: card3 properties: "y" to: card3.y==100?400:100 duration: 700 } PropertyAnimation{ target: card2 properties: "y" to: card2.y==100?400:100 duration: 700 } PropertyAnimation{ target: card4 properties: "y" to: card4.y==100?400:100 duration: 700 } } ParallelAnimation{ id: anim3 NumberAnimation{ target: card2 property: "y" from: card2.y to: card2.y==100?400:100 duration: 700 } NumberAnimation{ target: card4 property: "y" from: card4.y to: card4.y==100?400:100 duration: 700 } } ParallelAnimation{ id: anim4 NumberAnimation{ target: card1 property: "y" from: card1.y to: card1.y==100?400:100 duration: 700 } NumberAnimation{ target: card3 property: "y" from: card3.y to: card3.y==100?400:100 duration: 700 } } ParallelAnimation{ id: anim5 NumberAnimation{ target: card1 property: "x" from: card1.x to: card1.x==100?550:100 duration: 700 } NumberAnimation{ target: card2 property: "x" from: card2.x to: card2.x==100?550:100 duration: 700 } } ParallelAnimation{ id: anim6 NumberAnimation{ target: card3 property: "x" from: card3.x to: card3.x==100?550:100 duration: 700 } NumberAnimation{ target: card4 property: "x" from: card4.x to: card4.x==100?550:100 duration: 700 } } SequentialAnimation{ id: cekPict1 PropertyAnimation{ target: rot1 property: "angle" to: 180 duration: 1000 } ScriptAction{ script:Script.cekPict(Script.getPict(0))===true?match.start():mismatch.start(); } } SequentialAnimation{ id: cekPict2 PropertyAnimation{ target: rot2 property: "angle" to: 180 duration: 1000 } ScriptAction{script: Script.cekPict(Script.getPict(1))===true?match.start():mismatch.start();} } SequentialAnimation{ id: cekPict3 PropertyAnimation{ target: rot3 property: "angle" to: 180 duration: 1000 } ScriptAction{script: Script.cekPict(Script.getPict(2))===true?match.start():mismatch.start();} } SequentialAnimation{ id: cekPict4 PropertyAnimation{ target: rot4 property: "angle" to: 180 duration: 1000 } ScriptAction{script: Script.cekPict(Script.getPict(3))===true?match.start():mismatch.start();} } SequentialAnimation{ id: match ScriptAction{ script: { card1.enabled = false; card2.enabled = false; card3.enabled = false; card4.enabled = false; blackRect.visible = true; blackRectText.text = "You Win!"; } } PropertyAnimation { target: blackRect property: "opacity" from: 0 to: 0.5 duration: 1000 } PauseAnimation { duration: 500 } ScriptAction{ script: { blackRectText.visible = true; playAgain.visible = true; playAgain.enabled = true; } } } SequentialAnimation{ id: mismatch ScriptAction{ script: { card1.enabled = false; card2.enabled = false; card3.enabled = false; card4.enabled = false; blackRect.visible = true; blackRectText.text = "You Lose!"; } } PropertyAnimation { target: blackRect property: "opacity" from: 0 to: 0.5 duration: 1000 } PauseAnimation { duration: 500 } ScriptAction{ script: { blackRectText.visible = true; playAgain.visible = true; } } } }
Functions.js Code:
var pict = new Array(0,0,0,0); var randPict = 0; function randomPict(){ var i=0; var idx = 0; for(i=0;i<4;i++){ if(i==0) { idx = Math.ceil(Math.random()*12); pict[i] = idx; } else { var flag = 0; while(flag == 0) { var a = 0; idx = Math.ceil(Math.random()*12); for(var j=0;j<i;j++) { if(pict[j] == idx) { a = 1; break; } } if(a==0) { pict[i] = idx; flag = 1; } } } } } function getRandPict(){ var idx = Math.ceil(Math.random()*4)-1; randPict = pict[idx]; return randPict; } function getPict(idx){ return pict[idx]; } function randomAnimation(){ var flag = true; while(flag) { switch(Math.ceil(Math.random()*6)) { case 1: if(card1.y == card3.y && card2.y == card4.y) { anim1.start(); flag = false; } break; case 2: if(card1.x == card3.x && card2.x == card4.x) { anim2.start(); flag = false; } break; case 3: if(card2.x == card4.x) { anim3.start(); flag = false; } break; case 4: if(card1.x == card3.x) { anim4.start(); flag = false; } break; case 5: if(card1.y == card2.y) { anim5.start(); flag = false; } break; case 6: if(card3.y == card4.y) { anim6.start(); flag = false; } break; } } } function cekPict(a) { if(a === randPict)return true; else return false; }