PDA

View Full Version : A little help needed on improving raycasting.



yodalr
January 8th, 2008, 11:02 AM
Ok, I'm not a very good programmer(lol, I mean scripter... I'm too far from programmer). Right now I'm working on a game, when starting the project I quickly ran into well known hitTest-highspeed bullets problem, where the bullets were going through targets. So I googled and found out about raycasting in 2D, but I wasn't able to find good/easy tutorials on it, mainly theory and math, so I started mixing something together by myself.

The results... hmm better than hitTesting, but far from OK.
Have a look at yourself: http://www.lrstudio.eu/si/
Problems:
1. A little unstable on fps(when bullets are hitting the wall).
2. Sometimes the ray goes through target and targets behind the first one.

Here's the bullet generation code:

closestTarget = 1000;
function genBullet() {
var myBullet = attachMovie("bullet_mc", "bullet_nr"+total_bullets, total_bullets--, {_rotation:john_faust._rotation, _x:john_faust._x, _y:john_faust._y});
myBullet.reachedTarget = false;
myBullet.bulletMind = function() {
//securing bullets entity removal
//trace(this.matterActivate);
this.degrees = john_faust.myDegrees;
this.radians = this.degrees*(Math.PI/180);
//trace(john_faust.myDegrees);
john_faust.lineOfSight._height = closestTarget;
//line of sight
for (var m = obstacles+1; m<=enemies+obstacles; m++) {
matterActive = eval("matter"+m);
//trace(eval("matter"+m));
//Speed always positve
matterActive.matterDistance = Math.sqrt(((matterActive._x-john_faust._x)*(matterActive._x-john_faust._x))+((matterActive._y-john_faust._y)*(matterActive._y-john_faust._y)));
matterActive.matterRadians = Math.atan2(matterActive._y-john_faust._y, matterActive._x-john_faust._x);
matterActive.matterDegrees = (matterActive.matterRadians*180/Math.PI);
if ((john_faust.myDegrees>matterActive.matterDegrees-(((matterActive._width/2)/matterActive.matterDistance)*50)) && (john_faust.myDegrees<matterActive.matterDegrees+(((matterActive._width/2)/matterActive.matterDistance)*50))) {
if (matterActive.alreadySelected != true) {
targetsOnSight += 1;
matterActive.alreadySelected = true;
}
if ((matterActive.matterDistance>closestTarget) && (matterActive.onSight == true)) {
matterActive.onSight = false;
closestTarget = 1000;
} else if (matterActive.matterDistance<closestTarget) {
closestTarget = matterActive.matterDistance+john_faust.speed*2+5;
matterActive.onSight = true;
if (matterActive.speed>0) {
matterActive.speed -= 2;
}
this.removeMovieClip();
}
} else {
if (matterActive.alreadySelected == true) {
targetsOnSight -= 1;
matterActive.alreadySelected = false;
}
if (targetsOnSight == 0) {
closestTarget = 1000;
if ((((john_faust.myDegrees<-90) && (john_faust.myDegrees<0)) || ((john_faust.myDegrees>90) && (john_faust.myDegrees>0)))) {
this.between1 = matter1._x-john_faust._x;
this.median1 = (this.between1)*(Math.tan(this.radians));
this.theBulletPlace1 = ((john_faust._y-15.2)+(this.median1)+(Math.random()*12-5));
if ((this.theBulletPlace1>27.5) && (this.theBulletPlace1<264)) {
_level0.main_mc.matter1.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter1.getNextHighestDepth(), {_rotation:-180, _x:Math.random()*11-5, _y:this.theBulletPlace1});
this.removeMovieClip();
} else {
this.between2 = matter2._x-john_faust._x;
this.median2 = (this.between2)*(Math.tan(this.radians));
this.theBulletPlace2 = ((john_faust._y-15.2)+(this.median2)+(Math.random()*12-5));
if ((this.theBulletPlace2<-27.5) && (this.theBulletPlace2>-264)) {
_level0.main_mc.matter2.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter2.getNextHighestDepth(), {_rotation:-180, _x:Math.random()*11-5, _y:this.theBulletPlace2});
this.removeMovieClip();
} else {
this.between9 = matter9._x-john_faust._x;
this.median9 = (this.between9)*(Math.tan(this.radians));
this.theBulletPlace9 = ((john_faust._y-15.2)+(this.median9)+(Math.random()*12-5));
if ((this.theBulletPlace9>-24) && (this.theBulletPlace9<24)) {
_level0.main_mc.matter9.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter9.getNextHighestDepth(), {_rotation:-180, _x:Math.random()*6-1, _y:this.theBulletPlace9});
this.removeMovieClip();
}
}
}
} else if ((((john_faust.myDegrees<90) && (john_faust.myDegrees>0)) || ((john_faust.myDegrees>-90) && (john_faust.myDegrees<0)))) {
this.between5 = matter5._x-john_faust._x;
this.median5 = (this.between5)*(Math.tan(this.radians));
this.theBulletPlace5 = ((john_faust._y-15.2)+(this.median5)+(Math.random()*12-5));
if ((this.theBulletPlace5<-27.5) && (this.theBulletPlace5>-264)) {
_level0.main_mc.matter5.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter5.getNextHighestDepth(), {_x:Math.random()*11-5, _y:this.theBulletPlace5});
this.removeMovieClip();
} else {
this.between6 = matter6._x-john_faust._x;
this.median6 = (this.between6)*(Math.tan(this.radians));
this.theBulletPlace6 = ((john_faust._y-15.2)+(this.median6)+(Math.random()*12-5));
if ((this.theBulletPlace6>27.5) && (this.theBulletPlace6<264)) {
_level0.main_mc.matter6.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter6.getNextHighestDepth(), {_x:Math.random()*11-5, _y:this.theBulletPlace6});
this.removeMovieClip();
} else {
this.between11 = matter11._x-john_faust._x;
this.median11 = (this.between11)*(Math.tan(this.radians));
this.theBulletPlace11 = ((john_faust._y-15.2)+(this.median11)+(Math.random()*12-5));
if ((this.theBulletPlace11>-24) && (this.theBulletPlace11<24)) {
_level0.main_mc.matter11.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter11.getNextHighestDepth(), {_rotation:-180, _x:Math.random()*6-1, _y:this.theBulletPlace11});
this.removeMovieClip();
}
}
}
}
if ((john_faust.myDegrees<0) && (john_faust.myDegrees>-180)) {
this.between3 = matter3._y-john_faust._y;
this.median3 = (this.between3)/(Math.tan(this.radians));
this.theBulletPlace3 = ((john_faust._x)+(this.median3)+(Math.random()*12-5));
if ((this.theBulletPlace3<-27.5) && (this.theBulletPlace3>-349)) {
_level0.main_mc.matter3.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter3.getNextHighestDepth(), {_rotation:-90, _x:this.theBulletPlace3, _y:Math.random()*8-4});
this.removeMovieClip();
} else {
this.between4 = matter4._y-john_faust._y;
this.median4 = (this.between4)/(Math.tan(this.radians));
this.theBulletPlace4 = ((john_faust._x)+(this.median4)+(Math.random()*12-5));
if ((this.theBulletPlace4>27.5) && (this.theBulletPlace4<349)) {
_level0.main_mc.matter4.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter4.getNextHighestDepth(), {_rotation:-90, _x:this.theBulletPlace4, _y:Math.random()*8-4});
this.removeMovieClip();
} else {
this.between10 = matter10._y-john_faust._y;
this.median10 = (this.between10)/(Math.tan(this.radians));
this.theBulletPlace10 = ((john_faust._x)+(this.median10)+(Math.random()*12-5));
if ((this.theBulletPlace10>-24) && (this.theBulletPlace10<24)) {
_level0.main_mc.matter10.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter10.getNextHighestDepth(), {_rotation:-180, _x:Math.random()*6-1, _y:-this.theBulletPlace10});
this.removeMovieClip();
}
}
}
} else if ((john_faust.myDegrees>0) && (john_faust.myDegrees<180)) {
this.between7 = matter7._y-john_faust._y;
this.median7 = (this.between7)/(Math.tan(this.radians));
this.theBulletPlace7 = ((john_faust._x)+(this.median7)+(Math.random()*12-5));
if ((this.theBulletPlace7>27.5) && (this.theBulletPlace7<349)) {
_level0.main_mc.matter7.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter7.getNextHighestDepth(), {_rotation:90, _x:this.theBulletPlace7, _y:Math.random()*8-4});
this.removeMovieClip();
} else {
this.between8 = matter8._y-john_faust._y;
this.median8 = (this.between8)/(Math.tan(this.radians));
this.theBulletPlace8 = ((john_faust._x)+(this.median8)+(Math.random()*12-5));
if ((this.theBulletPlace8<-27.5) && (this.theBulletPlace8>-349)) {
_level0.main_mc.matter8.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter8.getNextHighestDepth(), {_rotation:90, _x:this.theBulletPlace8, _y:Math.random()*8-4});
this.removeMovieClip();
} else {
this.between12 = matter12._y-john_faust._y;
this.median12 = (this.between12)/(Math.tan(this.radians));
this.theBulletPlace12 = ((john_faust._x)+(this.median12)+(Math.random()*12-5));
if ((this.theBulletPlace12>-24) && (this.theBulletPlace12<24)) {
_level0.main_mc.matter12.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.matter12.getNextHighestDepth(), {_rotation:-180, _x:Math.random()*6-1, _y:-this.theBulletPlace12});
this.removeMovieClip();
}
}
}
}
}
if (matterActive.onSight == true) {
matterActive.onSight = false;
closestTarget = 1000;
}
}
}
};
myBullet.bulletMind();
bullets.text = "BULLETS:"+total_bullets;
if (total_bullets == 0) {
holdFire();
}
}

I really hope someone can give me some tips/help here, cause I keep running into wall with this one, thanks.

Jerryscript
January 8th, 2008, 01:47 PM
Here's a great tutorial on vectors and how to determine collisions and reactions: http://www.tonypa.pri.ee/vectors/start.html

yodalr
January 9th, 2008, 03:04 AM
Here's a great tutorial on vectors and how to determine collisions and reactions: http://www.tonypa.pri.ee/vectors/start.html


tnx, this link is really useful

yodalr
January 11th, 2008, 09:42 AM
Muhahahaa(read - evil world dominator laugh)

I finally got it working the way I intended.

Right now there are 100 enemy objects: http://www.lrstudio.eu/si/raycast/

Thanks all for help!

If anyone runs into same trouble in future, here's the final raycasting codes:

function checkRadius(matterActive) {
matterActive.matterDistance = Math.sqrt(((matterActive._x-john_faust._x)*(matterActive._x-john_faust._x))+((matterActive._y-john_faust._y)*(matterActive._y-john_faust._y)));
matterActive.matterRadians = Math.atan2(matterActive._y-john_faust._y, matterActive._x-john_faust._x);
matterActive.matterDegrees = (matterActive.matterRadians*180/Math.PI);
}
function checkOb(ob, ax, ay) {
var dx = px-ob.x;
var dy = py-ob.y;
var dist = ob.matterDistance;
var nx = dx/dist;
var ny = dy/dist;
var cx = ax*dist;
var cy = ay*dist;
var ex = (px+cx)-ob.x;
var ey = (py+cy)-ob.y;
var nd = ex*ex+ey*ey;
if (nd<ob.r2) {
return dist;
}
return null;
}
function openFire() {
if (total_bullets>0) {
weapon_mc.play();
head_mc.play();
weaponSound.start(0, 100);
fireBullets();
}
}
function genBullet() {
//rayCasting
var mx = crosshair._x-px;
var my = crosshair._y-py;
var dist = Math.sqrt(mx*mx+my*my);
var ax = mx/dist;
var ay = my/dist;
//find closestTarget object
var closest = [];
var closestTarget = undefined;
var i = obs.length;
while (--i>=0) {
var ob = obs[i];
checkRadius(ob);
if ((john_faust.myDegrees>ob.matterDegrees-(((ob._width/2)/ob.matterDistance)*50)) && (john_faust.myDegrees<ob.matterDegrees+(((ob._width/2)/ob.matterDistance)*50))) {
var dist = checkOb(ob, ax, ay);
if (dist != null) {
closest.push({ob:ob, dist:dist});
}
}
}
closest.sortOn("dist", Array.NUMERIC);
closestTarget = closest[0].ob;
if (closestTarget.speed>0) {
closestTarget.speed -= 2;
}
if (closestTarget == undefined) {
var bulletRotation = john_faust._rotation;
var bulletRadians = bulletRotation*(Math.PI/180);
if ((bulletRotation<0) && (bulletRotation>-180)) {
//trace("west");
var johnFaustDistanceFromWestWall = westWall._x-john_faust._x;
var johnFaustDistanceFromBulletHittingPoint = (johnFaustDistanceFromWestWall)/(-Math.tan(bulletRadians));
var theBulletHittingWallCoordinate = john_faust._y+johnFaustDistanceFromBulletHittingPo int+(Math.random()*12-5);
if ((theBulletHittingWallCoordinate>westWall._y) && (theBulletHittingWallCoordinate<westWall._y+westWall._height)) {
_level0.main_mc.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.getNextHighestDepth(), {_rotation:-180, _x:westWall._x+7+Math.random()*11-5, _y:theBulletHittingWallCoordinate});
}
} else if ((bulletRotation>0) && (bulletRotation<180)) {
//trace("east");
var johnFaustDistanceFromeastWall = eastWall._x-john_faust._x;
var johnFaustDistanceFromBulletHittingPoint = (johnFaustDistanceFromeastWall)/(-Math.tan(bulletRadians));
var theBulletHittingWallCoordinate = john_faust._y+johnFaustDistanceFromBulletHittingPo int+(Math.random()*12-5);
if ((theBulletHittingWallCoordinate>eastWall._y) && (theBulletHittingWallCoordinate<eastWall._y+eastWall._height)) {
_level0.main_mc.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.getNextHighestDepth(), {_rotation:0, _x:eastWall._x-7+Math.random()*11-5, _y:theBulletHittingWallCoordinate});
}
}
if ((((bulletRotation<-90) && (bulletRotation<0)) || ((bulletRotation>90) && (bulletRotation>0)))) {
//trace("south");

var johnFaustDistanceFromsouthWall = southWall._y-john_faust._y;
var johnFaustDistanceFromBulletHittingPoint = (johnFaustDistanceFromsouthWall)*(-Math.tan(bulletRadians));
var theBulletHittingWallCoordinate = john_faust._x+johnFaustDistanceFromBulletHittingPo int+(Math.random()*12-5);
if ((theBulletHittingWallCoordinate>southWall._x) && (theBulletHittingWallCoordinate<southWall._x+southWall._width)) {
_level0.main_mc.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.getNextHighestDepth(), {_rotation:90, _y:southWall._y-6+Math.random()*11-5, _x:theBulletHittingWallCoordinate});
}
} else if ((((bulletRotation<90) && (bulletRotation>0)) || ((bulletRotation>-90) && (bulletRotation<0)))) {
//trace("north");
var johnFaustDistanceFromnorthWall = northWall._y-john_faust._y;
var johnFaustDistanceFromBulletHittingPoint = (johnFaustDistanceFromnorthWall)*(-Math.tan(bulletRadians));
var theBulletHittingWallCoordinate = john_faust._x+johnFaustDistanceFromBulletHittingPo int+(Math.random()*12-5);
if ((theBulletHittingWallCoordinate>northWall._x) && (theBulletHittingWallCoordinate<northWall._x+northWall._width)) {
_level0.main_mc.attachMovie("hole", "hole"+holeCounter, _level0.main_mc.getNextHighestDepth(), {_rotation:-90, _y:northWall._y+6+Math.random()*11-5, _x:theBulletHittingWallCoordinate});
}
}
}
//bullet used
total_bullets--;
bullets.text = "BULLETS:"+total_bullets;
if (total_bullets == 0) {
holdFire();
}
}If anyone sees even more ways to improve the code, let me know.