2016-05-01 14 views
0

So für ein Projekt, ich arbeite an, würde ich gerne vier unterschiedlich große Leinwände mit vier Kugeln von der Wand mit der gleichen Geschwindigkeit abprallen. Der Code funktioniert gut, wenn alle Leinwände die gleiche Größe haben, aber sobald ich versuche, die Höhe und Breite der Leinwände anzupassen, springt der Ball weiter in einem Bereich der Größe der ersten Leinwand. Ich bin nicht sicher, was ich falsch mache, und ich würde wirklich etwas Hilfe schätzen. Ich bin ziemlich neu in Javascript. HierBall in verschiedenen Größen Leinwand javascript

ist die HTML:

<canvas id="canvas1" width="200" height="200"></canvas> 
<canvas id="canvas2" width="200" height="400"></canvas> 
<canvas id="canvas3" width="400" height="200"></canvas> 
<canvas id="canvas4" width="200" height="200"></canvas> 

Und hier ist das Javascript:

var canvas = document.getElementById("canvas1"); 
var ctx = canvas.getContext("2d"); 
var x = canvas.width/2; 
var y = canvas.height-30; 
var dx = -2; 
var dy = 2; 
var ballRadius = 10; 

var canvas2 = document.getElementById("canvas2"); 
var ctx2 = canvas2.getContext("2d"); 
var x2 = canvas2.width/2; 
var y2 = canvas2.height-30; 

var canvas3 = document.getElementById("canvas3"); 
var ctx3 = canvas3.getContext("2d"); 
var x3 = canvas3.width/2; 
var y3 = canvas3.height-30; 

var canvas4 = document.getElementById("canvas4"); 
var ctx4 = canvas4.getContext("2d"); 
var x4 = canvas4.width/2; 
var y4 = canvas4.height-30; 

function drawBall() { 
    ctx.beginPath(); 
    ctx.arc(x, y, ballRadius, 0, Math.PI*2); 
    ctx.fillStyle = "#0095DD"; 
    ctx.fill(); 
    ctx.closePath(); 

    ctx2.beginPath(); 
    ctx2.arc(x2, y2, ballRadius, 0, Math.PI*2); 
    ctx2.fillStyle = "#0095DD"; 
    ctx2.fill(); 
    ctx2.closePath(); 

    ctx3.beginPath(); 
    ctx3.arc(x3, y3, ballRadius, 0, Math.PI*2); 
    ctx3.fillStyle = "#0095DD"; 
    ctx3.fill(); 
    ctx3.closePath(); 

    ctx4.beginPath(); 
    ctx4.arc(x4, y4, ballRadius, 0, Math.PI*2); 
    ctx4.fillStyle = "#0095DD"; 
    ctx4.fill(); 
    ctx4.closePath(); 
} 

function draw() { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx2.clearRect(0, 0, canvas2.width, canvas2.height); 
    ctx3.clearRect(0, 0, canvas3.width, canvas3.height); 
    ctx4.clearRect(0, 0, canvas4.width, canvas4.height); 

    drawBall(); 
    x += dx; 
    y += dy; 
    x2 += dx; 
    y2 += dy; 
    x3 += dx; 
    y3 += dy; 
    x4 += dx; 
    y4 += dy; 

    if(y + dy > canvas.height-ballRadius || y + dy < ballRadius) { 
     dy = -dy; } 
    if(x + dx > canvas.width-ballRadius || x + dx < ballRadius) { 
     dx = -dx; } 

    if(y2 + dy > canvas2.height-ballRadius || y2 + dy < ballRadius) { 
     dy = -dy; } 
    if(x2 + dx > canvas2.width-ballRadius || x2 + dx < ballRadius) { 
     dx = -dx; } 

    if(y3 + dy > canvas3.height-ballRadius || y3 + dy < ballRadius) { 
     dy = -dy; } 
    if(x3 + dx > canvas3.width-ballRadius || x3 + dx < ballRadius) { 
     dx = -dx; } 

    if(y4 + dy > canvas4.height-ballRadius || y4 + dy < ballRadius) { 
     dy = -dy; } 
    if(x4 + dx > canvas4.width-ballRadius || x4 + dx < ballRadius) { 
     dx = -dx; } 
    } 
    setInterval(draw, 10); 

Antwort

2

Das Problem ist, dass alle Kugeln die gleiche Geschwindigkeit teilen (dx, dy), so dass, wenn ein Die Kugeln treffen auf eine Wand und lassen alle springen. Um es zu beheben müssten Sie für jede einzelne Kugel eine Geschwindigkeit haben (dx2, Dy2, usw.)

0

EDIT
meinen Code nicht funktioniert, aber man kann immer noch die Idee von Proportionen mit den Werten übernehmen und verwenden eine andere Variable für jede dx und dy


Statt dx und dy für die Geschwindigkeit jeder Kugel verwendet wird, die Verwendung entsprechenden Zahlen für die Leinwand und Kugel:

// dx1, dx2, dx3, dx4, dy1, dy2, dy3, dy4 instead of dx, dy 
// also you can use proportions to keep them bouncing at the same time 
// see below 

var canvas = document.getElementById("canvas1"); 
var ctx = canvas.getContext("2d"); 
var x = canvas.width/2; 
var y = canvas.height/2; 
/*var dx = -2; 
var dy = 2;*/ 
var ballRadius = 10; 

var canvas2 = document.getElementById("canvas2"); 
var ctx2 = canvas2.getContext("2d"); 
var x2 = canvas2.width/2; 
var y2 = canvas2.height/2; 

var canvas3 = document.getElementById("canvas3"); 
var ctx3 = canvas3.getContext("2d"); 
var x3 = canvas3.width/2; 
var y3 = canvas3.height/2; 

var canvas4 = document.getElementById("canvas4"); 
var ctx4 = canvas4.getContext("2d"); 
var x4 = canvas4.width/2; 
var y4 = canvas4.height/2; 

/***********************************************/ 
/***********************************************/ 
/***********************************************/ 
/***********************************************/ 
/***********************************************/ 

var dx1 = 2, dx2 = dx1*canvas2.width/canvas.width, dx3 = dx1*canvas3.width/canvas.width, dx4 = dx1*canvas4.width/canvas.width; 
var dy1 = 2, dy2 = dy1*canvas2.height/canvas.height, dy3 = dy1*canvas3.height/canvas.height, dy4 = dy1*canvas4.height/canvas.height; 

function drawBalls() { 
    ctx.beginPath(); 
    ctx.arc(x, y, ballRadius, 0, Math.PI*2); 
    ctx.fillStyle = "#0095DD"; 
    ctx.fill(); 
    ctx.closePath(); 

    ctx2.beginPath(); 
    ctx2.arc(x2, y2, ballRadius, 0, Math.PI*2); 
    ctx2.fillStyle = "#0095DD"; 
    ctx2.fill(); 
    ctx2.closePath(); 

    ctx3.beginPath(); 
    ctx3.arc(x3, y3, ballRadius, 0, Math.PI*2); 
    ctx3.fillStyle = "#0095DD"; 
    ctx3.fill(); 
    ctx3.closePath(); 

    ctx4.beginPath(); 
    ctx4.arc(x4, y4, ballRadius, 0, Math.PI*2); 
    ctx4.fillStyle = "#0095DD"; 
    ctx4.fill(); 
    ctx4.closePath(); 
} 

function clearCanvases() { 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
    ctx2.clearRect(0, 0, canvas2.width, canvas2.height); 
    ctx3.clearRect(0, 0, canvas3.width, canvas3.height); 
    ctx4.clearRect(0, 0, canvas4.width, canvas4.height); 
} 

function changeSpeeds() { 
    x += dx1; 
    y += dy1; 
    x2 += dx2; 
    y2 += dy2; 
    x3 += dx3; 
    y3 += dy3; 
    x4 += dx4; 
    y4 += dy4; 
} 

function what(a, b, c, r) 
{ 
    if (a + b > c - r || a + b < r) 
    { 
     b = -b; 
    } 
} 

function checkForCollisions() { 
    what(y, dy1, canvas.height, ballRadius); 
    what(x, dx1, canvas.width, ballRadius); 
    what(y2, dy2, canvas2.height, ballRadius); 
    what(x2, dx2, canvas2.width, ballRadius); 
    what(y3, dy3, canvas3.height, ballRadius); 
    what(x3, dx3, canvas3.width, ballRadius); 
    what(y4, dy4, canvas4.height, ballRadius); 
    what(x4, dx4, canvas4.width, ballRadius); 
} 


// I split the draw function into four functions, named bounceBalls 
function bounceBalls() 
{ 
    clearCanvases(); // context.clearRect for each of the four canvases... 
    drawBalls(); // drawBall in your code 
    changeSpeeds(); 
    checkForCollisions(); // bouncing against sides 
} 

var FPS = 60; 
window.setInterval(bounceBalls, 1000/FPS); 
2

In Ihrem Code teilen sich die Bälle die gleichen Geschwindigkeitswerte (dx, dy), was dazu führt, dass sich alle Bälle auf die gleiche Weise verhalten.

Eine Möglichkeit, Ihr Problem zu lösen und Ihren Code sauberer (/ skalierbar) zu machen, besteht darin, eine Klasse für die Zeichnung und verschiedene Instanzen dieser Klasse für jede Zeichenfläche zu erstellen, um x, y, Geschwindigkeit und andere Variablen sicherzustellen separate

Ich verzweigte eine Geige von @JupeP, wo ich eine Basisklasse und neue Instanzen für jede Leinwand durch die Übergabe der einzelnen Canvas-ID erstellen.

http://jsfiddle.net/jtjpv2bf/1/

<canvas id="myCanvas" width="800" height="400" style="border:1px solid #000000;"></canvas> 
<canvas id="myCanvas1" width="400" height="400" style="border:1px solid #000000;"></canvas> 
<canvas id="myCanvas2" width="200" height="200" style="border:1px solid #000000;"></canvas> 
<canvas id="myCanvas3" width="600" height="300" style="border:1px solid #000000;"></canvas> 

window.requestAnimFrame = 
    window.requestAnimationFrame || 
    window.webkitRequestAnimationFrame || 
    window.mozRequestAnimationFrame || 
    function(callback) { 
    window.setTimeout(callback, 1000/60); 
    }; 

AnimationHandler = function(canvasId) { 

    var canvas, WIDTH, HEIGHT, 
     ctx, dx, dy, x, y; 

    function init() { 
    // find the <canvas> element 
    canvas = document.getElementById(canvasId); 
    WIDTH = canvas.width; 
    HEIGHT = canvas.height; 
    // get canvas context 
    ctx = canvas.getContext("2d"); 
    (...) 
    } 

    AnimationHandler.prototype = {} 
    AnimationHandler.prototype.constructor = init; 
    ... 
    return init(); 
}; 

new AnimationHandler("myCanvas"); 
new AnimationHandler("myCanvas1"); 
new AnimationHandler("myCanvas2"); 
new AnimationHandler("myCanvas3"); 

request

Bedenken Sie auch request statt setInterval verwenden. Es ist eine optimierte API, die Browser für gleichzeitige Animationen verwenden und wird angehalten, wenn sie nicht in einem aktiven Tab ist (spart Batterie/verbessert die Leistung).

Paul Irish erklärt es here

+1

Danke, das hilft viel! Wird sicher über requestAnimationFrame lesen. @bfmags –

Verwandte Themen