Criando obstáculo do jogo com javascript e P5.play
No p5.js, o framecount (ou frameCount
em código) é uma variável interna que conta o número de quadros (frames) que foram renderizados desde o início da execução do programa. Ele é útil para controlar ou sincronizar eventos ao longo do tempo em uma animação ou simulação.
Características do frameCount
No p5.js, o framecount (ou frameCount
em código) é uma variável interna que conta o número de quadros (frames) que foram renderizados desde o início da execução do programa. Ele é útil para controlar ou sincronizar eventos ao longo do tempo em uma animação ou simulação.
Incremento automático: O
frameCount
é incrementado automaticamente pelo p5.js a cada quadro renderizado.Começa em 0: Quando o programa inicia, o
frameCount
começa em 0 e aumenta em 1 a cada quadro.Taxa de quadros (frame rate): O valor do
frameCount
depende da taxa de quadros (frames por segundo, ou FPS) definida no programa. Por padrão, o p5.js tenta rodar a 60 FPS.
Explicando o jogo
Aqui está o jogo que usaremos como referência:
Passo 1: Configurando o ambiente
Antes de começarmos a programar, certifique-se de ter um ambiente de desenvolvimento configurado:
Um editor de código (VS Code)
- Um navegador (Google Chrome)
Arquivo de template
Passo 2: Declaração de variáveis
Aqui, estamos declarando as variáveis que serão usadas para armazenar os sprites e suas imagens.
// Personagem principal
var boy;
// Grupos de obstáculos e colecionáveis
var cashG, diamondsG, jwelleryG, swordGroup;
// Elementos do cenário
var path;
// Sistema de pontuação e estados
var treasureCollection = 0;
var gameState = "PLAY";
// Imagens do jogo
var pathImg, cashImg, diamondsImg, jwelleryImg, swordImg;
// Animação do personagem
var boyImg;
// Animação de fim de jogo
var endImg;
Passo 3: Função preload()
A função preload() é usada para carregar imagens e animações antes do jogo iniciar.
loadImage("Road.png")
: Carrega a imagem da pista para ser usada como plano de fundoloadAnimation("Runner-1.png","Runner-2.png")
: Cria uma animação para o personagem usando uma sequência de imagensloadImage("cash.png")
: Carrega a imagem do item de dinheiro colecionávelloadImage("diamonds.png")
: Carrega a imagem do item de diamante colecionávelloadImage("jwell.png")
: Carrega a imagem do item de joia colecionávelloadImage("sword.png")
: Carrega a imagem do obstáculo espadaloadAnimation("fimdeJogo.png")
: Cria animação para a tela de fim de jogo
function preload(){
cashImg = loadImage("cash.png");
diamondsImg = loadImage("diamonds.png");
jwelleryImg = loadImage("jwell.png");
swordImg = loadImage("sword.png");
endImg = loadAnimation("fimdeJogo.png");
}
Passo 4: Função setup()
A função setup()
é executada apenas uma vez e configura o ambiente do jogo.
createCanvas(400,600)
: Cria um canvas de 400×600 pixels.
function setup(){
createCanvas(400,600);
Agora criamos o sprite do fundo da pista:
// Criando o fundo da pista
path = createSprite(200,200);
path.addImage(pathImg);
path.velocityY = 4;
path.scale = 1.2;
createSprite(200,200)
: Cria um sprite posicionado no centro da tela.addImage(pathImg)
: Adiciona a imagem da pista ao sprite.velocityY = 4
: Faz com que a pista se mova para baixo.scale = 1.2
: Ajusta o tamanho da imagem.
Agora criamos o sprite do corredor:
// Criando o personagem principal
boy = createSprite(180,340,30,30);
boy.scale = 0.08;
boy.addAnimation("JakeRunning", boyImg);
createSprite(180,340,30,30)
: Cria o sprite do personagem na posição inicial.addAnimation("JakeRunning", boyImg)
: Adiciona a animação ao sprite.scale = 0.08
: Reduz o tamanho do sprite.
Criamos também os sprites das bordas:
leftBoundary = createSprite(0,0,100,800);
leftBoundary.visible = false;
rightBoundary = createSprite(410,0,100,800);
rightBoundary.visible = false;
createSprite(0,0,100,800)
: Cria um sprite para a borda esquerda.createSprite(410,0,100,800)
: Cria um sprite para a borda direita.visible = false
: Torna os sprites invisíveis para que não sejam vistos na tela, mas ainda funcionem como barreiras.
E criamos também os grupos dos sprites:
// Inicializa grupos
cashG = new Group();
diamondsG = new Group();
jwelleryG = new Group();
swordGroup = new Group();
}
cashG = new Group():
cria o grupo das notas de dinheiro.diamondsG = new Group():
cria o grupo dos diamantes.jwelleryG = new Group():
cria o grupo das joias.swordGroup = new Group():
cria o grupo das espadas.
Passo 5: Função draw()
A função draw() é chamada continuamente para atualizar a tela do jogo e manter a animação fluida.
background(0)
: Define o fundo como preto.
function draw() {
background(0);
Agora, precisamos garantir que o ao iniciar o jogo, quando o estado de jogo for “PLAY”, a função PLAY() seja chamada:
if(gameState === "PLAY"){
PLAY();
}
gameState === "PLAY"
: Executa a lógica principal do jogo
Quando o jogador perder, o estado de jogo será “END”, a função END() será chamada:
if(gameState === "END"){
END();
}
gameState === "END"
: Executa a rotina de fim de jogo
Desenhamos todos os sprites na tela:
drawSprites();
drawSprites()
: Exibe todos os sprites criados na tela do jogo, garantindo que a animação seja atualizada a cada quadro.
Por fim, exibimos a pontuação na tela:
textSize(20);
fill(255);
text("Tesouro: "+ treasureCollection, 150, 30);
}
textSize(20)
: Define tamanho da fontefill(255)
: Cor branca para o textotext()
: Exibe a pontuação atual na posição (150,30)
Passo 6: Criando a função para gerar as notas de dinhero
A função createCash()
é chamada continuamente para criar os objetos de dinheiro na tela do jogo.
frameCount % 200 == 0
: Cria um novo objeto de dinheiro a cada 200 quadrosrandom(50, 350)
: Faz com que o dinheiro apareça em posições aleatórias no eixo X.createSprite(random(50, 350),40, 10, 10)
: Cria o sprite na posição definida.addImage(cashImg)
: Aplica a imagem do dinheiro ao spritescale=0.12
: Define o tamanho do sprite.velocityY = 3
: Define a velocidade de queda.lifetime = 150
: Evita consumo excessivo de memória ao remover sprites antigos.cashG.add(cash)
: Adiciona o objeto ao grupo de dinheiro para gerenciamento coletivo
function createCash() {
if (frameCount % 200 == 0) {
var cash = createSprite(Math.round(random(50, 350)),40, 10, 10);
cash.addImage(cashImg);
cash.scale = 0.12;
cash.velocityY = 3;
cash.lifetime = 150;
cashG.add(cash);
}
}
Passo 7: Criando a função para gerar os diamantes
A função createDiamonds()
é chamada continuamente para criar os diamantes na tela do jogo.
frameCount % 320 == 0
: Cria um novo diamante a cada 320 quadrosrandom(50, 350)
: Faz com que o dinheiro apareça em posições aleatórias no eixo X.createSprite(random(50, 350),40, 10, 10)
: Cria o sprite na posição definida.addImage(diamondsImg)
: Aplica a imagem do diamantescale=0.03
: Define o tamanho do sprite.velocityY = 3
: Define a velocidade de queda.lifetime = 150
: Evita consumo excessivo de memória ao remover sprites antigos.diamondsG.add(diamonds)
: Adiciona ao grupo de diamantes para controle coletivo
function createDiamonds() {
if (frameCount % 320 == 0) {
var diamonds = createSprite(Math.round(random(50, 350)),40, 10, 10);
diamonds.addImage(diamondsImg);
diamonds.scale = 0.03;
diamonds.velocityY = 3;
diamonds.lifetime = 150;
diamondsG.add(diamonds);
}
}
Passo 8: Criando a função para gerar as joias
A função createJwellery()
é chamada continuamente para criar as joias na tela do jogo.
frameCount % 320 == 0
: Cria um novo diamante a cada 320 quadrosrandom(50, 350)
: Faz com que o dinheiro apareça em posições aleatórias no eixo X.createSprite(random(50, 350),40, 10, 10)
: Cria o sprite na posição definida.addImage(jwelleryImg)
: Aplica a imagem da joiascale=0.13
: Define o tamanho do sprite.velocityY = 3
: Define a velocidade de queda.lifetime = 150
: Evita consumo excessivo de memória ao remover sprites antigos.jwelleryG.add(jwellery)
: Adiciona ao grupo de joias para gerenciamento
function createJwellery() {
if (frameCount % 410 == 0) {
var jwellery = createSprite(Math.round(random(50, 350)),40, 10, 10);
jwellery.addImage(jwelleryImg);
jwellery.scale = 0.13;
jwellery.velocityY = 3;
jwellery.lifetime = 150;
jwelleryG.add(jwellery);
}
}
Passo 9: Criando a função para gerar as espadas
A função createSword()
é chamada continuamente para criar as joias na tela do jogo.
frameCount % 530 == 0
: Cria uma nova espada a cada 530 quadrosrandom(50, 350)
: Faz com que o dinheiro apareça em posições aleatórias no eixo X.createSprite(random(50, 350),40, 10, 10)
: Cria o sprite na posição definida.addImage(swordImg)
: Aplica a imagem da espadascale=0.1
: Define o tamanho do sprite.velocityY = 3
: Define a velocidade de queda.lifetime = 150
: Evita consumo excessivo de memória ao remover sprites antigos.swordGroup.add(sword)
: Adiciona ao grupo de espadas para controle coletivo
function createSword(){
if (frameCount % 530 == 0) {
var sword = createSprite(Math.round(random(50, 350)),40, 10, 10);
sword.addImage(swordImg);
sword.scale = 0.1;
sword.velocityY = 3;
sword.lifetime = 150;
swordGroup.add(sword);
}
}
Passo 10: Função PLAY()
A função PLAY()
contém toda a lógica do jogo quando o estado está ativo.
function PLAY(){
boy.x = World.mouseX;
boy.x = World.mouseX
: Faz o personagem principal seguir horizontalmente a posição do mouse.
Agora, precisamos garantir que o fundo volte ao início quando sair da tela:
if(path.y > 400 ){
path.y = height / 2;
}
if(path.y > 400)
: Verifica se o sprite do caminho saiu da tela.path.y = height / 2;
: Reposiciona o caminho para criar um efeito infinito.
Adicionando colisão do corredor nas bordas:
boy.collide(leftBoundary);
boy.collide(rightBoundary);
boy.collide(leftBoundary):
Verifica a colisão do corredor com a borda da esquerda.boy.collide(rightBoundary):
Verifica a colisão do corredor com a borda da direita.
Chama as funções que criam os diferentes tipos de objetos:
createCash();
createDiamonds();
createJwellery();
createSword();
createCash():
cria as notas de dinheiro.createDiamonds():
cria os diamantes.createJwellery():
cria as joais.createSword():
cria as espadas.
Coletando as notas de dinheiro:
if (cashG.isTouching(boy)) {
cashG.destroyEach();
treasureCollection = treasureCollection + 50;
}
if(cashG.isTouching(boy))
: Verifica se o personagem (boy
) tocou algum objeto do grupo de dinheiro (cashG
).cashG.destroyEach()
: Remove os sprites de dinheiro que colidiram com o personagem.treasureCollection = treasureCollection + 50
: Adiciona 50 pontos ao contador de tesouro.
Coletando os diamantes:
if (diamondsG.isTouching(boy)) {
diamondsG.destroyEach();
treasureCollection = treasureCollection + 100;
}
if(diamondsG.isTouching(boy))
: Verifica se o personagem tocou algum diamante (diamondsG
).diamondsG.destroyEach()
: Remove os diamantes coletados.treasureCollection = treasureCollection + 100
: Adiciona 100 pontos (valor maior que dinheiro).
Coletando as joias:
if (jwelleryG.isTouching(boy)) {
jwelleryG.destroyEach();
treasureCollection = treasureCollection + 150;
}
if(jwelleryG.isTouching(boy))
: Verifica se o personagem tocou alguma joia (jwelleryG
).jwelleryG.destroyEach()
: Remove as joias coletadas.treasureCollection = treasureCollection + 150
: Adiciona 150 pontos (item mais valioso).
Detectando a colisão com as espadas:
if (swordGroup.isTouching(boy)) {
gameState = "END";
}
if(swordGroup.isTouching(boy))
: Verifica se o personagem tocou alguma espada (swordGroup
).gameState = "END"
: Encerra o jogo, mudando seu estado para “END”.
Passo 11: Função END()
A função END()
contém toda a lógica do jogo quando está no fim.
function END() {
Agora, precisamos criar a animação e nova posição do jogador quando perder o jogo:
boy.addAnimation("SahilRunning", endImg);
boy.x = 200;
boy.y = 300;
boy.scale = 0.6;
boy.addAnimation("SahilRunning", endImg)
: Define uma nova animação para o jogador.boy.x = 200
eboy.y = 300
: Reposiciona o personagem nas coordenadas x=200 e y=300 na tela.boy.scale = 0.6
: Redimensiona o personagem.
Destruindo os grupos de objetos:
cashG.destroyEach();
diamondsG.destroyEach();
jwelleryG.destroyEach();
swordGroup.destroyEach();
cashG.destroyEach()
: Remove todos os sprites de dinheiro (cashG
) da tela.diamondsG.destroyEach()
: Remove todos os diamantes (diamondsG
) da tela.jwelleryG.destroyEach()
: Remove todas as joias (jwelleryG
) da tela.swordGroup.destroyEach()
: Remove todas as espadas (swordGroup
) da tela.
Agora, precisamos garantir que o fundo volte ao início quando sair da tela:
if(path.y > 400 ){
path.y = height / 2;
}
if(path.y > 400)
: Verifica se o sprite do caminho saiu da tela.path.y = height / 2;
: Reposiciona o caminho para criar um efeito infinito.
Por fim, retirando a velocidade dos objetos:
cashG.setVelocityYEach(0);
diamondsG.setVelocityYEach(0);
jwelleryG.setVelocityYEach(0);
swordGroup.setVelocityYEach(0);
cashG.setVelocityYEach(0)
: Define a velocidade vertical (Y) dos objetos de dinheiro como 0 (para evitar que continuem se movendo após o fim do jogo).diamondsG.setVelocityYEach(0)
: Faz o mesmo para os diamantes.jwelleryG.setVelocityYEach(0)
: Paralisa as joias.swordGroup.setVelocityYEach(0)
:Paralisa as espadas.