[Resolved] Detecing distance to player? (locked)

17 posts

Flag Post

Hi there,

I’m working on a game where there will be many moving objects on the screen at once, one of which is the player.

I need a way for the player to detect which of the other objects is currently closest to it and I am completely stumped.

Has anyone got any ideas or examples? Any help appreciated.

Thanks

 
Flag Post

well i would make a loop, find the coordinates and calculate the distance with a simple pythgore thing :)

 
Flag Post

well yeah, I already know the distance of every object to the player, but i need to know which of them is the lowest

 
Flag Post

What I would do is give every object you are testing a custom property called ‘dist’. Then, every time you calculate the distance between the player and an object, store the value in ‘dist.’ Then you can have a for loop that runs every frame (or on an interval) which loops through all of your objects (if they’re not in an array try using the array access notation _root[object1], _root[object2], etc.) and get a reference to the closest one.

 
Flag Post

when you calculate dist you can test it versus a global “shortest dist” or a “shortest dist” as part of the player object, then if the new dist value isnt smaller then you dont have to store it or keep track for your purposes, making one less entire loop through all the values vs. the above solution which is quoted here:

“Then you can have a for loop that runs every frame (or on an interval) which loops through all of your objects (if they’re not in an array try using the array access notation _root[object1], _root[object2], etc.) and get a reference to the closest one.”

 
Flag Post

Well okay storing a global variable is way more efficient than doing a loop on every frame. :(

when you calculate dist you can test it versus a global “shortest dist” or a “shortest dist” as part of the player object

…then store a reference to the closest object in your player object also, so you can use this for something later.

It might still be helpful to keep the distance value stored in each object in case you needed to do some other calculations, such as second closest, etc.

 
Flag Post


There are a variety of ways, all depending on situation, cpu usage, how the rest of your engine works, etc. Here are a couple that I’ll demonstrate using basic objects with distances already saved:

You can do a number check as mentioned using Math.min():

// Objects to check against
var p0:Object = { ID:"Bat", dist:100 };
var p1:Object = { ID:"Rock", dist:300 };
var p2:Object = { ID:"House", dist:200  };

// Array that has all the objects
var objects_array:Array = new Array( p0, p1, p2 );


function getClosest(): Object
{
	var closestObject:Object;
	var smallestDist:Number = 999999999;
	
	// Check whos closest  
	for ( var i:Number = objects_array.length-1; i>-1; i-- ){
		
		// Get an object
		var obj:Object = objects_array[i];
		
		// Remember who's closest
		smallestDist = Math.min ( smallestDist, obj.dist );
		
		// Save reference to closest object
		if( obj.dist == smallestDist)closestObject = obj;
	}
	
	return closestObject;
}

// 
var closestObject:Object = getClosest();

trace( closestObject.ID +" is closest with a distance of: "+ closestObject.dist );



Or you can sort all the objects in an array by lowest to highest distance and then get the first item in the array. This is the easiest way for some:



// Objects to check against
var p0:Object = { ID:“Bat”, dist:100 };
var p1:Object = { ID:“Rock”, dist:300 };
var p2:Object = { ID:“House”, dist:200 };

// Array that has all the objects
var objects_array:Array = new Array( p0, p1, p2 );

// Array sorting method
function SortDistance (a, b): Boolean
{
return a.dist > b.dist;
}

function getClosest(): Object
{
// Sort array by distance
objects_array.sort( SortDistance );

// Get closest object (first one, since we sorted ASC)
return objects_array0;
}

//
var closestObject:Object = getClosest();

trace( closestObject.ID " is closest with a distance of: " closestObject.dist );


If you just need the smallest number and not the actual object, you can use less code.


Also, whenever you get distances you can use the Point class for ease of use, or a barebones Pythagorean theorem (no Math.sqrt) if you want something faster. I mostly use the Pythagorean method.

 
Flag Post

acctually i came up with a way more simple soloution, every object has a variable D for its distance to the player, and theres a _root variable called lowest dist, all the objects have the code

if (D< _root.lowestdist){
_root.lowestdist = D;
_root.closestObject = _name;
}

so there you go…look out for the feature in the sequel to cosmic crush!

 
Flag Post


Thats the same concept as the first one with Math.min, except you are not coding on the _root (which you should not be doing) and works on your reference arrays (which you should be using to track your objects anyways). In fact if you just wanted the smalled number, you could just use the 1 Math.min() line itself and wouldn’t even need an if statement.

As I said, there are a variety of ways. The only reason is seems simpler is because I included extra code with full declarations to demonstrate the principle for use in many situations, including (but not limited to) more advanced object oriented engines. When you compare the applicable code you see they are about the same:


// Number 1
if ( D < _root.lowestdist ){
_root.lowestdist = D;
_root.closestObject = _name;
}

// Number 2
smallestDist = Math.min ( smallestDist, obj.dist );
if( obj.dist == smallestDist ){
closestObject = obj;
}

Any of the ways works, depending on your engine; except I strongly recommend you starting moving away from the use of _root. Its bad practice and additionally makes it more difficult to integrate your game into other environments. In fact, if so many people didnt code with _root or _level0, then there wouldnt have been so many integration issues with the games on the site and the upcoming Kongregate API. But do what you like, its just a suggestion ;)

For more info on best practices, theres a good article here. Its not entirely perfect but 99% of it is very well done.

PS Cosmic crush was cool, but I had a hard time with the slow performance. If you could optimize the next one that would be so awesome :) (Remember that fps always drops in the browser).

 
Flag Post

oh, yeah i understand everything you suggested, appreciate the help, I never really give much of a thought to good practices or anything though, its not like i do this professionally or have any intention to learn any other programming language.

my philosophy is, if it works, HOORAY!

 
Flag Post

Arcane is right on one major point, though, and that is not using _root anywhere in your code. Even if you don’t care for other best practices in coding (which is fine if you’re not a programmer, I totally understand), getting rid of references to _root in your code makes the game infinitely more portable.

In fact, I don’t think it would work on a site like GreatGamesExperiment if it had _root references in it (not that you would care, necessarily, but that’s one example). None of my games use _root, and I don’t miss it at all. In fact, I’ve never used it…

By the way, how did you get your code to format like that in this forum, Arcane? I’m sure I’ll need to know that for the future =P

And, Sarcastro, I’m looking forward to your next version of Cosmic Crush, keep up the good work!!

 
Flag Post

No problem. Even if you are not a pro, best practices help. They make coding more enjoyable.


Indie, I use the preformatted text html tags:

<pre>
 
Flag Post

OT but MovieClip._lockroot makes those _root integration problems pretty much go away, if you can require Flash 7 or later. Using _root isn’t really all that evil if it helps you get stuff done faster, especially in a game…

 
Flag Post


MovieClip.lockroot should only be used as a last result as it is a hack-like solution to a problem that will not exist if the project is coded properly in the first place. If you didnt read that ‘best practices’ article I linked to, heres are some quotes:


bq. *Avoiding Absolute Targets (’
root’)*
You can use several methods to target instances that let you avoid using _root; these methods are discussed later in this section. Avoid using _root in ActionScript 2.0 because SWF files that load into other SWF files might not work correctly. The _root identifier targets the base SWF file that is loading, not the SWF file using relative addressing instead of _root. This issue limits code portability in SWF files that are loaded into another file, and, particularly, in components and movie clips. You can help resolve problems by using _lockroot, but only use _lockroot when necessary (such as when you are loading a SWF file but do not have access to the FLA file).


Using ‘_lockroot’
You can use _lockroot to target content as a way to solve the scoping issues sometimes associated with the inappropriate use of _root. Although this solves many problems with applications, consider _lockroot as a work-around for problems caused by using _root.



It is such bad practice that in AS 3.0 (Flash 9) you cant even code like that anymore.

Additionally, _root only makes things faster if you want to code sloppily. That works fine in smaller projects, but when your game or application becomes more evolved, these bad practices tend to create more bugs and troubleshooting those bugs becomes even harder.

Trust me, I’ve been professionally coding for a long time. I’ve coded with it and without, so I know both sides very well ;). I even had to go to Kongregate’s office last week to help them iron out some bugs with the integration of the API/Ad system with the games because so many people have coded with bad scoping. If all the games coding had been scoped properly, things would have went a lot more smoothly (_lockroot did not even come close to solving the problems). Instead I had to devise a workaround to deal with this problem. root/level may not be evil to you, but it is when you have to deal with more complex situations. Its best avoided if at all possible.

 
Flag Post

I wouldn’t exactly say that AS3 doesn’t let you code like that anymore. It only lets you do it if you have a reference to some DisplayObject that’s in the hierarchy, but they do have a root property that can be used in much the same way. AS3 is pretty ridiculous in a lot of ways in that are really going to hurt the platform, but that’s another discussion for another day.

I’ve been professionally coding for a long time too, with about 8 years of Flash experience. I don’t use _root a whole lot myself, but it certainly has its uses. If you’re providing certain kinds of API to users, it makes a great default MovieClip reference because it’ll work for maybe 99% of most use cases with less work for the user. It’s also where you get URL variables, find out how big your SWF is and if it’s fully loaded, etc.

My real point is that people should do whatever they can get done quickest, provided that it works under the constraints they need it to. Games especially, because they’re usually relatively “throwaway” projects that are quite self-contained. Maybe Kongregate has some problems loading stuff, but only because they did it wrong. For the most part you just can’t load arbitrary movie clips and expect them to do the right thing (until Flash 9) because the Flash player simply wasn’t designed very well at the time. Unless of course you’re also advocating that everyone should use the same frame rate and that not using the same frame rate is bad because it won’t work in “complex situations”.

 
Flag Post

it makes a great default MovieClip reference because it’ll work for maybe 99% of most use cases with less work for the user.

Contrary to what people may think it is possible to write code quickly and easily without using _root references. The whole point is that writing proper code makes it easier for the programmer, and also makes less problems when you try to integrate your game with other things, such as a standard API. Also, OOP allows you to re-use code and even entire game engines, how’s that for convenience?

My real point is that people should do whatever they can get done quickest, provided that it works under the constraints they need it to.

Agreed; however, if you want your games to be ‘throwaway’ projects, you can code them sloppily and finish them in a week. Nothing wrong with that, of course, but if anyone is serious about this programming stuff, I suggest learning OOP and doing it right, because it can still be done rather quickly :)

 
Flag Post

I wouldn’t exactly say that AS3 doesn’t let you code like that anymore. It only lets you do it if you have a reference to some DisplayObject that’s in the hierarchy, but they do have a root property that can be used in much the same way.


Not quite. Its true you can get a reference to root after an object is loaded into the display list, but in my experience its not quite consistent, and not wise in general. Additionally, if a person tried to code something like root.dist = 100 like they were doing in AS 2.0, they would get a compiler error. Sure, you could get around the compile checking by using a method or two, but the compiler warns you for a reason. And if you are going to do that, you might as well do it the right way, as this one is too unreliable and defeats the purpose of stricter coding.


bq. AS3 is pretty ridiculous in a lot of ways in that are really going to hurt the platform, but that’s another discussion for another day.


If you consider proper coding as ridiculous, then ya. As far as hurting the platform, I agree, its very possible. In the end it will make it harder for the amateurs, which is where it will hurt the most. As far as the benefits it brings as a result of stricter coding, those will help it.


bq. I don’t use _root a whole lot myself, but it certainly has its uses. If you’re providing certain kinds of API to users, it makes a great default MovieClip reference because it’ll work for maybe 99% of most use cases with less work for the user. It’s also where you get URL variables, find out how big your SWF is and if it’s fully loaded, etc.


I agree, it has its uses. That was not denied, and is not what the discussion is about. As I said, it should be avoided if possible. If you have an occasional use for it, thats totally fine. But if a person is relying on it as a crutch, its bad for expanding their programming skills.


bq. My real point is that people should do whatever they can get done quickest, provided that it works under the constraints they need it to. Games especially, because they’re usually relatively “throwaway” projects that are quite self-contained.


That only works if your project is truly “throwaway”. If you want to grow as a developer, you should use “best practices”. Thats why they are called “best practices” – because sure, you can do it 100 different ways and it will still work, but its not the best way, and its going to limit you down the road (or worse, cause you headaches in the current project). The choice in the end is up to the person, but as with anything, there is a recommended way, and other ways.


bq. Maybe Kongregate has some problems loading stuff, but only because they did it wrong.


Sorry dude, but thats totally wrong. It didnt have to do with what Kongregate was doing, it had to do with the coding of the games. I should know, I’m the one who went in and got it working properly for them. As I said, if the games were scoped properly, it wouldnt have been such an issue.


bq. For the most part you just can’t load arbitrary movie clips and expect them to do the right thing (until Flash 9) because the Flash player simply wasn’t designed very well at the time.


Yes you can, if you code them properly. Again, thats the point of best practices. If everyone followed them, things would be so much easier.

All it is is a suggestion for coding better, thats it. No one is being forced, no one is being insulted, it was just brought up as a suggestion so that our fellow flash coders can grow in their skills. They dont have to do it if they are just going to create quick projects, and thats fine; but theres no point in arguing about this further…you will just confuse them. I try to recommend what will work for them now, as well as in the future when they grow, not just the “quick fix”.

If you took a good Flash seminar and asked them about using root/level0, they would say “avoid it if all possible”. Thats just being passed along to our friends here :).

Lets leave it at that, the thread has strayed enough.