Ir para conteúdo

Arquivado

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

Daniel o rei

[Resolvido] calculando colisões: entre duas linhas e dois circulo

Recommended Posts

Calcular colisões é importante, principalmente para jogos.

 

Então vamos calcular colisões entre dois circulos e também de duas linhas.

 

circulo-circulo

 

Para calcular é bem fácil.

 

Basta saber a distância dos centros dos dois circulos e o raio dos dois.

 

Se a distância dos dois circulos for menor que a soma dos dois raios há interseção.

 

Para saber a distância use o teronema de pitágoras.

"O quadrado da hipotenusa é igual a soma do quadrado dos catetos."

Hipotenusa ² = cateto_adjascente ² + cateto_oposto ²

 

Então é só elevar ao quadrado os dois catetos e somar eles. Depois tirar a raiz quadrada.

 

 

Fiz um exemplo:

 

http://megaswf.com/serve/2311190

 

import flash.events.MouseEvent;
import flash.display.Sprite;
import flash.display.Shape;
var format:TextFormat = new TextFormat();
format.size = 17 ;
var ins = new TextField() ;
addChild(ins);
ins.x = 72;
ins.y = 332;
ins.width = 401;
ins.height = 25;
ins.defaultTextFormat = format;
//texto interseção
var intersection = new TextField() ;
addChild(intersection);
intersection.x = 72;
intersection.y = 365;
intersection.width = 401;
intersection.height = 25;
intersection.defaultTextFormat = format;
stage.addEventListener(MouseEvent.CLICK , mclick);
var cirtemp:Shape = new Shape();
var lintemp:Shape = new Shape();
addChild(lintemp);
addChild(cirtemp);
var circ1:Shape = new Shape();
var circ2:Shape = new Shape();
addChild(circ1);
addChild(circ2);
var p_r:Array = new Array();
var px:Number ;
var py:Number ;
var clicks:Number = 0;
ins.text = "defina o ponto do meio do circulo 1" ;
function mclick(e:MouseEvent):void{
if(clicks == 0){
px = e.localX;
py = e.localY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, mm);
trace('down');
ins.text = "defina o raio do circulo 1" ;
clicks = 1;
p_r['x1'] = e.localX;
p_r['y1'] = e.localY;
}else if(clicks == 1){
circ1.graphics.lineStyle(1,0x000000,1);
circ1.graphics.drawCircle(px,py, teronema_de_pitagoras(e.localX - px, e.localY - py));
lintemp.graphics.clear();
clicks = 2 ;
ins.text = "defina o ponto do meio do circulo 2" ;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mm);
p_r['r1'] = teronema_de_pitagoras(e.localX - px, e.localY - py);
}else if(clicks == 2){
px = e.localX;
py = e.localY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, mm);
trace('down');
clicks = 3;
ins.text = "defina o raio do circulo 2" ;
p_r['x2'] = e.localX;
p_r['y2'] = e.localY;
}else if(clicks == 3){
circ2.graphics.lineStyle(1,0x000000,1);
circ2.graphics.drawCircle(px,py, teronema_de_pitagoras(e.localX - px, e.localY - py));
lintemp.graphics.clear();
clicks = 4 ;
ins.text = "clique em algum lugar para apagar" ;
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mm);
p_r['r2'] = teronema_de_pitagoras(e.localX - px, e.localY - py);
if(teronema_de_pitagoras(p_r['x1'] - p_r['x2'] ,p_r['y1'] - p_r['y2'] ) < p_r['r1'] + p_r['r2']){
	intersection.text = "há interseção";
}else intersection.text = "não há interseção";
}else if(clicks == 4){
	circ2.graphics.clear();
	circ1.graphics.clear();
	cirtemp.graphics.clear();
	clicks = 0;
	ins.text = "defina o ponto do meio do circulo 1" ;
	intersection.text = "";
}


}

function mm(e:MouseEvent):void{
cirtemp.graphics.clear();
cirtemp.graphics.lineStyle(1,0xFF0000,1);
cirtemp.graphics.drawCircle(px,py, teronema_de_pitagoras(mouseX - px, mouseY - py));
lintemp.graphics.clear();
lintemp.graphics.lineStyle(1,0xFF0000,1);
lintemp.graphics.moveTo(px,py);
lintemp.graphics.lineTo(mouseX,mouseY);
trace('mm');
}
function teronema_de_pitagoras(ca:Number , co:Number):Number{
//soma dos quadrados dos catetos
var s_d_q_d_c:Number = Math.pow(Math.abs(ca),2) + Math.pow(Math.abs(co),2)
var hipotenusa:Number = Math.sqrt(s_d_q_d_c);
return hipotenusa;
trace('tdp');
}

para testar o exemplo é só criar o fla com 550x400 px e colar o script no frame 1

A função teronema_de_pitagoras funciona assim:

ca é o cateto adsjascente, e co o oposto

ca é a diferença da posição x dos dois pontos(ponto1.x - ponto2.y)

e co é a diferença da posição y.

 

linha-linha

 

 

Eu estava querendo calcular a interseção de duas linhas,

Fiz vários calculos com seno e cosseno, só que não achava uma fórmula,

Até achar no wikipedia.

http://en.wikipedia....ne_intersection

 

Aqui está a formula:

 

acd2938d1c482f5247654e6822ec06ad.png

Imagem do wikipedia.

 

Para saber se é paralelo:

6c88e10b6c07b86c33deac72ba33cf6f.png

 

 

Então fiz um exemplo:

 

http://megaswf.com/serve/2311190

 

É só clicar para definir os 4 pontos das 2 linhas.

 

E vai aparecer duas linhas vermelhas indicando a interseção.

 

 

Só que tem o seguinte:

 

Essa formula calcula a interseção das linhas como se fossem infinitas, então entre duas linhas que não sejam paralelas, sempre haverá uma interseção em algum lugar.

 

Então é só ver se essa interseção está na "área" das duas linhas, se estiver fora vai aparecer no textfield "fora da linha:true".

Se for paralelo vai aparecer: "paralelo:false"

 

import flash.events.MouseEvent;
import flash.display.Sprite;
//cria todos os textsfields
var format:TextFormat = new TextFormat();
format.size = 17 ;
var instr:TextField = new TextField();
instr.x = 26;
instr.y = 49;
instr.defaultTextFormat = format;
instr.width = 367;
instr.height = 45;
instr.selectable = false;
//
var line1p1:TextField = new TextField();
line1p1.x = 15;
line1p1.y = 226.6;
line1p1.defaultTextFormat = format;
line1p1.width = 200;
line1p1.height = 65;
line1p1.selectable = false;
//cria outro textfield
var line1p2:TextField = new TextField();
line1p2.x = 15;
line1p2.y = 295;
line1p2.width = 200;
line1p2.height = 65;
line1p2.defaultTextFormat = format ;
line1p2.selectable = false;
//mais um
var line2p1:TextField = new TextField();
line2p1.x = 12;
line2p1.y = 363;
line2p1.width = 200;
line2p1.height = 65;
line2p1.defaultTextFormat = format ;
line2p1.selectable = false;
//outro		
var line2p2:TextField = new TextField();
line2p2.x = 12;
line2p2.y = 430;
line2p2.width = 200;
line2p2.height = 65;
line2p2.defaultTextFormat = format ;
line2p2.selectable = false;
//o ultimo
var inter:TextField = new TextField();
inter.x = 363;
inter.y = 219;
inter.width = 209;
inter.height = 203;
inter.defaultTextFormat = format ;
inter.selectable = false;
//agora addChild em tudo
addChild(inter);
addChild(line1p1);
addChild(line1p2);
addChild(line2p1);
addChild(line2p2);
addChild(instr);
var ponto_atual:int = 0;
var pontos = new Array();
stage.addEventListener(MouseEvent.CLICK , mclick);
var ln1:Shape = new Shape();
var ln2:Shape = new Shape();
var lnx:Shape = new Shape();
var lny:Shape = new Shape();
addChild(ln2);
addChild(ln1);
addChild(lnx);
addChild(lny);

instr.text = "clique em lugar para definir o ponto 1(linha 1)";
function mclick(e:MouseEvent):void{
if(ponto_atual == 0){
	pontos['x1'] = mouseX;
	pontos['y1'] = mouseY;
	ponto_atual = 1;
	//ja definiu o ponto 1
	line1p1.text = "linha 1(ponto1(x1 e y2)) \n x1 = " + pontos["x1"] + "\ny1 = " + pontos["y1"] ;
	instr.text = "clique em lugar para definir o ponto 2(linha 1)";
}else
if(ponto_atual == 1){
	pontos['x2'] = mouseX;
	pontos['y2'] = mouseY;
	ln1.graphics.lineStyle(2, 0x000000, 1);
	ln1.graphics.moveTo(pontos['x1'], pontos['y1']);
	ln1.graphics.lineTo(pontos['x2'], pontos['y2']);
	ponto_atual = 2;
	line1p2.text = "linha 1(ponto2(x2 e y2)) \n x2 = " + pontos["x2"] + "\ny2 = " + pontos["y2"] ;
	//ja definiu o ponto 2
instr.text = "clique em lugar para definir o ponto 3(linha 2)";
}else 
if(ponto_atual == 2){
	pontos['x3'] = mouseX;
	pontos['y3'] = mouseY;
	ponto_atual = 3;
			line2p1.text = "linha 2(ponto1(x3 e y3)) \n x3 = " + pontos["x3"] + "\ny3 = " + pontos["y3"] ;
	//ja definiu o 3
	instr.text = "clique em lugar para definir o ponto 4(linha 2)";

}else 
if(ponto_atual == 3){
	pontos['x4'] = mouseX;
	pontos['y4'] = mouseY;
	ln2.graphics.lineStyle(2, 0x000000, 1);
	ln2.graphics.moveTo(pontos['x3'], pontos['y3']);
	ln2.graphics.lineTo(pontos['x4'], pontos['y4']);
	ponto_atual = 4;
					line2p2.text = "linha 2(ponto2(x4 e y4)) \n x4 = " + pontos["x4"] + "\ny4 = " + pontos["y4"] ;
	//ja definiu o 4
	instr.text = "Para zerar tudo clique em qualquer lugar";
	var a_intc = line_intersection(pontos);
	//desenha a linha do ponto de interseção x
	lnx.graphics.lineStyle(1, 0xFF0000, 1);
	lnx.graphics.moveTo(a_intc['x'], 0);
	lnx.graphics.lineTo(a_intc['x'], stage.stageHeight);
	//aqui é do y
	lny.graphics.lineStyle(1, 0xFF0000, 1);
	lny.graphics.moveTo(0, a_intc['y']);
	lny.graphics.lineTo(stage.stageWidth,a_intc['y']);
	inter.text= "interseção:\nx: " + a_intc["x"] + "\ny: " +  a_intc["y"] + "\nfora da linha: " + a_intc['f'] + "\nparalelo: " + a_intc['p'];

}else
if(ponto_atual == 4){
	ponto_atual = 0 ;
	ln1.graphics.clear();
	ln2.graphics.clear();
	lnx.graphics.clear();
	lny.graphics.clear();
	pontos["x1"] = null ;
	pontos["x2"] = null ;
	pontos["x3"] = null ;
	pontos["x4"] = null ;
	pontos["y1"] = null ;
	pontos["y2"] = null ;
	pontos["y3"] = null ;
	pontos["y4"] = null ;
	//ja apagou tudo
	instr.text = "clique em lugar para definir o ponto 1(linha 1)";
}


}
function line_intersection(pontos_array:Array):Array{
var array = new Array();
var x1 = pontos_array['x1'];
var x2 = pontos_array['x2'];
var x3 = pontos_array['x3'];
var x4 = pontos_array['x4'];
var y1 = pontos_array['y1'];
var y2 = pontos_array['y2'];
var y3 = pontos_array['y3'];
var y4 = pontos_array['y4'];
var conta1 = (x1 * y2 - y1* x2) * (x3 - x4) - (x1 - x2) * (x3 * y4 - y3*x4);
var conta2 = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3-x4);
array["x"] = conta1/conta2;
var conta3 = (x1*y2 - y1* x2) * (y3 - y4) - (y1-y2)*(x3*y4 - y3 * x4) ;
var conta4 = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3-x4);
array["y"] = conta3/conta4;
//agora verifica se é está fora da linha
if(en(x1,x2,array['x'])  && en(y1,y2,array['y']) && en(x3,x4,array['x'])  && en(y3,y4,array['y'])){
	array["f"] = false;
}else array["f"] = true;
var conta5:Number = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
if(conta5 ==0){
array['p'] = true;
}else array['p'] = false;
return array ;

}

function en(a:Number , b :Number,c:Number):Boolean{
	var maior:Number ;
	var menor:Number ;
	if(a>B){
		maior = a;
		menor = b;
	}else{
		maior = b;
		menor = a;
	}
	if(c >= menor && maior >= c){
		return true;
	}else return false

}

 

Para testar esse exemplo:

 

Crie um fla com 600x500 px e coloque o script no frame 1.

 

Se quizer pode colocar um static text com "interseção de duas linhas retas" como coloquei.

 

A função line_intersection recebe um array com os 4 pontos das duas linhas(x1,y1,x2,y2,x3,y3,x4 e y4), e retorna um array com o ponto da interseção(x e y) e se está fora da linha(f) e se é paralelo(p)

 

Acredito que esse algoritmo possa servir para qualquer liguagem.

 

Se tiverem algum problema por favor postem.

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.