6 ms·
CutJS – Fast 2D HTML5 rendering engine for game development
- polskibus 12y agoThe approach reminds me of React in terms of keeping entire state aside from the DOM. Of course it is much older than React, but you can see it performs very well and is suited for things other than HTML elements.
- zerr 12y agoNice, but "Fast" - compared to what?
- shakiba 12y agoThanks! Fast enough for game development >= 60fps Check out http://piqnt.com/o/ http://piqnt.com/o/
- camus2 12y agoso you claim your engine maintains 60fps whatever the code is thrown at it right?
- shakiba 12y agoNot whatever, but it makes game dev as easy as web dev while still almost as fast as native development. See your CPU usage while playing.
- camus2 12y agoso you mean fast like RAD , not fast like SPEED,right ? because >=60fps highly depends on the machine one is running , and the browser one is using. Saying something is fast without benchmarks is stupid. speed is something relative. Nothing is fast or slow, but faster or slower than something else. So what is your framework faster than?
- seszett 12y agoFaster than SVG or DOM under certain conditions, obviously. Nobody is claiming that CutJS is "fast" in a somehow absolute way, I think most HN visitors are intelligent enough to understand that performance depends on the machine running the application and also on the complexity of the tasks that are running. Speed aside, CutJS seems like a nice canvas manipulation library, I'll have to give it a try.
- shakiba 12y agoNo, I didn't mean RAD by fast, I meant it makes development easier (than not using it) while it is still almost as "fast" as directly using Canvas and "fast" enough for game dev.
- deleted 12y ago[deleted]
- deleted 12y ago[deleted]
- IanCal 12y agoThat game judders and skips at times, I'm concerned if current "fast" HTML5 games are simple 2d games that perform badly. Even the asteroids game has perceptible little jumps. It's asteroids! It's one of the simplest to render games there is.
- varg 12y agoVery nice! ... was looking for something like this for some experiments, thanks.
- shakiba 12y agoThanks!
- illicium 12y ago>new concept called pinning introduced instead of styling It's just a scene graph.
- shakiba 12y agoPinning is about positioning variables, not graph structure.
- aviraldg 12y agoA scene graph is a scene graph is a scene graph. Whatever you call it. Also, it looks like the pinwheel demo has an error. I suggest you add one of the more advanced demos along with source code on the intro page. Just looking at the first few demos I felt it reimplemented stuff that's already possible with CSS, but it looks like it's capable of much more (the last few demos)
- shakiba 12y agoYes, a scene graph is a scene graph but by pinning I meant "how" the positioning is "described", not the fact that it is positioned. The game O! is open source. Everything is almost possible with HTML/CSS too, the point is performance across different devices. Thanks, found and corrected the error.
- deleted 12y ago[deleted]
- Jare 12y agoI couldn't understand exactly how it is supposed to work. Is it about defining anchor points in both parent and child (what you call "align" and "handle"), and then an offset from that?
- shakiba 12y agoExactly! Plus scale/skew and rotation.
- throwaway15213 12y ago>A CutJS app consists of a tree of nodes, each node is pinned (transformed) against its parent and have zero, one or more image cutouts. Image cutouts comes from either image textures or Canvas drawing. Won't SVG achieve the same thing?
- shakiba 12y agoYes, it has inspired me, but CutJS renders to HTML5 Canvas to be usable in game development.
- olegkikin 12y agoWhy not WebGL-based?
- pjmlp 12y agoMost likely because they also want to target mobile and system browsers don't allow for it.
- shakiba 12y agoExactly that's right, WebGL needed 2D fallback anyway.
- kevingadd 12y agoNote that most canvas implementations on mobile are not hardware accelerated, so you're not getting all that much for your trouble. ;/ WebGL on mobile performs much better than Canvas on mobile for configurations that support both, just like on desktops.
- pjmlp 12y agoWhich configurations? WebGL is forbiden on iOS other than iAds. Most Android devices don't support WebGL on their system browsers, requiring the users to install Chrome or FireFox. Even then, some devices have their drivers blacklisted. WP only supports partially hardware accelerated WebGL in some devices with IE 11 mobile.
- shakiba 12y agoWhen I started it 2D was enough for what I was trying to achieve, it is also both easier to use and more supported. However WebGL may be added in future, but currently it is a costly development effort for me.
- jablan 12y agoI know nothing about game development nor 2D/3D graphics, but why does an HTML animation of an airplane flying has to pin my i5 core to 100%?
- martinml 12y agoYou probably don't have GPU acceleration enabled/supported in your browser. For example, if you use Chrome, check about:gpu.
- jablan 12y agoThat's true (thanks), but anyways, it seems to me that a simple animation should take only a fraction of a modern CPU's (or GPU) power. Is the engine calculating more often than what's needed for 60fps or whatever refresh rate our eyes need to be satisfied?
- shakiba 12y agoThe issue is not with this engine, no other HTML5 game/engine can do better in your browser. CPU is not optimized to do what takes only a fraction of GPU.
- kevingadd 12y agoThis is false. Properly optimized rasterizers (like Adobe Flash's, for example) can deliver vastly superior performance for simple animated scenes like that, and have been doing so for over a decade. Cut's renderer would be much faster if it were designed in a GPU and CPU-friendly manner instead of the naive graph traversal it does right now (I'll post about this in detail outside this thread)
- shakiba 12y agoCutJS is already GPU and CPU-friendly, the problem is that his browser is not GPU-enabled and uses CPU for GPU tasks. It is not about CutJS, Canvas or Flash. When you use CutJS with a GPU enabled browser only a very small portion of CPU is used which shows that is CPU-friendly.
- dikei 12y agoYet another canvas manipulation library, just like fabricjs, kineticjs and easeljs
- mycounty 12y agoDoes it support high DPI (retina) resolutions?
- shakiba 12y agoYes, just use a high res texture and set imageRatio with texture definition. See http://piqnt.com/o/ http://piqnt.com/o/ It is open source and available for iOS.
- nacs 12y agoOne of the best 2d rendering engines I've found is Pixi.js ( http://www.pixijs.com/ http://www.pixijs.com/ ) which uses WebGL with a canvas fallback. Also works great on mobile. Theres another framework that uses pixi for the rendering but adds physics, sprite support and sound/input managers called Phaser ( http://phaser.io/ http://phaser.io/ ), also open source.
- shakiba 12y agoIf you like Pixi/Phaser you will love CutJS! Using CutJS is far simpler and you can use whatever physics and sound library you like. There are P2.js, PhysicsJS and SAT.js examples in repo. For sound you can use Howler.js, SoundManager, etc.
- kevingadd 12y ago'Fast' is a poor descriptive choice for a library that was clearly written without attention paid to CPU performance characteristics, GPU performance characteristics, or the nature of modern Canvas implementations. EDIT: A quick glance at the sample game 'O!' in the chrome profiler shows that it is triggering a garbage collection roughly every second. Pretty bad for a game with such low scene complexity and rendering complexity, and those pauses may be long on a mobile device. Based on a casual review of the source code (which I'll note is quite readable - good job!), here are some obvious problems that probably need to be addressed, both in terms of actual performance and code quality. Don't render the scene in graph traversal order; doing so ensures that the number of graphics state changes (shader, transform, texture, etc) is as high as possible. Most game engines render using a more sophisticated algorithm where your drawing operations are ordered (as possible - obviously layering has to be preserved) by graphics state in order to minimize overhead. For some documentation on this approach, see articles like http://realtimecollisiondetection.net/blog/?p=86 http://realtimecollisiondetection.net/blog/?p=86 I've been using this approach in my games for years and it produces a huge measurable performance improvement on virtually all modern architectures (even canvas, though it's less significant there) The tickBefore/tick/tickAfter architecture is particularly suspicious, as is its use of poorly-scaling algorithms/primitives like Array.splice. Usually this sort of thing is more clearly and efficiently handled by having an ordered set of operations (typically represented by a linked list, a heapqueue, or an array of priority-value tuples that you sort once per frame). I see frequent references to Cut.Pin.prototype.absoluteMatrix and .matrix. I will note that these don't appear to create garbage - which is great! - but they silently mutate a shared Matrix instance which means that it is very easy for a library consumer to end up with their state corrupted - if you store the result of absoluteMatrix, then modify the state of a Pin, that matrix will suddenly become corrupted. Sadly the code appears to make no effort to warn users about this. You're not using any type hinting (i.e. | 0, +) which means that JS JITs will have to work harder to figure out whether given values are integers, floats, or something else. This results in JIT recompilations, less efficient in-memory representation, and in some cases results in floating point/integer values being boxed instead of stored efficiently on the stack/heap. You mix different types in some of your slots (for one example, Anim._time is both 'object' and 'integer') which prevents optimization in most modern JS runtimes. This can have a catastrophic impact on performance in some scenarios, so you should avoid it if possible. A good way to replace a null/integer pattern is to have an integer that's always an integer, along with a hasValue boolean - this is how nullable primitives work in C#, for example. Some of your non-initialization code uses temporary object literals - this.pin({ ... }), this._next = { ... }, etc - which is a recipe for bad performance and GC pauses if you're doing it during updates or rendering operations. It's not immediately obvious to me whether you could optimize this out easily, but you should make sure these temporary literals are not being created in large quantities. You have many functions containing throw statements and a few containing catch statements. In most JS runtimes these both prevent optimization of the function body. You can solve this by hoisting the throw into a utility function (In JSIL I have a 'JSIL.RuntimeError' function that just does 'throw') - this allows the function to be optimized even if the throw-function is not optimized or inlined. When you have a single throw statement in a complex high-traffic function this can matter a lot. You appear to not be validating or properly type-casting the inputs you pass to canvas.drawImage, which will impair performance and result in runtime errors. I can tell you've already run into problems with this since your drawImage call has a try/catch wrapped around it (YUCK) - the right solution here is to read the spec (that more or less clearly specifies the expected types and constraints for drawImage), and then make sure your code satisfies those constraints. It will be much faster and more reliable if you do so. It appears that you may have many scenarios where you call drawImage with a source rectangle. This tends to be poorly-performing in canvas implementations (due to deficiencies in the spec), so if you want that to be fast for source rectangles that don't change, you should cache the source rectangle in a unique canvas so you can draw without source parameters. Typically source-rect blits can't be batched at all (i.e. one hardware draw call per blit) so this makes a big difference. I'm sure there's more, this is just the result of a quick skim of the code. Feel free to contact me if you have more questions. You can identify many of these performance problems by reading specs and using things like Chrome's profiler and Firefox's SPS and JIT Inspector profiling tools. I'm a huge fan of people sharing their libraries and engines with the world, but if you're going to spout superlatives you need to be prepared to back them up. Otherwise, people who don't know better will be misled by your dishonesty and end up having their efforts at using your tech go to waste when they have to port to something better.