Champs de vision, premiers tests
dans la rubrique Dev
←
/ #66
/ rss
/ →
J'ai commencé à mettre en place le champ de vision en mode Zone. Je me suis inspiré de l'algorithme de Brensenham, que j'ai trouvé ici: http://mail.python.org/pipermail/python-list/1999-July/007163.html
Ray Tracing
Je l'ai simplement adapté pour que le calcul de la ligne soit toujours valable dans un monde où la gauche et la droite sont connectés, ainsi que le haut et le bas:
def Brensenham_line(pos1, pos2, taille):
"""
D'après l'algorithme :
Brensenham line algorithm, par Phillip Lenhardt
http://mail.python.org/pipermail/python-list/1999-July/007163.html
"""
steep = 0
coords = []
x,y,x2,y2 = pos1[0], pos1[1], pos2[0], pos2[1]
if x2 > x + taille/2:
x += taille
if x > x2 + taille/2:
x2 += taille
if y2 > y + taille/2:
y += taille
if y > y2 + taille/2:
y2 += taille
dx = abs(x2 - x)
if (x2 - x) > 0:
sx = 1
else:
sx = -1
dy = abs(y2 - y)
if (y2 - y) > 0:
sy = 1
else:
sy = -1
if dy > dx:
steep = 1
x,y = y,x
dx,dy = dy,dx
sx,sy = sy,sx
d = (2 * dy) - dx
for i in range(0,dx):
if steep:
coords.append((Replace(y, taille), Replace(x, taille)))
else:
coords.append((Replace(x, taille), Replace(y, taille)))
while d >= 0:
y = Replace(y + sy, taille)
d = d - (2 * dx)
x = Replace(x + sx, taille)
d = d + (2 * dy)
return coords
Cette fonction, qui accepte en entrée les deux positions pos1 et pos2, et la taille du monde taille, fourni en sortie la liste des positions formant une ligne entre pos1 et pos2.
On utilise ensuite cette fonction pour tracer une ligne imaginaire entre le joueur et chaque case affichée. Si on rencontre une case au travers de laquelle on ne peut pas regarder, la valeur booléenne vue_libre devient fausse, et toutes les cases situées derrière ne seront pas visibles.
vue_libre = True
if [xx, yy] <> self.pos:
for pos in el.Brensenham_line(self.pos, (xx, yy), self.jeu.cfg.taille_zone * self.monde.taille)[1:]:
# On évalue chaque pos entre le joueur et (xx, yy)
zone, posxy = self.l1(pos)
vue_libre = zone.Est_Visible(posxy)
if not vue_libre:
break
self.pos est la position du joueur dans le monde, et (xx, yy) la position de la case qu'on veut afficher à l'écran. Le test if xx, yy == self.pos: est juste une exception pour ne pas prendre en compte la case courante.
Grille sur tuile
Ensuite, si vue_libre est vrai, la tuile est affichée normalement, sinon elle est affichée avec une grille dessus. Les objets et les animaux ne sont ensuite affichées que sur les cases visibles.
L'affichage de la grille est ce qui me pose le plus de problème. Il s'agit pourtant simplement d'afficher un quadrillage sur la partie de la tuile qui n'est pas transparente, mais je n'ai pas encore trouvé de moyen élégant (et rapide) pour le faire. Je passe par surfarray pour le faire, mais c'est lent et pas très propre:
tab1 = pygame.surfarray.pixels3d(self.tuile_iso[(xx,yy)])
tab2 = pygame.surfarray.pixels3d(self.monde.tiletech.tuile_iso_horsvue1)
tabres = ((tab1 * (tab1 <> [255, 0, 255])) & tab2) + ([255, 0, 255] * (tab1 == [255, 0, 255]))
surf = pygame.Surface((54, 54))
pygame.surfarray.blit_array(surf, tabres)
surf.set_colorkey((255, 0, 255))
Voila le résultat pour l'instant :










Commentaires
Aucun commentaire pour le moment.
Ajouter un commentaire