11. Физика игрового процесса тоже адаптивна
Типичная ошибка в HTML5-играх: интерфейс адаптируется, но игровая логика продолжает использовать старые границы.
В Stickers Merge границы физического мира пересчитываются при изменении экрана.
LevelPhysicsBoundsResolver использует текущий виртуальный размер и вёрстку:
const virtualSize = this.screen.getVirtualSize();
const leftInset = this.screen.getOrientation() === 'land'
? this.resolveLandLeftInset(layout, virtualSize)
: 0;
const localTopLeft = playfield.view.toLocal({ x: leftInset, y: 0 }, root.view);
const localTopRight = playfield.view.toLocal({ x: virtualSize.width, y: 0 }, root.view);
const localBottomLeft = playfield.view.toLocal({ x: leftInset, y: virtualSize.height }, root.view);
В горизонтальной ориентации границы начинаются после левой панели. В вертикальной — с нуля, поскольку панель находится внизу.
При SCREEN_CHANGED FSM запускает:
[SharedUiEvents.ScreenChanged]: {
actions: ['RebuildLevelStickersOnResizeCommand'],
},
Команда вызывает:
await this.getSceneService<LevelStickerResizeRebuildService>(
GameServices.LevelStickerResizeRebuildService,
).rebuildFromCurrentScene({
layout: this.layout,
stickersLayer: this.getStickersLayer(),
});
Сервис:
- завершает активное перетаскивание;
- сохраняет текущее состояние наклеек;
- пересчитывает границы физического мира;
- удаляет старые физические тела;
- заново создаёт наклейки в новой вёрстке;
- прогревает физическую симуляцию;
- помечает наклейки как установившиеся.
const stickersSnapshot = this.captureSnapshot();
this.physics.setBounds(this.boundsResolver.resolveFromLayout(params.layout));
await this.mergeService.consumeManyByIds(stickersSnapshot.map((entry) => entry.id));
const respawnedRecords = await this.spawnFlowService.spawnBatch({
layer: params.stickersLayer,
physics: this.physics,
registrar: this.registrar,
entries: stickersSnapshot,
mode: 'packed_visible',
});
Адаптивный игровой процесс не ограничивается визуальным изменением размера. Физика, позиции создания объектов, границы столкновений и состояние перетаскивания тоже должны реагировать.