Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit ea8166e7 authored by Julian Helfferich's avatar Julian Helfferich

Fix slowdown issue

The slowdown appeared after playing for a few minutes. The bug appeared
after the move to QML because QML timers have a minimum interval of
16ms. Now, instead of cutting the timer interval in half, the evaluation
is split into substeps.
parent a4d73a10
......@@ -28,7 +28,6 @@ const int REPAINT_INTERVAL = 16; // should be a power of two
// 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;
......
......@@ -41,18 +41,4 @@ CanvasItem {
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;
}
}
}
}
......@@ -25,7 +25,6 @@ var REPAINT_INTERVAL = 16; // should be a power of two
// 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;
......
......@@ -34,6 +34,11 @@ var randomCounter = 0;
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 @@ function resumeGame() {
bar.reset();
speed = 1.8;
repaintInterval = 1;
substeps = 1;
elapsedTimeTimer.restart();
gameTimer.interval = Globals.REPAINT_INTERVAL;
gameTimer.restart();
......@@ -255,6 +261,19 @@ function endGame() {
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 updateBallDirection() {
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 @@ function changeSpeed(ratio) {
// 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 @@ function detectBallCollisions(ball) {
}
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);
......
......@@ -198,7 +198,12 @@ Item {
id: gameTimer
interval: Globals.REPAINT_INTERVAL
repeat: true
onTriggered: Logic.detectCollisions();
onTriggered: {
for (x = 0; x < Logic.substeps; ++x) {
Logic.moveBalls()
Logic.detectCollisions()
}
}
}
Timer {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment