Ashley's Forum Posts

  • I can't seem to reproduce this in Firefox.

  • Well, there's the "Signal" system action and "On signal" trigger, which provides a basic event listener system.

  • E.g. player would select scale factor 1, 2, 3, 4 etc and it would resize the window based on that.

    Why not use letterbox integer scale? That essentially does that and supports any window size. So then you shouldn't have to be trying to change the window size.

  • If it works in Chrome, it probably means Construct is working correctly - if the problem was with Construct then it wouldn't work in Chrome either.

    I think Brave has very strict privacy settings by default. This may mean it intentionally deletes local storage (confusingly also referred to as "cookies", although the term means any locally saved data). If it does that, then all you can do is change the browser settings to not do that.

  • I'm not sure, possibly - but games tend to redraw every frame anyway, so it's probably not that significant. Either way it's fixed in r364+.

  • 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.

  • I tried this out and was surprised to find it is indeed the case - adding a Text object in the editor increases the GPU work, even if you are not doing anything.

    It turned out to be a regression from fixing a bug a few releases ago (#7358). It's just causing the Text to keep redrawing. I fixed it for the next release so it won't use any extra GPU.

  • I think WebView2 doesn't currently support these window positioning methods out of the box. I filed an issue about it a while back.

    Can I ask why you need this though? It seems a weird thing to do. If you're trying to set a specific window size, it should default to the viewport size of your project.

  • Ashley do you think there is a chance that one day the Addon SDK would supports new "function-like True Triggers" for Timers or any plugin/behavior that wants to implement some kind of "Self-Functions" ?

    The triggers system is not designed to be used for performance-sensitive cases. Basically it's quite slow, but for things like input events, that doesn't matter. The built-in functions are specifically designed to be used in performance-sensitive cases, but they are deeply integrated in to the event engine and so aren't easily extendable. So I'd say if you really need maximum performance, use the built-in functions, but as I was saying before, probably the vast majority of cases don't need extreme performance, so some other solution is probably usually fine anyway.

    I did not expect timers to be this complex :V

    A good rule of thumb is everything is more complicated than you think! For example, want to know how long a string is? It's complicated.

  • It's not 10x the overhead of the entire behavior again, it's just the timer complete check, which is a very small and simple check. If you use triggers it still does that check but internally, and then has to fire a trigger which could well be 100x slower or more than the simple check, which would make rapidly firing timers much slower.

    As I say, it's all tradeoffs, and there is usually no perfect solution. Changing A for B usually means you tip the scales another way and some other case becomes worse. A general-purpose engine usually tries to avoid making any one case particularly bad.

  • I'd really caution against kneejerk reaction to performance numbers like this. It can really send you on a wild goose chase and end up in giving people bad advice.

    To illustrate how subtle performance is as a topic, you can take the "quad issue performance" benchmark, add the Solid behavior to the main sprite being created, and the benchmark drops about 3%. "OMG! Is the Solid behavior slow? Scirra should delete the extra code it's running to ensure maximum performance!"

    The thing is it is literally not running a single line of extra code. How could it be slower then? It uses a tiny bit more memory per instance. That means the hardware memory caching systems are a tiny bit less effective. So it takes a bit longer to run identical code. This goes further: you'll be able to measure bigger differences the more features you add, solely due to the increase in memory usage and caching effects. This is just a fact of computing. Advising people to avoid the Solid behavior due to this overhead is firstly pretty much useless advice, and secondly irrelevant to 99.9% of projects anyway, which don't have such demanding performance requirements.

    I can indeed measure a fairly big performance difference between the Timer behavior and using an instance variable. This is for three reasons:

    1. The Timer behavior uses the behavior ticking system, which for compatibility reasons must preserve a specific ordering. This means internally it iterates a special data structure which has a small overhead compared to iterating a simpler data structure like an array.
    2. The Timer behavior does not merely subtract from a variable. If you do that, you will find the timer drifts off from a real clock over time, because floating point precision errors accumulate. The solution to this is to use the Kaham summation algorithm, which improves precision enough to be suitable for practical purposes. Since it tracks both the current and total time, it in fact does kahan summation twice per tick.
    3. The Timer behavior has more features, like being able to dynamically add timers with a string expression for its tag.

    You can start by subtracting from an instance variable for your timer. But you may well find over time you run in to these same problems. If you want accuracy over time, then you need kahan summation; if you want a predictable timer finish order, you'll need to sequence things somehow; if you want dynamic timers, you'll need a dictionary or some other such feature to track state by string.

    All of those things add a small amount of performance overhead. When you do that with tens of thousands of sprites, the difference can add up and show up as significant results. However JavaScript is still super fast, the Timer behavior really is already about as minimal and optimal as it can be given its features, and I'm sure for 99% of projects it's perfectly fine. I don't think it's right to say "the timer behavior is slow": if you did all the same things it does in event sheets, you'd probably find your events are actually slower still.

    Sure, if you want a buggy and limited version of a timer solely to maximize performance at all costs, then you can do the instance variable thing. I suppose a few particularly intensive games might need that. But the Timer behavior still performs well given its feature set. There is no obvious way to further optimize it without deleting features. No, a "true trigger" won't help, because internally it still has to do the same checks, and that just means it fires the timer a different way. In fact the trigger infrastructure has a high performance overhead (as it's designed for things like input events, not performance critical stuff) and so making it a real trigger may well degrade performance further. In that case you can view the fact it's not a real trigger as an optimization.

    All software is about tradeoffs, and there is usually a fundamental choice: do you want it to have lots of features and work correctly, or maximize performance? If you improve one it will come at the cost of the other. We try to get a good balance with Construct, but if you have a specific situation, maybe you want a different tradeoff. That's OK but it doesn't mean the built-in stuff sucks.

  • As often as not, I find my use of arrays and dictionary to be tied to objects. Dropping them in a container is great... but I always use families.

    Thus... object picking is required for every object pair...

    Containers are meant to be the way this works - it gives you one Array/Dictionary/etc per instance. Does that not work with families? I guess that might be an oversight in the engine. Could you file an issue for that so I can take a look? Ideally this would just work and not need workarounds if you use families.

  • It looks like the TypeScript compiler removes unused imports by default, which doesn't work for importsForEvents.js, because it adds code after the import later on but the TypeScript compiler doesn't know about that.

    It looks like adding the option "verbatimModuleSyntax": true in tsconfig.json fixes this - I'll add that to the next beta so it's a default setting.

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • I tried it and it looks fine to me. Always share a project! More often than most people expect, it depends on exactly what you're doing.

    I'd guess it's some kind of mipmapping artefacts you're seeing, but that's only a guess without knowing what's really happening.

  • It's hard to comment because it depends on the details of what you're doing. If there's a 1:1 relationship between objects, you can use containers and everything should "just work" without needing extra picking. Even if not, if you can rearrange it to use such a system it may be more efficient. Nested loops tend to be pretty inefficient (as the algorithmic efficiency can be poor - a fundamental mathematical limitation that tends to make it slow in any tool). So if you can do anything that avoids nested loops it should help a lot. For example if instead of "for each bullet - for each effect in list", you can instead precompute the state for the bullet only when it changes and store it on an instance variable, then you don't need to do all that intensive CPU work every tick.

    If you have an extreme performance requirement and the event system just isn't cutting it, there is also the scripting feature - I know writing JS isn't for everyone but at least the option is there for raw code to make things as fast as possible if necessary.