使用Tululoo Game Maker API编程游戏时,我正在准确计算碰撞,因为从弧度计算x和y。
下面x和y的计算产生了大量的小数点,我发现很难检查碰撞。
image_angle是子弹最初使用的手枪的最终角度。
在设置中:
x = instance_list(pistol)[0].x;
y = instance_list(pistol)[0].y;
startAng = instance_list(pistol)[0].image_angle;
this.travelX = cos(degtorad(instance_list(pistol)[0].image_angle)) * 5;
this.travelY = sin(degtorad(instance_list(pistol)[0].image_angle)) * 5;
在更新框架中:
x+=this.travelX;
y+=this.travelY;
计算球将从墙上反弹的角度,凌乱我知道:
for(var i = 0; i < instance_number(bounce_barrier);i++){
if(place_meeting(x,y,instance_list(bounce_barrier)[i])){
if(Math.round(x*10)/10 > instance_list(bounce_barrier)[i].x ){
newAng = 180 - startAng;
this.travelX = +cos(degtorad(newAng)) * 15;
this.travelY = +sin(degtorad(newAng)) * 15;
startAng = newAng;
}
else if(y > instance_list(bounce_barrier)[i].y - 5 && y <= instance_list(bounce_barrier)[i].y + 10){
newAng = 180 - startAng;
this.travelX = -cos(degtorad(newAng)) * 15;
this.travelY = -sin(degtorad(newAng)) * 15;
startAng = newAng;
}
else if(y <= instance_list(bounce_barrier)[i].y - 5 + bounce_spr.height && y >= instance_list(bounce_barrier)[i].y + bounce_spr.height - 10){
newAng = 180 - startAng;
this.travelX = -cos(degtorad(newAng)) * 15;
this.travelY = -sin(degtorad(newAng)) * 15;
startAng = newAng;
}
else if(x < instance_list(bounce_barrier)[i].x){
newAng = 180 - startAng;
this.travelX = +cos(degtorad(newAng)) * 15;
this.travelY = +sin(degtorad(newAng)) * 15;
startAng = newAng;
}
else{}
}
}
place_meeting是Tululoo Game API的一部分:
function __place_meeting__(nx, ny, what, many) {
this.other = null;
var i, l,
// sprite, scale:
ts = this.sprite_index,
tsx, tsy, tfx, tfy, tst,
// circle:
tcx, tcy, tcr,
// bbox:
tbl, tbr, tbt, tbb,
// instances, multiple, output, types:
tz, tm, ct, ch, ra,
// other:
o, ox, oy, os, ost, osx, osy, ofx, ofy, ofr;
if (ts == null) return false;
tfx = ts.xoffset;
tfy = ts.yoffset;
tsx = this.image_xscale;
tsy = this.image_yscale;
tst = ts.collision_shape;
// bbox:
if (tst == 2) {
tbl = nx + tsx * (ts.collision_left - tfx);
tbr = nx + tsx * (ts.collision_right - tfx);
tbt = ny + tsy * (ts.collision_top - tfy);
tbb = ny + tsy * (ts.collision_bottom - tfy);
}
// circle:
if (tst == 3) {
tcr = ts.collision_radius * (tsx > tsy ? tsx : tsy);
tcx = nx + tsx * (ts.width / 2 - tfx);
tcy = ny + tsy * (ts.height / 2 - tfy);
}
//
tz = (what.__instance ? [what] : instance_list(what));
tm = many ? true : false;
if (tm) ra = [];
l = tz.length;
for (i = 0; i < l; i++) {
o = tz[i];
if (!o.collision_checking) continue;
os = o.sprite_index;
if (os == null) continue;
ox = o.x; osx = o.image_xscale;
oy = o.y; osy = o.image_yscale;
ost = os.collision_shape;
ct = (tst << 4) | ost;
ch = false;
switch(ct) {
case 0x22:
if (osx == 1 && osy == 1) {
ofx = os.xoffset; ofy = os.yoffset;
if (!collide_bbox_bbox(tbl, tbt, tbr, tbb,
ox + os.collision_left - ofx, oy + os.collision_top - ofy,
ox + os.collision_right - ofx, oy + os.collision_bottom - ofy)) break;
} else if (!collide_bbox_sbox(tbl, tbt, tbr, tbb, ox, oy, osx, osy, os)) break;
ch = true;
break;
case 0x23:
ofr = os.collision_radius * (osx > osy ? osx : osy);
ofx = ox + osx * (os.width / 2 - os.xoffset);
ofy = oy + osy * (os.height / 2 - os.yoffset);
if (!collide_bbox_circle(tbl, tbt, tbr, tbb, ofx, ofy, ofr)) break;
ch = true;
break;
case 0x32:
if (osx == 1 && osy == 1) {
ofx = os.xoffset; ofy = os.yoffset;
if (!collide_bbox_circle(
ox + os.collision_left - ofx, oy + os.collision_top - ofy,
ox + os.collision_right - ofx, oy + os.collision_bottom - ofy,
tcx, tcy, tcr)) break;
} else if (!collide_sbox_circle(ox, oy, osx, osy, os, tcx, tcy, tcr)) break;
ch = true;
break;
case 0x33:
ofr = os.collision_radius * (osx > osy ? osx : osy);
ofx = ox + osx * (os.width / 2 - os.xoffset);
ofy = oy + osy * (os.height / 2 - os.yoffset);
if (!collide_circle_circle(tcx, tcy, tcr, ofx, ofy, ofr)) break;
ch = true;
break;
} if (!ch) continue;
this.other = o;
o.other = this;
if (!tm) return (o);
ra.push(o);
} return ra;
}
我已经设法让一颗子弹从墙上弹开,其角度与射击的位置成比例,但是碰撞检测非常糟糕,因为它会反射一些子弹但不是全部,有些直接穿过墙壁。
刚刚添加了Line Collision Detection,我做了子弹线,所以我可以看到
this.oldTravelX,this.oldTravelY到this.travelX,this.travelY。它肯定有所改善,但有些子弹仍然在经历。
一些子弹似乎粘在弹跳区域内或滑动弹跳区左侧,然后决定是向左还是向右。
更新代码:
pntdis = point_distance(this.oldTravelX, this.oldTravelY, this.travelX, this.travelY);
noPoints = pntdis/0.01;
for(var i=0; i < pntdis; i+=noPoints)
{
pointsArrX[i] = this.travelX - (this.oldTravelX * i);
pointsArrY[i] = this.travelY - (this.oldTravelY * i);
}
for(var i=0;i<pointsArrX.length;i++){
if(place_meeting(Math.round(pointsArrX[i]),Math.round(pointsArrY[i]),bounce_barrier) || place_meeting(x,y,bounce_barrier))
{
newAng = 180 - startAng;
this.travelX = +cos(degtorad(newAng)) * 15;
this.travelY = +sin(degtorad(newAng)) * 15;
startAng = newAng;
}
}
提前致谢。
答案 0 :(得分:1)
看起来place_meeting
函数应该确定子弹和障碍物之间是否存在碰撞。但是,此功能仅占用子弹的新位置。鉴于子弹每次更新移动5个单位,子弹可能会在一个框架内从障碍的一侧移动到另一侧。 e.g:
|
. |
\| barrier
\
|\_______
\
.
place_meeting
应该同时采用子弹的新旧位置,以便确定是否有任何中间位置与障碍物碰撞(例如,通过与子弹的路径和边缘进行线 - 线交叉测试屏障;它应该也可以返回碰撞点。)
修改强>
您的更新代码看起来像是要检查子弹路径上的多个点的碰撞。有更快的方法可以做到这一点,但您的方法可能足够快,并且易于理解。您计算要检查的点数似乎存在错误。
在纸上手动单步执行代码:
pntdis = 5 // assume point_distance returns 5
noPoints = 5 / 0.01 = 500
i = 0
pointsArrX[0] = this.travelX
pointsArrY[0] = this.travelY
i = i + noPoints = 500
500 < 5: false, for loop ends
需要考虑的其他事项:
break
声明,因此您不会继续测试其他点。for
循环组合成一个,因为您没有重复使用数组中的值。只需计算您的测试点,然后立即进行测试。console.log
在程序运行时输出调试信息,以便更好地了解正在发生的事情。var
(例如pntdis
和noPoints
),以避免意外创建全局变量。