Legacy GM [SOLVED] Problem with Collisions / place_meeting()

L

lmhrpr

Guest
I have a villager object which uses mp_potential_step() to navigate between objects (such as trees). When it reaches the tree in question, I use place_meeting() to change the villager's behaviour. In order to make this work, I have the villager set to solid and the trees not set to solid.

However, when path finding, the villager will walk through other trees because they're not solid. If I make the trees solid, or set the checkall flag in mp_potential_step() to true, the place_meeting() never returns true. The villager will approach the tree then just circle it forever (there are rare exceptions where place_meeting() does return true).

Why does place_meeting() not return true if the trees are solid? I have precise collision checking on everything.
 

Neptune

Member
I think using the game maker "solid" attribute may be stopping your villager before he is able to reach the tree -- thus returning 'true' for your place_meeting check.

I could be wrong though, I personally try to avoid game maker attributes like "speed" "gravity" "solid", so I don't know too much about them.

You could incorporate the villager's speed in the collision check as well, if you are not already.

Goodluck
 
L

lmhrpr

Guest
Thanks. The only check I'm using is place_meeting(). According to the documentation, this should return true when the two objects' precise collision masks meet. I guess you're right, that the solid flag is somehow preventing them truly meeting, even though they appear to be touching.
 

Neptune

Member
So if you are using place_meeting, you could try:
Code:
if place_meeting(x+xspeed,y+yspeed,obj_tree)
{
xspeed = 0;
yspeed = 0;
}
Or however it world be incorporated into your code.

Its hard to discern the issue without either writing you a entire new system, or seeing your current code for the system you got
 
Last edited:
L

lmhrpr

Guest
Here's my code:

Code:
if instance_exists(NearestResource) {
    // If we're not yet at the resource
    if !place_meeting(x, y, NearestResource) {
        // Pathfind to the nearest resource
        mp_potential_step(NearestResource.x, NearestResource.y, WalkingSpeed, false);
    } else {
        // Stop
        speed = 0;
        // Chop down the tree
        ...
    }
}
I'm using the built in speed attribute. I tried adding that to the x and y parameters of place_meeting() but that didn't work. I may need to figure out how to use my own xspeed and yspeed variables to try your suggestion properly.
 

GMWolf

aka fel666
Check the distance to the target tree instead.

To do this, you must have the Id of the tree stored in a variable. I'm going to assume the name "target_tree"
You will also need to know the distance between the player one the tree needed for a 'collision'. I'm calling it target_radius. This should be larger than the sum of the radius of the villager and the tree.

Then, in the step event
Code:
if (point_distance(x, y, target_tree.x, target_tree.y) < target_radius)
{
 //here goes your 'collision' code
 //do something
}
 
L

lmhrpr

Guest
I tried this and it has exactly the same effect. If the tree is solid, or mp_potential_step is set to avoid instances, the villager never reaches the tree, just circles around it endlessly.

Edit: I inverted my logic as below:

Code:
if point_distance(x, y, NearestResource.x, NearestResource.y) < 20 {
    // Chop down tree
} else {
    mp_potential_step(NearestResource.x, NearestResource.y, WalkingSpeed, true);
}
and this worked. I'm trying to get my head around how that's different to what I had before.
 

GMWolf

aka fel666
I tried this and it has exactly the same effect. If the tree is solid, or mp_potential_step is set to avoid instances, the villager never reaches the tree, just circles around it endlessly.
Make sure the target radius is large enough. And make especially sure you are not simply using obj_tree instead of target_tree, it has to the the ID of the tree you are going towards.
 
L

lmhrpr

Guest
I tried a range of radii from 0 up to 50. And I used the NearestTree instance of my oTree object. As in my edit above, inverted the logic from !point_distance() to point_distance() solved it, for some reason.

Thanks a lot for your help!
 

GMWolf

aka fel666
I tried a range of radii from 0 up to 50. And I used the NearestTree instance of my oTree object. As in my edit above, inverted the logic from !point_distance() to point_distance() solved it, for some reason.

Thanks a lot for your help!
!point_distance?
Why did you have !point distance?
 
L

lmhrpr

Guest
My original code (as above in #5) was:

Code:
if instance_exists(NearestResource) {
    // If we're not yet at the resource
    if !place_meeting(x, y, NearestResource) {
        // Pathfind to the nearest resource
        mp_potential_step(NearestResource.x, NearestResource.y, WalkingSpeed, false);
    } else {
        // Stop
        speed = 0;
        // Chop down the tree
        ...
    }
}
I substituted place_meeting() for point_distance() as per your suggestion. When that didn't work, I inverted the logic to this:

Code:
if instance_exists(NearestResource) {
    // If we meet the resource
    if point_distance(x, y, NearestResource.x, NearestResource.y) < 20 {
        // Stop
        speed = 0;
        // Chop down the tree
        ...
    } else {
        // Pathfind to the nearest resource
        mp_potential_step(NearestResource.x, NearestResource.y, WalkingSpeed, true);
    }
}
And this works.
 

Neptune

Member
Glad you got it working!
If you want to drop the built-in 'speed' variable. You can just create 2 variables (the components of a velocity vector), like x_speed and y_speed, and then manipulate them depending on what your character is doing, or what buttons are being pressed.

And then somewhere in the villager's step event, just put:
Code:
x += x_speed;
y += y_speed;
//Set both to zero to stop moving.
So if x_speed is not zero, the villager will move horizontally, and if y_speed is not zero the villager will move vertically.
 
L

lmhrpr

Guest
If I use two separate variables for speed, does that mean I can't use functions that take in a single speed parameter?
 

Neptune

Member
Any functions that have an actual 'speed' parameter are refering to the built in speed-variable.

Try to forget the idea of speed, and just think, "These x_speed and y_speed variables are just how many pixels I want the villager to move each time this code runs."

If you are using functions like move_towards and are scared to lose your built-in speed, there is always a equal (probably better) coding replacement that will give you exactly what you want, with more flexibility!

More complex movement:
If you want a true velocity vector -- so a single speed magnitude and a direction of travel you will have to use trigonometry. In doing so, you'll essentially be setting your x_speed and y_speed components using a total_speed magnitude and the angle you want move in radians. (There may actually be a function for this, but I don't have any experience with it).
 
Top