What's kind of this technology such as moving pixels?

  • > BlueSkies

    > Yeah it's the same way to access pixels.

    >

    > Logomachine

    > Physics would work in concept, but in practice it would be much too slow. A manual per-pixel motion as you describe would be a bit faster, but you'd need to implement most of it in js to get a useable speed.

    >

    You're right, it's CPU expensive, I tryed and i fall to 20FPS with ~500 sprite sized to 8x8 pixels on ground and wall.

    Do you think get the position of the overlapping blood sprite, write his color to the ground/wall sprite, then destroy his instance would be effective?

    Or does in engine like construct 2, run a plugin is the only way to get this result without killing the framerate?

    This is one of those times where C2 is actually too complicated to solve the problem, there's too much code bloat in using a game engine to do something so low level.

  • >

    > > BlueSkies

    > > Yeah it's the same way to access pixels.

    > >

    > > Logomachine

    > > Physics would work in concept, but in practice it would be much too slow. A manual per-pixel motion as you describe would be a bit faster, but you'd need to implement most of it in js to get a useable speed.

    > >

    >

    > You're right, it's CPU expensive, I tryed and i fall to 20FPS with ~500 sprite sized to 8x8 pixels on ground and wall.

    > Do you think get the position of the overlapping blood sprite, write his color to the ground/wall sprite, then destroy his instance would be effective?

    > Or does in engine like construct 2, run a plugin is the only way to get this result without killing the framerate?

    >

    This is one of those times where C2 is actually too complicated to solve the problem, there's too much code bloat in using a game engine to do something so low level.

    All right, thanks for answering.

  • Logomachine

    You could draw those sprites to the "paster" or "canvas" plugins, and then destroy the sprites to reduce the number of objects. The physics behavior itself has more features that we need. Basically we only need a simpler physics for the particles and a per-pixel collision detection. Such collision detection isn't compatible with polygon collisions, so all motion would need to be done via events. Drawing to the terrain is doable as stated above, but with a huge amount of moving pixels it would be faster setting pixels directly rather than using sprites and such which is faster for larger objects.

    Lastly to get the utmost speed js should be used instead of the event sheet.

    Elliott

    It's the type of game that needs as much optimization as possible and C2's general purpose nature isn't efficient for it. It does stuff like per-pixel collisions, and reading and writing pixels which C2 doesn't do because such features, even when optimized are only usable for low-res games.

  • Hello world (it's my first post here)!

    I'm responsible for Butcher's programming (and for a few other things, but that's unrelated now). We (THD) have received an email asking for explanation of how the game works, so I hope I'll provide you enough info about it.

    • I haven't used any external engine, it's a custom JavaScript (it started as a simple experiment/exploration of canvas capabilities). It has its good and bad sides. The bad side is that some parts definitely could be coded in a more elegant way, but overall it was a cool experience.
    • I haven't used WebGL (besides pixelation/stretching the screen, which seems to be faster if done with WebGL shader - the rest is fully software/canvas and you can play without WebGL support)
    • The burning logo, the rain of blood in the intro and the lava effects (including lava particles - they repeat after a while) are just color-cycled images, this part was partly inspired by Canvas Cycle demo, although the implementation and functionality is a little different (simpler I think):
      • The palette is a strip of colors that will appear in the output image, including transparent colors.
      • The input image is completely grayscale, each pixel represents a different place on the palette, shifted by a time variable (and also looped, so it can cycle)
      • I obviously read the input image once, then just put pixels repeatedly at the runtime.
      I must admit I did that thing mainly because of my nostalgia (some games used palette cycle technique in the past), I don't know yet whether that approach is useful or not (in comparison to normal animations), but it has some advantages (for example, creating organic animations like fluids or burning seems to be easier that way). R0J0hound was right that the canvas implementation requires low-res for good performance, but a pixel shader doing the same thing on much bigger textures could be very fast (it'd require only 2 texture reads after all).
    • The collision is based on internal array to avoid reading pixels. The level was even initially destructible in some areas, but we got rid of it as it didn't work out well for this type of gameplay. The collision masks are also pre-processed to avoid too awkward logic at the runtime (and also to make the movement smoother). For example, I detect slopes to simplify the platformer collision code.
    • I do use drawImage() a lot like other games, because that's the fastest method of drawing bigger sprites, also the game supports rotation and scale (saws, bullets, some particles), it's just not used that much because of the style we were aiming for. However, the level is indeed painted per-pixel because of the internally stored collision mask. I need to paint both the mask (i.e., the array) and the image, so the easiest way is just to paint pixels (one by one) of both at the same time (because I don't have any high level function to paint arrays ). It's definitely slower than using drawImage(), but the sprites painted on the level are very small (4x4 pixels max. I think), so it shouldn't hurt that much. The fastest and most flexible method of painting blood (and in general pixels that were potentially spread everywhere) was to draw filled 1x1px rectangles (because you don't want to draw 400x400 pixels just to draw 5 blood pixels and you don't have to create image data each blood pixel), at least that was what jsPerf test told me back then.
    • I use my own matrix stack and matrix operations, because it seems to be faster than save()/restore() on modern PCs/browsers. I think it squeezed out a 0.5 ms or so, not that much, but it was just kind of a mental masturbation to fiddle with it.
    • I use an extremely simple space division algorithm (I just divide the whole level to a "buckets" and put things in proper buckets according to their positions), it could support 1000 of self colliding squares spread throughout the whole level at 60fps on my computer, afair the drawing of the rectangles was a bottleneck here, so I considered it good enough for my case.
    • The Doom effect is just a bunch od drawImage() calls (each strip is a different call).
    • The game could run pretty smoothly on computers from 2007+, but the bottleneck on the older graphic cards was, surprisingly, stretching the whole canvas aka pixelation. The game was playable if played in its native resolution (320x180, yes, it's 16:9 ), it started to lose frames if you tried to stretch the screen to enlarge in-game pixels. Also, the modern browsers didn't want to support the WebGL pixelation on older cards, Chrome even blacklisted some chipsets. Oh well. That's one of the reasons I now develop the game on a different platform (I don't develop my own engine this time, I decided to use Unity - now I regret a little, because it's still not a perfect engine for that kind of game, but at least the new Butcher runs smoothly on older PCs).
    • Standalone versions are built with node-webkit.

    I think that's all for now, ask me if you want to know further details. I've originally tried to post some links, but I can't do it (the posts just didn't appear, no messages, no anything, I think it's a bug in the forums script - even if newcomers can't post links, I'd expect some validation messages).

  • Try Construct 3

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

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

    Thanks for the detailed write up. I always enjoy reading about that kind of low level stuff, and I could only gather so much from skimmed through the source. To post links, I've seen newcomers putting then inside

     tags and the forum doesn't erase them.
    
    

    spongehammer[/p] Logomachine[/p] I was toying with a way to access pixels to see how fast it could be from construct and here's a working test:[/p] [url=https://dl.dropboxusercontent.com/u/5426011/examples28/imageData.capx]https://dl.dropboxusercontent.com/u/542 ... eData.capx[/url][/p] It's fast but only when using js.[/p] With a 160x120 image, updating all the pixels took an average of 12 ms on my machine. For 60fps that plus everything else needs to be 16ms or less.[/p] The event system on the other hand was way to slow to loop over the pixels. I actually just looped over a 160x120 array to set each xy to a random number and got an average of [b]230 ms[/b].

  • smk

    That's crazy, seriously.

    I really appreciate your explanation what you did this game. I was wondering you used arrays for collision, didn't you use tilemap to get locations of x and y to register collisions?

  • With a 160x120 image, updating all the pixels took an average of 12 ms on my machine. For 60fps that plus everything else needs to be 16ms or less.

    The event system on the other hand was way to slow to loop over the pixels. I actually just looped over a 160x120 array to set each xy to a random number and got an average of 230 ms.

    Using your capx

    I got an average of 2ms.

    The looped option giving an average of 138ms

  • smk

    Thanks for your explanations, a lot of interesting stuff is in there, plus, it's always a real pleasure to get the behind the scene point of view. Very kind of you.

    R0J0hound

    Thanks, I understand better now, I will play with your .capx and experience the browser object (I've never use it before).

  • I really appreciate your explanation what you did this game. I was wondering you used arrays for collision, didn't you use tilemap to get locations of x and y to register collisions?

    Yes, originally I thought this game will be great with bitmap-based maps (like Liero or Worms). Concepts changed, but the old collision system still worked well, so I didn't change it. In the non-prototype version, though, the level is now tile-based (but the per-pixel gore effects work there too).

  • I did similar effects in construct classic and moved everything using pixel shaders to process faked liquid physics collisions, in particular for this game: http://gamejolt.com/games/super-clean-clean/19382. The thing is with games like this that have lots of dynamics, the event engine in construct creates too much overhead and you'd be better off writing your own engine/plugin to highly optimize things for the particular "special case" you design the game around. You just need too much low level control over rendering and collisions, where the general solutions construct offers aren't specialized enough.

Jump to:
Active Users
There are 1 visitors browsing this topic (0 users and 1 guests)