Ruskul's Forum Posts

  • I think you know the answer. It's likely not part of c3 because it wasn't deemed an internal priority or requested in high demand. Though I believe someone recently made a great plugin for it.

    But what does getting on your high horse accomplish? Do you think this will be added because you were shocked? Or by telling Scirra just how 'wrong' they are for not including it?

    Wouldn't it be far more productive, and more positive, to put this energy into a feature request?

    Nobody votes on those anyway, and when they do, Scirra mostly ignores it and adds something else. I just expected more to have happened in 10 years, especially since now we have to pay annually.

    Getting saltier by the day about that.

  • I'm a little shocked. I'll accept that I had to create this effect 10 years ago with c2, but now? Frankly, its time to get up on a high horse here and soap box.

    Bloom and color grading, if no others, are basically in every game for the last 10 years. I understand having to author particular effects, but pretty much EVERY game uses color grading and bloom, and to not include either in a game engine when you have 20 other useless effects is astounding... Indie to AAA, color grading is absolutely nec. Even if you are making a nes game clone, you need palette swapping and the easiest way to achieve that on modern hardware is with a table lookup. And bloom... Well... I mean, video games have been trying to fake it since the 90s and now we are post hdr by about 20 years.

    glow vertical + glow horizontal still equals absolute rubbish. It did 15 years ago, and it still does now.

    It's wrong if you like math.

    It's wrong if you like details.

    It's wrong if you have an any sense of aesthetics (unless your game is going for a chip on its glow's shoulder, but then so is everyone else in construct)

    And it's so easy to author a bloom and color lookup table, how is this not in c3?

  • Update -

    Updating positions for children isn't an issue since they can be set not track. When not tracking, there is basically 0 impact. However, the issue of not being able to set an array/dictionaries to hierarchies is still a problem, as you have to create a linked pair.

    I use Overboy's data+ behaviors, so the issue is mitigated. Alternates include using containers which (doesn't work with families) or uid standard linking.

    -----

    Hey all,

    Iʻm still mucking about trying to create a truly flexible, scalable, event sheet pattern that can handle dynamic and arbitrary inter-object relationships at runtime. Event sheet is key.

    Hierarchies are very useful in this, as they provide a way to traverse a parent/child pattern. You canʻt create such a system with families, as the links can only travel 1 layer deep before you have to have another family to track additional children. For example, you could have a family for top parents called System, their children are Components, the children of those are called modules, etc... Needless to say, using families, this pattern is not scalable. The family route requires repeating boiler plate logic for each additional type added.

    Great for hierarchies... but....

    Hierarchies demand that all objects are iworldinstances. Once again, construct has a neat feature that makes core assumptions about the use case of that feature, without considering all the applications that the feature could have had, had it been left open and singular in responsibility.

    Hierarchies, in principal, should have no need for position. Simply put, they define relationships between nodes.

    The reason this is important: Many times components define behavior in a system, and as such, using an object with position (that has to be calculated and updated) is unnecessarily bloated, increases overhead, and is performance degrading for no reason.

    While the issue of creating n-number of nodal relationships is solved with hierarchies, the constraint becomes component count. Ideally, modules solve a singular problem. You could break down the functioning of a single weapon on a tank into a dozens of modules. Multiply that by every engine, weapon, ammo box, and piece of armor on the tank. Thatʻs not good if every module now has to describe a position and is updated every tick.

    Back to the drawing board.

    ----

    If you donʻt understand why a component system is useful, consider the following - Lets say you are making a game where the player pilots customizable mechs. If the customization is knowable to the programmer, and the number of combinations is limited, its likely that hard coded solutions are acceptable. But lets say you can start with a frame, and add any number of components to it. Engines, batteries, fuel-cells, ammo, communications, sensors, thrusters, weapons, and so on.

    Even the weapon is customizable, the the player defining the magazine size, reload systems, triggering systems, barrels, etc...

    A tank is simple, until you consider that the player could put 5 canons on one turret, and a flamethrower on front, and bow and stern machine guns, and wings, because why not.

    If you can solve this problem in a flexible, scalable way, nothing the designer throws at the programmer will be a problem to add.

  • I like that way, but not if it needs to be used regularly in events through a single js block...

    Lets just say its fine, but if you have performance woes, avoid jsblocks inside loops at all costs. As a replacement for a custom action, for example, in a foreach obj loop, calling the function via js is like 300x slower than by event, as far as the raw overhead goes.

    On the other hand, if you have a function call from within a jsblock that is doing the iterating, that will be faster.

    TLDR is don't loop outside of a js block.

  • I believe instances are ordered and processed by their z-index. So A with the lowest z-index will be moved to B with the lowest z-index, and so on.

    Do you know why it is ordered according to z? Seems like it would be easier to leave in unordered from a performance/lazy standpoint.

  • I think many people have said they prefer c2 functions over c3 and for me personally that is because we cannot simply call a function from a string without it being first pushed through a router function.

    Router functions are nice for certain patterns, but sometimes you simply need a good old function pointer.

    Why canʻt we call a mapped function by string directly, and choose to send it parameters?

    The current implementation is unnecessarily rigid and overly complicated, and makes it impossible to have a 100% flexible function call.

  • For the explanation, that is what I thought, but I can create scenarios where each A has a B pair, and for some reason several A will be moved to the same B, leaving several B oh so lonely.

    Its possible that somehow the order of b in the list isnʻt being preserved in the order they are added, Let me see if I can get a demonstration capx built.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Lest say you have two types of objects, A and B.

    Lets create a different number of each. Then, lets toss 'em in a layout, with a good number overlapping each other.

    and have the following event:

    On start of Layout

    A is Overlapping B

    --- Set A position to B

    Now, on one hand, I'd naively expect every A to be aligned to a B that it was overlapping, but I'm smart enough to know that won't nec be the case. It tends to work with predictably even pairings, but at other times it the pairing won't be accurate, and there will be a few A moved to a B that wasn't being overlapped by that A.

    This concept translates to any situation where you need A to respond to a specific data on B or reverse. such as:

    A is overlapping B

    --- A set instancevariable to B.somVar.

    //A will not nec have the value of the B that it was overlapping.

    Can someone tell me what exactly is happening behind the scenes that results in... the mixed results we see in this situation?

  • Ashley - Its easy to say the cost of the tradoff is worth it; because you aren't paying that price.

    I really need you to understand that dev-hell already exists in construct in a very real way as a result of trying to avoid hypothetical dev-hell in future construct. Without a road map, all I can do is sit here and hope. Instead of useful, and basic features, we know have a follow behavior and flowcharts. Both aren't nec, and could be made by users if we had a functional api.

    The current api, however well supported, is insufficient to create basic behaviors. Creating a custom platformer should totally be possible, but it isn't without making private calls to a number of systems.

    You could try it in events... but...they offer little abstraction potential. It only takes repeating a complex behavior twice and then making modifications before any sane person learns you should NEVER be repeating logic.

    This can be overcome with verbose boiler plate picking systems or custom action overrides that are repetitive and require performance draining for each loops. To avoid that repetition and create a generic version, this can be avoided by creating a modular component system from objects and uid refs, but at that point performance is dead because you are essentailly creating a game engine in a game engine to address the game engines shortfalls.

    Then comes js editor side. Super awesome, until you realize once again you have to recreate just about every wheel construct has already made, and it also has another api to learn with some of the api existing on one side but not the other ... iCollisionEngine being a fine example. And most importantly, and ignored, a js block has a huge overhead performance cost over standard events, meaning like functions and custom actions, they have to be rationed in performance critical areas... meaning its back to manual inline, copy/paste, clone object, dev hell.

    Can I can share an example, that demonstrates the high performance cost of abstraction for a basic bullet hell game?

  • In the addon sdk I can do unofficially supported things... like this:

    const wi = this.GetWorldInfo();
    wi.SetSourceCollisionPoly(someAnimationFrameRefference.GetCollisionPoly());
    wi.SetBboxChanged();

    Is it possible to bypass the official interfaces provided in the editor, either in modules or js blocks?

    I was trying to test out moving some behaviors into modules, for ease of cross behavior interaction and the ability to extend classes, and I was having trouble figuring out how to do basic, unsupported api calls.

  • github.com/Scirra/Construct-feature-requests/issues/173

    At the end of the day, scripting is suggested to be able to solve needs that the event system can't.

    But...

    There is limited api access for basically EVERYTHING.

    The devs know this, but choose to ignore it for other priorities, and that makes sense in their position. But if Scirra has to access private internals to get a behavior or plugin to work, its because the public API is far too limited. You can't recreate a huge swathe of vanilla behaviors, let alone create better versions of them with the current public api.

    This isn't good if you care about creating anything unique, or have higher standards - I'm looking at you pathfinding, platformer, and 8way.

    This makes Construct an engine that supports ONLY out of the box behaviors. Creating sophisticated behaviors in events is poor in performance if you keep them abstract or wish to scale, and using JS to recreate all the wheels construct won't expose is stupid when other engines do you the favor of allowing you access. Plus, to beat a dead horse, the event system is objectively one of the best things about construct, in terms of speed of design. Wading into scripting editor side essentially defeats the advantages of working with construct and, objectively, there are much better engines out there if you are coding.

    The issue as I see it is that Scirra wishes to keep things internal to allow them to be able to a.) refactor at will when needed, and b.) not break peoples projects in the process, which is a great goal and I understand. But the flipside is that while construct is very stable, there is so little exposed that the promised "stability" is nearly pointless as you have to use the undocumented api to accomplish anything.

    All and all, I understand I am in a minority here.

    I am at a cross roads. I can keep building up my brittle collection of behaviors built on so many undocumented api calls...

    Many undocumented features have remained very stable over the years, and I'm okay correcting the odd compatibility issue here and there - But what if they become inaccessible or obfuscated in the future - for no other reason than simply scirra wants it to be? Ashley has hinted at that possibility - though that would pointlessly break many 3rd party addons that have necessarily used internal features.

    This isn't an issue if you are making small, uncomplicated games, or are happy with the provided boxed solutions. I am not, and I am not.

    How many other people have simply ignored the official advice and built behaviors on undocumented API?

    I personally don't feel like I have a choice. Either I use the unofficial api, or I don't use construct for this project... again...

    And to be clear, my project isn't fancy. I just want a custom platformer that doesn't resolve collisions the same way construct does, is extendable and well written in "SOLID" fashion, and one that isn't pigeon holed into using the solid attribute, along with better oneway jump through handing, slope performance, and a different physics integration model that accurately deals with variable accelerations over time. This is all pretty basic needs stuff AND construct has everything built in to handle this... just not exposed. What is exposed through the custom behavior makes alot of hard-coded assumptions about what is needed instead of just letting the user decide.

    For example: PushOutSolid, which is an undocumented function that custom movement behavior uses, has a hard coded max distance for resolves, a fractional nudge algorithm that iterates a hard coded 4 times, and only works with solids, when in fact, along with other internal functions, you can do less work and achieve sub-pixel perfect collision resolutions without limiting it to solids only or hard-coding the details.

    Construct has trapped itself in a place where it is afraid to expose api because it needs to stay flexible, but insisting on remaining backwards compatible for decades means things can't advance.

    ---

    Perhaps a new class of api should be released. A publicly documented "experimental" api. This would allow construct to sanction the use of more internal features, but with the caveat that they can change in the future, with "fair" warning.

    Basically, you can use them, but they are subject to documented change.

    Thoughts anyone?

  • I should add, depending on the setup, you may need to wi.setwidth set height, change image point, etc...

    If you aren't familiar with any of that, you should probably dig around and make sure you know the basics.

  • How to swap collision polygons without interrupting an animation

    TLDR: I use unofficial "Getters" to the construct3 CollisionEngine, in order to directly set collision polygons and bypass the sprite plugin changeframe/animation behavior. This allows me to control and check collisions from a behavior, and reduces alot of the overhead to changing frames through an ace. Since I bypass the change frame entirely, it doesn't disrupt any currently playing animations. It only affects collision polys on the object.

    The problem : Compound collider objects require picking loops, containers(no families), hierarchies (with picking loops for animation), or similar solutions

    The issue isn't obvious until you try to scale, extend, or have performance issues, then it's painful.

    When it comes to managing complex/compound objects, do you ever get annoyed with picking, iterating hierarchies, or dealing with containers, just to be able to have multiple collision polygons for an object? Picking loops often require a "foreach" loop, which can be expensive at scale. Hierarchies do a lot of additional lifting but will still likely require a loop if you need to separate view and model. And containers don't work with families.

    Sometimes, all of this isn't a big deal for unique objects, or those in lower quantities. But the more you have, the more difficult scaling will be, and extending any solution through abstraction will also require a lot of repetition.

    You can avoid the above if you create an animation on the object and simply switch frames for different collider polygons, BUT that comes at the cost of not being able to run animations automatically, and will require additional systems for tracking the animation state. Swapping frames around can also cause any triggers set up to repeat.

    The solution : WorldInfo polygon swapping.

    There are a number of ways to approach this, but currently, the way I do it is as follows:

    You will need a distinct objectType in the editor to be able to create animations and create collision polygons for various frames. It has no other purpose than to serve as a place to edit your collision polygons.

    Then you will need the object you want to have the super ability to change colliders without changing animation frames or interrupting the animation playing.

    Last... you have to create a behavior or script an equivalent tool editor side to then automate the process of changing polys. I chose to use a behavior.

    The behavior

    The behavior is going to have an action with 3 parameters to pass in an objectType(restricted to sprites), an animation string name, and the number of frames in the animation to collect.

    Here is a sample bit of code that sets up the behavior: (obj, animName, frameCount)

    const pickedInstance = obj.GetFirstPicked();		
    frameCount = Math.min(frameCount, this._stateCount);		
    const animation = pickedInstance.GetSdkInstance()._objectClass.GetAnimationByName(animName);
    for(let i = 0; i < frameCount; i++) {
    	this._stateFrames[i] = animation.GetFrameAt( i );
    }

    I haven't done any error checks here, so you have to be sure there is at least one object instance you are referencing, and that the animation name exists on the object and there are enough frames in it.

    Basically, this just creates a reference in an array on the behavior to the animation frames that have the collision polygons you want to use

    Later, via actions, or in tick(), you can do something like this to use it:

    const wi = this.GetWorldInfo();
    const ce = this.GetRuntime().GetCollisionEngine();
    
    //you can iterate through all states with a for loop, or pick individual frames
    //Keep all related variables in equal length arrays and you can easily iterate
    //Use solids, build a candidate list, or test against whatever
    wi.SetSourceCollisionPoly(this._stateFrames[i].GetCollisionPoly());
    wi.SetBboxChanged();
    if (ce.TestOverlapSolid(this._inst)) {
    	this._state[i] = 1;
    }
    else this._state[i] = 0;

    All in all, you can use the index however you please, I have variables on each object type that are the keys : ie _stateUp = 3, You are also free to add as many states/frames as you wish.

    For me, I also loaded the behavior with PushOut functions for solids and arbitrary object types, a suite of vector math tools, raycast tools, and some advanced physics/velocity/integration ACES.

    Using aces editor side, Creating a goomba is as simple as defining initializing the behavior with a 2 frame state check.

    EveryTick:

    ---Goomba UpdateStates

    Goomba State(left) or Goomba State(right)

    ---Goomba InvertXVelocity

    EveryTick:

    ---Goomba HandlePhysics //Integrate velocity and pushout of collision if applicable

  • Okay! Sounds like this case is nicely wrapped up, and has been for a while. I will do as you suggest.

    You may well be right about gc in c# not being as well optimized - and that sounds like an excellent rabbit hole research project for next time I am distracted :D

    Thanks!

  • Thanks for the details. I suppose that all makes sense,

    As I understand, you are essentially saying the cost/benefit ratio also doesn't exist engine side, due to increased bugs/complexity without a "real" benefit to most games. I agree given your explanation.

    2 things I disagree with though:

    1. Making a pool via events isn't worth it. The cost of the event editor overhead eats a major portion of the performance gained, and its nigh impossible to create a generic one that doesn't spend more energy than it saves. This activity is much better to be done in script - but the cost of tying that into the editor can still outweigh the performance gained IF you use js blocks. If everything is in script it and you don't need to make recycle calls from events, perfect.

    For that reason, I would argue it isn't worth the time, because the cost/benefit ratio just isn't there.

    2. GC is most performant when collecting newly created items. I think the vast improvement in JS gc is in this realm, yes? But recycling is good because it helps major collection (though total allocations has an ongoing cost). If the bulk of gc allocations are items created every tick, the collection of those items is much, much faster. These items are part of a minor garbage collection and typically get collected in the idle time each frame, so have no impact on frame or stutter whatsoever. However, if performance is being impacted by minor gc, reducing it is as easy as not discarding obj refs every tick and not creating objs just to discard them every tick.

    Items that remain in memory for longer get collected by the major collector and those can indeed cause frame drops when it runs. Object pooling helps most in this arena.