Quando si utilizzano gli event listener, non si può prevenire la comparsa di due eventi se si premono due tasti contemporaneamente.
Ci sono alcuni modi per risolvere questo problema.
Il più semplice che mi viene in mente per la tua specifica situazione è fare in modo che, una volta effettuato il controllo, non venga assegnato il valore direttamente alla variabile "dir". Utilizzerei piuttosto una variabile temporanea, e poi l'assegnerei appena prima di calcolare il movimento.
Questo perché, assegnando subito la variabile 'dir', influenzi il risultato delle successive chiamate al listener.
let dir, tempDir;
document.addEventListener('keydown', direction);
function direction(event){
if(event.keyCode == 37 && dir != 'RIGHT')
tempDir = 'LEFT';
if(event.keyCode == 38 && dir != 'DOWN')
tempDir = 'UP';
if(event.keyCode == 39 && dir != 'LEFT')
tempDir = 'RIGHT';
if(event.keyCode == 40 && dir != 'UP')
tempDir = 'DOWN';
}
function calculateNewPosition() {
dir = tempDir
// Calcola la nuova posizione dello snake
}
In questo codice si presuppone che stai facendo un remake "classico" del gioco, dove il serpente si muove di blocco in blocco.
P.S. questa volta avevi poco codice, ma in futuro ti consiglio di usare il bottone che trovi nell'editor del post per formattare correttamente il codice (ha il simbolo </> )