Долго, сложно и невыносимо интересно.
Долго, сложно и невыносимо интересно.
Но никто из них не доделывает до конца и не стремится объединяться
const me = {name: 'Alex', left: 0}...setInterval(() => update(), 1000)...window.addEventListener('keyup', () => me.left++)...requestAnimationFrame(() => draw())
const me = {name: 'Alex', left: 0}...setInterval(() => update(), 1000)...window.addEventListener('keyup', () => me.left++)...requestAnimationFrame(() => draw())
const me = {name: 'Alex', left: 0}...setInterval(() => update(), 1000)...window.addEventListener('keyup', () => me.left++)...requestAnimationFrame(() => draw())
const me = {name: 'Alex', left: 0}...setInterval(() => update(), 1000)...window.addEventListener('keyup', () => me.left++)...requestAnimationFrame(() => draw())
const me = {name: 'Alex', left: 0}...setInterval(() => update(), 1000)...window.addEventListener('keyup', () => me.left++)...requestAnimationFrame(() => draw())
Карты, персонажи, навыки, умения...
Это набор библиотек и утилит, для работы с картами
const ctx = canvas.getContext('2d')ctx.drawImage(hero, 0, 0)ctx.clearRect(0, 0, 100, 100)ctx.drawImage(hero, 100, 0)ctx.clearRect(0, 0, 100, 100)ctx.drawImage(hero, 200, 0)
const ctx = canvas.getContext('2d')ctx.drawImage(hero, 0, 0)ctx.drawImage(grass, 0, 0)ctx.drawImage(hero, 100, 0)ctx.drawImage(grass, 100, 0)ctx.drawImage(hero, 200, 0)
<canvas id="terrain"><canvas id="objects"><canvas id="ui">
Иллюзия непрерывного блока спасибо Яндекс-картам за идею
А ведь кол-во объектов на карте может достигать over 9000!
+ отсечение видимых объектов
+ корректное перекрытие
+ более дешевая итерация
const renderTree = {32: [object, object, ...]64: [object, object]96: [object, object, ...]128: [object]}
const object = getObject(id)const {x, y} = getAnimationFrame(object)const offsetleft = getMapLeft()const offsetTop = getMapTop()context.drawImage(object.texture, x - offsetleft, ...
context.drawImage(object.texture, x, y)
Поэтому мы просто возьмем и запишем их в Render tree!
const drawer = context.drawImage.bind(context, ...)renderTree.add(x, y, drawer)
И получим отличный прирост производительности!
new Promise(resolve => {setTimeout(() => {// расчеты для анимацииrequestAnimationFrame(() => /* рисование */)resolve()})})
startAnimation().then(step).then(step).then(step).then(step).then(doAction).then(endAnimation)
AsyncSequence([startAnimation, [stepstep...],doAction,endAnimation])
* а точнее — тайлы
const map = [[{...}, {...}, {...}, {...}, {...}, {...}],[{...}, {...}, {...}, {...}, {...}, {...}],[{...}, {...}, {...}, {...}, {...}, {...}],...]const tile = map[1][3]
const tile = {// данные для отрисовкиrender: {...},// данные для поиска путиpassability: {...},// данные которые нужны значительно режеotherStuff: {...},}
| Цикл отрисовки | массив функций отрисовки |
| Поиск пути | массив чисел |
| Ассоциация объектов к тайлам | массив строк |
| Дополнительные свойства тайлов | массив чисел |
| Для игровой логики | Map объектов c их ID |
Остается только своевременное обновление данных из медленных хранилищ в быстрые
const map = [[{...}, {...}, {...}, {...}, {...}, {...}],[{...}, {...}, {...}, {...}, {...}, {...}],[{...}, {...}, {...}, {...}, {...}, {...}],...]
const map = [{...}, {...}, {...}, {...}, ...]const tile = map[y * width + x]
const map = [{...}, {...}, {...}, {...}, ...]const tile = map[y * width + x]map.forEach((value, index) => {const y = Math.floor(index / width)const x = index - (y * width)})
Math.floor(X / 2n) === X >> n
const map = [{...}, {...}, {...}, {...}, ...]const powerOfTwo = Math.ceil(Math.log2(width))const tile = map[y << powerOfTwo + x]map.forEach((value, index) => {const y = index >> powerOfTwoconst x = index - (y << powerOfTwo)})
const grid = new Grid(32)const tile = grid.get(x, y)grid.forEach((value, x, y) => {})
- только квадратные сетки
- неэффективен для сеток стороной более чем 256
const okButton = new Buttton(0, 10, 'Ok')okButton.addEventListener('click', () => { ... })const cancellButton = new Buttton(0, 10, 'Cancel')cancellButton.addEventListener('click', () => { ... })
const okButton = new Buttton({left: 0,top: 10,onClick: () => { ... }})const cancellButton = new Buttton({...})
[{id: 'okButton',options: {left: 0,top: 10,onClick: () => { ... }},},...]
<button id="okButton"left="0"top="10"onClick="{doSomething()}"/>
При сборке он собирается в JSON с предыдущего слайда
<group id="main" ... ><group id="header" ... ><text-block ... /><button ... /></group><group id="footer" ... ><any-component ... /><button ... /></group></group>
После каждого шага нужно обновлять позицию героя в дереве отрисовки


const objectInAction = Objects.get(ID)const hero = Player.activeHeroobjectInAction.events.dispatch('action', hero)...this.events.on('action', hero => {hero.owner.resources.set('gems', this.value)this.remove()})
Доля динамических объектов около 10% от всех.
Так почему бы не сэкономить на расчетах:
// только при загрузке карты, содержит много данныхconst baseGrid = new Grid(mapSize)// обновляется намного чаще, потому содержит мало данныхconst dynamicGrid = new Grid(mapSize)
// Объект содержит гарнизон и может быть атакован@Mixin(Attacable)class TownObject extends OwnershipObject {...}// Содержит все для отрисовки флажка, его смены и т.п.class OwnershipObject extends MapObject {...}// Содержит все базовые поля для объекта картыclass MapObject {...}