aboutsummaryrefslogtreecommitdiffstats
path: root/examples/demos/samegame/content/samegame.js
diff options
context:
space:
mode:
authorAlan Alpert <alan.alpert@nokia.com>2012-02-20 10:34:44 +1000
committerQt by Nokia <qt-info@nokia.com>2012-02-24 10:24:58 +0100
commit9d2b618fa022daeabd45e57aa1596197db883037 (patch)
tree90536e9fc088d734439921dde304b49fe7f38df0 /examples/demos/samegame/content/samegame.js
parent91d543f00904a6caa2fab850ff3eca12de2d65ac (diff)
Start of examples refactor
This is the general reorg of the examples directory structure, plus additional guidelines. calculator, animations and accessibility have been updated to the new standards and tested, as an example. Task-number: QTBUG-24133 Change-Id: I76c3b86751d3195ba2a5474ff23afb875765e9a4 Reviewed-by: Alan Alpert <alan.alpert@nokia.com>
Diffstat (limited to 'examples/demos/samegame/content/samegame.js')
-rwxr-xr-xexamples/demos/samegame/content/samegame.js290
1 files changed, 290 insertions, 0 deletions
diff --git a/examples/demos/samegame/content/samegame.js b/examples/demos/samegame/content/samegame.js
new file mode 100755
index 0000000000..611767584b
--- /dev/null
+++ b/examples/demos/samegame/content/samegame.js
@@ -0,0 +1,290 @@
+/* This script file handles the game logic */
+.pragma library
+.import QtQuick.LocalStorage 2.0 as Sql
+
+var maxColumn = 10;
+var maxRow = 15;
+var maxIndex = maxColumn*maxRow;
+var board = new Array(maxIndex);
+var blockSrc = "BoomBlock.qml";
+var scoresURL = "";
+var gameDuration;
+var component = Qt.createComponent(blockSrc);
+var highScoreBar = -1;
+var gameCanvas;
+var nameInputDialog = null;
+var dialog = null;
+
+// Index function used instead of a 2D array
+function index(column, row)
+{
+ return column + row * maxColumn;
+}
+
+function timeStr(msecs)
+{
+ var secs = Math.floor(msecs/1000);
+ var m = Math.floor(secs/60);
+ var ret = "" + m + "m " + (secs%60) + "s";
+ return ret;
+}
+
+function startNewGame(gc)
+{
+ gameCanvas = gc;
+ // Delete blocks from previous game
+ for (var i = 0; i < maxIndex; i++) {
+ if (board[i] != null)
+ board[i].destroy();
+ }
+
+ // Calculate board size
+ maxColumn = Math.floor(gameCanvas.width/gameCanvas.blockSize);
+ maxRow = Math.floor(gameCanvas.height/gameCanvas.blockSize);
+ maxIndex = maxRow * maxColumn;
+
+ // Close dialogs
+ if(nameInputDialog != null)
+ nameInputDialog.forceClose();
+ if(dialog != null)
+ dialog.forceClose();
+
+ // Initialize Board
+ board = new Array(maxIndex);
+ gameCanvas.score = 0;
+ for (var column = 0; column < maxColumn; column++) {
+ for (var row = 0; row < maxRow; row++) {
+ board[index(column, row)] = null;
+ createBlock(column, row);
+ }
+ }
+ gameDuration = new Date();
+}
+
+var fillFound; // Set after a floodFill call to the number of blocks found
+var floodBoard; // Set to 1 if the floodFill reaches off that node
+
+// NOTE: Be careful with vars named x,y, as the calling object's x,y are still in scope
+function handleClick(x,y)
+{
+ if(gameCanvas == undefined){
+ console.log("But the game hasn't started yet!");
+ return;
+ }
+ var column = Math.floor(x/gameCanvas.blockSize);
+ var row = Math.floor(y/gameCanvas.blockSize);
+ if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
+ return;
+ if (board[index(column, row)] == null)
+ return;
+ // If it's a valid block, remove it and all connected (does nothing if it's not connected)
+ floodFill(column,row, -1);
+ if (fillFound <= 0)
+ return;
+ gameCanvas.score += (fillFound - 1) * (fillFound - 1);
+ shuffleDown();
+ victoryCheck();
+}
+
+function floodFill(column,row,type)
+{
+ if (board[index(column, row)] == null)
+ return;
+ var first = false;
+ if (type == -1) {
+ first = true;
+ type = board[index(column,row)].type;
+
+ // Flood fill initialization
+ fillFound = 0;
+ floodBoard = new Array(maxIndex);
+ }
+ if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
+ return;
+ if (floodBoard[index(column, row)] == 1 || (!first && type != board[index(column, row)].type))
+ return;
+ floodBoard[index(column, row)] = 1;
+ floodFill(column + 1, row, type);
+ floodFill(column - 1, row, type);
+ floodFill(column, row + 1, type);
+ floodFill(column, row - 1, type);
+ if (first == true && fillFound == 0)
+ return; // Can't remove single blocks
+ board[index(column, row)].dying = true;
+ board[index(column, row)] = null;
+ fillFound += 1;
+}
+
+function shuffleDown()
+{
+ // Fall down
+ for (var column = 0; column < maxColumn; column++) {
+ var fallDist = 0;
+ for (var row = maxRow - 1; row >= 0; row--) {
+ if (board[index(column,row)] == null) {
+ fallDist += 1;
+ } else {
+ if (fallDist > 0) {
+ var obj = board[index(column, row)];
+ obj.y = (row + fallDist) * gameCanvas.blockSize;
+ board[index(column, row + fallDist)] = obj;
+ board[index(column, row)] = null;
+ }
+ }
+ }
+ }
+ // Fall to the left
+ fallDist = 0;
+ for (column = 0; column < maxColumn; column++) {
+ if (board[index(column, maxRow - 1)] == null) {
+ fallDist += 1;
+ } else {
+ if (fallDist > 0) {
+ for (row = 0; row < maxRow; row++) {
+ obj = board[index(column, row)];
+ if (obj == null)
+ continue;
+ obj.x = (column - fallDist) * gameCanvas.blockSize;
+ board[index(column - fallDist,row)] = obj;
+ board[index(column, row)] = null;
+ }
+ }
+ }
+ }
+}
+
+function victoryCheck()
+{
+ // Awards bonuses for no blocks left
+ var deservesBonus = true;
+ for (var column = maxColumn - 1; column >= 0; column--)
+ if (board[index(column, maxRow - 1)] != null)
+ deservesBonus = false;
+ if (deservesBonus)
+ gameCanvas.score += 500;
+ // Checks for game over
+ if (deservesBonus || !(floodMoveCheck(0, maxRow - 1, -1))) {
+ gameDuration = new Date() - gameDuration;
+ if(nameInputDialog == null){
+ nameInputDialog = Qt.createQmlObject('import "."; import "samegame.js" as Logic; NameInputDialog{onAccepted: Logic.saveHighScore(name)}', gameCanvas, "highscoredialog.qml");
+ }
+ if(dialog == null){
+ dialog = Qt.createComponent("Dialog.qml").createObject(gameCanvas);
+ }
+ initHighScoreBar();
+ if(gameCanvas.score > highScoreBar){
+ nameInputDialog.show("You won! Please enter your name: ");
+ nameInputDialog.initialWidth = nameInputDialog.text.width + 20;
+ if (nameInputDialog.name == "")
+ nameInputDialog.width = nameInputDialog.initialWidth;
+ nameInputDialog.text.opacity = 0; // Just a spacer
+ }else{
+ dialog.show("You won!");
+ }
+ }
+}
+
+// Only floods up and right, to see if it can find adjacent same-typed blocks
+function floodMoveCheck(column, row, type)
+{
+ if (column >= maxColumn || column < 0 || row >= maxRow || row < 0)
+ return false;
+ if (board[index(column, row)] == null)
+ return false;
+ var myType = board[index(column, row)].type;
+ if (type == myType)
+ return true;
+ return floodMoveCheck(column + 1, row, myType) ||
+ floodMoveCheck(column, row - 1, board[index(column, row)].type);
+}
+
+function createBlock(column,row)
+{
+ // Note that we don't wait for the component to become ready. This will
+ // only work if the block QML is a local file. Otherwise the component will
+ // not be ready immediately. There is a statusChanged signal on the
+ // component you could use if you want to wait to load remote files.
+ if(component.status == 1){
+ var dynamicObject = component.createObject(gameCanvas,
+ {"type": Math.floor(Math.random() * 3),
+ "x": column*gameCanvas.blockSize,
+ "width": gameCanvas.blockSize,
+ "height": gameCanvas.blockSize,
+ "particleSystem": gameCanvas.ps});
+ if(dynamicObject == null){
+ console.log("error creating block");
+ console.log(component.errorString());
+ return false;
+ }
+ dynamicObject.y = row*gameCanvas.blockSize;
+ dynamicObject.spawned = true;
+
+ board[index(column,row)] = dynamicObject;
+ }else{
+ console.log("error loading block component");
+ console.log(component.errorString());
+ return false;
+ }
+ return true;
+}
+
+function initHighScoreBar()
+{
+ var db = Sql.openDatabaseSync(
+ "SameGameScores",
+ "1.0",
+ "Local SameGame High Scores",
+ 100
+ );
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(name TEXT, score NUMBER, gridSize TEXT, time NUMBER)');
+ // Only show results for the current grid size
+ var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "'
+ + maxColumn + "x" + maxRow + '" ORDER BY score desc LIMIT 10');
+ if(rs.rows.length < 10)
+ highScoreBar = 0;
+ else
+ highScoreBar = rs.rows.item(rs.rows.length - 1).score;
+ }
+ );
+}
+
+function saveHighScore(name)
+{
+ if (scoresURL != "")
+ sendHighScore(name);
+ // Offline storage
+ var db = Sql.openDatabaseSync(
+ "SameGameScores",
+ "1.0",
+ "Local SameGame High Scores",
+ 100
+ );
+ var dataStr = "INSERT INTO Scores VALUES(?, ?, ?, ?)";
+ var data = [
+ name,
+ gameCanvas.score,
+ maxColumn + "x" + maxRow,
+ Math.floor(gameDuration / 1000)
+ ];
+ db.transaction(
+ function(tx) {
+ tx.executeSql('CREATE TABLE IF NOT EXISTS Scores(name TEXT, score NUMBER, gridSize TEXT, time NUMBER)');
+ tx.executeSql(dataStr, data);
+
+ // Only show results for the current grid size
+ var rs = tx.executeSql('SELECT * FROM Scores WHERE gridSize = "'
+ + maxColumn + "x" + maxRow + '" ORDER BY score desc LIMIT 10');
+ var r = "\nHIGH SCORES for this grid size\n\n"
+ for (var i = 0; i < rs.rows.length; i++) {
+ r += (i+1) + ". " + rs.rows.item(i).name + ' got '
+ + rs.rows.item(i).score + ' points in '
+ + rs.rows.item(i).time + ' seconds.\n';
+ }
+ if(rs.rows.length == 10)
+ highScoreBar = rs.rows.item(9).score;
+ dialog.show(r);
+ }
+ );
+}