5b57058a19ad00858062949d64f13af072e86850
[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 "content"
45
46 Rectangle {
47     id: root
48     width: 320; height: 480
49     property int acc: 0
50     property int menuDelay: 500
51
52     function loadPuzzle() {
53         if (gameCanvas.mode != "")
54             Logic.cleanUp();
55         Logic.startNewGame(gameCanvas,"puzzle","levels/level"+acc+".qml")
56     }
57     function nextPuzzle() {
58         acc = (acc + 1) % 10;
59         loadPuzzle();
60     }
61     Timer {
62         id: gameOverTimer
63         interval: 1500
64         running : gameCanvas.gameOver && gameCanvas.mode == "puzzle" //mode will be reset by cleanUp();
65         repeat  : false
66         onTriggered: {
67             Logic.cleanUp();
68             nextPuzzle();
69         }
70     }
71
72     Image {
73         source: "content/gfx/background.png"
74         anchors.fill: parent
75     }
76
77     GameArea {
78         id: gameCanvas
79         z: 1
80         width: parent.width
81
82         y: 20
83         height: parent.height - 64
84         backgroundVisible: root.state == "in-game"
85         onModeChanged: if (gameCanvas.mode != "puzzle") puzzleWon = false; //UI has stricter constraints on this variable than the game does
86         Age {
87             groups: ["redspots", "greenspots", "bluespots", "yellowspots"]
88             enabled: root.state == ""
89             system: gameCanvas.ps
90         }
91
92         onPuzzleLost: acc--;//So that nextPuzzle() reloads the current one
93
94     }
95
96     Item {
97         id: menu
98         z: 2
99         width: parent.width;
100         anchors.top: parent.top
101         anchors.bottom: bottomBar.top
102
103         LogoAnimation {
104             x: 64
105             y: 20
106             particleSystem: gameCanvas.ps
107             running: root.state == ""
108         }
109         Row {
110             x: 112
111             y: 20
112             Image { source: "content/gfx/logo-a.png" }
113             Image { source: "content/gfx/logo-m.png" }
114             Image { source: "content/gfx/logo-e.png" }
115         }
116
117         Column {
118             y: 100 + 40
119             spacing: 0
120
121             Button {
122                 height: 64
123                 width: root.width
124                 rotatedButton: true
125                 imgSrc: "content/gfx/but-game-1.png"
126                 onClicked: {
127                     if (root.state == "in-game")
128                         return //Prevent double clicking
129                     root.state = "in-game"
130                     gameCanvas.blockFile = "Block.qml"
131                     gameCanvas.background = "gfx/background.png"
132                     arcadeTimer.start();
133                 }
134                 //Emitted particles don't fade out, because ImageParticle is on the GameArea
135                 system: gameCanvas.ps
136                 group: "green"
137                 Timer {
138                     id: arcadeTimer
139                     interval: menuDelay
140                     running : false
141                     repeat  : false
142                     onTriggered: Logic.startNewGame(gameCanvas)
143                 }
144             }
145
146             Button {
147                 height: 64
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: menuDelay
164                     running : false
165                     repeat  : false
166                     onTriggered: Logic.startNewGame(gameCanvas, "multiplayer")
167                 }
168             }
169
170             Button {
171                 height: 64
172                 width: root.width
173                 rotatedButton: true
174                 imgSrc: "content/gfx/but-game-3.png"
175                 onClicked: {
176                     if (root.state == "in-game")
177                         return
178                     root.state = "in-game"
179                     gameCanvas.blockFile = "SimpleBlock.qml"
180                     gameCanvas.background = "gfx/background.png"
181                     endlessTimer.start();
182                 }
183                 system: gameCanvas.ps
184                 group: "blue"
185                 Timer {
186                     id: endlessTimer
187                     interval: menuDelay
188                     running : false
189                     repeat  : false
190                     onTriggered: Logic.startNewGame(gameCanvas, "endless")
191                 }
192             }
193
194             Button {
195                 height: 64
196                 width: root.width
197                 rotatedButton: true
198                 imgSrc: "content/gfx/but-game-4.png"
199                 group: "yellow"
200                 onClicked: {
201                     if (root.state == "in-game")
202                         return
203                     root.state = "in-game"
204                     gameCanvas.blockFile = "PuzzleBlock.qml"
205                     gameCanvas.background = "gfx/background.png"
206                     puzzleTimer.start();
207                 }
208                 Timer {
209                     id: puzzleTimer
210                     interval: menuDelay
211                     running : false
212                     repeat  : false
213                     onTriggered: loadPuzzle();
214                 }
215                 system: gameCanvas.ps
216             }
217         }
218     }
219
220     Image {
221         id: scoreBar
222         source: "content/gfx/bar.png"
223         width: parent.width
224         z: 6
225         y: -24
226         height: 24
227         Behavior on opacity { NumberAnimation {} }
228         Text {
229             id: arcadeScore
230             anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
231             text: '<font color="#f7d303">P1:</font> ' + gameCanvas.score
232             font.pixelSize: 14
233             textFormat: Text.StyledText
234             color: "white"
235             opacity: gameCanvas.mode == "arcade" ? 1 : 0
236             Behavior on opacity { NumberAnimation {} }
237         }
238         Text {
239             id: arcadeHighScore
240             anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
241             text: '<font color="#f7d303">Highscore:</font> ' + gameCanvas.highScore
242             font.pixelSize: 14
243             color: "white"
244             textFormat: Text.StyledText
245             opacity: gameCanvas.mode == "arcade" ? 1 : 0
246             Behavior on opacity { NumberAnimation {} }
247         }
248         Text {
249             id: p1Score
250             anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
251             text: '<font color="#f7d303">P1:</font> ' + gameCanvas.score
252             textFormat: Text.StyledText
253             font.pixelSize: 14
254             color: "white"
255             opacity: gameCanvas.mode == "multiplayer" ? 1 : 0
256             Behavior on opacity { NumberAnimation {} }
257         }
258         Text {
259             id: p2Score
260             anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
261             text: '<font color="#f7d303">P2:</font> ' + gameCanvas.score2
262             textFormat: Text.StyledText
263             font.pixelSize: 14
264             color: "white"
265             opacity: gameCanvas.mode == "multiplayer" ? 1 : 0
266             Behavior on opacity { NumberAnimation {} }
267             rotation: 180
268         }
269         Text {
270             id: puzzleMoves
271             anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
272             text: '<font color="#f7d303">Moves:</font> ' + gameCanvas.moves
273             textFormat: Text.StyledText
274             font.pixelSize: 14
275             color: "white"
276             opacity: gameCanvas.mode == "puzzle" ? 1 : 0
277             Behavior on opacity { NumberAnimation {} }
278         }
279         Text {
280             Image {
281                 source: "content/gfx/icon-time.png"
282                 x: -20
283             }
284             id: puzzleTime
285             anchors { topMargin: 3; top: parent.top; horizontalCenter: parent.horizontalCenter; horizontalCenterOffset: 20}
286             text: "00:00"
287             font.pixelSize: 14
288             color: "white"
289             opacity: gameCanvas.mode == "puzzle" ? 1 : 0
290             Behavior on opacity { NumberAnimation {} }
291             Timer {
292                 interval: 1000
293                 repeat: true
294                 running: gameCanvas.mode == "puzzle" && !gameCanvas.gameOver
295                 onTriggered: {
296                     var elapsed = Math.floor((new Date() - Logic.gameDuration)/ 1000.0);
297                     var mins = Math.floor(elapsed/60.0);
298                     var secs = (elapsed % 60);
299                     puzzleTime.text =  (mins < 10 ? "0" : "") + mins + ":" + (secs < 10 ? "0" : "") + secs;
300                 }
301             }
302         }
303         Text {
304             id: puzzleScore
305             anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
306             text: '<font color="#f7d303">Score:</font> ' + gameCanvas.score
307             textFormat: Text.StyledText
308             font.pixelSize: 14
309             color: "white"
310             opacity: gameCanvas.mode == "puzzle" ? 1 : 0
311             Behavior on opacity { NumberAnimation {} }
312         }
313     }
314
315     Image {
316         id: bottomBar
317         width: parent.width
318         height: 44
319         source: "content/gfx/bar.png"
320         y: parent.height - 44
321         z: 2
322         function selectButtons() {
323             menuButton.visible = (root.state == "in-game");
324             nextButton.visible = (root.state == "in-game");
325             againButton.visible = (root.state == "in-game");
326         }
327         Button {
328             id: quitButton
329             imgSrc: "content/gfx/but-quit.png"
330             onClicked: {Qt.quit(); }
331             anchors { left: parent.left; verticalCenter: parent.verticalCenter; leftMargin: 11 }
332         }
333         Button {
334             id: menuButton
335             imgSrc: "content/gfx/but-menu.png"
336             visible: false
337             onClicked: {root.state = ""; Logic.cleanUp(); gameCanvas.mode = ""}
338             anchors { left: quitButton.right; verticalCenter: parent.verticalCenter; leftMargin: 0 }
339         }
340         Button {
341             id: againButton
342             imgSrc: "content/gfx/but-game-new.png"
343             visible: false
344             opacity: gameCanvas.gameOver && (gameCanvas.mode == "arcade" || gameCanvas.mode == "multiplayer") ? 1 : 0
345             Behavior on opacity{ NumberAnimation {} }
346             onClicked: {if (gameCanvas.gameOver) Logic.startNewGame(gameCanvas, gameCanvas.mode);}
347             anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 11 }
348         }
349         Button {
350             id: nextButton
351             imgSrc: "content/gfx/but-puzzle-next.png"
352             visible: false
353             opacity: gameCanvas.puzzleWon ? 1 : 0
354             Behavior on opacity{ NumberAnimation {} }
355             onClicked: {if (gameCanvas.puzzleWon) nextPuzzle();}
356             anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 11 }
357         }
358     }
359
360     Connections {
361         target: root
362         onStateChanged: stateChangeAnim.running = true
363     }
364     SequentialAnimation {
365         id: stateChangeAnim
366         ParallelAnimation {
367             NumberAnimation { target: bottomBar; property: "y"; to: root.height; duration: menuDelay/2; easing.type: Easing.OutQuad }
368             NumberAnimation { target: scoreBar; property: "y"; to: -24; duration: menuDelay/2; easing.type: Easing.OutQuad }
369         }
370         ScriptAction { script: bottomBar.selectButtons(); }
371         ParallelAnimation {
372             NumberAnimation { target: bottomBar; property: "y"; to: root.height - 44; duration: menuDelay/2; easing.type: Easing.OutBounce}
373             NumberAnimation { target: scoreBar; property: "y"; to: root.state == "" ? -24 : 0; duration: menuDelay/2; easing.type: Easing.OutBounce}
374         }
375     }
376
377     states: [
378         State {
379             name: "in-game"
380             PropertyChanges {
381                 target: menu
382                 opacity: 0
383                 visible: false
384             }
385         }
386     ]
387
388     transitions: [
389         Transition {
390             NumberAnimation {properties: "x,y,opacity"}
391         }
392     ]
393
394     //"Debug mode"
395     focus: true
396     Keys.onAsteriskPressed: Logic.nuke();
397     Keys.onSpacePressed: gameCanvas.puzzleWon = true;
398 }