Day.png);">
Apprendre


Vous êtes
nouveau sur
Oniromancie?

Visite guidée
du site


Découvrir
RPG Maker


Apprendre
RPG Maker

Tutoriels
Guides
Making-of

Dans le
Forum

Section Entraide

Jeux: puie z / Jeux: Citymaime - Chapitre 1 / Jeux: Mer, îles et fous / News: Du neuf dans le making / News: Muma|Rope est disponible en (...) / Chat

Bienvenue
visiteur !




publicité RPG Maker!

Statistiques

Liste des
membres


Contact

Mentions légales

604 connectés actuellement

30729211 visiteurs
depuis l'ouverture

2828 visiteurs
aujourd'hui



Barre de séparation

Partenaires

Indiexpo

Akademiya RPG Maker

Blog Alioune Fall

Fairy Tail Constellations

RPG Maker Détente

ConsoleFun

Eclipso

Level Up!

RPG Maker - La Communauté

Tous nos partenaires

Devenir
partenaire



[RGSS] Inclure des régions sur une carte

Pour faire des zones de combat ou région avec le RGSS.

Ecrit par Lufia le 20/05/2009


❤ 0

Zones de combat en Ruby



Ceci est un tutoriel pour vous apprendre comment coder vos zones de combat en Ruby sous RMXP, pas un script prêt à être copié-collé. La théorie est exactement la même que celle expliquée dans cet excellent tuto de Joke que je vais vous demander d'aller lire.

...

Vous l'avez compris et assimilé ? Bien, nous allons pouvoir ajouter une couche de Ruby par dessus tout ça !


I. Comment ça marche, une liste de monstres ?

Ouvrez votre éditeur de script et allez farfouiller dans Game_Map. A la ligne 177 se trouve le code suivant :

Portion de code : Tout sélectionner

1
2
3
def encounter_list
    return @map.encounter_list
end



Quoi qu'ça fait ? Lisons ensemble.

def encounter list : Définition d'une fonction nommée "encounter_list". Notez comme le nom est prometteur pour ce qui nous intéresse...

return : Renvoie la valeur contenue dans ce qui suit.

@map.encounter_list : Ce qui suit. image Il s'agit de la liste des monstres contenue dans les propriétés de la carte (si, si, vous savez, dans l'éditeur...). Cette variable (car c'est une variable) est un tableau contenant toutes les ids des groupes de monstres "rencontrables" sur une carte, sous la forme [x, y, z].

end : Fin de la définition de notre fonction (car même les meilleures choses ont une fin...)

Vous l'aurez compris, tout ce que fait le programme par défaut pour définir la liste des monstres présents sur une carte, c'est d'aller chercher la-dite liste dans les propriétés de la carte. Et ça, ça ne nous plait pas. Eh bien ! Qu'attendons-nous pour changer les choses ?


II. Nos premières zones

1) Zones définies par deux points

Si le titre ne vous dit rien, retournez lire le tutoriel de Joke sur les zones par variables.

Vous vous souvenez de ce code pour savoir si le joueur est dans une zone ou pas ?
modifier variable : "X héros" rendre égal à coordonnée X du héros
modifier variable : "Y héros" rendre égal à coordonnée Y du héros
condition : si "X héros" supérieur ou égal à "56"
--condition : si "X héros" inférieur ou égal à "88"
----condition : si "Y héros supérieur ou égal à "40"
------condition : si "Y héros inférieur ou égal à "77"
[...]


Nous allons le traduire en Ruby. ^^


If et coordonnées du joueur

Voici la première condition :

Portion de code : Tout sélectionner

1
2
# condition : si "X héros" supérieur ou égal à "56"
if $game_player.x >= 56



Lisez "Si la valeur de $game_player.x est supérieure ou égale à 56". Et la valeur de $game_player.x est tout simplement la valeur de la coordonnée en x (comptée en carreaux) de $game_player, le joueur. De la même façon, la coordonnée en y du joueur sera désignée par $game_player.y

Facile, non ?


Avec plusieurs conditions

C'est pas tout ça, mais nous, on voudrait bien les quatre conditions simultanées... Et c'est pour ça qu'on est bien contents que les opérateurs logiques marchent en Ruby. Si vous voulez une codition de la forme "Si ça et ça", ça s'écrit "if ça and ça".

Pouvez-vous écrire les quatre conditions simultanées sans regarder ce qui suit ?

Portion de code : Tout sélectionner

1
2
3
4
if $game_player.x >= 56 and
$game_player.x <= 88 and
$game_player.y >= 40 and
$game_player.y <= 77



Alors, ça ressemble à ce que vous aviez fait ?

NB : En général, en Ruby, un saut de ligne représente une fin d'instruction, ma condition devrait donc se finir à la fin de ma première ligne de code. Cependant, comme la ligne se finit par l'opérateur "and" qui appelle nécessairement une suite, le programme comprend que ma condition se poursuit sur la ligne suivante et ne s'arrête qu'a la première ligne qui n'appelle pas de suite, ici la dernière ligne de mon code. C'est important de ne pas sauter des lignes n'importe comment, ça conduit à des erreurs de syntaxe.

Au fait, faudrait pas un peu changer notre liste de monstres, aussi ?


Si la condition est remplie...

Le conditionnement est fait, faudrait peut-être faire quelque chose quand notre condition est remplie, non ? Examinons le code à écrire...

Portion de code : Tout sélectionner

1
2
3
4
5
6
if $game_player.x >= 56 and
$game_player.x <= 88 and
$game_player.y >= 40 and
$game_player.y <= 77
  return [7, 8]
end



Le code est tout simplement calqué sur la fonction originale de Game_Map. Si nos quatre conditions sont remplies, alors on renvoie [7, 8], les groupes de monstres aux ids 7 et 8 sont maintenant ceux rencontrés dans la zone.

Le "end" est important car il indique au programme de n'effectuer que les actions situées avant celui-ci quand les conditions sont remplies, et pas le reste du programme. De toute façon, si vous l'oubliez, vous aurez une erreur de syntaxe lors de l'exécution. ^^'


Le beau code complet

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
def encounter_list
  if $game_map.map_id == 1 and
  $game_player.x >= 56 and
  $game_player.x <= 88 and
  $game_player.y >= 40 and
  $game_player.y <= 77
    return [7, 8]
  else
    return @map.encounter_list
  end #du if
end #du def



Quelques petites choses ont été rajoutées :

$game_map.map_id == 1 : Le signe "==" sert à vérifier une égalité et $game_map.map_id désigne tout simplement l'id d'une carte. Si vous ne le précisez pas, votre zone sera créée sur toutes les cartes du jeu ! Cette condition existait de façon implicite dans la programmation en évènement, puisque les évènements sont propres à une carte.

else : "sinon". Ben oui, faut bien dire à la bestiole ce qu'elle doit faire si on n'y est pas, dans la zone créée... Sinon vous aurez un beau bug dès que vous en sortirez. J'ai remis la définition par défaut de la liste de monstres dans ce "else", mais si un coup de folie vous prend, libre à vous de changer cela.

Une traduction "littérale" du code, pour être sûre que même les dissipés du fond suivent :
<>définir la fonction "encounter_list"
<><>si l'id de la carte est 1
<><>et que la coordonnée x du joueur est supérieure ou égale à 56
<><>et que la coordonnée x du joueur est inférieure ou égale à 88
<><>et que la coordonnée y du joueur est supérieure ou égale à 40
<><>et que la coordonnée y du joueur est inférieure ou égale à 77
<><><> alors on rencontre les groupes de monsstres aux ids 7 et 8
<><>sinon
<><><>on rencontre la liste spécifiée dans les propriétés de la carte
<><>fin
<>fin



2) Zones définies par un point et une distance

Maintenant que vous avez assimilé les bases (*ahem* ...), je vais pouvoir aller un peu plus vite.

Reprenons le code de Joke dans la section correspondante :
<>modif variable "X diff" = coord "X perso 2"
<>modif variable "Y diff" = coord "Y perso 2"
<>modif variable "X diff" - (soustraire) coord X "perso 1"
<>modif variable "Y diff" - (soustraire) coord Y "perso 1"
condition : si "X diff" >= -3
--condition : si "X diff" <= 3
----condition : si "Y diff" >= -3
------condition : si "Y diff" <= 3
[...]


Et sa traduction (l'explication suit, pas d'inquiétude) :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
if $game_map.map_id == 1 and
$game_player.x - $game_map.events[1].x >= -3 and
$game_player.x - $game_map.events[1].x <= 3 and
$game_player.y - $game_map.events[1].y >= -3 and
$game_player.y - $game_map.events[1].y <= 3
  return [3, 4]
end



Utiliser une variable "différence" ? Pah, on fait les calculs directement, nous. image Ca ressemble furieusement à notre code d'avant, avec toutefois l'apparition d'une nouvelle variable.

$game_map.events[1] : L'évènement avec l'id 1. Tous les évènements du jeu avec l'id 1. Vous comprenez l'importance de la condition sur l'id de la carte... Et nous utilisons ses coordonnées x et y comme nous utilisons celles de $game_player.

N.B. : Contrairement au tuto de Joke, nous travaillons bien ici avec des coordonnées absolues et non pas avec des coordonnées écran.

Voilà notre nouveau "code complet" qui crée une zone de 3 carreaux de large autour de l'évènement avec l'id 1 :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
def encounter_list
  if $game_map.map_id == 1 and
  $game_player.x - $game_map.events[1].x >= -3 and
  $game_player.x - $game_map.events[1].x <= 3 and
  $game_player.y - $game_map.events[1].y >= -3 and
  $game_player.y - $game_map.events[1].y <= 3
    return [3, 4]
  else
    return @map.encounter_list
  end #du if
end #du def



Rien de nouveau sous le soleil, mais traduisons quand même :
<>définir la fonction "encounter_list"
<><>si l'id de la carte est 1
<><>et que (joueur.x - évènement 1.x) est supérieur ou égal à -3
<><>et que (joueur.x - évènement 1.x) est inférieur ou égal à 3
<><>et que (joueur.y - évènement 1.y) est supérieur ou égal à -3
<><>et que (joueur.y - évènement 1.y) est inférieur ou égal à 3
<><><> alors on rencontre les groupes de monsstres aux ids 3 et 4
<><>sinon
<><><>on rencontre la liste spécifiée dans les propriétés de la carte
<><>fin
<>fin


3) Les deux en même temps !

Une seule zone par jeu, ça craint un peu... La clé pour réunir nos deux zones précedentes ? Le elsif !

La démonstration en image :

Portion de code : Tout sélectionner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def encounter_list
  if $game_map.map_id == 1 and
  $game_player.x >= 56 and
  $game_player.x <= 88 and
  $game_player.y >= 40 and
  $game_player.y <= 77
    return [7, 8]
  elsif $game_map.map_id == 1 and
  $game_player.x - $game_map.events[1].x >= -3 and
  $game_player.x - $game_map.events[1].x <= 3 and
  $game_player.y - $game_map.events[1].y >= -3 and
  $game_player.y - $game_map.events[1].y <= 3
    return [3, 4]
  else
    return @map.encounter_list
  end #du if
end #du def



Vous avez maintenant sur votre carte 1 deux zones : une zone rectangulaire définie par deux points dans laquelle on rencontre les groupes 7 et 8 et une zone de 3 carreaux de large autour de l'évènement 1 dans laquelle on rencontre les groupes 3 et 4.

Attention ! Le programme vérifie d'abord le premier jeu de conditions, si elles ne sont pas remplies, celles du 1e elsif, si celles-ci ne sont pas remplies non plus, celles du 2nd elsif, etc. L'ordre dans lequel vous écrivez votre échelle de elsif définit donc la priorité des conditions les unes par rapport aux autres. Si je suis dans les deux zones à la fois, je rencontrerai les monstres 7 et 8, ceux qui correspondent au premier jeu de conditions à être rempli.

Si ce n'est pas très clair, je vous invite à tester vous-même.

Vous pouvez ajouter autant de elsif que vous voulez.


III. Variantes

1) Sur les coordonnées

Il y a en Ruby deux autres manières de désigner les coordonnées des objets.

$game_player.screen_x
C'est ce qui est appelé la "coordonnée écran" en évènements et qui désigne la coordonnée x du joueur par rapport au bord de l'écran. Cette coordonnée est au pixel près.
De la mêmz manière, il existe
$game_player.screen_y
$game_map.events[1].screen_x
$game_map.events[1].screen_y

$game_player.real_x
La coordonnée absolue du joueur... au quart de pixel près ! Comme $game_player.x mais 128 fois plus précis.
Bien sûr, on peut écrire :
$game_player.real_y
$game_map.events[1].real_x
$game_map.events[1].real_y


2) Sur les conditions

Pourquoi se limiter à de bêtes zones ? Lâchez vous ! Quelques exemples de conditions que vous pourrez réutiliser ailleurs :

if $game_party.item_number(1) > 0
Si l'équipe a au moins un exemplaire de l'objet avec l'id 1

if $game_party.actors[0] == $game_actors[1]
Si le premier membre de l'équipe est le héros avec l'id 1

$game_actors[1].weapon_id == 1
Si le héros avec l'id 1 est équipé de l'arme 1

$game_party.actors.include?($game_actors[1])
Si le héros avec l'id 1 est dans l'équipe

if $game_variables[1] == 1
Si la variable 1 est égale à 1

if $game_switches[1] == true
Si l'interrupteur 1 est sur ON

Enfin bref, toutes les conditions disponibles en évènements, plus toutes celles qui vous passent par la tête.


3) Sur la forme des zones

Vous décidez des conditions à remplir, vous décidez de la forme de vos zones ! Utilisez des "and" et des "or" pour faire quelque chose de bien.

Dans les choses qui marchent, j'avais fait ça :

Portion de code : Tout sélectionner

1
2
3
4
5
if game_map.map_id == 1 and
($game_player.x - 12)*($game_player.x - 12) +
($game_player.y - 12)*($game_player.x - 12) < 9
  return [4, 5]
end



C'est l'équation d'un disque. ^^ (Il n'était pas très rond, il faudrait essayer avec des coordonnées au pixel... Mais pas de message d'erreur, donc ça marchait !)


4) Et si on veut changer la fréquence des rencontres ?

Devinez quoi ? Juste en dessous de notre terrain de jeu sur Game_Map figure la fonction suivante :

Portion de code : Tout sélectionner

1
2
3
def encounter_step
  return @map.encounter_step
end



Ca ressemble à ce qu'on sait déjà modifier, non ? Ben oui, ça marche exactement pareil, sauf que ce n'est plus une liste mais un nombre seul qui doit figurer après return.

Portion de code : Tout sélectionner

1
2
3
def encounter_step
  return 10
end



Je vous laisse vous amuser pour mettre des conditions.


IV. Le mot de la fin

Ce tutoriel m'a permis de vous montrer par l'exemple quelques trucs faisables en Ruby, et de vous expliquer quelques fonctions et variables présentes de base. Je vous encourage à vous plonger dans l'éditeur de script et à essayer de comprendre comment ça marche par vous-mêmes. Il faut juste de la logique, des bases d'anglais et un peu de rigueur. ^^

Merci de votre attention.



d arkangel - posté le 20/05/2009 à 22:31:58 (322 messages postés)

❤ 0

bidouilleur professionnel

Excellent tuto, très instructif et bien expliqué en plus.

Par contre ça doit être chaud de créer des zones sur des dizaines de map différentes...

La théorie, c'est quand on comprend tout mais que rien ne marche. La pratique, c'est quand ça marche mais personne ne sait pourquoi. Ici, on fait les deux : rien ne marche et personne ne sait pourquoi !


Lufia - posté le 20/05/2009 à 22:52:15 (5792 messages postés)

❤ 0

Un Oniromancien. PVs 1, Attaque 0, Défense 0.

J'ai foiré la fermeture d'une $@#* de balise couleur. image

C'est chaud d'en faire beaucoup, oui et non. C'est toujours le même principe, si tu sais en faire une, tu sais en faire 2573. Faut juste un peu d'organisation.

Une signature ? Pour quoi faire ?


Alemphkujo - posté le 06/07/2009 à 12:43:59 (21 messages postés)

❤ 0

Un cartomancien, c'est pas un vieux qui joue aux cartes, OK ?

Voilà un bon tuto ^^ explications claires et nettes (même si je l'ai brièvement parcouru par manque de temps). Bravo :)

Si vous piquez son coeur au trèfle, tenez vous à carreaux !


Zealous - posté le 28/12/2009 à 14:51:10 (39 messages postés)

❤ 0

Artisan Scripteur

Yop
Je me permets de réagir sur ce tutorial qui m'a d'ailleurs aidé un peu à capter ces @#*#!$ de variables Ruby.
Dans l'ensemble c'est une bonne méthode, mais pour les projets de grand envergure avec des maps de 50 voir 60 microzones, voir même plusieurs map de plusieurs microzones, ça ne devient pas un peu usine à gaz dans la classe Game_Map ?

Ne serait ce pas plus simple (même si on se retrouve submergé d'events) d'entourer de doubles couches nos zones d'events où l'on veut trouver des créatures différentes, en appelant juste une fonction de script dynamique ? :-/

Suite à de nombreux abus, le post en invités a été désactivé. Veuillez vous inscrire si vous souhaitez participer à la conversation.

Haut de page

Merci de ne pas reproduire le contenu de ce site sans autorisation.
Contacter l'équipe - Mentions légales

Plan du site

Communauté: Accueil | Forum | Chat | Commentaires | News | Flash-news | Screen de la semaine | Sorties | Tests | Gaming-Live | Interviews | Galerie | OST | Blogs | Recherche
Apprendre: Visite guidée | RPG Maker 95 | RPG Maker 2003 | RPG Maker XP | RPG Maker VX | RPG Maker MV | Tutoriels | Guides | Making-of
Télécharger: Programmes | Scripts/Plugins | Ressources graphiques / sonores | Packs de ressources | Midis | Eléments séparés | Sprites
Jeux: Au hasard | Notre sélection | Sélection des membres | Tous les jeux | Jeux complets | Le cimetière | RPG Maker 95 | RPG Maker 2000 | RPG Maker 2003 | RPG Maker XP | RPG Maker VX | RPG Maker VX Ace | RPG Maker MV | Autres | Proposer
Ressources RPG Maker 2000/2003: Chipsets | Charsets | Panoramas | Backdrops | Facesets | Battle anims | Battle charsets | Monstres | Systems | Templates
Ressources RPG Maker XP: Tilesets | Autotiles | Characters | Battlers | Window skins | Icônes | Transitions | Fogs | Templates
Ressources RPG Maker VX: Tilesets | Charsets | Facesets | Systèmes
Ressources RPG Maker MV: Tilesets | Characters | Faces | Systèmes | Title | Battlebacks | Animations | SV/Ennemis
Archives: Palmarès | L'Annuaire | Livre d'or | Le Wiki | Divers