Arena Shooter tutorial

Step 2: Decorators, Game Object and Components

DOM provides all objects needed to efficiently code a game, it is a fully suficient game framework. All we need is to decorate them.

Our rocket will be <b id="R">A</b>, which is a HTMLElement object capable of render itself within browser canvas. We need to promote it to something similar to Unity's GameObject, object capable to perform in the game. For that, we use RenderDecorator below: if we need to remove it from the DOM, we need to call its free() method to remove its reference from Render object, and this is all we need (unlike class-based languages, JS doesn't have destructors).

Features is added via Components in Unity. JS allows adding new properties to created objects (it is a classless OOP, albeit ES6 also supports classfull OOP), so we will add the features via decorators as well. For this, we will use RotationDecorator to rotate left and right, and MovementDecorator to move and slow down to stop at arbitrary direction.

Now the left (keyCode 37), right (39) and speed up (38) works. To enable the movement, we also add position: absolute style to rocket element and transition: 30ms to smooth the transition between frames. Proceed to step 3 to decorate the Arena.

RenderDecorator = o => { o.updates = new Set; o.register = fn => (o.updates.add(fn), Render.register(fn)); = _=> (o.updates.forEach(Render.remove), o.updates.clear()); }; RotationDecorator = (o,L,R) => { o.angle = 0; Keys.reserved.add(L); Keys.reserved.add(R); o.rotate = delta => = `rotate(${o.angle+=8*delta}deg)`; o.register(_ => (Keys.down[L] && o.rotate(-1), Keys.down[R] && o.rotate(+1))); }; MovementDecorator = (o,U) => { o.speed = 0; o.angle = 0; Keys.reserved.add(U); o.register( _=> { if(U) { if(Keys.down[U]) o.speed+= o.speed>=10 ? 0 : 1; else o.speed-= o.speed>0 ? 1 : 0; } = o.offsetLeft + o.speed * Math.sin(o.angle * .017455) + "px", = o.offsetTop - o.speed * Math.cos(o.angle * .017455) + "px" }); }; RenderDecorator(R); RotationDecorator(R, 37, 39); MovementDecorator(R, 38);