Touhou-France
Vous souhaitez réagir à ce message ? Créez un compte en quelques clics ou connectez-vous pour continuer.
Le Deal du moment :
Cdiscount : -30€ dès 300€ ...
Voir le deal

[Tuto]Danmakufu ph3 β1.[Work In Progress]

+2
UFO_Buddha
Nasty_bdfp
6 participants

Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Nasty_bdfp Jeu 04 Aoû 2011, 12:37 am

Bonjour à tous et à toutes, ici Nasty (d) qui prend exemple sur (D)ynast (j'avais remarqué mais mon pseudo est une quasi anagramme). Suite à la parution d'une nouvelle version de danmakufu
https://touhou-france.forumactif.com/t1533-danmakufu-ph3-1aka-new-game-des-danmakufueurs
Je vais essayer de vous faire un petit tuto en français pour aider ceux qui commenceraient a utiliser danmakufu par cette nouvelle version, qui a de nombreux changements, je pense qu'un tout nouveau tutorial que j'essayerai de faire aussi complet que celui de Dynast ne sera pas du luxe.
Bien sur la 1ère chose à faire est évidemment de télécharge Danmakufu. (passez par le wiki dont le lien est donné dans le lien ci dessus)
Je passe l'aspect technique, Applocale et tout ça, je vous renvois au tuto de Dynast : https://touhou-france.forumactif.com/t170-danmakufu-tuto-p?highlight=danmakufu
Ensuite pour faire vos scripts vous aurez besoin de fichiers blocs notes. Dans le bloc note suivez les étapes suivantes du tutorial:

Je mettrai en spoiler les informations relatives à la précédente version (notamment aux niveaux des différences entre la version précédente et celle ci)
Initialisation :
Tout d'abord tout script danmakufu comprends des mentions obligatoires: Créez un fichier texte et collez y ceci:

Code:

#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["xxx"]
#Text["xxx:xxx"]

let objEnemy;
let frame = 0;

@Event
  {alternative(GetEventType())
   case(EV_REQUEST_LIFE)
   {
      SetScriptResult(1500);}
  }

@Initialize
  {
  }
 
@MainLoop
  {
  }

Notes complémentaires:
Spoiler:

Je passerai les deux premières lignes, sachez juste qu'elles sont obligatoire. J'y reviendrai plus en avant dans le tutorial.
La 3ème ligne est le titre >il vous faudra mettre entre les crochets entre guillemet le nom de ce que vous faites (le nom de la spell si c'est une spell, par exemple). Cela vous servira à identifier le script lorsque vous lancerez danmakufu. (Attention : Ne pas confondre avec le nom du fichier, qui peut être semblable pour des raisons pratiques, mais qui peut tout aussi bien être différent).

La 4ème ligne est une petite description que vous pouvez faire. (de même mettez entre les crochets et entre guillemet votre texte).
Il peut aussi avoir dans les scripts quelques autres #blabla["xxx"]. La liste complète est déjà disponible sur le wiki (que je mettrais en fin de tutorial).

Il y a après toutes ces lignes en # deux lignes commençant par let: ces deux lignes servent à définir des variables (ici frame et objEnemy). L'une définit et est égal à 0 (une valeur mathématique), l'autre ne l'est pas et est donc du néant. Toutefois grâce à ces deux lignes, on pourra réutiliser ces deux termes (objEnemy et frame) plus tard dans le script. Je définirai leurs intérêts quand on réutilisera ces deux termes. SANS ces lignes, danmakufu nous indiquera une erreur par la suite lorsqu'on réutilisera ces deux derniers élément.
Vient ensuite la @Event que je ne peux encore décrire précisément à l'heure ou j'écrit ses lignes. Sachez seulement que les lignes qu'il contient permettent de définir la vie du boss (ici fixé à 1500), et qu'elles sont nécessaire à son fonctionnement.

Insérer le boss:

Nous voici dans le gros du script, avec 3 blocs :@Initialize, @MainLoop et @Event.
Spoiler:
Dans cette partie nous allons nous préoccuper de @Initialize.
@Initialize est le plus simple des 3 blocs : C'est ce qui se passe lorsque le script est déclenché, au tout début. C'est donc le bloc nécessaire pour faire apparaitre notre boss.
tout d'abord insérez dasn @Initialize ces deux lignes:
Code:

        objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS);
   ObjEnemy_Regist(objEnemy);
Ces deux lignes servent à indiquer ce que l'on veux créer: un ennemi, de type Boss. La 1ère ligne, définit une variable comme un objet de type ennemi. La 2nde ligne permettrait de donner un nom a cet ennemi pour le programme. Maintenant a chaque fois qu'on retapera objEnemy, le programme sait qu'on est en train de parler du boss.
Surtout n'oubliez pas les ; a la fin de chaque ligne de script, qui permet de différencier les tâches à accomplir.
Note:
Spoiler:

Vous pouvez des a présent allez voir sur votre programme danmakufu et lancer le boss... normalement il fonctionnera, et il y aura même une barre de vie qui va se remplir, et un petit compteur en haut à droite bloqué à 99... Mais pas de boss.. c'est normal!

Pour faire apparaitre le boss, vous avez besoin de deux choses: Lui donner une apparence, et le faire venir à l'écran.

Pour lui donner une apparence tapez ses 4 lignes à la suite (séparé d'un saut de ligne si vous voulez que ça soit propre):

Code:

        let imgExRumia = GetCurrentScriptDirectory ~"./ExRumia/ExRumia.png";
   ObjPrim_SetTexture(objEnemy, imgExRumia);
   ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64);
   ObjSprite2D_SetDestCenter(objEnemy);
A la 1ère ligne vous retrouvez let xxx : au début nous avions mis "let objEnemy;" et "let count=0;" : let sert à établir l'existence d'une variable. Cette variable peut être un objet, une valeur numérique, ou rien (comme au début n a écrit let objEnemy... mais on a pas dit a quoi c'était égal, > donc c'était du néant, ce qui nous empêchait pas de nous en servir plus tard.
Ici on définit cette variable "imgExRumia comme êtant égal à une image (en fichier PNG que vous devriez avoir avec votre fichier danmakufu)
La 2nde ligne donne cette image (nommé sous la variable imgExRumia) a l'ennemi (nommé sous la variable objEnemy)
La 3ème ligne est plus technique elle sert à définir le rectangle qui sera visible dans l'image. En effet si vous jetez un coup d'oeil à votre fichier ExRumia.png, vous vous apercevrez qu'il y a plusieurs sprites. Vous voulez donc qu'une seule de ces sprites ne soit affichés à la fois à votre écran.
Le dernier sert à placer l'image, ici directement sur l'ennemi. (on pourrait en théorie le placer n'importe ou ailleurs, mais pour des raisons pratiques, en général on le placera directement sur l'ennemi).

Voila vous pouvez lancer votre script... mais toujours pas d'ennemi? > Regardez en haut à gauche, vous verrez une jambe dépassée.

Il est maintenant temps de le faire venir! insérez les lignes de codes:

Code:
 
   ObjMove_SetDestAtFrame(objEnemy, GetStgFrameWidth() / 2, 60, 60);
Cette ligne va permettre au boss d'aller à sa destination.
Note:
Spoiler:
GetStgFrameWidth permet de reporter la largeur de l'écran,la diviser par deux permet donc d'avoir le boss au milieu de l'écran dans sa largeur. La 2nde valeur donnée (le 1er 60), correspond aux coordonnées Y, ou coordonnées en longueur. Ici Le boss se positionnera a 60 pixel du bord haut de l'écran.
La 3ème valeur permet de déterminer le temps en frame que prendra le boss pour parcourir cette distance. Ici il prendra 60 frames (soit une seconde exactement, sachant que danmakufu marche à 60 frames par secondes).

Et voila : Si vous décidez de lancer danmakufu, et de choisir ce script, vous verrez Rumia arriver! Toutefois, vos tirs ne la toucheront pas et si vous foncez dedans vous passerez comme si elle n'existait pas. ça sera l'objet de la prochaine partie.

Donner un corps à notre boss.

Okay donc, Nous avons un boss, mais c'est comme si il n'était pas réellement là.... En fait il faut que le jeu détecte la collision de vos tirs avec l'ennemi, et celle de votre personnage avec l'ennemi. L'une servira à pouvoir infliger des dommages aux boss, l'autre à se faire toucher si vous foncez dedans. Il faudra aussi que cette collision soit détectée à tout instant. Si elle l'est mis dans initialize, la collision ne sera détecté qu'à la 1ère frame du jeu. D'ou on se servira du MainLoop: Dans cette partie, tout le contenu est répété à chaque frame.
Ainsi il vous faut insérer les lignes suivantes dans le Main Loop :
Code:
ObjEnemy_SetIntersectionCircleToShot(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 32);
   ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 24);
(je ferai un résumé à la fin de cette partie). La 1ère ligne rend le boss vulnérable à vos tirs, et positionne cette vulnérabilité sur le boss, dans un rayon de 32 autour du pixel central du boss.
Spoiler:
Maintenant vous pouvez lancer le script, tirez et vous devriez voir la barre de vie du boss descendre... mais une fois à 0 le boss ne disparaîtra pas.
Spoiler:

Il faut donc permettre une fin au script : insérez ces lignes plus loin dans le MainLoop:
Code:
if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0)
   {
      Obj_Delete(objEnemy);
      CloseScript(GetOwnScriptID());
      return;
   }
Okay, donc description de chacun de ces éléments: Le 1er élément commence par if indique que les lignes suivantes se trouvant entre crochet ne s'exécuteront que si la condition qui se trouve entre parenthèse est remplie : Il vous faut absolument comprendre cela pour coder le moindre chose, If est le "conditionneur" le plus récurrent. (il n'est pas le seul vous pourrez trouver par exemple while() ; loop(x); ou encore else if ()... je n'en connais pas la liste exhaustive).

le Obj_Delete(objEnemy); est la ligne chargée d'effacer l'objet ennemi (on retrouve l'utilisation de la variable objEnemy sous laquelle le boss est enregistré).
CloseScript(GetOwnScriptID) permet de mettre fin aux scripts. > c'est ce qui indique que le script est finit. sans cela, le boss era certes détruit, mais vous ne verrez pas le CLEAR affiché.
Enfin j'ignore à quoi sert la dernière ligne puisque, une fois retirée cela ne change rien. Peut être dans le cadre de scripts multiples...


Et voila vous avez enfin un script qui fonctionne,et qui affiche le menu de fin une fois le boss vaincu bravo. Toutefois Rumia n'est pas encore bien dangereuse. C'est pourquoi nous verrons un peu plus loin comment créer des tirs. Mais d'abord un petit résumé et quelques infos complémentaires:

Résumé:
Quelque soit votre script, il faut qu'ils contiennent au minimum les lignes suivantes :

Code:
#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["xxx"]
#Text["xxx:xxx"]

let objEnemy;

@Event
  {alternative(GetEventType())
   case(EV_REQUEST_LIFE)
   {
      SetScriptResult(1500);}
  [color=red] }[/color]

@Initialize
  { objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS);
   ObjEnemy_Regist(objEnemy);

   let imgExRumia = GetCurrentScriptDirectory ~ "./ExRumia/ExRumia.png";
   ObjPrim_SetTexture(objEnemy, imgExRumia);
   ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64);
   ObjSprite2D_SetDestCenter(objEnemy);

   ObjMove_SetDestAtFrame(objEnemy, GetStgFrameWidth() / 2, 60, 60);
   
  }
 
@MainLoop
  {

        ObjEnemy_SetIntersectionCircleToShot(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 32);
   ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 24);
   if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0)
   {

      Obj_Delete(objEnemy);
      CloseScript(GetOwnScriptID());
      return;}
 }
Si je peux donner un conseil : sauvegarder l'intégralité du code dans un fichier bloc note, et réutiliser le à chaque script que vous allez faire.

Information Avancées :
Le présent chapitre et pour ceux voulant utiliser les fonctions vues ci dessus "à leur manière" Elle contient le définition des différentes fonctions, la liste des arguments de chaques fonctions et leurs effets. Un bon niveau sur danmakufu est conseillé. Pour les autres passez directement à la partie suivante:

Les entêtes de scripts:
Celles vues:
#TouhouDanmakufu[xxx] >Cette ligne sert à faire reconnaitre le script cmme êtant un script danmakufu. Les xxx peuvent être remplacé par Single, Plural, Stage et Player. Dans le 1er cas pas de problèmes, le 2nd concerne les enchainements de scripts (comme un boss en entier et pas seulement une spell par exemple) Stage, je ne pense pas que cela pose d eproblèmes non plus. enfin player... bah pareil ^^ selon le script construit, mettez la mention correspondante. Vous retrouverez le script sur danmakufu dans la menu du même nom (stage plural single ou all qui contient les 3, et player qui sera disponible pour certains scripts).

#ScriptVersion[3] > rien à dire dessus, cela permet juste d'indiquer quelle est la version de danmakufu. la version précédente il y avait un 2 a la place du 3.

#Title["xxx"] > déjà décrit
#Text["xxx"] > déjà décrit

Les autres têtes de script:
#ID["xxx"] > Remplace le nom du fichier (sachant que les scripts sont triés par ordre alphabétique des IDs, en cas d'absence de cette ligne l'ID sera le nom du fichier).

#Image["xxx"] > Permet d'ajouter une image au script mis en surbrillance.
#System["xxx"] > définit le système utilisé par le script, c'est à dire la base, le nombres de vies, la fenêtre de score sur la droite, le nombre de obmbes, etc... En cas d'absence le système par défaut sera choisi. (faites attention a ne pas déplacer le système par défaut ou tous vos scripts pourraient devenir injouables. By the way je ne serai pas surpris de voir émerger en plus de nouveaux scripts players et de nouveaux scripts boss, des nouveaux scripts system pour personnaliser l'interface.

#Background["xxx"] > donne le background, si non précisé il sera noir par défaut.
#BGM["xxx"] > comme son nom l'indique.
#Player["xxx","yyy",etc"] > Les xxx/yyy doivent être remplacés par les chemins menant aux scripts des players devant être accessible. Si non précisé tous les scripts de player se trouvant dans le dossier player (à l'intérieur de votre dossier script) pourront être utilisés.
#ReplayName["xxx"] > Pas sur d'avoir compris ça et flemne d'essayer, surement pour définir le nom par défaut des replay.

je complèterai cette partie plus tard si besoin est ou selon conseil.
Suitesur le prochain post probablement

EDIT Si un admin que cela plus à faire dans la section tuto qu'il n'hésite pas à déplacer le topic.


Dernière édition par Nasty_bdfp le Jeu 04 Aoû 2011, 5:59 pm, édité 3 fois
Nasty_bdfp
Nasty_bdfp
Lunatic
Lunatic

Messages : 843
Date d'inscription : 26/06/2010
Age : 33

Profil Joueur
 : TH13.5 - HM TH13.5 - HM
Niveau: Difficile
Score: (non communiqué)

https://www.youtube.com/user/bouledeflipper

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Nasty_bdfp Jeu 04 Aoû 2011, 12:38 am

Création du pattern : notre 1er tir

(je ne fais pas dans l'originalité je sais, mais ne pas être original n'est pas forcément un défaut lorsque vous faites un tuto).

Donc le plus difficile à comprendre est fait, il reste le plus difficile à mettre en oeuvre : Comment donner un beau pattern aux tirs de notre boss.

C'est pour cela qu'il faut savoir avant tout comment tirer: Vous vous souvenez de cette ligne que je vous ait fait mettre précédemment:
Code:
let frame=0;
Et bien cette ligne va nous servir à faire un décompte en frame de chaque passage. Personnellement je vous conseil de remplacer le "=0" par un "=-90"... Pourquoi? Tout simplement pour éviter que le boss se mette à tirer tant qu'il n'a pas atteint sa position de départ (il met 60 frames pou y arriver, j'ai rajouté 30 frames pour donner une minimarge).
rajoutez ensuite dans le MainLoop la ligne suivante :
Code:
frame++;
Cette ligne va rajouter un a la valeur de la variable" frame ". Après un tour du MainLoop, frame aura un en plus, après deux tours 2 en plus etc.... (vous pouvez aussi écrire frame+=1; ou frame=frame+1;, frame++ êtant plus rapide à écrire c'est celle que j'utilise instinctivement).

Je vous conseil d'ajouter aussi après la 4ème ligne ceci :
Code:
#include"script/default_system/Default_ShotConst.txt"
Ceci va permettre d'obtenir les graphiques disponibles dans le fichier default_ShotConst, qui nous servira plus tard.
Bien donc maintenant que nos détails techniques sont passés vous devriez avoir ceci:

Code:
#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["xxx"]
#Text["xxx:xxx"]
#include"script/default_system/Default_ShotConst.txt"

let objEnemy;
let frame = -90;
@Event
  {alternative(GetEventType())
   case(EV_REQUEST_LIFE)
   {
      SetScriptResult(1500);}
  }

@Initialize
  { objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS);
   ObjEnemy_Regist(objEnemy);

   let imgExRumia = GetCurrentScriptDirectory ~ "./ExRumia/ExRumia.png";
   ObjPrim_SetTexture(objEnemy, imgExRumia);
   ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64);
   ObjSprite2D_SetDestCenter(objEnemy);

   ObjMove_SetDestAtFrame(objEnemy, GetStgFrameWidth() / 2, 60, 60);
   
  }
 
@MainLoop
  {

        ObjEnemy_SetIntersectionCircleToShot(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 32);
   ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 24);
   if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0)
   {

      Obj_Delete(objEnemy);
      CloseScript(GetOwnScriptID());
      return;
   }
   frame++;

  }

insérez dans le @MainLoop, (je vous conseille de le mettre au dessus de la ligne "if (ObjEnemy_GetInfo([...]<=0)" et ne le mettez surtout pas à l'intérieur des crochets qui suivent cette ligne) les lignes suivantes :

Code:
if(frame == 60)
   {
      CreateShotA1(ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 3, 90, DS_BALL_S_RED, 30);
                frame = 0;
        }
On retrouve ce bloc de condition if que j'avais présenté pour mettre une fin au boss. Là, la condition est que frame soit =60.
La fonction CreateshotA1 est la fonction créatrice de tir : Elle fonctionne avec 6 "arguments" comme cela :
CreateshotA1 (Coordonnée X, Coordonnée Y, vitesse, angle, graphismes, délai)
Pas de problèmes je penses pour définir les coordonnées X et Y, ici les bullets vont apparait sur la même ligne et la même colonne que celle du boss.
La vitesse est exprimée en pixel par frame (ici le bullet va parcourir 3 pixels a chaque frame).
L'angle est utilisé comme le schèma ci dessous:
[Tuto]Danmakufu ph3 β1.[Work In Progress] 004a10
les graphismes donnent l'apparence du projectile créé.
Enfin le délai est le temps d'attente pour que le bullets apparaissent. ce temps d'attente sera symbolisé par la formation d'un nuage de la même couleur que le bullet, qui ne comprendra aucune collision.

la liste complète des différentes formes de bullets est disponible sur le fichier texte Default_ShotConst.txt" (script > défaut systel > default_shotconst); si j'ai le courage je ferai un schèma comme il en existait un pour la version précédente j'en ferais un.

Et pourquoi faire revenir frame à 0...? C'est évidemment pour faire un tour complet, afin que la valeur frame puisse de nouveau être égal à 60 et tirer un tir et ainsi de suite.
A la limite vous pouvez aussi remplacer "if (frame==60){" par :
Code:
if (frame%60==0&&frame>0){

et supprimer le frame =0; : le % 'est ce qu'on appelle un modulo (cf tuto de Dynast). Ce modulo a pour effet d'exiger que frame soit égal à un multiple de 60
Cependant, si on mettait ce modulo seul, le tir serait aussi déclenché pour les valeurs négatives (-60 par exemple)... d'ou l'intérêt d'y adjoindre une seconde condition, quie st que la valeur frame doit être supérieur à0.
Souvenez vous des modulos, ils sont vitaux pour faire certains patterns (notamment lorsque deux trois patterns différents se superposent sans avoir le même rythme de tir).

Vous pouvez lancer le script et vous apercevoir que le boss tire des bullets rouges de tailles normales de façon perpendiculaire. Bravo vous avez fait votre 1er tir.

Lancer le script et ça y est vous avez votre 1er tir.

Ce a quoi devrait ressembler votre script :
Code:
#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["xxx"]
#Text["xxx:xxx"]
#include"script/default_system/Default_ShotConst.txt"

let objEnemy;
let frame = -90;
@Event
  {alternative(GetEventType())
   case(EV_REQUEST_LIFE)
   {
      SetScriptResult(1500);}
  }

@Initialize
  { objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS);
   ObjEnemy_Regist(objEnemy);

   let imgExRumia = GetCurrentScriptDirectory ~ "./ExRumia/ExRumia.png";
   ObjPrim_SetTexture(objEnemy, imgExRumia);
   ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64);
   ObjSprite2D_SetDestCenter(objEnemy);

   ObjMove_SetDestAtFrame(objEnemy, GetStgFrameWidth() / 2, 60, 60);
   
  }
 
@MainLoop
  {

        ObjEnemy_SetIntersectionCircleToShot(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 32);
   ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 24);

   if (frame%60==0&&frame>0)
   {
      CreateShotA1(ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 3, 90, DS_BALL_S_RED, 30);}
   if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0)
   {

      Obj_Delete(objEnemy);
      CloseScript(GetOwnScriptID());
      return;
   }
   frame++;

  }

Création du pattern : des effets de tirs!

Création d'un cercle de tir!
Okay donc un tir c'est bien, mais ça n'est ni joli ni dangereux. Il est donc de faire un peu plus complexe: créez un tir en cercle: Comme l'a si bien dit Dynast, le programmeur est censé être une créature paresseuse cherchant toujours à en faire le moins possible. On ne va donc pas taper manuellement chaque fonction à la main pour faire apparaitre autant de bullets. Cherchons un autre moyen:

Très bien repartons du script suivant :
Code:
#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["xxx"]
#Text["xxx:xxx"]
#include"script/default_system/Default_ShotConst.txt"

let objEnemy;
let frame = -90;
@Event
  {alternative(GetEventType())
   case(EV_REQUEST_LIFE)
   {
      SetScriptResult(1500);}
  }

@Initialize
  { objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS);
   ObjEnemy_Regist(objEnemy);

   let imgExRumia = GetCurrentScriptDirectory ~ "./ExRumia/ExRumia.png";
   ObjPrim_SetTexture(objEnemy, imgExRumia);
   ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64);
   ObjSprite2D_SetDestCenter(objEnemy);

   ObjMove_SetDestAtFrame(objEnemy, GetStgFrameWidth() / 2, 60, 60);
   
  }
 
@MainLoop
  {

        ObjEnemy_SetIntersectionCircleToShot(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 32);
   ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 24);

      if (frame%60==0&&frame>0){


}
frame++;
   if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0)
   {

      Obj_Delete(objEnemy);
      CloseScript(GetOwnScriptID());
      return;
   }
  }

Cette fois ci insérons avant le @Initialize ceci :
Code:
let Bcount=0;

Et dans les crochets qui suivent le "if (frame%60==0&&frame>0)"les lignes suivantes:

Code:
let px = GetPlayerX();
      let py = GetPlayerY();
      let angle=0;
                let n=18;
      let angleToPlayer = atan2(py - ObjMove_GetY(objEnemy), px - ObjMove_GetX(objEnemy));
      while (Bcount<n){
         CreateShotA1(ObjMove_GetX(objEnemy),ObjMove_GetY(objEnemy), 3, angle + angleToPlayer, DS_RICE_S_BLUE, 30);
         angle+=360/n;
         Bcount++;
      }
Bcount=0;

pas de panique je vais tout vous expliquer :
Vous retrouver les let, on définit un peu plus de variable, pour des raisons pratiques. px et py sont des variables que l'on pourrait obtenir facilement autrement, mais c'est plus pratique pour faire la formule de angleToPlayer.D'ailleurs les samples disponible montrent qu'ils avaient aussi remplacés le ObjMoveGetX/Y par ex et ey. (ça va plus vite à taper je ne les blâmerai pas).
la variable angle va nous servir pour faire tirer les bullets en cercle.
La variable AngleToPlayer utilise une formule permettant de calculer l'angle entre le boss et le joueur.
Spoiler:
Cela va nous permettre de tirer le 1er bullets systéatiquement en direction du joueur.
n est censé être égal aux nombres de bullets que vous voulez (ici 18)

Maintenant attardons nous au principal du script ajouté : ce qui va nous permettre de tirer les bullets en cercle > "while Bcount<18" : Cette fonction va faire tourner en boucle son contenu jusqu'à ce que la condition ne soit plus remplis! Attention soyez très prudent avec ce conditionneur, car si vous y prenez pas garde votre script sera bloqué sur une boucle infinie, ce qui résultera en un freeze de danmakufu : VERIFIEZ TOUJOURS QUE LE RENOUVELLEMENT DE LA CONDITION FINIT PAR S ACHEVER! Cela se traduira presque toujours par une modification interne de la condition: En gros ici, a chaque boucle du while, Bcount va avoir un en plus (d'ou l'intérêt d'avoir mis Bcount++), il finira donc par atteindre 18, et il ne sera donc plus inférieur à 18. Le while va donc arrêter de se renouveler. Toutefois, pour que le script refonctionne à la prochaine lecture, il faut ramener le Bcount à 0, d'ou le Bcount=0; APRES LE WHILE (ça pourrait aussi marcher avant, mais surtout pas dedans).

Enfin jetons un oeil a la fonction create shot, les 2 1ers arguments ne changent pas, la vitesse non plus, le délai non plus, les graphismes changent car j'avais envie, mais il y a surtout un changement pour l'argument relatif à l'angle: il est maintenant égal à angle + angleToPlayer > angletoplayer est l'angle donné pour tirer directement vers le joueur lorsque le tir part du boss. angle est à 0 donc le 1er tir va viser directement le joueur. Pour les suivantes, a chaque fois l'angle sera augmenté de 360/n (une formule mathématique), c'est à dire qu'après "n" tir, l'angle aura fait un tour de 360.

Lancez le script, bien joué vous avez créé un cercle de tir qui en plus a un bullet qui vous vise toujours!

Vous pouvez alternativement utilisez cette fonction, qui est bien plus facile à utiliser,e t qui contrairement à ce que je croyais marche encore^^ :

Code:
let px = GetPlayerX();
      let py = GetPlayerY();
      let angle=0;
                let n=18;
      let angleToPlayer = atan2(py - ObjMove_GetY(objEnemy), px - ObjMove_GetX(objEnemy));
      loop(n){
         CreateShotA1(ObjMove_GetX(objEnemy),ObjMove_GetY(objEnemy), 3, angle + angleToPlayer, DS_RICE_S_BLUE, 30);
         angle+=360/n;
      }
Bcount=0;

La fonction loop a pour effet de relancer le script le autant de fois que la valeur de la variable entre parenthèses (ici n donc 18 fois)

Le script s'enr etrouve allégé, je n'ai pas voulu remplacer la formule que je vous ai donné précédemment par celle ci, car elle vous permet de vous familiariser avec le While, qui sera nécessaire dans certains cas!


Dernière édition par Nasty_bdfp le Sam 20 Aoû 2011, 7:51 pm, édité 7 fois
Nasty_bdfp
Nasty_bdfp
Lunatic
Lunatic

Messages : 843
Date d'inscription : 26/06/2010
Age : 33

Profil Joueur
 : TH13.5 - HM TH13.5 - HM
Niveau: Difficile
Score: (non communiqué)

https://www.youtube.com/user/bouledeflipper

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Nasty_bdfp Jeu 04 Aoû 2011, 12:39 am

Réservé pour de la place en plus au cas où.
Nasty_bdfp
Nasty_bdfp
Lunatic
Lunatic

Messages : 843
Date d'inscription : 26/06/2010
Age : 33

Profil Joueur
 : TH13.5 - HM TH13.5 - HM
Niveau: Difficile
Score: (non communiqué)

https://www.youtube.com/user/bouledeflipper

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Nasty_bdfp Jeu 04 Aoû 2011, 12:39 am

Faire un Boss avec plusieurs patterns :

Bon c'est bien, vous savez faire un pattern pour un boss, mais ça ne vous dit toujours pas comment faire un boss entier!
En effet, au dernière nouvelle un boss sans patterns multiples, c'est un mini boss, et vous aimeriez pouvoir balancez dans la tronche du malhereux qui s'essayera à votre script plusieurs non spells et spells d'affilées.

En fait il vous faudra ici plusieurs scripts: 1 par patterns que vous voulez insérer à votre boss, et 1 dernier appelé "plural" qui se chargera de regrouper et ordonner toutes ses joyeusetés...

Création D'une succession de patterns:
Okay donc avant tout il nous faut deux scripts single... vu que cleui qui écrit ce topic est flemmard, on va tout simplement réutiliser les deux scripts que nous avons créé précédemment :

Code:

#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["Attaque 1"]
#Text["xxx:xxx"]
#include"script/default_system/Default_ShotConst.txt"

let objEnemy;
let frame = -90;
@Event
  {alternative(GetEventType())
  case(EV_REQUEST_LIFE)
  {
      SetScriptResult(1500);}
  }
@Initialize
  { objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS);
  ObjEnemy_Regist(objEnemy);

  let imgExRumia = GetCurrentScriptDirectory ~ "./ExRumia/ExRumia.png";
  ObjPrim_SetTexture(objEnemy, imgExRumia);
  ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64);
  ObjSprite2D_SetDestCenter(objEnemy);

  ObjMove_SetDestAtFrame(objEnemy, GetStgFrameWidth() / 2, 60, 60);
  let Bcount=0;
  }
 
@MainLoop
  {

        ObjEnemy_SetIntersectionCircleToShot(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 32);
  ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ObjMove_GetX(objEnemy), ObjMove_GetY(objEnemy), 24);

      if (frame%60==0&&frame>0){
let px = GetPlayerX();
      let py = GetPlayerY();
      let angle=0;
                let n=18;
      let angleToPlayer = atan2(py - ObjMove_GetY(objEnemy), px - ObjMove_GetX(objEnemy));
      loop(n){
        CreateShotA1(ObjMove_GetX(objEnemy),ObjMove_GetY(objEnemy), 3, angle + angleToPlayer, DS_RICE_S_BLUE, 30);
        angle+=360/n;
      }
}
frame++;
  if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0)
  {

      Obj_Delete(objEnemy);
      CloseScript(GetOwnScriptID());
      return;
  }
  }
et...
Code:
#TouhouDanmakufu[Single]
#ScriptVersion[3]
#Title["Attack 2"]
#Text["Tuto part 2"]
#include"script/default_system/Default_ShotConst.txt"

let objEnemy;
let objPlayer;
let frame = 0;

@Event
{
   alternative(GetEventType())
   case(EV_REQUEST_LIFE)
   {
      SetScriptResult(1500);
   }
}

@Initialize
{
   objPlayer = GetPlayerObjectID();

   objEnemy = ObjEnemy_Create(OBJ_ENEMY_BOSS);
   ObjEnemy_Regist(objEnemy);

   let imgExRumia = GetCurrentScriptDirectory ~ "./ExRumia/ExRumia.png";
   ObjPrim_SetTexture(objEnemy, imgExRumia);
   ObjSprite2D_SetSourceRect(objEnemy, 64, 1, 127, 64);
   ObjSprite2D_SetDestCenter(objEnemy);
   let cx = GetStgFrameWidth() / 2;
   ObjMove_SetDestAtFrame(objEnemy, cx, 120, 60);
}

@MainLoop
{
   let ex = ObjMove_GetX(objEnemy);
   let ey = ObjMove_GetY(objEnemy);

   if(frame == 360)
   {
      let px = GetPlayerX();
      let py = GetPlayerY();

      let angleToPlayer = atan2(py - ey, px - ex);

      let iAngle = -20;
      while(iAngle <= 20)
      {

         let obj1 = CreateShotA1(ex, ey, 4, iAngle + angleToPlayer, DS_SCALE_BLUE, 30);
         ObjShot_SetDeleteFrame(obj1, 46);
         let jAngle = -15;
         while(jAngle <= 15)
         {
            let obj2 = CreateShotA1(0, 0, 0, 0, DS_SCALE_RED, 10);
            ObjMove_AddPatternA4(obj2, 0, 3, jAngle + 180, 0, 0, 3, objPlayer, NO_CHANGE);
            ObjShot_SetDeleteFrame(obj2, 61);

            let kAngle = -30;
            while(kAngle <= 30)
            {   let obj3 = CreateShotA1(0, 0, 0, 0, DS_SCALE_PURPLE, 10);
               ObjMove_AddPatternA4(obj3, 0, 2, kAngle, 0, 0, 3, objPlayer, NO_CHANGE);
               ObjShot_AddShotA1(obj2, obj3, 60);
               kAngle += 15;
            }
            ObjShot_AddShotA1(obj1, obj2, 45);
            jAngle += 15;
         }

         iAngle += 20;
      }

      frame = 0;
   }

   ObjEnemy_SetIntersectionCircleToShot(objEnemy, ex, ey, 32);
   ObjEnemy_SetIntersectionCircleToPlayer(objEnemy, ex, ey, 24);
   frame++;

   if(ObjEnemy_GetInfo(objEnemy, INFO_LIFE) <= 0)
   {
      Obj_Delete(objEnemy);
      CloseScript(GetOwnScriptID());
      return;
   }
}


Pour ceux qui se demandent d'ou provient ce 2ème script, je vous le donnerai quand j'aurai finis le tuto sur les patterns, sachez seulement que ce script est présent en tant que sample A04 dans votre fichier danmakufu, légèrement modifié.
Pour des raisons pratiques nous appelerons le 1er "Tuto 1" et le 2nd "Tuto 2"
Donc voila vous avez 2 scripts. mais on veut les faire s'enchainer comment faire?

C'est à ça que servent les scripts plural! créons un 3ème script "Tuto 3" (placez les directement dans le dossier script pour que le fichier trouve l'image).
Mettez y :

Code:
#TouhouDanmakufu[Plural]
#ScriptVersion[3]
#Title["Boss Tutoriel"]
#Text["Danmakufu pour les nuls : le boss"]

Donc les lignes 2 3 4 ne changent pas, la 1ère ligne on remarque que "plural" remplace "single" : C EST TRES IMPORTANT. C'est ce qui permettra au script de reconnaitre le script en tant que script plural. (et de le traiter en conséquence).

insérez à la suite de ces lignes:


Code:
@Initialize
{
   TPlural();
}

@MainLoop
{
   yield;
}

@Finalize
{
}


task TPlural
{
}

Quelques éléments nouveaux qui ne devraient pas l'être, sachez simplement que nous allons utiliser une task. Je les expliquerai plus haut quand la flemne me quittera...

On pourrait définir la task comme un script dans le script.on l'utilise essentiellement pour des raisons pratiques: pour créer une task il faut insérer une portion sous la forme : task [Nom de la task] { contenu }, ailleurs que dans des crochets. (à la fin pour des raisons pratiques en général).
Et pour utiliser cette task il suffira d'ajouter, dans le initialize ou le mainloop selon le but recherché, le nom de cette task. seul.

Ainsi ici nous avons
task TPlural{}
Qui définit la task, pour l'instant vide.
Et
TPlural;
Dans le initialize qui l'active.

Mais il faut encore définir ce à quoi servira cette task :

insérez dans les crochets de la task :

Code:
   let dir = GetCurrentScriptDirectory();
   let obj = ObjEnemyBossScene_Create();
   ObjEnemyBossScene_Add(obj, 0, dir ~ "Tuto 1.txt");
   ObjEnemyBossScene_Add(obj, 0, dir ~ "Tuto 2.txt");
   ObjEnemyBossScene_LoadInThread(obj);
   ObjEnemyBossScene_Regist(obj);

   while(!Obj_IsDeleted(obj))
   {
      yield;
   }
   CloseScript(GetOwnScriptID());

La 1ère ligne est de la pure paresse, je fais comme le gars qui m'a inspiré à fait... il est paresseux et à la flemne de copier 5 fois la même phrase, je le suis également.
Le 2nd, je vous ait deja expliqué, on crée une variable boss pour pouvoir lui dire quoi faire, c'est le même principe qu'avec l'image de Rumia
Les 2 lignes suivantes ont pour but d'ajouter une scène au boss... Ainsi le boss va enchainer les deux spells. Une fois que la 1ère est terminée la 2nde prendra le relai, on a mi entre guillemet après le dir le nom du fichier sous lequel nous avons inscrit les "scènes" single.
La ligne suivante est mal expliquée par le wiki, mais je pense qu'elle sert à charger les deux scripts d'un coup, pour ne pas avoir de lags au moment ou vous éliminerez la 1ère scène.
La suivante on la connait deja, et j'ai toujours autant de mal à l'expliquer, elle est là mettez là c'est tout.

Enfin
while(!Obj_IsDeleted(obj))
{
yield;
}
CloseScript(GetOwnScriptID());

Le While (!Obj_IsDeleted(obj)){yield;} définit que tant que l'objet obj n'est pas détruit (il sera détruit quand il tombera à court de vie), il faut ne rien faire... En effet, yield; a pour but d'attendre une frame (je schématise). cependant le while dit "tant que", tant que l'objet n'est pas détruit, il faut attendre une frame. Cette fonction va ainsi faire arrêter le script, et l'empêcher de continuer.
Quand le boss sera détruit, la dernière ligne pourra s'appliquer : La fermeture du script.

Lancer votre script, normalement il marche, et normalement vous avez réussi à faire succéder deux scripts sur un seul boss^^ bien joué. Vous pouvez maintenant ajouter n'importe quel script, remplacer les scripts du tuto par les votres, et recréer un tout nouveau boss... ou presque!

Simplissime n'est ce pas?

Récapitulatif :

Ce que vous devez avoir dans ce script :

Code:
#TouhouDanmakufu[Plural]
#ScriptVersion[3]
#Title["Boss Tutoriel"]
#Text["Danmakufu pour les nuls : le boss"]

@Initialize
{
   TPlural();
}

@MainLoop
{
   yield;
}

@Finalize
{
}


task TPlural
{
   let dir = GetCurrentScriptDirectory();
   let obj = ObjEnemyBossScene_Create();
   ObjEnemyBossScene_Add(obj, 0, dir ~ "Tuto 1.txt");
   ObjEnemyBossScene_Add(obj, 0, dir ~ "Tuto 2.txt");
   ObjEnemyBossScene_LoadInThread(obj);
   ObjEnemyBossScene_Regist(obj);

   while(!Obj_IsDeleted(obj))
   {
      yield;
   }
   CloseScript(GetOwnScriptID());
}
Si vous avez utilisez des noms différents pour vos scripts, n'oubliez pas de changer le contenu correspondant, ou au pire de renommer les scripts précédemment donné.
Conserver ce script vous en aurez besoin pour la suite du tuto.

Insérez une spell



Dernière édition par Nasty_bdfp le Mer 28 Déc 2011, 11:37 pm, édité 2 fois
Nasty_bdfp
Nasty_bdfp
Lunatic
Lunatic

Messages : 843
Date d'inscription : 26/06/2010
Age : 33

Profil Joueur
 : TH13.5 - HM TH13.5 - HM
Niveau: Difficile
Score: (non communiqué)

https://www.youtube.com/user/bouledeflipper

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par UFO_Buddha Jeu 04 Aoû 2011, 1:35 pm

Ouah merci Nasty >.<, ça va me permettre de m'y mettre un peu, parce que le laché de fonction sur le wiki est assez incompréhensible T_T
UFO_Buddha
UFO_Buddha
Normal
Normal

Messages : 172
Date d'inscription : 19/05/2010
Age : 27
Localisation : Lost place ~

Profil Joueur
 : TH12 - UFO TH12 - UFO
Niveau: Normal
Score: (non communiqué)

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Miplouf Saigyouki Sam 13 Aoû 2011, 2:48 pm

Nasty,petit coquin,la fonction loop existe toujours.Tout comme GetAngle to Player.

Code:


if(frame==120){
   let num=15;
      loop(num){
         
         
         CreateShotA1(ex , ey , 3,angle,DS_STAR_S_BLUE, 0);
         
         angle += 360/num;
      }
      
      
      frame = 60;}

Le GetAngleToPlayer existe toujours,il faut juste utiliser ceci dans les scripts:
Code:

let px = GetPlayerX();
      let py = GetPlayerY();
      let angleToPlayer = atan2(py - ey, px - ex);


if(frame==60){
   CreateShotA1(ex , ey , 3,angleToPlayer,DS_STAR_S_BLUE, 0);
frame=0;}
A mettre en dessous de let ex=GetEnemyX,bla bla.
Ca evitera d'avoir a utiliser atan2 plus d'une fois! Moe moe

Les radius sont toujours la au passage~
Miplouf Saigyouki
Miplouf Saigyouki
CB Terror 「Patate Sparker」

Messages : 190
Date d'inscription : 21/12/2009
Age : 29
Localisation : A un certain endroit

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Remilia Scarlet Sam 13 Aoû 2011, 10:08 pm

Je ne sais pas pas si c'est moi le sous doué ou si mon ordi déconne à ce sujet, mais je n'arrive pas à charger de System Frame alternatif (L'image qui encadre le jeu).

Je parle juste de l'image, c'était déjà possible sur le Ver[2] mais je savais déjà pas le faire.

Help ? Please ?
Remilia Scarlet
Remilia Scarlet
Cosmic Stalker
Cosmic Stalker

Messages : 343
Date d'inscription : 19/07/2011
Age : 29
Localisation : Entre mon PC et ma carafe de café

Profil Joueur
 : TH13.5 - HM TH13.5 - HM
Niveau: Normal
Score: (non communiqué)

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Nasty_bdfp Sam 13 Aoû 2011, 10:24 pm

Miplouf : t'es sur pour loop? j'ai essayé plusieurs fois mais ça bugguait é_e, je corrigerai ça quand je serai de retour (là j'ai pas le matériel qui faut pour travailler sur danmakufu).
Pour Le GetAngleToPlayer ce n'est pas une fonction mais une variable dans ce cas, qui calcule automatiquement cet angle, si tu avais lu le code que j'ai fait j'ai mis la Même formule juste en un peu plus compliqué, mais la formule marche de façon identique.

Pour remilia, je sais pas c'est pas mon domaine x) pas encore travaillé dessus... Même si j'avoue avoir mon idée (faut aller dans systeme je pense, et copier sur le système laissé en défaut en changeant l'image ou un truc comme ça, je peux pas te répondre précisément j'ai pas danamkufu sur cet ordi).
Nasty_bdfp
Nasty_bdfp
Lunatic
Lunatic

Messages : 843
Date d'inscription : 26/06/2010
Age : 33

Profil Joueur
 : TH13.5 - HM TH13.5 - HM
Niveau: Difficile
Score: (non communiqué)

https://www.youtube.com/user/bouledeflipper

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Miplouf Saigyouki Dim 14 Aoû 2011, 10:45 am

Le loop est approuvé!Je l'ai testé sur une de mes SC,ca marche nickel!:D
GetAngleToPlayer est simplifié dans mon truc,tu le mets une fois au début de MainLoop,et hop,ca y'est!

D'ailleurs,je sais que ce que je vais demander va sembler impossible,mais je voudrais savoir une chose:C'est quoi la difference entre une fonction et une task,c'est quoi qui est mieux?
Miplouf Saigyouki
Miplouf Saigyouki
CB Terror 「Patate Sparker」

Messages : 190
Date d'inscription : 21/12/2009
Age : 29
Localisation : A un certain endroit

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par ---Astre-Noir---ess Mar 16 Aoû 2011, 1:23 pm

A merci beaucoup !! Maintenant j'arrive a faire des cercles de tirs sans faire fonctions par fonctions :D . Par contre tu aurais pas quelquechose qui font partir les tir de travers ? Et une autre question que j'ai pas compris mais que vous avez quand même expliqué , comment faire GetAngleToPlayer sa marche pas c'est peut-être que je sais pas ou le mettre :/ ?
---Astre-Noir---ess
---Astre-Noir---ess
Easy
Easy

Messages : 68
Date d'inscription : 28/12/2010
Age : 26

Profil Joueur
 : TH12 - UFO TH12 - UFO
Niveau: Normal
Score: (non communiqué)

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Miplouf Saigyouki Mer 17 Aoû 2011, 10:04 am

Tu mets:

Code:
let ex = ObjMove_GetX(objEnemy);
   let ey = ObjMove_GetY(objEnemy);

      let px = GetPlayerX();
      let py = GetPlayerY();
      let angleToPlayer = atan2(py - ey, px - ex);

Dans ton Mainloop,ca permettra de calculer l'angle de l'ennemi jusqu'a toi~

Apres,c'est écrit "angleToPlayer", si tu veux mettre "GetAngleToPlayer", remplace "let angleToPlayer" par let GetAngleToPlayer...okais?:D
Miplouf Saigyouki
Miplouf Saigyouki
CB Terror 「Patate Sparker」

Messages : 190
Date d'inscription : 21/12/2009
Age : 29
Localisation : A un certain endroit

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par DgBarca Mer 17 Aoû 2011, 11:01 am

En sachant que pour GetAngleToPlayer dans ph3, il faut mettre l'ID du boss.
"GetAngleToPlayer(objEnemy)"
comme ça si tu veux des familiar qui visent le player tu met "GetAngleToPlayer(FamiliarID)"
DgBarca
DgBarca
Easy
Easy

Messages : 69
Date d'inscription : 17/09/2009
Age : 29
Localisation : France

Profil Joueur
 : TH08 - IN TH08 - IN
Niveau: Difficile
Score: (non communiqué)

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Nasty_bdfp Mer 17 Aoû 2011, 12:02 pm

Miplouf Saigyouki a écrit:
D'ailleurs,je sais que ce que je vais demander va sembler impossible,mais je voudrais savoir une chose:C'est quoi la difference entre une fonction et une task,c'est quoi qui est mieux?

Hmm Je crois (et je n'en suis pas sur) que La fonction s'applique directement sur l'ensemble ou elle est (mainloop drawloop ou une autre task)... alors que la task s'applique indépendamment.
EN gros, vu que c'est pas clair ce que je vient de dire, si tu fait une fonction wait (loop(n){yield;}), et que tu met ce wait dans mainloop, le mainloop s'arrêtera pendant n frame. Par contre sur une task, cela voudrait dire que la task attends nframes, mais elle n'arrête pas le mainloop pendant ses 20 secondes.

C'est la différence majeur que j'ai repéré^^ (si c'est la même chose que pour la 1ère version).

Sinon pour faire partir les tirs de travers? c'est à dire?
Nasty_bdfp
Nasty_bdfp
Lunatic
Lunatic

Messages : 843
Date d'inscription : 26/06/2010
Age : 33

Profil Joueur
 : TH13.5 - HM TH13.5 - HM
Niveau: Difficile
Score: (non communiqué)

https://www.youtube.com/user/bouledeflipper

Revenir en haut Aller en bas

[Tuto]Danmakufu ph3 β1.[Work In Progress] Empty Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]

Message par Contenu sponsorisé


Contenu sponsorisé


Revenir en haut Aller en bas

Revenir en haut

- Sujets similaires

 
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum