FORUM DE DISCUSSION SUR LE LANGAGE PANORAMIC
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.
FORUM DE DISCUSSION SUR LE LANGAGE PANORAMIC

Développement d'applications avec le langage Panoramic
 
AccueilAccueil  RechercherRechercher  Dernières imagesDernières images  S'enregistrerS'enregistrer  MembresMembres  Connexion  
Derniers sujets
» Form(résolu)
Gestion de collisions entre sprites en 2D Emptypar leclode Hier à 17:59

» trop de fichiers en cours
Gestion de collisions entre sprites en 2D Emptypar Marc Hier à 11:42

» Bataille navale SM
Gestion de collisions entre sprites en 2D Emptypar jjn4 Ven 26 Avr 2024 - 17:39

» Une calculatrice en une ligne de programme
Gestion de collisions entre sprites en 2D Emptypar jean_debord Ven 26 Avr 2024 - 8:01

» Gestion d'un système client-serveur.
Gestion de collisions entre sprites en 2D Emptypar Pedro Jeu 25 Avr 2024 - 19:31

» Les maths du crocodile
Gestion de collisions entre sprites en 2D Emptypar jean_debord Jeu 25 Avr 2024 - 10:37

» Naissance de Crocodile Basic
Gestion de collisions entre sprites en 2D Emptypar jean_debord Jeu 25 Avr 2024 - 8:45

» Editeur EliP 6 : Le Tiny éditeur avec 25 onglets de travail
Gestion de collisions entre sprites en 2D Emptypar Froggy One Mer 24 Avr 2024 - 18:38

» Dessine-moi une galaxie
Gestion de collisions entre sprites en 2D Emptypar jjn4 Lun 22 Avr 2024 - 13:47

» Erreur END_SUB
Gestion de collisions entre sprites en 2D Emptypar jjn4 Lun 22 Avr 2024 - 13:43

» Bug sur DIM_LOCAL ?
Gestion de collisions entre sprites en 2D Emptypar papydall Dim 21 Avr 2024 - 23:30

» 2D_fill_color(résolu)
Gestion de collisions entre sprites en 2D Emptypar leclode Sam 20 Avr 2024 - 8:32

» Consommation gaz électricité
Gestion de collisions entre sprites en 2D Emptypar leclode Mer 17 Avr 2024 - 11:07

» on_key_down (résolu)
Gestion de collisions entre sprites en 2D Emptypar leclode Mar 16 Avr 2024 - 11:01

» Sous-programme(résolu)
Gestion de collisions entre sprites en 2D Emptypar jjn4 Jeu 4 Avr 2024 - 14:42

Navigation
 Portail
 Index
 Membres
 Profil
 FAQ
 Rechercher
Rechercher
 
 

Résultats par :
 
Rechercher Recherche avancée
Avril 2024
LunMarMerJeuVenSamDim
1234567
891011121314
15161718192021
22232425262728
2930     
CalendrierCalendrier
Le Deal du moment : -21%
LEGO® Icons 10329 Les Plantes Miniatures, ...
Voir le deal
39.59 €

 

 Gestion de collisions entre sprites en 2D

Aller en bas 
4 participants
Aller à la page : 1, 2  Suivant
AuteurMessage
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyVen 19 Oct 2012 - 22:55

Suite à un échange de messages privés, je publie ici le résultat: un exemple de la gestion de collision entre sprites dans une scene2D.

Remarques:

1. comme la commande COLOR ne fonctionne pas pour le moment pour une scene2d, je contourne le problème avec un picture qui sera coloré, sauvegardé dans un fichier BMP puis supprimé. Ce fichier sera ensuite chargé dans la scene2d comme couleur de fond. Et tant qu'on y est, on emploie la même astuce pour colorer les sprites.

2. la notion même de collusion entre sprites est vague. Un sprite est un rectangle, au départ de 200x200. Il peut être redimensionné par les commandes SCALE, dans une ou deux directions, pour obtenir des rectangles de tailles variés. Mais cela reste des rectangles. La collision entre rectangles se résume au fait que le haut de l'un touche le bas de l'autre ou inversement, ou que la gauche de l'un touche la droite de l'autre ou inversement. Dans l'exemple qui suit, j'ai fait exactement cela. Et bien que mes sprites soient des carrés, les formules sont réellement faites pour des rectangles, en respectant les largeurs et hauteurs.

3. un sprite peut recevoir une image par un fichier BMP dont la oouleur noire (RGB=0,0,0) sera traité comme couleur transparente (ces pixels ne sont tout simplement pas affichés). Maintenant, que veut dire "collision" pour un tel sprité ? Qu'un pixel non-noir d'un sprite touche un pixel non-noir d'un autre sprite ? Très complexe. Malheureusement, nous n'avons pas de moyen simple de faire cela en Panoramic.

Donc, on revient à l'idée de la collusion entre 2 rectangles, et voici le code (Panoramic V0.9.24i4):
Code:
' collisions_en_scene2d.bas

dim i%, choc%
dim larg1%, haut1%, larg2%, haut2%

picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
  color 100,255,0,0 : file_save 100,"sprite_2.bmp"
delete 100

picture 100 : full_space 100 : color 100,220,220,220
file_save 100,"vide_2D.bmp"
delete 100

scene2d 100 : full_space 100 : file_load 100,"vide_2d.bmp" : file_delete "vide_2d.bmp"

sprite 1 : sprite_file_load 1,"sprite_1.bmp" : file_delete "sprite_1.bmp"
  sprite_position 1,10,100 : sprite_scale 1,1/4,1/4
  larg1% = 200/4 : haut1% = 200/4
sprite 2 : sprite_file_load 2,"sprite_2.bmp" : file_delete "sprite_2.bmp"
  sprite_position 2,300,150 : sprite_scale 2,1/3,1/3
  larg2% = int(200/3+0.5) : haut2% = int(200/3+0.5)

for i%=10 to 400
  sprite_position 1,i%,10+int(140*i%/400)
  collision(1,2)
  if choc%=1
    message "Collision !"
    exit_for
  end_if
  pause 10
next i%

end

sub collision(s1%,s2%)
  dim_local x1%,y1%,  x2%,y2%
  choc% = 1
  x1% = sprite_x_position(1)
  y1% = sprite_y_position(1)
  x2% = sprite_x_position(2)
  y2% = sprite_y_position(2)
  ' le bas du sprite 1 touche le haut du sprite 2
  if (y1%+haut1%-1)=y2%
    if (x1%<=x2%) and ((x1%+larg1%-1)>x2%) then exit_sub
    if (x1%>x2%) and (x1%<=(x2%+larg2%-1)) then exit_sub
  end_if
  ' le haut du sprite 1 touche le bas du sprite 2
  if y1%=(y2%+haut2%-1)
    if (x1%<=x2%) and ((x1%+larg1%-1)>x2%) then exit_sub
    if (x1%>x2%) and (x1%<=(x2%+larg2%-1)) then exit_sub
  end_if
  ' la gauche du sprite 1 touche la droite du sprite 2
  if (x1%+larg1%-1)=x2%
    if (y1%<=y2%) and ((y1%+haut1%-1)>y2%) then exit_sub
    if (y1%>y2%) and (y1%<=(y2%+haut2%-1)) then exit_sub
  end_if
  ' la droite du sprite 1 touche la gauche du sprite 2
  if x1%=(x2%+larg2%-1)
    if (y1%<=y2%) and ((y1%+haut1%-1)>y2%) then exit_sub
    if (y1%>y2%) and (y1%<=(y2%+haut2%-1)) then exit_sub
  end_if
  choc% = 0
end_sub

J'espère que cela vous inspirera. J'avais posté un exemple de collusion 3D dans un autre fil de discussion...


Dernière édition par Klaus le Sam 20 Oct 2012 - 10:59, édité 1 fois
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 0:23

Je me suis permis de modifier un peu l'exemple de Klaus et de rajouter quelques commentaires, le principe de la collision utilisé est le recouvrement et non le touché du sprite. Tout simplement par ce qu'il peut y avoir un "pas" qui fait que le bord du sprite 1 ne touche jamais l'un des bord du sprite2 mais se retrouve directement "dedans" en fonction du pas de déplacement choisi.
Ca donne ça:
Pour la procédure, j'aurais voulu éviter de mettre la taille des sprites, mais width(sprite1) et height(sprite1) ne semblent pas fonctionner, du coup ils sont passés en paramètres
Code:
' collisions_en_scene2d.bas

dim i%, choc%,d_choc%

' Création des 2 sprites de test
picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
  color 100,255,0,0 : file_save 100,"sprite_2.bmp"

' Création d'une image vide pour le fond
full_space 100 : color 100,220,220,220 :file_save 100,"vide_2D.bmp": delete 100

' Creation de l'air de déplacement des sprites
scene2d 100 : full_space 100 : file_load 100,"vide_2d.bmp"

' Création et chargement des sprites
sprite 1 : sprite_file_load 1,"sprite_1.bmp" : sprite_position 1,10,100  : sprite_scale 1,1/4,1/4
sprite 2 : sprite_file_load 2,"sprite_2.bmp" : sprite_position 2,300,150 : sprite_scale 2,1/3,1/3

' Boucle de déplacement quelconque
for i%=10 to 4000
  sprite_position 1,i%,10+int(140*i%/400) : ' On bouge le sprite
  collision(1,50,50,2,66,66)              : ' On teste la collision su sprite1 et du sprite 2
                                          : ' Paramètres N°sprite, Largeur, hauteur et pareil pour le second
  if choc%=1                              : ' Si la procédure retourne qu'il y a collision
    message "Collision !"                : ' on traite l'événement (on pourrait changer le sens, supprimer un sprite, ...
    exit_for                              : ' Ici on affiche un message et on sort de la boucle
  end_if
  pause 5                                : ' Attente avant déplacement du sprite
next i%

end

sub collision(s1%,larg1%,haut1%,s2%,larg2%,haut2%)
  dim_local x1%,y1%, x2%,y2%
  x1% = sprite_x_position(s1%): y1% = sprite_y_position(s1%)
  x2% = sprite_x_position(s2%): y2% = sprite_y_position(s2%)
  ' le bas du sprite 1 touche le haut du sprite 2
  if (((y1%+haut1%) >= y2%) and (y1% <= (y2%+haut2%)) and ((x1%+larg1%) >= x2%)  and (x1% <= (x2%+larg2%)))
          choc% = 1 : ' Si le rectangle du sprite 1 recouvre partiellement celui du sprite 2, il y a collision
        else
          choc% = 0 : ' Sinon, on retourne qu'ils ne se touchent pas
  end_if
end_sub
Revenir en haut Aller en bas
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 0:32

Merci, Jicehel. Voici un autre exemple sur lequel tu peux t'exercer: je fais bouger les deux sprites avec des vitesses verticales et horizontales différentes, et le programme s'arrête lorsqu'ils se touchent.
Code:
' collisions_en_scene2d.bas

caption 0,"Interrompre par Echap"

dim i%, choc%
dim larg%(2), haut%(2)
dim delta_x%(2), delta_y%(2)
dim dir_x%(2), dir_y%(2)

delta_x%(1) = 2 : delta_y%(1) = 4
delta_x%(2) = 2 : delta_y%(2) = 1
dir_x%(1) = 1 : dir_y%(1) = 1
dir_x%(2) = 1 : dir_y%(2) = 1

picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
  color 100,255,0,0 : file_save 100,"sprite_2.bmp"
delete 100

picture 100 : full_space 100 : color 100,220,220,220
file_save 100,"vide_2D.bmp"
delete 100

scene2d 100 : full_space 100 : file_load 100,"vide_2d.bmp" : file_delete "vide_2D.bmp"

sprite 1 : sprite_file_load 1,"sprite_1.bmp" : file_delete "sprite_1.bmp"
  sprite_position 1,10,100 : sprite_scale 1,1/4,1/4
  larg%(1) = 200/4 : haut%(1) = 200/4
sprite 2 : sprite_file_load 2,"sprite_2.bmp" : file_delete "sprite_2.bmp"
  sprite_position 2,300,150 : sprite_scale 2,1/3,1/3
  larg%(2) = int(200/3+0.5) : haut%(2) = int(200/3+0.5)

repeat
  move(1)
  if choc%=0 then move(2)
  pause 5
until (choc%=1) or scancode=27

end

sub move(s%)
  dim_local i%
  ' déplacer horizontalement
  if dir_x%(s%)>0 : ' à droite
    if (sprite_x_position(s%)+larg%(s%)-1)>=(width(100)-1)
      dir_x%(s%) = 0 - dir_x%(s%)
    end_if
  else              : ' à gauche
    if sprite_x_position(s%)<=0
      dir_x%(s%) = 0 - dir_x%(s%)
    end_if
  end_if
  for i%=1 to delta_x%(s%)
    sprite_x_position s%,sprite_x_position(s%) + dir_x%(s%)
    collision(1,2)
    if choc%=1 then exit_sub
  next i%
  ' déplacer verticalement
  if dir_y%(s%)>0 : ' en bas
    if (sprite_y_position(s%)+haut%(s%)-1)>=(height(100)-1)
      dir_y%(s%) = 0 - dir_y%(s%)
    end_if
  else              : ' en haut
    if sprite_y_position(s%)<=0
      dir_y%(s%) = 0 - dir_y%(s%)
    end_if
  end_if
  for i%=1 to delta_y%(s%)
    sprite_y_position s%,sprite_y_position(s%) + dir_y%(s%)
    collision(1,2)
    if choc%=1 then exit_sub
  next i%
end_sub

sub collision(s1%,s2%)
  dim_local x1%,y1%,  x2%,y2%
  choc% = 1
  x1% = sprite_x_position(s1%)
  y1% = sprite_y_position(s1%)
  x2% = sprite_x_position(s2%)
  y2% = sprite_y_position(s2%)
  ' le bas du sprite 1 touche le haut du sprite 2
  if (y1%+haut%(1)-1)=y2%
    if (x1%<=x2%) and ((x1%+larg%(1)-1)>x2%) then exit_sub
    if (x1%>x2%) and (x1%<=(x2%+larg%(2)-1)) then exit_sub
  end_if
  ' le haut du sprite 1 touche le bas du sprite 2
  if y1%=(y2%+haut%(2)-1)
    if (x1%<=x2%) and ((x1%+larg%(1)-1)>x2%) then exit_sub
    if (x1%>x2%) and (x1%<=(x2%+larg%(2)-1)) then exit_sub
  end_if
  ' la droite du sprite 1 touche la gauche du sprite 2
  if (x1%+larg%(1)-1)=x2%
    if (y1%<=y2%) and ((y1%+haut%(1)-1)>y2%) then exit_sub
    if (y1%>y2%) and (y1%<=(y2%+haut%(2)-1)) then exit_sub
  end_if
  ' la gauche du sprite 1 touche la droite du sprite 2
  if x1%=(x2%+larg%(2)-1)
    if (y1%<=y2%) and ((y1%+haut%(1)-1)>y2%) then exit_sub
    if (y1%>y2%) and (y1%<=(y2%+haut%(2)-1)) then exit_sub
  end_if
  choc% = 0
end_sub



Dernière édition par Klaus le Sam 20 Oct 2012 - 10:58, édité 2 fois
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 1:43

Encore une variante du programme de Klaus, la collision entre les 2 sprites fait changer le sens des 2 sprites, mais il faudrait tester comment s'effectue la colilsion pour n'inverser le mouvement que dans certaines directions en fonction du sens de la collision. mais bon il est tard et c'est l'heure d'aller dormir ...
Bonne nuit
Code:
' collisions_en_scene2d.bas

caption 0,"Interrompre par Echap"

dim i%, choc%
dim larg%(2), haut%(2)
dim delta_x%(2), delta_y%(2)
dim dir_x%(2), dir_y%(2)

delta_x%(1) = 2 : delta_y%(1) = 4 : delta_x%(2) = 2 : delta_y%(2) = 1
dir_x%(1) = 1 : dir_y%(1) = 1 : dir_x%(2) = 1 : dir_y%(2) = 1

' Création des 2 sprites de test
picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
  color 100,255,0,0 : file_save 100,"sprite_2.bmp"

' Création d'une image vide pour le fond
full_space 100 : color 100,220,220,220 :file_save 100,"vide_2D.bmp": delete 100

' Creation de l'air de déplacement des sprites
scene2d 100 : full_space 100 : file_load 100,"vide_2d.bmp"

' Création et chargement des 2 sprites
sprite 1 : sprite_file_load 1,"sprite_1.bmp"
  sprite_position 1,10,100  : sprite_scale 1,1/4,1/4 : larg%(1) = 200/4 : haut%(1) = 200/4
sprite 2 : sprite_file_load 2,"sprite_2.bmp"
  sprite_position 2,300,150 : sprite_scale 2,1/3,1/3 : larg%(2) = int((200/3)+0.5) : haut%(2) = int((200/3)+0.5)

' Boucle de déplacement
repeat
  move(1,2)
  move(2,1)
  pause 5
until scancode=27

end

' Procédure de déplacement
sub move(s1%,s2%)
  dim_local i%, delta%
  ' déplacer horizontalement
  if dir_x%(s1%)>0 : ' à droite
    if (sprite_x_position(s1%)+larg%(s1%))>=(width(100))
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  else              : ' à gauche
    if sprite_x_position(s1%)<=0
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  end_if
  ' déplacer verticalement
  if dir_y%(s1%)>0 : ' en bas
    if (sprite_y_position(s1%)+haut%(s1%))>=(height(100))
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  else              : ' en haut
    if sprite_y_position(s1%)<=0
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  end_if
  if abs(delta_x%(s1%))> abs(delta_y%(s1%))
    delta%=abs(delta_x%(s1%))
  else
    delta%=abs(delta_y%(s1%))
  end_if
 
  for i%=0 to delta%
    sprite_position s1%,sprite_x_position(s1%) + dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%)),sprite_y_position(s1%) + dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
    collision(s1%,s2%)
    if choc%=1 then exit_for
  next i%
  if choc%=1 then change_dir(s1%,s2%)
  for i%=0 to delta%
    sprite_position s1%,sprite_x_position(s1%) + dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%)),sprite_y_position(s1%) + dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
  next i%
end_sub

sub change_dir(s1%,s2%)
  dir_x%(s1%) = 0-dir_x%(s1%): dir_y%(s1%) = 0-dir_y%(s1%)
  dir_x%(s2%) = 0-dir_x%(s2%): dir_y%(s2%) = 0-dir_y%(s2%)
end_sub

sub collision(s1%,s2%)
  dim_local x1%,y1%, x2%,y2%
  x1% = sprite_x_position(s1%): y1% = sprite_y_position(s1%)
  x2% = sprite_x_position(s2%): y2% = sprite_y_position(s2%)
  ' le bas du sprite 1 touche le haut du sprite 2
  if (((y1%+haut%(1)) >= y2%) and (y1% <= (y2%+haut%(2))) and ((x1%+larg%(1)) >= x2%)  and (x1% <= (x2%+larg%(2))))
          choc% = 1 : ' Si le rectangle du sprite 1 recouvre partiellement celui du sprite 2, il y a collision
        else
          choc% = 0 : ' Sinon, on retourne qu'ils ne se touchent pas
  end_if
end_sub
Revenir en haut Aller en bas
Nardo26

Nardo26


Nombre de messages : 2294
Age : 55
Localisation : Valence
Date d'inscription : 02/07/2010

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 10:44

Juste une petite remarque en passant que j'ai déjà faite à ygeronimi :

Vos programme génèrent des fichier, ok... c'est nécessaire Smile

mais quand le programme se termine, cela serait bien de faire le ménage... Wink)

Car ça devient vite un foutoir sur les disques !!! Gestion de collisions entre sprites en 2D 10
Revenir en haut Aller en bas
http://nardo26.lescigales.org
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 10:59

Tu as raison, Nardo26. J'ai corrigé mes modules dans ce sens.
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 13:05

Klaus dans mon programme d'hier, je ne sais pas ce que tu en penses, mais l'idée dans la boucle de déplacement c'est de faire les 2 mouvements en même temps pour ne pas avoir un déplacement en escalier (qui ne se voit pas avec des petites valeurs et une vitesse importante mais qui pourrait se voir avec un delta plus grand ou un déplacement plus lent).
Que penses tu de la méthode de déplacement Klaus ?
Revenir en haut Aller en bas
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 13:40

C'est ce que j'ai essayé de faire au début. Mais comme dans le cas général, les composantes horizontales et verticales du vecteur de déplacement ne sont pas identiques, il y a forcément une gymnastique à faire au niveau de la boucle de positionnement. Et même pire: si tu fais le déplacement d'un seul coup pour tester la collision après déplacement, le sprite en mouvement a probablement déjà dépassé la limite de l'autre sprite, et la détection de collision selon ma formule ne marche plus. Il faudrait alors sophistiquer les équations de critère de collision.

S'il y a des amateurs pour cela, tant mieux. Mon but était simplement de présenter les difficultés dans la gestion des collisions dans un scene2d et de montrer une possibilité de gesrion de ces collisions, suite à un échange par MP avec un panoramicien, et je voulais faire profiter tout le monde du résultat.

L'idéal serait bien sûr que Jack transpose la fonction 3d_collision à une fonction 2d_collision...

Ceci dit, j'ai une autre idée. Je n'ai pas essayé, mais on pourrait peut-être utiliser la scene3d avec des objets 3d_plane pour simuler les sprites. On laisserait les coordonnées z à zéro et on ne travaillerait que dans le plan x-y. Et du coup, on a une simulation de scene2d avec la collision gérée de façon native par Panoramic. Qu'est-ce que tu en penses ?
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 18:57

Je mets une variante fait vite fait, mais il y avait une grosse erreur dans mon précédent source Embarassed (des 1 et 2 étaient resté en fixe à la place de s1% et s2% dans les procédures ...)
Comme il y a plus de sprites, je trouve la démo plus visuelle et j'espère qu'elle reste simple d'accès.
Klaus et Nardo, j'ai repris le principe de Klaus pour nettoyer les images temporaire Wink
Vous avez raison puisque l'on fait un programme autonome, autant laisser la place propre après usage Wink
Les nouveaux, pourquoi ne faites vous pas de commentaire, c'est pour vous que Klaus a fait ce programme d'exemple. Est-ce que ça vous guide ? Est-ce que cela vous permet de comprendre les collisions ? Arrivez-vous à l'adapter à vos programmes ?

Code:
' collisions_en_scene2d.bas

caption 0,"Interrompre par Echap"

dim i%, choc%                    : ' i% compteur temporaire et choc% variable globale permettant de savoir s'il y a collision ou non
dim nb_sprites : nb_sprites = 15 : ' Constante indiquant le nombre de sprites utilisés
dim larg%(nb_sprites), haut%(nb_sprites) : ' tableau contenant les dimensions des sprites
dim delta_x%(nb_sprites), delta_y%(nb_sprites) : ' vitesses horizontales et verticales des sprites
dim dir_x%(nb_sprites), dir_y%(nb_sprites) : ' directions horizontales et verticales des sprites
dim c% : c% = 255/nb_sprites : ' diviseur pour le calcul des couleurs

' Initialisation du sprite 1
delta_x%(1) = 2 : delta_y%(1) = 2 : dir_x%(1) = 1 : dir_y%(1) = 1

' Initialisation des autres sprites
for i%=2 to nb_sprites
  delta_x%(i%) = 4 : delta_y%(i%) = 3
  dir_x%(i%) = 1 : dir_y%(i%) = 1
next i%

' Création des images pour les sprites de test
picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
for i%=2 to nb_sprites
  color 100,255 - i%*c%,i%*c%,0 : file_save 100,"sprite_"+str$(i%)+".bmp"
next i%

' Création d'une image vide pour le fond
full_space 100 : color 100,220,220,220 :file_save 100,"vide_2D.bmp": delete 100

' Creation de l'air de déplacement des sprites et supression du fond temporaire
scene2d 100 : hide 100 : full_space 100 : file_load 100,"vide_2d.bmp" : file_delete "vide_2D.bmp"

' Création et chargement des sprites et suppression des images temporaires
sprite 1 : sprite_file_load 1,"sprite_1.bmp" : file_delete "sprite_1.bmp"
sprite_position 1,180,120  : sprite_scale 1,1/4,1/4 : larg%(1) = int(200/4) : haut%(1) = int(200/4)


for i%=2 to nb_sprites
  sprite i% : sprite_file_load i%,"sprite_"+str$(i%)+".bmp" : file_delete "sprite_"+str$(i%)+".bmp"
  sprite_position i%,400-rnd(400),300 - rnd(300) : sprite_scale i%,1/3,1/3 : larg%(i%) = int(200/3) : haut%(i%) = int(200/3)
  test_recouvrement(i%,1) : ' procédure pour empécher que le sprite 1 ne soit recouvert par un autre sprite au démarrage
next i%

show 100 : ' On montre la scene

' Boucle de déplacement
repeat
  for i%=2 to nb_sprites
    move(i%,1)
  next i%
until scancode=27

end

' Procédure de déplacement
sub move(s1%,s2%)
  dim_local i%, delta%
  ' déplacer horizontalement
  if dir_x%(s1%)>0 : ' à droite
    if (sprite_x_position(s1%)+larg%(s1%))>=(width(100))
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  else              : ' à gauche
    if sprite_x_position(s1%)<=0
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  end_if
  ' déplacer verticalement
  if dir_y%(s1%)>0 : ' en bas
    if (sprite_y_position(s1%)+haut%(s1%))>=(height(100))
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  else              : ' en haut
    if sprite_y_position(s1%)<=0
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  end_if
  if abs(delta_x%(s1%))> abs(delta_y%(s1%))
    delta%=abs(delta_x%(s1%))
  else
    delta%=abs(delta_y%(s1%))
  end_if
 
  for i%=0 to delta%
    sprite_position s1%,sprite_x_position(s1%) + dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%)),sprite_y_position(s1%) + dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
    collision(s1%,s2%)
    if choc%=1 then exit_for
  next i%
  if choc%=1 then change_dir(s1%,s2%)
  for i%=0 to delta%
    sprite_position s1%,sprite_x_position(s1%) + dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%)),sprite_y_position(s1%) + dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
  next i%
end_sub

' Inverse les directions
sub change_dir(s1%,s2%)
  dir_x%(s1%) = 0-dir_x%(s1%): dir_y%(s1%) = 0-dir_y%(s1%)
  dir_x%(s2%) = 0-dir_x%(s2%): dir_y%(s2%) = 0-dir_y%(s2%)
end_sub

' Test s'il y a collision
sub collision(s1%,s2%)
  dim_local x1%,y1%, x2%,y2%
  x1% = sprite_x_position(s1%): y1% = sprite_y_position(s1%)
  x2% = sprite_x_position(s2%): y2% = sprite_y_position(s2%)
  ' le bas du sprite 1 touche le haut du sprite 2
  if (((y1%+haut%(s1%)) >= y2%) and (y1% <= (y2%+haut%(s2%))) and ((x1%+larg%(s1%)) >= x2%)  and (x1% <= (x2%+larg%(s2%))))
          choc% = 1 : ' Si le rectangle du sprite 1 recouvre partiellement celui du sprite 2, il y a collision
        else
          choc% = 0 : ' Sinon, on retourne qu'ils ne se touchent pas
  end_if
end_sub

' Test s'il y a recouvrement entre 2 sprites
sub test_recouvrement(s1%,s2%)
  dim_local x1%,y1%, x2%,y2%
  x1% = sprite_x_position(s1%): y1% = sprite_y_position(s1%)
  x2% = sprite_x_position(s2%): y2% = sprite_y_position(s2%)
  ' le bas du sprite 1 touche le haut du sprite 2
  while (((y1%+haut%(s1%)) >= y2%) and (y1% <= (y2%+haut%(s2%))) and ((x1%+larg%(s1%)) >= x2%)  and (x1% <= (x2%+larg%(s2%))))
    sprite_position s1%,400-rnd(400),300 - rnd(300)
    x1% = sprite_x_position(s1%): y1% = sprite_y_position(s1%)
  end_while
end_sub
Revenir en haut Aller en bas
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 19:17

C'est très parlant ce que tu as fait. Mais, sans plonger dans le code: tu as certainement fait le test de collision après avoir effectué le déplacement du sprite, en non pas pixel par pixel comme je l'avais fait. Certes, c'est plus rapide, mais tu vous souvent des sprites "rentrer" dans le sprite bleu avant de faire demi-tour. Si c'étaient des voitures - que de tôle froissée !
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 19:25

En fait c'est par ce que j'ai voulu garder la structure de ton programme pour ne pas compliquer, car là on travaille directement sur les sprites.
Normalement, ce que je ferais, ce serait travailler sur les coordonnées des sprites sans les déplacer.
Puis si il y a collision, on affiche le sprite avec la collision et on change les directions. Sinon on affiche le sprite avec ses nouvelles coordonnées.
Je vais coder ça pour illustrer, mais ça change un peu le code et les fonctions
Revenir en haut Aller en bas
Nardo26

Nardo26


Nombre de messages : 2294
Age : 55
Localisation : Valence
Date d'inscription : 02/07/2010

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 19:59

Perso c'est ce que j’aurais fait : anticiper la collision avant l'affichage... Smile

Revenir en haut Aller en bas
http://nardo26.lescigales.org
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 20:27

Voilà, les sprites ne se recouvre plus. Par contre, ils devraient se toucher, mais je pense que le fait qu'il ne se touchent pas est perfectible je pense, mais bon, je n’ai pas trop envie de chercher pourquoi. Il doit y avoir une petite idée ou une petite correction à faire quelque part.

Code:
' collisions_en_scene2d.bas

caption 0,"Interrompre par Echap"

dim i%, choc%                    : ' i% compteur temporaire et choc% variable globale permettant de savoir s'il y a collision ou non
dim nb_sprites : nb_sprites = 15 : ' Constante indiquant le nombre de sprites utilisés
dim larg%(nb_sprites), haut%(nb_sprites) : ' tableau contenant les dimensions des sprites
dim delta_x%(nb_sprites), delta_y%(nb_sprites) : ' vitesses horizontales et verticales des sprites
dim dir_x%(nb_sprites), dir_y%(nb_sprites) : ' directions horizontales et verticales des sprites
dim pos_x%(nb_sprites), pos_y%(nb_sprites) : ' coordonnées logiques des sprites
dim c% : c% = 255/nb_sprites : ' diviseur pour le calcul des couleurs

' Initialisation du sprite 1
delta_x%(1) = 2 : delta_y%(1) = 2 : dir_x%(1) = 1 : dir_y%(1) = 1

' Initialisation des autres sprites
for i%=2 to nb_sprites
  delta_x%(i%) = 4 : delta_y%(i%) = 3
  dir_x%(i%) = 1 : dir_y%(i%) = 1
next i%

' Création des images pour les sprites de test
picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
for i%=2 to nb_sprites
  color 100,255 - i%*c%,i%*c%,0 : file_save 100,"sprite_"+str$(i%)+".bmp"
next i%

' Création d'une image vide pour le fond
full_space 100 : color 100,220,220,220 :file_save 100,"vide_2D.bmp": delete 100

' Creation de l'air de déplacement des sprites et supression du fond temporaire
scene2d 100 : hide 100 : full_space 100 : file_load 100,"vide_2d.bmp" : file_delete "vide_2D.bmp"

' Création et chargement des sprites et suppression des images temporaires
sprite 1 : sprite_file_load 1,"sprite_1.bmp" : file_delete "sprite_1.bmp"
pos_x%(1) =  180: pos_y%(1) = 120
sprite_scale 1,1/4,1/4 : larg%(1) = int(200/4) : haut%(1) = int(200/4)
sprite_position 1,pos_x%(1),pos_y%(1)

for i%=2 to nb_sprites
  sprite i% : sprite_file_load i%,"sprite_"+str$(i%)+".bmp" : file_delete "sprite_"+str$(i%)+".bmp"
  sprite_scale i%,1/5,1/5 : larg%(i%) = int(200/5) : haut%(i%) = int(200/5)
  pos_x%(i%) =  400-rnd(400): pos_y%(i%) = 300 - rnd(300)
  test_recouvrement(i%,1) : ' procédure pour empécher que le sprite 1 ne soit recouvert par un autre sprite au démarrage
  sprite_position i%,pos_x%(i%),pos_y%(i%)
next i%

show 100 : ' On montre la scene

' Boucle de déplacement
repeat
  for i%=2 to nb_sprites
    move(i%,1)
  next i%
until scancode=27

end

' Procédure de déplacement
sub move(s1%,s2%)
  dim_local i%, delta%
  ' déplacer horizontalement
  if dir_x%(s1%)>0 : ' à droite
    if (sprite_x_position(s1%)+larg%(s1%))>=(width(100))
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  else              : ' à gauche
    if sprite_x_position(s1%)<=0
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  end_if
  ' déplacer verticalement
  if dir_y%(s1%)>0 : ' en bas
    if (sprite_y_position(s1%)+haut%(s1%))>=(height(100))
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  else              : ' en haut
    if sprite_y_position(s1%)<=0
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  end_if
  if abs(delta_x%(s1%))> abs(delta_y%(s1%))
    delta%=abs(delta_x%(s1%))
  else
    delta%=abs(delta_y%(s1%))
  end_if
 
  for i%=0 to delta%
    pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%))
    pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
    collision(s1%,s2%)
    if choc%=1 then exit_for
    sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
  next i%
  if choc%=1
      change_dir(s1%)
      for i%=0 to delta%
        pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%))
        pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
        sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      next i%
  end_if
end_sub

' Inverse les directions
sub change_dir(s1%)
  dir_x%(s1%) = 0-dir_x%(s1%): dir_y%(s1%) = 0-dir_y%(s1%)
end_sub

' Test s'il y a collision
sub collision(s1%,s2%)
  if (((pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) and ((pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%))  and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))))
          choc% = 1 : ' Si le rectangle du sprite 1 recouvre partiellement celui du sprite 2, il y a collision
        else
          choc% = 0 : ' Sinon, on retourne qu'ils ne se touchent pas
  end_if
end_sub

' Test s'il y a recouvrement entre 2 sprites
sub test_recouvrement(s1%,s2%)
  while (((pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) and ((pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%))  and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))))
    pos_x%(s1%) = 400-rnd(400): pos_y%(s1%) = 300 - rnd(300)
  end_while
end_sub
Revenir en haut Aller en bas
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 21:09

C'est justement parce que tu ne fais pas le test pixel par pixel, comme dans mon deuxième code. Dans ta technique, il faudrait réduire le déplacement dans les directions x et y s'il y avait dépassement de limite, puis effectuer la collision. C'est ce que j'évite en faisant les déplacements pixel par pixel.
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Yannick




Nombre de messages : 8610
Age : 52
Localisation : Bretagne
Date d'inscription : 15/02/2010

Gestion de collisions entre sprites en 2D Empty
MessageSujet: re   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 21:11

@ Nardo26,

Promis, je vais étudier une procédure "Conchita()" Laughing
Revenir en haut Aller en bas
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptySam 20 Oct 2012 - 23:01

Non Klaus, justement, le déplacement se fait normalement au maximum de 1
Code:

  for i%=0 to delta%
    pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%))
    pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
    collision(s1%,s2%)
    if choc%=1 then exit_for
    sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
  next i%
on rajoute comme dans le tient dir_x à chaque boucle
Par contre j'ai trouvé pourquoi j'avais laissé des référence fixe dans ma proc ... c'était par ce que j'étais parti de ton programme. Il y a des erreurs dedans. Le programme ne fonctionne que par ce que tu as 2 sprites. En effet, tu fait référence dans collision soit au sprite transmis en paramètre (S1% ou s2%) soit directement à l'indice du sprite dans le tableau (1 ou 2). Ca marche dans la démo puisqu'il ne sont que 2 mais le comportement serait hiératique si la procédure était employée avec d'autres sprites.

Je pense que le code est améliorable, mais je mets une petite amélioration telle qu'elle m'ait venu.
Si quelqu'un voit une solution plus satisfaisante ou des amélioration, il est le bienvenu ... Smile
Code:

' collisions_en_scene2d.bas

caption 0,"Interrompre par Echap"

dim i%, choc%                    : ' i% compteur temporaire et choc% variable globale permettant de savoir s'il y a collision ou non
dim nb_sprites : nb_sprites = 15 : ' Constante indiquant le nombre de sprites utilisés
dim larg%(nb_sprites), haut%(nb_sprites) : ' tableau contenant les dimensions des sprites
dim delta_x%(nb_sprites), delta_y%(nb_sprites) : ' vitesses horizontales et verticales des sprites
dim dir_x%(nb_sprites), dir_y%(nb_sprites) : ' directions horizontales et verticales des sprites
dim pos_x%(nb_sprites), pos_y%(nb_sprites) : ' coordonnées logiques des sprites
dim c% : c% = 255/nb_sprites : ' diviseur pour le calcul des couleurs

' Initialisation du sprite 1
delta_x%(1) = 2 : delta_y%(1) = 2 : dir_x%(1) = 1 : dir_y%(1) = 1

' Initialisation des autres sprites
for i%=2 to nb_sprites
  delta_x%(i%) = 4 : delta_y%(i%) = 3
  dir_x%(i%) = 1 : dir_y%(i%) = 1
next i%

' Création des images pour les sprites de test
picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
for i%=2 to nb_sprites
  color 100,255 - i%*c%,i%*c%,0 : file_save 100,"sprite_"+str$(i%)+".bmp"
next i%

' Création d'une image vide pour le fond
full_space 100 : color 100,220,220,220 :file_save 100,"vide_2D.bmp": delete 100

' Creation de l'air de déplacement des sprites et supression du fond temporaire
scene2d 100 : hide 100 : full_space 100 : file_load 100,"vide_2d.bmp" : file_delete "vide_2D.bmp"

' Création et chargement des sprites et suppression des images temporaires
sprite 1 : sprite_file_load 1,"sprite_1.bmp" : file_delete "sprite_1.bmp"
pos_x%(1) =  180: pos_y%(1) = 120
sprite_scale 1,1/4,1/4 : larg%(1) = int(200/4) : haut%(1) = int(200/4)
sprite_position 1,pos_x%(1),pos_y%(1)

for i%=2 to nb_sprites
  sprite i% : sprite_file_load i%,"sprite_"+str$(i%)+".bmp" : file_delete "sprite_"+str$(i%)+".bmp"
  sprite_scale i%,1/5,1/5 : larg%(i%) = int(200/5) : haut%(i%) = int(200/5)
  pos_x%(i%) =  400-rnd(400): pos_y%(i%) = 300 - rnd(300)
  test_recouvrement(i%,1) : ' procédure pour empécher que le sprite 1 ne soit recouvert par un autre sprite au démarrage
  sprite_position i%,pos_x%(i%),pos_y%(i%)
next i%

show 100 : ' On montre la scene

' Boucle de déplacement
repeat
  for i%=2 to nb_sprites
    move(i%,1)
  next i%
until scancode=27

end

' Procédure de déplacement
sub move(s1%,s2%)
  dim_local i%, delta%
  ' déplacer horizontalement
  if dir_x%(s1%)>0 : ' à droite
    if (sprite_x_position(s1%)+larg%(s1%))>=(width(100))
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  else              : ' à gauche
    if sprite_x_position(s1%)<=0
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  end_if
  ' déplacer verticalement
  if dir_y%(s1%)>0 : ' en bas
    if (sprite_y_position(s1%)+haut%(s1%))>=(height(100))
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  else              : ' en haut
    if sprite_y_position(s1%)<=0
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  end_if
  if abs(delta_x%(s1%))> abs(delta_y%(s1%))
    delta%=abs(delta_x%(s1%))
  else
    delta%=abs(delta_y%(s1%))
  end_if
 
  for i%=0 to delta%
    pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%))
    pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
    collision(s1%,s2%)
    if choc%=1
      affiche_contact(s1%,s2%)
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      exit_for
    else
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
    end_if
  next i%
  if choc%=1
      change_dir(s1%)
      for i%=0 to delta%
        pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%))
        pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
        sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      next i%
  end_if
end_sub

' Inverse les directions
sub change_dir(s1%)
  dir_x%(s1%) = 0-dir_x%(s1%): dir_y%(s1%) = 0-dir_y%(s1%)
end_sub

' Test s'il y a collision
sub collision(s1%,s2%)
  if (((pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) and ((pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%))  and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))))
          choc% = 1 : ' Si le rectangle du sprite 1 recouvre partiellement celui du sprite 2, il y a collision
        else
          choc% = 0 : ' Sinon, on retourne qu'ils ne se touchent pas
  end_if
end_sub

' Test s'il y a recouvrement entre 2 sprites
sub test_recouvrement(s1%,s2%)
  while (((pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) and ((pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%))  and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))))
    pos_x%(s1%) = 400-rnd(400): pos_y%(s1%) = 300 - rnd(300)
  end_while
end_sub

' Arrète le mouvement sur la position du contact
sub affiche_contact(s1%,s2%)
dim_local x,y : x=0 : y=0
  if (pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%)
    if (pos_x%(s1%) < pos_x%(s2%))
      if (pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)
        if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)) then x = pos_x%(s2%) - larg%(s1%) -1
      end_if
    end_if
  else
    if (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))
      if pos_x%(s1%) > pos_x%(s2%)
        if (((pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) then x = pos_x%(s2%) + larg%(s2%)
      end_if
    end_if
  end_if

  if (pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)
    if pos_y%(s1%) < pos_y%(s2%)
      if (pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%)
        if pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)) then y = pos_y%(s2%) - haut%(s1%)-1
      end_if
    end_if
  else
    if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))
      if pos_y%(s1%) > pos_y%(s2%)
        if (((pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%)) and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))) then y = pos_y%(s2%) + haut%(s2%)
      end_if
    end_if
  end_if
  if x > 0 then pos_x%(s1%) = x
  if y > 0 then pos_y%(s1%) = y
end_sub
Revenir en haut Aller en bas
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyDim 21 Oct 2012 - 11:15

Qu'est-ce que tun penses de cette version ? J'ai corrigé quelques indices, et j'ai rétabli les vitesses différentes selon les deux axes- tu avais gommé cet aspect en ramenant tout à ta variable locale delta%. J'ai commencé aussi à faire le rebond "façon billard" sur le sprite bleu. cela ne marche pas encore pour les coins, mais le début y est. Et les sprites mobiles s'arrêtent bien au ras du sprite bleu, maintenant, sans rentrer dedans.
Code:

' collisions_en_scene2d.bas

caption 0,"Interrompre par Echap"

dim i%, choc%                    : ' i% compteur temporaire et choc% variable globale permettant de savoir s'il y a collision ou non
dim nb_sprites : nb_sprites = 15 : ' Constante indiquant le nombre de sprites utilisés
dim larg%(nb_sprites), haut%(nb_sprites) : ' tableau contenant les dimensions des sprites
dim delta_x%(nb_sprites), delta_y%(nb_sprites) : ' vitesses horizontales et verticales des sprites
dim dir_x%(nb_sprites), dir_y%(nb_sprites) : ' directions horizontales et verticales des sprites
dim pos_x%(nb_sprites), pos_y%(nb_sprites) : ' coordonnées logiques des sprites
dim c% : c% = 255/nb_sprites : ' diviseur pour le calcul des couleurs

' Initialisation du sprite 1
delta_x%(1) = 2 : delta_y%(1) = 2 : dir_x%(1) = 1 : dir_y%(1) = 1

' Initialisation des autres sprites
for i%=2 to nb_sprites
  delta_x%(i%) = int(rnd(8)+0.5) + 1
  delta_y%(i%) = int(rnd(8)+0.5) + 1
  dir_x%(i%) = 1 : dir_y%(i%) = 1
next i%

' Création des images pour les sprites de test
picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
for i%=2 to nb_sprites
  color 100,255 - i%*c%,i%*c%,0 : file_save 100,"sprite_"+str$(i%)+".bmp"
next i%

' Création d'une image vide pour le fond
full_space 100 : color 100,220,220,220 :file_save 100,"vide_2D.bmp": delete 100

' Creation de l'air de déplacement des sprites et supression du fond temporaire
scene2d 100 : hide 100 : full_space 100 : file_load 100,"vide_2d.bmp" : file_delete "vide_2D.bmp"

' Création et chargement des sprites et suppression des images temporaires
sprite 1 : sprite_file_load 1,"sprite_1.bmp" : file_delete "sprite_1.bmp"
pos_x%(1) =  180: pos_y%(1) = 120
sprite_scale 1,1/4,1/4 : larg%(1) = int(200/4) : haut%(1) = int(200/4)
sprite_position 1,pos_x%(1),pos_y%(1)

for i%=2 to nb_sprites
  sprite i% : sprite_file_load i%,"sprite_"+str$(i%)+".bmp" : file_delete "sprite_"+str$(i%)+".bmp"
  sprite_scale i%,1/5,1/5 : larg%(i%) = int(200/5) : haut%(i%) = int(200/5)
  pos_x%(i%) =  400-rnd(400): pos_y%(i%) = 300 - rnd(300)
  test_recouvrement(i%,1) : ' procédure pour empécher que le sprite 1 ne soit recouvert par un autre sprite au démarrage
  sprite_position i%,pos_x%(i%),pos_y%(i%)
next i%

show 100 : ' On montre la scene

' Boucle de déplacement
repeat
  for i%=2 to nb_sprites
    move(i%,1)
  next i%
until scancode=27

end

' Procédure de déplacement
sub move(s1%,s2%)
  dim_local i%, delta%
  dim_local dx%, dy%
  ' déplacer horizontalement
  if dir_x%(s1%)>0 : ' à droite
    if (sprite_x_position(s1%)+larg%(s1%))>=(width(100))
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  else              : ' à gauche
    if sprite_x_position(s1%)<=0
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  end_if
  ' déplacer verticalement
  if dir_y%(s1%)>0 : ' en bas
    if (sprite_y_position(s1%)+haut%(s1%))>=(height(100))
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  else              : ' en haut
    if sprite_y_position(s1%)<=0
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  end_if
 
  dx% = abs(delta_x%(s1%))
  dy% = abs(delta_y%(s1%))
  delta% = max(dx%,dy%)
 
  for i%=0 to delta%
    if i%<=dx% then pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/dx%))
    if i%<=dy% then pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/dy%))
    collision(s1%,s2%)
    if choc%>0
      affiche_contact(s1%,s2%)
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      exit_for
    else
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
    end_if
  next i%
  if choc%>0
      change_dir(s1%)
      i% = 1
      repeat
        pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%))
        pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
        sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      collision(s1%,s2%)
      until choc%=0
  end_if
end_sub

' Inverse les directions
sub change_dir(s1%)
  select choc%
    case 1
      dir_x%(s1%) = 0-dir_x%(s1%)
      dir_y%(s1%) = 0-dir_y%(s1%)
    case 2
      dir_x%(s1%) = 0-dir_x%(s1%)
  case 3
      dir_y%(s1%) = 0-dir_y%(s1%)
  end_select
end_sub

' Test s'il y a collision
sub collision(s1%,s2%)
  choc% = 0
  if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
    if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)-1)
    if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
      if pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1)
          choc% = 1 : ' Si le rectangle du sprite 1 recouvre partiellement celui du sprite 2, il y a collision
          if pos_x%(s1%)>=pos_x%(s2%)
            if (pos_x%(s1%)+larg%(s1%)-1)<(pos_x%(s2%)+larg%(s2%)-1) then choc% = 2
          end_if
          if pos_y%(s1%)>=pos_y%(s2%)
            if (pos_y%(s1%)+haut%(s1%)-1)<(pos_y%(s2%)+haut%(s2%)-1) then choc% = 3
          end_if
        end_if
      end_if
    end_if
  end_if
end_sub

' Test s'il y a recouvrement entre 2 sprites
sub test_recouvrement(s1%,s2%)
  while (((pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) and ((pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%))  and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))))
    pos_x%(s1%) = 400-rnd(400): pos_y%(s1%) = 300 - rnd(300)
  end_while
end_sub

' Arrète le mouvement sur la position du contact
sub affiche_contact(s1%,s2%)
dim_local x,y : x=0 : y=0
  if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
    if (pos_x%(s1%) < pos_x%(s2%))
      if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
        if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)) then x = pos_x%(s2%) - larg%(s1%) + 1 : ' -1
      end_if
    end_if
  else
    if (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1)
      if pos_x%(s1%) > pos_x%(s2%)
        if (((pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) then x = pos_x%(s2%) + larg%(s2%) - 1 : ' + 0
      end_if
    end_if
  end_if

  if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
    if pos_y%(s1%) < pos_y%(s2%)
      if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
        if pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1) then y = pos_y%(s2%) - haut%(s1%) + 1 : ' -1
      end_if
    end_if
  else
    if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)-1)
      if pos_y%(s1%) > pos_y%(s2%)
        if (((pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)) and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))) then y = pos_y%(s2%) + haut%(s2%) - 1 : + 0
      end_if
    end_if
  end_if
  if x > 0 then pos_x%(s1%) = x
  if y > 0 then pos_y%(s1%) = y
end_sub
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyDim 21 Oct 2012 - 11:27

En effet Wink
Bon pour nos amis débutants qui se font toujours aussi discret, j'ai rajouté la gestion des touches pour bouger le sprite bleu.
J'espère qu'ils suivent ce post pour ne pas être perdus. Je ne veux pas compliquer le programme plus que nécessaire, mais s'ils suivent la discussion, ils comprendront les problématique et l'utilité des ajouts.
Les nouveaux, si vous ne comprenez pas quelque chose posez vos questions pendant que l'on est dedans...
Klaus, je l'ais fais sans événement pour ne pas mélanger les sujets. Qu'est-ce que tu en pense ?

Code:

' collisions_en_scene2d.bas

caption 0,"Interrompre par Echap"

dim i%, choc%                    : ' i% compteur temporaire et choc% variable globale permettant de savoir s'il y a collision ou non
dim nb_sprites : nb_sprites = 15 : ' Constante indiquant le nombre de sprites utilisés
dim larg%(nb_sprites), haut%(nb_sprites) : ' tableau contenant les dimensions des sprites
dim delta_x%(nb_sprites), delta_y%(nb_sprites) : ' vitesses horizontales et verticales des sprites
dim dir_x%(nb_sprites), dir_y%(nb_sprites) : ' directions horizontales et verticales des sprites
dim pos_x%(nb_sprites), pos_y%(nb_sprites) : ' coordonnées logiques des sprites
dim c% : c% = 255/nb_sprites : ' diviseur pour le calcul des couleurs
dim touche : ' on définit une variable qui contiendra la touche appuyée
dim depl  : ' definit une variable définissant si on doit déplacer le sprite

' Initialisation du sprite 1
delta_x%(1) = 2 : delta_y%(1) = 2 : dir_x%(1) = 0 : dir_y%(1) = 0

' Initialisation des autres sprites
for i%=2 to nb_sprites
  delta_x%(i%) = int(rnd(8)+0.5) + 1
  delta_y%(i%) = int(rnd(8)+0.5) + 1
  dir_x%(i%) = 1 : dir_y%(i%) = 1
next i%

' Création des images pour les sprites de test
picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
for i%=2 to nb_sprites
  color 100,255 - i%*c%,i%*c%,0 : file_save 100,"sprite_"+str$(i%)+".bmp"
next i%

' Création d'une image vide pour le fond
full_space 100 : color 100,220,220,220 :file_save 100,"vide_2D.bmp": delete 100

' Creation de l'air de déplacement des sprites et supression du fond temporaire
scene2d 100 : hide 100 : full_space 100 : file_load 100,"vide_2d.bmp" : file_delete "vide_2D.bmp"

' Création et chargement des sprites et suppression des images temporaires
sprite 1 : sprite_file_load 1,"sprite_1.bmp" : file_delete "sprite_1.bmp"
pos_x%(1) =  180: pos_y%(1) = 120
sprite_scale 1,1/4,1/4 : larg%(1) = int(200/4) : haut%(1) = int(200/4)
sprite_position 1,pos_x%(1),pos_y%(1)

for i%=2 to nb_sprites
  sprite i% : sprite_file_load i%,"sprite_"+str$(i%)+".bmp" : file_delete "sprite_"+str$(i%)+".bmp"
  sprite_scale i%,1/5,1/5 : larg%(i%) = int(200/5) : haut%(i%) = int(200/5)
  pos_x%(i%) =  400-rnd(400): pos_y%(i%) = 300 - rnd(300)
  test_recouvrement(i%,1) : ' procédure pour empécher que le sprite 1 ne soit recouvert par un autre sprite au démarrage
  sprite_position i%,pos_x%(i%),pos_y%(i%)
next i%

show 100 : ' On montre la scene

' Boucle de déplacement
repeat
  for i%=2 to nb_sprites
    move(i%,1)
  next i%
 touche = scancode : rem lecture du clavier, code mis dans touche
 depl=0
 if touche = 37 then dir_x%(1) = -1 : dir_y%(1) = 0 : depl=1 : rem 37=code de FLECHE GAUCHE
 if touche = 38 then dir_y%(1) = -1 : dir_x%(1) = 0 : depl=1 : rem 38=code de FLECHE HAUT
 if touche = 39 then dir_x%(1) =  1 : dir_y%(1) = 0 : depl=1 : rem 39=code de FLECHE DROITE
 if touche = 40 then dir_y%(1) =  1 : dir_x%(1) = 0 : depl=1 : rem 40=code de FLECHE BAS
 if depl=1
  for i%=2 to nb_sprites
    move(1,i%)
    depl=0
  next i%
 end_if
until scancode=27

end

' Procédure de déplacement
sub move(s1%,s2%)
  dim_local i%, delta%
  dim_local dx%, dy%
  ' déplacer horizontalement
  if dir_x%(s1%)>0 : ' à droite
    if (sprite_x_position(s1%)+larg%(s1%))>=(width(100))
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  else              : ' à gauche
    if sprite_x_position(s1%)<=0
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  end_if
  ' déplacer verticalement
  if dir_y%(s1%)>0 : ' en bas
    if (sprite_y_position(s1%)+haut%(s1%))>=(height(100))
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  else              : ' en haut
    if sprite_y_position(s1%)<=0
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  end_if

  dx% = abs(delta_x%(s1%))
  dy% = abs(delta_y%(s1%))
  delta% = max(dx%,dy%)

  for i%=0 to delta%
    if i%<=dx% then pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/dx%))
    if i%<=dy% then pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/dy%))
    collision(s1%,s2%)
    if choc%>0
      affiche_contact(s1%,s2%)
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      exit_for
    else
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
    end_if
  next i%
  if choc%>0
      change_dir(s1%)
      i% = 1
      repeat
        pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%))
        pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
        sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      collision(s1%,s2%)
      until choc%=0
  end_if
end_sub

' Inverse les directions
sub change_dir(s1%)
  select choc%
    case 1
      dir_x%(s1%) = 0-dir_x%(s1%)
      dir_y%(s1%) = 0-dir_y%(s1%)
    case 2
      dir_x%(s1%) = 0-dir_x%(s1%)
  case 3
      dir_y%(s1%) = 0-dir_y%(s1%)
  end_select
end_sub

' Test s'il y a collision
sub collision(s1%,s2%)
  choc% = 0
  if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
    if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)-1)
    if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
      if pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1)
          choc% = 1 : ' Si le rectangle du sprite 1 recouvre partiellement celui du sprite 2, il y a collision
          if pos_x%(s1%)>=pos_x%(s2%)
            if (pos_x%(s1%)+larg%(s1%)-1)<(pos_x%(s2%)+larg%(s2%)-1) then choc% = 2
          end_if
          if pos_y%(s1%)>=pos_y%(s2%)
            if (pos_y%(s1%)+haut%(s1%)-1)<(pos_y%(s2%)+haut%(s2%)-1) then choc% = 3
          end_if
        end_if
      end_if
    end_if
  end_if
end_sub

' Test s'il y a recouvrement entre 2 sprites
sub test_recouvrement(s1%,s2%)
  while (((pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) and ((pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%))  and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))))
    pos_x%(s1%) = 400-rnd(400): pos_y%(s1%) = 300 - rnd(300)
  end_while
end_sub

' Arrète le mouvement sur la position du contact
sub affiche_contact(s1%,s2%)
dim_local x,y : x=0 : y=0
  if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
    if (pos_x%(s1%) < pos_x%(s2%))
      if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
        if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)) then x = pos_x%(s2%) - larg%(s1%) + 1 : ' -1
      end_if
    end_if
  else
    if (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1)
      if pos_x%(s1%) > pos_x%(s2%)
        if (((pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) then x = pos_x%(s2%) + larg%(s2%) - 1 : ' + 0
      end_if
    end_if
  end_if

  if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
    if pos_y%(s1%) < pos_y%(s2%)
      if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
        if pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1) then y = pos_y%(s2%) - haut%(s1%) + 1 : ' -1
      end_if
    end_if
  else
    if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)-1)
      if pos_y%(s1%) > pos_y%(s2%)
        if (((pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)) and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))) then y = pos_y%(s2%) + haut%(s2%) - 1 : + 0
      end_if
    end_if
  end_if
  if x > 0 then pos_x%(s1%) = x
  if y > 0 then pos_y%(s1%) = y
end_sub
Revenir en haut Aller en bas
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyDim 21 Oct 2012 - 11:37

Bonne idée. Mais curieusement, la vitesse du déplacement du sprite bleu est égale au nombre de sprites existants, à cause de ta boucle. Pourquoi tu ne fais pas comme ceci:
Code:
 if depl=1
'  for i%=2 to nb_sprites
'    move(1,i%)
'    depl=0
'  next i%
  move(1,0)
 end_if
quitte à modifier delta_x%(1) et delta_y%(1) pour choisir la vitesse que tu souhaites ?
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyDim 21 Oct 2012 - 12:25

Absolument Klaus, tu as raison Wink J'ai voulu faire simple et je n'ai pas pensé au 0. Bonne idée, je mets le code en dessous avec cette modif
Code:
' collisions_en_scene2d.bas
' Pour apprendre à gérer les collisions avec les sprites
' Le sprite 1 est déplacé avec le pavé directionnel
' Les autres sprites se déplacent et rebondissent

caption 0,"Interrompre par Echap"

dim i%, choc%                    : ' i% compteur temporaire et choc% variable globale permettant de savoir s'il y a collision ou non
dim nb_sprites : nb_sprites = 15 : ' Constante indiquant le nombre de sprites utilisés
dim larg%(nb_sprites), haut%(nb_sprites) : ' tableau contenant les dimensions des sprites
dim delta_x%(nb_sprites), delta_y%(nb_sprites) : ' vitesses horizontales et verticales des sprites
dim dir_x%(nb_sprites), dir_y%(nb_sprites) : ' directions horizontales et verticales des sprites
dim pos_x%(nb_sprites), pos_y%(nb_sprites) : ' coordonnées logiques des sprites
dim c% : c% = 255/nb_sprites : ' diviseur pour le calcul des couleurs
dim touche : ' on définit une variable qui contiendra la touche appuyée
dim depl  : ' definit une variable définissant si on doit déplacer le sprite

' Initialisation du sprite 1
delta_x%(1) = 5 : delta_y%(1) = 5 : dir_x%(1) = 0 : dir_y%(1) = 0

' Initialisation des autres sprites
for i%=2 to nb_sprites
  delta_x%(i%) = int(rnd(8)+0.5) + 1
  delta_y%(i%) = int(rnd(8)+0.5) + 1
  dir_x%(i%) = 1 : dir_y%(i%) = 1
next i%

' Création des images pour les sprites de test
picture 100 : height 100,200 : width 100,200
  color 100,0,0,255 : file_save 100,"sprite_1.bmp"
for i%=2 to nb_sprites
  color 100,255 - i%*c%,i%*c%,0 : file_save 100,"sprite_"+str$(i%)+".bmp"
next i%

' Création d'une image vide pour le fond
full_space 100 : color 100,220,220,220 :file_save 100,"vide_2D.bmp": delete 100

' Creation de l'air de déplacement des sprites et supression du fond temporaire
scene2d 100 : hide 100 : full_space 100 : file_load 100,"vide_2d.bmp" : file_delete "vide_2D.bmp"

' Création et chargement des sprites et suppression des images temporaires
sprite 1 : sprite_file_load 1,"sprite_1.bmp" : file_delete "sprite_1.bmp"
pos_x%(1) =  180: pos_y%(1) = 120
sprite_scale 1,1/4,1/4 : larg%(1) = int(200/4) : haut%(1) = int(200/4)
sprite_position 1,pos_x%(1),pos_y%(1)

for i%=2 to nb_sprites
  sprite i% : sprite_file_load i%,"sprite_"+str$(i%)+".bmp" : file_delete "sprite_"+str$(i%)+".bmp"
  sprite_scale i%,1/5,1/5 : larg%(i%) = int(200/5) : haut%(i%) = int(200/5)
  pos_x%(i%) =  400-rnd(400): pos_y%(i%) = 300 - rnd(300)
  test_recouvrement(i%,1) : ' procédure pour empécher que le sprite 1 ne soit recouvert par un autre sprite au démarrage
  sprite_position i%,pos_x%(i%),pos_y%(i%)
next i%

show 100 : ' On montre la scene

' Boucle de déplacement
repeat
  for i%=2 to nb_sprites
    move(i%,1)
  next i%
 touche = scancode : rem lecture du clavier, code mis dans touche
 depl=0
 if touche = 37 then dir_x%(1) = -1 : dir_y%(1) = 0 : depl=1 : rem 37=code de FLECHE GAUCHE
 if touche = 38 then dir_y%(1) = -1 : dir_x%(1) = 0 : depl=1 : rem 38=code de FLECHE HAUT
 if touche = 39 then dir_x%(1) =  1 : dir_y%(1) = 0 : depl=1 : rem 39=code de FLECHE DROITE
 if touche = 40 then dir_y%(1) =  1 : dir_x%(1) = 0 : depl=1 : rem 40=code de FLECHE BAS
 if depl=1 then move(1,0): depl=0
until scancode=27

end

' Procédure de déplacement
sub move(s1%,s2%)
  dim_local i%, delta%
  dim_local dx%, dy%
  ' déplacer horizontalement
  if dir_x%(s1%)>0 : ' à droite
    if (sprite_x_position(s1%)+larg%(s1%))>=(width(100))
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  else              : ' à gauche
    if sprite_x_position(s1%)<=0
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  end_if
  ' déplacer verticalement
  if dir_y%(s1%)>0 : ' en bas
    if (sprite_y_position(s1%)+haut%(s1%))>=(height(100))
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  else              : ' en haut
    if sprite_y_position(s1%)<=0
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  end_if

  dx% = abs(delta_x%(s1%))
  dy% = abs(delta_y%(s1%))
  delta% = max(dx%,dy%)

  for i%=0 to delta%
    if i%<=dx% then pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/dx%))
    if i%<=dy% then pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/dy%))
    collision(s1%,s2%)
    if choc%>0
      affiche_contact(s1%,s2%)
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      exit_for
    else
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
    end_if
  next i%
  if choc%>0
      change_dir(s1%)
      i% = 1
      repeat
        pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%))
        pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
        sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      collision(s1%,s2%)
      until choc%=0
  end_if
end_sub

' Inverse les directions
sub change_dir(s1%)
  select choc%
    case 1
      dir_x%(s1%) = 0-dir_x%(s1%)
      dir_y%(s1%) = 0-dir_y%(s1%)
    case 2
      dir_x%(s1%) = 0-dir_x%(s1%)
  case 3
      dir_y%(s1%) = 0-dir_y%(s1%)
  end_select
end_sub

' Test s'il y a collision
sub collision(s1%,s2%)
  choc% = 0
  if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
    if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)-1)
    if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
      if pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1)
          choc% = 1 : ' Si le rectangle du sprite 1 recouvre partiellement celui du sprite 2, il y a collision
          if pos_x%(s1%)>=pos_x%(s2%)
            if (pos_x%(s1%)+larg%(s1%)-1)<(pos_x%(s2%)+larg%(s2%)-1) then choc% = 2
          end_if
          if pos_y%(s1%)>=pos_y%(s2%)
            if (pos_y%(s1%)+haut%(s1%)-1)<(pos_y%(s2%)+haut%(s2%)-1) then choc% = 3
          end_if
        end_if
      end_if
    end_if
  end_if
end_sub

' Test s'il y a recouvrement entre 2 sprites
sub test_recouvrement(s1%,s2%)
  while (((pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) and ((pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%))  and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))))
    pos_x%(s1%) = 400-rnd(400): pos_y%(s1%) = 300 - rnd(300)
  end_while
end_sub

' Arrète le mouvement sur la position du contact
sub affiche_contact(s1%,s2%)
dim_local x,y : x=0 : y=0
  if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
    if (pos_x%(s1%) < pos_x%(s2%))
      if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
        if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)) then x = pos_x%(s2%) - larg%(s1%) + 1 : ' -1
      end_if
    end_if
  else
    if (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1)
      if pos_x%(s1%) > pos_x%(s2%)
        if (((pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) then x = pos_x%(s2%) + larg%(s2%) - 1 : ' + 0
      end_if
    end_if
  end_if

  if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
    if pos_y%(s1%) < pos_y%(s2%)
      if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
        if pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1) then y = pos_y%(s2%) - haut%(s1%) + 1 : ' -1
      end_if
    end_if
  else
    if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)-1)
      if pos_y%(s1%) > pos_y%(s2%)
        if (((pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)) and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))) then y = pos_y%(s2%) + haut%(s2%) - 1 : + 0
      end_if
    end_if
  end_if
  if x > 0 then pos_x%(s1%) = x
  if y > 0 then pos_y%(s1%) = y
end_sub
Revenir en haut Aller en bas
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyDim 21 Oct 2012 - 13:40

C'est pas mal, comme ça. Ca donne une bonne idée comment gérer les collisions en 2d.

Mais il est vrai qu'une fonction 2d_collision() serait la bienvenue !
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Jicehel

Jicehel


Nombre de messages : 5947
Age : 51
Localisation : 77500
Date d'inscription : 18/04/2011

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyDim 21 Oct 2012 - 14:21

C'est sûr Wink C'est sans doute une des fonctions manquantes auxquelles Jack pensait quand il disait qu'il voulait pouvoir faire des jeux facilement avec Panoramic, mais bon on aura la surprise bientôt. Je fais preuve de patiente pour une fois Wink
Revenir en haut Aller en bas
Nardo26

Nardo26


Nombre de messages : 2294
Age : 55
Localisation : Valence
Date d'inscription : 02/07/2010

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyDim 21 Oct 2012 - 18:47

Jicehel a écrit:
En effet Wink
Bon pour nos amis débutants qui se font toujours aussi discret,...
C'est très bien jicehel ce que tu as fait mais :
je viens de parcourir ton code, a moins d'être l'auteur où de bien comprendre le principe (auquel cas, la question ne se pose même pas sur le forum) je doute que Lucifor31 comprenne la moindre ligne de code à ton programme....
Perso, ton source ne me pose pas de problème mais pour un débutant, sans aucun commentaire, cela risque d'être un peu hard ! Wink
Revenir en haut Aller en bas
http://nardo26.lescigales.org
Klaus

Klaus


Nombre de messages : 12274
Age : 74
Localisation : Ile de France
Date d'inscription : 29/12/2009

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyDim 21 Oct 2012 - 19:35

Et je vais rajouter une couche !

Je n'étais pas satisfait des conditions de rebond des sprites mobiles sur le sprite bleu. J'aurais aimé que le rebond se fasse comme sur les bords, façon "billard". J'ai donc essayé de réécrire la routine de test de collision, mais je me suis vite heurté à des monceaux de code en Panoramic, rien que pour pouvoir déterminer le type et l'endroit du recouvrement.

Alors, et je m'en excuse, j'ai fait une fonction DLL qui détermine le type de recouvrement d'un rectangle par un autre. Du coup, KGF.dll passe à la version
1.79 21/10/2012 ajout fonction IsRectangleInRectangle

Cette fonction retourne une valeur indiquant le type de recouvrement. Voici un extrait de la doc:
Citation :
valeur indiquant l'état de recouvrement.
Elle est consituée du OR logique des valeurs suivantes:
0 = R1 ne touche pas R2
1 = le coin en haut à gauche de R1 est dans R2
2 = le coin en haut à droite de R1 est dans R2
4 = le coin en bas à gauche de R1 est dans R2
8 = le coin en bas à droite de R1 est dans R2
16 = R1 recouvre totalement R2

Cette nouvelle fonction est dans la section "Fonctions de la souris" de la doc.

Bien sûr, la doc est à jour, et KGF_SUB suivra prochainement.

J'ai utilisé cette fonction dans ce programme de sprites movants. Et j'ai ajouté un autre effet sympa: le programme démarre avec 2 sprites mobiles. il est prévu pour un maximum de 20 sprites au total. La barre d'espacement injecte un nouveau sprite n cours de fonctionnement, et la touche TAB supprime un sprite. On peut supprimer tous les sprites, y compris le sprite bleu. Et on les recrée aussitôt par la barre d'espacement.

Voici le code:
Code:
' collisions_en_scene2d.bas
' Pour apprendre à gérer les collisions avec les sprites
' Le sprite 1 est déplacé avec le pavé directionnel
' Les autres sprites se déplacent et rebondissent

label sortie

caption 0,"Interrompre par Echap"
 on_close 0,sortie
dll_on "KGF.dll"

dim i%, choc%                    : ' i% compteur temporaire et choc% variable globale permettant de savoir s'il y a collision ou non
' dim nb_sprites% : nb_sprites% = 15 : ' Constante indiquant le nombre de sprites utilisés
dim nb_sprites% : nb_sprites% = 3 : ' Constante indiquant le nombre de sprites utilisés
dim max_sprites% : max_sprites% = 20
dim larg%(max_sprites%), haut%(max_sprites%) : ' tableau contenant les dimensions des sprites
dim delta_x%(max_sprites%), delta_y%(max_sprites%) : ' vitesses horizontales et verticales des sprites
dim dir_x%(max_sprites%), dir_y%(max_sprites%) : ' directions horizontales et verticales des sprites
dim pos_x%(max_sprites%), pos_y%(max_sprites%) : ' coordonnées logiques des sprites
dim c% : c% = int(255/max_sprites%) : ' diviseur pour le calcul des couleurs
dim touche : ' on définit une variable qui contiendra la touche appuyée
dim depl  : ' definit une variable définissant si on doit déplacer le sprite
dim flag% : ' flag "un sprite a été supprimé"

' Initialisation du sprite 1
delta_x%(1) = 5 : delta_y%(1) = 5 : dir_x%(1) = 0 : dir_y%(1) = 0

' Initialisation des autres sprites
for i%=2 to max_sprites%
  delta_x%(i%) = int(rnd(8)+0.5) + 1
  delta_y%(i%) = int(rnd(8)+0.5) + 1
  dir_x%(i%) = 1 : dir_y%(i%) = 1
next i%

' Création d'une image vide pour le fond
picture 100
full_space 100 : color 100,220,220,220 :file_save 100,"vide_2D.bmp": delete 100

' Creation de l'air de déplacement des sprites et supression du fond temporaire
scene2d 100 : hide 100 : full_space 100 : file_load 100,"vide_2d.bmp" : file_delete "vide_2D.bmp"

' Création et chargement des sprites et suppression des images temporaires
create_sprite(1)

for i%=2 to nb_sprites%
  create_sprite(i%)
next i%

show 100 : ' On montre la scene

' Boucle de déplacement
repeat
  if flag%=1
    pause 100
    flag% = 0
  end_if
  if nb_sprites%>1
    for i%=2 to nb_sprites%
      move(i%,1)
    next i%
  end_if
 touche = scancode : rem lecture du clavier, code mis dans touche
 depl=0
 select touche
  case 37: dir_x%(1) = -1 : dir_y%(1) = 0 : depl=1 : rem 37=code de FLECHE GAUCHE
  case 38: dir_y%(1) = -1 : dir_x%(1) = 0 : depl=1 : rem 38=code de FLECHE HAUT
  case 39: dir_x%(1) =  1 : dir_y%(1) = 0 : depl=1 : rem 39=code de FLECHE DROITE
  case 40: dir_y%(1) =  1 : dir_x%(1) = 0 : depl=1 : rem 40=code de FLECHE BAS
  case 32
    if nb_sprites%<max_sprites%
      nb_sprites% = nb_sprites% + 1
      create_sprite(nb_sprites%)
    end_if
  case 9
    if nb_sprites%>0
      sprite_delete nb_sprites%
      nb_sprites% = nb_sprites% - 1
      flag% = 1
    end_if
 end_select
 if depl=1 then move(1,0): depl=0
until scancode=27

end

sortie:
  dll_off
  return

' Procédure de déplacement
sub move(s1%,s2%)
  if scancode=27 then end : ' terminate
  dim_local i%, delta%
  dim_local dx%, dy%
  ' déplacer horizontalement
  if dir_x%(s1%)>0 : ' à droite
    if (sprite_x_position(s1%)+larg%(s1%))>=(width(100))
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  else              : ' à gauche
    if sprite_x_position(s1%)<=0
      dir_x%(s1%) = 0 - dir_x%(s1%)
    end_if
  end_if
  ' déplacer verticalement
  if dir_y%(s1%)>0 : ' en bas
    if (sprite_y_position(s1%)+haut%(s1%))>=(height(100))
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  else              : ' en haut
    if sprite_y_position(s1%)<=0
      dir_y%(s1%) = 0 - dir_y%(s1%)
    end_if
  end_if

  dx% = abs(delta_x%(s1%))
  dy% = abs(delta_y%(s1%))
  delta% = max(dx%,dy%)

  for i%=0 to delta%
'    if i%<=dx% then pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/dx%))
'    if i%<=dy% then pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/dy%))
    if i%<=dx% then pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*delta_x%(s1%)/dx%
    if i%<=dy% then pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*delta_y%(s1%)/dy%
    collision(s1%,s2%)
    if choc%>0
      affiche_contact(s1%,s2%)
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      exit_for
    else
      sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
    end_if
  next i%
  if choc%>0
      change_dir(s1%,s2%)
      i% = 1
      repeat
        pos_x%(s1%) = pos_x%(s1%)+ dir_x%(s1%)*(i%*(delta_x%(s1%)/delta%))
        pos_y%(s1%) = pos_y%(s1%)+ dir_y%(s1%)*(i%*(delta_y%(s1%)/delta%))
        sprite_position s1%,pos_x%(s1%),pos_y%(s1%)
      collision(s1%,s2%)
      until choc%=0
  end_if
end_sub

' Inverse les directions
sub change_dir(s1%,s2%)
  select choc%
    case 1  : ' top left
      if pos_y%(s1%)<(pos_y%(s2%)+haut%(s2%)-1)
        dir_x%(s1%) = 0-dir_x%(s1%)
      else
        dir_y%(s1%) = 0-dir_y%(s1%)
      end_if
    case 2  : ' top right
      if pos_y%(s1%)<(pos_y%(s2%)+haut%(s2%)-1)
        dir_x%(s1%) = 0-dir_x%(s1%)
      else
        dir_y%(s1%) = 0-dir_y%(s1%)
      end_if
    case 3  : ' top left + top right
        dir_y%(s1%) = 0-dir_y%(s1%)
    case 4  : ' bottom left
      if (pos_y%(s1%)+haut%(s1%)-1)<pos_y%(s2%)
        dir_x%(s1%) = 0-dir_x%(s1%)
      else
        dir_y%(s1%) = 0-dir_y%(s1%)
      end_if
    case 5  : ' top left + bottom left
        dir_x%(s1%) = 0-dir_x%(s1%)
    case 6:  ' top right + bottom left ==> impossible
    case 7:  ' top left + top right + bottom left ==> impossible
    case 8:  ' bottom right
      if (pos_y%(s1%)+haut%(s1%)-1)<pos_y%(s2%)
        dir_x%(s1%) = 0-dir_x%(s1%)
      else
        dir_y%(s1%) = 0-dir_y%(s1%)
      end_if
    case 9:  ' top left + bottom right ==> impossible
    case 10: ' top right + bottom right ==> impossible
        dir_x%(s1%) = 0-dir_x%(s1%)
    case 11: ' top left + top right + bottom right ==> impossible
    case 12: ' bottom left + bottom right
        dir_y%(s1%) = 0-dir_y%(s1%)
    case 13: ' top left + bottom left + bottom right ==> impossible
    case 14: ' top right + bottom left + bottom right ==> impossible
    case 15: ' entièrement à l'intérieur
        dir_x%(s1%) = 0-dir_x%(s1%)
        dir_y%(s1%) = 0-dir_y%(s1%)
        if dir_x%(s1%)>0
          pos_x%(s1%) = pos_x%(s2%)+larg%(s2%) + 1
        else
          pos_x%(s1%) = pos_x(s2%) - larg%(s1%) - 1
        end_if
        if dir_y%(s1%)>0
          pos_y%(s1%) = pos_y%(s2%)+haut%(s2%) + 1
        else
          pos_y%(s1%) = pos_y(s2%) - haut%(s1%) - 1
        end_if
    case 16: ' recouvrement complet ==> impossible ici
  end_select
end_sub

' Test s'il y a collision
sub collision(s1%,s2%)
  dim_local top1%, dim1%, top2%, dim2%
  top1% = pos_y%(s1%) + pos_x%(s1%)*65536
  dim1% = haut%(s1%) + larg%(s1%)*65536
  top2% = pos_y%(s2%) + pos_x%(s2%)*65536
  dim2% = haut%(s2%) + larg%(s2%)*65536
  choc% = dll_call4("IsRectangleInRectangle",top1%,dim1%,top2%,dim2%)
  exit_sub
end_sub

' Test s'il y a recouvrement entre 2 sprites
sub test_recouvrement(s1%,s2%)
  while (((pos_y%(s1%)+haut%(s1%)) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) and ((pos_x%(s1%)+larg%(s1%)) >= pos_x%(s2%))  and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))))
    pos_x%(s1%) = 400-rnd(400): pos_y%(s1%) = 300 - rnd(300)
  end_while
end_sub

' Arrète le mouvement sur la position du contact
sub affiche_contact(s1%,s2%)
dim_local x,y : x=0 : y=0
  if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
    if (pos_x%(s1%) < pos_x%(s2%))
      if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
        if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)) then x = pos_x%(s2%) - larg%(s1%) + 1 : ' -1
      end_if
    end_if
  else
    if (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1)
      if pos_x%(s1%) > pos_x%(s2%)
        if (((pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)) and (pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%))) then x = pos_x%(s2%) + larg%(s2%) - 1 : ' + 0
      end_if
    end_if
  end_if

  if (pos_y%(s1%)+haut%(s1%)-1) >= pos_y%(s2%)
    if pos_y%(s1%) < pos_y%(s2%)
      if (pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)
        if pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%)-1) then y = pos_y%(s2%) - haut%(s1%) + 1 : ' -1
      end_if
    end_if
  else
    if pos_y%(s1%) <= (pos_y%(s2%)+haut%(s2%)-1)
      if pos_y%(s1%) > pos_y%(s2%)
        if (((pos_x%(s1%)+larg%(s1%)-1) >= pos_x%(s2%)) and (pos_x%(s1%) <= (pos_x%(s2%)+larg%(s2%))) then y = pos_y%(s2%) + haut%(s2%) - 1 : + 0
      end_if
    end_if
  end_if
  if x > 0 then pos_x%(s1%) = x
  if y > 0 then pos_y%(s1%) = y
end_sub

' Création des sprites
sub create_sprite(k%)
  picture 101 : height 101,200 : width 101,200
  if k%=1
    color 101,0,0,255
    file_save 101,"sprite_x.bmp"
  else
    color 101,255 - k%*c%,k%*c%,0
    file_save 101,"sprite_x.bmp"
  end_if
  delete 101
  sprite k% : sprite_file_load k%,"sprite_x.bmp" : file_delete "sprite_x.bmp"
  if k%=1
    pos_x%(1) =  180: pos_y%(1) = 120
    sprite_scale 1,1/4,1/4 : larg%(1) = int(200/4) : haut%(1) = int(200/4)
    sprite_position 1,pos_x%(1),pos_y%(1)
  else
    sprite_scale k%,1/5,1/5 : larg%(k%) = int(200/5) : haut%(k%) = int(200/5)
    pos_x%(k%) =  400-rnd(400): pos_y%(k%) = 300 - rnd(300)
    test_recouvrement(k%,1) : ' procédure pour empécher que le sprite 1 ne soit recouvert par un autre sprite au démarrage
    sprite_position k%,pos_x%(k%),pos_y%(k%)
  end_if
end_sub
Revenir en haut Aller en bas
http://klauspanoramic.comxa.com/index.html
Nardo26

Nardo26


Nombre de messages : 2294
Age : 55
Localisation : Valence
Date d'inscription : 02/07/2010

Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D EmptyDim 21 Oct 2012 - 20:31

@Lucifor31 :
comme tu peux le constater, la gestion de collision même en 2D n'est pas si évidente que ça...
perso je préfère laisser la place à des matheux, car je bien peur que pour vraiment traiter correctement une collision, il faut passer par des calculs vectoriels et franchement cela fait vraiment trop longtemps que je n'y ai pas mis mon nez dedans... Very Happy
(Je sais pas quel système Klaus à mis en place dans sa DLL...)

Peut être que jean debord aura quelque chose à proposer?...
Ou attendre dans ce cas l'avis de Jack qui a certainement du réfléchir à la chose...

Un gars (galmiza) a réalisé la chose en C++ (voir ici), et je me permet de mettre ce schema pour te donner une idée du principe (pour par exemple une collision avec un rectangle):

Gestion de collisions entre sprites en 2D 8109634245_37acc98356
Revenir en haut Aller en bas
http://nardo26.lescigales.org
Contenu sponsorisé





Gestion de collisions entre sprites en 2D Empty
MessageSujet: Re: Gestion de collisions entre sprites en 2D   Gestion de collisions entre sprites en 2D Empty

Revenir en haut Aller en bas
 
Gestion de collisions entre sprites en 2D
Revenir en haut 
Page 1 sur 2Aller à la page : 1, 2  Suivant
 Sujets similaires
-
» Demande de maquette d'un moteur 2D avec sprites/collisions
» Collisions en 3D
» Aide pour trouver un problème de détection de collisions
» Sprites
» un peu sur les sprites

Permission de ce forum:Vous ne pouvez pas répondre aux sujets dans ce forum
FORUM DE DISCUSSION SUR LE LANGAGE PANORAMIC :: PANORAMIC :: Vos sources, vos utilitaires à partager-
Sauter vers: