• Hello [name]! Thanks for joining the GMC. Before making any posts in the Tech Support forum, can we suggest you read the forum rules? These are simple guidelines that we ask you to follow so that you can get the best help possible for your issue.

Question - Code How do tile-based collision systems work with move_bounce, etc.?

csanyk

Member
Currently, move_bounce_all and move_bounce_solid are bugged, so I can't test with them.

These functions have traditionally worked with bouncing on objects. Now that we have tile based collision systems, I'm wondering what will become of functions like move_bounce? Will we need to use hidden instances for collisions after all if we want to use these functions? Will these functions work with tiles as well as objects? Will there be a move_bounce_tile function to work with tile-based systems?

What other GML functions are also affected by this type of concern re: tiles? Move_contact, move_outside? What about the motion planning functions (mp_*)?
 
I

icuurd12b42

Guest
I believe mike made a twitch about this last week, it's on YT
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Move bounce is literally:

hspeed *= -1
vspeed *= -1

So you can make your own with a tile collision easily. If the bbox left or right is in collision set hspeed *= -1. If the bbox top or bottom is in collision, set vspeed *= -1... ;)

Mouse contact and move_outside are simply using a "while" loop to check collision and move, which is again easy to do. And the MP grid functions are easy to set up as you have a set_cell function which can be used to set up the grid by parsing the tile layer.
 

csanyk

Member
Move bounce is literally:

hspeed *= -1
vspeed *= -1

So you can make your own with a tile collision easily. If the bbox left or right is in collision set hspeed *= -1. If the bbox top or bottom is in collision, set vspeed *= -1... ;)

Mouse contact and move_outside are simply using a "while" loop to check collision and move, which is again easy to do. And the MP grid functions are easy to set up as you have a set_cell function which can be used to set up the grid by parsing the tile layer.
@Nocturne, thanks for the explanation... but what about the "advanced" argument in move_bounce? How does the function work when this is set to true?
 

csanyk

Member
In all honesty, I have no idea!!!! I'll need to ask about that in the office tomorrow... :)
Reading the manual, it says that "advanced" uses the sprite's collision mask to do precise collision checking.

I think if I read that as literally all it's doing, and the bounce is still handled by *= -1-ing the vspeed/hspeed, then that's easy enough to understand.

I had always thought (assumed) that there was something more fancy going on, where the GM runtime did some super-fancy angle calculations based on the angle at which the precise collision mask hit the object it was in collision with, to do some sort of pseudo-physics to make the collision angles a bit more realistic. I gather this is probably not the case, but if you care to follow up w/ a confirmed answer, I'd really find that helpful!
 

Mike

nobody important
GMC Elder
Precise collisions are horrible. "solid" is even worse. Read this first....

http://www.yoyogames.com/blog/32

Now think that all it'll do is move it out slowly, continually checking the collision each step. So doing the check in that blog over...and over....and over. This is why tile collisions are so much better, they are virtually instant, and you can snap them in easily without doing this "loop" of horrible collision checks.

never...ever use solid if you're trying to produce anything you hope to have any kind of performance.
 

csanyk

Member
Precise collisions are horrible. "solid" is even worse. Read this first....

http://www.yoyogames.com/blog/32

Now think that all it'll do is move it out slowly, continually checking the collision each step. So doing the check in that blog over...and over....and over. This is why tile collisions are so much better, they are virtually instant, and you can snap them in easily without doing this "loop" of horrible collision checks.

never...ever use solid if you're trying to produce anything you hope to have any kind of performance.
I know... I only mentioned the _solid functions for completeness.

Are you guys ever going to get rid of the solid property? It seems like something so broken should be deprecated. Any reason why it hasn't been?
 
I

icuurd12b42

Guest
Precision need to calculate the normal of the thing it hits. I'm not sure how it does it but you can see something like this here collision_normal
 

FrostyCat

Redemption Seeker
Precise collisions are horrible. "solid" is even worse. Read this first....

http://www.yoyogames.com/blog/32

Now think that all it'll do is move it out slowly, continually checking the collision each step. So doing the check in that blog over...and over....and over. This is why tile collisions are so much better, they are virtually instant, and you can snap them in easily without doing this "loop" of horrible collision checks.

never...ever use solid if you're trying to produce anything you hope to have any kind of performance.
This is not about perceived good and bad practices, this is about having well-defined behaviour for implemented functionality and possible use cases. Either you make it clear what would happen in that case, or you state explicitly that it isn't supported/defined.

I know... I only mentioned the _solid functions for completeness.

Are you guys ever going to get rid of the solid property? It seems like something so broken should be deprecated. Any reason why it hasn't been?
There is still one valid use case for solid: Solid tagging.

Solid tagging basically sets solid in certain instances, uses solid-dependent functions to work with them, then unsets their solid status afterwards. This is a quick way to check collisions against a select group of instances of the same object/lineage, or among disparate instances sharing no common parent. The iteration across all instances is now responsible for the much cheaper operation of setting solid, instead of actual collision checking.

I agree that solid is awful when allowed to stay true, but I don't see any comparable equivalent for solid tagging (i.e. with only one call to collision checking functions). If collision-checking functions start taking arrays for its object argument, only then I'd agree with letting solid go completely.
 

csanyk

Member
This is not about perceived good and bad practices, this is about having well-defined behaviour for implemented functionality and possible use cases. Either you make it clear what would happen in that case, or you state explicitly that it isn't supported/defined.
This is a valid point, and a good one to make. I think @Mike's trying to be helpful in steering users away from features in GMS that have turned out to be misadventures. But it's still important to know how they work.


There is still one valid use case for solid: Solid tagging.

Solid tagging basically sets solid in certain instances, uses solid-dependent functions to work with them, then unsets their solid status afterwards. This is a quick way to check collisions against a select group of instances of the same object/lineage, or among disparate instances sharing no common parent. The iteration across all instances is now responsible for the much cheaper operation of setting solid, instead of actual collision checking.

I agree that solid is awful when allowed to stay true, but I don't see any comparable equivalent for solid tagging (i.e. with only one call to collision checking functions). If collision-checking functions start taking arrays for its object argument, only then I'd agree with letting solid go completely.
That's interesting! I've never heard of this or seen it done before. It would be nice if there were a way to separate this tagging use from the other baggage that attends to the solid property, though. It never fails to fascinate me how broken/disused stuff gets repurposed by clever engineers...

I would love it as well if there were collision functions that returned a data structure containing all of the id's of instances found to be in collision by the function.
 

FrostyCat

Redemption Seeker
I would love it as well if there were collision functions that returned a data structure containing all of the id's of instances found to be in collision by the function.
When something is doable within GML, YoYo can be counted on to ignore requests for getting it implemented. This is one of them.

For instance, here is the list-oriented analogue for instance_place():
Code:
/// instances_place(x, y, obj)
var list = ds_list_create();
with (argument2) {
  if (id != other.id && place_meeting(x+other.x-argument0, y+other.y-argument1, other)) {
    ds_list_add(list, id);
  }
}
return list;
If you want your wish to happen, you have to prove that this is an inadequate alternative. For example, if checking collisions with an instance ID isn't constant time (i.e. still loops through every instance), then there could be a case for getting it built-in to collect instance IDs en-passant. That would boost the performance from quadratic to linear time.

Make engine-level requests, present engine-level arguments.
 

Mike

nobody important
GMC Elder
SOLID is a long standing feature from Game Maker days. I've no idea when it was introduced but was certainly in Game Maker 7. It's still there for beginners, and so old projects that worked in studio could still be imported and work. It's incredibly CPU intensive, nasty, and doesn't always work, but for beginners (especially DnD users) it's a foot in the door, so it's here to stay until there's a better way.

When something is doable within GML, YoYo can be counted on to ignore requests for getting it implemented. This is one of them.
This is just stupid. If we were to implement everything you could do in GML you really would end up with the "Maker me an MMORPG" button. We can not make every function. We tried this before and we became a major bottleneck in development as users waited for the function/feature THEY wanted. This is why extensions were brought in, and it's why we don't even try to write all these little functions folk use.

IF....and I mean IF...there was a massive number of users that wanted a function, then we'd consider it, but when it's a handful, it's a waste of time if you can do it easily in GML.

We're not here to write your game for you, we're here to try and make it as simple as possible. But that doesn't mean doing every other function they might need to write.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
I would love it as well if there were collision functions that returned a data structure containing all of the id's of instances found to be in collision by the function.
Yep, so would I and we've discussed this internally and I've added a bug/suggestion to look at how feasible it would be to add functions which return a meaningful list of colliding instances. ;)
 
I

icuurd12b42

Guest
^ Oh yes, I want that! A lot of other functions could also have a multi-instance version that return, maybe through an array, all the items involved...
 

csanyk

Member
When something is doable within GML, YoYo can be counted on to ignore requests for getting it implemented. This is one of them.

[...]

If you want your wish to happen, you have to prove that this is an inadequate alternative. For example, if checking collisions with an instance ID isn't constant time (i.e. still loops through every instance), then there could be a case for getting it built-in to collect instance IDs en-passant. That would boost the performance from quadratic to linear time.

Make engine-level requests, present engine-level arguments.
This is just stupid. If we were to implement everything you could do in GML you really would end up with the "Maker me an MMORPG" button. We can not make every function. We tried this before and we became a major bottleneck in development as users waited for the function/feature THEY wanted. This is why extensions were brought in, and it's why we don't even try to write all these little functions folk use.

IF....and I mean IF...there was a massive number of users that wanted a function, then we'd consider it, but when it's a handful, it's a waste of time if you can do it easily in GML.

We're not here to write your game for you, we're here to try and make it as simple as possible. But that doesn't mean doing every other function they might need to write.
I was about to agree with FrostyCat that, at least in the past, YYG have been reluctant to add things to GMS that one could feasibly build in GML, but express hope that this was due to the abundance of code cruft in the Delphi codebase. The Modern C++ rewrite that is GMS2 was supposed to make it feasible to add features that would have broken the development team due to the amount of work that it would require.

Granted, it is possible to write a GML script that can check for collisions in a loop, removing instances temporarily, adding their id to a data structure, until no more collisions are detected, then restore the position of all the detected instances back to where they were, and return the list. I don't know that this is the best possible way to implement it, but it is feasible, it works. I've done it, and I've seen it done by others.

That means YYG shouldn't do it, right? Wrong!

The point of a framework is to provide functionality that other developers can use to create applications. It should eliminate the need for many developers working on similar projects to have to waste their time re-implementing things that are commonly needed.

Asking for collision functions that return all instances in collision is a far cry from asking for an "Implement MMORPG" button. It's a simple enough request, and if enough people have such a need, it would be worth YYG's time to consider implementing it, so that it's one of the tools in the toolbox they're selling to their users.

I know that returning a single instance is preferable from a certain standpoint: It's simpler to understand, and it's almost certainly faster at runtime. Yet, it's a pretty common newbie question that comes up perennially: "I just dropped "big sprite explosion" on "group of instances" and it only collided with one of them. How do I make it kill all of them?" Then they have to go back and re-think how the're doing their collisions. Maybe the targets should all handle a collision with the explosion, rather than having the explosion handle a collision with all the instances. Maybe the explosion should hang around an extra frame before being destroyed, to ensure that all collisions are detected. Or maybe, just maybe, having a multi-instance aware collision function would be a good solution.

How many developers have to stumble on the same problem and come up with their own solutions before it makes sense to put into the framework?

I guess YYG can use the telemetry data they're gathering from us to answer that question!

Please consider it!

In the meantime I suppose I'll work on an extension that I can sell in the marketplace... and maybe make $5/year from it :/ instead of being paid a reasonable salary as a fulltime developer would.

But I want to make games not spend all my time implementing functionality to build games. I do it because it's practical and sensible to create re-usable code, and because I like giving back to the community. On the other hand, I'd also really like to focus on making games. YYG are the ones who should be making the tools!
 
  • Like
Reactions: Ubu

Mike

nobody important
GMC Elder
So, my argument isn't with this set of functions (collision_ ones), its with the general attitude of "I want all function built in and if you don't do it, your useless", when it's perfectly possible to write a script for it.

Yes, having a framework lets you have lots built in, but it is impossible to build everything into it, and implying that we will simply ignore you if you ever suggest one is not only under valuing everything we do actually do, but claiming we're too bone ass lazing to bother. Both these things are just wrong, and bitchy. I've implemented loads of common functions that lots of users have asked for, all of which were do-able in GML because, well....LOTS of users asked for it. It's a waste of time and resources to implement an engine level function if only 1 or 2 people want it. Even if 1000 want it, if we have no time to do it due to other considerations no one outside the company will know about, then as long as it can be achieved via GML then you should be fine.

So perhaps @FrostyCat should stop being a dick when the solution to a problem is only half a dozen lines of code, and start realising we do more here than cater to his personal requests.
 

csanyk

Member
So, my argument isn't with this set of functions (collision_ ones), its with the general attitude of "I want all function built in and if you don't do it, your useless", when it's perfectly possible to write a script for it.

Yes, having a framework lets you have lots built in, but it is impossible to build everything into it, and implying that we will simply ignore you if you ever suggest one is not only under valuing everything we do actually do, but claiming we're too bone ass lazing to bother. Both these things are just wrong, and bitchy. I've implemented loads of common functions that lots of users have asked for, all of which were do-able in GML because, well....LOTS of users asked for it. It's a waste of time and resources to implement an engine level function if only 1 or 2 people want it. Even if 1000 want it, if we have no time to do it due to other considerations no one outside the company will know about, then as long as it can be achieved via GML then you should be fine.
Thanks for clarifying, @Mike. That is a much more reasonable stance than what it seemed like you were saying a moment ago.

Granted, it's impossible to implement every feature that gets suggested. Over time, though, the highest priority stuff should (one would hope) stabilize to where there's little if any maintenance needed, and at that time you can give attention to lower priority features.

I don't think YYG are lazy, at all, but over the last year+ prior to GMS2 going into public beta, there was a perception on my part as well as others that YYG were not responsive to suggestions. (My most frequent response to Suggestion Box posts seemed to be something along the lines of "This is a good idea but we'll never do it in 1.x, and we're not taking anyone's suggestions at all for 2.x." tied with "This won't be done in 1.x and *maybe* we'll look into it in 2.x.")

Not taking any feature requests forward out of 1.x into 2.x is what really felt painful for me. Understanding that you had your own plans for it, which you weren't at liberty to disclose, it would have been difficult to accept suggestions (or at least publicly acknowledge acceptance) but it created the perception that YYG was not responsive to customer suggestions.

Granted, now that we see 2.x, I'm happy to find that a number of suggestions that I'd made have been added (room inheritance, yay!)

Again, not having a detailed public road map showing YYG's intent for the future of the product also makes it harder for us to know whether you're working on the things we want or not. (We do now once again have a roadmap, but it's still a pretty high level document.)

I trust YYG to know what the most important and urgent things are to work on, but that doesn't mean that judgment shouldn't be challenged sometimes. That's why customers speak up, and why it's good that you hear and take it into consideration.

I will always feel better hearing something like "This is a good idea, and maybe it does belong in the framework at some point, but I don't know that we'll ever be able to get to it. The good news is you can write your own extension, and it may become popular if you put it on the MP and lots of others agree." than "Nope, we're not doing this, and you're lazy for suggesting that we should." Hard "no" responses should be for stuff that are totally infeasible or a bad idea for technical reasons.

I do also think that extremely popular extensions should eventually "graduate" and become rolled into the product, though (and it'd be nice to compensate the author, buying out their asset). That's essentially (more or less) how we got auto tile, right? Originally a forum post by @Nocturne, eventually a MP asset for 1.x, and now a fully supported feature in 2.0.
 

Mike

nobody important
GMC Elder
Thanks for clarifying, @Mike.I trust YYG to know what the most important and urgent things are to work on, but that doesn't mean that judgment shouldn't be challenged sometimes. That's why customers speak up, and why it's good that you hear and take it into consideration.

I do also think that extremely popular extensions should eventually "graduate" and become rolled into the product, though (and it'd be nice to compensate the author, buying out their asset). That's essentially (more or less) how we got auto tile, right? Originally a forum post by @Nocturne, eventually a MP asset for 1.x, and now a fully supported feature in 2.0.
Asking is always fine, and I think we've more than shown over time that we'll listen. Continually bitching is not. We're not just a faceless company, we're a load of developers who will get upset and offended by the continual rude, and sometimes downright offensive remarks.

Be constructive, be polite, or keep it to yourself.

No, auto tiling was a no brainer, lots of other tools have it. Actually... its funny seeing lots of folk going "oh look! They put in my suggestion!" actually... all the core elements were based off internal discussions and suggestions. Since it came out, we have of course added lots of community suggestions to help improve the product.

I'm also not a fan of pulling in popular extensions unless we're adding significant value to it. If they're doing well, then leave them.
 

rIKmAN

Member
In the meantime I suppose I'll work on an extension that I can sell in the marketplace... and maybe make $5/year from it :/ instead of being paid a reasonable salary as a fulltime developer would.
If you only make $5 a year from the extension, doesn't that just prove the point that @Mike is making in that it's not a highly requested feature?

As he said they simply can't cater to individual whims - they aren't creating GMS for you, or me, or any single person and they have to cater to the entire userbase based on number of requests or backing for a particular feature.

Whilst I don't disagree there are things that can and should be added to the engine, if they are easily enough done with a few lines of code as Mike is saying, then I can see why they aren't exactly high priority.
 

csanyk

Member
No, auto tiling was a no brainer, lots of other tools have it. Actually... its funny seeing lots of folk going "oh look! They put in my suggestion!" actually... all the core elements were based off internal discussions and suggestions. Since it came out, we have of course added lots of community suggestions to help improve the product.

I'm also not a fan of pulling in popular extensions unless we're adding significant value to it. If they're doing well, then leave them.
I figured. I don't mean to take credit for the suggestion that you expand inheritance to include rooms. I did make that suggestion, though, and it was shot down for 1.x. I didn't care about whether it was included in 1.x, or eventually sometime. I'm sure I wasn't the only person who had the idea, and I'm just glad to see things that people were asking for being added, regardless of the decision making process.

As far as buying out popular extensions so they can be included in the core product, I would agree that you'd need to be adding significant value. You would anger developers if you stole the best ideas and re-implemented them as core features, leaving them in the cold, though. That's something you would want to be very cautious about. That's why I suggested buying out, not simply adopting the ideas.

Much as other software developers offer bug bounties for people who find flaws or security vulnerabilities, you could make a "feature bounty" for people who come up with must-have extensions.

Of course they should probably go through some additional integration (re-implemented in C++ or whatever language you're using, for performance optimization at runtime, stronger integration with other features of the engine, IDE support if appropriate, etc.) so it's not like it wouldn't take some YYG-staff work to do this, but it's also important to reward the person who came up with the system somehow.

That all said, adopting popular assets adds value in several ways:
  1. Adding features to the core product gives the end user more value for their license.
  2. Other developers can build extensions of their own, off of the new feature, in ways that wouldn't work well if the new feature was kept as a separately purchased add-on that not everyone has.
  3. Official support and documentation, so the one-time add-on will never be broken by some future update to GMS.
  4. Consistency of coding/api style for a continually unified product.
  5. Frees up YYG devs to focus on core product improvement, while allowing them to integrate 3rd-party improvements with less work from the YYG dev team to deliver said features, and so acting as a force multiplier for the YYG development team. Almost as good as open sourcing the project, in some ways, since contributions can come from lots of people, but YYG still has control over the direction of the project. Maybe it's more like having a bunch of part-time programmers, or contractors working on things that YYG wouldn't mind seeing done, but doesn't have the resources internally to prioritize doing themselves. Properly managed, it could improve your velocity.
  6. Once integrated into the product, no user of YYG ever needs to re-invent that particular wheel, unless they really want to for some good reason. (Even today people implement their own hspeed/vspeed systems so they have full control over movement, which is fine, but it's also good that YYG have speed/hspeed/vspeed built-in.)
  7. It could be a "big break" that an amateur developer might use to get noticed professionally. I hate when companies exploit creative talent by getting them to do work cheaply "for exposure" but if the bounty system fairly compensated people who participated, I think it could work.
You get the idea. It's something to think about.
 
Top