diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -28,7 +28,6 @@ // how ofter the position of the item is updated (but not repainted) const int DEFAULT_UPDATE_INTERVAL = 13; //const int MAXIMUM_UPDATE_INTERVAL = REPAINT_INTERVAL; -const int MINIMUM_UPDATE_INTERVAL = 8; // the higher this number the more the game becomes faster over time const qreal AUTO_SPEED_INCREASE = 1.05; diff --git a/src/qml/Ball.qml b/src/qml/Ball.qml --- a/src/qml/Ball.qml +++ b/src/qml/Ball.qml @@ -41,18 +41,4 @@ property real posY x: m_scale * posX y: m_scale * posY - - Timer { - interval: gameTimer.interval - running: gameTimer.running - repeat: true - onTriggered: { - if (toBeFired) { - posX = (bar.x + barPosition*bar.width)/m_scale; - } else { - posX += directionX * speed; - posY += directionY * speed; - } - } - } } diff --git a/src/qml/globals.js b/src/qml/globals.js --- a/src/qml/globals.js +++ b/src/qml/globals.js @@ -25,7 +25,6 @@ // how ofter the position of the item is updated (but not repainted) var DEFAULT_UPDATE_INTERVAL = 13; //var MAXIMUM_UPDATE_INTERVAL = REPAINT_INTERVAL; -var MINIMUM_UPDATE_INTERVAL = 8; // the higher this number the more the game becomes faster over time var AUTO_SPEED_INCREASE = 1.05; diff --git a/src/qml/logic.js b/src/qml/logic.js --- a/src/qml/logic.js +++ b/src/qml/logic.js @@ -34,6 +34,11 @@ var itemsGotDeleted; var singleShotComponent = Qt.createComponent("Singleshot.qml"); +// Substeps are used to avoid that the ball is moved too far in a single update, +// possibly leading to buggy behavior. The movement is divided into multiple +// substeps and collisions are detected after each substep. +var substeps = 1; + function remove(array, object) { array.splice(array.indexOf(object), 1); } @@ -245,6 +250,7 @@ bar.reset(); speed = 1.8; repaintInterval = 1; + substeps = 1; elapsedTimeTimer.restart(); gameTimer.interval = Globals.REPAINT_INTERVAL; gameTimer.restart(); @@ -255,6 +261,19 @@ canvas.gameEnded(score, (gameWon ? -1 : level), elapsedTimeTimer.elapsedTime); } +function moveBalls() { + for (var i in balls) { + var ball = balls[i] + if (ball.toBeFired) { + ball.posX = (bar.x + ball.barPosition*bar.width)/m_scale; + } else { + ball.posX += ball.directionX * speed; + ball.posY += ball.directionY * speed; + } + + } +} + function detectCollisions() { // needed to exit from the loop if the arrays that they cycle // change (items get deleted) @@ -406,25 +425,14 @@ function changeSpeed(ratio) { speed *= ratio; if (speed > 2.0) { - // make sure the minimum update interval is respected - if (gameTimer.interval < Globals.MINIMUM_UPDATE_INTERVAL*2) { - speed = 2.0; - return; - } - // else - // half the speed speed /= 2.0; // and double the number of ticks of the timer per time unit - gameTimer.interval /= 2; - repaintInterval *= 2; - gameTimer.restart(); + substeps *= 2; } if (speed < 1.0) { - if (gameTimer.interval >= Globals.REPAINT_INTERVAL) { - if (speed < Globals.MINIMUM_SPEED) { - speed = Globals.MINIMUM_SPEED; - } + if (substeps == 1) { + speed = Globals.MINIMUM_SPEED return; } // else @@ -432,9 +440,7 @@ // double the speed speed *= 2.0; // and half the number of ticks of the timer per time unit - gameTimer.interval *= 2; - repaintInterval /= 2; - gameTimer.restart(); + substeps /= 2; } } @@ -527,11 +533,9 @@ } var angle = (Math.PI/3) * (barCenter-ballCenter)/(bar.width/2) + Math.PI/2; - var speed = Math.sqrt(Math.pow(ball.directionX, 2) + - Math.pow(ball.directionY, 2)); - ball.directionX = Math.cos(angle) * speed; - ball.directionY = -Math.sin(angle) * speed; + ball.directionX = Math.cos(angle) * Globals.BALL_SPEED; + ball.directionY = -Math.sin(angle) * Globals.BALL_SPEED; } } else { // bounce against the bricks (and optionally break them) handleBrickCollisions(ball); diff --git a/src/qml/main.qml b/src/qml/main.qml --- a/src/qml/main.qml +++ b/src/qml/main.qml @@ -198,7 +198,12 @@ id: gameTimer interval: Globals.REPAINT_INTERVAL repeat: true - onTriggered: Logic.detectCollisions(); + onTriggered: { + for (x = 0; x < Logic.substeps; ++x) { + Logic.moveBalls() + Logic.detectCollisions() + } + } } Timer {