Come creare un animazione in JavaScript (5) - tastiera
Possiamo integrare l'animazione precedente con l'aggiunta dell'interazione con la tastiera, ovvero la possibilità di controllare il movimento di uno sprite attraverso i tasti.
Come prima cosa costuisco un oggetto per memorizzare i tasti premuti:
poi, tramite gli eventi di tastiera keydown e keyup, posso settare le variabili corrispondenti ai tasti premuti e gestire meglio la situazione in cui il tasto viene mantenuto premuto:
A questo punto devo aggiungere una proprietà agli sprite (animationType) per decidere se deve essere mosso da tastiera e da quale combinazione di tasti:
Avendo un nuovo tipo di movimento, quello da tastiera, devo gestire in modo specifico l'aggiornamento della posizione:
e la collisione con i bordi in quanto, per gli sprite mossi da tastiera, non devo invertire il movimento:
Ovviamente devo anche aggiungere gli sprite mossi da tastiera:
Il risultato è l'animazione a inizio pagina.
Usa i tasti cursore per muovere il quadrato bianco e i tasti WDSA per muovere il cerchio viola.
Come prima cosa costuisco un oggetto per memorizzare i tasti premuti:
JavaScript
/* gestione eventi da tastiera */
// creo un oggetto che mantiene traccia dei tasti premuti
// e gestisco due set di tasti
// keyboardRight: W (alto), D (destra), S (basso), A (sinistra)
// keyboardLeft: tasti cursore
function UserInput() {
this.keyboardRight = {
up: false,
right: false,
down: false,
left: false
};
this.keyboardLeft = {
up: false,
right: false,
down: false,
left: false
};
}
//creo l'oggetto
const userInput = new UserInput();
JavaScript
const handleKeys = function (event) {
//in base al tipo di evento verifico se il tasto è ancora premuto o meno
const ok = event.type === 'keydown';
switch (event.keyCode) {
// cursor
case 38:
userInput.keyboardLeft.up = ok;
event.preventDefault();
break;
case 39:
userInput.keyboardLeft.right = ok;
event.preventDefault();
break;
case 40:
userInput.keyboardLeft.down = ok;
event.preventDefault();
break;
case 37:
userInput.keyboardLeft.left = ok;
event.preventDefault();
break;
// W D S A
case 87:
userInput.keyboardRight.up = ok;
event.preventDefault();
break;
case 68:
userInput.keyboardRight.right = ok;
event.preventDefault();
break;
case 83:
userInput.keyboardRight.down = ok;
event.preventDefault();
break;
case 65:
userInput.keyboardRight.left = ok;
event.preventDefault();
break;
}
//console.log(event.keyCode);
};
//aggancio gli eventi di tastiera
document.addEventListener('keydown', handleKeys);
document.addEventListener('keyup', handleKeys);
JavaScript
// gestisco il tipo di animazione
const AnimationType = {
NONE: 0,
LINEAR: 1,
KEYBOARD_RIGHT: 2,
KEYBOARD_LEFT: 3,
MOUSE: 4
};
function SpriteRect(x, y, w, h, color, fillColor, deltaX, deltaY) {
this.type = SpriteType.RECTANGLE;
this.x = x; // x e y sempre riferiti al centro dell'oggetto
this.y = y;
this.w = w;
this.h = h;
this.color = color == null ? null : color;
this.fillColor = fillColor == null ? null : fillColor;
this.deltaX = deltaX == null ? 0 : deltaX;
this.deltaY = deltaY == null ? 0 : deltaY;
//this.animationOn non mi serve più uso animation type
this.animationType = (this.deltaX !== 0 || this.deltaY !== 0) ? AnimationType.LINEAR : AnimationType.NONE;
this.alpha = 1;
this.animationType = AnimationType.LINEAR;
}
function SpriteBackground(x, y, w, h, fillColor) {
this.type = SpriteType.BACKGROUND;
this.x = x; // x e y sempre riferiti all'angolo in alto a sinistra
this.y = y;
this.w = w;
this.h = h;
this.fillColor = fillColor == null ? null : fillColor;
//this.animationOn non mi serve più uso animation type
this.animationType = AnimationType.NONE;
this.alpha = 1;
//gli oggetti di tipo background sono fissi, non richiedono animationType
}
function SpriteText(x, y, text, font, color, fillColor, textAlign, baseline, deltaX, deltaY) {
this.type = SpriteType.TEXT;
this.x = x;
this.y = y;
this.text = text;
this.font = font == null ? '14px Arial' : font;
this.color = color == null ? null : color;
this.fillColor = fillColor == null ? null : fillColor;
this.textAlign = textAlign == null ? 'left' : textAlign;
this.baseline = baseline == null ? 'bottom' : baseline;
this.deltaX = deltaX == null ? 0 : deltaX;
this.deltaY = deltaY == null ? 0 : deltaY;
//this.animationOn non mi serve più uso animation type
this.animationType = (this.deltaX !== 0 || this.deltaY !== 0) ? AnimationType.LINEAR : AnimationType.NONE;
this.alpha = 1;
}
JavaScript
function updatePosition() {
arena.sprites.forEach(sprite => {
//gestisco lo spostamento da tastiera tramite i tasti cursore
if (sprite.animationType === AnimationType.KEYBOARD_LEFT || sprite.animationType === AnimationType.KEYBOARD_RIGHT) {
const keyBoard = sprite.animationType === AnimationType.KEYBOARD_LEFT ? userInput.keyboardLeft : userInput.keyboardRight;
if (keyBoard.up)
sprite.y -= Math.abs(sprite.deltaY);
if (keyBoard.right)
sprite.x += Math.abs(sprite.deltaX);
if (keyBoard.down)
sprite.y += Math.abs(sprite.deltaY);
if (keyBoard.left)
sprite.x -= Math.abs(sprite.deltaX);
} else if (sprite.animationType === AnimationType.LINEAR) {
//normale animazione
sprite.x += sprite.deltaX;
sprite.y += sprite.deltaY;
}
});
}
JavaScript
function checkCollision() {
//verifico la collisione con i bordi
arena.sprites.forEach(sprite => {
//memorizzo se lo sprite è mosso dalla tastiera
if (sprite.animationType === AnimationType.KEYBOARD_LEFT || sprite.animationType === AnimationType.KEYBOARD_RIGHT) {
switch (sprite.type) {
case SpriteType.RECTANGLE:
const w2 = sprite.w / 2;
const h2 = sprite.h / 2;
if (sprite.x - w2 < 0 || sprite.x + w2 > innerWidth) {
//se è mosso dalla tastiera non devo invertire il moto
sprite.x = sprite.x - w2 < 0 ? w2 : innerWidth - w2;
}
if (sprite.y - h2 < 0 || sprite.y + h2 > innerHeight) {
//se è mosso dalla tastiera non devo invertire il moto
sprite.y = sprite.y - h2 < 0 ? h2 : innerHeight - h2;
}
break;
case SpriteType.CIRCLE:
if (sprite.x - sprite.radius < 0 || sprite.x + sprite.radius > innerWidth) {
sprite.x = sprite.x - sprite.radius < 0 ? sprite.radius : innerWidth - sprite.radius;
}
if (sprite.y - sprite.radius < 0 || sprite.y + sprite.radius > innerHeight) {
sprite.y = sprite.y - sprite.radius < 0 ? sprite.radius : innerHeight - sprite.radius;
}
break;
}
} else if (sprite.animationType !== AnimationType.NONE) {
switch (sprite.type) {
case SpriteType.RECTANGLE:
const w2 = sprite.w / 2;
const h2 = sprite.h / 2;
if (sprite.x - w2 < 0 || sprite.x + w2 > innerWidth) {
sprite.deltaX = -sprite.deltaX;
sprite.x += sprite.deltaX;
}
if (sprite.y - h2 < 0 || sprite.y + h2 > innerHeight) {
sprite.deltaY = -sprite.deltaY;
sprite.y += sprite.deltaY;
}
break;
case SpriteType.CIRCLE:
if (sprite.x - sprite.radius < 0 || sprite.x + sprite.radius > innerWidth) {
sprite.deltaX = -sprite.deltaX;
sprite.x += sprite.deltaX;
}
if (sprite.y - sprite.radius < 0 || sprite.y + sprite.radius > innerHeight) {
sprite.deltaY = -sprite.deltaY;
sprite.Y += sprite.deltaY;
}
break;
}
}
});
}
JavaScript
function createSprites() {
...
//aggiungo un quadrato BIANCO controllato dai tasti cursori
const velLeft = 3; // deve essere un numero positivo
const rectKeyLeft = new SpriteRect(cx + 50, cy, 20, 20, null, '#fff', velLeft, velLeft);
//cambio il tipo di animazione
rectKeyLeft.animationType = AnimationType.KEYBOARD_LEFT;
arena.addSprite(rectKeyLeft);
//aggiungo un cerchio VIOLA controllato dai tasti WDSA
const velRight = 3; // deve essere un numero positivo
const circleKeyRight = new SpriteCircle(cx - 50, cy, 10, null, '#f0f', velRight, velRight);
//cambio il tipo di animazione
circleKeyRight.animationType = AnimationType.KEYBOARD_RIGHT;
arena.addSprite(circleKeyRight);
}
- Come creare un animazione in JavaScript
- Come creare un animazione in JavaScript (2)
- Come creare un animazione in JavaScript (3)
- Come creare un animazione in JavaScript (4) - collisioni
- Come creare un animazione in JavaScript (5) - tastiera
- Come creare un animazione in JavaScript (6) - mouse
- Come creare un animazione in JavaScript (7) - immagini