Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1804 connectés 

  FORUM HardWare.fr
  Programmation
  Python

  [Python] Petit programme de raycasting ( - de 3ko)

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Python] Petit programme de raycasting ( - de 3ko)

n°999524
Rasthor
Posté le 03-03-2005 à 13:49:25  profilanswer
 

(j'ai changé le titre, ça fait moins pompeux [:cupra])
 
 
Je me suis mis sérieusement au Python et je viens d'achever mon premier code original hier soir, donc c'est un peu la fête.   [:diskobeck]  
 
Enfin original est un bien grand mot, puisque je n'ai fait que retranscrire mot pour mot, variables pour variables, un programme Rebol, qui était donné en exemple dans un numéro de Login (Numéro 14 de Septembre 2002, pages 76-77).
 
Le principe du programme est bêtement un moteur de Raycasting, comme celui de Wolfenstein premier du nom.
 
Un screenshot ([:cupra]) :
http://img100.exs.cx/img100/1488/doomwdegrade8lv.png
 
 
Il faut aussi télécharger cette image:
http://img71.exs.cx/img71/421/degrade8ag.gif
 
Ca met un dégradé en fond d'image. Il faut le sauver sur le disque, le placer dans le même dossier que le script et le renommer en "degrade.gif".
 
 
 
 
 
Enfin bref, voici le code:

Code :
  1. #########################
  2. #                       #
  3. # Moteur de Raycasting  #
  4. #                       #
  5. #########################
  6. # Import de Tkinter et des fonctions trigo utilisees
  7. from Tkinter import *
  8. from math import cos, radians
  9. # Definition des variables
  10. px = 9 * 1024
  11. py = 11 * 1024
  12. stride = 5 # pas de deplacement 
  13. heading = 0  # angle de vue 
  14. turn = 10  # nombre de degres par rotation
  15. # Definition du labyrinthe.
  16. # 0 = sol ou l'on peut se deplacer
  17. # Plus grand que 0 = mur, et le chiffre defini la couleur
  18. laby = [[ 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7],
  19.         [ 7, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 8],
  20.         [ 8, 0, 0, 0, 12, 0, 0, 0, 14, 0, 9, 7],
  21.         [ 7, 0, 0, 0, 12, 0, 4, 0, 13, 0, 0, 8],
  22.         [ 8, 0, 4, 11, 11, 0, 3, 0, 0, 0, 0, 7],
  23.         [ 7, 0, 3, 0, 12, 3, 4, 3, 4, 3, 0, 8],
  24.         [ 8, 0, 4, 0, 0, 0, 3, 0, 3, 0, 0, 7],
  25.         [ 7, 0, 3, 0, 0, 0, 4, 0, 4, 0, 9, 8],
  26.         [ 8, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 7],
  27.         [ 7, 0, 5, 6, 5, 6, 0, 0, 0, 0, 0, 8],
  28.         [ 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7],
  29.         [ 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7]]
  30. # Palette de couleur. La valeur du mur defini la valeur de la couleur.
  31. palette = ["#000080","#008000","#008080",
  32.            "#000080","#800080","#808000","#C0C0C0",
  33.            "#808080","#0000FF","#00FF00","#FFFF00",
  34.            "#0000FF","#FF00FF","#00FFFF","#FFFFFF"]
  35. # Table des cosinus precalcules. On gagne un peu en vitesse.
  36. ctable = []
  37. for a in range(0,(359+180)):
  38.     ctable.append(int((cos(radians(a))*1024)/10))
  39. # Fonction pour trouver le cosinu de l'angle v.
  40. def getangle(v):
  41.     return ctable[v+1]
  42. #####################################
  43. #
  44. # Moteur principal du raycasting
  45. #
  46. def retrace():
  47.     # On efface le labyrinthe
  48.     can1.delete('rectangle')
  49.     # On initialise les valeurs
  50.     xy1x = 0
  51.     xy1y = 0
  52.     xy2x = 0
  53.     xy2y = 0
  54.     angle = heading-44 % 360
  55.     if angle < 0:
  56.         angle = angle+360
  57.     # On parcout les 90 degres de l'angle de vue.
  58.     # On lance un rayon xx/yy et des qu'il touche un mur,
  59.     # on affiche un rectangle
  60.     for a in range(angle,angle+89):
  61.         xx = px
  62.         yy = py
  63.         stepx = getangle(a+90)
  64.         stepy = getangle(a)
  65.         l = 0
  66.         while 1:
  67.             xx = xx-stepx
  68.             yy = yy-stepy
  69.             l = l+1
  70.             colonne = int(xx/1024)
  71.             ligne = int(yy/1024)
  72.             # Instruction de controle:
  73.             # la boucle s'arrete si le rayon touche un mur (<> 0).
  74.             if laby[ligne][colonne] <> 0:
  75.                 break
  76.         # On calcule la hauteur du rectangle
  77.         h = int(900/l)
  78.         xy1y = 100-h
  79.         xy2y = 100+h
  80.         # Le rectangle fait 3 pixels de largeur
  81.         xy2x = xy1x + 3
  82.         # On determine la couleur du rectangle
  83.         color = palette[laby[ligne][colonne]]
  84.         # On affiche le rectangle et on recommence
  85.         can1.create_rectangle(xy1x, xy1y, xy2x, xy2y, fill=color,outline=color,tag='rectangle')
  86.         xy1x = xy2x+1
  87. ##################################
  88. #
  89. # Gestionnaire d'evenements :
  90. #
  91. # On determine les 4 fonctions possibles: avancer, reculer, tourner la tête
  92. # à droite et tourner la tête à gauche.
  93. def depl_avance(event):
  94.     global px, py
  95.     # On avance selon le pas "stride" determie au debut.
  96.     # On calcul le cosinus de l'angle en question.
  97.     newpx = px - getangle(heading+90)*stride
  98.     newpy = py - getangle(heading)*stride
  99.     c = int(newpx/1024)
  100.     l = int(newpy/1024)
  101.     # On controle si l'on peut se deplacer.
  102.     if laby[l][c] == 0:
  103.         px = newpx
  104.         py = newpy
  105.     retrace()
  106. def depl_recule(event):
  107.     global px, py
  108.     newpx = px - getangle(heading+90)*stride*-1
  109.     newpy = py - getangle(heading)*stride*-1
  110.     c = int(newpx/1024)
  111.     l = int(newpy/1024)
  112.     if laby[l][c] == 0:
  113.         px = newpx
  114.         py = newpy
  115.     retrace()
  116. def turn_left(event):
  117.     global heading
  118.     heading = (heading + (360 -turn)) % 360
  119.     retrace()
  120. def turn_right(event):
  121.     global heading
  122.     heading = (heading + turn) % 360
  123.     retrace()
  124. # Creation du canvas:
  125. fen1 = Tk()
  126. can1 = Canvas(fen1,bg="dark grey", height=200, width=360)
  127. # On charge le degrade de fond. C'est une image gif.
  128. # A ameliorer: degrade directement en python.
  129. if open("degrade.gif" ):
  130.     photo = PhotoImage(file="degrade.gif",width=360, height=200)
  131.     item = can1.create_image(0, 0, anchor=NW, image=photo)
  132. can1.pack()
  133. # On trace une premiere fois le labyrinthe
  134. retrace()
  135. # Liaison des evenements
  136. fen1.bind("<Up>",depl_avance)
  137. fen1.bind("<Down>",depl_recule)
  138. fen1.bind("<Left>",turn_left)
  139. fen1.bind("<Right>",turn_right)
  140. # demarrage du receptionnaire d'evenements (boucle principale) :
  141. fen1.mainloop()


 
 
Faut encore que je fasse un degradé en fond d'écran (quelqu'un saurait-il faire ceci ?), que je fusionne les commande avance et recule et que je le commente un peu plus. [:dao]
 
Sinon des avis sur le code en lui-même ? Des idées d'amélioration, d'optimisation ?
 
 
PS: le code pour le copier coller directement:
 
#########################
#                       #
# Moteur de Raycasting  #
#                       #
#########################
 
# Import de Tkinter et des fonctions trigo utilisees
 
from Tkinter import *
from math import cos, radians
 
# Definition des variables
 
px = 9 * 1024
py = 11 * 1024
stride = 5 # pas de deplacement    
heading = 0  # angle de vue  
turn = 10  # nombre de degres par rotation
 
# Definition du labyrinthe.
# 0 = sol ou l'on peut se deplacer
# Plus grand que 0 = mur, et le chiffre defini la couleur
laby = [[ 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7],
        [ 7, 0, 0, 0, 0, 0, 0, 0, 13, 0, 0, 8],
        [ 8, 0, 0, 0, 12, 0, 0, 0, 14, 0, 9, 7],
        [ 7, 0, 0, 0, 12, 0, 4, 0, 13, 0, 0, 8],
        [ 8, 0, 4, 11, 11, 0, 3, 0, 0, 0, 0, 7],
        [ 7, 0, 3, 0, 12, 3, 4, 3, 4, 3, 0, 8],
        [ 8, 0, 4, 0, 0, 0, 3, 0, 3, 0, 0, 7],
        [ 7, 0, 3, 0, 0, 0, 4, 0, 4, 0, 9, 8],
        [ 8, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 7],
        [ 7, 0, 5, 6, 5, 6, 0, 0, 0, 0, 0, 8],
        [ 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7],
        [ 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7]]
 
# Palette de couleur. La valeur du mur defini la valeur de la couleur.
palette = ["#000080","#008000","#008080",
           "#000080","#800080","#808000","#C0C0C0",
           "#808080","#0000FF","#00FF00","#FFFF00",
           "#0000FF","#FF00FF","#00FFFF","#FFFFFF"]
 
# Table des cosinus precalcules. On gagne un peu en vitesse.
ctable = []
for a in range(0,(359+180)):
    ctable.append(int((cos(radians(a))*1024)/10))
 
# Fonction pour trouver le cosinu de l'angle v.
def getangle(v):
    return ctable[v+1]
 
#####################################
#
# Moteur principal du raycasting
#
 
def retrace():
    # On efface le labyrinthe
    can1.delete('rectangle')
    # On initialise les valeurs
    xy1x = 0
    xy1y = 0
    xy2x = 0
    xy2y = 0
    angle = heading-44 % 360
    if angle < 0:
        angle = angle+360
    # On parcout les 90 degres de l'angle de vue.
    # On lance un rayon xx/yy et des qu'il touche un mur,
    # on affiche un rectangle
    for a in range(angle,angle+89):
        xx = px
        yy = py
        stepx = getangle(a+90)
        stepy = getangle(a)
        l = 0
        while 1:
            xx = xx-stepx
            yy = yy-stepy
            l = l+1
            colonne = int(xx/1024)
            ligne = int(yy/1024)
            # Instruction de controle:
            # la boucle s'arrete si le rayon touche un mur (<> 0).
            if laby[ligne][colonne] <> 0:
                break
        # On calcule la hauteur du rectangle
        h = int(900/l)
        xy1y = 100-h
        xy2y = 100+h
        # Le rectangle fait 3 pixels de largeur
        xy2x = xy1x + 3
        # On determine la couleur du rectangle
        color = palette[laby[ligne][colonne]]
        # On affiche le rectangle et on recommence
        can1.create_rectangle(xy1x, xy1y, xy2x, xy2y, fill=color,outline=color,tag='rectangle')
        xy1x = xy2x+1
 
##################################
#
# Gestionnaire d'evenements :
#
 
# On determine les 4 fonctions possibles: avancer, reculer, tourner la tête
# à droite et tourner la tête à gauche.
 
 
def depl_avance(event):
    global px, py
    # On avance selon le pas "stride" determie au debut.
    # On calcul le cosinus de l'angle en question.
    newpx = px - getangle(heading+90)*stride
    newpy = py - getangle(heading)*stride
    c = int(newpx/1024)
    l = int(newpy/1024)
    # On controle si l'on peut se deplacer.
    if laby[l][c] == 0:
        px = newpx
        py = newpy
    retrace()
def depl_recule(event):
    global px, py
    newpx = px - getangle(heading+90)*stride*-1
    newpy = py - getangle(heading)*stride*-1
    c = int(newpx/1024)
    l = int(newpy/1024)
    if laby[l][c] == 0:
        px = newpx
        py = newpy
    retrace()
def turn_left(event):
    global heading
    heading = (heading + (360 -turn)) % 360
    retrace()
def turn_right(event):
    global heading
    heading = (heading + turn) % 360
    retrace()
 
 
# Creation du canvas:
 
fen1 = Tk()
can1 = Canvas(fen1,bg="dark grey", height=200, width=360)
# On charge le degrade de fond. C'est une image gif.
# A ameliorer: degrade directement en python.
if open("degrade.gif" ):
    photo = PhotoImage(file="degrade.gif",width=360, height=200)
    item = can1.create_image(0, 0, anchor=NW, image=photo)
can1.pack()
# On trace une premiere fois le labyrinthe
retrace()
# Liaison des evenements
fen1.bind("<Up>",depl_avance)
fen1.bind("<Down>",depl_recule)
fen1.bind("<Left>",turn_left)
fen1.bind("<Right>",turn_right)
 
# demarrage du receptionnaire d'evenements (boucle principale) :
fen1.mainloop()


Message édité par Rasthor le 04-03-2005 à 23:57:50
mood
Publicité
Posté le 03-03-2005 à 13:49:25  profilanswer
 

n°1000151
printf
Baston !
Posté le 03-03-2005 à 21:21:01  profilanswer
 

Le John Carmack suisse :D

n°1000157
Rasthor
Posté le 03-03-2005 à 21:34:04  profilanswer
 

printf a écrit :

Le John Carmack suisse :D


 :D  
Je précise encore une fois que je n'ai strictement rien inventé. J'ai repris ce programme de Login, qui l'a surement repris de John Carmack.  :jap:

n°1000251
Evadream -​jbd-
Posté le 03-03-2005 à 23:33:24  profilanswer
 

C'est très chouette :)

n°1000275
Rasthor
Posté le 04-03-2005 à 00:12:09  profilanswer
 

New version !!!
 
 
Pour ceux qui veulent avoir un truc plus "style", téléchargez cette image:
http://img71.exs.cx/img71/421/degrade8ag.gif
http://img71.exs.cx/img71/421/degrade8ag.gif
 
Ca met un dégradé en fond d'image. Il faut le sauver sur le disque, le placer dans le même dossier que le script et le renommer en "degrade.gif".
 
 
Ensuite, il faut modifier le code. Il faut ajouter ces deux lignes entre les lignes 110 et 111:
 
photo = PhotoImage(file="degrade.gif",width=360, height=200)
item = can1.create_image(0, 0, anchor=NW, image=photo)
 
 
 
Et voici le résultat:
http://img100.exs.cx/img100/1488/doomwdegrade8lv.png


Message édité par Rasthor le 04-03-2005 à 02:29:12
n°1000316
0x90
Posté le 04-03-2005 à 02:30:44  profilanswer
 

Est-ce que tu pourrais expliquer/commenter ce que fait exactement le code ( quelle est la logique pour rendre une telle image ) stp ?

n°1000320
Rasthor
Posté le 04-03-2005 à 02:39:04  profilanswer
 

0x90 a écrit :

Est-ce que tu pourrais expliquer/commenter ce que fait exactement le code ( quelle est la logique pour rendre une telle image ) stp ?


Ouaip, je le ferais demain, promis. ;)

n°1000321
tet2neu
emmerdeur
Posté le 04-03-2005 à 03:10:58  profilanswer
 

Kikoo drapalesque :o

n°1001245
Rasthor
Posté le 04-03-2005 à 20:05:03  profilanswer
 

Voila, j'ai ajouté quelques commentaires dans le code. Je vais essayer d'en rajouter un peu plus ce soir.
 
 
Si vous avez des questions, n'hésitez pas. :hello:

n°1001268
Mr Mala
Posté le 04-03-2005 à 20:29:12  profilanswer
 

Nan .. pas de questions ..  
Par contre, je dis [:sarah connor] !
J'espère que tu vas continuer à nous abbreuver de ce genre de petits programmes très sympathiques ! :D

mood
Publicité
Posté le 04-03-2005 à 20:29:12  profilanswer
 

n°1001273
Rasthor
Posté le 04-03-2005 à 20:32:45  profilanswer
 

Mr Mala a écrit :

Nan .. pas de questions ..  
Par contre, je dis [:sarah connor] !

Merci. Mais c'était facile, vu que j'avais tout sous la main. Par contre, j'ai un autre projet en tête, mais bien, bien plus lourd et plus sérieux que celui-ci. :D
(mais qui n'a rien à voir avec ce genre de programme)

Citation :

J'espère que tu vas continuer à nous abbreuver de ce genre de petits programmes très sympathiques ! :D

Si je trouve des idées, pourquoi pas.  :sol:  
 
A part ça, je suis un peu déçu du faible nombre de posts dans cette rubrique Python.  
 :(  
Y'aurait pourtant de quoi faire nettement plus.


Message édité par Rasthor le 04-03-2005 à 20:33:13
n°1001281
Mr Mala
Posté le 04-03-2005 à 20:44:06  profilanswer
 

Ben faut peut-être lancer la machine ?
D'autant plus qu'en voyant ça, tout doucement envie de m'y mettre moi ! [:huit]

n°1001289
Rasthor
Posté le 04-03-2005 à 20:56:38  profilanswer
 

Mr Mala a écrit :

Ben faut peut-être lancer la machine ?

Ouaip. :D

Citation :

D'autant plus qu'en voyant ça, tout doucement envie de m'y mettre moi ! [:huit]

C'est clair, c'est graphique, ludique, ça donne envie.
 
Tu programmes dans quel(s) langage(s) actuellement ?

n°1001352
Mr Mala
Posté le 04-03-2005 à 22:28:26  profilanswer
 

Rasthor a écrit :

Tu programmes dans quel(s) langage(s) actuellement ?


 
Ben .. mmmmmmmmh .. je sais pas comment je dois te dire ça .. mmmmmmh ... ActionScript :whistle:  
( entre autre .. mais principalement .. cf ma signature - Chemistry - pour avoir une idée plus précise :p )


Message édité par Mr Mala le 04-03-2005 à 22:28:50
n°1001446
Rasthor
Posté le 04-03-2005 à 23:21:42  profilanswer
 

Mr Mala a écrit :

Ben .. mmmmmmmmh .. je sais pas comment je dois te dire ça .. mmmmmmh ... ActionScript :whistle:  
( entre autre .. mais principalement .. cf ma signature - Chemistry - pour avoir une idée plus précise :p )

C'est toi qui l'a fait ? Sympa.  :)  
 
Mais Python, c'est mieux. :D

n°1007271
Kristoph
Posté le 09-03-2005 à 20:39:34  profilanswer
 

C'est vraiment cool ça. Quand est ce qu'on a la version avec textures et avec forme plus arbitraires comme dans Doom 1 ? :D

n°1007610
Rasthor
Posté le 10-03-2005 à 00:33:45  profilanswer
 

Kristoph a écrit :

C'est vraiment cool ça. Quand est ce qu'on a la version avec textures et avec forme plus arbitraires comme dans Doom 1 ? :D


Je peux vite essayer de coder ça. ;)

n°1346174
eltoto37
Posté le 13-04-2006 à 15:41:17  profilanswer
 

Rasthor a écrit :

Je peux vite essayer de coder ça. ;)


 
ca serait super cool
tres utilise cette source..

n°1349299
Profil sup​primé
Posté le 19-04-2006 à 01:18:18  answer
 

juste une petite suggestion... ca a l'air de rien, parce que la c'est du precalcul, mais quand même, pour la route :)
 

Code :
  1. # Table des cosinus precalcules. On gagne un peu en vitesse.
  2. ctable = []
  3. for a in range(0,(359+180)):
  4.     ctable.append(int((cos(radians(a))*1024)/10))
  5. # Fonction pour trouver le cosinu de l'angle v.
  6. def getangle(v):
  7.     return ctable[v+1]


 
le truc, c'est que cos(a) est compris entre -1 et 1 modulo Pi donc, il te suffi de calculer la moitiée... ce qui deviendrait
 

Code :
  1. # Table des cosinus precalcules. On gagne un peu en vitesse.
  2. ctable = []
  3. for a in range(0,180):
  4.     ctable.append(int((cos(radians(a))*512)/5))
  5. # Fonction pour trouver le cosinu de l'angle v.
  6. def getangle(v):
  7.     return ctable[abs(v)+1] # ou simplement un test...


 
on peut même aller jusqu'a ne calculer qu'un quart de cercle...

n°1372609
leto
Posté le 22-05-2006 à 21:56:36  profilanswer
 

Rendu différent chez moi :??: :  
http://let0.free.fr/temp_ray.png

n°1372620
zapan666
Tout est relatif
Posté le 22-05-2006 à 22:03:54  profilanswer
 

Il est où le problème ?  :??:  
 
 
Bon, sinon, il y a quelque temps, j'ai repris le script python et l'article Rebol que j'avais aussi, j'ai adapté ça en java, ça marche. et y'a 2 semaines, j'ai essayé le "Write Once, Run Every Where" de java, en faisiant une version J2ME
 
et ça marche  [:totoz]  
 
http://img422.imageshack.us/img422/2388/j2me23if.png
 
 [:mullet] Ca sert bien evidement a rien
 
 
(désoler pour le screen un peu grand...)


Message édité par zapan666 le 22-05-2006 à 22:04:32

---------------
my flick r - Just Tab it !
mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Python

  [Python] Petit programme de raycasting ( - de 3ko)

 

Sujets relatifs
Besoin d'aide pour un petit script[resolu]petit pb de structures...
[C++/SQL./Oracle] Juste un petit problème de chaine...[PHP] Petit problème avec les checkbox
petit defi, réelle optimisation[PYTHON] 2 listebox & 1 scrollbar
Vidage de dossiers local & setting via programmePetit projet
Programme Accessbesoin d'aide pour un programme
Plus de sujets relatifs à : [Python] Petit programme de raycasting ( - de 3ko)


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR