Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Vini_Aviva

[Resolvido] uma forma de usar vários objetos dentro de um só canvas

Recommended Posts

Minha primeira dúvida é sobre criações de tiles em JavaScript dentro de um canvas. Inicialmente sei que o tiles precisam ser configurados por uma array

t = [
[0,0,0],
[0,0,0],
[0,0,0]
];

E tenho mais variáveis que seriam

ts = 100; // Tamanho do tile
tr = t.length; // Quantidade de linhas
tc = t[0].length; // Quantidade de Colunas

E sei que preciso montar essas informações em dois for um dentro do outro mas é nessa parte que estou tendo problemas, gostaria que alguém pudesse me ajudar.

 

Minha segunda dúvida é sobre a criação de mais de um objeto dentro do canvas um exemplo.

ctx.fillRect(50,20,20,20);
x = 0;
function loop(){
x += 1;
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillRect(x,0,20,20);
}
setInterval('loop()',0);

Podem ver que criei 2 quadrados no mesmo canvas e um deles está dentro de um loop que coloca +1 a x cada 0 milissegundo criando assim uma "ideia" de movimento redesenhando o bloco na nova posição mas o que acontece é que ele deixa um rastro e para que não deixe precisamos limpar o canvas com a clearRect já tentei por exemplo fazer com que ele só limpe a parte em que o bloco passa subtraindo a posição do bloco - 1.

ctx.fillRect(50,20,20,20);
x = 0;
function loop(){
x += 1;
ctx.clearRect(x - 1,0,20,20);
ctx.fillRect(x,0,20,20);
}
setInterval('loop()',0);

Mas teria grandes problemas se fosse mudar a direção do objeto e quando ele passa sobre outro objeto ele corta o outro por cima. :(

 

Então na minha ultima dúvida gostaria que vocês me explicassem uma forma de usar vários objetos dentro de um só canvas sem que eu tenha problemas em ter que limpar todo o canvas pra redesenhar o objeto, obrigado a quem poder me ajudar.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Referente à primeira dúvida, leia este tópico: http://forum.imasters.com.br/topic/466460-game-em-html5/

 

Sobre a segunda dúvida, só vejo vantagem em limpar apenas um único objeto do canvas, caso todo o restante do mesmo seja estático, e se esse for o caso, você não deveria está usando o mesmo canvas, deveria usar um outro para o bg.

 

Mas se realmente deseja isso, crie um objeto para o teu retângulo, assim facilitaria, seria algo como:

var rect = {
       x : 50,
       y : 20,
       w : 20,
       h : 20
   },
   speed = {
       x : 1,
       y : 0
   };

function loop(){
   ctx.clearRect( rect.x, rect.y, rect.w, rect.h ); //limpa apenas o retângulo
   ctx.fillRect( rect.x, rect.y, rect.w, rect.h );
   rect.x += speed.x;
}
setInterval( loop, 0 ); //não use uma string como parâmetro, apenas passe a função.

 

Detalhe, usar 0 no setInterval não adianta, os timers do Javascript não são exatos, se tiver algo mais importante para fazer, ele vai deixar o código em segundo plano, e retornar para ele depois, quando a tarefa com mais prioridade for concluída, portanto o melhor é usar requestAnimationFrame para animações.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Tem até um post aqui no fórum que eu pergunto sobre atualizar o canvas. :thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Estou com mais uma dúvida e não queria criar outro tópico pra retira-la então é o seguinte.

 

Criei os dois canvas como o JCMais falou, um para o boneco e outro para o bg mas infelizmente não estou conseguindo detectar colisões

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; heroset=utf-8" />
<title>Untitled Document</title>
<style>
body {
margin:0px;
padding:0px;
}
</style>
</head>

<body>
<canvas id="panel2" width="156" height="156" style="position:absolute;"></canvas>
<canvas id="panel" width="156" height="156"></canvas>
<script type="text/javascript">
var canvas = document.getElementById('panel');
if(canvas.getContext){
var ctx = canvas.getContext('2d');
}else{
alert("Seu navegador não tem suporte a HTML5");
}
var canw = canvas.width;
var canh = canvas.height;
ctx.fillStyle = '#000';

var charlayer = document.getElementById('panel2');
var charctx = charlayer.getContext('2d');

var t = [
[0,0,0,0,0],
[0,0,1,0,0],
[0,1,1,1,0],
[0,0,1,0,0],
[0,0,0,0,0]
],
tc = t[0].length,
tr = t.length,
ts = 31,
ti = [
'http://i.imgur.com/z2Ulf.gif',
'http://i.imgur.com/iKSXz.gif'
],i,x,y;

for(i = 0; i < ti.length; i++){
var src = ti[i],
img = new Image();
img.src = src;
img.onload = (function(index){
	return function(){
		imageLoaded(this,index);
};
}(i));
}
var imageLoaded = (function(){
var totalImagesLoaded = 0;
return function(image,index){
	++totalImagesLoaded;
       ti[index] = image;
	if(totalImagesLoaded === ti.length)
		drawTileMap();
	}
}());

var drawTileMap = function(){
for(y = 0; y < tr; y++){
	for(x = 0; x < tc; x++){
		ctx.drawImage(ti[t[y][x]],ts * x,ts * y);		
		char = new Image();
			char.src = 'http://i.imgur.com/9GyzZ.png';
			charx = 62;
			chary = 62;
			char.onload = function(){
				charctx.drawImage(char,charx,chary);
			}
		function loop(){
			window.onkeydown = keypressed;
				function keypressed(e){
				charctx.clearRect(0,0,canw,canh);
				if(e.keyCode == 39){
					charx += ts;
					charctx.drawImage(char,charx,chary);
				}
				if(e.keyCode == 38){
					chary -= ts;
					charctx.drawImage(char,charx,chary);
				}
				if(e.keyCode == 37){
					charx -= ts;
					charctx.drawImage(char,charx,chary);
				}
				if(e.keyCode == 40){
					chary += ts;
					charctx.drawImage(char,charx,chary);
				}
			}
		}
		setInterval(loop,0);
	}
}
}
</script>
</body>
</html>

Assim que a página é carregada a bolinha é colocada no centro dos tiles, os tiles configurados na array pelo número 1 são os espaços em que ele pode andar o 0 não pode. Este é o código "limpo" sem minhas tentativas de colisões e etc gostaria de saber o que posso fazer, obrigado desde já.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Estranho, agora abriu;. :huh:

 

Referente à sua dúvida, primeiramente, defina a posição do elemento no tile com base na array que contém o mapa de tiles, você está usando por exemplo x:62,y:62, e esses valores não são com base na array, pois não existem tais índices (t[62][62]).

 

Apenas quando for renderizar a imagem que você converte para os valores absolutos.

 

Neste caso, o centro do mapa é t[y:2][x:2], que quando for renderizar se transforma em x:62 e y:62. Consegue pensar na fórmula para transformar tais valores? :rolleyes:

 

Após conseguir elaborar a fórmula, fica fácil saber se é permitido a movimentação para determinado tile, basta pegar as coordenadas e verificar na array, se o valor obtido for 1, é permitido, caso contrário, não.

 

Este é o esquema mais básico, de acordo com o que você for estudado irá ver outras formas, mais complexas, porém mais eficientes.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Cara desculpa infelizmente não estou conseguindo :( mas vou continuar tentando aqui... Se você tiver mais algo a acrescentar que possa me ajudar ficaria grato.

Compartilhar este post


Link para o post
Compartilhar em outros sites

O que exatamente você não está conseguindo?

Não estou sabendo utilizar as variáveis de forma adequada para poder ler se aquele tal tile tem o valor de 0 ou 1 e não estou conseguindo montar essa tal "fórmula" que você mencionou. Mas vou continuar tentando aqui até conseguir.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Você precisa trabalhar com coordenadas que são baseadas na array de tiles, e não nos pixels do Canvas.

 

Para centralizar o char no centro, por exemplo, você usou as coordenadas X:62 e Y:62

charx = 62;
chary = 62;

 

Porém você deveria ter usado x:2 e y:2 (se lembre da array que contém seu mapa, esses são os indices que representam o centro da mesma, t[y:2][x:2]):

t = [
   [0,0,0,0,0],
   [0,0,1,0,0],
   [0,1,1,1,0],
   [0,0,1,0,0],
   [0,0,0,0,0]
],

 

Apenas na hora de renderizar o char, momento no qual você precisaria saber em qual pixel colocar a imagem do char, que você transformaria a coordenada x:2,y:2 para x:62,y:62.

 

O cálculo parece difícil, mas qual o tamanho de cada tile? Bom... no exemplo que você postou é 31.

ts = 31

 

Logo, analisando o que temos:

charImageX = tileSize * char.X;
charImageY = tileSize * char.Y;

 

:thumbsup:

Compartilhar este post


Link para o post
Compartilhar em outros sites

Estou tentando tomara que eu consiga a coisa ta complicada kkk, percebi que tem outro problema por cima disso tudo só não sei exatamente qual é. Já tenho noções de programação e etc porque já trabalho com isso a um bom tempo mas só agora que estou entrando pra área de jogos então isso está me ajudando bastante :D

 

EDIT:

Só uma coisa eu estou usando dois canvas como você falou um para o char e outro para o bg e não estou conseguindo trazer algumas variáveis do bg para o char por algum motivo que eu não sei '-'

Compartilhar este post


Link para o post
Compartilhar em outros sites

Verifique se as suas variaveis são globais. :thumbsup:

Esse realmente não era bem meu problema mas tudo bem valeu as tentativas vou continuar tentando aqui se eu consegui (um dia) eu retorno aqui postando a solução para ajudar outros iniciantes :D

Compartilhar este post


Link para o post
Compartilhar em outros sites

Graças a nosso amigo JCMais todas as minhas dúvidas foram devidamente retiradas obrigado.

 

http://jsfiddle.net/kbjEp/

 

 

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; heroset=utf-8" />
<title>Untitled Document</title>
<style>
body {
margin:0px;
padding:0px;
}
#canvas-main {
position:absolute;
}
</style>
</head>

<body>
<canvas id="canvas-main" width="150" height="150"></canvas>
<canvas id="canvas-bg" width="150" height="150"></canvas>
<script type="text/javascript">
var bgCanvas = document.getElementById('canvas-bg'),
bgCtx = bgCanvas.getContext('2d'),
cWidth = bgCanvas.width,
cHeight = bgCanvas.height;

var canvasMain = document.getElementById('canvas-main'),
mainCtx = canvasMain.getContext('2d'),
player = {
x : 1,
y : 1
};

var tileMap = [
	[0,0,0,0],
	[0,1,1,0],
	[0,1,1,0],
	[0,0,0,0]
   ],
   tileMapWidth = tileMap[0].length,
   tileMapHeight = tileMap.length,
   tileSize = 31,
   tileImages = [
	'http://i.imgur.com/z2Ulf.gif',
	'http://i.imgur.com/iKSXz.gif'
],i,x,y;

for(i = 0; i < tileImages.length; i++){ //preload das imagens
var src = tileImages[i],
	img = new Image();
   img.src = src;
   img.onload = (function(index) {
       return function(){
           imageLoaded(this,index);
       };
   }( i ));
}
var imageLoaded = (function(){
var totalImagesLoaded = 0;
   return function(image,index){
       ++totalImagesLoaded;
       tileImages[index] = image;
       if(totalImagesLoaded === tileImages.length)
           drawTileMap(); // todas as imagens carregadas, renderizar mapa.
       }
}());
var drawTileMap = function(){ // renderiza o mapa
for(y = 0; y < tileMapHeight; y++){
	for(x = 0; x < tileMapWidth; x++){
		bgCtx.drawImage(tileImages[tileMap[y][x]],tileSize * x, tileSize * y);
	}
}
};

var drawPlayer = function(player){ // renderiza o jogador
var playerImg = new Image();
playerImg.src = 'http://i.imgur.com/9GyzZ.png';
playerImg.onload = function(){
	drawPlayer = function(player){
		mainCtx.clearRect(0,0,cWidth,cHeight);
		mainCtx.drawImage(playerImg,player.x * tileSize,player.y * tileSize);
	}
	drawPlayer(player);
}
}

var keypressed = function(e){
   if(e.keyCode == 39 && tileMap[player.y][player.x + 1] != 0){
	player.x += 1;
   }
   if(e.keyCode == 38 && tileMap[player.y - 1][player.x] != 0){
	player.y -= 1;
   }
   if(e.keyCode == 37 && tileMap[player.y][player.x - 1] != 0){
	player.x -= 1;
   }
   if(e.keyCode == 40 && tileMap[player.y + 1][player.x] != 0){
	player.y += 1;
   }
drawPlayer(player);
document.getElementById('cord').innerHTML = 'X: '+player.x+' Y: '+player.y;
}
window.onkeydown = keypressed;
drawPlayer(player);
</script>
<div id="cord"></div>
</body>
</html>

 

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.