我想每次撞到墙壁时都会改变球的弹跳角度.
它将根据它击中墙壁中间的距离而发生变化......
现在,当我遇到表面时,我很难对X和Y的变化进行编码......我的目标是从当前的X和Y获得度数,对度数应用一个变化(现在我随机添加一个数字到度),然后计算X和Y的新增量值.我知道如何获得newX和newY,但不知道如何获得增量值.
绿色是开始x y的(5,5)......蓝色是下一帧(4,4).

45基于此的度数.currX(5) - wallX(0)= distX(5)
currY(5) - wallY(0)= distY(5)
取我的角度的余弦+随机增量,我们会说55度,*distX
cos(55 degrees) = .5735... .5735 x distX (5) = 2.86
和我的角度的罪恶*distiy
sin(55 degrees) = .8191... .8191 x distY (5) = 4.09
newX = cos result (2.86) + originX (5) = 7.86
newY = sin result (4.09) + originY (5) = 9.09
newX, newY = (7.86, 9.09)
好的......所以我有了新的坐标......
但那些并不等于我的新增量值,x而y应该基于我的发病率角度.
代码片段:你可以看到我很难对x,y增量进行编码(dragger.x += 2; )
function tick() {
var rand = Math.floor((Math.random()*10)+1);
console.log("ticking..." + rand);
if (dragger.x >= 400-20) {
dragger.xDir = "right";
}
if (dragger.x < 20) {
dragger.xDir = "left";
}
if (dragger.y >= 150-20) {
dragger.yDir = "up";
}
if (dragger.y < 20) {
dragger.yDir = "down";
}
var oldX = dragger.y;
var oldY = dragger.x;
if (dragger.xDir == "left") {
dragger.x += 2;
}
else {
dragger.x -= 2;
}
if (dragger.yDir == "up") {
dragger.y -= 2;
}
else {
dragger.y += 2;
}
//post update...
var newX = dragger.y;
var newY = dragger.x;
var angle = getAngle(newX, oldX, newY, oldY)
angle+=rand;
$('#getAngle').empty();
$('#getAngle').append("bounce angle (degrees): " + angle);
//console.log(xDir);
// update the stage:
stage.update();
}
function getAngle(x2, x1, y2, y1) {
var deltaX = Math.abs(x2-x1);
var deltaY = Math.abs(y2-y1);
var radians = Math.atan2(deltaX, deltaY);
var degrees = radians * (180/Math.PI);
return degrees;
}
Run Code Online (Sandbox Code Playgroud)
由于它的特异性,这是一个非常有趣的问题.
用编程语言弹球可以很容易地完成.像这个例子.
但显然,你的问题不是"让它发挥作用"; 你想要明确控制坐标和角度,以便你可以根据自己的想法改变它们.
因为我非常容易受到书呆子狙击,所以我摒弃了几何技能并想出了下面的伪代码(我从头开始做这个以确保我完全控制):


theta = starting angle
a = current x-coordinate of ball
b = current y-coordinate of ball
quadrant = quadrant-direction to which ball is moving
/> Determine number between 1 and 360: theta
/> Calculate quadrant
.> 0-90 : quadrant 1: horizontal: 90-a vertical: b alpha: 90 - theta
.> 90-180: quadrant 4: horizontal: 90-a vertical: 30-b alpha: theta - 90
.> 180-270: quadrant 3: horizontal: a vertical: 30-b alpha: 270 - theta
.> 270-360: quadrant 2: horizontal: a vertical: b alpha: theta - 270
/> Calculate distance to side |
/> Calculate distance to top/bottom |
.> to side: n(alpha) = horizontal/cos(alpha)
.> to top/bottom: m(alpha) = vertical /sin(alpha)
/> Determine where ball is going to hit (n = side, m = top/bottom)
.> n >= m : bounces at top/bottom
.> m >= n : bounces at side
.> switch (quadrant)
.> 1 : n = right side m = top
.> 2 : n = left side m = top
.> 3 : n = left side m = bottom
.> 4 : n = right side m = bottom
/> Calculate coordinates of hit
/> Define new angle
// Normally, angle of impact = angle of reflection
// Let's define the angle of impact with respect to the origin (0,0)
.> switch (quadrant)
.> 1 :
.> n >= m (at top/bottom) : x = a + vertical*tan(alpha) y = 0 theta = 180-theta
.> m >= n (at side) : x = 90 y = b - horizontal*tan(alpha) theta = 270+alpha
.> 2 :
.> n >= m (at top/bottom) : x = a - vertical/tan(alpha) y = 0 theta = 270-alpha
.> m >= n (at side) : x = 0 y = b - horizontal*tan(alpha) theta = 90-alpha
.> 3 :
.> n >= m (at top/bottom) : x = a - vertical/tan(alpha) y = 30 theta = 270+alpha
.> m >= n (at side) : x = 0 y = b + horizontal*tan(alpha) theta = 90+alpha
.> 4 :
.> n >= m (at top/bottom) : x = a + vertical/tan(alpha) y = 30 theta = 90-alpha
.> m >= n (at side) : x = 90 y = b + horizontal*tan(alpha) theta = 270-alpha
/> Define new coordinates (for reusage of function)
.> a = x
.> b = y
.> (optional) if you would like the angles to differ, enter extra term here:
.> extra = ...
.> theta = theta + extra
Run Code Online (Sandbox Code Playgroud)
实现此代码将允许您使用度数的简单性并仍然能够确定坐标.
它的工作原理如下:
首先确定球的初始位置(a,b)和它的初始方向(theta)
现在该程序将计算:
然后它重新开始计算新的命中.
在JavaScript中,代码如下所示:
var width = 500;
var height = 200;
var extra = 0;
var a;
var b;
var x;
var y;
var angle;
var n;
var m;
var quadrant;
var horizontal;
var vertical;
var alpha;
var side;
var topbottom;
var sides;
var i = 1;
var txt=document.getElementById("info");
txt.innerHTML="x: "+a+"<br>y: "+b+"<br>angle: "+angle+"<br>quadrant: "+quadrant;
function buttonClick()
{
if (i == 1)
{
a = 75;
b = 75;
//determine first angle randonmly
angle = Math.floor((Math.random()*360)+1);;
} else
{
a = xcoord();
b = ycoord();
}
var oldAngle = angle;
angle = findNewCoordinate(a, b, angle);
sides = hitWhere();
var txt=document.getElementById("info");
txt.innerHTML="x: "+a+"<br>y: "+b+"<br>horizontal: "+horizontal+"<br>vertical: "+vertical+"<br>n: "+n+"<br>m: "+m+"<br>angle: "+oldAngle+"<br>alpha: "+alpha+"<br>quadrant: "+quadrant+"<br>side: "+topbottom+side+"<br>"+sides+"<br>"+i;
i++;
}
function findNewCoordinate(a, b, angle)
{
if (angle >= 0 && angle < 90) { quadrant = 1; horizontal = width-a; vertical = b; alpha = (90 - angle); }
else if (angle >= 90 && angle < 180) { quadrant = 4; horizontal = width-a; vertical = height-b; alpha = (angle-90); }
else if (angle >= 180 && angle < 270) { quadrant = 3; horizontal = a; vertical = height-b; alpha = (270-angle); }
else if (angle >= 270 && angle <= 360) { quadrant = 2; horizontal = a; vertical = b; alpha = (angle-270); }
var cosa = Math.cos(alpha * Math.PI / 180);
var sina = Math.sin(alpha * Math.PI / 180);
var tana = Math.tan(alpha * Math.PI / 180);
var tant = Math.tan(angle * Math.PI / 180);
n = horizontal/cosa;
m = vertical/sina;
switch (quadrant)
{
case 1:
if (m >= n) //hit at side
{
y = b - horizontal*tana;
x = width;
angle = 270+alpha;
} else
{
y = 0;
x = a + vertical*tant;
angle = 180-angle;
}
side = "right side"; topbottom = "top";
break;
case 2:
if (m >= n) //hit at side
{
y = b-horizontal*tana;
x = 0;
angle = 90-alpha;
} else
{
y = 0;
x = a - vertical/tana;
angle = 270-alpha;
}
side = "left side"; topbottom = "top";
break;
case 3: side = "left side"; topbottom = "bottom";
if (m >= n) //hit at side
{
x = 0;
y = b + tana*horizontal;
angle = 90+alpha;
} else
{
y = height;
x = a - vertical/tana;
angle = 270+alpha;
} break;
case 4: side = "right side"; topbottom = "bottom";
if (m >= n) //hit at side
{
y = b+horizontal*tana;
x = width;
angle = 270-alpha;
} else
{
y = height;
x = a + vertical/tana;
angle = 90-alpha;
} break;
}
//add extra degrees to the angle (optional)
angle += extra;
context.beginPath();
context.arc(a, b, 5, 0, Math.PI*2, true);
context.stroke();
context.closePath();
context.fill();
drawLine(a,b,x,y);
return angle;
}
Run Code Online (Sandbox Code Playgroud)
请注意,还有很多方法可以制作弹跳程序.但是,因为我在几何上解决了这个问题而没有"快捷方式",所以我的程序的独特特性使你可以很容易地将它改变为你的喜好:
var extra).另请注意,我没有使程序非常简洁,因为这根本不是我的目标.我想创造一个弹跳球程序,尽管它是长度的,但却完全体现了它背后的几何直觉.
你可以在这个JSFiddle中找到我的程序的演示.请注意,起始角度是随机确定的.因此重新启动程序将给出不同的角度.

嗯,就是这样.
祝你好好构建其余的程序!
| 归档时间: |
|
| 查看次数: |
2293 次 |
| 最近记录: |