Migające przedmioty w grze "Catch and dodge"

0

Siemka,

uprzejma prośba o pomoc- robię catch and dodge game i wszystko działa elegancko poza tym, że przy łapaniu przedmiotów lub przy ich upadku wszystkie przedmioty mrugają jakby omijały jedną klatkę. Problem występuje przy usuwaniu i dodawaniu elementów do tablicy. Owinąłem wszystkie splice'y w setTimeout 0 i problem występuje teraz rzadziej ale nadal się objawia.

Poniżej kod. Wszelki feedback mile widziany.

export function gamePage() {
  startCounting();
  app.innerHTML = `
  <div id="gameContainer">
  <canvas id="canvas">
</canvas>
<div id="topBar"><span id="gameScore">Punkty: 0</span> <span id="gameTime">
Czas: 00:30</span><span id="gameLives">Życia: <img src="/assets/img/02/elementy/zycie.png"></img><img src="/assets/img/02/elementy/zycie.png"></img><img src="/assets/img/02/elementy/zycie.png"></img></span></div>
</div>`;

  const time = document.getElementById("gameTime");
  const gameScore = document.getElementById("gameScore");
  const gameLives = document.getElementById("gameLives");
  const gameContainer = document.getElementById("gameContainer");
  const topBar = document.getElementById("topBar");
  var seconds = 30;
  let gameTimer = setInterval(showTime, 1000);

  function showTime() {
    seconds--;
    let mins = Math.floor(seconds / 60);
    let secs = Math.floor(seconds % 60);
    time.innerHTML =
      "Czas: " +
      mins.toString().padStart(2, "0") +
      ":" +
      secs.toString().padStart(2, "0");
  }
  const canvas = document.getElementById("canvas");
  const height = window.innerHeight;
  let heightChange = window.innerHeight;
  let widthChange = (heightChange * 9) / 16;
  let width = (height * 9) / 16;
  let tile = height / 32;
  canvas.setAttribute("height", height);
  canvas.setAttribute("width", height * (9 / 16));
  const ctx = canvas.getContext("2d");
  var body = document.getElementById("body");
  let windowWidth = body.offsetWidth;
  let windowHeight = body.offsetHeight;
  let gameWidth = canvas.offsetWidth;
  let gameHeight = canvas.offsetHeight;
  const widthConst = width;
  const heightConst = height;

  if (gameWidth >= windowWidth) {
    topBar.classList.add("active");
  }

  window.addEventListener("resize", () => {
    heightChange = window.innerHeight;
    widthChange = (heightChange * 9) / 16;
    windowWidth = body.offsetWidth;
    windowHeight = body.offsetHeight;
    gameWidth = gameContainer.offsetWidth;
    gameHeight = gameContainer.offsetHeight;
    tile = height / 32;
    width = (height * 9) / 16;

    if (gameWidth >= windowWidth) {
      // canvas.setAttribute("height", heightChange);
      // canvas.setAttribute("width", (heightChange * 9) / 16);
      // canvas.setAttribute("height", heightConst);
      // canvas.setAttribute("width", (heightConst * 9) / 16);
      console.log("height2 ", canvas.height);
      console.log("width2 ", canvas.width);
      topBar.classList.add("active");
    } else {
      canvas.setAttribute("height", "840px");
      canvas.setAttribute("width", "472.5px");
      // console.log("height1 ", canvas.height);
      // console.log("width1 ", canvas.width);
      topBar.classList.remove("active");
      // player.x = canvas.width / 2 - player.width / 2;
      // console.log("ok");
    }
    player.width = canvas.height / 6;
    player.height = (canvas.height / 6) * 1.15;
    player.y = (canvas.height * 7.6) / 10;
    gameWidth = canvas.offsetWidth;
    gameHeight = canvas.offsetHeight;
  });

  const enemies = {
    speed: 3,
    arr: [],
    total: 4,
    images: [
      "./assets/img/02/elementy/burger.png",
      "./assets/img/02/elementy/frytki.png",
      "./assets/img/02/elementy/hotdog.png",
      "./assets/img/02/elementy/kawa.png",
      "./assets/img/02/elementy/nano.png",
      "./assets/img/02/elementy/sok.png",
      "./assets/img/02/elementy/tortilla.png",
      "./assets/img/02/elementy/zapiekanka.png",
    ],
  };

  const game = {
    play: false,
    req: "",
    dif: 0.09,
  };

  var player = {
    speed: 1,
    width: canvas.height / 6,
    height: (canvas.height / 6) * 1.15,
    color: "red",
    score: 0,
    lives: 0,
    image: "./assets/img/02/elementy/torba.png",
    hotdog: 0,
    sok: 0,
    burger: 0,
    kawa: 0,
    frytki: 0,
    zapiekanka: 0,
    tortilla: 0,
    x: canvas.width / 2 - height / 6 / 2,
    y: (canvas.height * 7.6) / 10,
  };

  function col(a, b) {
    let boo =
      a.x < b.x + b.width &&
      a.x + a.width > b.x &&
      a.y < b.y + b.height &&
      a.y + a.height > b.y;
    if (boo) {
      // console.log("HIT");
    }
    return boo;
  }

  function enemyMaker() {
    let number = Math.floor(Math.random() * 8);
    let xPos;
    xPos = Math.random() * canvas.width * 0.5;
    // console.log("window 1", gameWidth);
    let badValue = false;
    enemies.arr.push({
      x: xPos + 0.5 * xPos,

      y: Math.random() * -1000,
      speed: (Math.random() * windowHeight * 3) / windowHeight + 2,
      bad: badValue,
      image: enemies.images[number],
    });
    // console.log(xPos);
  }

  function gameOver() {
    cancelAnimationFrame(game.req);
    game.play = false;
    ctx.beginPath();
    scorePage();
  }

  function gameStart() {
    game.req = requestAnimationFrame(draw);
    game.play = true;
    player.score = 0;
    player.lives = 3;
  }

  function draw() {
    if (time.textContent.includes("00:00")) {
      gameOver();
    }
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    if (enemies.arr.length < enemies.total) {
      // console.log(enemies.arr);
      enemyMaker();
    }
    canvas.addEventListener("mousemove", mouseMoveHandler);
    // canvas.addEventListener("click", mouseMoveCheck);
    let oldX;
    let newX;
    let diffX;
    function mouseMoveHandler(e) {
      if (windowWidth > canvas.width) {
        // console.log("e client X", e.clientX);
        // console.log("oksss");
        oldX = 0;
        newX =
          e.clientX -
          (windowWidth - canvas.width) / 2 -
          player.x -
          player.width / 2;
        diffX = newX - oldX;
        if (diffX > 0 && player.x <= canvas.width - player.width)
          player.x += player.speed;
        else if (diffX < 0 && player.x > 0) player.x -= player.speed;
        newX = oldX;
      } else {
        oldX = 0;
        newX = e.clientX - player.x;
        // console.log("e client X", e.clientX);
        // console.log("player X", player.x);
        // console.log("window width", windowWidth);
        // console.log("ok");
        diffX = newX - oldX;
        if (diffX >= 0 && player.x <= windowWidth) player.x += player.speed;
        else if (diffX < 0 && player.x > 0) player.x -= player.speed;
        newX = oldX;
      }
    }
    canvas.addEventListener("touchstart", handleTouchEvent, true);
    canvas.addEventListener("touchmove", handleTouchEvent, true);
    canvas.addEventListener("touchend", handleTouchEvent, true);
    canvas.addEventListener("touchcancel", handleTouchEvent, true);
    // canvas.addEventListener("click", mouseMoveCheck);
    let oldX2;
    let newX2;
    let diffX2;
    function handleTouchEvent(e) {
      if (e.touches.length === 0) return;
      // e.preventDefault();
      // e.stopPropagation();
      var touch = e.touches[0];

      if (windowWidth > canvas.width) {
        // console.log("touch page x", touch.pageX);
        // console.log("oksss");
        oldX2 = 0;
        newX2 =
          touch.pageX -
          (windowWidth - canvas.width) / 2 -
          player.x -
          player.width / 2;
        diffX2 = newX2 - oldX2;
        if (diffX2 > 0 && player.x <= canvas.width - player.width)
          player.x += player.speed;
        else if (diffX2 < 0 && player.x > 0) player.x -= player.speed;
        newX2 = oldX2;
      } else {
        oldX2 = 0;
        newX2 = touch.pageX - player.x;
        diffX2 = newX2 - oldX2;
        if (diffX2 >= 0 && player.x <= windowWidth) player.x += player.speed;
        else if (diffX2 < 0 && player.x > 0) player.x -= player.speed;
        newX2 = oldX2;
      }
    }

    // function mouseMoveCheck(e) {
    //   console.log("client X", e.clientX);
    //   console.log("player X", player.x);
    //   var newX =
    //     e.clientX - (windowWidth - width) / 2 - player.x - player.width / 2;
    //   console.log("new X", newX);
    // }

    let img = new Image();
    img.src = player.image;

    ctx.drawImage(img, player.x, player.y, player.width, player.height);

    enemies.arr.forEach((enemy, index) => {
      enemy.y += enemy.speed;
      if (
        enemy.y > canvas.height * 0.85 &&
        enemy.image != "./assets/img/02/elementy/nano.png"
      ) {
        setTimeout(() => {
          enemies.arr.splice(index, 1);
        }, 0);

        player.lives--;
        if (player.lives == 0) {
          gameOver();
          player.lives = "-";
        }
      } else if (enemy.y > canvas.height * 0.85) {
        setTimeout(() => {
          enemies.arr.splice(index, 1);
        }, 0);
      }

      ctx.beginPath();

      if (game.play) {
        var imgEnemy = new Image();
        imgEnemy.src = enemy.image;
        if (enemy.image == "./assets/img/02/elementy/burger.png") {
          enemy.width = (canvas.height / 12) * 1.52;
          enemy.height = canvas.height / 12;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/frytki.png") {
          enemy.width = (canvas.height / 10) * 0.72;
          enemy.height = canvas.height / 10;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/hotdog.png") {
          enemy.width = canvas.height / 20;
          enemy.height = (canvas.height / 20) * 3.22;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/kawa.png") {
          enemy.width = canvas.height / 20;
          enemy.height = (canvas.height / 20) * 1.58;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/nano.png") {
          enemy.width = canvas.height / 20;
          enemy.height = (canvas.height / 20) * 1.69;
          enemy.bad = true;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/sok.png") {
          enemy.width = canvas.height / 20;
          enemy.height = (canvas.height / 20) * 2.55;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/tortilla.png") {
          enemy.width = canvas.height / 20;
          enemy.height = (canvas.height / 20) * 3.06;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/zapiekanka.png") {
          enemy.width = (canvas.height / 20) * 3.13;
          enemy.height = canvas.height / 20;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        }
      }

      if (col(player, enemy)) {
        setTimeout(() => {
          var removed;
          removed = enemies.arr.splice(index, 1)[0];
          if (removed.bad) {
            player.score -= 10;
          } else if (enemy.image == "./assets/img/02/elementy/burger.png") {
            burger++;
            player.score += 20;
          } else if (enemy.image == "./assets/img/02/elementy/frytki.png") {
            frytka++;
            player.score += 10;
          } else if (enemy.image == "./assets/img/02/elementy/hotdog.png") {
            hotdog++;
            player.score += 15;
          } else if (enemy.image == "./assets/img/02/elementy/kawa.png") {
            kawa++;
            player.score += 15;
          } else if (enemy.image == "./assets/img/02/elementy/sok.png") {
            sok++;
            player.score += 5;
          } else if (enemy.image == "./assets/img/02/elementy/tortilla.png") {
            player.score += 20;
          } else if (enemy.image == "./assets/img/02/elementy/zapiekanka.png") {
            zapiekanka++;
            player.score += 10;
          }
          gameScore.innerHTML = `Punkty: ${player.score}`;
          score = player.score;
        }, 0);
        //console.log(removed);
      }
    });

    if (game.play) {
      if (player.lives == 2) {
        gameLives.innerHTML = `Życia: <img src="/assets/img/02/elementy/zycie.png"></img><img src="/assets/img/02/elementy/zycie.png"></img>`;
      } else if (player.lives == 1) {
        gameLives.innerHTML = `Życia: <img src="/assets/img/02/elementy/zycie.png"></img>`;
      } else if (player.lives == 0) {
        gameLives.innerHTML = `Życia: -`;
      }
      ctx.beginPath();
      game.req = requestAnimationFrame(draw);
    }
  }
  gameStart();
}
1

Polecam rozbić to na jakieś klasy, bo dla mnie jest nieczytelne xd

3

Wiesz, że dodajesz w każdej klatce nowe handlery zdarzeń?

function draw() {
// ... 
canvas.addEventListener("mousemove", mouseMoveHandler);
// ...
canvas.addEventListener("touchstart", handleTouchEvent, true);
canvas.addEventListener("touchmove", handleTouchEvent, true);
canvas.addEventListener("touchend", handleTouchEvent, true);
canvas.addEventListener("touchcancel", handleTouchEvent, true);

Czyli w najlepszym wypadku sam się pozbawiasz wydajności tworząc ciągle to nowe handlery (powinieneś to umieścić poza funkcją draw, przy inicjalizacji).

Jednak też nie zdziwiłbym się, gdyby coś w tych handlerach się działo, że powoduje ci to miganie - jeśli ileś handlerów naraz się odpali, to mogą wystąpić jakieś anomalie. Ale to trzeba by zbadać bardziej szczegółowo. Bo może tam jest problem, może gdzie indziej. Ale zacząłbym od zrobienia porządku z handlerami, żeby mieć pewność.

Poza tym:

masz duplikacje w ifach:

  if (enemy.image == "./assets/img/02/elementy/burger.png") {
          enemy.width = (canvas.height / 12) * 1.52;
          enemy.height = canvas.height / 12;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/frytki.png") {
          enemy.width = (canvas.height / 10) * 0.72;
          enemy.height = canvas.height / 10;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/hotdog.png") {
          enemy.width = canvas.height / 20;
          enemy.height = (canvas.height / 20) * 3.22;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/kawa.png") {
        // ...

w każdej gałęzi jest ta sama linijka na końcu:

 ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);

więc to już można po prostu wywalić poza ify:

 if (enemy.image == "./assets/img/02/elementy/burger.png") {
          enemy.width = (canvas.height / 12) * 1.52;
          enemy.height = canvas.height / 12;
        } else if (enemy.image == "./assets/img/02/elementy/frytki.png") {
          enemy.width = (canvas.height / 10) * 0.72;
          enemy.height = canvas.height / 10;
        } else if (enemy.image == "./assets/img/02/elementy/hotdog.png") {
          enemy.width = canvas.height / 20;
          enemy.height = (canvas.height / 20) * 3.22;
        } else if (enemy.image == "./assets/img/02/elementy/kawa.png") {
        // ...

ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);

no i w tych ifach masz jeszcze ustawianie rozmiarów do każdego obrazka:

enemy.width = (canvas.height / 12) * 1.52;
enemy.height = canvas.height / 12;

to też można inaczej rozwiązać. Jeżeli każdy obrazek potrzebujesz mieć w innych rozmiarach, to czemu nie zrobisz sobie takiego obiektu trzymającego te rozmiary:

const sizes = {
   './assets/img/02/elementy/burger.png': { width: 1 / 12 * 1.52, height: 1 / 12 },
   "./assets/img/02/elementy/frytki.png": { width: 1 / 10 * 0.72, height: 1 / 10 }, 
   // ...
}

a później możesz sobie pobierać te wielkości (i mnożyć przez canvas.width i canvas.height)

podobnie w innym miejscu sprawdzasz obrazek i na podstawie tego obrazka dajesz odpowiednią liczbę punktów:

 } else if (enemy.image == "./assets/img/02/elementy/frytki.png") {
            frytka++;
            player.score += 10;

Tutaj tak:

  1. zmienne frytka i inne są niezadeklarowane, więc przemyśl co chcesz zrobić (chyba chciałeś dać player.frytki++? Tutaj też spójrz uważnie, bo to też może być potencjalna przyczyna, dla którego ci coś miga, skoro robisz jakieś dziwne rzeczy)

  2. samo to, że sprawdzasz warunek przez enemy.image jest słabe, bo uzależniasz logikę od grafiki (co jeśli zmienisz plik graficzny, albo jeśli jeden plik graficzny użyjesz w dwóch różnych typach obiektów?). Jeśli enemy ma mieć jakiś rodzaj/typ, to możesz np. dodać mu właściwość type i sprawdzać tak:

 } else if (enemy.type == "frytki") {
       player.frytki++;
       player.score += 10;

ale znowu, zamiast ciągu ifów, to możesz zrobić sobie jakiś obiekt:

{
   frytki: {
       scoreDelta: 10,
   },
   // ...
}

albo w jakiś inny sposób to trzymać jako dane.

Czyli ogólnie za dużo ifów robisz i próbujesz zapisać "na pałę" logikę, zamiast pomyśleć bardziej z lotu ptaka i myśleć w kategoriach parametrów, właściwości, relacji (które możesz zapisywać w różny sposób, jednym ze sposobów to umieszczanie tego w obiektach JS tak jak w moich przykładach).

var imgEnemy = new Image();
imgEnemy.src = enemy.image;

wiesz, że nie musisz tworzyć za każdym razem nowego obrazka? Możesz raz sobie utworzyć ileś obiektów Image, a potem je sobie zapisać np.

// ...
enemy.cachedImage = new Image(); 
// ...

Być może przez to jest to miganie - bo jak tworzysz nowe obrazki, to być może nie wczytują się od razu, więc teoretycznie mogłoby to spowodować miganie (chociaż przeglądarka prawdopodobnie i tak pobierze je z cache'a za drugim razem. To trzeba by sprawdzić).

Owinąłem wszystkie splice'y w setTimeout 0 i problem występuje teraz rzadziej ale nadal się objawia.

Zależy, co chcesz osiągnąć. Jak zrobisz w setTimeout 0, to usunie się dopiero po wyjściu z renderowania klatki.

Jeśli chcesz usunąć go natychmiast, to po prostu zamiast iterować do przodu, powinieneś iterować do tyłu. Ale forEach tego nie obsługuje, więc można zrobić to pętlą for:

for (let i = enemies.arr.length - 1; i >= 0; i--) {

}

wtedy nawet jak coś usuniesz, to nie spowoduje to konfliktu.

0
LukeJL napisał(a):

Wiesz, że dodajesz w każdej klatce nowe handlery zdarzeń?

function draw() {
// ... 
canvas.addEventListener("mousemove", mouseMoveHandler);
// ...
canvas.addEventListener("touchstart", handleTouchEvent, true);
canvas.addEventListener("touchmove", handleTouchEvent, true);
canvas.addEventListener("touchend", handleTouchEvent, true);
canvas.addEventListener("touchcancel", handleTouchEvent, true);

Czyli w najlepszym wypadku sam się pozbawiasz wydajności tworząc ciągle to nowe handlery (powinieneś to umieścić poza funkcją draw, przy inicjalizacji).

Jednak też nie zdziwiłbym się, gdyby coś w tych handlerach się działo, że powoduje ci to miganie - jeśli ileś handlerów naraz się odpali, to mogą wystąpić jakieś anomalie. Ale to trzeba by zbadać bardziej szczegółowo. Bo może tam jest problem, może gdzie indziej. Ale zacząłbym od zrobienia porządku z handlerami, żeby mieć pewność.

Poza tym:

masz duplikacje w ifach:

  if (enemy.image == "./assets/img/02/elementy/burger.png") {
          enemy.width = (canvas.height / 12) * 1.52;
          enemy.height = canvas.height / 12;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/frytki.png") {
          enemy.width = (canvas.height / 10) * 0.72;
          enemy.height = canvas.height / 10;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/hotdog.png") {
          enemy.width = canvas.height / 20;
          enemy.height = (canvas.height / 20) * 3.22;
          ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);
        } else if (enemy.image == "./assets/img/02/elementy/kawa.png") {
        // ...

w każdej gałęzi jest ta sama linijka na końcu:

 ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);

więc to już można po prostu wywalić poza ify:

 if (enemy.image == "./assets/img/02/elementy/burger.png") {
          enemy.width = (canvas.height / 12) * 1.52;
          enemy.height = canvas.height / 12;
        } else if (enemy.image == "./assets/img/02/elementy/frytki.png") {
          enemy.width = (canvas.height / 10) * 0.72;
          enemy.height = canvas.height / 10;
        } else if (enemy.image == "./assets/img/02/elementy/hotdog.png") {
          enemy.width = canvas.height / 20;
          enemy.height = (canvas.height / 20) * 3.22;
        } else if (enemy.image == "./assets/img/02/elementy/kawa.png") {
        // ...

ctx.drawImage(imgEnemy, enemy.x, enemy.y, enemy.width, enemy.height);

no i w tych ifach masz jeszcze ustawianie rozmiarów do każdego obrazka:

enemy.width = (canvas.height / 12) * 1.52;
enemy.height = canvas.height / 12;

to też można inaczej rozwiązać. Jeżeli każdy obrazek potrzebujesz mieć w innych rozmiarach, to czemu nie zrobisz sobie takiego obiektu trzymającego te rozmiary:

const sizes = {
   './assets/img/02/elementy/burger.png': { width: 1 / 12 * 1.52, height: 1 / 12 },
   "./assets/img/02/elementy/frytki.png": { width: 1 / 10 * 0.72, height: 1 / 10 }, 
   // ...
}

a później możesz sobie pobierać te wielkości (i mnożyć przez canvas.width i canvas.height)

podobnie w innym miejscu sprawdzasz obrazek i na podstawie tego obrazka dajesz odpowiednią liczbę punktów:

 } else if (enemy.image == "./assets/img/02/elementy/frytki.png") {
            frytka++;
            player.score += 10;

Tutaj tak:

  1. zmienne frytka i inne są niezadeklarowane, więc przemyśl co chcesz zrobić (chyba chciałeś dać player.frytki++? Tutaj też spójrz uważnie, bo to też może być potencjalna przyczyna, dla którego ci coś miga, skoro robisz jakieś dziwne rzeczy)

  2. samo to, że sprawdzasz warunek przez enemy.image jest słabe, bo uzależniasz logikę od grafiki (co jeśli zmienisz plik graficzny, albo jeśli jeden plik graficzny użyjesz w dwóch różnych typach obiektów?). Jeśli enemy ma mieć jakiś rodzaj/typ, to możesz np. dodać mu właściwość type i sprawdzać tak:

 } else if (enemy.type == "frytki") {
       player.frytki++;
       player.score += 10;

ale znowu, zamiast ciągu ifów, to możesz zrobić sobie jakiś obiekt:

{
   frytki: {
       scoreDelta: 10,
   },
   // ...
}

albo w jakiś inny sposób to trzymać jako dane.

Czyli ogólnie za dużo ifów robisz i próbujesz zapisać "na pałę" logikę, zamiast pomyśleć bardziej z lotu ptaka i myśleć w kategoriach parametrów, właściwości, relacji (które możesz zapisywać w różny sposób, jednym ze sposobów to umieszczanie tego w obiektach JS tak jak w moich przykładach).

var imgEnemy = new Image();
imgEnemy.src = enemy.image;

wiesz, że nie musisz tworzyć za każdym razem nowego obrazka? Możesz raz sobie utworzyć ileś obiektów Image, a potem je sobie zapisać np.

// ...
enemy.cachedImage = new Image(); 
// ...

Być może przez to jest to miganie - bo jak tworzysz nowe obrazki, to być może nie wczytują się od razu, więc teoretycznie mogłoby to spowodować miganie (chociaż przeglądarka prawdopodobnie i tak pobierze je z cache'a za drugim razem. To trzeba by sprawdzić).

Owinąłem wszystkie splice'y w setTimeout 0 i problem występuje teraz rzadziej ale nadal się objawia.

Zależy, co chcesz osiągnąć. Jak zrobisz w setTimeout 0, to usunie się dopiero po wyjściu z renderowania klatki.

Jeśli chcesz usunąć go natychmiast, to po prostu zamiast iterować do przodu, powinieneś iterować do tyłu. Ale forEach tego nie obsługuje, więc można zrobić to pętlą for:

for (let i = enemies.arr.length - 1; i >= 0; i--) {

}

wtedy nawet jak coś usuniesz, to nie spowoduje to konfliktu.

siemka, jeszcze raz dzięki za pomoc. Problem z migającymi przedmiotami wynikał z nie cache'owania image'y. Mam za to problem z wyciągnięciem handlerów poza klatkowanie z funkcji draw ponieważ handlery przestają wtedy płynnie działać i player porusza się powolutku za myszką a musi płynnie. Zwiększenie player speed pomaga natomiast wtedy koszyk przeskakuje np o 20 pikseli i wciąż nie jest idealnie płynnie. Za to nie mogę zostawić handlerów w draw ponieważ siada performance apki :( @LukeJL jakieś pomysły?

0
Mietekk napisał(a):

siemka, jeszcze raz dzięki za pomoc. Problem z migającymi przedmiotami wynikał z nie cache'owania image'y. Mam za to problem z wyciągnięciem handlerów poza klatkowanie z funkcji draw ponieważ handlery przestają wtedy płynnie działać i player porusza się powolutku za myszką a musi płynnie. Zwiększenie player speed pomaga natomiast wtedy koszyk przeskakuje np o 20 pikseli i wciąż nie jest idealnie płynnie. Za to nie mogę zostawić handlerów w draw ponieważ siada performance apki :( @LukeJL jakieś pomysły?

A jak je wyciągnąłeś?
Tam widzę, że handlery operują na zmiennych z zewnątrz funkcji np.:

 let oldX;
 let newX;
 let diffX;
 function mouseMoveHandler(e) {
    // ...
    if (diffX > 0 && player.x <= canvas.width - player.width)

czy wyciągając funkcję, wyciągasz też te zmienne? W ogóle pokaż kod, jaki obecnie masz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1