This patch cleans up the example and makes it more customizeable by adding a setting file. Also a bug has been fixed, where the "New game" button could not been clicked.
Change-Id: Ia397258721dfcf4900e3ed1e176a257eccfad354
Reviewed-by: Alan Alpert (RIM) <aalpert@rim.com>
import QtQuick 2.0
import QtQuick.Particles 2.0
+import "../settings.js" as Settings
+
Emitter {
property Item block: parent
velocity: TargetDirection{targetX: block.width/2; targetY: block.height/2; magnitude: -40; magnitudeVariation: 40}
lifeSpan: 700; lifeSpanVariation: 100
emitRate: 1000
maximumEmitted: 100 //only fires 0.1s bursts (still 2x old number)
- size: 28
- endSize: 14
+ size: Settings.blockSize * 0.85
+ endSize: Settings.blockSize * 0.85 /2
}
property alias group: emitter.group
signal clicked
property bool rotatedButton: false
- //Defaults, feel free to override
+
width: image.width
- height: image.height
+ height: image.sourceSize.height
Image {
id: image
- anchors.centerIn: parent
+ height: parent.height
+ width: height/sourceSize.height * sourceSize.width
+
+ anchors.horizontalCenter: parent.horizontalCenter
rotation: rotatedButton ? ((Math.random() * 3 + 2) * (Math.random() <= 0.5 ? -1 : 1)) : 0
MenuEmitter {
id: emitter
property int score: 0
property int highScore: 0
property int moves: 0
- property int blockSize: 32
property string mode: ""
property ParticleSystem ps: particleSystem
//For easy theming
Image {
id: bg
z: -1
+ anchors.fill: parent
source: background;
fillMode: Image.PreserveAspectCrop
}
- width: 320
- height: 480
MouseArea {
anchors.fill: parent; onClicked: {
if (puzzleTextBubble.opacity == 1) {
import QtQuick 2.0
import QtQuick.Particles 2.0
+import "../settings.js" as Settings
Emitter {
property Item block: parent
"yellowspots";
}
}
- size: 64
- endSize: 16
+ size: Settings.blockSize * 2
+ endSize: Settings.blockSize/2
lifeSpan: 30000
enabled: false
emitRate: 60
--- /dev/null
+/***************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import "../settings.js" as Settings
+
+Text {
+ font.pixelSize: Settings.fontPixelSize;
+ color: "white";
+ textFormat: Text.StyledText;
+ Behavior on opacity { NumberAnimation {} }
+}
/* This script file handles the game logic */
.pragma library
.import QtQuick.LocalStorage 2.0 as Sql
+.import "../settings.js" as Settings
var maxColumn = 10;
var maxRow = 13;
gc.gameOver = false;
gc.mode = gameMode;
// Calculate board size
- maxColumn = Math.floor(gameCanvas.width/gameCanvas.blockSize);
- maxRow = Math.floor(gameCanvas.height/gameCanvas.blockSize);
+ maxColumn = Math.floor(gameCanvas.width/Settings.blockSize);
+ maxRow = Math.floor(gameCanvas.height/Settings.blockSize);
maxIndex = maxRow * maxColumn;
if (gameMode == "arcade") //Needs to be after board sizing
getHighScore();
{
if (betweenTurns || gameOver || gameCanvas == undefined)
return;
- var column = Math.floor(x/gameCanvas.blockSize);
- var row = Math.floor(y/gameCanvas.blockSize);
+ var column = Math.floor(x/Settings.blockSize);
+ var row = Math.floor(y/Settings.blockSize);
if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
return;
if (board[index(column, row)] == null)
} else {
if (fallDist > 0) {
var obj = board[index(column, row)];
- obj.y = (row + fallDist) * gameCanvas.blockSize;
+ obj.y = (row + fallDist) * Settings.blockSize;
board[index(column, row + fallDist)] = obj;
board[index(column, row)] = null;
}
obj = board[index(column, row)];
if (obj == null)
continue;
- obj.x = (column - fallDist) * gameCanvas.blockSize;
+ obj.x = (column - fallDist) * Settings.blockSize;
board[index(column - fallDist,row)] = obj;
board[index(column, row)] = null;
}
} else {
if (fallDist > 0) {
var obj = board[index(column, row)];
- obj.y = (row - fallDist) * gameCanvas.blockSize;
+ obj.y = (row - fallDist) * Settings.blockSize;
board[index(column, row - fallDist)] = obj;
board[index(column, row)] = null;
}
obj = board[index(column, row)];
if (obj == null)
continue;
- obj.x = (column - fallDist) * gameCanvas.blockSize;
+ obj.x = (column - fallDist) * Settings.blockSize;
board[index(column - fallDist,row)] = obj;
board[index(column, row)] = null;
}
}
var dynamicObject = component.createObject(gameCanvas,
{"type": type,
- "x": column*gameCanvas.blockSize,
- "y": -1*gameCanvas.blockSize,
- "width": gameCanvas.blockSize,
- "height": gameCanvas.blockSize,
+ "x": column*Settings.blockSize,
+ "y": -1*Settings.blockSize,
+ "width": Settings.blockSize,
+ "height": Settings.blockSize,
"particleSystem": gameCanvas.ps});
if (dynamicObject == null){
console.log("error creating block");
console.log(component.errorString());
return false;
}
- dynamicObject.y = row*gameCanvas.blockSize;
+ dynamicObject.y = row*Settings.blockSize;
dynamicObject.spawned = true;
board[index(column,row)] = dynamicObject;
SOURCES += main.cpp
target.path = $$[QT_INSTALL_EXAMPLES]/qtquick/demos/samegame
-qml.files = samegame.qml content
+qml.files = samegame.qml content settings.js
qml.path = $$[QT_INSTALL_EXAMPLES]/qtquick/demos/samegame
INSTALLS += target qml
import QtQuick 2.0
import QtQuick.Particles 2.0
import "content/samegame.js" as Logic
+import "settings.js" as Settings
import "content"
Rectangle {
id: root
width: 320; height: 480
property int acc: 0
- property int menuDelay: 500
+
function loadPuzzle() {
if (gameCanvas.mode != "")
GameArea {
id: gameCanvas
z: 1
+ y: Settings.headerHeight
+
width: parent.width
+ height: parent.height - Settings.headerHeight - Settings.footerHeight
- y: 20
- height: parent.height - 64
backgroundVisible: root.state == "in-game"
onModeChanged: if (gameCanvas.mode != "puzzle") puzzleWon = false; //UI has stricter constraints on this variable than the game does
Age {
LogoAnimation {
x: 64
- y: 20
+ y: Settings.headerHeight
particleSystem: gameCanvas.ps
running: root.state == ""
}
Column {
y: 100 + 40
- spacing: 0
+ spacing: Settings.menuButtonSpacing
Button {
- height: 64
width: root.width
rotatedButton: true
imgSrc: "content/gfx/but-game-1.png"
group: "green"
Timer {
id: arcadeTimer
- interval: menuDelay
+ interval: Settings.menuDelay
running : false
repeat : false
onTriggered: Logic.startNewGame(gameCanvas)
}
Button {
- height: 64
width: root.width
rotatedButton: true
imgSrc: "content/gfx/but-game-2.png"
group: "green"
Timer {
id: twopTimer
- interval: menuDelay
+ interval: Settings.menuDelay
running : false
repeat : false
onTriggered: Logic.startNewGame(gameCanvas, "multiplayer")
}
Button {
- height: 64
width: root.width
rotatedButton: true
imgSrc: "content/gfx/but-game-3.png"
group: "blue"
Timer {
id: endlessTimer
- interval: menuDelay
+ interval: Settings.menuDelay
running : false
repeat : false
onTriggered: Logic.startNewGame(gameCanvas, "endless")
}
Button {
- height: 64
width: root.width
rotatedButton: true
imgSrc: "content/gfx/but-game-4.png"
}
Timer {
id: puzzleTimer
- interval: menuDelay
+ interval: Settings.menuDelay
running : false
repeat : false
onTriggered: loadPuzzle();
source: "content/gfx/bar.png"
width: parent.width
z: 6
- y: -24
- height: 24
+ y: -Settings.headerHeight
+ height: Settings.headerHeight
Behavior on opacity { NumberAnimation {} }
- Text {
+ SamegameText {
id: arcadeScore
anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
text: '<font color="#f7d303">P1:</font> ' + gameCanvas.score
- font.pixelSize: 14
+ font.pixelSize: Settings.fontPixelSize
textFormat: Text.StyledText
color: "white"
opacity: gameCanvas.mode == "arcade" ? 1 : 0
Behavior on opacity { NumberAnimation {} }
}
- Text {
+ SamegameText {
id: arcadeHighScore
anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
text: '<font color="#f7d303">Highscore:</font> ' + gameCanvas.highScore
- font.pixelSize: 14
- color: "white"
- textFormat: Text.StyledText
opacity: gameCanvas.mode == "arcade" ? 1 : 0
- Behavior on opacity { NumberAnimation {} }
}
- Text {
+ SamegameText {
id: p1Score
anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
text: '<font color="#f7d303">P1:</font> ' + gameCanvas.score
- textFormat: Text.StyledText
- font.pixelSize: 14
- color: "white"
opacity: gameCanvas.mode == "multiplayer" ? 1 : 0
- Behavior on opacity { NumberAnimation {} }
}
- Text {
+ SamegameText {
id: p2Score
anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
text: '<font color="#f7d303">P2:</font> ' + gameCanvas.score2
- textFormat: Text.StyledText
- font.pixelSize: 14
- color: "white"
opacity: gameCanvas.mode == "multiplayer" ? 1 : 0
- Behavior on opacity { NumberAnimation {} }
rotation: 180
}
- Text {
+ SamegameText {
id: puzzleMoves
anchors { left: parent.left; topMargin: 3; leftMargin: 11; top: parent.top}
text: '<font color="#f7d303">Moves:</font> ' + gameCanvas.moves
- textFormat: Text.StyledText
- font.pixelSize: 14
- color: "white"
opacity: gameCanvas.mode == "puzzle" ? 1 : 0
- Behavior on opacity { NumberAnimation {} }
}
- Text {
+ SamegameText {
Image {
source: "content/gfx/icon-time.png"
x: -20
id: puzzleTime
anchors { topMargin: 3; top: parent.top; horizontalCenter: parent.horizontalCenter; horizontalCenterOffset: 20}
text: "00:00"
- font.pixelSize: 14
- color: "white"
opacity: gameCanvas.mode == "puzzle" ? 1 : 0
- Behavior on opacity { NumberAnimation {} }
Timer {
interval: 1000
repeat: true
}
}
}
- Text {
+ SamegameText {
id: puzzleScore
anchors { right: parent.right; topMargin: 3; rightMargin: 11; top: parent.top}
text: '<font color="#f7d303">Score:</font> ' + gameCanvas.score
- textFormat: Text.StyledText
- font.pixelSize: 14
- color: "white"
opacity: gameCanvas.mode == "puzzle" ? 1 : 0
- Behavior on opacity { NumberAnimation {} }
}
}
Image {
id: bottomBar
width: parent.width
- height: 44
+ height: Settings.footerHeight
source: "content/gfx/bar.png"
- y: parent.height - 44
+ y: parent.height - Settings.footerHeight;
z: 2
- function selectButtons() {
- menuButton.visible = (root.state == "in-game");
- nextButton.visible = (root.state == "in-game");
- againButton.visible = (root.state == "in-game");
- }
Button {
id: quitButton
+ height: Settings.toolButtonHeight
imgSrc: "content/gfx/but-quit.png"
onClicked: {Qt.quit(); }
anchors { left: parent.left; verticalCenter: parent.verticalCenter; leftMargin: 11 }
}
Button {
id: menuButton
+ height: Settings.toolButtonHeight
imgSrc: "content/gfx/but-menu.png"
- visible: false
+ visible: (root.state == "in-game");
onClicked: {root.state = ""; Logic.cleanUp(); gameCanvas.mode = ""}
anchors { left: quitButton.right; verticalCenter: parent.verticalCenter; leftMargin: 0 }
}
Button {
id: againButton
+ height: Settings.toolButtonHeight
imgSrc: "content/gfx/but-game-new.png"
- visible: false
- opacity: gameCanvas.gameOver && (gameCanvas.mode == "arcade" || gameCanvas.mode == "multiplayer") ? 1 : 0
+ visible: (root.state == "in-game");
+ opacity: gameCanvas.gameOver && (gameCanvas.mode == "arcade" || gameCanvas.mode == "multiplayer")
Behavior on opacity{ NumberAnimation {} }
- onClicked: {if (gameCanvas.gameOver) Logic.startNewGame(gameCanvas, gameCanvas.mode);}
+ onClicked: {if (gameCanvas.gameOver) { Logic.startNewGame(gameCanvas, gameCanvas.mode);}}
anchors { right: parent.right; verticalCenter: parent.verticalCenter; rightMargin: 11 }
}
Button {
id: nextButton
+ height: Settings.toolButtonHeight
imgSrc: "content/gfx/but-puzzle-next.png"
- visible: false
+ visible: (root.state == "in-game") && gameCanvas.mode == "puzzle" && gameCanvas.puzzleWon
opacity: gameCanvas.puzzleWon ? 1 : 0
Behavior on opacity{ NumberAnimation {} }
onClicked: {if (gameCanvas.puzzleWon) nextPuzzle();}
SequentialAnimation {
id: stateChangeAnim
ParallelAnimation {
- NumberAnimation { target: bottomBar; property: "y"; to: root.height; duration: menuDelay/2; easing.type: Easing.OutQuad }
- NumberAnimation { target: scoreBar; property: "y"; to: -24; duration: menuDelay/2; easing.type: Easing.OutQuad }
+ NumberAnimation { target: bottomBar; property: "y"; to: root.height; duration: Settings.menuDelay/2; easing.type: Easing.OutQuad }
+ NumberAnimation { target: scoreBar; property: "y"; to: -Settings.headerHeight; duration: Settings.menuDelay/2; easing.type: Easing.OutQuad }
}
- ScriptAction { script: bottomBar.selectButtons(); }
ParallelAnimation {
- NumberAnimation { target: bottomBar; property: "y"; to: root.height - 44; duration: menuDelay/2; easing.type: Easing.OutBounce}
- NumberAnimation { target: scoreBar; property: "y"; to: root.state == "" ? -24 : 0; duration: menuDelay/2; easing.type: Easing.OutBounce}
+ NumberAnimation { target: bottomBar; property: "y"; to: root.height - Settings.footerHeight; duration: Settings.menuDelay/2; easing.type: Easing.OutBounce}
+ NumberAnimation { target: scoreBar; property: "y"; to: root.state == "" ? -Settings.headerHeight : 0; duration: Settings.menuDelay/2; easing.type: Easing.OutBounce}
}
}
--- /dev/null
+/****************************************************************************
+**
+** Copyright (C) 2012 Research In Motion
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** You may use this file under the terms of the BSD license as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
+** of its contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+.pragma library
+
+//This should be switched over once a proper QML settings API exists
+
+var menuDelay = 500
+
+var headerHeight = 20 // 70 on BB10
+var footerHeight = 44 // 100 on BB10
+
+var fontPixelSize = 14 // 55 on BB10
+
+var blockSize = 32 // 64 on BB10
+
+var toolButtonHeight = 32 // 64 on BB10
+
+var menuButtonSpacing = 0 // 15 on BB10
return -1;\
}\
view.connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));\
- view.setSource(QUrl::fromLocalFile(fileName));\
- view.show();\
+ view.setSource(QUrl::fromLocalFile(fileName)); \
+ if (QGuiApplication::platformName() == QLatin1String("qnx") || \
+ QGuiApplication::platformName() == QLatin1String("eglfs")) {\
+ view.setResizeMode(QQuickView::SizeRootObjectToView);\
+ view.showFullScreen();\
+ } else {\
+ view.show();\
+ }\
return app.exec();\
}