diff --git a/client/index.js b/client/index.js index 87e1b26..d7bc2ce 100644 --- a/client/index.js +++ b/client/index.js @@ -1,5 +1,5 @@ import {create as createClient} from '@avocado/client'; -import {create as createEntity, EntityList} from '@avocado/entity'; +import {EntityList} from '@avocado/entity'; import {ActionRegistry} from '@avocado/input'; import {AnimationView, Color, Container, Primitives, Renderer} from '@avocado/graphics'; import {StateSynchronizer} from '@avocado/state'; @@ -13,22 +13,20 @@ const stateSynchronizer = new StateSynchronizer({ }); let selfEntity; +function hasSelfEntity() { + return selfEntity && 'string' !== typeof selfEntity; +} entityList.on('entityAdded', (entity) => { + // Add to graphics. if ('container' in entity) { stage.addChild(entity.container); - // Debug circle. - const primitives = new Primitives(); - primitives.drawCircle( - [0, 0], - 16, - Primitives.lineStyle(new Color(255, 0, 255), 1) - ); - primitives.zIndex = 1; - entity.container.addChild(primitives); } + // Set self entity. if ('string' === typeof selfEntity) { - // Set self entity. - selfEntity = entity; + const mappedUuid = entityList.mappedUuid(selfEntity); + if (entity.instanceUuid === mappedUuid) { + selfEntity = entity; + } } else { // Only self entity should be controllable. @@ -36,11 +34,12 @@ entityList.on('entityAdded', (entity) => { } }); entityList.on('entityRemoved', (entity) => { + // Remove from graphics. if ('container' in entity) { stage.removeChild(entity.container); } }); - +// Accept input. const actionRegistry = new ActionRegistry(); actionRegistry.mapKeysToActions({ 'w': 'MoveUp', @@ -48,29 +47,16 @@ actionRegistry.mapKeysToActions({ 's': 'MoveDown', 'd': 'MoveRight', }); +actionRegistry.listen(); let actionState = actionRegistry.state(); - +// Create the socket connection. const socket = createClient(window.location.href); +// Create the graphics canvas. const renderer = new Renderer([1280, 720]); const appNode = document.querySelector('.app'); appNode.appendChild(renderer.element); - -if (module.hot) { - module.hot.accept((error) => { - console.error(error); - }); - module.hot.dispose(() => { - entityList.destroy(); - appNode.removeChild(renderer.element); - stage.destroy(); - renderer.destroy(); - }); -} - -// Input. -actionRegistry.listen(); -// Messages sent. -const handle = setInterval(() => { +// Input messages. +const messageHandle = setInterval(() => { if (actionState !== actionRegistry.state()) { actionState = actionRegistry.state(); socket.send({ @@ -78,12 +64,15 @@ const handle = setInterval(() => { payload: actionState.toJS() }); } - if (selfEntity) { +}, 1000 / 60); +// Prediction. +const predictionHandle = setInterval(() => { + if (hasSelfEntity()) { selfEntity.inputState = actionState.toJS(); } entityList.tick(1 / 60); }, 1000 / 60); -// Messages received. +// State updates. let dirty = false; function onMessage({type, payload}) { switch (type) { @@ -108,3 +97,15 @@ function render() { dirty = false; } const renderHandle = setInterval(render, 1000 / 60); +// Hot reloading. +if (module.hot) { + module.hot.accept((error) => { + console.error(error); + }); + module.hot.dispose(() => { + entityList.destroy(); + appNode.removeChild(renderer.element); + stage.destroy(); + renderer.destroy(); + }); +}