Moteur Raycasting

15 sujets de 1 à 15 (sur un total de 28)

  • 1
  • 2
  • Anonyme

      #176436

      Hello,

      Plutôt que de passer mon temps a critiquer tous le monde et comme ma femme me laisse plus de temps à coder, j’ai revu mon moteur de raycasting créé avec Hollywood.

       

      J’ai essayé de faire un code clair, facile à retranscrire sur d’autres langage de programmation tel que l’Amos (d’ailleurs, si quelqu’un pouvait s’y atteler, sa pourrait être marrant car je suis sûre que le rendu serait plus rapide sur un 1200 mais en 320×256)

       

      Trêve de plaisanterie et laissons place au code :

      <code>

      ; Moteur de Raycasting Simplifié

      ; Créer par Artblink en 2010, modifié en 2013

      ; Se moteur n’est pas optimisé mais simplifié pour la lecture

      ; Moteur à 90 FPS => peut être poussé à 200 FPS, mais difficilement lisible

      ; (testé Sur PC Quad Q9550 @ 2.83Ghz/4 Go/NVIDIA GeForce GTX 570 avec Hollywood 4.8)

      ; Il sert de tuto pour être adapté sur d’autres langage de programmation

      ; Normalement, il doit être très simple de l’adapter en Amos

      ;

      @SCREEN {Mode = « ask », Width = 640, Height = 480}

      ; Définition de la taille de la carte, un tableau de 24 colonnes/24 lignes

      NombreDeLigne=24

      NombreDeColonne=24

      ; 0 rien, >0 un mur, le numéro étant la couleur de se mur

      CarteDuJeux = {

      {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,2,2,2,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},

      {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,3,0,0,0,3,0,0,0,1},

      {1,0,0,0,0,0,2,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,2,2,0,2,2,0,0,0,0,3,0,3,0,3,0,0,0,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,4,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,4,0,4,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,4,0,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1},

      {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}

      }

      ; Position du départ dans le tableau

      PositionEnXSurCarte = 22 ; Ligne N°21

      PositionEnYSurCarte = 12 ; Colonne N°11

       

      ; Définition des variables Globales

      DirectionEnX = 1

      DirectionEnY = 0.1

      planex = 0

      planey = 0.66

      VitesseDeDeplacement= 0.25

      VitesseDeLaRotation = 0.05

      TailleEcranEnX=639

      TailleEcranEnY=479

      ; Fonction Principale

      Function prg()

      StartTimer(1) ; Départ du chronomètre pour calculer le nombre d’image par seconde

      For Local CoordonnesEnX = 1 To TailleEcranEnX

      ; Variables Local pour gagner en rapidité

      Local CameraEnX = 2*CoordonnesEnX/TailleEcranEnX-1

      Local PositionEnXduLancerdeRayon = PositionEnXSurCarte

      Local PositionEnYduLancerdeRayon = PositionEnYSurCarte

      Local DirectionEnXduLancerDeRayon = DirectionEnX + planex*CameraEnX

      Local DirectionEnYduLancerDeRayon = DirectionEnY + planey*CameraEnX

      Local CarteEnX = Int(PositionEnXduLancerdeRayon)

      Local CarteEnY = Int(PositionEnYduLancerdeRayon)

      Local DistanceLateraleEnX = 0

      Local DistanceLateraleEnY = 0

      Local deltadistx = Sqrt(1+(DirectionEnYduLancerDeRayon*DirectionEnYduLancerDeRayon)/(DirectionEnXduLancerDeRayon*DirectionEnXduLancerDeRayon))

      Local deltadisty = Sqrt(1+(DirectionEnXduLancerDeRayon*DirectionEnXduLancerDeRayon)/(DirectionEnYduLancerDeRayon*DirectionEnYduLancerDeRayon))

      Local Perspective = 0

      Local stepx = 0

      Local stepy = 0

      Local MurTouche = 0

      Local CoteDuMur = 0

      ; Début des tests du raycasting (lancé de rayon)

      If DirectionEnXduLancerDeRayon < 0

      stepx = -1

      DistanceLateraleEnX = (PositionEnXduLancerdeRayon – CarteEnX)*deltadistx

      Else

      stepx = 1

      DistanceLateraleEnX = (CarteEnX + 1 – PositionEnXduLancerdeRayon)*deltadistx

      EndIf

      If DirectionEnYduLancerDeRayon < 0

      stepy = -1

      DistanceLateraleEnY = (PositionEnYduLancerdeRayon – CarteEnY)*deltadisty

      Else

      stepy = 1

      DistanceLateraleEnY = (CarteEnY + 1 – PositionEnYduLancerdeRayon)*deltadisty

      EndIf

      ; On test si lorsque l’on bouge, on touche un mur de la carte

      While MurTouche = 0  ; Tant qu’il n’y a pas de mur

      ;

      If DistanceLateraleEnX < DistanceLateraleEnY

      DistanceLateraleEnX = DistanceLateraleEnX + deltadistx

      CarteEnX = CarteEnX + stepx

      CoteDuMur = 0

      Else

      DistanceLateraleEnY = DistanceLateraleEnY + deltadisty

      CarteEnY = CarteEnY + stepy

      CoteDuMur = 1

      EndIf

      ;

      If CarteDuJeux[CarteEnX][CarteEnY] > 0 Then MurTouche = 1

      ;

      Wend ; fin du test de tant qu’il y a pas de mur

      ; Il est plus rapide de multiplier par 0.5 que de diviser par 2

      If CoteDuMur = 0

      Perspective = Abs((CarteEnX – PositionEnXduLancerdeRayon + (1-stepx)*0.5)/DirectionEnXduLancerDeRayon)

      Else

      Perspective = Abs((CarteEnY – PositionEnYduLancerdeRayon + (1-stepy)*0.5)/DirectionEnYduLancerDeRayon)

      EndIf

      ;

      If Perspective=0 Then Perspective=1

      HauteurLigne = Int(TailleEcranEnY/Perspective)

      DepartLigne = (-HauteurLigne*0.5 + TailleEcranEnY*0.5)

      ;

      If DepartLigne <0 Then DepartLigne=0

      ;

      FinLigne = (HauteurLigne*0.5 + TailleEcranEnY*0.5)

      ;

      If FinLigne >= TailleEcranEnX Then FinLigne = TailleEcranEnX

      ; En fonction de la valeur du mur dans la carte, on change la couleur du mur

      Switch(CarteDuJeux[CarteEnX][CarteEnY])

      ;

      Case 1:  Couleur = $AA2222 ; Rouge

      Case 2:  Couleur = $22AA22 ; Vert

      Case 3:  Couleur = $2222AA ; Bleu

      Case 4:  Couleur = $AAAAAA ; Blanc

      Default: Couleur = $AAAA22 ; Jaune

      ;

      EndSwitch

      ; Variable global pour les couleurs sauf celles des murs

      Local CouleurSol = $444444

      Local CouleurPlafond = $888888

      Local CouleurBandes = $666666

      ;

      If CoteDuMur = 1

      Couleur=Couleur*0.5

      CouleurBandes = CouleurBandes *0.5

      EndIf

      ; Encore du local pour la rapiditée

      Local BandeHaut = TailleEcranEnY/2+FinLigne

      Local BandeBas = TailleEcranEnY/2+DepartLigne

      ; On trace les lignes pour créer la perspective

      Line (CoordonnesEnX,DepartLigne,CoordonnesEnX,FinLigne,Couleur); Mur

      Line (CoordonnesEnX,FinLigne,CoordonnesEnX,FinLigne+240,CouleurSol) ; Sol

      Line (CoordonnesEnX,0,CoordonnesEnX,DepartLigne,CouleurPlafond) ; Plafond

      Line (CoordonnesEnX,BandeHaut*0.5,CoordonnesEnX,BandeHaut*0.5,CouleurBandes) ; Trait haut des murs

      Line (CoordonnesEnX,TailleEcranEnY*0.5,CoordonnesEnX,TailleEcranEnY*0.5,CouleurBandes); Trait du milieu des murs

      Line (CoordonnesEnX,BandeBas*0.5,CoordonnesEnX,BandeBas*0.5,CouleurBandes) ; Trait bas des murs

      ; Fin de la boucles

      Next

      ; Test si on appuie sur la touche flèche « Haut »

      If IsKeyDown(« Up »)=True

      ;

      If CarteDuJeux[Int(PositionEnXSurCarte + DirectionEnX * VitesseDeDeplacement)][Int(PositionEnYSurCarte)] = 0 Then PositionEnXSurCarte = PositionEnXSurCarte + DirectionEnX * VitesseDeDeplacement

      If CarteDuJeux[Int(PositionEnXSurCarte)][Int(PositionEnYSurCarte + DirectionEnY * VitesseDeDeplacement)] = 0 Then PositionEnYSurCarte = PositionEnYSurCarte + DirectionEnY * VitesseDeDeplacement

      ;

      EndIf

      ; Test si on appuie sur la touche flèche « Bas »

      If IsKeyDown(« Down »)=True

      If CarteDuJeux[Int(PositionEnXSurCarte + DirectionEnX * VitesseDeDeplacement)][Int(PositionEnYSurCarte)] = 0 Then PositionEnXSurCarte = PositionEnXSurCarte – DirectionEnX * VitesseDeDeplacement

      If CarteDuJeux[Int(PositionEnXSurCarte)][Int(PositionEnYSurCarte + DirectionEnY * VitesseDeDeplacement)] = 0 Then PositionEnYSurCarte = PositionEnYSurCarte – DirectionEnY * VitesseDeDeplacement

      EndIf

      ; Test si on appuie sur la touche flèche « Gauche »

      If IsKeyDown(« Left »)=True

      ;

      AncienneDirectionEnX=DirectionEnX

      DirectionEnx = DirectionEnX * Cos(-VitesseDeLaRotation) – DirectionEnY * Sin(-VitesseDeLaRotation);

      DirectionEnY = AncienneDirectionEnX * Sin(-VitesseDeLaRotation) + DirectionEnY * Cos(-VitesseDeLaRotation);

      oldPlaneX = planex;

      planex = planex * Cos(-VitesseDeLaRotation) – planey * Sin(-VitesseDeLaRotation);

      planey = oldPlaneX * Sin(-VitesseDeLaRotation) + planey * Cos(-VitesseDeLaRotation);

      EndIf

      ; Test si on appuie sur la touche flèche « Droite »

      If IsKeyDown(« Right »)=True

      ;

      AncienneDirectionEnX = DirectionEnX ;

      DirectionEnx = DirectionEnX * Cos(VitesseDeLaRotation) – DirectionEnY * Sin(VitesseDeLaRotation);

      DirectionEnY = AncienneDirectionEnX * Sin(VitesseDeLaRotation) + DirectionEnY * Cos(VitesseDeLaRotation);

      oldPlaneX = planex;

      planex = planex * Cos(VitesseDeLaRotation) – planey * Sin(VitesseDeLaRotation);

      planey = oldPlaneX * Sin(VitesseDeLaRotation) + planey * Cos(VitesseDeLaRotation);

      EndIf

      ; Calcule simple du FPS

      Local Temps=GetTimer(1)

      Local FPS=Int((1/Temps)*1000)

      ; Affichage du FPS

      TextOut(0,0,FPS)

      ; Flip d’écran (technique du double buffer)

      Flip

      ; Effacer l’écran est inutile, puisque l’on retrace par dessus l’ancienne image

      ; donc la commande Cls ne sert à rien, encore du temps de gagner

      ;

      ; Fin de la fonction principale

      EndFunction

      ; Lancement du moteur Double Buffer, toujours en dehors de fonction

      BeginDoubleBuffer

      ; Configuration de l’intervalle Maximale de temps entre l’affichage de chaque image, ici 50 FPS

      SetInterval(1,PRG,20)

      ; Boucle infinie pour que le programme ne se termine jamais

      Repeat

      WaitEvent() ; Attendre une action, ici, se sera les touches fléchées du clavier

      Forever
      Amusez-vous bien

       

      Le moteur tourne à 80 FPS, mais avec un peux d’optimisation, il peut tourner à 200Fps…. sur ma config PC bien sûr

       

      Edit : Si quelqu’un pouvais modifier les balises pour le départ du code car sa marche mais pas du tout se serait sympa… un codeur Hollywood reste un codeur de merde dixit bigard en manger un steack haché préparer sur une hacheuse piloter par AOS 4.x

      Screetch

        #176439

        Houuu, je sens que je vais regarder ce code de prêt pour voir à améliorer le miens qui me fait un bug d’eyefish très désagréable !

        Abonnez-vous à ma nouvelle chronique "En Route vers le Futur" sur Youtube !

        Anonyme

          #176443

          hum sur Amos…

          hum….

          je saurais pas faire…

          Anonyme

            #176450

            @screetch:

             

            L’effet eyefish, je l’ai eu, mais je sais plus comment j’ai fait pour l’enlever…. je crois si je m’en souvient que c’est du soit à la position de la caméra

             

            Pour ne pas marcher en crabe, ne pas oublier le -1 sur la ligne

            Local CameraEnX = 2*CoordonnesEnX/TailleEcranEnX-1

            Pour la commance Switch, en fait on remplace chaque cas par un test

             

            le bloc de cmd est le suivant

            Switch(CarteDuJeux[CarteEnX][CarteEnY])

            ;

            Case 1:  Couleur = $AA2222 ; Rouge

            Case 2:  Couleur = $22AA22 ; Vert

            Case 3:  Couleur = $2222AA ; Bleu

            Case 4:  Couleur = $AAAAAA ; Blanc

            Default: Couleur = $AAAA22 ; Jaune

            ;

            EndSwitch

             

            Ce code peut être remplacer par des conditions (est en plus c’est plus rapide) [corriger grâce à Tcheko]

            ex

            If CarteDuJeux[CarteEnX][CarteEnY]=1 then Couleur = $AA2222

            Etc… pour chaque cas

             

            @Hivernaal: Quasi aucune commande ne diffère de l’amos

             

            @screen=openscreen

            Pour les tables, utilise Dim

            pour remplacer le tracage

            Line (CoordonnesEnX,DepartLigne,CoordonnesEnX,FinLigne,Couleur); Mur

            on fait (si je me souvient bien)

            Pen 1,couleur

            Line CoordonnesEnX,DepartLigne to CoordonnesEnX,FinLigne

            Je crois que c’est pen, pas sur car je confond souvent l’Amos avec le basic loco

             

            Pour accélérer le code, précalculer les sin/cos

            ex :

            DirectionEnx = DirectionEnX * Cos(-VitesseDeLaRotation) – DirectionEnY * Sin(-VitesseDeLaRotation);

            La variable VitesseDeLaRotation est en fait une constante, donc on peux précalculer Cos(-VitesseDeLaRotation) et mettre la valeur dans une table, sa évite, lorsque l’on appuie sur la touche directionnel Gauche ou droite de refaire du sin cos

             

            Ex: Avant la boucle Principale on fait

            Dim Calcule[4]

            Calcule[0]=Sin(VitesseDeLaRotation)

            Calcule[1]=Cos(VitesseDeLaRotation)

            Calcule[2]=Cos(-VitesseDeLaRotation)

            Calcule[3]=Sin(-VitesseDeLaRotation)

             

            et dans le test If IsKeyDown, on a

            DirectionEnx = DirectionEnX * Cos(-VitesseDeLaRotation) – DirectionEnY * Sin(-VitesseDeLaRotation);

            on remplace par :

            DirectionEnx = DirectionEnX * Calcule[1] – DirectionEnY * Calcule[3]

             

            Et voila, plus de calcul avec cos et on gagne beaucoup de temps… surtout pas de variable global, sinon encore plus simple…

             

            On prend sa calculette et on remplace Calcule[1] par la vrai valeur puisque vitessedelarotation est tjrs la même 😉

             

            Sur Amos, je crois que l’on ne différencie pas les variables locales (interne à une boucle) à une variable globale (interne au programme=plus lente), donc pas de déclaration local devant les variables

             

            Petit truc aussi, c’est plus rapide avec hollywood de * par 0.5 que de diviser par 2

             

            Dans le prg il y a des variables globales inutiles qui font ralentir le moteur comme les variables globale TailleEcranEnX=639

            et TailleEcranEnY=479, il suffit de mettre la taille directement dans les formules (sauf si on vaut que sont prg puisse s’ouvrir sur n’importe quelle format d’écran bien sûr)

            Et il y a encore bien d’autre chose 😉

             

            Mod

            Tcheko

              #176451

              http://w3.restena.lu/amifra/exos/orth/regsece.htm

              Les se en ce et les ce en se me piquent les yeux.

              Anonyme

                #176452

                Si vous voyez des fotes d’ortaugraffes ou de congeuguézon, ou autres, merci de le faire savoir, le code en fait… on s’en fou

                 

                😀

                 

                Si sa intéresse quelqu’un qui veux utiliser se code, enlever les 2 lignes

                Line (CoordonnesEnX,FinLigne,CoordonnesEnX,FinLigne+240,CouleurSol) ; Sol

                Line (CoordonnesEnX,0,CoordonnesEnX,DepartLigne,CouleurPlafond) ; Plafond

                Pas besoin du sol et du plafond, par contre, dès le début de la boucle principale, mettre sa:

                 

                SetFillStyle(#FILLCOLOR)

                Box(0, 0, TailleEcranEnX+ 1, ((TailleEcranEnY+ 1) >>1), $6666DD)

                Box(0, #BOTTOM, TailleEcranEnX + 1, ((TailleEcranEnY+ 1) >>1), $999900)

                 

                Sa trace 2 rectangle qui se partage la moitié de l’écran donc tjrs out le Cls, et on peut choisir la couleur du plafond et du sol sans tracer 1 milliard de lignes supplémentaires

                 

                et hop, on passe de 80 à 120 FPS… Cooool

                 

                 

                Anonyme

                  #176453

                  oui les fautes ça pique les yeux….

                  AmiDARK

                    #176475

                    Si cela vous intéresse, je peux mettre en ligne mon vieux moteur 3D que j’avais commencé pour Amiga 68k en assembleur …
                    Cela pourait peut-être aider ?

                    @+

                    Tarzin

                      #176503

                      @Artblink,

                      Ah, je vois que tu t’y remets, c’est bien.

                      pas encore trouvé le temps de mon côté et c’est dommage car avec la tripoté de nouveautés sur Hollywood, il y a de quoi faire.

                      Tu peux me mettre ça dans notre Dropbox Hollywood pour que je jette un oeil?
                      Merci!

                      Anonyme

                        #176536

                        @Tarzin:

                         

                        Yes, je pense optimiser ce moteur assez facilement.

                        Mais le moteur sera plus rapide avec de la texture!!! Yes, normal, vu la gestion mémoire d’Hollywood complètement bizarroïde.

                         

                        Bref, j’y retourne d’ici peu et je le poste (+ upload compte DropBox)

                        A+

                        Anonyme

                          #176569

                          @screetch: post le code, comme sa on verra ensemble se qui va pas a ton moteur 😉

                          stefff285

                            #176573

                            bonjour a tous ! oué je vais essayer ce code cet aprem sur mon aresone !

                            on va voir ce que cela donne sur un bo proc athlon

                            bref bravo artlink et bonjour a toi ainsi qu’a tout le monde

                             

                            yo

                            Anonyme

                              #176638

                              Merci Steff

                              Pour expliquer comment fonctionne se moteur basé sur le même site que screetch à vu, sur 640 lignes (la taille en X de l’écran) on calcule la valeur du point le plus haut du mur en Y (la valeur de la variable DebutLigne) et la valeur du point le plus bas du mur en Y (la valeur de la variable FinLigne) et on trace un trait verticale de longueur FinLigne-DebutLigne qui commencera à la coordonnée Y=DebutLigne  pour chaque coordonnée en X de l’écran soit 640 trait (une boucle for de 0 à 639)

                               

                              Voilà

                               

                               

                              Screetch

                                #176665

                                Mon code provient principalement d’un vieux article de 2 pages dans (Amiga) Dream qui donnait les bases théoriques d’un tel moteur.

                                Je mettrais bien ici mon code (SDL Basic) mais il est relativement long et il est codé salement à l’arrache ! Il mériterait d’être bien amélioré ^^.

                                Je vais essayer de le poster dans la journée.

                                Abonnez-vous à ma nouvelle chronique "En Route vers le Futur" sur Youtube !

                                Anonyme

                                  #177005

                                  Kikou Screetch,

                                   

                                  T’as réussi à modifier ton prg? il fonctionne?

                                   

                                  A+

                                15 sujets de 1 à 15 (sur un total de 28)

                                • 1
                                • 2
                                • Vous devez être connecté pour répondre à ce sujet.

                                Forums AmigaOS, MorphOS et AROS Développement Moteur Raycasting

                                Amiga Impact