demos/declarative/snake/content/snake.js
changeset 30 5dc02b23752f
child 33 3e2da88830cd
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/demos/declarative/snake/content/snake.js	Tue Jul 06 15:10:48 2010 +0300
@@ -0,0 +1,306 @@
+
+var snake = new Array;
+var board = new Array;
+var links = new Array;
+var scheduledDirections = new Array;
+var numRows = 1;
+var numColumns = 1;
+var linkComponent = Qt.createComponent("content/Link.qml"); // XXX should resolve relative to script, not component
+var cookieComponent = Qt.createComponent("content/Cookie.qml");
+var cookie;
+var linksToGrow = 0;
+var linksToDie = 0;
+var waitForCookie = 0;
+var growType = 0;
+var skullMovementsBeforeDirectionChange = 0;
+
+
+function rand(n)
+{
+  return (Math.floor(Math.random() * n));
+}
+
+function scheduleDirection(dir)
+{
+    direction = dir;
+    if(scheduledDirections[scheduledDirections.length-1]!=direction)
+        scheduledDirections.push(direction);
+}
+
+function startNewGame()
+{
+    if (state == "starting")
+        return;
+
+    if (heartbeat.running) {
+        endGame();
+        startNewGameTimer.running = true;
+        return;
+    }
+    numRows = numRowsAvailable;
+    numColumns = numColumnsAvailable;
+    board = new Array(numRows * numColumns);
+    snake = new Array;
+    scheduledDirections = new Array;
+    growType = 0;
+
+    skull.z = numRows * numColumns + 1;
+
+    for (var i = 0; i < numRows * numColumns; ++i) {
+        if (i < links.length) {
+            var link = links[i];
+            link.spawned = false;
+            link.dying = false;
+        } else {
+            if(linkComponent.status != Component.Ready) {
+                if(linkComponent.status == Component.Error) 
+                    console.log(linkComponent.errorString());
+                else
+                    console.log("Still loading linkComponent");
+                continue;//TODO: Better error handling?
+            }
+            var link = linkComponent.createObject(playfield);
+            link.z = numRows * numColumns + 1 - i;
+            link.type = i == 0 ? 2 : 0;
+            link.spawned = false;
+            link.dying = false;
+            links.push(link);
+        }
+    }
+
+    head = links[0];
+    snake.push(head);
+    head.row = numRows/2 -1;
+    head.column = numColumns/2 -1;
+    head.spawned = true;
+
+    linksToGrow = 5;
+    linksToDie = 0;
+    waitForCookie = 5;
+    score = 0;
+    startHeartbeatTimer.running = true;
+    heartbeat.running = true;
+}
+
+function endGame()
+{
+    heartbeat.running = false;
+    for(var i in snake)
+        snake[i].dying = true;
+    if (cookie) {
+        cookie.dying = true;
+        cookie = 0;
+    }
+    lastScore = score;
+    highScores.saveScore(lastScore);
+}
+
+function move() {
+
+    if (!head)
+        return;
+
+    var dir = direction;
+
+    if (scheduledDirections.length) {
+        dir = scheduledDirections.shift();
+    }
+
+    if (state == "starting") {
+        var turn = (dir - headDirection);
+        head.rotation += turn == -3 ? 1 : (turn == 3 ? -1 : turn );
+        headDirection = dir;
+        return;
+    }
+
+    var row = head.row;
+    var column = head.column;
+
+    if (dir == 0) {
+        row = row - 1;
+    } else if (dir == 1) {
+        column = column + 1
+    } else if (dir == 2) {
+        row = row + 1;
+    } else if (dir == 3) {
+        column = column - 1;
+    }
+
+    //validate the new position
+    if (row < 0 || row >= numRows
+        || column < 0 || column >= numColumns
+        || (row == skull.row && column == skull.column)
+        || !isFree(row, column)) {
+        var turn = (dir - headDirection);
+        head.rotation += turn == -3 ? 1 : (turn == 3 ? -1 : turn );
+        headDirection = dir;
+        endGame();
+        return;
+    }
+
+    var newLink;
+    if (linksToGrow > 0) {
+        --linksToGrow;
+        newLink = links[snake.length];
+        newLink.spawned = false;
+        newLink.rotation = snake[snake.length-1].rotation;
+        newLink.type = growType;
+        newLink.dying = false;
+        snake.push(newLink);
+    } else {
+        var lastLink = snake[snake.length-1];
+        board[lastLink.row * numColumns + lastLink.column] = Undefined;
+    }
+
+    if (waitForCookie > 0) {
+        if (--waitForCookie == 0)
+            createCookie(cookie? (cookie.value+1) : 1);
+    }
+
+    for (var i = snake.length-1; i > 0; --i) {
+        snake[i].row = snake[i-1].row;
+        snake[i].column = snake[i-1].column;
+        snake[i].rotation = snake[i-1].rotation;
+    }
+
+    if (newLink) {
+        newLink.spawned = true;
+    }
+
+    // move the head
+    head.row = row;
+    head.column = column;
+    board[row * numColumns + column] = head;
+
+    var turn = (dir - headDirection);
+    head.rotation += turn == -3 ? 1 : (turn == 3 ? -1 : turn );
+    headDirection = dir;
+
+    var value = testCookie(row, column);
+    if (value > 0) {
+        linksToGrow += value;
+        score += value;
+    }
+}
+
+function isFree(row, column)
+{
+    return board[row * numColumns + column] == Undefined;
+}
+
+function isHead(row, column)
+{
+    return head.column == column && head.row == row;
+}
+
+function testCookie(row, column)
+{
+    if (cookie && !cookie.dying && cookie.row == row && cookie.column == column) {
+        var value = cookie.value;
+        waitForCookie = value;
+        growType = snake[snake.length-1].type == 1 ? 0 : 1;
+        cookie.dying = true;
+        cookie.z = numRows * numColumns + 2;
+        return value;
+    }
+    return 0;
+}
+
+function moveSkull()
+{
+
+    if (linksToDie > 0) {
+        --linksToDie;
+        var link = snake.pop();
+        link.dying = true;
+        board[link.row * numColumns + link.column] = Undefined;
+        if (score > 0)
+            --score;
+        if (snake.length == 0) {
+            endGame();
+            return;
+        }
+    }
+
+    var row = skull.row;
+    var column = skull.column;
+    if (isHead(row, column)) {
+        endGame();
+        return;
+    }
+    row +=  skull.verticalMovement;
+    column += skull.horizontalMovement;
+
+    var attempts = 4;
+
+    while (skullMovementsBeforeDirectionChange == 0 || row < 0 || row >= numRows
+        || column < 0 || column >= numColumns
+        || (!isFree(row, column) && !isHead(row, column))) {
+        var d = rand(8);
+        skull.verticalMovement = 0;
+        skull.horizontalMovement = 0;
+        skullMovementsBeforeDirectionChange = rand(20)+1;
+        if (d == 0) {
+            skull.verticalMovement = -1
+        } else if (d == 1) {
+            skull.horizontalMovement = -1;
+        } else if (d == 2) {
+            skull.verticalMovement = 1
+        } else if (d == 3){
+            skull.horizontalMovement = 1;
+        } else if (cookie) {
+            var rd = cookie.row - skull.row;
+            var rc = cookie.column - skull.column;
+            if (Math.abs(rd) > Math.abs(rc)) {
+                skull.verticalMovement = rd > 0 ? 1 : -1;
+                skullMovementsBeforeDirectionChange = Math.abs(rd);
+            } else {
+                skull.horizontalMovement= rc > 0 ? 1 : -1;
+                skullMovementsBeforeDirectionChange = Math.abs(rc);
+            }
+        }
+        row = skull.row + skull.verticalMovement;
+        column = skull.column + skull.horizontalMovement;
+        if (--attempts == 0)
+            return;
+    }
+
+    skull.row = row;
+    skull.column = column;
+    --skullMovementsBeforeDirectionChange;
+    var value = testCookie(row, column);
+    if (value > 0)
+        linksToDie += value/2;
+
+    if (isHead(row, column))
+        endGame();
+}
+
+function createCookie(value) {
+    if (numRows * numColumns - snake.length < 10)
+        return;
+
+    var column = rand(numColumns);
+    var row = rand(numRows);
+    while (!isFree(row, column)) {
+        column++;
+        if (column == numColumns) {
+            column = 0;
+            row++;
+            if (row == numRows)
+                row = 0;
+        }
+    }
+
+    if(cookieComponent.status != Component.Ready) {
+        if(cookieComponent.status == Component.Error)
+            console.log(cookieComponent.errorString());
+        else
+            console.log("Still loading cookieComponent");
+        return;//TODO: Better error handling?
+    }
+    cookie = cookieComponent.createObject(head.parent);
+    cookie.value = value;
+    cookie.row = row;
+    cookie.column = column;
+}