Ruskul's Forum Posts

  • Have you ever had jump height, or other abilities seemingly feeling different when framerate differs? Even while using dt correctly?

    When using Euler integration, constant acceleration of an object can result in differences in in object position over time based on the frame rate. This is undesirable.

    Put in simpler terms, the method that the 8direction behavior uses to calculate the objects new position depends on the frame rate.

    Let v = velocity and p = position.

    Euler integration method:

    //calculate acceleration * dt

    v += Acceleration;

    p += v * dt;

    Using the above method, if we accelerate constantly over some time period, the higher the dt value, the further we we get. The more steps we have (the lower the dt value and higher frame rate), we will get a more accurate final position. In order to compensate for the errors in Euler integration (which works fine where times doesn't fluctuate), we should use the method below:

    //calculate desired acceleration * dt, then split in two parts:

    a1 = Acceleration * 0.5;

    a2 = Acceleration - a1;

    v += a1;

    p += v * dt;

    v += a2;

    This second method applies half the acceleration this frame and the remainder after position has been updated, meaning it won't affect the object until next frame. You can plot out the math. Or I'll update with a website link explaining it. EDIT: openarena.ws/board/index.php

    Anybody else use the above method to smooth out acceleration, gravity, or other forces?

  • In the ghost shooter script, ObjectInstance.TestOverlap(SomeOtherObjectInstance); is used.

    There is no _privateVariable marker there, so I would assume its okay, but again.... it isn't "documented", so technically it isn't. I guesse? Idk?

    There is a code snippet provided at:

    construct.net/en/make-games/manuals/addon-sdk/runtime-reference/event-sheet-classes/eventblock

    In the above, _runtime is referenced... Again, no documentation on it, but it is part of an example.

    Honestly, without actual, robust, examples, construct's sdk is kind of an exclusive club. The documentation is poor compared to other software. Seems odd to just list a few methods and functions on a webpage and call it good. Reminds me of getting into shaders. The fact that the built in behaviors can't be used as an example... they use so many "cheats", custom runtime modifications, etc...

    It means authoring plugins is an obscure and esoteric art fraught with unavoidable pitfalls.

  • I'm really confused.

    I read through the manual for addon sdk several times. I also searched for it as well...

    Every included behavior that moves instances around and deals with collisions involves getting a reference to the CollisionEngine and using it for things like .TestOverlapSolid. I notice the example with the GhostShooter tutorial uses .testoverlap but that also isn't mentioned in the sdk as far as i can find (when I search for it)

    runtime.GetCollisionEngine isn't included in the sdk, but .runtime is. Are we allowed to use it? Why or why not.

    Is this not a part of the official sdk, and if not, how are we "supposed" to go about testing for collisions?

  • I want to agree if it's going to grant us power, but just need to understand better.

    I think Iʻll give it a shot, Overboy can clear up anything I get wrong.

    Imagine you are creating a game. In said game you have a spaceship. The space ship is really just a frame with many components. Engines, shields, thrusters, weapons, hull parts and so on. Each component on the ship doesnʻt need to know about other components implementations. The shield doesnʻt care what type of engine exists, so long as the power output is sufficient. The issue with the using functions, is that component specific code now needs to be placed under the ownership of other components which is BAD for maintainability and scaleability.

    Lets say your dynamic spaceship is all set up and built by the player. Then lets say during a mission, an enemy fires a vampire hull mine that is triggered by arcane engine output excess. Where do you put that code?

    The easiest and best answer is that it should go in the eventsheet/script for the vampire hull mine, not the arcane engine script. When the custom action to activate the engine triggers, there should only be code related to what the engine does. It doesnʻt care it there is a mine on the hull or not. you shouldnʻt have to write "if vampirehullmine is attached, then call vampirehullmine.activate". Instead, that should be in the vampire mineʻs script : "On specific engine type on a specific craft activates...".

    What if you have a shield that autoactivates on the ship hull taking damage? Imagine all the code tangle that will become impossible to manage once you have 10 different types of energy storage systems, dozens of weapon types, dozens of engine types, modules that add unique and specific abilities, components that dynamically react to specific situations or the pressence of other components, and so forth. A single ship could easily have dozens of parts. Just like a character in a rougue action game could have dozens of dynamic abilities, plus equipment, plus weapons.

    The issue seems not so bad when you make a single spaceship object in an arcade shooter and just hardcode everything. But the moment you try to make complex interacting systems, you need architecture/organization to handle it. In my experience, you have to add alot of custom boiler plate code to handle message passing in construct. I use callbacks, but that means every object has to maintain a list of listeners and iterate through it in order to callback to them when some event takes place. That equates to alot of foreach/pickbyUID/callback function.

    AND I didnʻt even get into passing parameters! Which is an absolute must. Many times, you want to pass several, or a whole object... ("UID to ANYTHING" ) probably the best 3rd part asset ever.

  • You can color/effect certain portions of the sprites in the following ways:

    1. (expert), create an effect shader yourself that either uses a mask to target the effect (could be its own texture), or a use colorLUT based on index and generate the mask from there. Afaik, this method wonʻt be very scaleable, as it combines multiple shaders in one and isnʻt ideal on the programming side.

    However, it will result in the easiest editor side work. I donʻt think you can reference other shaders in a shader in construct, that would be ideal if you could. You need to obviously know your way around shaders to go this route.

    2. Create your base sprite (as you have) then Create an additional sprite out of the areas you want to specifically effect with the shader and apply the effect to those that object. It should have the same number of frames, etc, as the parent sprite. You can then either pin, or manually move the effect sprite to always match position with the parent. Or you can use object Hierarchies, whichever is easier for your project. You can split up an object like this into many different parts with many different effects.

  • I think this thread has deviated a bit from its original intent. But the whole discussion of these "real trigger function signals" are still kinda relevant

    Oh, I'm happily sipping tea over here. Might even grab some popcorn. In all seriousness, I agree with much of what Overboy is advocating for. Though, personally, I have never created a project that relies on broadcasting signals. I like callback methods to drive communication, but that is more tightly coupled for sure/

  • Ashley , thanks. I realized now after creating another project that it had to do with the way I was pinning the covering sprite (at the center), the speed of the height change (in absolute pixels over time) and the display resolution. By changing height over time (slowly over,say 5 seconds) with a center image point, the object ends up "clicking 2 pixels at a time" in height change. Basically, since the object is shrinking from both top and bottom, the way the math works you get both the top of the sprite and bottom rounding at the same time, creating a "click". If the sprite displayed is absolutely only 8 pixels on screen, and the screen is low res enough to see the pixels (1080p 15"), you can def see the height change occur in 4 "distinct" steps - which makes sense after doing the math.

    In short, setup issue, combined with a particular display.

    Thanks for the project file!

  • Would somebody be able to confirm an easy bug for me?

    You need to be using the editor in Firefox.

    Simply create a new project, create a sprite, and then open the sprite editor.

    Put the mouse cursor on the image and Click and hold with the middle mouse button to pan the image. While holding the middle mouse button down move the cursor to the browser tabs/urls UI at the top of the screen. What happens?

    When I am panning around a sprite and overshoot and my cursor ends up in the firefox menu/tab area. Construct crashes.

    This does not happen in Chrome for me.

  • Aloha all,

    I was curious if anyone else noticed this. When uses the mouse wheel to zoom in and out while in the sprite editor, firefox zooms in more better :D. While chrome requires expnentially more finger work to continue to zoom in. If that makes any sense.

    Basically, with one or two clicks you will be zoomed in on Firefox, but with chrome, the further you zoom in, the more clicks it takes to keep zooming in. This is very relevant while working with pixel art.

    Perhaps there is a setting I changed in the editor in one browser but not the other? Not sure if construct has a setting for zoom speed/scale/distance.

  • And it would solve the longstanding issue that there is no way to create Performant Signals supporting multiple parameters that can trigger multiple event blocks efficiently. Which is a shame in a Eventsheet based game engine.

    But anyway regarding Better Signals this would probably be a better solution : construct23.ideas.aha.io/ideas/C23-I-165

    Yeah, That would be nice.

  • Then you could add "unpredictable tick order", "single timer only mode", etc. all to make up the performance difference... and now what's meant to be a simple feature is full of complicated configuration options, which makes it harder to use, unfriendly to beginners, makes the code much more complicated, and usually ends in lots more bugs. It's not worth it. It's pretty much the approach we took with Construct Classic years ago, and it ended in development hell.

    Yeah, I agree with all of that - I think it would be way better to have to have a seperate behavior/or custom script altogether. Which incidentally is the way I already went.

  • I did not expect timers to be this complex :V

    Haha, Ashley #2 point is super important in some types of situations. Many times not, but when it is, it def is.

    But, I understand that it does all that, but why does the tween not have the overhead for "OnFinished" that the "OnTimer" does? I haven't looked through the tween code, but I assumed it handles its time in a similarly accurate manner?

    It would be nice if both tween and timer had built a built in dt scale though. Sometimes it would be nice to scale dt for per obejct slow motion or speed up.

  • Thanks, great post!

    I use a billion timers throughout my events, they're so efficiently convenient!

    Sounds like it's better to let them go and to just use the old fashioned DT event method, I need all the performance I can get.

    I mean, the ease of use might trump the performance. In my case I was using them on bullets in a bullet hell and well... performance was getting chewed up the way I was using them for EVERYTHING.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • I'm looking over the behaviors code, I can understand why one might want a fake trigger for order of events stuff. (Right, true triggers can fire at any time? Or is the order in the event sheet still protected?)

    But it still seems like there should be a true trigger for performance reasons.

  • I realized I'm using JSON object for almost everything now. It's not perfect, but so much easier to work with than C3 arrays.

    We have dozens of large array files in the project because it's easier to edit the data in table format, but in runtime I convert them all to JSONs.

    I'll have to look into this. My current project has arrays acting as an inventory of effects affecting the instance the array is connected to. I assumed it was better for performance reasons, but I haven't trie using json for it.