SOLVED Event collision problems involving multiple instances.

Misael644

Member
Hello again! I'm here because I'm having problems with my game's collision event.
Basically, I'm trying to simulate a starfield that works like this:
I have an object called "obj_star", in the game, it is spawned by "obj_starcreator", which spawns a star in a random place on the screen. And so that the stars don't move in random directions around, I created an object that I call "obj_ramp", to give the illusion that you are traveling through a starfield, just like in this Wikicommons gif: https://upload.wikimedia.org/wikipedia/commons/e/e4/StarfieldSimulation.gif
The "obj_ramp" works like this:
I have a variable called "RampD" (D is for direction), and I have four ramps on the screen, each of which occupies 1/4. Each of the ramps has a RampD variable that works like this:
if a star collides with one of the ramps, if the rampD variable is number 0, the "obj_star" has to go to the northwest, and even to other numbers; 1 for NE, 2 for SE and 3 for SW.
The problem is that all the stars in the room will go in a specific direction, no matter which "obj_ramp" it is colliding with. I think it has to do that all stars share a single variable for direction, no matter the instance.
The code works like this:
GML:
//in obj_star event colliding with obj_ramp:
switch(obj_ramp.RampD){
    case 0:
        direction = irandom_range(90,180);
        break;
    case 1:
        direction = irandom_range(0,90);
        break;
    case 2:
        direction = irandom_range(270,0);
        break
    case 3:
        direction = irandom_range(180,270);
        break;
};
Do you have any idea what I could do to make all the stars move in the given direction?
 

TsukaYuriko

🌠
Forum Staff
Moderator
objRamp refers to the first instance of the object. You refer to the instance involved in a collision in a Collision event with other, not the name of its object.

You may also want to take a moment to rethink what exactly a range between 270 and 0 will be. ;)
 

Misael644

Member
objRamp refers to the first instance of the object. You refer to the instance involved in a collision in a Collision event with other, not the name of its object.

You may also want to take a moment to rethink what exactly a range between 270 and 0 will be. ;)
So does that mean I have to add "with(other){" at the beginning of my code?
And... ah yes, irandom_range (270,0) shakes a lot.
 
Last edited:

Misael644

Member
No, it means that you need the RampD value from other, which is the specific objRamp, instead of "Hey, Game Maker, I literally don't care which objRamp it is, pick one for me and use that one".

NEVER use object.variable. ALWAYS get an instance ID and use instance.variable.

Required reading: What's the difference between objects and instances?
Okay, but what could I change in my code to work? Because what I've tried to do so far has not worked as expected, and I also don't know why irandom_range(270,0) causes obj_star to stay stopped in place.
 

Nidoking

Member
Okay, but what could I change in my code to work?
other is an identifier for the objRamp that you collided with. objRamp.RampD gives you the RampD of a random objRamp instead of the objRamp you collided with, which is called other. other.RampD is the RampD variable of the objRamp you collided with, that being other.

I also don't know why irandom_range(270,0) causes obj_star to stay stopped in place
The sphinx has a riddle for you: What number is greater than 270 but less than 0? If you can answer this riddle, you will understand why you are not getting random numbers that are greater than 270 and also less than 0 at the same time. Now, when you're talking about angle measurements, 360 degrees is the same thing as 0 degrees. But the irandom_range function doesn't know that you're talking about angles.
 

Misael644

Member
I can't say if the code worked because all the stars in the room aren't moving yet. I replaced "irandom_range(270,0)" with "direction = irandom_range(270,360);" but it's still the same. Does anyone know what may be going wrong? :(
 

Misael644

Member
Here:
GML:
//in obj_star event colliding with obj_ramp:
switch(other.RampD){
    case 0:
        direction = irandom_range(90,180);
        break;
    case 1:
        direction = irandom_range(0,90);
        break;
    case 2:
        direction = irandom_range(270,360);
        break;
    case 3:
        direction = irandom_range(180,270);
        break;
}
 

Fineas333

Member
The sphinx has a conundrum for you: What number is more noteworthy than 270 however under 0? In the event that you can answer this enigma, you will comprehend why you are not getting irregular numbers that are more noteworthy than 270 and furthermore under 0 simultaneously.
 

TheouAegis

Member
Did you set speed in obj_star and is it still not equal to 0? You won't move if speed gets set to 0 for any reason.

And how is your room set up? I don't understand these "ramps". First time I've seen a star field made with "ramps".
 

Nidoking

Member
The sphinx has a conundrum for you: What number is more noteworthy than 270 however under 0? In the event that you can answer this enigma, you will comprehend why you are not getting irregular numbers that are more noteworthy than 270 and furthermore under 0 simultaneously.
Okay, you've found Babelfish. Why are you posting this? We finally got past that issue.
 

Misael644

Member
How are you setting the RampD variables?
I am giving a number for the creation code of each of the obj_ramp in the room, like this: RampD = //0, 1, 2 or 3;

Did you set speed in obj_star and is it still not equal to 0? You won't move if speed gets set to 0 for any reason.

And how is your room set up? I don't understand these "ramps". First time I've seen a star field made with "ramps".
In the obj_star creation event, it looks like this: speed = random_range(1.2,3);
My room is set up like this:
room.png
I call these objects "obj_ramp" because when I was creating them, I was listening to a podcast about skateboarding and I thought "I'm going to call this a ramp lol" ¯\_(ツ)_/¯
 

TheouAegis

Member
So are there just 4 "ramps" and you're basically trying to figure out the speed of the Star based on the quadrant it's in?
Code:
var X = sign(x-room_width/2);
var Y= sign(y-room_height/2);
var C = 90-(X * 90);
var S = 180+(Y * 90);
direction = irandom_range(min(C,S), max(C,S));
 

TsukaYuriko

🌠
Forum Staff
Moderator
What does obj_starcreator do, what is its code and how does it come into play? You haven't explained its role yet, and I believe it's there for a reason - maybe even responsible for the issue.
 

Misael644

Member
So are there just 4 "ramps" and you're basically trying to figure out the speed of the Star based on the quadrant it's in?
Code:
var X = sign(x-room_width/2);
var Y= sign(y-room_height/2);
var C = 90-(X * 90);
var S = 180+(Y * 90);
direction = irandom_range(min(C,S), max(C,S));
Umm... no. As I said before, obj_ramp works like this: if obj_star collides with obj_ramp, if if the number of the variable RampD is for example 2, then obj_star should go in a random direction between 270 and 360.
What does obj_starcreator do, what is its code and how does it come into play? You haven't explained its role yet, and I believe it's there for a reason - maybe even responsible for the issue.
Obj_starcreator works like this:
Code:
//creation event
StarCreate = false;
alarm[0] = 30;

//alarm 0 event
StarCreate = true;
alarm[2] = 10;

//alarm 2 event
StarCreate = false;
alarm[0] = 10;

//step event
var xx = random_range(0,640)
var yy = random_range(0,480)
if (StarCreate = true){
   
    repeat(1){
        instance_create(xx,yy,obj_star);
        }
}
These alarms work like what I call a "star dam", the dam starts closed (StarCreate = false), 30 steps later it opens (StarCreate = true), 10 steps later it closes and then it enters a loop where the dam closes and opens. It basically works to determine how many stars should be spawned in a given period of time.
 

TheouAegis

Member
Umm... no. As I said before, obj_ramp works like this: if obj_star collides with obj_ramp, if if the number of the variable RampD is for example 2, then obj_star should go in a random direction between 270 and 360.
I understand how your ramps work, I was asking what the point of them was. I still see no point to them. From that screenshot, it looks like all you are doing is using ramps to discern which quadrant of the room or whatever the stars are in to determine their direction of movement. That could just be done with very basic math in the star's Create event.

Code:
var X = sign(x-room_width/2);
var Y= sign(y-room_height/2);
var C = 90-(X * 90);
var S = 180+(Y * 90);
direction = irandom_range(min(C,S), max(C,S));
The simpler the process for determining the angle, the easier to maintain and debug.
 

Misael644

Member
I understand how your ramps work, I was asking what the point of them was. I still see no point to them. From that screenshot, it looks like all you are doing is using ramps to discern which quadrant of the room or whatever the stars are in to determine their direction of movement. That could just be done with very basic math in the star's Create event.

Code:
var X = sign(x-room_width/2);
var Y= sign(y-room_height/2);
var C = 90-(X * 90);
var S = 180+(Y * 90);
direction = irandom_range(min(C,S), max(C,S));
The simpler the process for determining the angle, the easier to maintain and debug.
Well, I tried to use your code and it apparently works, but not quite as expected. Some stars in the southeast are not going in the right direction, as seen in this gif:
ezgif-7-96aa3a09307c.gif
 

Misael644

Member
This is once again giving you an angle range of 270-0 for the southeast quadrant. You need 270-360.
So what code could I use to replace 270-0 by 270-360? I tried to use this code, but it didn't have much effect:
GML:
if (X = 1 && Y = 1 && C = 270 && S = 0){
S = 360
};
 

Nidoking

Member
The equality checks probably aren't going to work. (Although you don't need to check X and Y AND C and S.) It would probably be simpler at this point just to use if-else logic rather than trying to do something fancy.

Have you tried point_direction from screen center to the star, dividing by 90, then using 90 * floor and 90 * ceil as the bounds? That should handle all cases, including stars on a border going straight along the axis.
 

Misael644

Member
The equality checks probably aren't going to work. (Although you don't need to check X and Y AND C and S.) It would probably be simpler at this point just to use if-else logic rather than trying to do something fancy.

Have you tried point_direction from screen center to the star, dividing by 90, then using 90 * floor and 90 * ceil as the bounds? That should handle all cases, including stars on a border going straight along the axis.
Hmm... no, but what code could I use to do this?
 

Misael644

Member
Umm... That's not what I meant, I don't know how to deal with point_direction and I think that you could give me a code to make things easier.
 

Yal

🍋 *lemon noises*
GMC Elder
So what code could I use to replace 270-0 by 270-360? I tried to use this code, but it didn't have much effect:
GML:
if (X = 1 && Y = 1 && C = 270 && S = 0){
S = 360
};
You should use == for comparisons for stability and consistency with other languages (in the entire C family = will change the value and then return the new value, so the expression will appear as if it's always true - this could change later in GM without warning since = comparisons is a compatibility feature).
 

Misael644

Member
Well, I've been seeing some things about point_direction on the internet and now I understand how it works, my problem was with the Nidoking code, because I thought it was a bit complicated, but so, I thought in theory that my "starfield" code could have some problems, for example, not all stars would have their direction aligned correctly, because when created, their direction value is random, and so it would not look like a starfield correctly. Then I saw about point_direction, and saw that it returns the value of the angle of a line, so I used this code in my game to see how it would look:
GML:
direction = point_direction(room_width/2,room_height/2,x,y);
And well... apparently works as expected! :D It's like the way I wanted it:
I just didn't understand what Nidoking meant by "bounds"...
...dividing by 90, then using 90 * floor and 90 * ceil as the bounds?
so I used another code... that looks kind of bad:
GML:
var valueA = point_direction(room_width/2,room_height/2,x,y)
var valueB = valueA/90
var valueC = 90*floor(valueB)
var valueD = 90*ceil(valueC)
direction = valueD
and I saw that it created something cool, but not a "starfield".
Well, thanks for helping me with the code. I always hope to count on you when I have a question.
 
Last edited:

Nidoking

Member
using 90 * floor and 90 * ceil as the bounds
var valueC = 90*floor(valueB)
var valueD = 90*ceil(valueC)
direction = valueD
What? What twisted logic is this? Why do you seem to think that a variable can only be used in the very next line? The problem is not that anything is complex, but that you don't seem capable of thinking of anything beyond the very simplest sequence of steps, and you don't seem to be able to understand what it is that you are doing.

What you are doing: Generating a random number within a range of two values.

What I am telling you to do: Use two specific values as the bounds of those ranges.

What you appear to be doing: I have no idea whatsoever.

Here's some of your original code:

direction = irandom_range(90,180);
The bounds here are 90 and 180. You are generating a number between 90 and 180. 90 and 180 are the bounds of your random number range.

What I am trying to get you to understand is that they don't have to be 90 and 180. They can be expressions calculated from other values. They can, in fact, be the values 90*floor(point_direction(room_width/2,room_height/2,x,y)) and 90*ceil(point_direction(room_width/2,room_height/2,x,y)). For stars between 0 and 90, that will be the values 0 and 90, respectively. For stars between 90 and 180, that will be the values 90 and 180. I would like to say that I think you can see where it goes from there, but I'm not sure that that's true. What you've done there is to remove the random element and just have everything move directly away from the center. That's your traditional starfield, and it's fine, but it's not what you said you wanted.
 

Misael644

Member
What? What twisted logic is this? Why do you seem to think that a variable can only be used in the very next line? The problem is not that anything is complex, but that you don't seem capable of thinking of anything beyond the very simplest sequence of steps, and you don't seem to be able to understand what it is that you are doing.
Oops, sorry. Well, I said that I didn't understand your code because I didn't understand exactly what you were saying with "bounds", now I understand that it was the two numbers from irandom_range. Because of that I wrote that code because to me it seemed like the best way to do what you were trying to tell me, but I knew something was still wrong. I used these variables as "valueA/B/C/ ..." to make sure that nothing went wrong. As I didn't like the result very much, I preferred to use the alternative of "direction = point_direction (room_width / 2, room_height / 2, x, y)", and it came out exactly the way I wanted. That's why I wanted to put aside "direction = irandom_range". My bad...

So, I did some tests with RampD using this code:
GML:
//in obj_star event colliding with obj_ramp:
switch(other.RampD){
    case 0:
        direction = irandom_range(90*floor(point_direction(room_width/2,room_height/2,x,y)),
        180*ceil(point_direction(room_width/2,room_height/2,x,y)) );
        break;
    case 1:
        direction = irandom_range(0*floor(point_direction(room_width/2,room_height/2,x,y)),
        90*ceil(point_direction(room_width/2,room_height/2,x,y))  );
        break;
    case 2:
        direction = irandom_range(270*floor(point_direction(room_width/2,room_height/2,x,y)),
        360*ceil(point_direction(room_width/2,room_height/2,x,y))  );
        break;
    case 3:
        direction = irandom_range(180*floor(point_direction(room_width/2,room_height/2,x,y)),
        270*ceil(point_direction(room_width/2,room_height/2,x,y))  );
        break;
}
(excuse me if I did it wrong again).
But still something went wrong, look at this gif:
ezgif-3-4d66abafa829.gif
In order not to complicate the situation further, I replaced the code with one that seemed to be more efficient. Sorry for being a noob, I am new to game design and I still have many other things to understand, thanks for the help.
 

Misael644

Member
Let's play a game of "spot the difference". Here's what I gave you, and then what you wrote.




Can you possibly imagine what you might have done wrong?
Oh wait, you mean I don't have to use 90*floor(point_direction and 180*ceil(point_direction? This is kind of confusing because you said:

For stars between 0 and 90, that will be the values 0 and 90, respectively. For stars between 90 and 180, that will be the values 90 and 180.
 

Nidoking

Member
*sigh* Remember when you did this?

var valueA = point_direction(room_width/2,room_height/2,x,y)
var valueB = valueA/90
var valueC = 90*floor(valueB)
var valueD = 90*ceil(valueC)
direction = valueD
You're getting a direction as valueA, then getting 1/90 of that as valueB. Good. Then, you take the floor of valueB and multiply by 90 to get valueC. Excellent. Then, you take the ceiling of valueB and multiply by 90 to get valueD. The direction you want is between valueC and valueD.

Only that's NOT what you're doing. Inexplicably, you're using valueC to calculate valueD. There is no reason to do that. It makes no sense. Calculating valueD from valueB is what you were supposed to do, because that makes sense and is correct. The only conclusion I could draw is that you don't understand how variables work and think that once you've declared a variable, you have to use it on the very next line. That's wrong, and I don't know how to explain to you why it's wrong.

And then you assign valueD to direction... why? Again, this makes no sense. You have valueC and, if you were to calculate it correctly, valueD as the bounds (that's the first number between the parentheses and the second number between the parentheses) of your call to irandom_range, which gives you a number between the first number between the parentheses (the "lower bound", which is one of the bounds) and the second number between the parentheses (the "upper bound", which is one of the bounds). You want a value between valueC (the "lower bound") and valueD (the "upper bound"). These are calculated values, meaning that you determine what they are based on inputs, and that way, you don't need a switch statement. You just say "give me a starting value (in this case, x and y), and I will calculate a correct output".

You must understand this. Stop taking random things that I've said out of context and trying to mash them together. It doesn't work for your code, and it doesn't work for a technical explanation of such a difficult concept as first grade arithmetic.
 

Misael644

Member
Okay, okay, I finally got it. This must be the code, right?

GML:
direction = irandom_range(90*floor((point_direction(room_width/2,room_height/2,x,y))/90),90*ceil((point_direction(room_width/2,room_height/2,x,y))/90))
The only conclusion I could draw is that you don't understand how variables work and think that once you've declared a variable, you have to use it on the very next line. That's wrong, and I don't know how to explain to you why it's wrong.
Look, I said earlier that I put these "valueA/B/ C" variables in because the code seemed to be complicated for me. Like, look at the length of the line, do you think I would understand the code right away?

Well, here's the code in action:
ezgif-2-3b65cacb4ce2.gif

It's pretty much what I wanted (before), but it doesn't look much like a starfield. Not all stars go in the direction they should go, so I prefer to use "direction = point_direction", which is much more efficient.


In fact, thanks Nidoking for explaining in detail, I didn't need all of that. It's kind of funny to use my mistakes to teach me.
 
Last edited:

Nidoking

Member
You're welcome, and I sincerely hope this has all been instructive. You got there in the end, developed a better understanding of how directions and variables work, and discovered the difference between answering the question that was asked and providing a desired solution. Sometimes, we don't know what we want until someone gives us what we thought we wanted.
 
Top