#Dynamic Collision boxes

247 messages · Page 1 of 1 (latest)

formal elbow
#

Forewarning it might take a while for me to respond because I'm going to do something after posting this..
anyways I made these objects for my game that are webs that get your Y speed with collision boxes before you hit the web, but the collision boxes drawn for getting your Y speed are manually made with a set distance from the object, so when it's rotated you can see the difference in the screenshot of the game between the horizontal and diagonal ones.. If someone could help figure out how to make the collision rotate with the actual object that would be great
and here's the code for the object as well (I know what I want will probably need to be collision lines instead of rectangles and there's nothing in the player collision event)

gleaming olive
#

Rather than using the collision rectangle function you could make a new sprite to serve as the larger collision mask, and give that sprite the 'rectangle with rotation' type.

For your check, you switch mask index to the larger collision mask, check for collision, then switch back to the normal mask.

#

Just need to make sure that the origin settings for both sprites are the same.

#

Assuming you are rotating the objects by adjusting image_angle, that will rotate the masks with it.

formal elbow
gleaming olive
#

Yeah, pretty much. You can then have your object switch its mask to that sprite's mask, use it for a check, and then switch back.

var old_mask = mask_index;
mask_index = sprite_with_larger_mask_and_rotation;
var colliding_instance = instance_place(x,y,some_object);
mask_index = old_mask;
#

And go on to do whatever checks you need using the normal mask, if any.

#

Often I might have several different masks for an object, stored in variables.

That way you can have, like, one collision mask for movement, a different one for contact damage, another one for being hit by attacks. As many as you need, really. And then you just switch to the appropriate one.

Switch to the movement collision mask, run your collision/movement code, then switch to the contact damage mask, see if you're touching the player. It so, apply contact damage. Switch to the hitbox for being hit by attacks and end the step event.

That kind of thing.

#

This approach also allows you to take advantage of precise hitboxes for attacks and whatnot.

#

Most of the examples I have on-hand are hitboxes for attacks:

#

Which lines up with the attack thusly:

#

But the approach should be appicable to what you are trying to do.

formal elbow
#

wait, how do I swap the collision rectangle code with something using the mask?

gleaming olive
#

#1483199537437741269 message
Like this. You just change your collision mask and then run a check using a collision checking function that uses the mask, such as place_meeting, instance_place, or instance_place_list

#

Then change it back.

formal elbow
gleaming olive
#

Looks good to me provided the sprites get set up correctly.

#

For making the larger mask, it would probably suffice to duplicate the existing mask, change it to 'rectangle with rotation' then just switch the mask settings to manual and extend it by the desired number of pixels:

gleaming olive
#

Well, if it's just the extra height on the top and bottom that you're hoping to get, then that looks good to me.

#

You can always play around with the dimensions of the mask later to dial it in.

formal elbow
gleaming olive
#

It would only switch masks when you tell it to switch masks by changing the value of mask_index to some new sprite.

#

Changing value of mask index in code is the same thing as adjusting the collision mask dropdown in the object editor.

#

So you can change the mask, run a check, change it back. While place_meeting, instance_place, and instance_place_list will only ever check using the mask currently stored in mask index, you can change the mask in mask index as often as you need.

#

You could also make a function to swap the mask, run a collision check using that mask, swap the mask back, and return the results of the check:

function instance_place_mask(_x,_y,_obj,_mask){
  var oldmask = mask_index;
  mask_index = _mask;
  var instance = instance_place(_x,_y,_obj);
  mask_index = oldmask;
  return instance;
}
formal elbow
gleaming olive
#

Not really. Are you changing your mask back to the smaller one after you run your check?

#

And is this object intended to block movement?

formal elbow
# gleaming olive And is this object intended to block movement?

I had no idea how to change it to the bigger mask without something triggering it so I had it just be the bigger mask, change to the smaller mask and then back, cause the bigger mask needs to touch the blaper before the player touches the smaller mask or the player won't have any Yspd for the bigger mask to copy

#

and yes it's supposed to stop the player other than that

#

it rubber bands you back based on your speed going at it

gleaming olive
#

Where is the collision check happening? The web's step event or the player's step event?

#

Based on what you are describing, I might have the player identify the thing they are running into when they run into a thing, and, if it is an instance of the bouncy thing, bounce.

formal elbow
gleaming olive
#

Yeah, my assumption was that the check was happening in the web's step event, and my theory was that you were going to be changing the collision mask from the smaller mask to the larger mask, checking for the player, and then changing it back before the end of the step event.

#

If the web is left with the larger mask during the player's step event, then that is the mask it will have when his movement is performed.

#

And if the web is collidable, he will collide with it.

#

While the mask swap to the larger mask and the check of his yspd is technically feasible, it's not a fool-proof way of doing this. As it would require that the larger mask be sufficiently wide that it detects the player regardless of how fast he is moving on both axes.

#

It might make more sense to have the player, when colliding, check what he is colliding with. And, if it is a bouncy thing, bounce rather than zeroing his movement.

#

Usually when I have an object that does the bouncing, it'll be a spring, or something that doesn't immediately bounce you on-contact.

formal elbow
gleaming olive
#

Oh, gotcha.

formal elbow
#

also I'm now realizing I need to make the UI elements scale with the window 😅

formal elbow
gleaming olive
#

Yeah, the springs in my clip don't bounce you to a height which is proportional to your speed when you hit it, but here's how I would go about that if I wanted to do it-

formal elbow
#

you kind of slide while on the spring, I want the player to be stuck in place before bounding back up/down since a web would probably do that

gleaming olive
#

When your player lands on the spring, I would have the player store his yspd in a variable on the spring, and then, when the spring bounces you, I would have it use the inverse of that as the bounce height.

formal elbow
#

that is what mine does, but it stores it with the collision box you see above the web, though since it's made the way it is it doesn't rotate with the web :P

gleaming olive
#

Yeah, you could do it with the larger mask, it just wouldn't necessarily work regardless of xspd/yspd. It would require that the mask be sufficiently large to see the player before he hits the web, and I don't know what the maximum values of xspd and yspd are.

#

A potentially less error prone way to do it would be to do what I just said, when the player lands on an object, have him check whether it was the web, and, if it was, have him store his yspd on that web instance before zeroing it out.

formal elbow
#

and then have stuff like the webs just take that and use it like I have it just without the drawn collision boxes

gleaming olive
#

Well, you would need to at least make sure you're not hitting a tile layer, unless you're storing it in a global.

#

As the tile layer wouldn't have anywhere to store it.

formal elbow
#

and then have my web objects pull Player_Prt.XStore

#

or YStore whichever I'd be using for the part

gleaming olive
#

Sure, you could store it on the player, but if your bounce isn't immediate, and your player is able to keep moving, then there may be the potential of that value getting overwritten. Though that would really depend on what your player is able to do movement-wise when he is in contact with the web.

formal elbow
#

I mean would this not work?

gleaming olive
#

If the bounce is immediate, then you might as well just check whether the thing you hit was the web and, if so, invert his yspd rather than zero it, no?

#

That would certainly store the value of xSpd in a variable. But if the player moves again next frame, it would be overwritten with the new value of xSpd.

#

Anyway, I expect this'll be a ~~think ~~ thing you need to tinker with to get the exact feel you want.

formal elbow
gleaming olive
#

For sure. My instinct would definitely be:

  • If the player is bouncing immediately, just have the player object invert his yspd immediately when landing on the web. The web can then basically have no code.
  • If the player isn't bouncing immediately, and is instead bouncing after the web dips down a bit and pulls him with it/does an animation/whatever, then have the player store his yspd on a variable in the web object when landing on it (if that variable is currently undefined), and then, after the animation/dip/whatever, have the web use the inverse of that stored value to launch him into the air. And if he somehow manages to lose contact with the web before that launching happens, you could either launch him immediately at full or partial force and clear the stored value, or just clear the stored value.
#

Springs that move the player with them are somewhat complicated.

formal elbow
#

can you please teach me how to do the Mask thing properly..? T~T

#

cause that idea failed miserably

gleaming olive
#

Well, without seeing any code, I can't really be sure what is being done incorrectly.

But suffice it to say, when you do a function like place_meeting, instance_place, or instance_place_list you are telling gamemaker to move the calling object's currently assigned collision mask (mask_index) to a particular x/y coordinate, and check to see if it collides with an instance there (also based upon that object's currently assigned collision mask/mask index).

#

So there's nothing stopping you from switching to a custom collision mask, doing a specific check, and then switching back.

#

As long as you switch back before other objects run their respective events, then the custom mask will not interfere with stuff like their movement.

#

Since you should in theory have switched back to the normal mask before ending the event.

gleaming olive
#

For an example, the function I posted up here should suffice:

#1483199537437741269 message
It does the following:

  • Stores the current collision mask in a local variable
  • Switches to a collision mask you specify
  • Does an instance_place check in a place you specify using that mask
  • Switches back to the original mask
  • Returns the result of the instance_place
formal elbow
#

ok uh.. I took a bit of a break to eat dinner and didn't see this but got it to work... sorta..

#

nevermind it's doing something completely different now..

gleaming olive
#

So, not sure I'll be able to help without looking at code and reading an explanation of what it is doing which is different than expected.

formal elbow
#

nothing else has been changed

gleaming olive
#

Am I looking at the player's step event? The object name has been cropped.

formal elbow
gleaming olive
#

All good. Just not sure if its the web or the player.

#

Assuming web.

formal elbow
gleaming olive
#

I'm looking, but not seeing anywhere where the collision mask is being changed, so I don't really know what is new.

#

And I don't really see anywhere where the web is moving the player to keep the player on its surface as it moves. Which, incidentally, is going to be rather hard with a rotated object.

#

But like, if the web is fully collidable to the player, and it moves down, springs up, and gives the player a negative yspd, if the player is colliding with it then he isn't going anywhere, since the web will block him.

#

Unless that's just an animation?

formal elbow
gleaming olive
#

The player looks like he's sinking down a bit, so I'm unsure if the collision mask is changing. Might be my imagination.

#

Gotcha.

formal elbow
#

but I could try to add back the collision correction, I don't remember what it's called

gleaming olive
#

So you are at various places changing the xscale and yscale of the web.

#

Which will stretch the collision mask.

#

Possibly making it then overlap with the player and block his movement.

#

Are you doing that just to stretch the web visually?

formal elbow
#

the collision stays the same :P

gleaming olive
#

No, it doesn't. image_xscale and image_yscale affect the collision mask.

#

It will stretch it.

formal elbow
gleaming olive
#

It will increase proportionally with image_xscale, so if you increase image_xscale to make the sprite 10% wider the collision mask will also get 10% wider. And if that brings the collision mask into contact with the player, and the web is collidable, then he could get stuck in the web.

#

If you want to visually stretch the web without affecting collision, you should consider creating a new variable which can be used to achieve a purely visual stretch without affecting the mask.

#

By adding it to image_xscale in the draw event.

formal elbow
#

the dashes being like the length I mean

gleaming olive
#

I get you, but I asked a bit ago whether you were stretching it for a visual effect or with the understanding that it would affect collision, and you said it was a visual effect.

#

If the mask is stretched such that it overlaps with the player, and the mask is collidable, then he's going to get stuck inside it.

#

So the question that kinda needs answering is "for what purpose is xscale and yscale changing"?

formal elbow
gleaming olive
#

You mean to fill in gaps in the terrain? Like, stretch it between two platforms?

formal elbow
#

and the y scale is for just making it so I don't have to make 2 animations but I could if that's the problem

gleaming olive
#

So, you can do that in the room editor. I'm talking specifically about the scale changes that happen in the step event.

#

Like, if the image_yscale goes from 1 to -1 and back, then unless the origin is perfectly centered within the sprite it could cause it to suddenly overlap the player.

formal elbow
formal elbow
gleaming olive
#

Should be. But if the yscale changes are just for a visual effect it would make more sense to adjust something which doesn't affect collision.

formal elbow
gleaming olive
#

Up to you. But if you want to be able to visually stretch or flip an object in a way that can't change collision, it's relatively easy to do so:

draw_sprite_ext(sprite_index,image_index,x,y,image_xscale*squish,image_yscale*squash,image_angle,image_blend,image_alpha);
#

With the above draw event squish and squash could be modified to visually stretch or mirror the object without affecting collision.

#

So if I did squash = -1;, then it would vertically mirror the object, but not vertically invert the mask.

formal elbow
gleaming olive
#

What you're trying to do here is relatively hard, even for an object which isn't rotated.

I would be happy to share how I did the springs with you, and maybe you can get some inspiration from that, but the honest truth is that if I were gonna try to fix up the code for that web there probably isn't a lot of code there that I would keep.

#

This is the spring:

#

There's a small amount of logic in the draw event, which isn't great, but since my game prototype wasn't multiplayer it wasn't really an issue.

#

So, the spring stores the ID of the entity that is standing on it.

As its animation progresses, it switches its mask to a mask which visually aligns with where the surface of the spring is, and it uses a loop to make the entity standing on it move down with the mask.

#

When it reaches the 'bounce' part of the animation, it launches the entity standing on it into the air, be that the player, an enemy, whatever.

#

It's honestly not a great system, but it worked. One significant difference, though, is that my spring was a semi-solid, whereas your web is fully solid.

#

So you basically can't have a situation where the mask of the web overlaps with the player's position once the web's event has ended.

#

Ever. Or he gets stuck.

formal elbow
gleaming olive
#

Well, that sounds like another issue entirely.

#

Which is probably resolvable.

formal elbow
gleaming olive
#

Still, sounds like an issue with how the check for semi-solids is being done.

Unless you build up enough speed that you phase completely through the object that probably shouldn't happen. And if you were building up enough speed that you phase entirely through the object, that would affect full solids just as much as semi-solids with most collision code.

formal elbow
gleaming olive
#

Fair enough.

formal elbow
#

there's a reason why this isn't working.. T~T

#

wait no I'm dumb nevermind

gleaming olive
#

Given that your web seems to launch them into the air some percentage of the time (per the video) my assumption is that your code to launch them does technically function. My guess is the issue is that something in there is allowing them to come into collision with the web. Could be the stretching. Could be sprite changes if the collision mask isn't static.

I'm not really sure. But there are various points at which your player is being moved up and down with no collision checks at all AND the mask is being stretched on the X and Y axis. So it's not surprising to me at all that the player might end up overlapping the web.

#

Like, there's a collision rectangle check. If it sees the player, it moves him down. No collision check. For what purpose? No idea.

formal elbow
#

like no correction if you barely go into the object like a lot of my stuff does

#

(part of the code for no rotation)

gleaming olive
#

If your collision code is good, you shouldn't ever come into contact with a collidable object. If you are writing code to eject yourself from a solid object, then a mistake has already been made.

#

And moving your character without collision to get out of the solid object is just introducing more potential sources of clipping into stuff.

#

So yeah, I don't really see a way to proceed or for me to help unless all of the various places your player is being moved without proper collision checks are eliminated.

formal elbow
#

oh wait

#

maybe it's because I only have the Y check and not both X and Y..
like in my player object

gleaming olive
#

I'm honestly not sure what the purpose of that check is.

If I'm getting it right, it's checking to see whether the web would collide with the player if it were to move the inverse of the player's yspd. And, it it does meet the player there, the web itself moves up to meet him? And then it zeroes the player's speed.

#

But then, afterward, there is this and this:

#

And the shape of the collision mask gets changed.

#

Because you are adjusting xscale/yscale

#

So even if he wasn't colliding with the web before, he could be now.

formal elbow
#

what did I screw up

gleaming olive
#

The screenshot is cut off, but I believe it's running in the web's step event, no?

And there's no

with(Player_Prt)

...to change the scope to the player. So yes, the y adjustment is moving the web.

#

You can actually see it move in your first video.

#

Notice the outlines (which I assume is the collision mask?)

#

That drawn rectangle started off under the ledge to the left, but after the player's jump it was over it.

formal elbow
gleaming olive
#

So it moved.

formal elbow
gleaming olive
#

A more direct way to see whether it is moving might be to draw or print its y coordinate to the console.

gleaming olive
#

Also, not entirely sure whether the conditions of that loop are guaranteed to happen, so might want to give it a few attempts.

formal elbow
#

though it is also accounting for all the objects in the room

gleaming olive
#

Well, all I can say is that this is inside the web's step event, it's adjusting y and not Player_Prt.y, and there is no with() to change the conext in which the code is running.

#

There are a number of reasons why it might not happen. Maybe the sprite wasn't one of the two specified. Maybe the image_index wasn't less than 4. I don't really know.

#

But what I don't understand is what this is even really meant to do.

formal elbow
#

it works in the player object's events

gleaming olive
#

If the web is a child of a collidable object, wouldn't the player stop on his own?

#

It's pretty unusual for some other object to stop the player rather than the player stopping himself.

formal elbow
#

Idk I'll try switching it back around and see if it works like that

#

wait no cause I need it to only collide when the Web object's sprite is the regular one, and not the mask one

gleaming olive
#

I still haven't seen anywhere you're even changing the collision mask.

formal elbow
gleaming olive
#

No, not unless you have "Same as sprite" selected for collision mask on the object. Notice that in the code I shared with you, I am changing 'mask_index', not sprite_index

formal elbow
#

between these two

gleaming olive
#

It depends on whether you have same as sprite selected on the object.

#

For the collision mask.

#

For me it would make sense to just switch the mask.

formal elbow
gleaming olive
#

Yep. Just like in the code I posted earlier. But I wouldn't add that here until you have established what this code is actually meant to be doing, because that is super unclear.

gleaming olive
#

I mean this series of checks of the web's sprite and the web's image_index, followed by a collision check against the player based on the player's yspeed, followed by the web moving in a loop towards the player.

#

And finally zeroing the player's y speed.

#

If the web is solid, which you've told me that it is earlier, then would the player not collide with the web and zero out his own movement? What is any of this meant to be doing?

formal elbow
#

this to be exact

gleaming olive
#

Alright, I kinda figured. For the record, I really do want to help.

But trying to build a complex mechanic, like a spring that you move with over time, on top of code which you don't understand is kinda like trying to build a house on top of quicksand.

So I'm struggling to come up with advice that isn't 'delete this and start over on your web'.

So, it looks like your movement system is actually using tile collision, is that correct? So the web is not actually collidable, and the only thing stopping him was the web's code?

#

Err.... wait a minute.

#

Why is this stuff in create?

#

Is that part of a method function?

formal elbow
#

a lot of people call it a lot of different things so here's what makes it work and call it whatever you want, I usually call it a state system

gleaming olive
#

Okay, cool. So yeah, you have a basic state machine, and each of the states is stored inside a method variable.

#

(a method is a function stored inside of a variable, which is what you are doing there in create)

#

I just wanted to make sure.

gleaming olive
#

Because that part was cut off.

#

So the good news is that, if you wanted to make your web object collidable, that doing collision against both objects and tilemaps at the same time is very easy these days.

#

Since all of the collision functions can accept an array of collidables.

formal elbow
#

I think that's what I was doing? I just had
TileCollision = [TileMap,DWebPrtH,DWebPrtV,WWebPrtH,WWebPrtV]

gleaming olive
#

...Oh.

#

Well, it was called 'TileCollision'.

#

So I assumed it was Tiles.

formal elbow
#

and it worked like that but like I said before only without the rotation does it work TwT

gleaming olive
#

Because of the name.

formal elbow
gleaming olive
#

So why are there 4 different web objects?

#

Those are web objects, yes?

formal elbow
gleaming olive
#

Okay, so, to make your code cleaner, you could make an object:

obj_parent_web

#

Make obj_parent_web the parents of all 4 of those objects.

#

And then, in your collision code, check for your Tilemap and obj_parent_web by putting those in an array.

#

And all of the children of obj_parent_web will count as instances of obj_parent_web

#

Without having to put each and every one separately into the array.

formal elbow
gleaming olive
#

Sure.

#

I think the thing to do next would be trying to make those object collidable normally, and then we can take a look at what, specifically, wasn't working as you wanted when they were collidable.

#

Next time, if you are so inclined.

formal elbow
#

do you wanna continue here in the server or like dms

#

cause either is fine :P

gleaming olive
#

Here probably. Honestly, I wouldn't throw a bunch of stuff at it until you've finished dealing with the basics. It should be relatively simply to:

  • Make it collidable
  • Make the player bounce when he hits it

Then you can work on the additional step of making the player bounce after a delay.

formal elbow
#

well all 3 ig

#

but night

gleaming olive
#

Seeya.

formal elbow
#

talk later!