Jump to content
Kline777

Tratamento de colisões - Delphi XE5 - Android

Recommended Posts

Kline777

Bem, como prometido, ando a ver se faço qq coisa em 3D para o Android com o Delphi, provavelmente o pong então :P . No entanto, não se faz nada de jeito sem conseguir detectar as colisões entre objectos e foi aqui que a coisa parou um bocado, dado que apesar de ter sido feito bastante para o VCL e em 2D. Não consegui encontrar nada para FireMonkey.

Assim sendo, e como os meus conhecimentos em geometria e álgebra sempre foram poucos ou nulos, peguei em codigo desse já feito e adaptei para usar os objectos do FireMonkey.

Ainda não fiz nada de especial, apenas umas classezitas e detecção de colisões entre a bola e as paredes. Mas penso que o resto andará rápido.

Pelo teste que já fiz, parece correr no android igual ao que corre no Windows. Obviamente a performance ainda é uma fraqueza, mas neste tipo de aplicação penso que não se irá notar muito.

ff8y.png

Obvio que ainda nao liguei ao aspecto, mas pronto, a parte de andar pelo cenario está feita. Brevemente vou por mais qq coisa sobre isto. Se nao acontecer como de costume, que é fazer as classes com a pica toda e depois parar quando for para implementar no projecto xD

  • Vote 2

Share this post


Link to post
Share on other sites
I-NOZex

quando perderes a pica, faz tal e qual a tua foto de perfil :D

E volta ao trabalho mandriao :cheesygrin:

Boas continuaçoes, vai deixando atualizaçoes :thumbsup:


B2R » Beat2Revolution v3.0b | Regista e divulga-nos

beat2revolution.net

Share this post


Link to post
Share on other sites
Kline777

Bem, duvida:

Para fazer o movimento dos objectos no espaço, na minha classe existe uma propriedade MovSpeed que basicamente define a velocidade do objecto e se esta for maior que zero, activa uma thread para mover o objecto até que a velocidade volte a zero.

 tthread.CreateAnonymousThread(
   procedure ()
   begin
     //Confirmar que nao arranco com 2  threads a fazerem o mesmo
     if (not _IsMoving) and (_MovSpeed>0) then
     begin
       //Activar Lock
       _IsMoving:=true;
       while (_MovSpeed<>0) do
       begin
         //Mover o objecto consoante a sua velocidade e direcção
         center.X:=center.X+(MovVector.x*MovSpeed);
         center.Y:=center.Y+(MovVector.Y*MovSpeed);
         center.Z:=center.Z+(MovVector.Z*MovSpeed);
         //Sleep para o utilizador ver alguma coisa 
         Sleep(RefreshSpeed);
       end;
       //Desactivar o lock
       _IsMoving:=false;
     end;
   end).Start;

Isto por objecto, ou seja, cada objecto move-se no espaço sem ter ideia do movimento dos outros objectos.

A minha duvida é: Será que isto é uma boa abordagem? Para fazer o tratamento de colisões se calhar pode ser perigoso...

Estou a pensar que se calhar ficava mais seguro com um método que recebia a lista de objectos para mover nesse momento e fazê-lo de forma sequencial....

Assim depois de correr a lista dos objectos a mover, corria novamente para ver se algum tinha colidido, e so depois disso passava para a proxima iteração...

Alguém tem alguma ideia mais limpa e funcional, ou acham que é por aqui? :P

Edited by thoga31
GeSHi

Share this post


Link to post
Share on other sites
Kline777

J0u4T.png

Bem, depois das ferias e de umas batatadas... já consegui avançar mais um pouco. A bola já anda a bater nas paredes e no pad com as movimentaçoes normais.

Basicamente estou a fazer uma unit que se possa incluir num qualquer projecto Firemonkey e que com umas 5 ou 6 linhas de codigo passamos a ter informação das colisoes, adicionar movimentos e fazer uns joguitos basicos com poucas linhas de codigo.

É so adicionar os objectos 3d que quiserem á lista de objectos a 'escutar' e sempre que adicionarem uma direcção e velocidade a um objecto este vai mover-se sem mais programação e a cada colisao dispara um evento com os 2 objectos envolvidos assim como outros campos relevantes.

Está a funcionar no android como no windows, mas como de costume tive muito que me chatear, há coisas que nao se podem usar ou que tem de ser tentativa e erro... por exemplo, nao estou a conseguir usar TList's no android... tive de usar um array, o que me chateia bastante :P

Share this post


Link to post
Share on other sites
bioshock

(...) por exemplo, nao estou a conseguir usar TList's no android... tive de usar um array, o que me chateia bastante :P

Ao que é que te referes propriamente?

Share this post


Link to post
Share on other sites
thoga31

Ao facto de termos um tipo de dados muito útil, chamado TList, e que, aparentemente, no Android não está a funcionar devidamente.


Knowledge is free!

Share this post


Link to post
Share on other sites
Kline777

Ya... presumo que a TList seja basicamente uma lista simples de ponteiros. No windows corre tudo ok, mas no o android a coisa nao aponta para onde deve :P aponta para zonas aleatorias da memoria e dá barrakesh ^^ Mudei para um array de objectos e deu à primeira.

Edited by Kline777

Share this post


Link to post
Share on other sites
bioshock

Pelo que estive a ver aqui http://www.delphibasics.co.uk/RTL.asp?Name=TList, eventualmente, o que mais se pode semelhar em Android são as list.

List<customers> customer = new ArrayList<customers>();

Onde customers é uma classe.

Se quiseres por exemplo dois pontos de referência String, Integer, utilizas o Map.

Map<String, Integer>customers = new HashMap<String, Integer>();

Share this post


Link to post
Share on other sites
thoga31

@bioshock, mas isso é Java. Nós estamos a falar de código escrito em Delphi :D


Knowledge is free!

Share this post


Link to post
Share on other sites
bioshock

Eu sei..tinha-me era esquecido que o código é todo compilado em Delphi. Quando escrevi aquilo, estava na ideia que ele tinha ido fazer umas alterações ao código Java. :D

Share this post


Link to post
Share on other sites
Kline777
:P Nope... a ideia é ter a coisa a compilar para Windows e Android com o mm codigo Delphi. O problema é que pelos vistos algumas funções nao têm correspondencia. Tambem cometi o erro do usar o Application.ProcessMessages inicialmente e tb foi uma dar de cabeça para dar com aquilo, mas aí ja é bem feito que ninguem me manda usar essa funçao por dá cá aquela palha

Share this post


Link to post
Share on other sites
Kline777

Boas, estou com um problema por causa do android que nao estou a conseguir dar a volta. Basicamente tenho uma thread a correr sempre para calcular quando a bola bate no fundo, e quando isso acontece aparece uma label com o resultado actual.

Problema: Estou a mudar o text da label DENTRO da thread que criei... Isto nao é problema no windows mas no android nao dá (Não é limitaçao do delphi, no java é igual) pois pelo que percebi nao podemos fazer alteraçoes visuais sem ser na thread principal.

Questão: Tendo eu algo como

procedure A();
begin
 //Do stuff
 Label1.text:=' 0 - 1':
end;
procedure B();
begin
 TThread.CreateAnonymousThread(
procedure ()
begin
  //Do Stuff
  //Chamar funçao A
  A;
end).Start;
end;

Estando nós dentro da thread na funçao B, existe maneira de dizer para a funçao A ser chamada na thread principal?

Ou acham que posso dar a volta de outra maneira?

Edited by Kline777

Share this post


Link to post
Share on other sites
bioshock

Apesar de não te poder fornecer código de delphi, posso dar a ideia. Esse problema que tens é muito comum. Tudo o que tens de fazer é tornar a função A numa thread à parte, eventualmente como fizestes com a função B.

Edited by bioshock

Share this post


Link to post
Share on other sites
Kline777

Pois mas parece-me que neste caso (mudar o text de uma label) não posso simplesmente executar a funçao A numa thread nova, mas sim, especificamente na principal... não sei é como lá voltar :P

Share this post


Link to post
Share on other sites
bioshock

Hum? Atrevo-me a dizer que aí há gato.

Imagina que tens duas funções distintas, à partida não inicializadas.

Num evento qualquer, chamas a função A que está dentro de uma thread, que por sua vez chama a função B que também está dentro de uma thread.

procedure A();
begin
 TThread.CreateAnonymousThread(
	procedure ()
	begin
	   B;
	end).Start;
end;

procedure B();
begin
 TThread.CreateAnonymousThread(
	procedure ()
	begin
	   // código
          Label1.text:=' 0 - 1':
	end).Start;
end;

Estamos a falar da mesma classe, correcto? Se sim, isso devia de funcionar..em Java (Android) pelo menos funciona.

Edited by bioshock

Share this post


Link to post
Share on other sites
Kline777

Vou tentar logo... mas olha que tenho lido que no java só podes mudar coisas do layout na mainActivity...

Share this post


Link to post
Share on other sites
bioshock

Estamos a falar da mesma classe, correcto? Se sim, isso devia de funcionar..em Java (Android) pelo menos funciona.

Isto responde ao teu último post.

Se me dizes que estás na activity A (ou como quiseres chamar em Delphi) e alteras o conteúdo da Activity B, também é possível. Em Android podes conseguir isso de várias formas, desde bundles, shared preferences, base de dados, etc. Depois é só trabalhar com os eventos.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.