Maidens of the Kaleidoscope
~Hakurei Shrine~ => Rika and Nitori's Garage Experiments => Topic started by: Cyclone722 on April 28, 2009, 08:53:17 PM
-
Hi, I'm new to danmakufu and to the forum. I understand some basics, but I have a few questions.
1.How to make a boss stop and/or switch attacks.(not switching spellcards)
2.How to get the angle to the player when bullet not fired directly from the boss.
3.Correct way to add bgm (just can't seem to figure it out.)
I have looked through the tutorials here, if I just missed something could you point it out for me?
I'll probably have more questions later.
-
I can at least help with your second question.
To aim a regular bullet directly at the player from anywhere, use the command SetShotDirectionType(PLAYER);, then fire it at an angle of 0. It will cause danmakufu to measure the angle differently; 0? is not straight to the right now, but directly towards the player. After you fired the bullet, use the command SetShotDirectionType(ABSOLUTE); to return the measurement of angles to its usual state.
-
1) Well I suppose you know that most code for spellcards looks sorta like this:
@Mainloop
if frame==100 {
do the attack
}
frame++;
if frame>100 {
frame=0
}
}
If you want to alternate attacks it would be more like...
@Mainloop
if frame==100 {
do the attack
}
if frame==200 {
do a different attack
}
frame++;
if frame>200 {
frame=0
}
}
Or maybe you want to have it change depending on certain circumstances, in which case it would look more like
@MainLoop
if frame==100 && attacktype==1
do the attack
}
if frame==100 && attacktype==2
do a different attack
}
if life<100 or whatever your condition is
attacktype=2
}
frame++
if frame>100{
frame=0
}
}
3) Put BGM in the same folder as your script.
let music=GetCurrentScriptDirectory~"insert filename here";
at the top with the rest of your variables, then
PlayMusic(music);
in @Initialize or something.
-
Ah, Thanks!
Closing everything in the bracket things gets confusing sometimes.
-
I can at least help with your second question.
To aim a regular bullet directly at the player from anywhere, use the command SetShotDirectionType(PLAYER);, then fire it at an angle of 0. It will cause danmakufu to measure the angle differently; 0? is not straight to the right now, but directly towards the player. After you fired the bullet, use the command SetShotDirectionType(ABSOLUTE); to return the measurement of angles to its usual state.
Unfortunately, this only works when fired directly from the boss's position (at least in my experience). SetShotDirectionType(PLAYER) bases the shot angle off of the angle from the boss to the player, regardless of where you're firing the shot from.
In order to get the correct angle from another position, you need to use a quick bit of trigonometry.
Here's a simple example:
let dy = GetPlayerY() - bullet_y;
let dx = GetPlayerX() - bullet_x;
let a = atan2(dy, dx);
// fire shot from (bullet_x, bullet_y) at angle a
CreateShot01(bullet_x, bullet_y, 1.0, a, RED01, 0);
Basically, I first store the difference between the player's coordinates and the bullet's coordinates in dx and dy. Next, I use the function atan2() (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Mathematical_or_Information_Functions#atan2) to get the angle.
atan2() is a special form of the arctangent function (see wikipedia for generic info (http://en.wikipedia.org/wiki/Trigonometric_functions#Reciprocal_functions)) which takes the X and Y differences, and produces the angle.
Hi, I'm new to danmakufu and to the forum. I understand some basics, but I have a few questions.
3.Correct way to add bgm (just can't seem to figure it out.)
Use PlayMusic( (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Sound_Functions#PlayMusic)) to start it playing. The song will loop back to the beginning when it reaches the end.
To use these, you need to pass it the name of the music file. For instance, if you have a music file awesome_sound.mp3 in the same directory as your script, you can do something like this:
// Store the file's name so it is easier to reference later
let music_file = GetCurrentScriptDirectory() ~ "awesome_sound.mp3";
@Initialize
{
// stuff
PlayMusic(music_file);
// stuff
}
You can use DeleteMusic (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Sound_Functions#DeleteMusic) to stop the music playing.
-
Ok, thanks.
How would I set a variable to track the boss's life?
-
Actually I'm pretty sure SetShotDirectionType(PLAYER) DOES track from bullet to player. It's GetAngleToPlayer that can only do boss-to-player. Still, it doesn't hurt to know the actual formulas.
How would I set a variable to track the boss's life?
variable = GetEnemyLife(); Or heck you don't even need a variable, you can just stick GetEnemyLife() wherever you would use that variable.
-
ok, how do you get a random number (ex. random angle, x or y point)
I'm not overly diligent about danmakufu if you haven't noticed.
Anyway, if this is in another thread/tutorial, could you point me in the right direction?
-
i = rand(minimum number, maximum number);
rand generates numbers that can have decimals, use rand_int if you want only whole numbers.
You can also stick rand anywhere you would need to put a number, like:
CreateShot01(GetX,GetY,3,rand(0,360),RED01,0);
-
hmm, Guess I just had a space wrong or somthing... thanks.
-
building on the last thing, how would I make a ring of bullets appear in a random area?
-
Same way you would for a regular shot ring, but before the while loop do x=rand and y=rand to set a random position for it, and use x and y in place of GetX and GetY.
-
Example:
x = rand(minimumx,maximumy);
y = rand(minimumy,maximumy);
angle = rand(0,360);
loop(10)
{
CreateShot01(x,y,2,angle,RED01,10);
angle += 36;
}
Obviously you have to adjust the amount "angle" changes by if you change the number of bullets fired.
-
here's another one...
how can I make something like a 3 ring burst, a pause, another 3, pause...etc.?
-
ring
wait(5)
ring
wait(5)
ring
wait(100)
-
loop(20){
CreateShot01(x, y, 3, angle, BLUE50, 0);
wait(5);
CreateShot01(x, y, 3, angle, BLUE50, 0);
wait(5);
CreateShot01(x, y, 3, angle, BLUE50, 0);
wait(100);
Should it look something like this...? I get an error.
(this isn't the complete attack, just the part I need to wait on)
-
Ummm... did you put this exact code in your main loop..?
Then it would be no surprise that it didn't work.
"wait(5);" is not a real command. The proper way to type it out is "loop(5){ yield; }", and it only works correctly if you use it inside a task.
If you want to handle this three-ring-burst in your main loop, your best bet would be to create a timer variable called frame or something, then put this in your main loop:
frame++;
if(frame==60||frame==65||frame==70){
---Code-That-Makes-A-Ring---
}
if(frame==120) { frame=0; }
The timer variable is increased every frame. If the value of it is 60, 65 or 70, a ring of your desired kind will be shot. If the timer reaches 120, it will reset to zero.
-
Drake is getting lazier and lazier nowadays....
Anywho, what he means is make a task and have it loop yield; a few times to wait frames before doing something else. "Wait(x);" isn't actually a command that you can use, rather a function that most people create when throwing together stage scripts. Helps others know what's going on.
The code he means would look something like this:
script_enemy_main{
task ShotBurst(let x, let y, let angle){
CreateShot01(x, y, 3, angle, BLUE50, 0);
loop(10){yield;} //This pauses the task for ten frames. Will only work if you also have "yield;" in @MainLoop.
CreateShot01(x, y, 3, angle, BLUE50, 0);
loop(10){yield;}
CreateShot01(x, y, 3, angle, BLUE50, 0);
//etc.
}
let frame = 0;
@Initialize{
//blah blah...
}
@MainLoop{
frame++;
if(frame==120){
ShotBurst(GetX, GetY, GetAngleToPlayer);
frame = 0;
}
yield;
}
//etc.
This would start the task "ShotBurst" every two seconds, meaning that every two seconds three bursts of shots will be fired, one ten frames after the other, and so on. Make sure to include "yield;" at the end of your @MainLoop, so that all other yield; commands work correctly within tasks.
Edit: Damnit Iryan
-
if(frame2==60||65||70){
let x=rand(100,300);
let y=rand(50,224);
loop(20){
CreateShot01(x, y, 3, angle, BLUE50, 0);
CreateShot01(x, y, 3, angle, BLUE50, 0);
CreateShot01(x, y, 3, angle, BLUE50, 0);
angle += 360/20;
}
frame2=0;
}
frame2++;
I know what I did wrong, but this was cool anyways!
kinda like rippling water.
-
Is that the code you use inside your script? And it fires three-ring-bursts?
That'd puzzle me.
|| is a conditional OR. The code inside the if brackets will be executed if at least one of the conditions is met. As you put the frame reset inside this bracket, the reset will take place directly after the first ring is fired.
-
heres what I got in the end
if(frame2==60||frame2==65||frame2==70){
let x=rand(100,300);
let y=rand(50,224);
loop(20){
angle += 360/20;
CreateShot01(x, y, 3, angle, BLUE50, 0);
CreateShot01(x, y, 3, angle, BLUE50, 0);
CreateShot01(x, y, 3, angle, BLUE50, 0);
}
}
if (frame2==120){
frame2=0;
}
frame2++;
This was what I actually wanted to happen.
-
This is a little more complicated, but I'm trying to create a spiral effect.
kinda like a whirlpool.
the bullets would start at a point and spiral inward to a single point.
-
This is a little more complicated, but I'm trying to create a spiral effect.
kinda like a whirlpool.
the bullets would start at a point and spiral inward to a single point.
Bllrbll. (http://www.shrinemaiden.org/forum/index.php?topic=166.msg4426#msg4426)
-
Do you want bullets to come from beyond the borders of the playing field and move to the center in a spiral pattern, then dissappear in the center?
@Intitialize, create a variable called phase with a random value and call SetShotAutoDeleteClip(300, 300, 300, 300);
Then put this in your main loop:
phase+=angv;
ascent(i in 0..n){
let x=GetX+300*cos(phase+360*i/n);
let y=GetY+300*sin(phase+360*i/n);
CreateShotA(1 , x, y, 0);
SetShotDataA(1, 0, v, phase+180+360*i/n, 0, 0, 0, BLUE21);
SetShotKillTime(1, 300/v);
FireShot(1);
}
v = speed of your bullets
n = number of "arms" your whirl has.
angv= angular velocity of your whirlpool
Inserting a value for v that will divide 300 into a non-integer-number is likely to cause... bad things.
?dit: *cough* forgot the FireShot command, *cough*
-
hmm... that is interesting but not what I need.
(http://i731.photobucket.com/albums/ww315/Cyclone722/whirlexample.jpg)
this is somewhat closer.
-
Mh. Do the "arms" of the cyclone have to unite? Because that would be... ewwww...
Another take on this cyclone thing would be to use object bullets...
task TBall(angle, rad, v, angv, graph){
let obj = Obj_Create(OBJ_SHOT);
Obj_SetSpeed(obj, 0);
Obj_SetAngle(obj, 0);
ObjShot_SetDelay(obj, 120);
ObjShot_SetGraphic(obj, graph);
let time=0;
while(Obj_BeDeleted(obj)==false) {
angle+=angv;
rad-=v;
Obj_SetAngle(obj, angle + 90);
Obj_SetPosition(obj, GetCenterX+rad*cos(angle), GetCenterY+rad*sin(angle));
If(rad<0){ Obj_Delete(obj); }
yield;
}
}
-
CreateShotA a bullet with a constant angular velocity that has a slowing velocity, which will give it the whirlpool effect.
CreateShotA(0, GetX, GetY, 0);
SetShotDataA(0, 0, 3, angle, 2, -0.005, 0, RED12);
FireShot(0);
-
Yeah, but to get the correct values for the bullet to spiral towards a specific point requires some serious maths, doesn't it?
...wait, could it be that the center of the cyclone would be the center of the circle the bullet would move at if the speed didn't accelerate? Which would be... a circle with the radius r = ( (360/angular velocity)*v )/(2*pi)
Which would lead to the center position of... (X-r*cos(firing angle-90)| Y - r*sin(firing angle + 90) )....
Nah, that's probably wrong...