Juicy Squash - Match-3 Game
import Felgo 3.0
import QtQuick 2.0
import "../game"
import "../ui"
SceneBase {
id: scene
width: 320
height: 480
property int score
property double juicyMeterPercentage
property int remainingTime
property alias overlayText: overlays
property alias gameSound: gameSoundItem
property bool vPlayMsgBox: false
signal highscoreClicked()
signal reportScore(int score)
onBackButtonPressed: backPressed()
EntityManager {
id: entityManager
entityContainer: gameArea
poolingEnabled: true
dynamicCreationEntityList: [
Qt.resolvedUrl("../game/Block.qml")
]
}
BackgroundImage {
source: "../../assets/img/JuicyBackground.png"
anchors.centerIn: scene.gameWindowAnchorItem
}
BackgroundMusic {
source: "../../assets/snd/POL-coconut-land-short.wav"
autoPlay: true
}
GameSound {
id: gameSoundItem
}
JuicyMeter {
percentage: scene.juicyMeterPercentage
anchors.centerIn: gameArea
width: gameArea.width+36
height: gameArea.height
onJuicyMeterFull: {
overlays.showOverload()
whiteScreen.flash()
}
}
Image {
id: grid
source: "../../assets/img/Grid.png"
width: 258
height: 378
anchors.horizontalCenter: scene.horizontalCenter
anchors.bottom: scene.bottom
anchors.bottomMargin: 92
}
Image {
id: filledGrid
source: "../../assets/img/GridFull.png"
width: 258
height: 378
anchors.horizontalCenter: scene.horizontalCenter
anchors.bottom: scene.bottom
anchors.bottomMargin: 92
opacity: 1
Behavior on opacity {
PropertyAnimation { duration: 500 }
}
}
GameArea {
id: gameArea
anchors.horizontalCenter: scene.horizontalCenter
anchors.verticalCenter: grid.verticalCenter
blockSize: 30
onGameOver: { currentGameEnded() }
onInitFinished: {
whiteScreen.stopLoading()
scene.score = 0
scene.juicyMeterPercentage = 0
scene.remainingTime = 120
filledGrid.opacity = 0
gameTimer.start()
gAnalytics.logEvent("Game Event", "New Game Initialized")
}
opacity: filledGrid.opacity == 1 ? 0 : 1
}
Image {
id: juicyLogo
source: "../../assets/img/JuicySquashLogo.png"
width: 119
height: 59
anchors.horizontalCenter: scene.horizontalCenter
anchors.bottom: scene.bottom
anchors.bottomMargin: 35
}
Text {
font.family: gameFont.name
font.pixelSize: 12
color: "red"
text: scene.score
anchors.horizontalCenter: parent.horizontalCenter
y: 446
MouseArea {
anchors.centerIn: parent
width: 150
height: parent.height + 5
onClicked: highscoreClicked()
}
}
Image {
width: 80
height: 46
source: "../../assets/img/TimeLeft.png"
anchors.right: scene.gameWindowAnchorItem.right
anchors.top: juicyLogo.top
anchors.topMargin: juicyLogo.height / 2
Text {
font.family: gameFont.name
font.pixelSize: 12
color: "red"
text: remainingTime + " s"
y: 25
x: 15
width: 80 - 15
horizontalAlignment: Text.AlignHCenter
}
enabled: opacity == 1
visible: opacity > 0
opacity: filledGrid.opacity > 0.5 ? 0 : 1
Behavior on opacity {
PropertyAnimation { duration: 200 }
}
}
Timer {
id: gameTimer
repeat: true
interval: 1000
onTriggered: {
if(scene.remainingTime > 0)
scene.remainingTime--
else if(!gameArea.fieldLocked) {
currentGameEnded()
}
}
}
TitleWindow {
id: titleWindow
y: 25
opacity: 1
anchors.horizontalCenter: scene.horizontalCenter
onStartClicked: scene.startGame()
onHighscoreClicked: scene.highscoreClicked()
onCreditsClicked: {
gAnalytics.logEvent("User Action", "Open Credits");
titleWindow.hide(); creditsWindow.show()
}
onVplayClicked: {
gAnalytics.logEvent("User Action", "Felgo Clicked", "Title Window")
vPlayMsgBox = true
nativeUtils.displayMessageBox(qsTr("Felgo"),
qsTr("This game is built with Felgo. The source code is available in the free Felgo SDK - so you can build your own match-3 game in minutes! Visit Felgo.net now?"), 2)
}
}
GameOverWindow {
id: gameOverWindow
y: 90
opacity: 0
anchors.horizontalCenter: scene.horizontalCenter
onNewGameClicked: scene.startGame()
onBackClicked: { openTitleWindow() }
}
CreditsWindow {
id: creditsWindow
y: 90
opacity: 0
anchors.horizontalCenter: scene.horizontalCenter
onBackClicked: { openTitleWindow() }
onVplayClicked: {
gAnalytics.logEvent("User Action", "Open Felgo Match-3 Url", "Credits Window")
nativeUtils.openUrl("https://felgo.com/doc/felgo-demos-match-3-example/")
}
}
Image {
width: 52
height: 45
source: "../../assets/img/HomeButton.png"
MouseArea {
anchors.fill: parent
onClicked: backButtonPressed()
}
x: 5
y: 432
visible: opacity > 0
enabled: opacity == 1
opacity: titleWindow.opacity > 0.5 ? 0 : 1
Behavior on opacity {
PropertyAnimation { duration: 200 }
}
}
Rectangle {
id: whiteScreen
anchors.fill: gameArea
anchors.centerIn: gameArea
color: "white"
opacity: 0
visible: opacity > 0
enabled: opacity > 0
SequentialAnimation {
id: flashAnimation
NumberAnimation {
target: whiteScreen
property: "opacity"
to: 1
duration: 300
}
NumberAnimation {
target: whiteScreen
property: "opacity"
from: 1
to: 0
duration: 700
}
}
SequentialAnimation {
id: loadingAnimation
loops: Animation.Infinite
NumberAnimation {
target: whiteScreen
property: "opacity"
to: 1
duration: 400
}
NumberAnimation {
target: whiteScreen
property: "opacity"
from: 1
to: 0.8
duration: 1000
}
}
Text {
id: loadingText
font.family: gameFont.name
font.pixelSize: 12
color: "red"
text: "preparing fruits"
anchors.centerIn: parent
opacity: 0
Behavior on opacity {
PropertyAnimation { duration: 400 }
}
}
function flash() {
loadingText.opacity = 0
loadingAnimation.stop()
flashAnimation.stop()
flashAnimation.start()
}
function startLoading() {
loadingAnimation.start()
loadingText.opacity = 1
}
function stopLoading() {
flash()
}
}
Overlays {
id: overlays
y: 190
onOverloadTextDisappeared: {
scene.juicyMeterPercentage = 0
gameTimer.stop()
gameArea.removeAllBlocks()
whiteScreen.flash()
scene.remainingTime += 60
gameTimer.start()
}
}
Connections {
target: nativeUtils
onMessageBoxFinished: {
if(!accepted) {
gAnalytics.logEvent("User Action", "Message Box Declined")
vPlayMsgBox = false
if(!titleWindow.visible && !gameTimer.running)
gameTimer.start()
return
}
if(vPlayMsgBox) {
vPlayMsgBox = false
gAnalytics.logEvent("User Action", "Open Felgo Match-3 Url", "Title Window")
nativeUtils.openUrl("https://felgo.com/doc/felgo-demos-match-3-example/")
}
else if(!titleWindow.visible) {
gAnalytics.logEvent("User Action", "Abort Running Game")
if(scene.score > 0)
currentGameEnded()
else
openTitleWindow()
}
else {
gAnalytics.logEvent("User Action", "Quit Application")
Qt.quit()
}
}
}
Timer {
id: initTimer
interval: 400
onTriggered: {
gameArea.initializeField()
}
}
function openTitleWindow() {
filledGrid.opacity = 1
scene.juicyMeterPercentage = 0
gameTimer.stop()
creditsWindow.hide()
gameOverWindow.hide()
titleWindow.show()
gAnalytics.logEvent("User Action", "Open Title Window")
}
function currentGameEnded() {
gAnalytics.logEvent("Game Event", "Game Ended")
gameArea.gameEnded = true
gameOverWindow.show()
gameTimer.stop()
scene.reportScore(scene.score)
}
function startGame() {
titleWindow.hide()
gameOverWindow.hide()
creditsWindow.hide()
whiteScreen.startLoading()
initTimer.start()
gAnalytics.logEvent("User Action", "Start New Game")
}
function backPressed() {
if(titleWindow.visible) {
nativeUtils.displayMessageBox("Really quit the game?", "", 2)
}
else if(creditsWindow.visible) {
openTitleWindow()
}
else if(gameOverWindow.visible) {
openTitleWindow()
}
else {
if(gameTimer.running)
gameTimer.stop()
nativeUtils.displayMessageBox("Abort current game?", "", 2)