[Tuto]Danmakufu ph3 β1.[Work In Progress]
+2
UFO_Buddha
Nasty_bdfp
6 participants
Page 1 sur 1
[Tuto]Danmakufu ph3 β1.[Work In Progress]
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:
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.
@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:
Surtout n'oubliez pas les ; a la fin de chaque ligne de script, qui permet de différencier les tâches à accomplir.
Note:
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):
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:
Note:
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 :
Il faut donc permettre une fin au script : insérez ces lignes plus loin dans le MainLoop:
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 :
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.
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
{
}
- Spoiler:
- Note: Dans les samples qui vous sont fournis avec le fichier la 1ère ligne peut avoir un nom différent, en japonais (kanjis?), mais cela fonctionne aussi sous cette forme.
note 2:Le @Event et son contenu (dans "{}") peut être déplacé après le main loop, ou entre le main loop et le initialize).
Dès à présent votre fichier sera repéré par le programme danmakufu... ce qui ne veux pas dire qu'il fonctionne déjà, vu qu'il est vide.
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:
- Ceux qui connaissent déjà les scripts danmakufus peuvent s'apercevoir que 2 blocs ont disparues : @Finalize et @DrawLoop.
@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);
Surtout n'oubliez pas les ; a la fin de chaque ligne de script, qui permet de différencier les tâches à accomplir.
Note:
- Spoiler:
- Dans la précédente version de danmakufu, nous n'avions pas à faire ça, car tout le script était assujetti à cette ligne : " script_enemy_main{}" qui indiquait que tous le script était destiné à cet ennemi. Là le script existera "indépendamment" de l'ennemi. Il ne cessera pas d'exister si l'ennemi est détruit. L'ennemi n'est qu'un objet parmis d'autres, même si il pourrait être le seul objet que le script ait à traiter.
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);
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);
Note:
- Spoiler:
- GetStgframeWidth est tout simplement l'équivalent GetClipMaxX de l'ancienne version de danmakufu. Donc en l'espècela formule est égale à GetCenterX sur l'ancienne version.
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);
- Spoiler:
- Ces deux lignes remplacent les traditionnelles setcollisionA et SetCollisionB. Il est comme ça plus évident de voir quelle ligne correspond à quelle collision.
- Spoiler:
- ce rôle était autrefois tenu par @Finalize, qui a disparu sur cette nouvelle version.
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;
}
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;}
}
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
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
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:
rajoutez ensuite dans le MainLoop la ligne suivante :
Je vous conseil d'ajouter aussi après la 4ème ligne ceci :
Bien donc maintenant que nos détails techniques sont passés vous devriez avoir ceci:
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 :
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:
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 :
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 :
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 :
Cette fois ci insérons avant le @Initialize ceci :
Et dans les crochets qui suivent le "if (frame%60==0&&frame>0)"les lignes suivantes:
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.
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^^ :
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!
(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;
rajoutez ensuite dans le MainLoop la ligne suivante :
- Code:
frame++;
Je vous conseil d'ajouter aussi après la 4ème ligne ceci :
- Code:
#include"script/default_system/Default_ShotConst.txt"
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;
}
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:
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:
- Malheureusement GetAngleToPlayer a disparu de la circulation, la formule que j'ai tapé permet de l'obtenir.
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
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
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 :
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 :
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:
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
Et
Mais il faut encore définir ce à quoi servira cette task :
insérez dans les crochets de la task :
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
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 :
Conserver ce script vous en aurez besoin pour la suite du tuto.
Insérez une spell
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;
}
}
- 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
Qui définit la task, pour l'instant vide.task TPlural{}
Et
Dans le initialize qui l'active.TPlural;
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());
}
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
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
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- Normal
- Messages : 172
Date d'inscription : 19/05/2010
Age : 27
Localisation : Lost place ~
Profil Joueur
: TH12 - UFO
Niveau: Normal
Score: (non communiqué)
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
Nasty,petit coquin,la fonction loop existe toujours.Tout comme GetAngle to Player.
Le GetAngleToPlayer existe toujours,il faut juste utiliser ceci dans les scripts:
Ca evitera d'avoir a utiliser atan2 plus d'une fois!
Les radius sont toujours la au passage~
- 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;}
Ca evitera d'avoir a utiliser atan2 plus d'une fois!
Les radius sont toujours la au passage~
Miplouf Saigyouki- CB Terror 「Patate Sparker」
- Messages : 190
Date d'inscription : 21/12/2009
Age : 29
Localisation : A un certain endroit
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
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 ?
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- 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
Niveau: Normal
Score: (non communiqué)
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
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).
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).
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
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?
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- CB Terror 「Patate Sparker」
- Messages : 190
Date d'inscription : 21/12/2009
Age : 29
Localisation : A un certain endroit
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
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- Easy
- Messages : 68
Date d'inscription : 28/12/2010
Age : 26
Profil Joueur
: TH12 - UFO
Niveau: Normal
Score: (non communiqué)
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
Tu mets:
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
- 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- CB Terror 「Patate Sparker」
- Messages : 190
Date d'inscription : 21/12/2009
Age : 29
Localisation : A un certain endroit
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
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)"
"GetAngleToPlayer(objEnemy)"
comme ça si tu veux des familiar qui visent le player tu met "GetAngleToPlayer(FamiliarID)"
DgBarca- Easy
- Messages : 69
Date d'inscription : 17/09/2009
Age : 29
Localisation : France
Profil Joueur
: TH08 - IN
Niveau: Difficile
Score: (non communiqué)
Re: [Tuto]Danmakufu ph3 β1.[Work In Progress]
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?
Sujets similaires
» [Danmakufu] Tuto :p
» Différence de version danmakufu pour ceux à qui danmakufu ne marche pas
» Mes Projets sur Danmakufu
» [Tuto] Touhou Sky Arena - Custom BGM
» Le topic des Tuto pour le Micro, le Chant et Audacity
» Différence de version danmakufu pour ceux à qui danmakufu ne marche pas
» Mes Projets sur Danmakufu
» [Tuto] Touhou Sky Arena - Custom BGM
» Le topic des Tuto pour le Micro, le Chant et Audacity
Page 1 sur 1
Permission de ce forum:
Vous ne pouvez pas répondre aux sujets dans ce forum
|
|