Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Основы программирования на JavaScript. Учебное пособие

.pdf
Скачиваний:
0
Добавлен:
12.08.2026
Размер:
1 Мб
Скачать

те файл нажатием комбинации клавиш «ctrl + S». Попробуйте вместо 10 вставить -10.

Управление с клавиатуры

Игрок должен иметь возможность управлять движением Марио. Для этого в движке есть специальный массив keys, в котором хранится информация о нажатых в данном кадре клавишах. Чтобы получить доступ к нужной клавише, используется объект keyCode, который содержит коды клавиш, используемых в игре. Для клавиши «→»:

const keyRight = keys[keyCode.ARROW_RIGHT];

Возможные значения:

keyRight.isDown == true, если клавиша нажата в данный мо-

мент;

keyRight.wentDown == true, если клавиша была нажата в данном кадре;

keyRight.wentUp == true, если клавиша отпущена в данном

кадре.

Движением Марио можно управлять с помощью условного оператора if. Сделайте так, чтобы Марио двигался только тогда, когда нажата клавиша «→»:

export function updateMario(mario) { drawSprite(assets.sprMarioIdle, mario);

> const keyRight = keys[keyCode.ARROW_RIGHT]; > if (keyRight.isDown) {

> mario.x += 10 * time.deltaTime;

>

}

}

 

Добавьте движение Марио влево при нажатии клавиши «←» (рис. 7):

export function updateMario(mario) { drawSprite(assets.sprMarioIdle, mario); const keyRight = keys[keyCode.ARROW_RIGHT]; if (keyRight.isDown) {

mario.x += 10 * time.deltaTime;

}

>const keyLeft = keys[keyCode.ARROW_LEFT];

>if (keyLeft.isDown) {

>mario.x -= 10 * time.deltaTime;

>}

}

81

Рис. 7. Движение Марио влево

Сила тяжести

Как известно из физики, под воздействием силы тяжести объекты движутся с ускорением, направленным вниз, то есть их скорость постоянно увеличивается. За вертикальное перемещение Марио отвечает значение mario.speedY. Добавьте воздействие силы тяжести на Марио (рис. 8), увеличивая его скорость на константу settings.gravity каждый кадр:

export function updateMario(mario) { drawSprite(assets.sprMarioIdle, mario); const keyRight = keys[keyCode.ARROW_RIGHT]; if (keyRight.isDown) {

mario.x += 10 * time.deltaTime;

}

const keyLeft = keys[keyCode.ARROW_LEFT]; if (keyLeft.isDown) {

mario.x -= 10 * time.deltaTime;

}

>mario.speedY += settings.gravity * time.deltaTime;

>mario.y += mario.speedY * time.deltaTime;

}

82

Рис. 8. Воздействие силы тяжести на Марио

Продвинутое движение

На данный момент персонаж проходит сквозь стены. Для устранения этого недостатка в движке есть специальная функция:

function moveAndCheckForObstacles(entity, otherTypes) {...}

Функция moveAndCheckForObstacles передвигает сущность и останавливает ее, если она сталкивается с другими заданными сущностями. Возвращает сущности, с которыми произошло столкновение в данном кадре по горизонтали и вертикали (object). Параметры:

entity (object) – игровая сущность, которая будет передвигать-

ся на расстояние entity.speedX и entity.speedY;

otherTypes (array) – список типов сущностей, с которыми будет рассчитываться столкновение.

Внесите изменения в updateMario: удалите воздействие на координаты mario.x и mario.y, скорректируйте управление скоростью mario.speedX и mario.speedY и добавьте функцию moveAndCheckForObstacles:

export function updateMario(mario) { drawSprite(assets.sprMarioIdle, mario);

> const keyRight = keys[keyCode.ARROW_RIGHT]; > const keyLeft = keys[keyCode.ARROW_LEFT]; > mario.speedX = (keyRight.isDown -

keyLeft.isDown) * 5;

> mario.speedY += settings.gravity * time.deltaTime;

83

> moveAndCheckForObstacles(mario, [ENTITY_TYPE_WALL]);

}

Теперь Марио не проваливается сквозь пол и стены (рис. 9).

Рис. 9. Персонаж Марио опирается на пол и стены

Прыжки

Необходимо добавить Марио возможность прыгать, причем только в тот момент, когда он стоит на блоке. Для проверки коллизии используется функция moveAndCheckForObstacles:

const { horizWall, vertWall } = moveAndCheckForObstacles(mario, [ENTITY_TYPE_WALL]);

Параметры:

horizWall – результат проверки горизонтальной коллизии;

vertWall – результат проверки вертикальной коллизии.

Если в данном кадре не произошло коллизии по вертикали или горизонтали, horizWall или vertWall соответственно будут равны null. То есть, если Марио стоит на земле, vertWall будет не равен null.

Добавьте Марио прыжок при нажатии клавиши «space»

(рис. 10):

export function updateMario(mario) { drawSprite(assets.sprMarioIdle, mario); const keyRight = keys[keyCode.ARROW_RIGHT]; const keyLeft = keys[keyCode.ARROW_LEFT];

>const keyJump = keys[keyCode.SPACE];

mario.speedX = (keyRight.isDown - keyLeft.isDown) * 5;

84

mario.speedY += settings.gravity * time.deltaTime;

>if (mario.isOnGround && keyJump.wentDown) {

>mario.speedY = -12;

>}

>const { horizWall, vertWall } = moveAndCheckForObstacles(mario, [ENTITY_TYPE_WALL]);

>mario.isOnGround = vertWall !== null;

}

Рис. 10. Прыжок Марио

Движение камеры

На данный момент персонаж может свободно передвигаться. Внесите изменения в код, чтобы камера следовала за Марио по всему игровому уровню (рис. 11):

export function updateMario(mario) { drawSprite(assets.sprMarioIdle, mario); const keyRight = keys[keyCode.ARROW_RIGHT]; const keyLeft = keys[keyCode.ARROW_LEFT]; const keyJump = keys[keyCode.SPACE]; mario.speedX = (keyRight.isDown -

keyLeft.isDown) * 5;

mario.speedY += settings.gravity * time.deltaTime;

if (mario.isOnGround && keyJump.wentDown) { mario.speedY = -12;

}

const { horizWall, vertWall } = moveAndCheckForObstacles(mario, [ENTITY_TYPE_WALL]);

85

mario.isOnGround = vertWall !== null; > camera.x = mario.x;

}

Рис. 11. Движение камеры

Анимация

«Оживить» персонажа во время бега и прыжков можно, добавив анимацию с помощью функции drawSprite.

Направление изображения персонажа

Чтобы изменить направление изображения персонажа во время бега, нужно передать drawSprite опциональный четвертый аргумент scaleX. Тогда Марио будет поворачиваться по направлению движения, а не бегать спиной вперед.

Запишите новое значение mario.direction, которое должно будет меняться в зависимости от того, какая клавиша была нажата последней:

export function updateMario(mario) {

const keyRight = keys[keyCode.ARROW_RIGHT]; const keyLeft = keys[keyCode.ARROW_LEFT]; const keyJump = keys[keyCode.SPACE];

//анимация

>drawSprite(assets.sprMarioIdle, mario, 0, mario.direction);

//движение и коллизии

mario.speedX = (keyRight.isDown - keyLeft.isDown) * 5;

86

mario.speedY += settings.gravity * time.deltaTime;

if (mario.isOnGround && keyJump.wentDown) { mario.speedY = -12;

}

const { horizWall, vertWall } = moveAndCheckForObstacles(mario, [ENTITY_TYPE_WALL]);

mario.isOnGround = vertWall !== null; camera.x = mario.x;

}

Внесите изменения в код так, чтобы значение mario.direction изменялось на 1, если была нажата клавиша «→», и на -1, если «←» (рис. 12).

Рис. 12. Марио поворачивается по направлению движения

Анимация бега

Чтобы добавить анимацию бега, нужно сначала проверить, равна ли скорость Марио по оси x нулю, и если да, рисовать спрайт покоя:

drawSprite(assets.sprMarioIdle, mario, 0, mario.direction);

Иначе рисовать спрайт бега: drawSprite(assets.sprMarioRunning, mario, 0.2, mar-

io.direction);

В соответствии с условиями, приведенными выше, добавьте Марио анимацию бега (рис. 13).

87

Рис. 13. Анимация бега

Анимация прыжка

Для того чтобы добавить анимацию прыжка (рис. 14), необходимо определить, находится Марио в воздухе или нет. Используйте для этого значение mario.isOnGround:

export function updateMario(mario) {

const keyRight = keys[keyCode.ARROW_RIGHT]; const keyLeft = keys[keyCode.ARROW_LEFT]; const keyJump = keys[keyCode.SPACE];

// анимация

if (keyLeft.isDown) { mario.direction = -1;

}

if (keyRight.isDown) { mario.direction = 1;

}

>if (!mario.isOnGround) {

>drawSprite(assets.sprMarioJumping, mario, 0, mario.direction);

>} else if (mario.speedX === 0) { drawSprite(assets.sprMarioIdle, mario, 0,

mario.direction); } else {

drawSprite(assets.sprMarioRunning, mario, 0.2, mario.direction);

}

// движение и коллизии

88

...

}

Рис. 14. Анимация прыжка

Создание врагов

Добавим на карту в файле src/map.js символ G, означающий Гумбу (рис. 15).

const asciiMapRows = [

'

 

 

 

',

'

 

 

 

',

'

 

 

 

',

'

 

 

 

',

'

 

 

 

',

'

@

 

 

',

'

 

 

 

',

'

 

 

 

',

'#

#

 

 

',

'#

 

####

',

'#

G

#

#

',

'#############

###

#####################################'

];

Гумба появился в игре, но функция updateGoomba в файле src/entities/goomba.js только рисует спрайт, соответственно ее необходимо усовершенствовать:

export function updateGoomba(goomba) { drawSprite(assets.sprGoomba, goomba, 0.1);

}

89

Рис. 15. Персонаж Гумба появился в игре

Примените к Гумбе силу тяжести:

export function updateGoomba(goomba) { drawSprite(assets.sprGoomba, goomba, 0.1);

>goomba.speedY += settings.gravity * time.deltaTime;

>const { horizWall, vertWall } = moveAndCheckForObstacles(goomba, [ENTITY_TYPE_WALL]);

}

Добавьте в начало функции сегмент, который будет выполняться не каждый кадр, а лишь однажды, в начале игры. В этом сегменте можно задать начальные параметры сущности, например начальную скорость:

export function updateGoomba(goomba) {

>if (!goomba.isInit) {

>goomba.speedX = 2;

>goomba.isInit = true;

>}

drawSprite(assets.sprGoomba, goomba, 0.1); goomba.speedY += settings.gravity *

time.deltaTime;

const { horizWall, vertWall } = moveAndCheckForObstacles(goomba, [ENTITY_TYPE_WALL]);

}

После того как функция выполнится первый раз, значение goomba.isInit станет равно false и условие !goomba.isInit больше нико-

гда не позволит выполнить этот сегмент.

90

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]