Author Topic: I just started using Danmakufu,  (Read 28113 times)

Cabblecorento

  • I'm a cat!
  • MEOW.
I just started using Danmakufu,
« on: May 12, 2009, 10:22:29 PM »
and like I should, I'm running into problems.

This script won't seem to work

(I only copied the main loop, as the rest works.

Code: [Select]
    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 100);
        if(frame==frame2){
            CreateShot01(1, 1, 3, GetAngleToPlayer, BLACK03, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+30, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+60, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+90, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+120, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+150, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+180, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+210, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+240, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+270, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+300, BLACK01, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+330, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer, BLACK03, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+30, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+60, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+90, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+120, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+150, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+180, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+210, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+240, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+270, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+300, BLACK01, 10);
            CreateShot01(pos1, 1, 3, GetAngleToPlayer+330, BLACK01, 10);
        }
if (frame2<10) {
frame2=10;
}
       
        frame++;
frame2--;
    }

Whenever I try to start it, it has an error screen popping up, apparently suggesting that this is the problem:

Code: [Select]
            CreateShot01(1, 1, 3, GetAngleToPlayer, BLACK03, 10);
            CreateShot01(1, 1, 3, GetAngleToPlayer+30, BLAC

Anybody know what's wrong?

Drake

  • *
Re: I just started using Danmakufu,
« Reply #1 on: May 12, 2009, 10:35:01 PM »
Are you using the Shot Replace script already?

Also, you might need to add () to GetAngleToPlayer. I dunno.
Screenshot the error message if not solved.

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by Aiけん | ウサホリ -

Cabblecorento

  • I'm a cat!
  • MEOW.
Re: I just started using Danmakufu,
« Reply #2 on: May 12, 2009, 10:50:36 PM »
Are you using the Shot Replace script already?

Also, you might need to add () to GetAngleToPlayer. I dunno.
Screenshot the error message if not solved.

I don't even know what a Shot Replace script is.

Drake

  • *
Re: I just started using Danmakufu,
« Reply #3 on: May 12, 2009, 11:00:00 PM »
That'd be why. Danmakufu doesn't originally have a black shot color.
RED, ORANGE, YELLOW, GREEN, AQUA, BLUE, PURPLE, WHITE are the colors available.

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by Aiけん | ウサホリ -

Stuffman

  • *
  • We're having a ball!
Re: I just started using Danmakufu,
« Reply #4 on: May 12, 2009, 11:05:22 PM »
Black shots don't exist in the engine, that's why you're getting the error. It doesn't know what a BLACK03 is.

Danmakufu's standard colors are red, orange, yellow, green, blue, purple, aqua, and white.

The Shot Replace script is a thingy someone made to change Danmakufu's default shots into the ones used by CtC. It uses shot_all.png, a popular bullet spritesheet which offers many kinds of bullets that Danmakufu does not, which is why Drake thought you were using it, since you wouldn't have black shots otherwise.

EDIT: Dangit Drake

Cabblecorento

  • I'm a cat!
  • MEOW.
Re: I just started using Danmakufu,
« Reply #5 on: May 12, 2009, 11:08:25 PM »
I changed it to purple, but now it just fires 4 then stops.

Stuffman

  • *
  • We're having a ball!
Re: I just started using Danmakufu,
« Reply #6 on: May 12, 2009, 11:15:47 PM »
I'm not quite sure what you're trying to accomplish with frame and frame2. What do they start at? In any case, the bullets only fire if frame=frame2, and since frame constantly goes up but frame2 alternates between 10 and 9, they'll only be equal at one point in the script.

Also 1,1 is an odd place to fire bullets from, that's just the upper left corner. The rest are just going offscreen.

Cabblecorento

  • I'm a cat!
  • MEOW.
Re: I just started using Danmakufu,
« Reply #7 on: May 12, 2009, 11:39:38 PM »
I'm not quite sure what you're trying to accomplish with frame and frame2. What do they start at? In any case, the bullets only fire if frame=frame2, and since frame constantly goes up but frame2 alternates between 10 and 9, they'll only be equal at one point in the script.

Also 1,1 is an odd place to fire bullets from, that's just the upper left corner. The rest are just going offscreen.

I guess I should have put the rest of the script...

Anyways, the idea was that as time went past, the bullets started to fire more rapidly, and then they'd be firing every sixth of a second. It'd also be firing from both corners.

Anyways, I decided to completely remake it.

Now it shoots them randomly, so your dodging to main fast bullets, while having to weave through many slower bullets.

It's also my first thing that can even be called anything close to a spellcard.

Any idea how to make text boxes? ><

Re: I just started using Danmakufu,
« Reply #8 on: May 13, 2009, 03:56:53 AM »
Text boxes? Hmm, could be referring to two things. Do you want to start an Event (where the player and the boss talk to eachother, as per all Touhou game bosses) or do you just want text to be displayed somewhere in the gaming window?

I'll explain the latter first, since it's much easier to code.

To just draw a bit of text anywhere on the screen, you'll need to call the following function in @DrawLoop, in which you'll declare the text you want to be shown, as well as it's size, opacity and coordinates:

DrawText("Text you want to be displayed", x-coordiante, y-coordinate, text size (12 is a nice standard), alpha value);

That's five parameters. The first is what you want to be displayed, in quotations if it's a text string. The second and third parameters are the text's x and y coordinates, respectively. The fourth parameter is the text's size, for which 12 is a nice standard, though it can be bigger or smaller. The final parameter is it's alpha value or opacity. That is, how deep you want it to be coloured. 255, the maximum value you can put in, is solid and you will see nothing through the text, but bullets can pass above it. 0 is completely see-through, and will thus appear invisible, so you probably don't want to put 0 as the last paramter. ~150 or so is about half see-through, so you'll see the background through the text a bit, but still be able to read the text.

In order for this function to work, you need to draw it every frame. So if you want it to be drawn for the whole duration of a spellcard, just call it in @DrawLoop and leave it alone (because @DrawLoop is run every frame, it will cause the text to be drawn every frame). If you want it to be displayed after a certain amount of time, just make a variable increment every drawloop (like drawcounter++; or something) and say:
if(drawcounter>=120){
 DrawText(...);
}
Which will have the text drawn after two seconds (120 frames) have passed. You know what to do, anyway, for whatever effect you're looking for.




Alrighty, for event scripts, you're gonna have to go beyond "script_enemy_main{}" inside of a spellcard and write the following:

Code: [Select]
script_event name{


@Initialize{
  [Load all your graphics and foolishness here]
 }

@MainLoop{
 SetChar(LEFT, [player graphic]);           //Set the player's character on the left side, with the graphic you've told it to display.
 SetGraphicRect(LEFT, [left-side], [top-side], [right-side], [bottom-side]);           //The region you're displaying of the graphic for the player character.
 MoveChar(LEFT, BACK)           //Move the player's character into the background, to show she is not speaking.
 SetChar(RIGHT, [enemy's grahic]);           //Set the boss' picture on the right side of the screen.
 SetGraphicRect(RIGHT, 0, 0, 200, 350);           //Set the boundry of the picture you want displayed.
 MoveChar(RIGHT, FRONT);           //Move the boss' image to the front to show that she is speaking.
 TextOutA("The text you want the character to speak goes here");           //Self explanatory. Danmakufu will not pass this function until a certain amount of time has passed, or the player clicks the shot button.
 MoveChar(RIGHT, BACK):           //Move the boss to the background, then...
 MoveChar(LEFT, FRONT);           //Move the player forward, to show that she will now speak.
 TextOutA("More words here");           //What the player will be speaking.
 End;           //This ends the event.
 }

@Finalize{
  [delete all your graphics here]
 }
}

Keep in mind that anything after "//" in Danmakufu is a comment and will not be processed, so I can explain the functions as they appear in the code.

To initialize the event, call in your script:

CreateEventFromScript("name");

Which will tell Danmakufu to look in the current file for an event script called "name", then run it. There are other functions and options, such as coloured speech and whatnot, which are defined and explained here.


As you can see, it's a massive amount of code for a very small effect. I would highly recommend NOT trying to tackle event scripts until you've had a lot of experience with Danmakufu and Stage Scripts, which are primarily where events are called from. So if you're looking to make text boxes or whatever, try to make do with the DrawText function.
« Last Edit: May 13, 2009, 04:06:25 AM by Naut »

Cabblecorento

  • I'm a cat!
  • MEOW.
Re: I just started using Danmakufu,
« Reply #9 on: May 14, 2009, 01:19:33 AM »
Another question. (They just keep coming.)

How would I be able to make it so that bullets go towards one position, then after a certain amount of time, make more bullets and spread out?

Then I probably won't have many more questions.

Re: I just started using Danmakufu,
« Reply #10 on: May 14, 2009, 03:47:19 AM »
You mean spawn bullets from another bullet? The AddShot function is what you're looking for, and that's explained rather nicely in Blargel's Basics tutorial, in case you haven't read it.

Don't feel bad for asking questions, it gives us something to do (plus, I rather enjoy solving these problems). I'm on this forum more often than I'll admit, so ask away!

Cabblecorento

  • I'm a cat!
  • MEOW.
Re: I just started using Danmakufu,
« Reply #11 on: May 16, 2009, 01:09:52 AM »
One question:

How would I make something like a stage?

Re: I just started using Danmakufu,
« Reply #12 on: May 17, 2009, 12:06:03 AM »
Don't.

Here's why: You're new to Danmakufu, and stages take ages to code and yield very little for the amount of work you'll end up putting into it. It's a really big turn-off from Danmakufu coding, so I would recommend getting comfortable with just plain Spell-cards and Plural Scripts before attempting stage files.



...



...



However, if you're absolutely certain that you want to make a stage, here we go:

Start with your usual crap in any danmakufu script, except this time you're specifying that this is a stage script:

Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Stage script tutorial]
#Text[How to make stages in Danmakufu]
#Image[]
#Background[]
#BGM[]
#Player[FREE]
#ScriptVersion[2]

You should know what everything here means, just make sure you've specified "Stage" after the first line.

Alrighty, onto how to script full-length stages. It's not very difficult actually, we just need to understand a few things beforehand. We actually don't even need to understand how tasks work, we just need to know how to use them. I won't bother explaining tasks and yield;, all of that can be found here. It's not necessary to know for this, but it certainly helps.

So the bulk of the code will go inside "script_stage_main{}". This is how it plays out:

Code: [Select]
script_stage_main{

  @Initialize{

  }
 @MainLoop{
   yield;
  }
  @Background{

  }
  @Finalize{

  }
}

Nothing unfamiliar. How this stage will play out will not be written in @MainLoop, but instead inside of a task. This way we can dictate exactly when things will occur by waiting a certain amount of frames before doing something else -- here's how we do that: We'll make a task just after script_stage_main and just before @Initialize, and call the name of that task in @initialize, like so:

Code: [Select]
script_stage_main{

 task stage{

 }

  @Initialize{
 stage;
  }
 @MainLoop{
   yield;
  }
  @Background{

  }
  @Finalize{

  }
}

This tells Danmakufu to run "stage" once at the very start of the script. So this way, we begin running our stage task as soon as the script starts. Let's declare some helper functions to make timing things in the stage task a little easier. We'll put these just before task stage{} so we can see them before anything else.

Code: [Select]
script_stage_main{

 function Wait(let frames){
   loop(frames){yield;}
 }
 function WaitForZeroEnemy{
  while(GetEnemyNum != 0){yield;}
 }
 task stage{

 }

  @Initialize{
 stage;
  }
 @MainLoop{
   yield;
  }
  @Background{

  }
  @Finalize{

  }
}

Alright, we've made two functions. The first is called Wait, and requires us to declare a parameter everytime we call it. What we've made it do is pause the script for however many frames we tell it to. So saying Wait(60); will tell Danmakufu to stop reading anything beyond it for 60 frames (1 second). The second function is called WaitForZeroEnemy, and doesn't require us to declare any parameters. It tells Danmakufu "when there are enemies on the screen (when the enemy count does not equal zero), wait". This is useful if you want the player to kill all the enemies you've spawned before continuing any further with your stage.

These functions will actually have use if we start putting things between them! So, let's get to spawning some enemies. The way we spawn an enemy is simple:

CreateEnemyFromFile(path of enemy script, x-coordinate, y-coordinate, velocity (if you didn't declare it in the script), angle (if you didn't declare it in the script), user-defined arguement);

These 6 parameters are simple: The first is the pathname of your enemy script, the second and third are the x and y coordinates of where you want your enemy to spawn, the fourth parameter is the velocity you want the enemy to have when you spawn it (you can set it to 0 and just define the velocity in the enemy script if you'd like), the fifth is the angle you want the enemy to move towards (again, can be defined in the script), and the last is a user-defined arguement. Basically, any value you want to pass on to the enemy script you put into the last paramet. You get this information by saying "GetArgument" in the enemy script. So, if I said 2 for the last parameter in CreateEnemyFromFile, in the enemy script I could say:

v = GetArgument;

And then the variable v would assume a value of 2 for that enemy script. Useful if you want to change bullet angles or something but still use the same enemy.

Alright, I've done alot of explaining about enemy scripts, yet you don't even know how to create them. Well, good knews! They're exactly  the same as what you've been creating all along, except with even less information! In an enemy script, you can neglect anything beginning with "#" (like #TouhouDanmakufu, #Title, etc), and just get straight to script_enemy_main. In that, it's just the same shit, but a different pile. You include your @Initialize, @MainLoop, @DrawLoop and @Finalize just like a boss script. Load graphics, spawn bullets, set life, all of it you do exactly the same. For enemies, you won't want them to have too much health, so you can kill them quickly. Typically have them spawn a really basic flurry of bullets, and just continue off in one direction (they will be destroyed upon leaving the game screen).

So all that information is nice, but how do we throw it all together into a stage? Let's take a look:

Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Stage script tutorial]
#Text[How to make stages in Danmakufu]
#Image[]
#Background[]
#BGM[]
#Player[FREE]
#ScriptVersion[2]

script_stage_main{

 function Wait(let frames){
   loop(frames){yield;}
 }
 function WaitForZeroEnemy{
  while(GetEnemyNum != 0){yield;}
 }
 task stage{
  Wait(120);
  CreateEnemyFromFile(GetCurrentScriptDirectory~"enemy.txt", GetCenterX, GetCenterY, 0, 0, 0);
  CreateEnemyFromFile(GetCurrentScriptDirectory~"enemy.txt", GetCenterX, GetCenterY, 0, 0, 0);
  WaitForZeroEnemy;
  CreateEnemyFromFile(GetCurrentScriptDirectory~"enemy2.txt", GetCenterX, GetCenterY, 0, 0, 0);
  WaitForZeroEnemy;
  CreateEnemyBossFromFile(GetCurrentScriptDirectory~"cirno.txt", 0, 0, 0, 0, 0);
  WaitForZeroEnemy;
  Wait(60);
  Clear;
 }

  @Initialize{
 stage;
  }
 @MainLoop{
   yield;
  }
  @Background{

  }
  @Finalize{

  }
}

Let's go through how this stage will play out. First, the stage will wait two seconds before anything happens. Then, it will spawn two enemies at the center of the screen whose behavior I've defined in "enemy.txt", which is located in the same script directory as my stage file. The stage script will then wait until the player kills those two enemies before spawning a different enemy, "enemy2.txt". The script will again wait for the player to kill the enemy, then it will create a boss. The CreateEnemyBossFromFile function is exactly the same as CreateEnemyFromFile function, except you can summon plural files as well, and the enemy will be treated as a boss (will have an enemy marker, can use spellcards, etc). The stage script will then wait for you to defeat the boss (can be a multi-spellcard plural file), then end the stage with the "Clear" function.

Make sure you include "yield;" in your @MainLoop for the stage file, this allows all the other yield; commands to work correctly.

And that's it. This stage is incredibly small, since stages spawn hundreds of different kinds of enemies, which require seperate enmy files or really complex GetArgument statements. The coding is long and tiring, but it looks freakin' sweet when you finish one off. Good luck!
« Last Edit: May 17, 2009, 12:14:33 AM by Naut »

Cabblecorento

  • I'm a cat!
  • MEOW.
Re: I just started using Danmakufu,
« Reply #13 on: May 17, 2009, 07:49:05 PM »
Thanks.

I'm going to get started on a 1 minute stage with a 1 attack mid-boss and a 3-attack boss.

Now I need to get images working. I need to look at Nuclear Cheese's tutorial again.

Re: I just started using Danmakufu,
« Reply #14 on: May 17, 2009, 08:14:01 PM »
Good luck, it takes freakin' months. [/hyperbole]

Edit: Actually, no. Not hyperbole.

[tear]
« Last Edit: May 17, 2009, 08:18:24 PM by Naut »

Chronojet ⚙ Dragon

  • The Oddity
  • 今コソ輝ケ、我ガ未来、ソノ可能性!!
Re: I just started using Danmakufu,
« Reply #15 on: July 20, 2009, 09:42:11 PM »
OK. I finished making my first few events. But I want to make an event like the event in Touhou Eiyashou where the player has to choose between Final A and Final B. How should that look like?

Re: I just started using Danmakufu,
« Reply #16 on: July 20, 2009, 11:53:57 PM »