Cowdozer's Recent Forum Activity

  • Ok thanks, good to know. I find them super useful, so I may switch at some point to pf_animations and just refer to the first frame.

  • Hi Ashley, that's a good point about copy, but I was originally writing the first image with source-over and got a nearly identical graph. Magnitude was different, since copy is faster than source-over, but relative magnitudes were very similar. So for that reason, I'm fairly confident that switching modes wasn't having an effect on the test.

    It's also a good idea to note that all the results I've mentioned has been regarding Chrome v24.

    Yeah, the Firefox results are interesting. It shows that both browsers could do a lot in optimizing canvas writes for various blend modes. It's actually source-over that firefox performs the best in, though. It's a little confusing because both source-over and destination-out are the same colour on the graph.

    It should be pretty straightforward to make another test using the WebGL renderer, but I haven't done any WebGL yet (implementing drawGL in my plugin is next on my list) so I'll save that test for later.

    Thanks for the info. Not being in the standard and not being supported are reasonable reasons not to include them. :)

  • Hello, I'm working on a plugin that displays an image with other things superimposed on it. In edittime.js, I use the flag pf_texture because I don't need sprite animations or want to have to deal with the complexities of a changing texture. When I call this.instance.EditTexture(); and get into the image editor, though, I cannot set ImagePoints or edit the Collision Polygon. I would like the user to be able to set at least one ImagePoint and to create their own Collision Polygon which outlines the image they are using.

    Is there any way to enable this, or is my only option to use pf_animations instead and simply ignore all but the first frame of the first animation?

    Thanks!

  • Hello, I was curious as to what the performance differences are between different blend modes when drawing to a canvas. As we know, Blend Modes in Construct 2 translate directly to the globalCompositeOperation when using Canvas. The same blend can often be achieved in multiple ways, so it's worth knowing which way is most performant. I set up a jsperf test here so you can see the results and test it yourself. It would be interesting to see results from different browsers and on mobile devices:

    jsperf.com/globalcompositeoperation/5

    Notable results: "copy" is by far the fastest operation, and "source-over" ("Normal" in Construct 2) is next. "destination-out" and "destination-in" are next fastest, but still much slower. Note that since the Canvas and the images being drawn are the same size, this does not necessarily reflect a standard composite operation. Usually a sprite will be much smaller than the Canvas it's being drawn to. This might significantly affect the relative performance of these composite operations.

    Side question: why is the "darker" globalCopositeOperation not available through Construct 2? We have access to "lighter" (called "Additive in Construct 2). Do some platforms support "lighter" but not "darker"?

  • Okay, that's fair. I wasn't suggesting that we reinvent the wheel and make our own Vector2 library, I just felt it was peculiar that there wasn't already some library that plugins could share among one another.

    I did notice that the Physics behavior had all of Box2D in runtime.js instead of using the dependency field and thought that that was strange. What benefit do you get out of having all of your source in one file?

  • So I did a bit of research and after getting a bit more info from this post (http://www.scirra.com/forum/topic60071_post391987.html#369144), I took a look at the [Construct2 path]\exporters\html5\layout.js file to see how it's done.

    Functions Layer.prototype.draw and Layer.prototype.drawGL make it obvious that there are 4 ways that a layer will be rendered to its own texture:

    // Needs own texture
    this.render_offscreen = (this.forceOwnTexture || this.opacity !== 1.0
                             || this.active_effect_types.length > 0
                             || this.blend_mode !== 0);

    This also shows that my setting opacity to 99.999% was doing nothing but triggering the layer to be rendered off-screen, so it provides absolutely no performance improvement over enabling the layer's Force Own Texture mode. It also shows that if you have set a Blend Mode for the layer, it will automatically render off-screen, and the Force Own Texture setting will not make a difference. Force Own Texture is only needed when sprites on the layer have a special blend mode that you only want to apply to the current layer.

    Aside from that, the description I had in the previous post about the rendering process was pretty correct.

  • Hi Jubalicious,

    I had some similar questions about layers and blend modes so did some research (and found this post as well). When Ashley says that it's rendered to its own off-screen surface, he means that memory is reserved to hold another full screen image. The off-screen surface can't be seen, and it's not hiding off the edge of the screen or anything. It's used as a scratchpad and you will never actually see what's drawn to that memory, but instead, after we've drawn to the off-screen surface, then we draw the image from the off-screen surface to the screen.

    If you're interested in the technical details, you can check the Javascript file "layout.js" functions "Layer.prototype.draw" and "Layer.prototype.drawGL". Draw creates a new HTML5 Canvas in memory (but it's never added to the webpage), and DrawGL makes a WebGL Texture object.

  • Yeah, sorry, I was referring to having a Vector2 class during runtime.

    Currently, the way I plan to use my own Vector2 objects (I'm still in the prototyping/debugging stage) is that I create about 6 local Vector2 objects once and use them as temporary variables. Initialization would look like this:

    instanceProto.onCreate = function ()
    {
      this.tempVec0 = new Vector2();
      this.tempVec1 = new Vector2();
      //or if I need a large number of temporary vectors
      this.tempVec = this.CreateArrayOfVector2(numTempVectors);
    }

    And then later, I might rename my temporary vectors in methods for clarity, but I don't actually create any new vectors during a frame. I know this is a very basic resource pooling method, but it's fine for my current needs:

    instanceProto.doSomething = function ()
    {
      var posn = this.tempVec[0];
      var norm = this.tempVec[1];
      var aToB = this.tempVec[2];
      ...
      posn.x = someObj.GetX();
      posn.y = someObj.GetY();
      ...
    }

    As far as I understand, this should not add any extra garbage overhead per frame. Please correct me if I am mistaken! It seems that it should be pretty simple not to create more garbage as long as you're disciplined enough to never create a new object after initializing your object/plugin.

    Is your opinion basically "If people have sharp knives, they're likely to hurt themselves and others, so I don't want to make it easy for anyone to have a sharp knife"? I think that's reasonable, but still, if you don't provide a framework for those who do want the sharp knives, they might not do a good job at making them themselves. Certainly, the Vector class I wrote years ago in school wouldn't have been acceptable.

    I see that in Plugin Settings (https://www.scirra.com/manual/18/plugin-settings) there is a "dependency" property for including additional files in runtime. Would it be reasonable to provide a Vector2 library, but force people to figure out how to include it in their plugin. At the top of Vector2.js you could have a big disclaimer about how misuse of vectors can ruin performance.

  • The discussion in short: Can we have a set of Vector2 math functions in Construct 2 available for any plugin to use?

    For certain plugins and behaviors, having a vector math library is extremely useful as it can often cut down the amount of challenging, error-prone calculations by at least half. We see this in the Physics behavior, where Box2D uses b2Vec2 extensively and has a thorough selection of vector math functions. I found it surprising that there is really no useful set of 2D Vector operations provided as part of the Construct 2 framework for all plugins to use. It seems that currently, the only option as a plugin developer is to include your own Vector2 definition and set of methods, which is obviously inefficient and wasteful if more than one plugin needs vector support.

    I understand Scirra's reasoning for avoiding pervasive use of a Vector2 object (primarily because it lends itself easily to careless object creation and GC problems). I have read these articles concerning Vector2's and garbage collection (the last two are written by Ashley):

    Efficient JavaScript Vector Math - media.tojicode.com/sfjs-vectors

    scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript

    netmagazine.com/tutorials/make-your-javascript-apps-smoother

    The key takeaway I get from these articles is that careless instantiation of objects is the main problem. It sounds like the overhead of accessing properties or indexing arrays (ie. v.x or v[0] as opposed to vx) or using methods instead of inlining calculations is insignificant and generally acceptable for the increased code readability.

    To address the risk of garbage, I think a simple comment on the Vector2 object linking to one of Ashley's above articles would help a lot. Also, the methods should all be designed with out parameters so that the user needs to instantiate the result objects ahead of time, and will hopefully do so smartly. An example of what some of these functions might look like:

    Vec2.addV = function (a, b, out)
    {
         out.x = a.x + b.x;
         out.y = a.y + b.y;
         return out;
    };
    //Linearly interpolate between a (when s=0) and b (when s=1)
    Vec2.lerp = function (a, b, s, out)
    {
         out.x = a.x + s * (b.x - a.x);
         out.y = a.y + s * (b.y - a.y);
         return out;
    };

    The return out; is optional (and I don't know if it affects performance over returning nothing), but it allows you to nest operations instead of being limited to one operation per line. Ex:

    //This code only does one math operation per line
    Vec2.addV(a, obj, originToA);
    Vec2.subV(originToA, origin, originToA);
    
    //But you have the option of compacting into a single line for the same result
    Vec2.subV(Vec2.addV(a, obj, originToA), origin, originToA);

    Regarding the option of using typed arrays over objects (see 1st article), I think it's still best to use plain objects with x and y properties. Using objects and static methods is actually nice; in the code above, obj is a Sprite object, but it can still be used as if it were a Vec2 because it has numeric x and y properties.

  • I understand that this expression exists, but that means in this case that I'll have to use a For each and compare two variables. It would be nicer to just have a condition for "Pinned to UID".

    Here's an example situation where it would help:

    dl.dropbox.com/u/117529592/Construct%202/Forum%20questions/PinnedToUIDExample.capx

  • Try Construct 3

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

    Try Now Construct 3 users don't see these ads
  • rexrainbow

    Thanks for applying the update so quickly! Yeah, I understand that a linear or quadratic force function will return very large numbers when the distance between objects is very small. At first I was surprised that your simulation wasn't doing that, and then I realised that you were applying a constant force. :p To prevent excessively large forces, you can cap the force at some maximum value, or use a slightly different function that doesn't approach infinity at 0.

    For example, if the function for f at distance d was f(d) = 1/d, then f(0.001) is very large. But if instead our function was f(d) = 1/(d+0.01), then the largest force is f(0) = 1/0.01 = 100. This is reasonable, yet is still linear and feels almost the same. The only real challenge here is finding a solution that works well for everyone who wants to use it.

  • LOL, I've never been chastised for digging up an old thread! There's a first time for everything.

    Anyway, this post is referenced in the FAQ, so I would argue that it's something that people are going to see even though it's an old post, and it's worthwhile to direct people to an alternate solution.

Cowdozer's avatar

Cowdozer

Member since 6 Feb, 2013

None one is following Cowdozer yet!

Trophy Case

  • 11-Year Club
  • Email Verified

Progress

12/44
How to earn trophies