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)
#Dynamic Collision boxes
247 messages · Page 1 of 1 (latest)
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.
so would I just make a sprite that's like 10-30 pixels wider than the web sprite?
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.
I'll try it and get back to you if there's any problems!
wait, how do I swap the collision rectangle code with something using the mask?
#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.
ok, like I said I'll try it out and hope for the best, but is this good or does it need to be written another way
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:
so like this?
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.
real quick how does the object know when to switch the masks? I'm confused over how it works I've never used masks before other than literally making a second object with the second sprite and overlaying the both
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;
}
could you think of any other ways to do this other than the mask? cause each way I try to do it it acts like the bigger mask is solid instead of letting the player pass through T~T
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?
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
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.
I guess that could be the problem, the player object checks for the web and stops
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.
this is how I want it, and I think you said what I was thinking right here but just to make sure, I was going to say "the thing is immediately bouncing when I want a more rubberband effect, like making it stretch before bounding you back"
also I'm now realizing I need to make the UI elements scale with the window 😅
yes, but it locks your movement before bouncing you like how you see I try to walk left or right in the video I put, but can't move
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-
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
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.
that
sorry lol I pressed enter by accident
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
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.
I mean technically I could store Yspd before making it equal to 0 reguardless of what kind of collision it is cause I have them grouped like this
and then have stuff like the webs just take that and use it like I have it just without the drawn collision boxes
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.
I mean like I could put like
XStore = xSpd;
xSpd = 0;
here instead of just xSpd = 0;
and then have my web objects pull Player_Prt.XStore
or YStore whichever I'd be using for the part
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.
I mean would this not work?
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.
yeah probably, but thanks for helping me think it out!
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.
can you please teach me how to do the Mask thing properly..? T~T
cause that idea failed miserably
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.
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
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..
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.
yeah, gimme a second and you'll be able to see
nothing else has been changed
the result
Am I looking at the player's step event? The object name has been cropped.
oh sorry yeah couldn't get it all in T~T
I was thinking it would be the collision detection I put in place
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?
it's just animation
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.
but I could try to add back the collision correction, I don't remember what it's called
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?
yeah if I'm understanding you right
the collision stays the same :P
No, it doesn't. image_xscale and image_yscale affect the collision mask.
It will stretch it.
I know that.. Idk what I meant before but I meant it stays the same length of the sprite just gets longer or bigger right?
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.
but then the mask would be like -- and the actual sprite would be ---------
the dashes being like the length I mean
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"?
x scale (for this one at least) is just to fill in gaps where the base size would leave space
You mean to fill in gaps in the terrain? Like, stretch it between two platforms?
yeah
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
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.
still the same for the X scale and Y scale, Y scale is only in the code and not in the room
32 is the middle of 64 right?
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.
like I said I could just make 2 animations if I need to
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.
I uh.. definitly did something lol
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.
yeah and if a player is going fast enough my semisolids don't stop them
you'd have to be going very fast, like drop from the top to the bottom of my bigger rooms
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.
yeah I know, but until it becomes a real issue (there's like 2 ways you could phase through my semisolids in total) I don't think fixing it is a priority
Fair enough.
hey...
there's a reason why this isn't working.. T~T
wait no I'm dumb nevermind
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.
the most likely thing I see is there is no.. uh clipping stuff
like no correction if you barely go into the object like a lot of my stuff does
(part of the code for no rotation)
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.
the thing is this is the code in the web object (sorry I had gotten called away to do something else)
oh wait
maybe it's because I only have the Y check and not both X and Y..
like in my player object
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.
wait it should be moving the player not the other way around
what did I screw up
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.
that's just this, I didn't change or remove them yet
So it moved.
in reality it looks like this (I colored where the collision box is)
A more direct way to see whether it is moving might be to draw or print its y coordinate to the console.
ok I'll try that
Also, not entirely sure whether the conditions of that loop are guaranteed to happen, so might want to give it a few attempts.
I don't think the y changed for any of these
though it is also accounting for all the objects in the room
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.
make the player stop?
it works in the player object's events
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.
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
I still haven't seen anywhere you're even changing the collision mask.
is changing the sprite not the same thing?
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
between these two
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.
so to do that would I literally just do "mask_index" instead of "sprite_index"?
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.
wdym?
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?
to be honest this in my player object create event is from a tutorial I followed years ago and I couldn't tell you how it worked, I tried to use it for the collision when I realized I couldn't use it in the player object code and I have no idea how it even half works
this to be exact
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?
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
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.
okay :3
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.
I think that's what I was doing? I just had
TileCollision = [TileMap,DWebPrtH,DWebPrtV,WWebPrtH,WWebPrtV]
and it worked like that but like I said before only without the rotation does it work TwT
Because of the name.
well right now it's only the tile map
ones you can break and ones you can't, horizontal and vertical versions of each
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.
sorry but it's getting late for me, could we possibly continue tomorrow?
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.
yeah, I'll try to buff it out when I can't talk cause I have some ideas like maybe some sort of distance based code along with other calculations but that's for later
do you wanna continue here in the server or like dms
cause either is fine :P
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.
and I had both down before I tried to rotate it
well all 3 ig
but night
Seeya.
talk later!