Refactoring samegame
[profile/ivi/qtdeclarative.git] / examples / demos / samegame / samegame.qml
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the examples of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:BSD$
9 ** You may use this file under the terms of the BSD license as follows:
10 **
11 ** "Redistribution and use in source and binary forms, with or without
12 ** modification, are permitted provided that the following conditions are
13 ** met:
14 **   * Redistributions of source code must retain the above copyright
15 **     notice, this list of conditions and the following disclaimer.
16 **   * Redistributions in binary form must reproduce the above copyright
17 **     notice, this list of conditions and the following disclaimer in
18 **     the documentation and/or other materials provided with the
19 **     distribution.
20 **   * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
21 **     of its contributors may be used to endorse or promote products derived
22 **     from this software without specific prior written permission.
23 **
24 **
25 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40
41 import QtQuick 2.0
42 import QtQuick.Particles 2.0
43 import "content/samegame.js" as Logic
44 import "settings.js" as Settings
45 import "content"
46
47 Rectangle {
48     id: root
49     width: 320; height: 480
50     property int acc: 0
51
52
53     function loadPuzzle() {
54         if (gameCanvas.mode != "")
55             Logic.cleanUp();
56         Logic.startNewGame(gameCanvas,"puzzle","levels/level"+acc+".qml")
57     }
58     function nextPuzzle() {
59         acc = (acc + 1) % 10;
60         loadPuzzle();
61     }
62     Timer {
63         id: gameOverTimer
64         interval: 1500
65         running : gameCanvas.gameOver && gameCanvas.mode == "puzzle" //mode will be reset by cleanUp();
66         repeat  : false
67         onTriggered: {
68             Logic.cleanUp();
69             nextPuzzle();
70         }
71     }
72
73     Image {
74         source: "content/gfx/background.png"
75         anchors.fill: parent
76     }
77
78     GameArea {
79         id: gameCanvas
80         z: 1
81         y: Settings.headerHeight
82
83         width: parent.width
84         height: parent.height - Settings.headerHeight - Settings.footerHeight
85
86         backgroundVisible: root.state == "in-game"
87         onModeChanged: if (gameCanvas.mode != "puzzle") puzzleWon = false; //UI has stricter constraints on this variable than the game does
88         Age {
89             groups: ["redspots", "greenspots", "bluespots", "yellowspots"]
90             enabled: root.state == ""
91             system: gameCanvas.ps
92         }
93
94         onPuzzleLost: acc--;//So that nextPuzzle() reloads the current one
95
96     }
97
98     Item {
99         id: menu
100         z: 2
101         width: parent.width;
102         anchors.top: parent.top
103         anchors.bottom: bottomBar.top
104
105         LogoAnimation {
106             x: 64
107             y: Settings.headerHeight
108             particleSystem: gameCanvas.ps
109             running: root.state == ""
110         }
111         Row {
112             x: 112
113             y: 20
114             Image { source: "content/gfx/logo-a.png" }
115             Image { source: "content/gfx/logo-m.png" }
116             Image { source: "content/gfx/logo-e.png" }
117         }
118
119         Column {
120             y: 100 + 40
121             spacing: Settings.menuButtonSpacing
122
123             Button {
124                 width: root.width
125                 rotatedButton: true
126                 imgSrc: "content/gfx/but-game-1.png"
127                 onClicked: {
128                     if (root.state == "in-game")
129                         return //Prevent double clicking
130                     root.state = "in-game"
131                     gameCanvas.blockFile = "Block.qml"
132                     gameCanvas.background = "gfx/background.png"
133                     arcadeTimer.start();
134                 }
135                 //Emitted particles don't fade out, because ImageParticle is on the GameArea
136                 system: gameCanvas.ps
137                 group: "green"
138                 Timer {
139                     id: arcadeTimer
140                     interval: Settings.menuDelay
141                     running : false
142                     repeat  : false
143                     onTriggered: Logic.startNewGame(gameCanvas)
144                 }
145             }
146
147             Button {
148                 width: root.width
149                 rotatedButton: true
150                 imgSrc: "content/gfx/but-game-2.png"
151                 onClicked: {
152                     if (root.state == "in-game")
153                         return
154                     root.state = "in-game"
155                     gameCanvas.blockFile = "Block.qml"
156                     gameCanvas.background = "gfx/background.png"
157                     twopTimer.start();
158                 }
159                 system: gameCanvas.ps
160                 group: "green"
161                 Timer {
162                     id: twopTimer
163                     interval: Settings.menuDelay
164                     running : false
165                     repeat  : false
166                     onTriggered: Logic.startNewGame(gameCanvas, "multiplayer")
167                 }
168             }
169
170             Button {
171                 width: root.width
172                 rotatedButton: true
173                 imgSrc: "content/gfx/but-game-3.png"
174                 onClicked: {
175                     if (root.state == "in-game")
176                         return
177                     root.state = "in-game"
178                     gameCanvas.blockFile = "SimpleBlock.qml"
179                     gameCanvas.background = "gfx/background.png"
180                     endlessTimer.start();
181                 }
182                 system: gameCanvas.ps
183                 group: "blue"
184                 Timer {
185                     id: endlessTimer
186                     interval: Settings.menuDelay
187                     running : false
188                     repeat  : false
189                     onTriggered: Logic.startNewGame(gameCanvas, "endless")
190                 }
191             }
192
193             Button {
194                 width: root.width
195                 rotatedButton: true
196                 imgSrc: "content/gfx/but-game-4.png"
197                 group: "yellow"
198                 onClicked: {
199                     if (root.state == "in-game")
200                         return
201                     root.state = "in-game"
202                     gameCanvas.blockFile = "PuzzleBlock.qml"
203                     gameCanvas.background = "gfx/background.png"
204                     puzzleTimer.start();
205                 }
206                 Timer {
207                     id: puzzleTimer
208                     interval: Settings.menuDelay
209                     running : false
210                     repeat  : false
211                     onTriggered: loadPuzzle();
212                 }
213                 system: gameCanvas.ps
214             }
215         }
216     }
217
218     Image {
219         id: scoreBar
220         source: "content/gfx/bar.png"
221         width: parent.width
222         z: 6
223         y: -Settings.headerHeight
224         height: Settings.headerHeight
225         Behavior on opacity { NumberAnimation {} }
226         SamegameText {
227             id: arcadeScore
228             anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
229             text: '<font color="#f7d303">P1:</font> ' + gameCanvas.score
230             font.pixelSize: Settings.fontPixelSize
231             textFormat: Text.StyledText
232             color: "white"
233             opacity: gameCanvas.mode == "arcade" ? 1 : 0
234             Behavior on opacity { NumberAnimation {} }
235         }
236         SamegameText {
237             id: arcadeHighScore
238             anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
239             text: '<font color="#f7d303">Highscore:</font> ' + gameCanvas.highScore
240             opacity: gameCanvas.mode == "arcade" ? 1 : 0
241         }
242         SamegameText {
243             id: p1Score
244             anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
245             text: '<font color="#f7d303">P1:</font> ' + gameCanvas.score
246             opacity: gameCanvas.mode == "multiplayer" ? 1 : 0
247         }
248         SamegameText {
249             id: p2Score
250             anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
251             text: '<font color="#f7d303">P2:</font> ' + gameCanvas.score2
252             opacity: gameCanvas.mode == "multiplayer" ? 1 : 0
253             rotation: 180
254         }
255         SamegameText {
256             id: puzzleMoves
257             anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
258             text: '<font color="#f7d303">Moves:</font> ' + gameCanvas.moves
259             opacity: gameCanvas.mode == "puzzle" ? 1 : 0
260         }
261         SamegameText {
262             Image {
263                 source: "content/gfx/icon-time.png"
264                 x: -20
265             }
266             id: puzzleTime
267             anchors { topMargin: 3; top: parent.top; horizontalCenter: parent.horizontalCenter; horizontalCenterOffset: 20}
268             text: "00:00"
269             opacity: gameCanvas.mode == "puzzle" ? 1 : 0
270             Timer {
271                 interval: 1000
272                 repeat: true
273                 running: gameCanvas.mode == "puzzle" && !gameCanvas.gameOver
274                 onTriggered: {
275                     var elapsed = Math.floor((new Date() - Logic.gameDuration)/ 1000.0);
276                     var mins = Math.floor(elapsed/60.0);
277                     var secs = (elapsed % 60);
278                     puzzleTime.text =  (mins < 10 ? "0" : "") + mins + ":" + (secs < 10 ? "0" : "") + secs;
279                 }
280             }
281         }
282         SamegameText {
283             id: puzzleScore
284             anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
285             text: '<font color="#f7d303">Score:</font> ' + gameCanvas.score
286             opacity: gameCanvas.mode == "puzzle" ? 1 : 0
287         }
288     }
289
290     Image {
291         id: bottomBar
292         width: parent.width
293         height: Settings.footerHeight
294         source: "content/gfx/bar.png"
295         y: parent.height - Settings.footerHeight;
296         z: 2
297         Button {
298             id: quitButton
299             height: Settings.toolButtonHeight
300             imgSrc: "content/gfx/but-quit.png"
301             onClicked: {Qt.quit(); }
302             anchors { left: parent.left; verticalCenter: parent.verticalCenter; leftMargin: 11 }
303         }
304         Button {
305             id: menuButton
306             height: Settings.toolButtonHeight
307             imgSrc: "content/gfx/but-menu.png"
308             visible: (root.state == "in-game");
309             onClicked: {root.state = ""; Logic.cleanUp(); gameCanvas.mode = ""}
310             anchors { left: quitButton.right; verticalCenter: parent.verticalCenter; leftMargin: 0 }
311         }
312         Button {
313             id: againButton
314             height: Settings.toolButtonHeight
315             imgSrc: "content/gfx/but-game-new.png"
316             visible: (root.state == "in-game");
317             opacity: gameCanvas.gameOver && (gameCanvas.mode == "arcade" || gameCanvas.mode == "multiplayer")
318             Behavior on opacity{ NumberAnimation {} }
319             onClicked: {if (gameCanvas.gameOver) { Logic.startNewGame(gameCanvas, gameCanvas.mode);}}
320             anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 11 }
321         }
322         Button {
323             id: nextButton
324             height: Settings.toolButtonHeight
325             imgSrc: "content/gfx/but-puzzle-next.png"
326             visible: (root.state == "in-game") && gameCanvas.mode == "puzzle" && gameCanvas.puzzleWon
327             opacity: gameCanvas.puzzleWon ? 1 : 0
328             Behavior on opacity{ NumberAnimation {} }
329             onClicked: {if (gameCanvas.puzzleWon) nextPuzzle();}
330             anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 11 }
331         }
332     }
333
334     Connections {
335         target: root
336         onStateChanged: stateChangeAnim.running = true
337     }
338     SequentialAnimation {
339         id: stateChangeAnim
340         ParallelAnimation {
341             NumberAnimation { target: bottomBar; property: "y"; to: root.height; duration: Settings.menuDelay/2; easing.type: Easing.OutQuad }
342             NumberAnimation { target: scoreBar; property: "y"; to: -Settings.headerHeight; duration: Settings.menuDelay/2; easing.type: Easing.OutQuad }
343         }
344         ParallelAnimation {
345             NumberAnimation { target: bottomBar; property: "y"; to: root.height - Settings.footerHeight; duration: Settings.menuDelay/2; easing.type: Easing.OutBounce}
346             NumberAnimation { target: scoreBar; property: "y"; to: root.state == "" ? -Settings.headerHeight : 0; duration: Settings.menuDelay/2; easing.type: Easing.OutBounce}
347         }
348     }
349
350     states: [
351         State {
352             name: "in-game"
353             PropertyChanges {
354                 target: menu
355                 opacity: 0
356                 visible: false
357             }
358         }
359     ]
360
361     transitions: [
362         Transition {
363             NumberAnimation {properties: "x,y,opacity"}
364         }
365     ]
366
367     //"Debug mode"
368     focus: true
369     Keys.onAsteriskPressed: Logic.nuke();
370     Keys.onSpacePressed: gameCanvas.puzzleWon = true;
371 }