Hello Guest, please login or register.
Did you miss your activation email?
Login with username, password and session length.

Pages: [1]   Go Down

Author Topic: Primary Object Collision  (Read 3287 times)

0 Members and 1 Guest are viewing this topic.
Primary Object Collision
« on: June 08, 2010, 11:23:19 am »
  • *
  • Reputation: +8/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6604

This isn't a comprehensive, all-inclusive update; in fact it is probably boring to most people. When adding collision checks to Link's coding I ran into two situations. The first was that either I would be doing a lot of place or position checks when really Link can only run into so much at once; in the case of the engine so far, at most he can only run into 2. The second was that ledge jumping and pushing had similar code "phenomena". For example, both move Link over their respective object if he is also in contact with something that is not that object as well. Furthermore, without determining what Link is primarily running into, the ledge and push code was inexact which could lead to errors or a bunch of corrective code.

I am also aware that if you push the idol directly beneath the ledge and then jump off the ledge onto it that it will cause odd behavior. Also, I am aware that this code is boring; I switched up the commenting style so that it doesn't look so much like the real stuff is getting chopped up either. Truth be told, I am also not as good as Niek at integrating various facets of an engine together so much as I am someone who tries to get at the guts - I'm also lazy. The other parts of the code weren't what I was focusing on, and sorting it all out with new stuff sometimes gets a little hectic.

The hole checking is also in there with a decrement to Link's hearts. Earlier I had run into errors where if pushing off of a pushable object a certain way that Link would get stuck in the pit or something. I think that error won't come up, but who knows it might.

The download is in the attachments (the site page was taken down and will get put up again later)
« Last Edit: October 04, 2012, 11:40:31 pm by Diminish »
Logged
Re: Primary Object Collision
« Reply #1 on: June 08, 2010, 01:22:33 pm »
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 3725
I have seen your PM and I already downloaded the attachment. I'll go over your code once I get the time for it. From what I can see already I don't like it really how you have integrated all those checks inside the movement loop. I understand that the loop is necessary to move link to a collision point and the corner cutting.

For checking if Link is walking against ledges, pushable objects, bounces and all that. I seems to me that it actually only needs to be done once. Do it more often makes the algorithm more complex and inefficient. Just putting it inside the movement loop makes the complexity of a polynomial order.

I have also been thinking about interacting with objects. And doing things through Gamemaker's inheritance hierarchy would give a very complex tree. Especially because Gamemaker only allows 1 parent. For example a pot. You might want it to be liftable and pushable, and being destroyed with a sword or a bomb. So instead of checking things by object type, I was thinking of giving objects an attribute list.
Logged
Re: Primary Object Collision
« Reply #2 on: June 08, 2010, 06:18:05 pm »
  • *
  • Reputation: +8/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6604
Those checks only have to be done when Link is moving, and being in the movement loop helps them achieve accuracy. When outside the loop, the values for collisions have to be estimated to how much Link can potentially move. By having a primary collision object (which reduces certain place or position checking), using position checks primarily over place checks, and because the movement loops will loop for usually 2 or 3 iterations, having the checks inside the movement is not too much in terms of how the code is processed. Additionally, the STEP state scripts tend to exit early if something in them makes processing them unnecessary.

And yeah, it is able to help with the corner-cutting. More precisely, if Link is moving into 2 objects and is able to move the primary one, prior to that he isn't corner-cutting the object at all. Because of this, objects can be moved either by skimming off them or when pushing between 2 objects that which he is pushing will go on far without him if he is then corner-cutting. I had tried also do have push code just update Link's x/y position rather than relying on the move_x/move_y but he still needs to be able to corner cut around certain objects when pushing.

At one point I had also tried to redo Link's movement so that he moved at normal speed rather than moving multiple times to match that speed because most of the time Link isn't colliding with anything. This was a little complex in backing out of objects Link runs into and moving accurately diagonally. The loop structure of movement does do certain things multiple times but as I said in the first paragraph, with only 2 or 3 iterations it isn't too bad. When moving out in empty space, there are about 7 iterations of position checking, then going into the object checking (Link Pushing needs to know if he isn't running into anything so he'll quit the state), for at most 3 times, and then doubled for Y movement. The types of checking aren't too intensive.

About object interaction and hierarchy, I see your point about what can be pulled, pushed, and picked up. Since objects can only have one direct parent, it is a little more complicated. They have some common elements in that like a pickup-able object is pushable, and a pullable object is pushable. Not sure how much complexity an attribute list would apply to objects, but inheritance can still do a brunt of the work just as good.

Sometimes certain commonalities in the code come up which demand that the code be done so around them. I am surprised you said nothing about how when pushing the pot it looks all shaky.

Edit: Oh, and what I said about inheritance can also be done such that a child only inherits aspects of the parent it needs.

Edit2: In the gmk, the pot is skippy because its object_index is greater than objLink, where as the idol has an object_index which is greater. Essentially Game Maker is doing the code for Link and a different possible block in a different order. Having Link as the last object fixes all of this.
« Last Edit: June 08, 2010, 11:46:17 pm by 4Sword »
Logged
Re: Primary Object Collision
« Reply #3 on: July 03, 2010, 04:16:52 pm »
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 3725
He I found an error in your collision detection in case of the ledge checking. Create the situation in the attached screenshot and you'll see that Link won't corner cut and not ledge jump.
Logged
Re: Primary Object Collision
« Reply #4 on: July 03, 2010, 04:57:18 pm »
  • *
  • Reputation: +8/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6604
I am not sure exactly what you did because that GMK I used has the left and right ledges as 16 x 16 blocks. If you altered them to be 32 x 32 and didn't alter the ledge code which checks based on idea of the default horizontal ledge being 16 x 16, you are probably going to encounter some errors. Well actually I tested the download link just changing the left and right ledges to be big in both appearance and mask, and it worked fine - I was unable to replicate the issue you encountered.

Albeit the previous way of collision detection with ledges, if checked in a certain order, would make Link corner-cut to the ledge if he was one pixel away from it and moving towards it. I don't know. The up/down corner-cutting for left/right movement has to work with how Link's shadow mask is an odd number of pixels - it double checks the center from each side for balance. In your screen image though, Link is not encountering that condition.

I'll try and replicate it again though later today or if I get more information about what you altered about the download.
Logged
Re: Primary Object Collision
« Reply #5 on: July 03, 2010, 09:51:01 pm »
  • *
  • Reputation: +9/-0
  • Offline Offline
  • Gender: Male
  • Posts: 3725
I am not sure exactly what you did because that GMK I used has the left and right ledges as 16 x 16 blocks. If you altered them to be 32 x 32 and didn't alter the ledge code which checks based on idea of the default horizontal ledge being 16 x 16, you are probably going to encounter some errors.
No I did not alter anything in the code. As I did not expected it to need. It does mean that the code is not really flexible or practical. I also don't think it will do much good for use by the community of the engine.

BTW: I encountered the same problem with the small ledges. But I think it has more to do with the insensitivity towards corner cutting.

Albeit the previous way of collision detection with ledges, if checked in a certain order, would make Link corner-cut to the ledge if he was one pixel away from it and moving towards it.
That was more the problem of corner cutting instead of ledgejumping. If the movement is horizontal, the corner cutting is done with the entire height of the shadow mask. While with vertical movement the corner cutting is done with only half the width of the shadow mask. Then the corner cutting was done with a size of 6 or 7, while your corner cutting this time is only 4. Making it less sensitive.


I do not know about adding your Ledge Jumping to a new release yet. Mostly because of the inflexibility. Ah well, I'll take a look at it. Maybe I'll get it somewhat more flexible.
Logged
Re: Primary Object Collision
« Reply #6 on: July 05, 2010, 06:50:49 pm »
  • *
  • Reputation: +8/-0
  • Offline Offline
  • Gender: Male
  • Posts: 6604
The code itself is not inflexible or non-practical. It makes the assumption that the smallest base unit of a left/right ledge is 16 x 16. The adjustments done to the distance to be checked for the open landing space are fine because otherwise checking for an open space would be more intensive. I could go over the code again and see if there is another way of calculating that which would be more favorable.

Before you go and call my code total !@#$% though, I think that when you first introduced pushing that while push blocks could be set to only move in certain directions, beyond that the code was !@#$% poor. It didn't account for other objects that Link might run into if he is pushing the block and not completely behind it, the object being pushed would move with Link not even trying to push it (Link would be able to move while the block was still in motion), the code for it was just tacked on without really ensuring that it hit well with the overall code, etc. I am not going to even get into the imperfections of the swimming engine.

And no, that was the problem of the ledge-jumping entirely. I was referring to a time when the ledge jumping code either had to be first or otherwise if checked after other solid objects there would have to be something like "if place_meeting(x, y + 1, parLedge)". The code in the latter would have to look beyond where Link was because the solid object would move him back so at Link's x/y he would no longer be hitting the ledge. You are correct, the corner-cutting code thus moved him back, but in no way would the problem be better solved by moving Link back in the ledge code. Instead, by the collision system implemented in this Primary Object Collision code, any obstacle object is remembered, any obstacle object can be corner cut around, etc.

Corner-cutting works in this Primary Object Collision system by checking both sides. If one of the sides is nothing and the other is something, then corner-cutting occurs. Corner-cutting works, for example, when moving left and running into something, if there is no object colliding with Link's top vertical half, then it checks with a certain sensitivity to see if Link can move up. It does NOT use the entire height of the shadow mask, both height and width use about half.

About the size being either 6 or 7, the code in the download link for corner-cutting actually checks equally to each side even though technically it doesn't have to. This wouldn't be an insensitivity, but an oversensitivity. The reason that horizontally one side only has to check out 6 pixels one way and 7 the other is that because the width is 14, the origin's x value can't have an equal number of pixels on each side. Unless you are referring to how the corner-cutting show look out further, if adjusted to do that, trying to run into a 16 by 16 obstacle makes it seem like that obstacle is covered in butter.

Then again, I am being stupid. The corner-cutting you must have been referring to is actually in the ledge code because the wall and ledge are both obstacles; thus when first running into them and the ledge is the primary object, no corner-cutting is done anyway. Link only ledge jumps when he is squarely over the ledge object though, and is moved to that position when the ledge is the primary object he is running into.

My code isn't as bad as you think it is, you're just straining to fit it to your specific way of doing things. In the last PM I sent you, that is why I suggested having two code bases to prevent this. I am not even asking that my base be the de facto one. Well actually, I would not have to ask as I am the administrator who started this project and supplied the first movement base which you had built off of. And again though, I have been unable to replicate the specific error you encountered; in all cases I would still jump over the ledge.

If this comes across as me being mean or an ass, well that is somewhat true. I like criticism and analysis of my code, but when my code is a tried and honest attempt at solving the fundamental structure of any code base - for it to get dismissed as a waste of time feels a little insulting.
Logged
Pages: [1]   Go Up

 


Contact Us | Legal | Advertise Here
2013 © ZFGC, All Rights Reserved



Page created in 0.243 seconds with 48 queries.