[Jeu 2D]-Rol'An'Go ARENA-[réalisé en VB6-DX8] - Jeu de Rôle tactique - Action

Répondre
Partager Rechercher
l'autre, il me parle de charabia et derrière il me link du VB , mais il était bien entendu pas question de changé de langage au milieu d'un projet, mais pour les projets suivants je te conseille de changé.

je vais approfondir un peut la collaborative diffusion vu que j'ai découvert ça récemment et ça a changé ma vie en terme de perf et de simplicité de dev pour tout ce qui est des pathfinding.

le joueur difuse son "odeur" sur la map, concrètement, chaque case à une valeur d'odeur, à chaque frame tu applique ton odeur de manière récursive sur les case autour de ton personnage en diminuant l'intensité avec la distance, chaque case ayant des propriété de diffusion différente (certaines laissent bien passé l'odeur, d'autre la coupe complètement)
le code de pathfinding et la zone d'agro sont terminé!
il suffit de réveiller ton IA quand l'odeur atteint un certain seuil et elle à juste à toujours se déplacer vers la valeur la plus élevé autour de sa position. (tu à une complexité casi-constante en fonction du nombre d'IA, la ou un A* est linéaire!)

la ou ça deviens intéressant, c'est que tu peut ajouté de la répulsion sur les monstre. cette zone de répulsion fait que les IA essayent naturellement d'encercler le joueur quand elle sont nombreuse plutôt que de lui courir dessus toute en ligne droite(d'ou le "collaborative").

les limites:
toute les IA doivent avoir le même objectif, sinon chaque objectif doit être sur un layer de map différent (par exemple un A* est beaucoup plus modulable, une unité de plus d'une case peut avoir facilement sont pathfinding dédié pour éviter les trou);
ça alourdis légèrement la map;
zone d'agro et répulsion pas forcément compatible;
la complexité est linaire sur le nombre d'élément qui diffuse ou répulse, ainsi que sur la quantité de layer malgré tout

après tu peut complexifié ton algo pour ajouter des comportement de groupe varié, tu peut par exemple avoir de la panique contagieuse sur un layer (ou un "énervement" des monstres).
ou encore certains objet peuvent contribué à modifié la map d'odeur, par exemple, pour un jeu de zombie, tu peut avoir des lampes qui repulse, du coup les zombie évitent naturellement la zone de lumière mais si tu rentre dedans ils te suivent.

ps: pour le blog je peut pas t'aider
ps2: aprés vérif, tu peut développer avec XNA en restant sur ton VB tout pourrie!

Dernière modification par Titan. ; 04/01/2013 à 00h03.
Citation :
Publié par Titan.
l'autre, il me parle de charabia et derrière il me link du VB , mais il était bien entendu pas question de changé de langage au milieu d'un projet, mais pour les projets suivants je te conseille de changé.

je vais approfondir un peut la collaborative diffusion vu que j'ai découvert ça récemment et ça a changé ma vie en terme de perf et de simplicité de dev pour tout ce qui est des pathfinding.

le joueur difuse son "odeur" sur la map, concrètement, chaque case à une valeur d'odeur, à chaque frame tu applique ton odeur de manière récursive sur les case autour de ton personnage en diminuant l'intensité avec la distance, chaque case ayant des propriété de diffusion différente (certaines laissent bien passé l'odeur, d'autre la coupe complètement)
le code de pathfinding et la zone d'agro sont terminé!
il suffit de réveiller ton IA quand l'odeur atteint un certain seuil et elle à juste à toujours se déplacer vers la valeur la plus élevé autour de sa position. (tu à une complexité casi-constante en fonction du nombre d'IA, la ou un A* est linéaire!)

la ou ça deviens intéressant, c'est que tu peut ajouté de la répulsion sur les monstre. cette zone de répulsion fait que les IA essayent naturellement d'encercler le joueur quand elle sont nombreuse plutôt que de lui courir dessus toute en ligne droite(d'ou le "collaborative").

les limites:
toute les IA doivent avoir le même objectif, sinon chaque objectif doit être sur un layer de map différent (par exemple un A* est beaucoup plus modulable, une unité de plus d'une case peut avoir facilement sont pathfinding dédié pour éviter les trou);
ça alourdis légèrement la map;
zone d'agro et répulsion pas forcément compatible;
la complexité est linaire sur le nombre d'élément qui diffuse ou répulse, ainsi que sur la quantité de layer malgré tout

après tu peut complexifié ton algo pour ajouter des comportement de groupe varié, tu peut par exemple avoir de la panique contagieuse sur un layer (ou un "énervement" des monstres)
certains objet peuvent contribué a modifié la map d'odeur, par exemple, pour un jeu de zombie, tu peut avoir des lampes qui repulse du coup les zombie evitent naturellement la zone de lumière mais si tu rentre dedans ils te suivent.
Bonjour !

Très intéressant cette méthode d'odeur ... Merci en tout cas, ton explication est très claire !! Par contre, les odeurs ont elles une durée de vie si la case n'est pas visité par la cible ?? Je pense qu'il serait judicieux de définir une durée "d'odeur" pour ne pas trop alourdir l'algorithme ... Mais je testerai cette méthode !!

A bientôt !

V.
pour l'instant je me suis contenté de refresh la map à chaque frame, en me limitant à une certaine zone autour de mon joueur: je met toute la map à 0, je boucle sur ma liste de "diffuseur" et ils appliquent leur empreinte sur la map de manière récursive

Code:
void recurs(int deltaValue, int y, int x, int** map)
{
     if ( map[y][x] >= deltaValue)
           return;
     map[y][x] = deltaValue;
     recurs( -- deltaValue, y + 1, x    , map);
     recurs( -- deltaValue, y - 1, x    , map);
     recurs( -- deltaValue, y    , x + 1, map);
     recurs( -- deltaValue, y    , x - 1, map);
}
voila un mini exemple parce que je suis pas sur d'être clair sur la diffusion (et je sais pas si tu connais la récursivité) vu que j'ai pas vraiment compris ta question, dans cet exemple je vérifie pas les bords de map, je test pas le "taux de diffusion" de la case courante, j'applique pas de décroissance logarithmique, je gére pas la repulsion... mais c'est pour te donné une idée.

par contre ton intervention m'a fait pensé à un truc, tu peut éventuellement te servir du "temps" pour optimiser l'algo, en setant la valeur de la case à partir des valeurs des 4 cases alentour, de la valeur de diffusion des éléments de la case et du coefficient de diffusion de la case courante (avec un double buffer du coup pour pas scié la branche sur laquelle tu est assis), y'a peut être moyen de définir ta map d'odeur en une seul pass, je vais creusé l'idée la prochaine fois que j'ai un pathfinding à coder, je vais devoir faire un diablo like dans quelques semaines.

en tout cas, peut importe la méthode que tu utilise, il faut pas que t'est éléments mobile consomment les donnée lorsque ils se déplacent puisque ils sont certainement pas tout seul sur la map (en fait il faut juste qu'ils y accèdent en lecture, si mutex).

sinon, rien à voir, j'ai l'impression que ta génération procédurale se fait avec un random pour la densité d'arbre suivit d'un random pour chaque case, j'ai pas l'impression que tu utilise un bruit de perlin.

Dernière modification par Titan. ; 04/01/2013 à 12h16.
Merci Titan pour ces autres informations qui pourront aider d'autres personnes ...

Par contre, en ce qui concerne ma génération de map, je précise qu'elle est encore qu'aux bribes ... J'ai d'autres idées afin de créer des zones de forêt un peu plus réalistes ! Bien sûr, c'est du fait maison, travaillé et synthétisé sur papier avant de retranscrire tout cela en code.

Ton histoire de "bruit de perlin", jamais entendu parler avant de lire ton post ! ( http://fr.wikipedia.org/wiki/Bruit_de_Perlin ... Aprés avoir lu cet article,je me rappelle avoir eu un cours sur cette méthode dans un module de traitement de l'image quand j'étais en faculté ... mais il y a plus de 20 ans maintenant ... )

Il faut savoir, que je suis qu'un amateur autodidacte qui code et développe juste en loisir et qui diffuse depuis peu de temps, ses petites créations afin de partager avec d'autres, la passion de l'informatique qui m'anime depuis la fin des années 70'.

Cordialement.

V.
tu a plein de lib qui te génére des bruit de perlin (perlin noise), sinon basiquement ça consiste en superposant plusieurs textures random (avec des fonction consinus) de différentes résolution, puis tu additionne tout.
(intuitivement, c'est un peut comme si tu commençais par faire des random pour définir le biome -plaine ou foret- d'une portion de ta map, puis que tu refait un random en prenant en compte le type de biome -si tu est en foret 1 chance sur 2 pour avoir un arbre, si t'est en plaine 1 chance sur 10)

si tu trouve pas une lib toute faites, je suis tombé sur un article sympa sur le site du 0:
http://www.siteduzero.com/tutoriel-3...coherents.html, ce sera plus clair que mes explication bizarre

le bruit de perlin ne sert pas juste pour des textures -dans le sens d'affichage de couleur-, tu peut t'en servir par exemple pour une heightmap (http://www.ludumdare.com/compo/wp-co...reenshot-3.png), ça te donne des nombre aléatoire qui sont proche les un des autre, sans variation brutale, appliqué a ton jeu ça te ferait automatiquement des zones de foret (avec quelques trou) et des zones de plaines (avec quelques arbres).
Avec simplement un test ou tu répercute t'est coordonnée 2D du point où tu veux mettre l'arbre sur la texture généré, et en fonction de la couleur,comparé à une variable "densité", tu met un arbre ou non.

Dernière modification par Titan. ; 04/01/2013 à 18h45.
Post
Citation :
Publié par Titan.
tu a plein de lib qui te génére des bruit de perlin (perlin noise), sinon basiquement ça consiste en superposant plusieurs textures random (avec des fonction consinus) de différentes résolution, puis tu additionne tout.
(intuitivement, c'est un peut comme si tu commençais par faire des random pour définir le biome -plaine ou foret- d'une portion de ta map, puis que tu refait un random en prenant en compte le type de biome -si tu est en foret 1 chance sur 2 pour avoir un arbre, si t'est en plaine 1 chance sur 10)

si tu trouve pas une lib toute faites, je suis tombé sur un article sympa sur le site du 0:
http://www.siteduzero.com/tutoriel-3...coherents.html, ce sera plus clair que mes explication bizarre

le bruit de perlin ne sert pas juste pour des textures -dans le sens d'affichage de couleur-, tu peut t'en servir par exemple pour une heightmap (http://www.ludumdare.com/compo/wp-co...reenshot-3.png), ça te donne des nombre aléatoire qui sont proche les un des autre, sans variation brutale, appliqué a ton jeu ça te ferait automatiquement des zones de foret (avec quelques trou) et des zones de plaines (avec quelques arbres).
Avec simplement un test ou tu répercute t'est coordonnée 2D du point où tu veux mettre l'arbre sur la texture généré, et en fonction de la couleur,comparé à une variable "densité", tu met un arbre ou non.
Bonjour !

Je viens de lire ces articles quand à cette méthode, merci pour tous ces éclaircissements !!!

Cela tombe juste au moment ou je viens de finaliser une autre méthode de génération : La Méthode par blocs de forêts.

La méthode en question se déroule de cette manière :

1/ Génération des quelques points de coordonnées qui seront les points centraux des futures forêts à créer ( 10 forêts maximums) .
2/ Une fois les points générés, on vérifie qu'ils ne sont pas trop rapprochés ( ici j'ai réglé à 200 px minimum )
3/ Ensuite, on va générer pour chaque forêt, le rayon de celle ci, et le nombre d'arbre la composant.
4/ On veille a ce qu'il y ai plus de 10 arbres par forêts ... Et on prend en compte le rayon et le nombre d'arbre pour éviter des forêts trop clairsemées ...
5/ On génère les blocs de forêts en tenant compte des variables au dessus.

Voici comment se déroule, en gros, la fonction que je viens de réaliser !

Les images de tout ceci :
Méthode No1 ( Tout aléatoire avec gestion des espacements entre les éléments.)
13010407351813261110727132.png
Méthode No2 ( Par blocs de forêts ) :
13010407351813261110727133.png

On peut voir une différence entre les deux méthodes ... Il me reste à peaufiner les détails de l'algorithme de la méthode des blocs pour avoir des formes de forêts plus "lissées" ! Mais je trouve cette méthode assez satisfaisante par rapport à la première ...

J'ai mis à jour le menu de la démo :
13010407351913261110727134.png
On peut régler la méthode de génération pour se rendre compte du rendu ...

On pourra bien sur, régénérer en appuyant sur R les cartes !

J'ai recompilé le code, et débuggé le déplacement de notre avatar en mode génération de carte, car celui ci ne prenait en compte les limites de la carte .. Oups !!

Lien pour la démo ( fichier RAR du répertoire de la démo .. pas de SETUP ! Mais setup nécessaire pour enregistrer les DLL de la démo, si cela n'a pas été fait ... )
https://dl.dropbox.com/u/108143465/R...ENA%20Demo.rar

Merci de votre attention !!

Cordialement.

V.

EDIT :

Pour les curieux, voici le code de ma fonction de génération par blocs de forêts ( encore en cours de dév. )
Code:
Public Sub GenerateurCarteAutre(ByVal NombreForet)
Dim ResolutionCarteX As Long, ResolutionCarteY As Long
Dim NombreArbre As Integer
Dim NameElementCarte As Byte, NomArbre As String

'Définition de la résolution de la carte principale
ResolutionCarteX = Int(1020 / ScaleDetailScene)
ResolutionCarteY = Int(1020 / ScaleDetailScene)
NombreArbre = 0
NombreForetCarte = NombreForet

'On va définir les coordonnées centrales de ce que seront nos petites forêts
ReDim PointCentralForet(1 To NombreForet + 1)
ReDim Fx(1 To NombreForet + 1)
ReDim Fy(1 To NombreForet + 1)

For i = 1 To NombreForet
ChoixCoord i
Debut:
For j = 1 To i - 1
'Traitement des minimas et extrema
If Fx(i) <= 0 Or Fy(i) <= 0 Then
ChoixCoord i
GoTo Debut:
End If

If Fx(i) > 900 Or Fy(i) > 800 Then
ChoixCoord i
GoTo Debut:
End If

'Traitement des doublons
If (i > 1 Or i < NombreForet) Then
If Fx(j) = Fx(i) And Fy(j) = Fy(i) Then
ChoixCoord i
GoTo Debut:
End If
If ((Abs(Fx(j) - Fx(i)) <= 200) And (Abs(Fy(j) - Fy(i)) <= 200)) Then
'If (Abs((Fx(i) + Fy(i)) - (Fx(j) + Fy(j))) <= 250) Then
ChoixCoord i
GoTo Debut:
End If
End If
Next j
'Attribution des coordonnées centrales de nos forêts
PointCentralForet(i).CoordX = Fx(i)
PointCentralForet(i).CoordY = Fy(i)
'Nombre d'arbre par forêts
DebutCalculArbre:
Randomize
PointCentralForet(i).NombreArbre = Int((Rnd * 50) + 1)
If PointCentralForet(i).NombreArbre < 10 Then GoTo DebutCalculArbre:
'Rayon maximal entre le point central et l'abre le plus éloigné du centre
Randomize
Debutcalcul:
PointCentralForet(i).RayonForet = Int((Rnd * 300) + 1)
If PointCentralForet(i).NombreArbre < 15 And PointCentralForet(i).RayonForet > 100 Then GoTo Debutcalcul:
If PointCentralForet(i).NombreArbre > 25 And PointCentralForet(i).RayonForet < 100 Then GoTo Debutcalcul:
Next i

'Definition du nombre total d'abre
For i = 1 To NombreForet
For j = 1 To PointCentralForet(i).NombreArbre
NombreArbre = NombreArbre + 1
Next j
Next i

ReDim TableauCarte(1 To NombreArbre + 1)
ReDim Fx(1 To NombreArbre + 1)
ReDim Fy(1 To NombreArbre + 1)

'Définition de nos forêts !
For i = 1 To NombreForet
For j = 1 To PointCentralForet(i).NombreArbre
ChoixCoordForet j, PointCentralForet(i).CoordX, PointCentralForet(i).CoordY, PointCentralForet(i).RayonForet
'Définition du type d'arbre
Randomize
NameElementCarte = Int((Rnd * 5) + 1)
'Type d'arbres
Select Case NameElementCarte
Case 1
TableauCarte(j).NameSprite = "ArbreType1"
Case 2
TableauCarte(j).NameSprite = "ArbreType2"
Case 3
TableauCarte(j).NameSprite = "Sapin"
Case 4
TableauCarte(j).NameSprite = "ArbreType1Automne"
Case 5
TableauCarte(j).NameSprite = "ArbreType2Automne"
End Select

'Affection des coordonnées dans notre tableau principal
TableauCarte(j).CoordX = Fx(j)
TableauCarte(j).CoordY = Fy(j)
TableauCarte(j).ElementDecor = True
TableauCarte(j).ID = j
TableauCarte(j).NumberTableTile = 1

Next j
Next i

NombreArbreCarte = NombreArbre

End Sub

Public Function ChoixCoord(ByVal Number) As Boolean
Randomize
Fx(Number) = Int((Rnd * 1020) + 1)
Randomize
Fy(Number) = Int((Rnd * 900) + 1)
Randomize
End Function
Public Function ChoixCoordForet(ByVal Number, ByVal CentreX, ByVal CentreY, ByVal Rayon) As Boolean
Fx(Number) = CentreX + CalculSigne * Int((Rnd * Rayon) + 1)
Randomize
Fy(Number) = CentreY + CalculSigne * Int((Rnd * Rayon) + 1)
Randomize
End Function
Public Function CalculSigne() As Integer
Dim ChoixSigne As Byte
'Determination du signe
Randomize
ChoixSigne = Int((Rnd * 10) + 1)
If ChoixSigne <= 5 Then CalculSigne = -1 Else CalculSigne = 1

End Function
Citation :
Publié par Titan.
pour l'instant je me suis contenté de refresh la map à chaque frame, en me limitant à une certaine zone autour de mon joueur: je met toute la map à 0, je boucle sur ma liste de "diffuseur" et ils appliquent leur empreinte sur la map de manière récursive
Très intéressante comme technique, je l'utilise de manière "statique" pour des points qui ne changent pas donc en calculant une seule fois le résultat. Par contre refresh à chaque frame me semble prendre beaucoup de ressources. Rien qu'une matrice 100*100 qu'il faut remettre à 0 puis calculer les nouvelles valeurs, ça me semble coûteux. Je me trompe ?
déjà 100x100 tu vois large, dans la plupart des cas tu peut te limité à 40 ou 50, à voir avec ta résolution. mais surtout ça viens remplacer un A*, que tu doit effectué pour chaque élément mobile, potentiellement plusieurs dizaine:
Astar_progress_animation.gif

et quand tu vois que des jeux de stratégie comme starcraft 1 était capable de le faire pour plusieurs centaine d'unité avec des processeur digne du calculatrice graphique de lycéen, tu te dit que tu peut tout à fait te le permettre .

Dernière modification par Titan. ; 05/01/2013 à 17h36.
J'ai déjà implémenté plusieurs fois A* donc je connais .

Naïvement je pensais que la matrice faisait la même taille que la map donc ça fait des traitements trop lourd, mais en fait il suffit d'une matrice de taille plus restreinte et de sauvegarder le décalage pour la superposer à la carte, si c'est bien à ça que tu pensais. En effet dans ce cas c'est bien plus raisonnable niveau coût. Merci pour l'explication.

Je viens de remarquer, j'aurais pu implémenter dans mon projet le son qu'un personnage provoque sans problème, dommage que je n'ai pas découvert ça plus tôt .
12121810395313261110678925.png

Bonjour à tous !

Je vous propose une amélioration de mon générateur de carte par bloc de forêt.

Comme vous pouvez le voir au travers de cette image :
13010601081013261110732138.png

J'ai réussi à mieux répartir mes blocs et les étaler sur l'ensemble de ma carte. Bien sûr, tout dépend du nombre de forêt généré et du nombre d'arbre la composant ...

De plus, j'ai intégré la gestion du décor par fichier .INI, beaucoup plus pratique afin de rajouter des tile de décor ...
Dans ce cadre la, je rajouterai au fur et à mesure d'autres éléments : Eau, rivières, chemin, etc ... Pour un meilleur rendu des cartes.

Vous trouverez cette nouvelle version sur ce lien : https://dl.dropbox.com/u/108143465/R...0D%C3%A9mo.exe

Merci de vos retours quand au comportement de la démo sur vos systèmes !

Cordialement.

V.
Bonjour !

Je viens d'adapter l'idée d'un bêta testeur quand au sens de tir de notre avatar.

Celui ci sera directement influencé par la position de notre pointeur de souris !
Je calcule en temps réel les coordonnées du pointeur et celles de notre avatar et je déduis le sens de tir ... Bien sur, notre avatar ne tire que dans 4 positions : Haut, Bas, Gauche, Droite ! Il fallait donc déduire les priorités selon la position du pointeur à savoir :

1/ Quand le "Delta" ( soustraction des coordonnées Pointeur - Avatar ) Y est > X alors on tire verticalement ( haut ou bas ), ou sinon, on tire horizontalement ( Gauche ou droite )
2/ Le sens est donné par le signe de notre Delta ( positif ou négatif )


Voici le code de l'algo :
'Définition du sens de tir
'Coordonnées du pointeur souris au moment du tir
SpriteTableau(NumberSprite).DestinationX = TmpSouris.Coordonnees.X - ScrollingX - ScaleDetailScene / 1.5
SpriteTableau(NumberSprite).DestinationY = TmpSouris.Coordonnees.y - ScrollingY - ScaleDetailScene

'Déduction du sens de tir
If Abs(SpriteTableau(NumberSprite).CoordY - SpriteTableau(NumberSprite).DestinationY) < 75 Then
If SpriteTableau(NumberSprite).CoordX > SpriteTableau(NumberSprite).DestinationX Then
SpriteTableau(NumberSprite).SensDeplacement = "Gauche"
Else:
SpriteTableau(NumberSprite).SensDeplacement = "Droite"
End If
Else:
If Abs(SpriteTableau(NumberSprite).CoordY > SpriteTableau(NumberSprite).DestinationY) Then
SpriteTableau(NumberSprite).SensDeplacement = "Haut"
Else:
SpriteTableau(NumberSprite).SensDeplacement = "Bas"
End If
End If

suite:
SpriteTableau(31).SensDeplacement = SpriteTableau(NumberSprite).SensDeplacement ' Ici 31 et l'ID de la boule de feu


Cela rendra plus pratique le tir en mouvement d'un sort en "Instant Cast" !!

Vous m'en direz des nouvelles en cours d'utilsation, mais je trouve que l'effet est plus pratique en matière de Gameplay.
De plus, j'ai augmenté la vitesse de notre boule de feu ( vitesse x 2 ) ...

Merci de vos retours et à Dabou pour ses remarques utiles !

Lien : https://dl.dropbox.com/u/108143465/R...0D%C3%A9mo.exe

V.

EDIT :
J'ai retravaillé l'aspect de notre avatar magicien :
13010604411013261110734185.png
De plus, quand il se déplacera, il clignera les yeux ...
J'ai fait cette petite animation en dilettante ... Je la trouve mignonnette !
( Le lien reste le même : https://dl.dropbox.com/u/108143465/Rol'An'Go ARENA Démo.exe )
Dernière petite mise à jour avant la reprise ...

Mise en oeuvre d'une caméra dynamique suivant le projectile de l'avatar :
Voici un aperçu de l'un de mes derniers travaux : le suivi du projectile tiré par notre avatar par la caméra !
La vitesse de la caméra s'ajuste à la vitesse du projectile, une fois que le projectile sort du champ de la carte OU atteint sa cible, la caméra va se recentrer vers l'avatar à grande vitesse et ensuite, va s'adapter à la vitesse de l'avatar ...

C'est une option qui pourra être activer, par exemple, comme option dans le futur du projet ...

La petite vidéo :

( Vidéo saccadée, mais démo parfaitement fluide ... )

Le lien pour les tests : https://dl.dropbox.com/u/108143465/R...0D%C3%A9mo.exe

Merci de vos retours et avis !

Cordialement.

V.

EDIT : Vous pouvez désormais désactiver cette option en appuyant sur la touche "F" ( affichage de l'option sur l'écran ... )

Dernière modification par Vetea ; 07/01/2013 à 10h32.
Répondre

Connectés sur ce fil

 
1 connecté (0 membre et 1 invité) Afficher la liste détaillée des connectés