Как вы предотвращаете сбои при попытке рендеринга чего-либо на холсте?

#javascript #html #css #html5-canvas

#javascript #HTML #css #html5-холст

Вопрос:

Итак, я пытаюсь заставить персонажа перемещаться по экрану с помощью клавиш со стрелками, и пока он работает, он оставляет полосы. Я не хочу, чтобы полосы выходили из моего серверной части. Я знаю, почему он создает эти полосы, но не знаю, как от них избавиться. Причиной полос является то, что проигрыватель удаляется с холста, затем с БОЛЬШОЙ задержкой он рендерится. Как мне это остановить?

Редактировать: я хочу, чтобы он очищал ТОЛЬКО проигрыватель, и ничего вокруг него.

Фрагмент:

 const c = document.getElementById('c')
const ctx = c.getContext('2d')

c.height = window.innerHeight
c.width = window.innerWidth

let blockInfo = {
    h: 15, // Height in pixels. I'm gonna use this like blocks, like this: blockAmount * blockInfo.h
    w: 15
}

let renderedPlayer = false // The player wasn't rendered yet so this is false

let player = {
    speed: 0.125,
    x: 2,
    y: 2,
    height: 1,
    width: 1
}

function clearPlayer() { // I think this is where the glitch comes in.
    ctx.clearRect(player.x * blockInfo.w, player.y * blockInfo.h, player.width * blockInfo.w, player.height * blockInfo.h)
}

function renderPlayer() {
    ctx.fillRect(player.x * blockInfo.w, player.y * blockInfo.h, player.width * blockInfo.w, player.height * blockInfo.h)
}

function press(e) { // When a character on the keyboard gets pressed:
    let w = e.which
    
    if (renderedPlayer == true) {
        clearPlayer() // It clears the player before the player moves, so it doesn't have more streaks.
        
        if (w == 39) {
            player.x  = player.speed
        } else if (w == 37) {
            player.x -= player.speed
        } else if (w == 38) {
            player.y -= player.speed
        } else if (w == 40) {
            player.y  = player.speed
        }
    }
}

setInterval(function() { // Rendering player each MS.
    renderedPlayer = false
    renderPlayer()
    renderedPlayer = true
}, 0) 
 body {
    margin: 0;
    overflow: hidden;
} 
 <!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>repl.it</title>
    <link href="style.css" rel="stylesheet" type="text/css" />
  </head>
  <body onkeydown="press(event)">
    <canvas id="c"></canvas>

    <script src="script.js"></script>
  </body>
</html> 

Комментарии:

1.Очищайте весь холст в начале каждого кадра. Становится очень сложно очистить только движущийся объект, когда их становится много. ctx.clearRect(0,0,ctx.canvas.width,ctx.canvas.height) очень, очень быстро. Также используйте requestAnimartionFrame developer.mozilla.org/en-US/docs/Web/API/window / … вместо того, чтобы идти по утечке памяти, которая setInterval

2. Это помогло бы, но вы могли бы сказать это как ответ, а не комментарий. Но все же, спасибо за обучение.

Ответ №1:

Я бы просто очистил весь холст перед рисованием, вот так:

 const c = document.getElementById('c')
const ctx = c.getContext('2d')
c.height = c.width = 180

let blockInfo = {h: 15,  w: 15}
let player = {speed: 0.1, x: 2, y: 2, height: 1, width: 1}

function render() {
  ctx.clearRect(0, 0, c.width, c.height)
  
  //renderOtherStuff
  ctx.fillStyle = "#FF0000";
  ctx.arc(75, 75, 60, 0, Math.PI * 2, true);  
  ctx.fill();

  //renderPlayer
  ctx.fillStyle = "#000000";
  ctx.fillRect(player.x * blockInfo.w, player.y * blockInfo.h, player.width * blockInfo.w, player.height * blockInfo.h)
}

function press(e) { // When a character on the keyboard gets pressed:
  let w = e.which
  if (w == 39) {
    player.x  = player.speed
  } else if (w == 37) {
    player.x -= player.speed
  } else if (w == 38) {
    player.y -= player.speed
  } else if (w == 40) {
    player.y  = player.speed
  }
}

setInterval(render, 25) 
 <body onkeydown="press(event)">
  <canvas id="c"></canvas>
</body> 

Очистка только проигрывателя создает другие проблемы, поскольку вы вводите другие объекты, которые могут перекрываться, когда вы очищаете проигрыватель, вы также очищаете фон, который может содержать что-то еще.

… Кроме того, это похоже на начало простой игры, если вы серьезно относитесь к этому, загляните в подходящий игровой движок, там куча игр с открытым исходным кодом:
https://github.com/collections/javascript-game-engines

Комментарии:

1. Извините, но я упоминал, что не хотел, чтобы он очищал что-либо, кроме проигрывателя. Я хочу, чтобы он очищал проигрыватель только потому, что, если я добавлю другую вещь в холст, она также будет очищена. Вы можете отредактировать этот ответ, если у вас есть решение для этого.

2. @UnknownBobby это же решение применяется, когда вы рисуете несколько объектов, вы должны очистить весь холст и нарисовать все снова

3. @UnknownBobby Я отредактировал свой ответ, чтобы показать, как он выглядит с другой вещью на холсте… но когда у вас будет время, изучите подходящий игровой движок, который избавит вас от многих головных болей позже

4. Да, но я не люблю копировать. Это заставляет меня чувствовать.. Я не знаю.

5. Что значит, вам не нравится копировать? Как вы думаете, вы можете создать лучший игровой движок самостоятельно? и используя игровой движок, который вы не будете копировать, вы будете использовать хороший набор инструментов для создания своей игры. _ _ _ подумайте, можете ли вы, как плотник, использовать ручную пилу для сборки чего-либо или профессиональный стол для электропилы, который каждый раз будет выполнять быстрые и точные разрезы