Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Atraso no início do movimento do Ator

Olá pessoal!

Eu fiz o meu código bem diferente dos vídeos, inclusive para treinar fiz antes de ver os vídeos.

Mas tanto no projeto do pong como nesse projeto, percebo que antes de começar o movimento do ator, ele move 1px, para e depois volta a movimentar. Pq isso acontece:

Eu fiz o jogo com a Galinha e não com a vaquinha

addEventListener('keydown', (e) => {
  let key = e.key

  switch (key) {
    case 'ArrowUp':
      galinha1.y -= galinha1.velocity
      galinha1.animation()
      if (galinha1.y <= 10) {
        galinha1.y = 650
        galinha1.pontos++
      }
      break
    case 'ArrowDown':
      if (galinha1.y + galinha1.image.height < canvas.height - 10) {
        galinha1.y += galinha1.velocity
        galinha1.animation()
      }
      break
    case 'w':
      galinha2.y -= galinha1.velocity
      galinha2.animation()
      if (galinha2.y <= 10) {
        galinha2.y = 650
        galinha2.pontos++
      }
      break
    case 's':
      if (galinha2.y + galinha2.image.height < canvas.height - 10) {
        galinha2.y += galinha1.velocity
        galinha2.animation()
      }
      break
  }
})
7 respostas
solução!

Esse comportamento é causado porque o evento keydown é gerado toda vez que uma tecla é pressionada, então a cada pressionamento da tecla a posição da galinha é atualizada e ela é desenhada na tela. Quando a tecla é solta, o evento keyup é gerado e o movimento da galinha para.

Para evitar esse comportamento, uma solução seria adicionar uma flag para indicar se a tecla está pressionada ou não. Dessa forma, a posição da galinha só seria atualizada enquanto a tecla estiver pressionada. Algo como:

let teclaPressionada = false;

addEventListener('keydown', (e) => {
  teclaPressionada = true;
});

addEventListener('keyup', (e) => {
  teclaPressionada = false;
});

// no seu loop de animação:
if (teclaPressionada) {
  // atualiza posição da galinha e desenha na tela
}

Opa Grande Diogo!

Demorei um pouco para responder pq estava tentando implementar! O meu arquivo principal js estava ficando muito grande e difícil de ler, aí separei tudo!

Como eu disse não estou fazendo pelo P5, minha vontade é aprender o javaScript, aí pelo P5, além do JS eu tinha de ficar olando a documentação do P5 tb.

Segue meus códigos para vc dar uma avaliada.

class Galinha {
  constructor(x, y, image) {
    this.x = x
    this.y = y
    this.image = image
    this.velocity = 5
    this.dirY = 0
    this.pontos = 0
    this.movimentos = [
      getImage('./assets/sprites/galinha_1.png'),
      getImage('./assets/sprites/galinha_2.png'),
      getImage('./assets/sprites/galinha_3.png')
    ]
    this.frameAtual = 0
    this.life = 3
  }
  draw() {
    this.atualizarFrameAtual()
    const sprite = this.movimentos[this.frameAtual]
    ctx.drawImage(this.image, this.x, this.y, 30, 30)
  }
  update() {
    this.movimento()
    this.pontuacao()
  }
  movimento() {
    this.y += this.velocity * this.dirY
  }
  colisao(item) {
    if (
      this.x + this.image.width > item.x &&
      this.x < item.x + item.image.width
    ) {
      if (
        this.y < item.y + item.image.height &&
        this.y + this.image.height > item.y
      ) {
        this.y += 50
        this.life--
      }
    }
  }
  atualizarFrameAtual() {
    const intervaloDeFrames = 10
    const passouIntervalo = frames % intervaloDeFrames === 0
    if (passouIntervalo) {
      const baseIncremento = 1
      const incremento = baseIncremento + this.frameAtual
      const baseRepeticao = this.movimentos.length
      this.frameAtual = incremento % baseRepeticao
    }
  }

  animation() {
    this.atualizarFrameAtual()
    this.image = this.movimentos[this.frameAtual]
  }
  drawScore(x) {
    ctx.fillStyle = 'yellow'
    ctx.font = '25px "Press Start 2P"'
    ctx.fillText(`${this.pontos}`, `${x}`, 35)
  }
  pontuacao() {
    if (this.y <= 30) {
      this.pontos++
      this.y = 650
    }
  }
}

arquivo keys.js

const keys = {
  up: {
    g1: {
      pressed: false
    },
    g2: {
      pressed: false
    }
  },
  down: {
    g1: {
      pressed: false
    },
    g2: {
      pressed: false
    }
  }
}

addEventListener('keydown', ({ keyCode }) => {
  switch (keyCode) {
    case 38:
      keys.up.g1.pressed = true
      break
    case 40:
      keys.down.g1.pressed = true
      break
    case 87:
      keys.up.g2.pressed = true
      break
    case 83:
      keys.down.g2.pressed = true
      break
  }
})

addEventListener('keyup', ({ keyCode }) => {
  switch (keyCode) {
    case 38:
      keys.up.g1.pressed = false
      break
    case 40:
      keys.down.g1.pressed = false
      break
    case 87:
      keys.up.g2.pressed = false
      break
    case 83:
      keys.down.g2.pressed = false
      break
  }
})
class Carros {
  constructor(x, y, velocity, image) {
    this.x = x
    this.y = y
    this.velocity = velocity
    this.image = image
  }
  draw() {
    ctx.drawImage(this.image, this.x, this.y)
  }
  update() {
    if (this.x <= -this.image.width) {
      this.x = canvas.width
    } else {
      this.x -= this.velocity
    }
  }
}

arquivo main.js

const canvas = document.querySelector('canvas')
const ctx = canvas.getContext('2d')

canvas.width = 1024
canvas.height = 690
let y = 10
let frames = 0
let timeLimit = 90
let textTime = ''
const carros = []
const imagesCarros = [
  './assets/sprites/carro_verde.png',
  './assets/sprites/carro_vermelho.png',
  './assets/sprites/carro_roxo.png',
  './assets/sprites/carro_laranja.png',
  './assets/sprites/carro_amarelo.png',
  './assets/sprites/carro_azul.png',
  './assets/sprites/carro_oliva.png',
  './assets/sprites/carro_rosa.png',
  './assets/sprites/carro_telha.png'
]

function getImage(src) {
  img = new Image()
  img.src = src
  return img
}

const board = {
  image: getImage('./assets/sprites/pista.png'),
  draw() {
    //linha 1
    ctx.drawImage(this.image, 0, 0)
  }
}

function drawTimer() {
  let textMetricos = ctx.measureText(textTime)
  ctx.fillStyle = 'yellow'
  ctx.font = '20px "Press Start 2P"'
  ctx.fillText(textTime, `${canvas.width / 2 - textMetricos.width / 2}`, 35)
}

//Agentes do game
const galinha1 = new Galinha(
  canvas.width * 0.25,
  canvas.height - 35,
  getImage('./assets/sprites/galinha_1.png')
)

function movimento(galinha, key) {
  if (galinha === galinha1) {
    if (key.up.g1.pressed) {
      galinha1.dirY = -1
      galinha.animation()
    } else if (key.down.g1.pressed) {
      galinha1.dirY = 1
      galinha.animation()
    } else {
      galinha.dirY = 0
    }
  } else if (galinha === galinha2) {
    if (key.up.g2.pressed) {
      galinha2.dirY = -1
    } else if (key.down.g2.pressed) {
      galinha2.dirY = 1
    } else {
      galinha.dirY = 0
    }
  }
}

const galinha2 = new Galinha(
  canvas.width * 0.75,
  canvas.height - 35,
  getImage('./assets/sprites/galinha_1.png')
)

const carroVerde = new Carros(canvas.width, 48, 5, getImage(imagesCarros[0]))
const carroVermelho = new Carros(
  canvas.width,
  105,
  10,
  getImage(imagesCarros[1])
)
const carroRoxo = new Carros(canvas.width, 166, 8, getImage(imagesCarros[2]))

const carroLaranja = new Carros(canvas.width, 227, 3, getImage(imagesCarros[3]))
carros.push(carroVerde)
carros.push(carroVermelho)
carros.push(carroRoxo)
carros.push(carroLaranja)

function game() {
  ctx.fillStyle = '#ABABAB'
  ctx.fillRect(0, 0, canvas.width, canvas.height)
  board.draw()
  drawTimer()
  galinha1.draw()
  galinha2.draw()
  galinha1.drawScore(canvas.width * 0.25)
  galinha2.drawScore(canvas.width * 0.75)
  galinha1.update()
  galinha2.update()
  movimento(galinha1, keys)
  movimento(galinha2, keys)
  carros.forEach((carro) => {
    carro.update()
    carro.draw()
    galinha1.colisao(carro)
    galinha2.colisao(carro)
  })
  frames++

  requestAnimationFrame(game)
}

game()

let min = Math.floor(timeLimit / 60)
let sec = timeLimit % 60

function cronometro() {
  if (timeLimit > 0) {
    timeLimit--
    textTime = ''

    min = Math.floor(timeLimit / 60)
    sec = timeLimit % 60

    if (min < 10) {
      textTime += `0${min}`
    } else {
      textTime += `${min}`
    }
    if (sec < 10) {
      textTime += `:0${sec}`
    } else {
      textTime += `:${sec}`
    }
  } else {
    textTime = '00:00'
  }
}

setInterval(cronometro, 1000)

observação:

No meu exemplo eu coloquei para jogar de 2 pessoas!

Agora vou tentar implementar para o jogador escolher 1 ou 2 pessoas

assim como era no atari.

e vou tentar implementar os Levels.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software