GameCorp - Index des forumsGame MakingProgrammationDark Basic - DarkGDK[DarkBasic] Moteur de collision 2D
[DarkBasic] Moteur de collision 2D
| Darktib |
Posté le 08 Jan 2009 à 20:43
|
|
![]() Messages : 4017 GCPoints : 347288 |
dx,dy : t>1 je suppose (au lieu de t>0) ? En gros, maintenant les variables cx,cy sont inutiles ? En tout cas c'est une bonne optimisation, en ce moment je commence a programmer la librairie utilisant ce mode de collisions^^ edit : juste une question: si tu devais renommer les fonctions calcul_vectoriel et distance_vectoriel pour avoir des noms plus explicites, quels noms mettrait tu ?
Dernière édition le 08 Jan 2009 à 20:59
|
|
| Syltech |
Posté le 08 Jan 2009 à 21:25
|
|
![]() Messages : 282 GCPoints : 71266 |
Citation :
Erf, oui c'est t>1^^ Citation :
Elles sont bien inutiles ^^ Code : Pour avoir des noms plus explicites, quels noms mettrait tu ? Pour des noms plus explicites, c'est pas évident... Je dirais "Position_et_Distance_de_Projection" pour "calcul_vectoriel" et "Distance_de_Projection" pour "distance_vectoriel". D'ailleurs tu m'a fait remarqué que j'ai pas modifier la fonction "distance_vectoriel" avec la nouvelle méthode... Techniquement c'est a peu prêt les mêmes fonctions, à part que la fonction "distance_vectoriel" ne renvoie que la distance voici la nouvelle fonction: Code : function distance_vectoriel(x as float, y as float, Wall as v2d)
coef as float : t as float : vdist as float : wx as float : wy as float
coef = (x-Wall.ox)*Wall.lx+(y-Wall.oy)*Wall.ly
t = coef/(Wall.lx^2 + Wall.ly^2)
if t>=0 && t<=1
wx = Wall.ox + t*Wall.lx
wy = Wall.oy + t*Wall.ly
vdist = distance(x,y,wx,wy)
else
if t<0
vdist = distance(x,y,Wall.ox,Wall.oy)
endif
if t>1
vdist = distance(x,y,Wall.dx,Wall.dy)
endif
endif
endfunction vdistVoilou! Syltech Edit: erf je viens de voir qu'il faut que je modifie aussi la fonction "isUnder"... je m'y colle ^^ Et donc la fonction "limite" ne servira plus à rien. Voici la nouvelle fonction "isUnder": Code : function isUnder(x as float, y as float, Wall as v2d)
coef as float : t as float : vdist as float
coef = (x-Wall.ox)*Wall.lx + (y-Wall.oy)*Wall.ly
t = coef/(Wall.lx^2 + Wall.ly^2)
if t>=0 && t<=1
vDist = ((x-Wall.ox)*Wall.ly - (y-Wall.oy)*Wall.lx) / wall.l
endif
endfunction vDist
Dernière édition le 08 Jan 2009 à 21:47
![]() |
|
| Darktib |
Posté le 08 Jan 2009 à 22:12
|
|
![]() Messages : 4017 GCPoints : 347288 |
OK Pour l'instant j'ai quasiment fini les structures (joueur, mur, etc...) et je fais des tests de compilation en me battant avec ces foutues références^^ |
|
| Syltech |
Posté le 09 Jan 2009 à 00:26
|
|
![]() Messages : 282 GCPoints : 71266 |
Ok bon courage ^^, sinon je pense qu'il va falloir que je prenne du temps pour réfléchir sur les ellipse, car mon petit doigt me dit que j'ai pas bien cherché la dernière fois :) Syltech ![]() |
|
| Darktib |
Posté le 09 Jan 2009 à 15:06
|
|
![]() Messages : 4017 GCPoints : 347288 |
Probleme reglé^^ Pour ce qui est de l'architecture, celle que je code est différente : il y a une classe qui contient les murs, et une classe qui définit les entités (joueurs); les collisions sont gérées par les entités, c'est globalement assez simple. |
|
| Syltech |
Posté le 09 Jan 2009 à 15:34
|
|
![]() Messages : 282 GCPoints : 71266 |
Oui, j'imagine en gros comment ça marche. Rha je suis vraiment dégouté de pas pouvoir me plonger a fond dedans... vivement la fin d'étude Syltech ![]() |
|
| Darktib |
Posté le 09 Jan 2009 à 16:25
|
|
![]() Messages : 4017 GCPoints : 347288 |
Ca avance encore, j'ai par contre une question niveau logique : pour les collisions tu utilise les deux murs les plus proches si j'ai bien compris (nwall_a et nwall_b)? |
|
| Syltech |
Posté le 09 Jan 2009 à 16:45
|
|
![]() Messages : 282 GCPoints : 71266 |
Oui, c'est exactement ça! Je récupère les numéro des 2 murs les plus proches, si le joueur est en collision avec le mur_a, on renvoi au joueur la normal du mur_a. Puis on test si le mur_b est en collision(seulement si le joueur est en cour de collision avec le mur_a), si c'est le cas, on renvoi au joueur les anciennes positions, ainsi que la normal du mur_b. C'est principalement ce qui permet au joueur de ne pas trembler dans un coin, sinon dans un coin il testerait un mur puis l'autre, et ça en boucle tant qu'on avance dans un coin. Syltech
Dernière édition le 09 Jan 2009 à 16:47
![]() |
|
| bebou007 |
Posté le 09 Jan 2009 à 17:54
|
|
![]() Messages : 238 GCPoints : 43228 |
salut se systeme de collision a l'ai pas mal par contre le joueur doit etre un cercle. j'ai cherche des tutorial sur les collision par polygone par contre je capte rien et j'ai trouver aucun tutorial bien expliquer |
|
| Darktib |
Posté le 09 Jan 2009 à 20:25
|
|
![]() Messages : 4017 GCPoints : 347288 |
Le probleme c'est que gérer en cercle et gérer en polygone c'est completement différent : en cercle il suffit d'avoir un centre et son rayon, alors qu'avec les polygones il faut la liste des points du polygone... Sinon pour l'instant, sans joueur no gestion de collision j'en suis a 3000 fps sur un Pentium D 830, Geforce 6800 LE(256Mo DDR3), 3 Go DDR2, WinXP (et avec DirectX) edit : encore avancé, j'ai maintenant codé toutes les fonctions qui vont me servir, il ne me reste plus qu'a faires les collisions en tant que tel (Et le fps est descendu a 1600, mais pour l'instant je ne cherche pas a optimiser). edit2 : optimisations mathématiques : testA > 0 && testB > 0 est équivalent a testA*testB >0, et ainsi de suite pour les autres tests.
Dernière édition le 09 Jan 2009 à 23:17
|
|
| bebou007 |
Posté le 09 Jan 2009 à 23:53
|
|
![]() Messages : 238 GCPoints : 43228 |
resalut a tous voila j'ai trouver que pour faire des teste sur les collision il manquer un éditeur c'est pour quoi j'ai ajouter un éditeur de mur voici le code Code : set display mode 1024,768,32,1
sync on
Type v2d
ox as float
oy as float
dx as float
dy as float
lx as float
ly as float
l2 as float
l as float
cx1 as float
cy1 as float
cx2 as float
cy2 as float
EndType
Global nWall_nombre as integer : nWall_nombre=0
Global nWall_max as integer : nWall_max=50
Dim wallmap(nWall_max) as v2d
Global wallx as float
Global wally as float
Global Dist as float
Global nx as float
Global ny as float
Global nWall_A as integer
Global nWall_B as integer
testA as integer
testB as integer
Global taille as integer : taille=30
vitesse as integer : vitesse=8
oldx as float : Joueur_x as float : Joueur_x=125
oldy as float : Joueur_y as float : Joueur_y=0
Wall as v2d
rem pour stocke depart click souris
departx as integer : departx=0
departy as integer : departy=0
finx as integer : finx=0
finy as integer : finy=0
do
cls
Gosub Deplacements
if keystate(18)=1
if stop=0
if edit=0
edit=1
stop=1
else
edit=0
stop=1
endif
endif
endif
if keystate(18)=0
stop=0
endif
if edit=1
if mouseclick()=1
if stop1=0
if departx=0
departx=mousex()
departy=mousey()
stop1=1
endif
endif
endif
if mouseclick()=1
if stop1=0
if departx<>0
finx=mousex()
finy=mousey()
stop1=1
endif
endif
endif
if departx<>0
line departx,departy,mousex(),mousey()
endif
if mouseclick()=0
if stop1=1
stop1=0
endif
endif
if mouseclick()=0
if departx<>0
if finx<>0
add_mur(departx,departy,finx,finy)
departx=0
departy=0
finx=0
finy=0
endif
endif
endif
endif
mur_le_plus_proche(Joueur_x,Joueur_y)
wall=wallmap(nWall_A)
calcul_vectoriel(Joueur_x,Joueur_y,wall)
CoeficientDirecteurInv(Joueur_x,Joueur_y,wallx,wally)
if abs(dist)<=taille
hit=1
Joueur_x=wallx+nx : Joueur_y=wally+ny
testA=isUnder(Joueur_x,Joueur_y,Wall) : wall=wallmap(nWall_B) : testB=isUnder(Joueur_x,Joueur_y,Wall)
if ((testA>0 && testB>0) || (testA<0 && testB<0)) || ((testA<0 && testB>0) || (testA>0
&& testB<0) && ((wallmap(nWall_A).ox<>wallmap(nWall_B).dx && wallmap(nWall_A).oy<>wallmap(nWall_B).dx)))
if abs(testB)<=taille
Joueur_x=oldx
Joueur_y=oldy
calcul_vectoriel(Joueur_x,Joueur_y,wall)
CoeficientDirecteurInv(Joueur_x,Joueur_y,wallx,wally)
Joueur_x=wallx+nx : Joueur_y=wally+ny
endif
endif
else
hit=0
endif
Gosub Affichage
sync
loop
Deplacements:
if edit=0
oldx=Joueur_x : oldy=Joueur_y
if leftkey()=1 : a=a+3 : endif
if rightkey()=1 : a=a-3 : endif
if upkey()=1
Joueur_x=Joueur_x+cos(a)*vitesse
Joueur_y=Joueur_y-sin(a)*vitesse
endif
if downkey()=1
Joueur_x=Joueur_x+cos(a)*((vitesse*-1)/2)
Joueur_y=Joueur_y-sin(a)*((vitesse*-1)/2)
endif
endif
Return
Affichage:
if edit=0
circle Joueur_x,Joueur_y,taille
line Joueur_x,Joueur_y,Joueur_x+cos(a)*taille,Joueur_y-sin(a)*taille
endif
text 0,0,"FPS : "+str$(screen fps())
text 0,14,"Hit : "+str$(hit)
text 0,28, str$(edit)
Return
function calcul_vectoriel(x as float, y as float, Wall as v2d)
coef as float
coef = ((x-Wall.ox)*Wall.lx + (y-Wall.oy)*Wall.ly) / Wall.l2
wallx = Wall.ox + Wall.lx*coef
wally = Wall.oy + Wall.ly*coef
if (wallx=>Wall.cx1 && wally=>Wall.cy1 && wallx<=Wall.cx2 && wally<=Wall.cy2)
dist = ((x-Wall.ox)*Wall.ly - (y-Wall.oy)*Wall.lx) / Wall.l
else
if distance(x,y,Wall.ox,Wall.oy)<distance(x,y,Wall.dx,Wall.dy)
wallx = Wall.ox
wally = Wall.oy
dist = distance(x,y,Wall.ox,Wall.oy)
else
wallx = Wall.dx
wally = Wall.dy
dist = distance(x,y,Wall.dx,Wall.dy)
endif
endif
endfunction
function distance_vectoriel(x as float, y as float, Wall as v2d)
vDist as float
coef as float
coef = ((x-Wall.ox)*Wall.lx + (y-Wall.oy)*Wall.ly) / Wall.l2
wx = Wall.ox + Wall.lx*coef
wy = Wall.oy + Wall.ly*coef
if (wx=>Wall.cx1 && wy=>Wall.cy1 && wx<=Wall.cx2 && wy<=Wall.cy2)
vDist = ((x-Wall.ox)*Wall.ly - (y-Wall.oy)*Wall.lx) / Wall.l
else
if distance(x,y,Wall.ox,Wall.oy)<distance(x,y,Wall.dx,Wall.dy)
vDist = distance(x,y,Wall.ox,Wall.oy)
else
vDist = distance(x,y,Wall.dx,Wall.dy)
endif
endif
endfunction vDist
function mur_le_plus_proche(x as float,y as float)
Distance as float : wall as v2d
rayon_A as float : rayon_B as float
rayon_A=9999 : rayon_B=9999
for i=0 to nWall_nombre-1 : wall=wallmap(i)
Distance=abs(distance_vectoriel(x, y, wall))
if Distance<rayon_A
nWall_B=nWall_A
rayon_B=rayon_A
nWall_A=i
rayon_A=Distance
else
if Distance<rayon_B
nWall_B=i
rayon_B=Distance
endif
endif
draw(i)
next i
endfunction
function distance(x1 as float, y1 as float, x2 as float, y2 as float)
result as float : result = sqrt((x2-x1)^2+(y2-y1)^2)
endfunction result
function CoeficientDirecteurInv(x1 as float, y1 as float, x2 as float, y2 as float)
Normalex as float : Normaley as float : MagnitudeInv as float
Normalex=x1-x2
Normaley=y1-y2
MagnitudeInv = Taille / Sqrt(Normalex^2+Normaley^2)
nx=Normalex * MagnitudeInv: ny=Normaley * MagnitudeInv
endfunction
function isUnder(x as float, y as float, Wall as v2d)
coef as float : wx as float : wy as float : vDist as integer
coef = ((x-Wall.ox)*Wall.lx + (y-Wall.oy)*Wall.ly) / Wall.l2
wx = Wall.ox + Wall.lx*coef
wy = Wall.oy + Wall.ly*coef
if (wx=>Wall.cx1 && wy=>Wall.cy1 && wx<=Wall.cx2 && wy<=Wall.cy2)
vDist = ((x-Wall.ox)*Wall.ly - (y-Wall.oy)*Wall.lx) / wall.l
endif
endfunction vDist
function draw(nWall as integer)
line wallmap(nWall).ox,wallmap(nWall).oy,wallmap(nWall).dx,wallmap(nWall).dy
endfunction
function limite(nWall)
if wallmap(nWall).ox<wallmap(nWall).dx
wallmap(nWall).cx1=wallmap(nWall).ox
wallmap(nWall).cx2=wallmap(nWall).dx
else
wallmap(nWall).cx1=wallmap(nWall).dx
wallmap(nWall).cx2=wallmap(nWall).ox
endif
if wallmap(nWall).oy<wallmap(nWall).dy
wallmap(nWall).cy1=wallmap(nWall).oy
wallmap(nWall).cy2=wallmap(nWall).dy
else
wallmap(nWall).cy1=wallmap(nWall).dy
wallmap(nWall).cy2=wallmap(nWall).oy
endif
endfunction
function add_mur(posx1,posy1,posx2,posy2)
for x=0 to nWall_max-1
if wallmap(x).l=0
exit
endif
next x
wallmap(x).ox=posx1
wallmap(x).oy=posy1
wallmap(x).dx=posx2
wallmap(x).dy=posy2
wallmap(x).lx=wallmap(x).dx-wallmap(x).ox
wallmap(x).ly=wallmap(x).dy-wallmap(x).oy
wallmap(x).l2=wallmap(x).lx^2+wallmap(x).ly^2
wallmap(x).l=sqrt(wallmap(x).l2)
limite(x)
nWall_nombre=nWall_nombre+1
if nWall_nombre>nWall_max
nWall_nombre=nWall_max
endif
endfunction xappuyer sur "e" pour entre dans l'éditeur un premier clic pour le premier point et encore un clic pour le deuxième point puis "e" pour sortir dans le code nWall_max pour le nombre max que l'on peut faire de mur j'ai aussi remarquer que une vitesse de 50 le joueur passe a travers le mur
Dernière édition le 10 Jan 2009 à 00:03
|
|
| Darktib |
Posté le 10 Jan 2009 à 00:17
|
|
![]() Messages : 4017 GCPoints : 347288 |
Sympa l'éditeur, vraiment tres pratique! Par contre j'ai remarqué qu'on ne peut pas avancer quand ils n'y a pas de murs... Sinon pour l'instant le code C++ est 100% fonctionnel, j'ai juste viré une grosse partie des tests de collisions (testA et testB, ce qui fait qu'il oscille maintenant, mais je pense que ca sera bientot reglé. J'avais des problemes au début, mais qui étaient dus au fait que je n'utilise que des distances au carré. |
|
| bebou007 |
Posté le 10 Jan 2009 à 00:46
|
|
![]() Messages : 238 GCPoints : 43228 |
oui on peut pas avancer sans mur je sais pas de ou sa vient a parament comme il y a pas de mur le plus proche renvoyer et sa doit planter de la car il y a hit sur 1 serait il possible d'avoir le code c++ ou une lib pour tester en c++
Dernière édition le 10 Jan 2009 à 00:48
|
|
| Darktib |
Posté le 10 Jan 2009 à 11:55
|
|
![]() Messages : 4017 GCPoints : 347288 |
No prob' Par contre je le posterai dans la section C++ |
|
| bebou007 |
Posté le 10 Jan 2009 à 12:43
|
|
![]() Messages : 238 GCPoints : 43228 |
ok merci par contre j'ai rencontre certain bug sur les collision (tremblement,ne glisse pas a certain endroits) par example ici je bloque et ici je tremble |
|
| Darktib |
Posté le 10 Jan 2009 à 12:49
|
|
![]() Messages : 4017 GCPoints : 347288 |
Pour les tremblements, c'est du au fait qu'on ne vérifie qu'un mur. C'est bizarre, vu qu'en dbp ce code vérifie deux murs... Pour l'autre, que veut dire le 'il bloque' : il s'arrete la, ou il se bloque indéfiniment a cet endroit (impossible de le faire bouger ailleurs)? |
|
| bebou007 |
Posté le 10 Jan 2009 à 13:00
|
|
![]() Messages : 238 GCPoints : 43228 |
ben le tremblement non il vérifie bien les 2 mur pour le bloquage en fait on peut sortir mais il glisse pas contre le petit mur qui dépasse |
|
| Syltech |
Posté le 11 Jan 2009 à 21:23
|
|
![]() Messages : 282 GCPoints : 71266 |
Hello! Sympa de voir que ça a avancé! :) Deja, Bravo Darktib pour l'optimisation testA*testB>0 et sympa ce petit éditeur Bebou007! Pour la vitesse à 50 qui fait traversé les murs, c'est normal, c'est que si la vitesse est plus grande que la taille du joueur ça traverse et c'est tout à fait logique, imagine le cercle avancer de 50 alors que ça taille n'est que de 30, le test de collision ce fait de l'autre coté du mur. Il y a des façons pour remédié à ce problème, Graphiboc en a parlé d'ailleurs, de faire plusieurs test de collision entre une position initial et la prochaine position du joueur, évidement ça demande plus de calculs... Pour le tremblement que tu as découvert Bebou007, Bravo c'est un nouveau bug! Ça me fait donc un cas particulier supplémentaire à corriger! Le truc dans ce cas particulier, c'est que si le morceau de mur qui dépasse est inférieur au rayon du cercle, alors il y a tremblement. Je vais m'amuser à corrigé celui la je pense lol, m'enfin quand y faut y faut ^^ Syltech ![]() |
|
| Syltech |
Posté le 11 Fév 2009 à 20:08
|
|
![]() Messages : 282 GCPoints : 71266 |
Comme je l'ai expliqué dans mon sujet sur la collision cercle contre cercle : Citation :
Je vous conseille de modifier les fonctions qui utilisent le symbole "^" pour la puissance. Voici les fonctions corrigées : Code : function calcul_vectoriel(x as float, y as float, Wall as v2d)
coef as float : t as float
coef = (x-Wall.ox)*Wall.lx+(y-Wall.oy)*Wall.ly
t = coef/(Wall.lx*Wall.lx+ Wall.ly*Wall.ly)
if t>=0 && t<=1
wallx = Wall.ox + t*Wall.lx
wally = Wall.oy + t*Wall.ly
dist = distance(x,y,wallx,wally)
else
if t<0
wallx = Wall.ox
wally = Wall.oy
dist = distance(x,y,Wall.ox,Wall.oy)
endif
if t>1
wallx = Wall.dx
wally = Wall.dy
dist = distance(x,y,Wall.dx,Wall.dy)
endif
endif
endfunctionCode : function distance_vectoriel(x as float, y as float, Wall as v2d)
coef as float : t as float : vdist as float : wx as float : wy as float
coef = (x-Wall.ox)*Wall.lx+(y-Wall.oy)*Wall.ly
t = coef/(Wall.lx*Wall.lx+ Wall.ly*Wall.ly)
if t>=0 && t<=1
wx = Wall.ox + t*Wall.lx
wy = Wall.oy + t*Wall.ly
vdist = distance(x,y,wx,wy)
else
if t<0
vdist = distance(x,y,Wall.ox,Wall.oy)
endif
if t>1
vdist = distance(x,y,Wall.dx,Wall.dy)
endif
endif
endfunction vdistCode : function distance(x1 as float, y1 as float, x2 as float, y2 as float) result as float : result = sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1)) endfunction result Code : function CoeficientDirecteurInv(x1 as float, y1 as float, x2 as float, y2 as float) Normalex as float : Normaley as float : MagnitudeInv as float Normalex=x1-x2 Normaley=y1-y2 MagnitudeInv = Taille / Sqrt(Normalex*Normalex+Normaley*Normaley) nx=Normalex * MagnitudeInv: ny=Normaley * MagnitudeInv endfunction Code : function isUnder(x as float, y as float, Wall as v2d)
coef as float : t as float : vdist as float
coef = (x-Wall.ox)*Wall.lx + (y-Wall.oy)*Wall.ly
t = coef/(Wall.lx*Wall.lx + Wall.ly*Wall.ly)
if t>=0 && t<=1
vDist = ((x-Wall.ox)*Wall.ly - (y-Wall.oy)*Wall.lx) / wall.l
endif
endfunction vDistVoila ! Je pense avoir fait le tour ! Syltech Edit : J'ai mis mon tout premier message à jour pour les personnes qui découvriraient mon code, c'est propre, c'est clair et mon code est à jour !
Dernière édition le 12 Fév 2009 à 10:41
![]() |
|
GameCorp - Index des forumsGame MakingProgrammationDark Basic - DarkGDK[DarkBasic] Moteur de collision 2D
Répondre
Page précédente



