Maidens of the Kaleidoscope

~Hakurei Shrine~ => Rika and Nitori's Garage Experiments => Topic started by: Darkblizer on May 02, 2009, 05:36:16 AM

Title: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on May 02, 2009, 05:36:16 AM
Hey, I just decided I'd make a place where people can ask questions and post their problems, hopefully to be answered.

I might be able to answer some, but first, I have a question of my own. What's the difference between a sub, a task, and a function? they seem to be used in similar ways.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 02, 2009, 06:18:12 AM
In order of processing speed, from fastest to slowest:

sub
function
task

And here's why. A sub is just a routine that you often call that requires no changing whatsoever. So if I wanted to make the same array of shots happen over and over again, but at different places in the script, I could say somewhere in script_enemy_main:

Code: [Select]
sub bullatz{
CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 30, RED02, 0);
CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 20, RED02, 0);
CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 10, RED02, 0);
CreateShot01(GetX, GetY, 3, GetAngleToPlayer, RED02, 0);
CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 10, RED02, 0);
CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 20, RED02, 0);
CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 30, RED02, 0);
}

And then say bullatz; anywhere in my script and those shots will be fired.

A function is the same thing, except you can edit parameters of the shots as you're calling them. So, to fire a similar array of shots:

Code: [Select]
function bullutz(angle){
CreateShot01(GetX, GetY, 3, angle - 30, RED02, 0);
CreateShot01(GetX, GetY, 3, angle - 20, RED02, 0);
CreateShot01(GetX, GetY, 3, angle - 10, RED02, 0);
CreateShot01(GetX, GetY, 3, angle, RED02, 0);
CreateShot01(GetX, GetY, 3, angle + 10, RED02, 0);
CreateShot01(GetX, GetY, 3, angle + 20, RED02, 0);
CreateShot01(GetX, GetY, 3, angle + 30, RED02, 0);
}

This time, I'll call bullutz(90); to shoot this array of bullets with the updated angle of 90 degrees. I could say bullutz(270); for another direction. And that's what functions are in Danmakufuland. Ah, you can also call more than one paramter in a function, so don't feel limited by only one independent variable.

A task, as you might guess, is an upgraded function, and thus takes the most processing power. With tasks you are basically creating another @MainLoop that you control whenever it's run. To do this, tasks use the magical operator called yield;. yield; allows you to freely switch between processing your task and processing your @MainLoop, so you can list ordered events, and have them only carry out your actions once without repeat, and still edit them. yield; suspends the current task or MainLoop and then carries onto another task until it hits another yield; command, then it goes back to the MainLoop and finishes the frame cycle. It'll continue where it left off the next frame, which makes it very easy to list ordered events. A task is basically a list of events that you want to happen, that you can freely edit at anytime during the script using the same parameters as a function.

And an example of a task:

Code: [Select]
task attack(delay, angle){
CreateShot01(GetX, GetY, 5, GetAngleToPlayer, RED03, delay);
loop(120){yield;}
loop(5){
  CreateShot01(GetX, GetY, 3, GetAngleToPlayer, BLUE01, 0);
  loop(5){yield;}
  }
CreateShot01(GetX, GetY, 2, angle, YELLOW12, 0);
}

So now, I'll call attack(5, 90); somehwere in @MainLoop to fire of a large red shot towards the player with 5 delay, the script will wait two seconds (120 frames, the loop(120){yield;} statement), then fire 5 blue shots in succession but wait 5 frames inbetween each shot, and then finally firing a small yellow shot at 90 degrees.

It should be noted that you MUST include yield; somewhere in your @MainLoop (preferably at the beginning or end, easier to keep track of) and call it every frame to ensure that the yield; command works properly in your tasks.


Anyways, you probably already knew about yield; and crap, but I thought I would be clear with the explanation and include everything, even though this is a very poor description of the yield; command and what it does.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 03, 2009, 12:13:11 AM
I'll contribute with my own question now, I suppose. Does GetAngleToPlayer output a value between 0 and 360, a value between -180 and 180, or something else? Does atan2() have the same output parameters?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 03, 2009, 04:38:37 AM
There's a way to check. Spawn a bullet with the delay time GetAngleToPlayer, but stand in the upper right corner. Similarly you could set it to atan2(player-boss, player-boss).

Obviously if you get an error it's a negative value.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 03, 2009, 04:48:43 AM
As far as I know whenever the engine outputs an angle it's in the -180 to 180 range, even though it accepts any degree amount you put in.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Garlyle on May 03, 2009, 04:07:49 PM
Quickest way I can think of: Base script, boss moves to center of screen, and have a DrawText string that writes the GetAngleToPlayer onto the screen somewhere so you can check it.

I did the same when trying to test out damage originally: A boss script that, once its invincibility wore off, counted the frames that passed until you beat it.  Since it didn't move, it let me test damage in terms of how many frames it took to take down ~1000 HP.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 03, 2009, 05:44:04 PM
Figures. Here's the test results:


(http://i641.photobucket.com/albums/uu134/Nautth/angletest2.jpg)

(http://i641.photobucket.com/albums/uu134/Nautth/angletest1.jpg)

GetAngleToPlayer outputs an angle between 0 and 360, atan2 outputs an angle between -180 and 180. Why is this not surprising...?

Sigh, thanks Danmakufu.

Interestingly enough, the angles are not the same, so my thought that GetAngleToPlayer = atan2(GetPlayerY - GetY, GetPlayerX - GetX) seems to be incorrect, even if the angle has 360 added to it if it outputs a negative value (notice the decimal value...? Not cool). They are negligably different though, so it doesn't really make much of a difference in a script. But really, what the hell.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 03, 2009, 07:54:20 PM
atan2 is probably less accurate considering Danmakufu does math with rounded decimals based on pixel-perfect locations.

Although if that's how it works, I wonder how GetAngle works...?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on May 05, 2009, 12:58:02 AM
I've got a question.


1) Currently, I am messing with the curve laser function (CreateLaserC/SetLaserDataC). I place an AddShot (CreateShotA) to the lasers.

However, I add the bullets to the lasers, but every single bullet added to a laser goes in one direction (i.e. each curved laser goes in different directions, but every other bullet flies in the direction of, for example, 0 degrees). In addition, I am only looping one laser to add each of the bullets (one laser is looped five times in equal distances apart, the AddShot bullets are also looped to the one laser).

Here is the code I am trying to work with.

Code: [Select]
#TouhouDanmakufu
#Title[Winter Sign "Flower Wither Away"]
#Text[Test script]
#Image[.\img\Scarletsign.png]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_remilia.png";

let count = 0;
let a = 72;

@Initialize {
SetLife(2500);
SetTimer(60);
SetScore(10000000);

SetMovePosition02(225, 120, 60);
CutIn(YOUMU, "Winter Sign "\""Flower Wither Away"\", "", 0, 0, 0, 0);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 128, 128);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 90){
PlaySE("lib\THCCL\SE\lazer00.wav");
loop(5){
CreateLaserC(1, GetX, GetY, 10, 30, WHITE01, 0);
SetLaserDataC(1, 0, 5, a, 4, 0, 3);
SetLaserDataC(1, 50, NULL, NULL, 5, -0.05, 2);
SetLaserDataC(1, 90, NULL, NULL, 0, 0.05, 5);
a += 360/5;

ascent(i in 1..900){
    CreateShotA(2, 0, 0, 20);
    SetShotDataA(2, 0, 1, 30, 0, 0, 1, BLUE11);
    CreateShotA(3, 0, 0, 20);
    SetShotDataA(3, 0, 1, 180, 0, 0, 1, BLUE11);
    CreateShotA(4, 0, 0, 20);
    SetShotDataA(4, 0, 1, -30, 0, 0, 1, BLUE11);
    AddShot(i*6+60, 1, 2, 0);
    AddShot(i*6+61, 1, 3, 0);
    AddShot(i*6+61, 1, 4, 0);
}

FireShot(1);
}
}

if(count == 210){
PlaySE("lib\THCCL\SE\lazer00.wav");
loop(5){
CreateLaserC(5, GetX, GetY, 10, 30, WHITE01, 0);
SetLaserDataC(5, 0, 5, a, -4, 0, 3);
SetLaserDataC(5, 50, NULL, NULL, -5, -0.05, 2);
SetLaserDataC(5, 90, NULL, NULL, 0, 0.05, 5);
a += 360/5;

ascent(i in 1..900){
    CreateShotA(6, 0, 0, 20);
    SetShotDataA(6, 0, 1, 30, 0, 0, 1, BLUE11);
    CreateShotA(7, 0, 0, 20);
    SetShotDataA(7, 0, 1, 180, 0, 0, 1, BLUE11);
    CreateShotA(8, 0, 0, 20);
    SetShotDataA(8, 0, 1, -30, 0, 0, 1, BLUE11);
    AddShot(i*6+60, 5, 6, 0);
    AddShot(i*6+61, 5, 7, 0);
    AddShot(i*6+61, 5, 8, 0);
}

FireShot(5);
}
;
count=0
}
count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}


If you notice, I am trying to make a spellcard at least similar to Letty Whiterock's second spellcard of PCB. She creates five curved lasers. However, every one of the AddShot bullets in its respective I.D. only go in one direction. I am not quite sure how to make this easy to explain, but I would like each bullet to get the angle of its respective laser, not just the single core point.

Is it possible to do this with only one laser looped five times, or do I have to create separate lasers and bullets to make it work like Letty's? I want to keep the code as simple as possible.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on May 05, 2009, 10:26:48 PM
I've got a question.


1) Currently, I am messing with the curve laser function (CreateLaserC/SetLaserDataC). I place an AddShot (CreateShotA) to the lasers.

However, I add the bullets to the lasers, but every single bullet added to a laser goes in one direction (i.e. each curved laser goes in different directions, but every other bullet flies in the direction of, for example, 0 degrees). In addition, I am only looping one laser to add each of the bullets (one laser is looped five times in equal distances apart, the AddShot bullets are also looped to the one laser).

Here is the code I am trying to work with.

Code: [Select]
#TouhouDanmakufu
#Title[Winter Sign "Flower Wither Away"]
#Text[Test script]
#Image[.\img\Scarletsign.png]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_remilia.png";

let count = 0;
let a = 72;

@Initialize {
SetLife(2500);
SetTimer(60);
SetScore(10000000);

SetMovePosition02(225, 120, 60);
CutIn(YOUMU, "Winter Sign "\""Flower Wither Away"\", "", 0, 0, 0, 0);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 128, 128);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 90){
PlaySE("lib\THCCL\SE\lazer00.wav");
loop(5){
CreateLaserC(1, GetX, GetY, 10, 30, WHITE01, 0);
SetLaserDataC(1, 0, 5, a, 4, 0, 3);
SetLaserDataC(1, 50, NULL, NULL, 5, -0.05, 2);
SetLaserDataC(1, 90, NULL, NULL, 0, 0.05, 5);
a += 360/5;

ascent(i in 1..900){
    CreateShotA(2, 0, 0, 20);
    SetShotDataA(2, 0, 1, 30, 0, 0, 1, BLUE11);
    CreateShotA(3, 0, 0, 20);
    SetShotDataA(3, 0, 1, 180, 0, 0, 1, BLUE11);
    CreateShotA(4, 0, 0, 20);
    SetShotDataA(4, 0, 1, -30, 0, 0, 1, BLUE11);
    AddShot(i*6+60, 1, 2, 0);
    AddShot(i*6+61, 1, 3, 0);
    AddShot(i*6+61, 1, 4, 0);
}

FireShot(1);
}
}

if(count == 210){
PlaySE("lib\THCCL\SE\lazer00.wav");
loop(5){
CreateLaserC(5, GetX, GetY, 10, 30, WHITE01, 0);
SetLaserDataC(5, 0, 5, a, -4, 0, 3);
SetLaserDataC(5, 50, NULL, NULL, -5, -0.05, 2);
SetLaserDataC(5, 90, NULL, NULL, 0, 0.05, 5);
a += 360/5;

ascent(i in 1..900){
    CreateShotA(6, 0, 0, 20);
    SetShotDataA(6, 0, 1, 30, 0, 0, 1, BLUE11);
    CreateShotA(7, 0, 0, 20);
    SetShotDataA(7, 0, 1, 180, 0, 0, 1, BLUE11);
    CreateShotA(8, 0, 0, 20);
    SetShotDataA(8, 0, 1, -30, 0, 0, 1, BLUE11);
    AddShot(i*6+60, 5, 6, 0);
    AddShot(i*6+61, 5, 7, 0);
    AddShot(i*6+61, 5, 8, 0);
}

FireShot(5);
}
;
count=0
}
count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}


If you notice, I am trying to make a spellcard at least similar to Letty Whiterock's second spellcard of PCB. She creates five curved lasers. However, every one of the AddShot bullets in its respective I.D. only go in one direction. I am not quite sure how to make this easy to explain, but I would like each bullet to get the angle of its respective laser, not just the single core point.

Is it possible to do this with only one laser looped five times, or do I have to create separate lasers and bullets to make it work like Letty's? I want to keep the code as simple as possible.

Unfortunately, I don't think there's any way to track the angle of LaserC. Let me know if I'm wrong. You might have to use Object Lasers in order to be able to track the angle of it, and then fire the shots relative to that (or something along those lines..) .

I have another question. How do you make bullet patterns similar to Alice's PCB noncards?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 05, 2009, 10:41:30 PM
Haven't the slightest idea what to do about those curved lasers, don't mess with them myself. Sorry.

In reference to your question Darkblizer, which patterns are we looking at specifically? Her third one looks probably the hardest to code, but the rest of them shouldn't be too hard to throw together, relatively speaking. Mind telling us which one you're looking at?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on May 05, 2009, 11:43:40 PM
I was talking about her first and fourth noncard.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 06, 2009, 12:17:37 AM
Hmm, I was gonna just recreate them, but the values are a bit odd and I don't want to spend much time on this, so I'll give you the basic outline of what you could go about doing.

For her first non-card you'll want to create shots in a circle around her using [GetX + radius*cos(angle), GetY + radius*sin(angle)]. Angle will be constantly incrementing or decrementing, depending on if you want the bullets to be spawned in a clockwise or counter-clockwise circle, respectively. You'll want to decrease radius everytime you spawn a bullet, to give the same effect observed for her first non-card.

For the actual bullets, it looks like ZUN sets the to have a bit of an angular velocity at first, so we'll be dealing with CreateShotA's. loop(4) (with an angle+=360/4 inside the loop, you know the drill) of them, make sure you don't use the same id twice. Give them a slight negative (for counter clockwise movement) or positive (for clockwise) angular velocity (<1), and spawn four on each point (so, you're looping 4 instances of four different CreateShotA's, so 16 bullets will be spawned). Two of the bullets are just the exact same thing with a larger delay (10 vs 30, maybe), one of the bullets will have a higher velocity and be shot at a different angle (just change the angle parameter to angle + 30, or something), and the other bullet will just be shot at another different angle, with another different velocity. Repeat for all four of the colours, incrementing and decreaming angle and radius as necessary. Be sure to reset your values everytime you start another loop.

Taking a look at her fourth non-card now. Let me know if I wasn't clear.

Alright, for her fourth non-card, you'll want to loop(12) of loop(36) with bullets in them. CreateShotA's again, because of varying movement. The loop(36) is for the ring of bullets, loop(12) is how many rings you'll want to spawn. In the loop(36), you'll want two bullets, your RED01 shot, which will just be fired off, accellerate, then slow down again, and your RED21 shot, which will be fired off, negatively accelerate and continue onward (you'll actually want it to fire off at a negative velocity, so when you accelerate it backwards the bullet graphic will be pointing the correct direction). You'll be incrementing the angle in loop(36) for your ring, and in the loop(12) you'll want to increment velocity so that they'll be at different points (giving that expanding effect).

Instead of incrementing velocity, you could try incrementing delay, but I tried this and it didn't yield the correct results, or anything close really. But you might have more luck. Angular velocity seemed to play a slight role as well, but I couldn't get anything to work that I was happy with. Again, you can try it if you feel like it, but it's a lot of math for a very small effect.

Both of these patterns require you to test and retest the values to mimic them correctly, but since you're just looking for the general pattern, I should hope there wouldn't be a need for me to completely recreate the patterns as a guide. Anyways, I hope this has been helpful to you, and I hope to God I'm talking about the right non-cards. Eeep!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on May 07, 2009, 11:33:27 PM
Okay, I sort of need help figuring out on how to do spellcards where you need to find a gap in the pattern (virtue of wind god is one) to win.

Edit: And those sort of loop thingys Koishi does?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 08, 2009, 12:30:05 AM
Good luck with creating gaps in danmaku, it requires a Godly knowledge of mathematics to calculate, or a Godly amount of luck to pull off. Probably an inordinate amount of both. So I can give one tip that you can try. You'll want to spawn very thick rings of bullets, but with holes in them (this can be done by skipping the spawning stage of bullets but still adding the angle counter +=360/x, so it will make a hole in the ring of bullets. How you go about doing this varies depending on your style, so you can dablle away at it). You can spawn them at random or predetermined angles, but give them an angular velocity. This way it will spin around with seemingly no opens, but if you can math correctly, you can get some openings to appear as they get closer to the bottom of the stage. This is about all I can say, that kind of danmaku is really hard to make unless you know exactly what your doing... Or, y'know, the luck.

Alrighty, loopy things... Spellcard-loopy things or non-spellcard? Erm, closest I can think of is her "Rorschach in Danmaku" or "Genetics of the Subconcious". Honestly? I haven't much of the slightest. All I can say is it requires a knowledge of sin, cos and atan2 that I don't quite possess. So, this is the best I can do for you.

Behold, code!

Code: [Select]
#TouhouDanmakufu
#Title[Rorschach]
#Text[Math]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {

///////////////////////////
///////////////////////////
///////////////////////////
///////////////////////////

let ImgBoss = "script\ExRumia\img\ExRumia.png";

    @Initialize {

    SetLife(5000);
SetScore(5000000);
SetTimer(60);
SetEnemyMarker(true);
    SetDamageRate(100, 10);
    SetInvincibility(150);
SetEnemyMarker(true);
    LoadGraphic(ImgBoss);
CutIn(YOUMU, "Rorschach", "", 0, 0, 0, 0);
    SetMovePosition02(GetCenterX, GetClipMinY + 160, 1);
    SetGraphicRect(30, 30, 100, 100);

lissajous; //attack.

    }

    @MainLoop {
    SetCollisionA(GetX, GetY, 32);
    SetCollisionB(GetX, GetY, 16);

yield;

    }
    @DrawLoop {
SetTexture(ImgBoss);
if(GetSpeedX()==0){SetGraphicRect(64,1,127,64);}
else if(GetSpeedX()>0){SetGraphicRect(192,1,255,64);}
else if(GetSpeedX()<0){SetGraphicRect(128,1,191,64);}
DrawGraphic(GetX, GetY);
    }

    @Finalize {
DeleteGraphic(ImgBoss);
    }

function wait(k){
loop(k){yield;}
}

task lissajous {
let x = GetX;
let y = GetY + 170;
let x1 = 0;
let y1 = 0;
let ex1 = 0;
let ey1 = 0;
let x2 = 0;
let y2 = 0;
let ex2 = 0;
let ey2 = 0;

loop(2) {
let t1 = -90;
let t2 = -90;
loop(2) {
loop(78) {
x1 = x + cos(t1) * 100;
y1 = y + cos(t1 + 30) * 100;
ex1 = x + cos(t2) * 10000;
ey1 = y + sin(t2) * 10000;
x2 = x + cos(t2) * 100;
y2 = y + cos(t2 + 150) * 100;
ex2 = x + cos(t1) * 10000;
ey2 = y + sin(t1) * 10000;

CreateShotA(0, x1, y1, 22);
SetShotDataA(0, 0, 0, atan2(ey1 - y1, ex1 - x1) + 30, 0, 0, 0, BLUE01);
SetShotDataA(0, 56, 0, NULL, 0, 0.1, 2, BLUE04);
FireShot(0);

CreateShotA(0, x2, y2, 22);
SetShotDataA(0, 0, 0, atan2(ey2 - y2, ex2 - x2) - 30, 0, 0, 0, BLUE01);
SetShotDataA(0, 56, 0, NULL, 0, 0.1, 2, BLUE04);
FireShot(0);

t1 -= 4.6;
t2 += 4.6;

wait(1);
}
wait(1);
}
}

loop(2) {
let t1 = -90;
let t2 = -90;
loop(2) {
loop(78) {
x1 = x + cos(t1) * 100;
y1 = y + cos(t1 + 30) * 50;
ex1 = x + cos(t2) * 10000;
ey1 = y + sin(t2) * 10000;
x2 = x + cos(t2) * 100;
y2 = y + cos(t2 + 150) * 50;
ex2 = x + cos(t1) * 10000;
ey2 = y + sin(t1) * 10000;

CreateShotA(0, x1, y1, 22);
SetShotDataA(0, 0, 0, atan2(ey1 - y1, ex1 - x1) + 30, 0, 0, 0, GREEN01);
SetShotDataA(0, 56, 0, NULL, 0, 0.1, 2, GREEN04);
FireShot(0);

CreateShotA(0, x2, y2, 22);
SetShotDataA(0, 0, 0, atan2(ey2 - y2, ex2 - x2) - 30, 0, 0, 0, GREEN01);
SetShotDataA(0, 56, 0, NULL, 0, 0.1, 2, GREEN04);
FireShot(0);

t1 -= 4.6;
t2 += 4.6;

wait(1);
}
wait(1);
}
}
}
}

Run it, study it, become it!

I am too!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on May 08, 2009, 01:48:37 AM
For creating gaps in ring bullet attacks, it is not all that difficult if I am thinking about what you are talking about.

To do this, when you loop the number of bullets and add "[variable] += #/[number of loop]", do not input # as 360. Instead, try for less, such as 340, 300, 180, etc.

If you want the placement of the gap to stay the same, you will need to put "[variable] = [angle]", where angle = the placement of the gap, outside of the loop bracket. This way, the gap will always be opening in one direction.

If you want to randomize the placement of the gap, simply change the # in the first statement to rand(min. angle, max. angle). You can toy with those values as you please.

If you want randomized and MULTIPLE openings, I cannot help you there right now. Sorry.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 08, 2009, 01:55:23 AM
Oh, my bad, I immediately thought he meant multiple meshing gaps, as per Virute of Wind God, didn't even think about just single gaps. Yeah, Frazer's mothod work better than mine anyway, listen to him.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on May 11, 2009, 05:27:01 PM
soooo I'm re-making the scarlet devil mansion's hallways in danmakufu... here's a screenshot:
(http://i40.tinypic.com/r0o1ft.jpg)
it probably doesnt look very good but that's not the problem. the fog does not work the way it should. It would really look nicer if it did. but the results I'm getting are bad. is it danmakufu or just a wrong thing? this is what I use:       SetFog(800, 3200, 150, 50, 50);
what i get with the fog effect:
(http://i43.tinypic.com/2pt54qe.jpg)
note: everything is tiled and drawn somewhere close to 0,0,0.
you might not find the code very useful but anyways: here is it:
Code: [Select]
      rotation++;
      WriteZBuffer(true);
      UseZBuffer(true);
      SetViewTo(200 , 0 , sin(rotation /2) *50  );
      SetViewFrom( 800, 0, 50);
      SetAlpha(255);
      SetTexture(imagefile8);
      SetGraphicAngle(90, 90, 0);
      SetGraphicRect(0 , 0, 67 * 4000, 35 * 4000);
      DrawGraphic3D(rotation, 0, -100);
      SetTexture(imagefile10);
      SetGraphicScale(3,3);
      SetGraphicAngle(90, 90, 0);
      SetRenderState(ADD);
      SetGraphicRect(0 , 0, 66, 57* 10000);
      DrawGraphic3D( rotation, 5 , -50);
      SetAlpha(150);
      SetRenderState(ALPHA);
      SetTexture(imagefile9);
      SetGraphicScale(1,1);
      SetGraphicAngle(90, 90, 90);
      SetGraphicRect(0 , 0, 78 *20000, 43);
      DrawGraphic3D( rotation, 50 , 220);
      DrawGraphic3D( rotation, 50 , -220-35);
      DrawGraphic3D( rotation, 200 , 220);
      DrawGraphic3D( rotation, 200 , -220-35);
      DrawGraphic3D( rotation, 125 , 220);
      DrawGraphic3D( rotation, 125 , -220-35);
      DrawGraphic3D( rotation, 275 , 220);
      DrawGraphic3D( rotation, 275 , -220 -35);
      SetGraphicAngle(90, 90, 270);
      DrawGraphic3D( rotation, 50 , 220 +35);
      DrawGraphic3D( rotation, 50 , -220);
      DrawGraphic3D( rotation, 200 , 220+35);
      DrawGraphic3D( rotation, 200 , -220);
      DrawGraphic3D( rotation, 125 , 220+35);
      DrawGraphic3D( rotation, 125 , -220);
      DrawGraphic3D( rotation, 275 , 220+35);
      DrawGraphic3D( rotation, 275 , -220);
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Aphid on May 11, 2009, 06:41:07 PM
Note: You can't copy this code and expect it to work. You'll have to fill in the variables or have them defined in your script as a result of things (say getplayerX,Y, etc.)

A solution to making multiple gaps into a bullet circle.

Non-Array Variables used:

a, b ==> Angles of our bullet circle (starting and ending, thus a full circle would use 0, 360. It's vital that b > a, and that b, a are within the set (0,360). If not some problems occur with calculating correct lengths and positions. To get these values out of larger angles, use a modulus(360).
n ==> Amount of bullets in the circle.
v ==> Speed of the circle
a ==> Accelleration of the circle.
av ==> Angular velocity of bullets in the circle. Due to the nature of the circle it will always remain as such. A higher angular velocity will slow down the expansion of the circle limiting it to the size of a circle in which a bullet with angular velocity av will rotate, and also of course rotate the gap. Careful use can lead to interesting danmaku.
dur ==> Duration for which the angular velocity applies. I always set one so that there's never stray bullets. Of course there's other removal functions but having the bullets glide off the screen by themselves has preference. As long as v =/= 0 and the amount of bullets isn't too large it's okay to do it this way.
i, j, k, l==> Used to count.
m ==> Amount of gaps.
X, Y ==> Center Position of the ring.

3 arrays:

EXST (length n) ==> Used within the code itself.
l (length m)==> Length of all the gaps (in degrees).
p (length m)==> Starting position of all the gaps (in degrees).

The code consists of three sections. The first section a very basic thing you'll need to make it work in your script, the second section one to determine the EXST from the other variables, and the third one actual bullet fire script. Well let's see:

Code: [Select]

let EXST = [1,1,1,1,(...),1,1,1];
let l = [l1, l2, l3, (...), lm];
let lb = [0, 0, 0, (...), 0];
\\where of course l1, l2, are things I don't know, but you obviously have some things in mind...
let p = [p1, p2, p3, (...), pm];
let pb = [0, 0, 0, (...), 0];
\\ note that the lengths of l, lb, p, and pb are all m.


This should be in @initialize and at least the first line also somewhere in @mainloop. Each loop it resets EXST so that it can be used again. Alternatively, you can place it right after EXST is read out for the last time in a set of bullet rings so you can use it again when it comes around. Of course the other variables also need defining. Anyway, on to the script for EXST. First we create lb out of l, so we converge the angular lengths into lengths specified by the amount of bullets they contain, the same with the positions p.:

Code: [Select]

ascent(i in 1..n+1) {
let lb[i] = round(l[i] / (b - a) * n);
let pb[i] = round((p[i] - a) / (b - a) * n);
                    }

Next, we now determine our EXST, or 'EXIST'-variable, the one that determines which bullets should exist and which don't. By default, all exist (equal to '1'). And a diffrent value is there for when they don't exist, say '0', to keep it simple. In fact EXST can also be done as a boolean array, an array of true/false. More like a matter of personal preference here.

Code: [Select]

ascent(i in 1..n+1) {
ascent(j in 0..lb[i]) {
let EXST[pb[i] + j] = 0;
}
}

The rest should be quite easy. Now we just make our bullet loop, and add EXST as a conditional for it;

Code: [Select]

ascent(i in 1..n+1) {
if(EXST[i] = 1) then {
CreateShotA(1, X, Y, 0);
SetShotDataA(1, 0, v, a + (i / n)(b-a), av, a, 20, RED01);
SetShotDataA(1, dur, NULL, NULL, 0, 0, 20, RED01);
FireShot(1);
}
else {

// Insert here what you would like to happen with the bullets that are in the gaps. You might want them to disappear after some time, or have a diffrent color and a diffrent (angular) velocity (also causes gaps but obstructs elsewhere too).

}


And there we have it, multiple gaps.
Now it's my turn for a question *gulp*.

Code: [Select]
ascent(i in 0..36)
{
if(f == 7860 + 60 * i)
{

CreateShotA(2, 224, 30, 0);
SetShotDataA(2, 0, 3.1415 * 210 / 52.5, 0, 180 / 52.5, 0, 20, RED03);
SetShotDataA(2, 60, NULL, NULL, 0, 0, 20, RED03);
ascent(k in 0..3) {
CreateShotA(3, 0, 0, 0);
let Rthree =  ((-GetPlayerX + GetCenterX + 210 * cos(90 - 180 / 3.5 * (k + 1)))^2 + (-GetPlayerY + GetCenterY - 210 * sin(90 - 180 / 3.5 * (k + 1)))^2)^0.5;
let angthree = 180 + atan2((-GetPlayerY + GetCenterY - 210 * sin(90 - 180 / 3.5 * (k + 1))),(-GetPlayerX + GetCenterX + 210 * cos(90 - 180 / 3.5 * (k + 1))));
SetShotDataA(3, 0, Rthree / 60, angthree, 0, 0, 20, RED02);
AddShot(15 * k + 15, 2, 3, 0);
}
FireShot(2);

CreateShotA(2, 224, 30, 180);
SetShotDataA(2, 0, 3.1415 * 210 / 52.5, 180, -180 / 52.5, 0, 20, RED03);
SetShotDataA(2, 60, NULL, NULL, 0, 0, 20, RED03);
ascent(k in 0..3) {
CreateShotA(3, 0, 0, 0);
let Rthree =  ((-GetPlayerX + GetCenterX + 210 * cos(90 + 180 / 3.5 * (k + 1)))^2 + (-GetPlayerY + GetCenterY - 210 * sin(90 + 180 / 3.5 * (k + 1)))^2)^0.5;
let angthree = 180 + atan2((-GetPlayerY + GetCenterY - 210 * sin(90 + 180 / 3.5 * (k + 1))),(-GetPlayerX + GetCenterX + 210 * cos(90 + 180 / 3.5 * (k + 1))));
SetShotDataA(3, 0, Rthree / 60, angthree, 0, 0, 20, RED02);
AddShot(15 * k + 15, 2, 3, 0);
}
FireShot(2);

ascent(k in 0..120) {
CreateShotA(1, GetCenterX, GetCenterY, 0);
SetShotDataA(1, 0, 0.6, 2 * f + 2 * k + atan((GetPlayerY - GetCenterY) / (GetPlayerX - GetCenterX)) , 0, 0, 10, BLUE11);
FireShot(1);
}
ascent(k in 0..24) {
ascent(j in 0..3) {
CreateShotA(3 + j, GetCenterX, GetCenterY, 15 * j + 15);
SetShotDataA(3 + j, 0, 0.6, 2.5 + 10 * j + 15 * k + atan2((GetPlayerY - GetCenterY),(GetPlayerX - GetCenterX)) , 0, 0, 10, RED11);
FireShot(3 + j);
}
}
}
}

Note that 'f' is my frame counter. The framework is for a recurring event every 1 second, obviously. It spawns a ring of bullets, then shoots three large bullets towards the player, in a fashion of a 4/4 music measure, (i.e. Tik-tak-tak-tak-repeat). Now that's fine and all, but I want something way more complicated than this. You see, I want to have the blue bullets, the small ones where there is a ring of 120 of, to be a ring of 180, and that they change behaviour (they're getting their velocities & accellerations reversed) when they are hit by one of the large bullets. To do that both bullet types will need to be object bullets. However it's kind of obvious I cant just make some 80000ish object bullets and use the one function that checks whether or not objects have the same location (forgot the name), since uh... that'd need to be called way too many times (79999 + 79998 + (...) + 1 = approx. 80000 * 40000 = 32000000000, way too much.). Not to mention because of the peculiar ways in which danmakufu treats arrays, how am I supposed to make the double array of objects in the first place?

Question:

a: How do I rewrite this as an object bullet function?
b: How do I then change the behavior of the blue bullets as indicated?

My thought was to again use an array like I did with solving the previous example, but a 2D-one, a matrix as it were. Each frame the matrix would be set to '0', then all positions of all object bullets would be recorded and added in the matrix. So a blue bullet would add '1' to all locations where it is, say if it'd be a square of 3x3 pixels it'd add 9 1's somewhere in the matrix. And then the same is done for the red bullets. After that we'd ascent to the size of the matrix (which isn't too large), and check for any 2's. If so we'd check if any blue bullet matches a '2'-s position and if it does remove it, and add in a new bullet, a red one with reversed directions, etc.

But uhm... how do I do that?    ::)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 12, 2009, 02:37:14 AM
Quote
it probably doesnt look very good but that's not the problem. the fog does not work the way it should. It would really look nicer if it did. but the results I'm getting are bad. is it danmakufu or just a wrong thing? this is what I use:       SetFog(800, 3200, 150, 50, 50);

I think your numbers are too small and too big, respectively. Otherwise you're using it right. Try something like 1000,1500 for distances?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on May 12, 2009, 04:23:29 PM
too bad, it doesn't work. the result given is similar to the second picture seen in my prevorious post.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 12, 2009, 04:33:44 PM
Did you rip the images from the game...?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 12, 2009, 10:57:30 PM
OH, now I remember. I've had this problem too, I just forgot what the solution was.

Your GraphicRects are way too huge, try to keep them under 2000 pixels or so and keep your map on a tight loop. It shouldn't need to be very big for EoSD style SDM. For some reason fog gets borked on extremely large polygons.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 12, 2009, 11:04:05 PM
(http://img404.imageshack.us/img404/50/stg5bg.png)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 13, 2009, 03:24:28 AM
Sorry to make it look like we're ignoring you for so long Aphid, but I didn't have much time as of late to really ponder about your question. So let me get this straight, since I can't just directly copy your code to see what you're doing:

You want to spawn ~3 large object bullets aimed towards the player. You also want to spawn a massive ring of 180 (!!) bullets, that when they hit the big bullets, will change colour and reverse direction. Correct?

Do you mind explaining the massive distance ([x^2 + y^2]^0.5) and angle (atan2[y2 - y1, x2 - x1]) functions you've developed here, and are they really important to your object code? I might as well note as well: if you want anything to accelerate, your object code is going to look awfully funny, to say the least.

As far as I know, getting collision detection of objects isn't difficult, but I don't know it off the top of my head. I'll look around for you, but essentially the code is going to play out something like this for the small bullets:

"If(colliding with big bullet){
  Obj_SetSpeed(obj, -velocity);
  ObjShot_SetGraphic(obj, RED12 or whatever);
}"

If you want it to only ever change graphic and velocity once, you could impliment a counter system that counts up when colliding, so if it goes above zero you stop changing the object's properties.

Anyways, I'll think about this more after you clarify what you're looking for. I'm pretty tired at the moment, I'll admit, so my understanding of your question could be inebriated. My apologies. I am curious about your matrix system, I have to say, though it seems needlessly complex for the effect I think you're looking for.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on May 16, 2009, 10:47:37 PM
Me again.

This question has to do with Object Shot Bullets.

Does anyone know how to make the individual object bullets in an OBJ_SHOT script fire towards the player?

Think about the SetShotDirectionType(PLAYER) command, where 0 is equal to the player's angle. However, SetShotDirectionType(PLAYER) is completely nullified for some reason. GetAngleToPlayer does not work in my script's case, either.

Code: [Select]
#TouhouDanmakufu
#Title[Object Homing]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_yukari.png";

let count = 0;
let a=10;
let num=2;
let speed=3;





task Bounce(v, angle) {
     let obj=Obj_Create(OBJ_SHOT);
     let counter=0;

     Obj_SetPosition(obj, GetX, GetY);
     Obj_SetAngle(obj, angle);
     Obj_SetSpeed(obj, v);
     ObjShot_SetGraphic(obj, RED11);
     ObjShot_SetDelay(obj, 0);
     ObjShot_SetBombResist(obj, true);
     Obj_SetCollisionToObject(obj, true);


     while(Obj_BeDeleted(obj)==false){

           if(counter<=0){
           if(Obj_GetX(obj)<GetClipMinX) {

                Obj_SetAngle(obj, 0);
                Obj_SetX(obj, Obj_GetX(obj) + 0.1);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
                counter++;
           }
           }

           if(counter<=0){
           if(Obj_GetX(obj)>GetClipMaxX) {

                Obj_SetAngle(obj, 0);
                Obj_SetX(obj, Obj_GetX(obj) - 0.1);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
                counter++;
           }
           }

           if(counter<=0){
           if(Obj_GetY(obj)<GetClipMinY) {

                Obj_SetAngle(obj, 0) ;
                Obj_SetY(obj, Obj_GetY(obj) + 0.1);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
                counter++;
           }
           }

           if(num == 56){
           DeleteEnemyShotToItem(ALL);
           }

           if(num == 60){
           ObjShot_SetGraphic(obj, RED01);
           }

       yield;
}
}







@Initialize {
SetLife(6250);
SetTimer(60);
SetScore(10000000);

SetEnemyMarker(true);

SetMovePosition02(225, 120, 60);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 128, 128);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);
yield;

if(count == 45) {
       PlaySE("script\Remilia Spell Cards\sfx\shot4.wav");
       SetMovePositionRandom01(50,20,5,GetClipMinX()+100,30,GetClipMaxX()-100,100);
loop(num){
Bounce(speed, a);

a += 360/num;
}


if(num < 60){
num += 2;
}

if(num >= 60){
num += 0;
}


if(speed > 1){
speed -= 0.05;
}

if(speed <= 1){
speed += 0;
}


count=0;
}
count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}

See, I want the object bullets, when they reflect off of the top and side walls, to angle towards the player (think of Kaguya's Tree-Ocean of Hourai (Last Word) and Hourai Jewel [lesser version but similar, in the main game] spell cards of IN). How do I make that happen?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 16, 2009, 11:03:52 PM
First of all, does it reflect the bullets right now to fire horizontally? If so,...

Once the bullet hits the wall, create two new variables that equal Obj_GetX(obj) and Obj_GetY(obj). Then to get the angle,

atan2(varY - GetPlayerY, varX - GetPlayerX)

This arctan function will get the tangential angle based on the horizontal and vertical distance separating the location and the player. It's just a more complicated GetAngleToPlayer. Although I'm not sure why it wouldn't be working...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 16, 2009, 11:12:05 PM
atan2(GetPlayerY - Obj_GetY(obj),GetPlayerX - Obj_GetX(obj));

The arctangent of y/x (atan2) will get the angle from any point to any point. The formula is:
atan2(DestinationY - OriginY, DestinationX - OriginX);

To Drake, you don't need to set them as variables. Getting the angle the moment the bullet hits the wall should be fine.

So:

Code: [Select]
if(Obj_GetY<GetClipMinY){
  Obj_SetAngle(obj, atan2(GetPlayerY - Obj_GetY(obj), GetPlayerX - Obj_GetX(obj));
  PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
  counter++;
}

Etc.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on May 16, 2009, 11:47:31 PM
Huh. I guess I used the atan function wrong (I did try it, but I put it in the wrong area).

Thank you.


Also, one other thing: How can I shoot a ring of bullets that are set in a random position while still maintaining the ring (Flandre's last spell card)?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 17, 2009, 12:25:17 AM
Set your random origin as a variable that you can call upon in your CreateShot function in the same frame. Like this:

Code: [Select]
if(frame==120){
 let x = rand(0, 448);
 let y = rand(0, 480);
 loop(60){
  CreateShot01(x, y, 3, angle, BLUE12, 10);
  angle+=360/60;
 }
 frame = 0;
}

This way you can call upon the random origin you've created for the bullet ring.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on May 23, 2009, 07:57:24 PM
new question

what are the names of the get spellcard sound and the spellcard start sound? I need to know so I can replace them with
something else.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 23, 2009, 08:12:37 PM
Sounds that you can change by filename are

sePlayerShot01.wav   
seGraze.wav   
sePlayerCollision.wav (?)
sePlayerSpellCard.wav (?)
se1UP.wav   
seScore.wav   
seBomb_ReimuA.wav   
seExplode01.wav   
seBomb_ReimuB.wav
seUseSpellCard.wav (?)
seGetSpellCardBonus.wav (?)
seEnemyExplode01.wav   
seSuperNaturalBorder1.wav   
seSuperNaturalBorder2.wav

and

STG_Player01.png
STG_Player11.png
CutIn_PlayerChar01.png
CutIn_PlayerChar11.png
Select_Player01.png
Select_Player11.png
STG_Frame.png
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on May 23, 2009, 08:20:24 PM
Okay, thanks

Now I have two more questions. How do you
make a title screen, and how do you make something carry over
from game sessions? (Like say you unlocked Extra and quit the game, when you started
it up again Extra would still be there)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 23, 2009, 10:35:57 PM
God don't even start that what are you thinking.


Uh, am I able to define a bullet's collision detection without making a bullet script?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on May 23, 2009, 10:41:22 PM
How about creating an object bullet and then using Obj_SetCollisionToPlayer and Obj_SetCollisionToObject?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on May 23, 2009, 11:06:56 PM
God don't even start that what are you thinking.


Uh, am I able to define a bullet's collision detection without making a bullet script?


If you are looking for normal bullets, sorry, I don't believe there is a command. Not that I remember having seen, anyway.

Obj-SetCollisionto(Player/Object) just does it for object bullets.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 23, 2009, 11:07:21 PM
Oh, sorry, I meant define the size of the hitbox.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 23, 2009, 11:13:00 PM
Not for the default bullets. The hitbox is defined by how large the image is, and is scaled appropriately. So if you want the hitbox to fill the image, increase the black area surrounding the image so that the hitbox is larger. If you want it smaller, cut off as much black outline as possible. So no, you aren't able to define a hitbox unless you've created your own bullet script.

That said, you can dick around with the shot replace script until you get what your looking for. Good luck, in any case.

Now I have two more questions. How do you
make a title screen, and how do you make something carry over
from game sessions? (Like say you unlocked Extra and quit the game, when you started
it up again Extra would still be there)

[walloftext]
For the title screen, you'll have to change STG_Frame.png to be the outside of your game window as it would be if it was on the title screen. Then you draw an image overtop of everything in the game window that meshes with the image you've defined for STG_Frame.png, then draw text that changes whenever you change KEYSTATE (up and down, then moves onto new directives when you hit the shot button). Make sure everything is drawn above the player character, or have the player character forced off the screen with SetPlayerX(1000) or something. Depending on which combination of buttons the player clicks, you then run scripts accordingly. So you could have a certain variable set whenever "Start Game" is highlighted, so when you press the shot button is will start loading your game script. It's an absolutely INTENSE amount of coding for such a useless effect, seeing as it drops most people's FPS greatly (Fantom Fantasm, check the spellcard history screen. What's your FPS? Mine is like 42 and I've got a dual core with 4GB of RAM). Now that doesn't really matter, but seriously, why even bother with a title screen? It's nice, but it takes years to code. Not worth it at all, don't try it.
[/walloftext]


As for your second question, I've no idea. As far as I know, SetCommonData is only active for the duration of the game script, so I really have no idea how people accomplished this.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 24, 2009, 02:11:32 AM
Quote
As for your second question, I've no idea. As far as I know, SetCommonData is only active for the duration of the game script, so I really have no idea how people accomplished this.

There's a SaveCommonData function that will save all the common data you have set for a given script.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 24, 2009, 02:13:46 AM
....Well there you go.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 24, 2009, 08:16:30 PM
Oddly I'm having trouble with a rather simple issue. What's a good way to fire bullets in a smooth oval?

I figured I would break it into four 90 degree segments with steadily increasing speed towards the sides, but a linear formula creates a sort of dent in it, like so:

(http://img505.imageshack.us/img505/9646/badovalh.png)

Code: [Select]
PlaySE(GetCurrentScriptDirectory~"SFX\BulletWave.wav");
i=4;shotshift=1;
CreateShot01(GetX,GetY,1.5,GetAngleToPlayer,YELLOW21,0);
CreateShot01(GetX,GetY,1.5,GetAngleToPlayer-180,YELLOW21,0);
while(i<90){
  CreateShot01(GetX,GetY,1.5+(shotshift/10),GetAngleToPlayer-i,YELLOW21,0);
  CreateShot01(GetX,GetY,1.5+(shotshift/10),GetAngleToPlayer+i,YELLOW21,0);
  CreateShot01(GetX,GetY,1.5+(shotshift/10),180+GetAngleToPlayer-i,YELLOW21,0);
  CreateShot01(GetX,GetY,1.5+(shotshift/10),180+GetAngleToPlayer+i,YELLOW21,0);
  i+=shotshift;
  shotshift++;
}

Any ideas for a formula? (Also, if you're wondering, the bullets are intended to be more compressed towards the short end of the oval)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 24, 2009, 08:51:33 PM
Have two different radial values for your circle formula.

(http://i641.photobucket.com/albums/uu134/Nautth/szertxghck.jpg)

This code will spawn bullets along the oval defined.

Hope I'm understanding your question correctly....
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on May 24, 2009, 09:15:44 PM
Oddly I'm having trouble with a rather simple issue. What's a good way to fire bullets in a smooth oval?

I figured I would break it into four 90 degree segments with steadily increasing speed towards the sides, but a linear formula creates a sort of dent in it, like so:

(http://img505.imageshack.us/img505/9646/badovalh.png)

Code: [Select]
PlaySE(GetCurrentScriptDirectory~"SFX\BulletWave.wav");
i=4;shotshift=1;
CreateShot01(GetX,GetY,1.5,GetAngleToPlayer,YELLOW21,0);
CreateShot01(GetX,GetY,1.5,GetAngleToPlayer-180,YELLOW21,0);
while(i<90){
  CreateShot01(GetX,GetY,1.5+(shotshift/10),GetAngleToPlayer-i,YELLOW21,0);
  CreateShot01(GetX,GetY,1.5+(shotshift/10),GetAngleToPlayer+i,YELLOW21,0);
  CreateShot01(GetX,GetY,1.5+(shotshift/10),180+GetAngleToPlayer-i,YELLOW21,0);
  CreateShot01(GetX,GetY,1.5+(shotshift/10),180+GetAngleToPlayer+i,YELLOW21,0);
  i+=shotshift;
  shotshift++;
}

Any ideas for a formula? (Also, if you're wondering, the bullets are intended to be more compressed towards the short end of the oval)

Well, you could always make a variation of the Rosarch in Danmaku script Naut posted somewhere in page 1..
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 24, 2009, 09:33:08 PM
Pretty much what Naut said, anything with a circle you're going to have to use trig.

Squares, however...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 24, 2009, 09:54:21 PM
Well that's fine for spawning an oval, but I was looking for a way to spawn them all from the same origin point, i.e. the bullets make an oval due to flying at different speeds.

Quote
Squares, however...

I am intrigued by the idea of shot squares.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 24, 2009, 10:14:08 PM
Use a CreateShot11, then. You have the bullets spawn from the same point, with x velocity based on cos(angle) and y velocity based on sin(angle). I'm too lazy to make an example, though.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 24, 2009, 10:19:58 PM
Oh right, I forgot about that function. Yeah I should be able to figure it out from there.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 24, 2009, 10:25:17 PM
Oh crap I can probably make square patterns with that too

ALL HAIL ME
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 25, 2009, 01:56:38 AM
(http://i641.photobucket.com/albums/uu134/Nautth/Squares.jpg)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 25, 2009, 02:49:49 AM
Frick yeah

Looks like it would suit Reimu well? Someone go make a Reimu boss :V
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on May 25, 2009, 03:31:10 AM
I have got another question.

Is it possible to use AddShot with an object bullet? I am trying to recreate basically the first wave of bullets in Remilia's Red Magic attack (EoSD, last spell on Normal difficulty). I ran into a problem:

Code: [Select]
#TouhouDanmakufu
#Title[Red Magic]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_yukari.png";

let count = 1140;
let a=0;





task Bounce(x, y, v, angle) {
     let obj=Obj_Create(OBJ_SHOT);

     Obj_SetPosition(obj, x, y);
     Obj_SetAngle(obj, angle);
     Obj_SetSpeed(obj, v);
     ObjShot_SetGraphic(obj, RED03);
     ObjShot_SetDelay(obj, 0);
     ObjShot_SetBombResist(obj, true);
     Obj_SetCollisionToObject(obj, true);

     while(Obj_BeDeleted(obj)==false){

           if(Obj_GetX(obj)<GetClipMinX) {
                Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) ) ;
                Obj_SetX(obj, Obj_GetX(obj) + 0.1);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
           }

           if(Obj_GetX(obj)>GetClipMaxX) {
                Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) ) ;
                Obj_SetX(obj, Obj_GetX(obj) - 0.1);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
           }

           if(Obj_GetY(obj)<GetClipMinY) {
                Obj_SetAngle(obj, 0 - Obj_GetAngle(obj) ) ;
                Obj_SetY(obj, Obj_GetY(obj) + 0.1);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
           }

       yield;
}
}







@Initialize {
SetLife(2500);
SetTimer(60);
SetScore(10000000);

SetEnemyMarker(true);

SetMovePosition02(225, 120, 60);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 128, 128);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);
yield;

if(count == 1200) {
                PlaySE("script\Remilia Spell Cards\sfx\shot4.wav");

loop(8){
Bounce(GetX, GetY, 3, a);

ascent(i in 1..500){
    CreateShotA(1, 0, 0, 30);
    SetShotDataA(1, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);
    AddShot(i*15+0, obj, 1, 0);
}

a += 360/8;
}

count=0
}

count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}


Code: [Select]
AddShot(i*15+0, obj, 1, 0);

This is the problem being read. It refers to obj as the source of the error.

Is there a such way to use AddShot with object bullets properly? Do I have to use another object bullet? I hope not.

Speaking of which, about the bullets in AddShot... Is it possible with CreateShotA bullets to change every single one of them that are created by other bullets at once with SetShotDataA, as in Remilia's spell cards, or does that have to do with more object bullets?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Delpolo on May 25, 2009, 03:33:57 AM
My first post at these forums, and I need to know whether it's possible to make a square hitbox for an Object Bullet. I want to make a Tetris-like survival spell, but then the player could just hide in the safe corners between bullets. (At first, I thought it was something like SetCollisionA, like SetCollisionB, but then I realised that the B stands for Bullet, and not 2nd.)

Also, is changing the bomb graphic for the bomb count possible, like it's possible for the life graphic?

Last thing, someone did tests on the REIMU, MARISA and Sakuya players to check their damage rate, but did they also test Rumia?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 25, 2009, 04:01:56 AM
Quote
My first post at these forums, and I need to know whether it's possible to make a square hitbox for an Object Bullet.

It's possible but you're going to need to do manual hit detection. That is, since it's already an object bullet, you can have it check if, say, GetPlayerX and GetPlayerY are within certain coordinates and kill the player if they are. All built-in hit hitbox functions are round.

Quote
Also, is changing the bomb graphic for the bomb count possible, like it's possible for the life graphic?

No, which I find a bit odd. It probably can be changed, or at least replaced with a different default graphic, but there's no documented function.

Quote
Last thing, someone did tests on the REIMU, MARISA and Sakuya players to check their damage rate, but did they also test Rumia?

Lemme pull the data up for you.
Speed (unfocused/focused): 4/1.6
Hitbox size: 1
Unfocused shot (close/near): ~144/165
Focused shot: ~238
Unfocused bomb (close/near): ~0/800
Focused bomb: ~2200

Her unfocused stuff is pretty crappy, but her focused stuff is pretty good.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 25, 2009, 04:17:48 AM
I have got another question.

Is it possible to use AddShot with an object bullet?

No. AddShot only works on CreateShotA's And CreateLaserABC's. To spawn a bullet from an object bullet, you just spawn any bullet on the object bullet's coordinates. like this:

CreateShot01(Obj_GetX(obj), Obj_GetY(obj), ...);

To have it keep spawning bullets every fifteen frames, as per your AddShot code (by the way, ascent i in 1..500? Holy shit that is a lot of bullets to process on one frame... Eight times!), you'll want to use the modulus function (%15) and just set a frame counter to increment in the object bullet's while(){} code tree.

Anyways, here's the fixed code. Things I changed:


Code: [Select]
#TouhouDanmakufu
#Title[Red Magic]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_yukari.png";

let count = 1140;
let a=0;





task Bounce(x, y, v, angle) {
     let obj=Obj_Create(OBJ_SHOT);
     let frame = 0;
     Obj_SetPosition(obj, x, y);
     Obj_SetAngle(obj, angle);
     Obj_SetSpeed(obj, v);
     ObjShot_SetGraphic(obj, RED03);
     ObjShot_SetDelay(obj, 0);
     ObjShot_SetBombResist(obj, true);
     Obj_SetCollisionToObject(obj, true);

     while(Obj_BeDeleted(obj)==false){
frame++;
           if(Obj_GetX(obj)<GetClipMinX) {
        let position = GetClipMinX - Obj_GetX(obj);
                Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) ) ;
                Obj_SetX(obj, Obj_GetX(obj) + position);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
           }

           if(Obj_GetX(obj)>GetClipMaxX) {
        let position = GetClipMaxX - Obj_GetX(obj);
                Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) ) ;
                Obj_SetX(obj, Obj_GetX(obj) + position);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
           }

           if(Obj_GetY(obj)<GetClipMinY) {
        let position = GetClipMinY - Obj_GetY(obj);
                Obj_SetAngle(obj, 0 - Obj_GetAngle(obj) ) ;
                Obj_SetY(obj, Obj_GetY(obj) + position);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
           }
if(frame%15==0){
CreateShotA(1, Obj_GetX(obj), Obj_GetY(obj), 30);
SetShotDataA(1, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);
FireShot(1);
}

       yield;
}
}







@Initialize {
SetLife(2500);
SetTimer(60);
SetScore(10000000);

SetEnemyMarker(true);

SetMovePosition02(225, 120, 60);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 128, 128);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);
yield;

if(count == 1200) {
                PlaySE("script\Remilia Spell Cards\sfx\shot4.wav");

loop(8){
Bounce(GetX, GetY, 3, a);
a += 360/8;
}

count=0
}

count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}

Some things to note about your code and why it was running into errors. The reason it said obj was the source of the error is because the variable obj doesn't exist outside of task Bounce (you declared it inside the task, so to Danmakufu, that variable doesn't exist outside of it). To fix this, just declare let obj = NULL at the very start of the script. This way the variable obj can be used throughout the entire script without running into errors. This won't actually fix your problem though, since you can't use AddShot with object bullets, but I thought you should know that.

As I mentioned earlier, your reflection code was incorrect (as in, it won't work properly 100% of the time). The code I included gets the distance that the bullet would have traveled if it actually reflected off of the invisible barrier, then set's it's position accordingly. The code you have will only correct for small speed values, since the bullets will sometimes go 0.1 of a pixel beyond the game window.

Speaking of which, about the bullets in AddShot... Is it possible with CreateShotA bullets to change every single one of them that are created by other bullets at once with SetShotDataA, as in Remilia's spell cards, or does that have to do with more object bullets?

Do you mind rephrasing this? I'm not really sure what you're asking.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on May 25, 2009, 07:32:55 AM
No. AddShot only works on CreateShotA's And CreateLaserABC's. To spawn a bullet from an object bullet, you just spawn any bullet on the object bullet's coordinates. like this:

CreateShot01(Obj_GetX(obj), Obj_GetY(obj), ...);

To have it keep spawning bullets every fifteen frames, as per your AddShot code (by the way, ascent i in 1..500? Holy shit that is a lot of bullets to process on one frame... Eight times!), you'll want to use the modulus function (%15) and just set a frame counter to increment in the object bullet's while(){} code tree.

Anyways, here's the fixed code. Things I changed:

  • Removed the ascent code when you spawn the Bounce bullets, and moved a similar code into task Bounce to spawn RED01's every fifteen frames.
  • Restructured the Bounce task's reflection code to more accurately reflect the bullets. Try to use this formula from now on, it will never fail.

Code: [Select]
#TouhouDanmakufu
#Title[Red Magic]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_yukari.png";

let count = 1140;
let a=0;





task Bounce(x, y, v, angle) {
     let obj=Obj_Create(OBJ_SHOT);
     let frame = 0;
     Obj_SetPosition(obj, x, y);
     Obj_SetAngle(obj, angle);
     Obj_SetSpeed(obj, v);
     ObjShot_SetGraphic(obj, RED03);
     ObjShot_SetDelay(obj, 0);
     ObjShot_SetBombResist(obj, true);
     Obj_SetCollisionToObject(obj, true);

     while(Obj_BeDeleted(obj)==false){
frame++;
           if(Obj_GetX(obj)<GetClipMinX) {
        let position = GetClipMinX - Obj_GetX(obj);
                Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) ) ;
                Obj_SetX(obj, Obj_GetX(obj) + position);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
           }

           if(Obj_GetX(obj)>GetClipMaxX) {
        let position = GetClipMaxX - Obj_GetX(obj);
                Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) ) ;
                Obj_SetX(obj, Obj_GetX(obj) + position);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
           }

           if(Obj_GetY(obj)<GetClipMinY) {
        let position = GetClipMinY - Obj_GetY(obj);
                Obj_SetAngle(obj, 0 - Obj_GetAngle(obj) ) ;
                Obj_SetY(obj, Obj_GetY(obj) + position);
                PlaySE("script\Remilia Spell Cards\sfx\shot3.wav");
           }
if(frame%15==0){
CreateShotA(1, Obj_GetX(obj), Obj_GetY(obj), 30);
SetShotDataA(1, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);
FireShot(1);
}

       yield;
}
}







@Initialize {
SetLife(2500);
SetTimer(60);
SetScore(10000000);

SetEnemyMarker(true);

SetMovePosition02(225, 120, 60);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 128, 128);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);
yield;

if(count == 1200) {
                PlaySE("script\Remilia Spell Cards\sfx\shot4.wav");

loop(8){
Bounce(GetX, GetY, 3, a);
a += 360/8;
}

count=0
}

count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}

Some things to note about your code and why it was running into errors. The reason it said obj was the source of the error is because the variable obj doesn't exist outside of task Bounce (you declared it inside the task, so to Danmakufu, that variable doesn't exist outside of it). To fix this, just declare let obj = NULL at the very start of the script. This way the variable obj can be used throughout the entire script without running into errors. This won't actually fix your problem though, since you can't use AddShot with object bullets, but I thought you should know that.

As I mentioned earlier, your reflection code was incorrect (as in, it won't work properly 100% of the time). The code I included gets the distance that the bullet would have traveled if it actually reflected off of the invisible barrier, then set's it's position accordingly. The code you have will only correct for small speed values, since the bullets will sometimes go 0.1 of a pixel beyond the game window.

Do you mind rephrasing this? I'm not really sure what you're asking.


1. Okay. Thank you very much.

2. Eh, what I was trying to say is that I have a Scarlet Gensokyo replica script, but it doesn't work out like the actual Scarlet Gensokyo as to when the bullets begin to move.

Here is the code:
Code: [Select]
#TouhouDanmakufu
#Title[Scarlet Sign "Scarlet Gensokyo"]
#Text[Test script]
#Image[.\img\Scarletsign.png]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_remilia.png";

let count = 731;
let a=0;
let num=4;
let num2=16;
let num3=12;

@Initialize {
SetLife(6000);
SetDamageRate(100, 0);
SetTimer(120);
SetScore(10000000);
SetInvincibility(300);

SetMovePosition02(225, 120, 60);
CutIn(YOUMU, "Scarlet Sign "\""Scarlet Gensokyo"\", "", 0, 0, 0, 0);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 128, 128);
}

@MainLoop {
SetShotAutoDeleteClip(0, 0, 0, 0);
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 100){
PlaySE("lib\THCCL\SE\kira03.wav");

Concentration01(80);
PlaySE("lib\THCCL\SE\power0.wav");
}

if(count == 180){
SetMovePositionRandom01(50,20,5,GetClipMinX()+100,30,GetClipMaxX()-100,100);
PlaySE("lib\THCCL\SE\kira00.wav");

loop(num2){
CreateShotA(1, GetX, GetY, 0);
SetShotDataA(1, 0, 3, a, 1.5, 0, 5, RED03);
SetShotDataA(1, 60, 3, NULL, 0, 0, 5, RED03);
a += 360/num2;

ascent(i in 1..500){
    CreateShotA(2, 0, 0, 30);
    SetShotDataA(2, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);
    AddShot(i*10+0, 1, 2, 0);
}
FireShot(1);
}
}

if(count == 310){
PlaySE("lib\THCCL\SE\kira03.wav");
}

if(count == 390){
PlaySE("lib\THCCL\SE\kira00.wav");

loop(num2){
CreateShotA(9, GetX, GetY, 0);
SetShotDataA(9, 0, 3, a+135, -1.5, 0, 5, RED03);
SetShotDataA(9, 60, 3, NULL, -0, 0, 5, RED03);
a += 360/num2;

ascent(i in 1..500){
    CreateShotA(10, 0, 0, 30);
    SetShotDataA(10, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);
AddShot(i*10+0, 9, 10, 30);
}
FireShot⑨;
}
}

if(count == 520){
PlaySE("lib\THCCL\SE\kira03.wav");
}

if(count == 600){
SetMovePositionRandom01(100,20,5,GetClipMinX()+100,30,GetClipMaxX()-100,100);
PlaySE("lib\THCCL\SE\kira00.wav");

loop(num2){
CreateShotA(17, GetX, GetY, 0);
SetShotDataA(17, 0, 3, a+75, 1.5, 0, 5, RED03);
SetShotDataA(17, 60, 3, NULL, 0, 0, 5, RED03);
a += 360/num2;

ascent(i in 1..500){
    CreateShotA(18, 0, 0, 30);
    SetShotDataA(18, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);

AddShot(i*10+0, 17, 18, 30);
}
FireShot(17);
}
}

if(count == 730){
PlaySE("lib\THCCL\SE\kira03.wav");
}

if(count == 750){
Concentration01(120);
PlaySE("lib\THCCL\SE\power0.wav");
}

if(count == 870){
PlaySE("lib\THCCL\SE\kira00.wav");

loop(num3){
CreateShotA(33, GetX, GetY, 0);
SetShotDataA(33, 0, 5, a, 0, 0, 5, RED03);
CreateShotA(35, GetX, GetY, 0);
SetShotDataA(35, 8, 5, a+23, 0, 0, 5, RED03);
CreateShotA(37, GetX, GetY, 0);
SetShotDataA(37, 16, 5, a+46, 0, 0, 5, RED03);
CreateShotA(39, GetX, GetY, 0);
SetShotDataA(39, 24, 5, a+69, 0, 0, 5, RED03);
a += 360/num3;

ascent(i in 1..500){
    CreateShotA(34, 0, 0, 30);
    SetShotDataA(34, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);
    CreateShotA(36, 0, 0, 30);
    SetShotDataA(36, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);
    CreateShotA(38, 0, 0, 30);
    SetShotDataA(38, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);
    CreateShotA(40, 0, 0, 30);
    SetShotDataA(40, 100, 0, rand(0, 360), 0, 0.03, 2, RED01);

    AddShot(i*8+0, 33, 34, 30);
    AddShot(i*8+8, 35, 36, 30);
    AddShot(i*8+16, 37, 38, 30);
    AddShot(i*8+24, 39, 40, 30);

}

FireShot(33);
FireShot(35);
FireShot(37);
FireShot(39);
}

;
count=0
}
count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}


Let's take a look at the bullets that are left behind by the RED03's (the AddShot RED01's). It takes each bullet from the time it appears a delay of 100 frames to begin moving. This means that the bullets, in turns, begin to take their effects and move, instead of every one of them instantly accelerating at once. Remilia causes the latter to happen by creating some kind of wave during her fight that turns all of the bullets purple at once and slowly accelerate (this happens with one of her hard and lunatic spell cards [which I believe is the third to last one], Red Magic and Scarlet Gensokyo). What would I do to cause it to happen as Remilia does, instead of using the actual delay part of SetShotDataA?



Also, one other note: in (ascent 1... 500), it appears that this function states, by my witnessing, that this is the maximum number of bullets that can be added. What else does this code represent by increasing and decreasing the numbers?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on May 25, 2009, 09:10:49 PM
Frazer: That's actually simple to do. Make a variable that starts at the value of the frame you want the first bullet to move at. Every time you create a bullet, subtract that value by the same time it takes to create the next one. So:

Code: [Select]
let TimeToMove = 240;
if(frame==0)
{
CreateShotA(shot, GetX, GetY, 10);
SetShotDataA(shot, 0, 0, 0, 0, 0, 0, RED01);
SetShotDataA(shot, TimeToMove, Angle, 0, 0, 0.2, 4, RED01);
FireShot(shot);
shot++;
TimeToMove -= 10;
frame = -10;
}

Something similar to that. You most likely won't do it exactly like that, but I guess it shows what I mean. So, let's look at it...

Every time frame hits 0, the bullet is created, shot is increased so each new shot has its own number, frame is set to -10, meaning it'll take 10 more frames to get it up to 0 again. Because of this, we decrease TimeToMove by 10. However, I'm sure you know to reset the value of TimeToMove eventually, since it'd be bad if the bullet moves at say, -10 frames. XD



Okay, that said, I have a question of my own...

Is there a way to reduce the life of an enemy or boss without directly hitting the original boss enemy itself? Like, say I wanted a boss to have a familiar, but shooting said familiar would harm the boss, though not as much as shooting the boss itself. Know what I'm saying? (I think this happened in Imperishable Night...) Normally, I could just figure out how much damage the familiar is taking and do "SetLife(GetLife() - [value])", but that refills the lifebar, it doesn't visually represent anything related to the original size of the lifebar.

I'm probably wording this badly...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 25, 2009, 09:38:09 PM
Quote
Is there a way to reduce the life of an enemy or boss without directly hitting the original boss enemy itself? Like, say I wanted a boss to have a familiar, but shooting said familiar would harm the boss, though not as much as shooting the boss itself. Know what I'm saying? (I think this happened in Imperishable Night...) Normally, I could just figure out how much damage the familiar is taking and do "SetLife(GetLife() - [value])", but that refills the lifebar, it doesn't visually represent anything related to the original size of the lifebar.

You can put a negative number in AddLife to damage the boss.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 26, 2009, 02:17:05 AM
I'm wondering how Naut got his squares done. I did it this way, and for some reason angle 225 is missing.

Code: [Select]
task square(){     
    let a = 45;
    let xv = NULL;
    let yv = NULL;
    loop(40){
        if (a>=45 && a<135){
            xv = ((a - 90) / -9)/5;
            yv = 5/5;
        }else if(a>=135 && a<225){
            xv = -5/5;
            yv = ((a - 180) / -9)/5;
        }else if(a>=225 && a<315){
            xv = ((a - 270) / -9)/5;
            yv = -5/5;
        }else if(a>=315 && a<405){
            xv = 5/5;
            yv = ((a - 360) / -9)/5;
        }
        CreateShot11(GetEnemyX, GetEnemyY, xv, yv, RED01, 9);
        a += (360/40);
    }
}

The last /5 was just to slow it down and observe.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on May 26, 2009, 02:18:27 AM
Ah, thanks, Stuffman. New question: Is there any way I can stop a user-defined bullet from changing the angle its graphic is put in when it changes the angle it's moving in? Like

< v > ^

It'd spin like that when going at angle 0, but if it were to bounce off a wall...

^ > v <

It'd just flip. I don't want that, I want a bullet that never changes graphical direction based on its direction of movement- is this possible?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 26, 2009, 02:30:34 AM
Use Obj_SetX and Obj_SetY to guide it's movement, instead of the speed functions. it's more difficult, but the bullet's graphic is automatically adjusted for different angles of movement, so you'd have to keep setting it's angle to whatever you want it to be, then guide it's movement each frame. It's not as long and tiring as it sounds; just a bit of trigonometry, but it's still a pain in the ass.

For Drake:

Code: [Select]
#TouhouDanmakufu
#Title[What]
#BackGround[User(.\PIC\black.png, 1, 1)]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {


let ImgBoss = "script/ExRumia/img/ExRumia.png";
let vxa = -3;

    @Initialize {

SetLife(6000);
SetTimer(100);
SetScore(5000000);
MagicCircle(false);
SetDamageRate(100, 20);
SetEnemyMarker(true);
LoadGraphic(ImgBoss);
LoadSE(se1);
SetMovePosition02(GetCenterX, GetCenterY - 100, 1);
squares;

    }

    @MainLoop {
    SetCollisionB(GetX, GetY, 24);
SetShotAutoDeleteClip(64, 400, 64, 64);
yield;
}

    @DrawLoop {
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 64, 64);
DrawGraphic(GetX, GetY);
    }

    @Finalize {
DeleteGraphic(ImgBoss);
DeleteSE(se1);
    }

task squares{
loop(10){yield;}
let vxa = -3;
loop(33){
CreateShotA(0, GetX, GetY, 6);
CreateShotA(1, GetX, GetY, 6);
SetShotDirectionType(PLAYER);
SetShotDataA_XY(0, 0, vxa, 3, 0, 0, 0, 0, RED01);
SetShotDataA_XY(1, 0, vxa, -3, 0, 0, 0, 0, RED01);
vxa+= 3/16;
FireShot(0);
FireShot(1);}
vxa-= 6/16;
loop(31){
CreateShotA(2, GetX, GetY, 6);
CreateShotA(3, GetX, GetY, 6);
SetShotDirectionType(PLAYER);
SetShotDataA_XY(2, 0, 3, vxa, 0, 0, 0, 0, RED01);
SetShotDataA_XY(3, 0, -3, vxa, 0, 0, 0, 0, RED01);
vxa-= 3/16;
FireShot(2);
FireShot(3);
}
squares;
}

}

I like to think I cheated to make the squares, but here is the code you requested none-the-less. Needless CreateShotA's, I know, but I don't have the parameters of most of the shot functions memorized yet.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 26, 2009, 02:51:28 AM
Yeah, that won't quite work for anything else, lol. Oh well, I'll keep trying.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on May 26, 2009, 09:56:47 PM
Frazer: That's actually simple to do. Make a variable that starts at the value of the frame you want the first bullet to move at. Every time you create a bullet, subtract that value by the same time it takes to create the next one. So:

Code: [Select]
let TimeToMove = 240;
if(frame==0)
{
CreateShotA(shot, GetX, GetY, 10);
SetShotDataA(shot, 0, 0, 0, 0, 0, 0, RED01);
SetShotDataA(shot, TimeToMove, Angle, 0, 0, 0.2, 4, RED01);
FireShot(shot);
shot++;
TimeToMove -= 10;
frame = -10;
}

Something similar to that. You most likely won't do it exactly like that, but I guess it shows what I mean. So, let's look at it...

Every time frame hits 0, the bullet is created, shot is increased so each new shot has its own number, frame is set to -10, meaning it'll take 10 more frames to get it up to 0 again. Because of this, we decrease TimeToMove by 10. However, I'm sure you know to reset the value of TimeToMove eventually, since it'd be bad if the bullet moves at say, -10 frames. XD


Okay, but when I am looping the bullet say eight times, how do I make the delay separate for each individual bullet while keeping the delay above 0? When I have {TimeToMove -=  10}, this will stop making the bullets move altogether after the tenth one. With this function I mean using AddShot as well, i.e. Scarlet Gensokyo's case.

Things I can't do for this problem to make it work properly:

1. Leave it alone.
2. Set the delay at a higher point (because I don't want to wait that long for every bullet to act).
3. Make TimeToMove -= a shorter number (because it will still force the bullets to stop moving at a certain point anyway).
4. Create an individual I.D. for each shot (because then things will become horribly cluttered).


Also, still having to do with Remilia's spell cards, is it possible to use just one shot I.D. and make, say:

Code: [Select]
ascent(i in 1..20){
    CreateShotA(2, 0, 0, 30);
    SetShotDataA(2, 100, 0, angle, 0, 0.01, 2, PURPLE01);

    CreateShotA(4, 0, 0, 30);
    SetShotDataA(4, 100, 0, angle2, 0, 0.01, 2, PURPLE01);

    AddShot(i*8+0, 1, 2, 0);
    AddShot(i*8+0, 3, 4, 0);


    angle += 5;
    angle2 += 5;
}


See the [angle += 5;] part? Say I want to use that with only one shot I.D. but I want every one of the bullets in each line to move at a set angle (take a look at Scarlet Gensokyo's second and fourth bullet waves to see what I am trying to specify) instead of carrying [angle +=] to each line of bullets. Is this possible?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 26, 2009, 10:13:59 PM
Make the delay (shot*2)+1 or something. 1-3-5-7-9-11-13-15 should be fine, right?

EDIT: Also I fixed my squares

EDIT:

Code: [Select]
let ba=45;

task lolawesome{     
    let a = ba;
    let xv = NULL;
    let yv = NULL;
    loop(1){yield;}
    loop(40){
        if (a>=ba && a<(ba+90)){
            xv = ((a - 90) / -9)/3;
            yv = 5/3;
        }else if(a>=(ba+90) && a<(ba+180)){
            xv = -5/3;
            yv = ((a - 180) / -9)/3;
        }else if(a>=(ba+180) && a<(ba+270)){
            xv = ((a - 270) / 9)/3;
            yv = -5/3;
        }else if(a>=(ba+270) && a<(ba+360)){
            xv = 5/3;
            yv = ((a - 360) / 9)/3;
        }
        CreateShot11(GetEnemyX, GetEnemyY, xv, yv, RED01, 9);
        a += (360/40);
    }
    ba+=9;
    lolawesome;
}

hahaha cool

EDIT: Is there any way to get an effect like SetShotDirectionType, but indicating which angle falls at 0?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 27, 2009, 12:54:10 AM
Not that I know of offhand, that was my problem as well. I have no real idea how to aim the square in any direction. NuclearCheese does, however, as I can remember something along the lines of "changing the coordinate grid" posted on the old forums. Hopefully he'll bless us with his presence sometime soon~

...~
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on May 27, 2009, 09:47:14 PM
What is the syntax for an XOR statement? I can only find AND and OR statements on thwiki.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on May 27, 2009, 09:58:39 PM
Well, you can always use ( (A and not B) or (B and not A) )...

Code: [Select]
if((A&&!B)||(!A&&B)) { stuff }
...where A and B are the two conditions, of course.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 27, 2009, 10:03:10 PM
I don't think there is any. Just use this.


Code: [Select]
function XOR(x, y, a, b){
    if (x=a){
        if (y=b){
            return false;
        }else{
            return true;
        }
    }else if (y=b){
        return true;
    }else{
        return false;
    }
}

As an example,

Code: [Select]
varx = 1;
vary = 2;
answer1 = 5;
answer2 = 2;

if (XOR(varx, vary, answer1, answer2) == true){
    //do stuff
}

Stuff would be done here.

Code: [Select]
varx = 1;
vary = 2;
answer1 = 1;
answer2 = 2;

if (XOR(varx, vary, answer1, answer2) == true){
    //do stuff
}

Stuff would not be done here.

Code: [Select]
varx = 5;
vary = 4;
answer1 = 1;
answer2 = 2;

if (XOR(varx, vary, answer1, answer2) == true){
    //do stuff
}

Stuff would not be done here either.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on May 27, 2009, 10:29:36 PM
Curiously, I didn't need it in the end. I now have an EPIC coding headache, though... but damn it, this PC animation code WILL BE PERFECT!!!

... need aspirin, brb

This Yuka PC is going to be amazing, I know it... but mark my words, it will be the first and last thing I ever submit on MotK. I cannot see myself continuing to code after all the headaches this has given me.

EDIT: Actually, here's a question for you guys. Aside from Dual Spark, what other bomb should I give Yuka? I was contemplating Reflowering the Gensokyo, but that's so... bland. It's not visually very interesting (I already have a deathbomb for her, and it will easily take a week to finish)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 27, 2009, 11:05:04 PM
Quote
This Yuka PC is going to be amazing, I know it... but mark my words, it will be the first and last thing I ever submit on MotK. I cannot see myself continuing to code after all the headaches this has given me.

It gets easier.

Does Yuka even have named spellcards?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 27, 2009, 11:09:52 PM
Flower Sign "Reflowering of the Gensokyo", Double Spark I guess and Phantasm "Beauty of the Nature".
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 27, 2009, 11:16:47 PM
Make your own.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on May 27, 2009, 11:16:47 PM
That's the trouble, I don't WANT to use 'Reflowering of Gensokyo' because it's ugleah. D= And Phantasm "Beauty of Nature" I might use for the counterbomb, but I have something epic and awesome worked out for it already (that will involve more draw-coding than I'd like).

I'm just tired of trying to think of something, if someone could offer an idea...?

EDIT @Naut: NOOOOES I dun wanna. D; I've already made a counterbomb, I was asking for input...?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on May 27, 2009, 11:25:21 PM
I have got some inspiration for you:

http://www.youtube.com/watch?v=Y_Kvik8OzIs&feature=channel_page (http://www.youtube.com/watch?v=Y_Kvik8OzIs&feature=channel_page)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on May 28, 2009, 12:00:07 AM
Oh, I've seen that already... but that has given me an idea... >=3 Naut, what's the name of the spellcard before the survival one?

Oh, and Naut, there are actually TEN cards in an extra boss fight. Eight kill cards, one survival, and one final card.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 28, 2009, 12:06:54 AM
Perennial Sign "Wilt"
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on May 28, 2009, 03:00:40 AM
How do you do that sort of reverse danmaku? (like as if time was going backwards. Look at Keine's second midboss spellcard for extra and Utsuho's Subterranean Sun to see what I mean
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 28, 2009, 03:22:36 AM
...Create bullets that move inwards and make them disappear once they get to wherever they end up. Just call spawning points where the bullets would normally end up and give it backwards velocty.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on May 28, 2009, 03:25:34 AM
Yeah, but I want to spawn from the edges of the playing field and have it still come back in a circle shape.

Also, how do I add things/change things on the HUD? (Extra point areas) And how do I change the font the game uses?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 28, 2009, 04:11:59 AM
CreateShotA(0, GetX + 300*cos(angle), GetY + 300*sin(angle), 0);
SetShotDataA(0, 0, 3, angle - 180, 0, 0, 0, RED02);
SetShotKillTime(0, 100);
FireShot(0);

The 300 radius is far enough so that all the bullets are off the screen when they spawn. angle should be incremented appropriately for your ring of bullets (+=360/num), and their movement vector should be angle - 180, since you want them to move backwards. The SetShotKillTime is derived from dividing your radius (300) by your bullet speed (3), which is how many frames it will take for the bullets to hit the point (GetX, GetY). To have the bullets not just delete themselves as soon as they're spawned beyond the game window, use the function:
SetShotAutoDeleteClip(200, 200, 200, 200);

Which expands the deletion window 200 pixels in every direction, so that bullets will still be processed outside the game window instead of deleted. Be sure to call this function every frame, like SetCollisionA/B, or it will default to SetShotAutoDeleteClip(64, 64, 64, 64); (can somebody check if you actually need to call it every frame? I'm not so sure, and I haven't the time at the moment).

I haven't the slightest regarding your latter questions, so I won't comment on them and likely confuse you (and myself).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on May 28, 2009, 02:56:31 PM
How does one troubleshoot a player script? DNH just kind of... aborts the script you're trying to play if the player script is faulty, without actually telling you what is wrong. I can't see any reason my player script won't run, other than that I haven't defined the pattern of the player's shots (unnecessary) or what the bombs actually DO (also unnecessary, as I've seen PCs that lack both)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on May 28, 2009, 07:11:16 PM
how can i see if an object laser collides with an object bullet?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on May 28, 2009, 07:53:06 PM
Object collision is checked with:

Code: [Select]
Collision_Obj_Obj(obj1, obj2);
You'll get a true or false value.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 28, 2009, 10:03:30 PM
How does one troubleshoot a player script? DNH just kind of... aborts the script you're trying to play if the player script is faulty, without actually telling you what is wrong. I can't see any reason my player script won't run, other than that I haven't defined the pattern of the player's shots (unnecessary) or what the bombs actually DO (also unnecessary, as I've seen PCs that lack both)

I'm pretty sure it is supposed to give an error box when a player script fails. I would need to see it to know what's wrong.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on May 29, 2009, 02:55:18 PM
I have a question...

I'm new here and I've done some spell cards before. I have used all the functions I used in this spell card before, and they worked correctly, so I'm wondering why whenever I play it, Danmakufu crashes...

Code: [Select]
#TouhouDanmakufu
#Title[Laser Deflectors]
#Text[]
#BackGround[Default]
#PlayLevel[Test]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = 0;
    let miny = GetClipMinY;
    let cx = GetCenterX;
    let imgExRumia="script\img\ExRumia.png";
    let BossCutIn = "player\Rumia\RumiaCutIn.png";
    let LaserA = Obj_Create(OBJ_LASER);
    let LaserB = Obj_Create(OBJ_LASER);

task Bullet(x, y, angle, v) {
      let obj=Obj_Create(OBJ_SHOT);

      Obj_SetPosition(obj, x, y);
      Obj_SetAngle(obj, angle);
      Obj_SetSpeed(obj, v);
      ObjShot_SetGraphic(obj, BLUE21);
      ObjShot_SetDelay  (obj, 0);
      ObjShot_SetBombResist (obj, true);
Obj_SetCollisionToObject(obj, true);

      while(Obj_BeDeleted(obj)==false) {
              Obj_SetAngle(obj, Obj_GetAngle(obj) + 2);

if (Collision_Obj_Obj(obj, LaserA) == true)
{
              Obj_SetAngle(obj, Obj_GetAngle(LaserA)+90);
}
if (Collision_Obj_Obj(obj, LaserB) == true)
{
              Obj_SetAngle(obj, Obj_GetAngle(LaserB)-90);
}
       }
yield;
}

task BulletB(x, y, angleB, v) {
      let obj=Obj_Create(OBJ_SHOT);

      Obj_SetPosition(obj, x, y);
      Obj_SetAngle(obj, angleB);
      Obj_SetSpeed(obj, v);
      ObjShot_SetGraphic(obj, BLUE21);
      ObjShot_SetDelay  (obj, 0);
      ObjShot_SetBombResist (obj, true);
Obj_SetCollisionToObject(obj, true);

      while(Obj_BeDeleted(obj)==false) {
              Obj_SetAngle(obj, Obj_GetAngle(obj) - 2);

if (Collision_Obj_Obj(obj, LaserA) == true)
{
              Obj_SetAngle(obj, Obj_GetAngle(LaserA)+90);
}
if (Collision_Obj_Obj(obj, LaserB) == true)
{
              Obj_SetAngle(obj, Obj_GetAngle(LaserB)-90);
}
       }
yield;
}

task Laser1(x, y, angle) {

Obj_SetPosition(LaserA, x, y);
Obj_SetAngle(LaserA, angle);
ObjShot_SetGraphic(LaserA, BLUE01);
ObjShot_SetDelay(LaserA, 0);
ObjShot_SetBombResist (LaserA, true);
ObjLaser_SetLength(LaserA, 100);
ObjLaser_SetWidth(LaserA, 10);
ObjLaser_SetSource(LaserA, true);
Obj_SetCollisionToObject(LaserA, true);

while(Obj_BeDeleted(LaserA)==false) {
Obj_SetAngle(LaserA, Obj_GetAngle(LaserA) + 2);
}
yield;
}

task Laser2(x, y, angleB) {

Obj_SetPosition(LaserB, x, y);
Obj_SetAngle(LaserB, angleB);
ObjShot_SetGraphic(LaserB, BLUE01);
ObjShot_SetDelay(LaserB, 0);
ObjShot_SetBombResist (LaserB, true);
ObjLaser_SetLength(LaserB, 100);
ObjLaser_SetWidth(LaserB, 10);
ObjLaser_SetSource(LaserB, true);
Obj_SetCollisionToObject(LaserB, true);

while(Obj_BeDeleted(LaserB)==false) {
Obj_SetAngle(LaserB, Obj_GetAngle(LaserB) - 2);
}
yield;
}

    @Initialize {
        SetLife(4000);
SetDamageRate(100,80);
SetTimer(50);
        SetInvincibility(120);
Concentration01(120);
        SetEnemyMarker(true);
        SetScore(1000000);
        SetEffectForZeroLife(120,51,1);
        LoadGraphic(imgExRumia);
        SetGraphicRect(1,1,64,64);
        CutIn(YOUMU, "Mirror Sign Border Trackers", BossCutIn, 0, 0, 200, 600);
SetX(GetCenterX);
SetY(miny+120);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 24);
yield;

function Attack(x, y)
{
ascent (i in 0..20)
{
Bullet(x, y, 5+(i*5), 3);
BulletB(x, y, 175-(i*5), 3);
}
}
function Laser(x, y)
{
Laser1(x, y+150, -90);
Laser2(x, y+150, -90);
}

if (frame == 60)
{
Laser(GetX, GetY);
}
if (frame == 240)
{
Attack(GetX, GetY);
frame = 60;
}
frame++;
}

    @DrawLoop {
SetTexture(imgExRumia);
SetGraphicRect(64,1,127,64);
DrawGraphic(GetX,GetY);
    }

    @Finalize {
loop(8){
CreateItem(ITEM_SCORE,cx+rand(-100,100),rand(20,100));
}
DeleteGraphic(imgExRumia);
    }
}

As you can see, I'm making a spell card where the boss shoots out bullets that spin in a pattern below her and are reflected whenever they hit one of the 2 spinning lasers at the center of the screen. When the spell card only had the bullets it worked, but when I put in the lasers, the game kept on crashing when it reached the part where the lasers are spawned. Can someone help me? Thanks in advance.  :D
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 29, 2009, 03:07:25 PM
You need to take those yields in your tasks and put them inside the while loops, rather than outside.

Whenever Danmakufu freezes like that it's usually because it's stuck in an infinite while loop.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on May 29, 2009, 03:38:55 PM
You need to take those yields in your tasks and put them inside the while loops, rather than outside.

Whenever Danmakufu freezes like that it's usually because it's stuck in an infinite while loop.

Thanks! It works now...  ;D
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on May 30, 2009, 04:12:58 PM
Well, I'll throw in the shot data and all that stuff then post it here. I really don't understand why it refuses to work, though...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 30, 2009, 04:22:44 PM
Go on...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on May 30, 2009, 10:02:43 PM
I have two questions, then I should be able to get back to you with my first boss fight.

1. How do you make bullets move to a position, stop, then after 5 seconds move to another position?

2. How do you make bullets bounce of only the side walls. I'm new to C too, so I don't even know how to make them bounce.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on May 30, 2009, 10:22:29 PM
1.
Depending on what you exactly you want to do, you may either program a bullet with the SetShotDataA funtcion or you'll have to learn object bullets.

2. Needs object bullets. A tutorial on what they are, why they are used and how to make one can be found here (http://www.shrinemaiden.org/forum/index.php?topic=166.msg3549#msg3549). It is even exemplified with the creation of bouncing bullets.  8)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on May 30, 2009, 10:51:06 PM
Code: [Select]
#TouhouDanmakufu
#Title[Black Barrage]
#BackGround[User(.\bg.png, 1, 1)]
#BGM[.\bgm.mp3]
#PlayLevel[Easy]
#Player[REIMU, MARISA]
#ScriptVersion[2]

script_enemy_main {
let cx=GetCenterX();
let cy=GetCenterY();
let pos1 = cx + cx - 1;
    let BossImage = "script\img\olol.gif";
    let frame = 0;
let frame2 = 0;
let frame3 = 0;
let frame4 = 0;
    @Initialize {
        SetLife(3000);
        SetEnemyMarker(true);
SetMovePosition02(cx+0,60,60);
LoadGraphic(BossImage)
    }


    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 100);
if (frame2<20){
Bullet(GetX, GetY, 3, frame+180);
Bullet(GetX, GetY, 3, frame);
}
if (frame3<20){
Bullet(GetX, GetY, 3, frame4+180);
Bullet(GetX, GetY, 3, frame4);
}
if(frame2==30){
Bullet(GetX, GetY, 6, 105);
Bullet(GetX, GetY, 6, 45);
Bullet(GetX, GetY, 6, 75);
Bullet(GetX, GetY, 6, 135);
Bullet(GetX, GetY, 6, 105);
frame2 = 0;
}
if(frame3==30){
frame3 = 0;
}
        frame++;
frame2++;
frame3++;
frame4--;
    }

    @DrawLoop {
SetTexture(BossImage);
DrawGraphic(GetX, GetY);
    }

    @Finalize {
    }

    @BackGround {
    }
}
task Bullet(x, y, v, angle) {
      let obj=Obj_Create(OBJ_SHOT);

      Obj_SetPosition(obj, x, y);
      Obj_SetAngle(obj, angle);
      Obj_SetSpeed(obj, v);
      ObjShot_SetGraphic(obj, RED01);
      ObjShot_SetDelay  (obj, 0);
      ObjShot_SetBombResist (obj, true);

      while(Obj_BeDeleted(obj)==false) {

              if(Obj_GetX(obj)<GetClipMinX) {
                     Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) );
                     Obj_SetX(obj,  Obj_GetX(obj) + 0.1);
              }

              if(Obj_GetX(obj)>GetClipMaxX) {
                     Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) );
                     Obj_SetX(obj,  Obj_GetX(obj) - 0.1);
              }

              yield;
       }
Whenever I try to use that, an error pops up.

(http://i44.tinypic.com/2rgdxn8.png)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on May 30, 2009, 11:11:20 PM
You have put your task otuside the script_enemy_main brackets. Therefore it doesn't exist inside it and danmakufu can't find it, so it raises an error.

You have to put your task after everything else in the script_enemy_main brackets (or before everything else, or between the different @loops, but at the end they they are probably the least confusing) but still inside the main script.


So, the solution is to just move the "}" bracket from after the @Background to after the task.




Hmmm, I'll have to reword the tutorial post. This is the second time someone has assumed "after @Finalize" means "after the closing bracket of script_enemy_main". Is it that misleading?  :-X
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on May 31, 2009, 12:17:32 AM
It didn't work, Iryan.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on May 31, 2009, 12:21:36 AM
You don't have the correct number of ending brackets in the Bullet task. Try adding another } to the end of that part of the code.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on May 31, 2009, 12:31:25 AM
Oh. Indeed, I didn't notice that second mistake, sorry.  :-\

You forgot the closing bracket for your complete task. Because of that, danmakufu raised an error once you had put the task inside script_enemy_main. So, as Onthenet said, adding another closing bracket after your task will negate that error.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on May 31, 2009, 12:47:50 AM
But now the bullets won't bounce. 3:
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 31, 2009, 12:55:01 AM
Put "yield;" inside your @Mainloop, at the end of it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 31, 2009, 02:51:01 AM
How could I make this more awesome?

Code: [Select]
#TouhouDanmakufu
#Title[circles]
#BackGround[User(.\PIC\black.png, 1, 1)]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {

let inv = 2.27;
   
    @Initialize {

   SetLife(2000);
   SetTimer(40);
   SetMovePosition02(GetCenterX, GetCenterY, 20);
   circle;   
     
    }

    @MainLoop {
       SetCollisionB(GetX, GetY, 24);
       yield;
   }

    @DrawLoop {
    }

    @Finalize {
    }

    task circle{
        loop(30){yield;}
        Concentration01(80);
        loop(90){yield;}
        let a = rand(30, 60);
        let acc = 1;
        loop(4){
            CreateShotA(0, (cos(a)*170)+GetX, (sin(a)*170)+GetY, 20);
            SetShotDataA(0, 0, 5, a+(60*inv), inv, 0, 0, WHITE05);
            SetShotKillTime(0,36);
            ascent(i in 1..6){
                CreateShotA(1, 0, 0, 10);
                SetShotDataA(1, 0, 1.5, 0, 0, -0.01, 0.75, WHITE11);
                ascent(j in 1..24){
                    CreateShotA(2, 0, 0, 0);
                    SetShotDataA(2, 0, 1.5, j*15, 0, -0.01, 0.75, WHITE11);
                    AddShot(0, 1, 2, 0);
                }
                AddShot((i*6)-6, 0, 1, 0);
            }
            FireShot(0);
            a+=90;
        }
        inv *= -1;
        loop(170){yield;}
        circle;
    }
   
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 31, 2009, 03:17:28 AM
Make more circles appear more frequently (and make less bullets in the circle to compensate for more being spawned, something like AddShot(i*4)-4, 0, 1, 0); and ascent(j in 1..18) with j*20 as the angular SetShotData parameter -- maybe even less bullets than that). Have the shots keep spawning past the origin, so double it's time (SetShotKillTime(0, 72);) and double the loop (ascent(i in 1..12)). Don't wait 170 frames before making another wave (maybe like... 40), and toss the boss closer to the top of the screen to compensate for more frequent waves (and thus more bullets). Make them a different colour too, white is boring. Rainbow or something. China that shit up.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on May 31, 2009, 04:46:11 AM
It looks kind of messy if you're only looking at the bottom, but eh.

Code: [Select]
#TouhouDanmakufu
#Title[circles]
#BackGround[User(.\PIC\black.png, 1, 1)]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {

let inv = 2.27;
let color = [RED11, ORANGE11, YELLOW11, GREEN11, AQUA11, BLUE11, PURPLE11];
   
    @Initialize {

   SetLife(2000);
   SetTimer(40);
   SetMovePosition02(GetCenterX, GetCenterY-70, 20);
   circle;   
     
    }

    @MainLoop {
       SetCollisionB(GetX, GetY, 24);
       yield;
   }

    @DrawLoop {
    }

    @Finalize {
    }

    task circle{
        loop(30){yield;}
        Concentration01(80);
        loop(90){yield;}
        let a = rand(30, 60);
        let acc = 1;
        loop(4){
            CreateShotA(0, (cos(a)*170)+GetX, (sin(a)*170)+GetY, 20);
            SetShotDataA(0, 0, 5, a+(60*inv), inv, 0, 0, WHITE05);
            SetShotKillTime(0,72);
            ascent(i in 1..18){
            let c = RED11;
            if(i<=7){c = color[i-1];}
            if(i>7 && i<=14){c = color[i-8];}
            if(i>14 && i<18){c = color[i-15];}
                CreateShotA(1, 0, 0, 10);
                SetShotDataA(1, 0, 1.75, 0, 0, -0.01, 0.7, c);
                ascent(j in 1..10){
                    CreateShotA(2, 0, 0, 0);
                    SetShotDataA(2, 0, 1.75, j*36, 0, -0.01, 0.7, c);
                    AddShot(0, 1, 2, 0);
                }
                AddShot((i*4)-4, 0, 1, 0);
            }
            FireShot(0);
            a+=90;
        }
        inv *= -1;
        loop(160){yield;}
        circle;
    }
   
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on May 31, 2009, 04:42:41 PM
Is it possible to draw things outside the playable screen ie have it appear under your bombs/lives and stuff?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on May 31, 2009, 05:15:02 PM
No.

SetEffectLayer will let you change the layer certain effects take place on but currently only works with Concentration01/02.

ObjEffect_SetLayer lets you change the layer an effect object is on, but it only goes up to 7, which is still below the frame.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Delpolo on May 31, 2009, 09:27:37 PM
I had another problem (and I'd like to thank all of you for answering before) which was more mathematical than anything, but I figured it out before posting.

I found out how to do slanted ovals, and I thought I might as well post it here. (I got the idea from Lissajous's curve (http://en.wikipedia.org/wiki/Lissajou#Application_for_the_case_a_.3D_b).)

Here's the code:
Code: [Select]
    let frame=0;
    let cx=GetCenterX();
    let cy=GetCenterY();
    let angle;
    if(frame==60) {
        ascent (angle in 0..360) {
            CreateShot01(cx+100*sin(angle), cy+100*sin(angle-45), 1, angle-40, YELLOW05, 10);
            CreateShot01(cx+100*sin(angle), cy-100*sin(angle-45), 1, -angle+40, YELLOW05, 10);
        }
    }
    frame++;

Just insert it into a boss' code and you'll see two crossing ovals with a safe zone in the center of the playing field. Changing the -45 makes the safe zone smaller or bigger (with 0 making it start as a line and 90 making it a circle).

Anyways, does anyone know how to do a rose curve (http://en.wikipedia.org/wiki/Rose_curve)?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 31, 2009, 10:43:48 PM
Depends on if you know your trig laws well enough to get k outside of the angle area.

If memory serves, this should be correct for k = 2:

r(θ) = cos(2θ) = cosθ*cosθ - sinθ*sinθ

Which just comes from...

cos(A + B) = cosA*cosB - sinA*sinB

Where A and B are the same number (2A).

Hell if I know any other value of k... Except 1 of course. But that's just a circle.



If you feel adventurous you could try the sin version as well, but it's not the Rose curve formula:

r(θ) = sin(2θ) = sinθ*cosθ + cosθ*sinθ
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on May 31, 2009, 10:50:22 PM
Mmmmmh.....
If k=number of petals and n=total number of bullets...


loop(n){
   a+=360/n;
   CreateShot01(x+r*cos(k*a)^k, y+r*sin(k*a)^k, 1, a, RED01, 0);
}

Could that work..?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on May 31, 2009, 10:52:56 PM
A colleague of mine claims that is incorrect. You should test it though, Danmakufu is crazy afterall.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on June 01, 2009, 09:26:28 AM
SUCCESS!

Modify b and d to modify the rose. n is the number of bullets.
I haven't worked out the correct angles for each bullets, though...


?dit: I somehow had made a stupid edit to the script while posting that made it not work as it should've... Now it will work as intended! (at least as you don't put in too strange k values. If you do, you have to either increase the value of n or the value of z to fix it.)


Code: [Select]
#TouhouDanmakufu
#Title[Stuff 73]
#Text[Stuff]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let BossImage = "script\img\ExRumia.png";
    let BossCutIn = "script\img\ExRumia.png";
    let frame=1400;

    let color=[RED32, BLUE32, GREEN32, RED32, BLUE32, GREEN32];

    let flyangle=rand(0, 360);

    let b=5;
    let d=1;
    let k=b/d;
    let n=3600;
    let z=3;
    let a=100;

    let x=1;
    let y=1;
    let r=1;

    @Initialize {
        LoadGraphic(BossImage);
        SetLife(3000);
        SetDamageRate(100, 0);
        SetTimer(60);
        SetInvincibility(120);
        SetMovePosition02(GetCenterX, 128, 60);
        Concentration01(60);

    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 24);
        SetCollisionB(GetX, GetY, 24);

if(frame==1500){


        ascent(i in 0..(n+2)){
           r = a*cos(k*z*i);
           x = r*cos(z*i);
           y =  (r^2 - x^2)^0.5 ;
           CreateShot01(GetCenterX + x, GetCenterY+ y, 0.1, 3*k*i, RED05, 0);
           CreateShot01(GetCenterX + x, GetCenterY- y, 0.1, -3*k*i, RED05, 0);
        }

        frame=0;
}

        frame++;

        yield;
 
    }

    @DrawLoop {
SetRenderState(ALPHA);
if(GetSpeedX()==0){SetGraphicRect(64,1,127,64);}
else if(GetSpeedX()>0){SetGraphicRect(192,1,255,64);}
else if(GetSpeedX()<0){SetGraphicRect(128,1,191,64);}
        SetTexture(BossCutIn);
       
    }

    @Finalize {
    }
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 05, 2009, 12:09:27 AM
Excellent stuff, didn't think multiplying values inside the angle area (I mean cos(here)) would work.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on June 05, 2009, 12:29:15 AM
Note that, in this code, a high b value will cause the pattern to look broken unless you lower the z value.

I think this will provide good rose curves only if both (n*z)/360>b && (n*z)/360>d are true statements.

As it is, the axis of symmetry points to the right. If you want the rose to have a vertical axis of symmetry, replacing x and y in the CreateShot should do the job. At least I think so. Hm, I may test it some time later...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on June 07, 2009, 12:27:54 AM
I think someone said a while back that the amount of blackspace on the bulletsheet image determines the hitbox size, and the more black there is the larger the hitbox. To confirm it, I tried making bullets with no background and the result is thier hitboxes are extremely small related to the sprite.

So basically less black = smaller hitbox.


Then again I might be completely wrong. Please correct me if that is so.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 07, 2009, 01:41:49 AM
You are 100% correct. The bigger the image dimentions, the bigger the hitbox, and vice versa.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on June 07, 2009, 02:02:41 AM
You are 100% correct. The bigger the image dimentions, the bigger the hitbox, and vice versa.
Also the hitbox always appears to be a circle. I tried using a rectangular object and it was all screwy. No wonder the knife hitboxes are messed.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 07, 2009, 02:07:52 AM
Yes sir. You can make a square hitbox if you'd like, but it requires object bullets~
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on June 07, 2009, 05:43:57 AM
No wonder the knife hitboxes are messed.
please stop saying this
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on June 07, 2009, 03:49:39 PM
That is really bizarre, but hopefully it won't end up being a huge problem...

Okay, I might as well post it now, so I can deal with whatever is making my script blow itself to pieces.

Code: [Select]
#TouhouDanmakufu[Player]
#ScriptVersion[2]
#Menu[Yuka Kazami]
#Text[]

#Image[.\yukaimage.png]
#ReplayName[Yuka]

script_player_main {
    let ImgPlayer = GetCurrentScriptDirectory()~"pl09.png";
    let ImgCutIn = GetCurrentScriptDirectory()~"yuka_cutin.png";
    let YukaShotData = GetCurrentScriptDirectory()~"Yuka_Shot.txt";
    let bslow = false; //Parameter that defines whether Yuka is in focus or not. Presumably it's a boolean where true is focus and false is not.
    let CharAlpha = 255; //Alpha of the character, starts out big.
    let bShot = false; //The shot button is being depressed.
    let bLeft = false;
    let bRight = false;
    let bSlow = false;
let drawframe = 0;
let drawnext = 1;
let rect = 1;

//I'll get to more variables later

    @Initialize {
      LoadGraphic(ImgPlayer);
      LoadGraphic(ImgCutIn);
      SetRibirthFrame(12);
      SetGrazeCircle(45);
      SetSpeed(2.9, 1.7);
      SetItemCollectLine(150); //May have to change this, I only decreased it because Yuka's so damn slow.
      SetPlayerLifeImage(NEED_SOMETHING_HERE);
  SetTexture(ImgPlayer);

      TMain;
    }
   
    @MainLoop {
        if(OnBomb){SetItemCollectLine(464);} //Auto-collects all items on screen on bombing.
        else{SetItemCollectLine(128);}
        SetIntersectionCircle(GetPlayerX, GetPlayerY, 1.5); //May have to change this, might be too small.
        yield;
    }
/*
    @SpellCard {
      if(!IsLastSpell){
        if(bSlow){
          UseSpellCard("TwinSpark");
          CutIn(YOUMU, "Yokai Sign "\""Twin Spark"\", ImgCutIn, 0, 0, WIDTH, HEIGHT); //Need the width and the height, here.
        }
        else{
          UseSpellCard("RTrap");
          CutIn(YOUMU, "Yokai Sign "\""Raspberry Trap"\", ImgCutIn, 0, 0, WIDTH, HEIGHT); //Need the width and the height here too.
        }
      }
      else{
        UseSpellCard("Gensokyo"); //Actual name: Gensokyo, Past and Present
        CutIn(YOUMU, "Flower Sign "\""Gensokyo, Past and Present"\", ImgCutIn, 0, 0, WIDTH, HEIGHT);
}
}
*/
@DrawLoop{
if(drawframe%6 == 0){
if(GetKeyState(VK_LEFT)==KEY_PUSH || GetKeyState(VK_RIGHT)==KEY_PUSH){rect = 1;}
if(GetKeyState(VK_LEFT)==KEY_FREE && GetKeyState(VK_RIGHT)==KEY_FREE && drawnext==1){
  YukaNull(rect);
  rect++;
  if(rect==8){rect=1;}
}
if(bLeft && !bRight){
YukaLeft(rect);
rect++;
if(drawnext<=4){drawnext++;}
if(rect>=5){
  YukaLeft(rect);
  if(rect==8){rect=5;
  drawnext=5;}
}}
if(bRight){
YukaRight(rect);
rect++;
if(drawnext<=4){drawnext++;}
if(rect>=5){
  YukaRight(rect);
  if(rect==8){rect=5;
  drawnext=5;}
}
if((GetKeyState(VK_LEFT)==KEY_PULL || GetKeyState(VK_LEFT)==KEY_FREE) && drawnext>1){
YukaLeft(rect);
rect--;
drawnext--;
}
if((GetKeyState(VK_RIGHT)==KEY_PULL || GetKeyState(VK_RIGHT)==KEY_FREE) && drawnext>1){
if(rect!=5){rect=5;}
YukaRight(rect);
rect--;
drawnext--;
}
}//drawframe endbracket
DrawGraphic(GetPlayerX, GetPlayerY);
drawframe++;
}
}

    @Finalize {
      DeleteGraphic(ImgPlayer);
      DeleteGraphic(ImgCutIn);
    }

//TASK TIME OHOHOH

    task TMain {
      TKeyInput; //Task that checks for important movement parameters.
      TShot; //Task for shootin's.
      yield;
    }

    task TKeyInput{
      let state;

      loop {
        state  = GetKeyState(VK_SHOT);
        bShot  = (state == KEY_PUSH || state == KEY_HOLD);

        state  = GetKeyState(VK_LEFT);
        bLeft  = (state == KEY_PUSH || state == KEY_HOLD);

        state  = GetKeyState(VK_RIGHT);
        bRight = (state == KEY_PUSH || state == KEY_HOLD);

        state  = GetKeyState(VK_SLOWMOVE);
        bSlow  = (state == KEY_PUSH || state == KEY_HOLD);

        yield;
        }
      }
task TShot{
if(!bSlow){}

function YukaNull(let nframe){
alternative(nframe)
case(1){SetGraphicRect(0, 0, 32, 48);}
case(2){SetGraphicRect(32, 0, 64, 48);}
case(3){SetGraphicRect(64, 0, 96, 48);}
case(4){SetGraphicRect(96, 0, 128, 48);}
case(5){SetGraphicRect(128, 0, 160, 48);}
case(6){SetGraphicRect(160, 0, 192, 48);}
case(7){SetGraphicRect(192, 0, 224, 48);}
case(8){SetGraphicRect(224, 0, 256, 48);}
}
function YukaLeft(let lframe){
alternative(lframe)
case(1){SetGraphicRect(0, 48, 32, 96);}
case(2){SetGraphicRect(32, 48, 64, 96);}
case(3){SetGraphicRect(64, 48, 96, 96);}
case(4){SetGraphicRect(96, 48, 128, 96);}
case(5){SetGraphicRect(128, 48, 160, 96);}
case(6){SetGraphicRect(160, 48, 192, 96);}
case(7){SetGraphicRect(192, 48, 224, 96);}
case(8){SetGraphicRect(224, 48, 256, 96);}
}
function YukaRight(let rframe){
alternative(rframe)
case(1){SetGraphicRect(0, 96, 32, 144);}
case(2){SetGraphicRect(32, 96, 64, 144);}
case(3){SetGraphicRect(64, 96, 96, 144);}
case(4){SetGraphicRect(96, 96, 128, 144);}
case(5){SetGraphicRect(128, 96, 160, 144);}
case(6){SetGraphicRect(160, 96, 192, 144);}
case(7){SetGraphicRect(192, 96, 224, 144);}
case(8){SetGraphicRect(224, 96, 256, 144);}
//FUCK MY LIFE AAAAHHHHHHH.
}
}
I did in fact call her spellcards later in the script, but they're so fragmentary that it's redundant to insert them. Oh, and that huge drawloop mess is supposed to be animations for Yuka turning one way or another, proceeding through the frames. Obviously I used a spritemap for this.
Basically, the problem is: every time I try to load a stage with this character, some weird blippy nonsense happens, and it reverts back to the stage select screen. ... halp?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 07, 2009, 06:05:42 PM
I'm having some trouble with a script... Basically, it just randomly crashes. I just can't figure it out. It's so random, it'd be difficult to tell whether or not the crashing ever stopped, because it could just look fixed, but still crash later on...

-WARNING-

You might consider the reference in the script to be a spoiler, so if you don't like spoilers, HELP AT YOUR OWN RISK. (I don't feel like hiding the reference to avoid possible spoilers.)

Code: [Select]
#TouhouDanmakufu
#Title[Unzrirock Assault]
#Text[...]
#Image[]
#BackGround[Default]
#PlayLevel[UNZRIROCK]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{
let BossImage = GetCurrentScriptDirectory ~ "Ichirirock.png";
let BossCutIn = GetCurrentScriptDirectory ~ "IchirirockCutIn.png";
let frame = -40;
let frame2 = -60;
let frame3 = -120;
let frame4 = -121;
let Angle = 0;
let ShotSFX = "script\sfx\shot.wav";
let LaserSFX = "script\sfx\laser.wav";
let Face = [];
let Position = false;
let Stop = false;
let a = 0;
let b = 0;
let c = 0;
let speed = 8;
let Colors = [YELLOW11, WHITE11];

task Unzrirock()
{
let i = 0;
while (i < length(Face))
{
if(Obj_BeDeleted(Face[i]))
{
Face = erase(Face, i);
i--;
}
else if(! Obj_BeDeleted(Face[i]))
{
if(Obj_GetSpeed(Face[i]) == 0)
{
Position = true;
Obj_SetAngle(Face[i], atan2(GetPlayerY - Obj_GetY(Face[i]), GetPlayerX - Obj_GetX(Face[i])));
}
else if(Obj_GetSpeed(Face[i]) > 0 && Obj_GetSpeed(Face[i]) > -0.1)
{
Obj_SetSpeed(Face[i], Obj_GetSpeed(Face[i]) - 0.5);
}
}
i++;
}
}

@Initialize
{
LoadGraphic(BossImage);
SetLife(512);
SetDamageRate(10,10);
SetTimer(152);
SetInvincibility(30);
CutIn(YOUMU, "Test", BossCutIn, 0, 0, 256, 320);
SetScore(70000);
SetEnemyMarker(true);
MagicCircle(true);
SetMovePosition02(GetCenterX,90,30);
LoadUserShotData(GetCurrentScriptDirectory ~ "Unzrirock.txt");
}

@MainLoop
{
Unzrirock();
SetCollisionA(GetX(),GetY(),32);
SetCollisionB(GetX(),GetY(),24);
if(frame == 0)
{
CreateShot01(GetClipMinX, GetClipMinY, speed, atan2(GetPlayerY - GetClipMinY, GetPlayerX - GetClipMinX), 2, 0);
CreateShot01(GetClipMaxX, GetClipMinY, speed, atan2(GetPlayerY - GetClipMinY, GetPlayerX - GetClipMaxX), 4, 0);
CreateShot01(GetClipMinX, GetClipMaxY, speed, atan2(GetPlayerY - GetClipMaxY, GetPlayerX - GetClipMinX), 2, 0);
CreateShot01(GetClipMaxX, GetClipMaxY, speed, atan2(GetPlayerY - GetClipMaxY, GetPlayerX - GetClipMaxX), 4, 0);
PlaySE(ShotSFX);
a++;
speed -= 1;
frame = -15;
}
if(frame2 == 0)
{
let obj = Obj_Create(OBJ_SHOT);
ObjShot_SetGraphic(obj, 1);
Obj_SetPosition(obj, GetClipMinX-5, GetClipMinY-5);
Obj_SetAngle(obj, 45);
Obj_SetSpeed(obj, 6);
ObjShot_SetBombResist(obj, true);
Face = Face ~ [obj];

let obj2 = Obj_Create(OBJ_SHOT);
ObjShot_SetGraphic(obj2, 3);
Obj_SetPosition(obj2, GetClipMaxX+20, GetClipMinY-5);
Obj_SetAngle(obj2, 135);
Obj_SetSpeed(obj2, 6);
ObjShot_SetBombResist(obj2, true);
Face = Face ~ [obj2];

let obj3 = Obj_Create(OBJ_SHOT);
ObjShot_SetGraphic(obj3, 1);
Obj_SetPosition(obj3, GetClipMinX-20, GetClipMaxY+5);
Obj_SetAngle(obj3, 315);
Obj_SetSpeed(obj3, 6);
ObjShot_SetBombResist(obj3, true);
Face = Face ~ [obj3];

let obj4 = Obj_Create(OBJ_SHOT);
ObjShot_SetGraphic(obj4, 3);
Obj_SetPosition(obj4, GetClipMaxX+20, GetClipMaxY+5);
Obj_SetAngle(obj4, 225);
Obj_SetSpeed(obj4, 6);
ObjShot_SetBombResist(obj4, true);
Face = Face ~ [obj4];
PlaySE(LaserSFX);
}
if(frame3 == 0)
{
Stop = true;
TimeStop(120, 1, 1, 1);
frame3 = -180;
}
if(frame3 == -70)
{
Concentration01(60);
}
if(Position && !Stop)
{
frame3++;
frame = -40;
frame4++;
}
if(Stop)
{
frame++;
b++;
}
if(b == 120)
{
speed = 8;
b = 0;
Stop = false;
PlaySE(LaserSFX);
}
if(frame4 == 0)
{
CreateShot01(GetX, GetY, 3, Angle, Colors[c], 5);
CreateShot01(GetX, GetY, 3, Angle, Colors[c], 5);
if(c == 1)
{
c = 0;
}
else if(c == 0)
{
c = 1;
}
Angle += 28;
frame4 = -2;
}
frame2++;
}

@DrawLoop
{
SetTexture(BossImage);
SetGraphicRect(12,1,56,93);
DrawGraphic(GetX, GetY);
}

@Finalize
{
DeleteGraphic(BossImage);
}
}

Code: [Select]
#PlayerShotData

ShotImage = ".\Unzrirock.PNG"

ShotData
{
id = 1
rect = (0,0,88,92)
angular_velocity = 0
}

ShotData
{
id = 2
rect = (178,0,242,64)
angular_velocity = 0
}

ShotData
{
id = 3
rect = (88,0,176,92)
angular_velocity = 0
}

ShotData
{
id = 4
rect = (178,64,242,128)
angular_velocity = 0
}


http://i244.photobucket.com/albums/gg13/MatthewPZC/Ichirirock.png (http://i244.photobucket.com/albums/gg13/MatthewPZC/Ichirirock.png)


http://i244.photobucket.com/albums/gg13/MatthewPZC/IchirirockCutIn.png (http://i244.photobucket.com/albums/gg13/MatthewPZC/IchirirockCutIn.png)


http://i244.photobucket.com/albums/gg13/MatthewPZC/Unzrirock.png (http://i244.photobucket.com/albums/gg13/MatthewPZC/Unzrirock.png)


(And as for the sounds, I REALLY hate reuploading them. They're just sounds from the official Touhou games, after all.)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Heath Robinson on June 07, 2009, 07:48:55 PM
Does anyone happen to know the scoping rules that Danmakufu uses?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 07, 2009, 08:11:19 PM
@Heath Robinson

Does anyone happen to know the scoping rules that Danmakufu uses?

Specify what you mean? Scoping...?



@Karfloozly

Your script isn't detected in my player list. Can you .rar all your files and upload it?



@pikaguy900

Getting to yours, expect edits.

Edit 1: Can't get it to crash, going to look through your script for anything odd.

Edit 2: Didn't see anything out of the ordinary... Are you using a .ogg or corrupted music file when you play the script or something? I'm not sure what would make it crash.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 07, 2009, 09:09:33 PM
@pikaguy900

Getting to yours, expect edits.

Edit 1: Can't get it to crash, going to look through your script for anything odd.

Edit 2: Didn't see anything out of the ordinary... Are you using a .ogg or corrupted music file when you play the script or something? I'm not sure what would make it crash.

Nope, there's no song files in this script. What you see in what I posted is what is in my script...

However, I'm curious as to something... Could you copy the LoadUserShotData out of @Initialize and put it in @MainLoop, while leaving the original where it was? I previously had a copy of that function in the MainLoop because I thought you couldn't access the original bullets while you had a LoadUserShotData in a script. Thus, I also had a LoadUserShotData("") later on, where I spawn the YELLOW11 bullets. It crashed then, often, even when I commented out the LoadUserShotData("")... So perhaps LoadUserShotData can't be called more than once without ill effects?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 07, 2009, 09:26:27 PM
Perhaps. Interesting thing about comments is that they don't work sometimes. For example, in one of my stage scripts I had  commented something regarding a task I created, so I named the task inside my comment and Danmakufu read it as if it was uncommented. Not sure how it worked or what I screwed up... But it was a mind boggling result that took me a while to fix.

Best thing is to just call it once and leave it at that. You have shot_all.png, so you can just take any of the original bullets off of that and copy them onto your sprite sheet, if you need to spawn something outside of your custom shots.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on June 08, 2009, 12:00:29 AM
I'm not sure what that would amount to, Naut, but I can try... the thing is, she currently lacks any semblance of shot information (I have the shot data already configured, although it was just as a troubleshoot... I only defined one bullet) and bomb info. I wonder why she doesn't show up, though... that's very bizarre.

I'll try to find a method of uploading.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on June 09, 2009, 04:34:27 AM
I have a question...

How do you make a spellcard for a player you're creating as a laser, like Marisa's, but using a custom picture, like a .png file that you already have?

Pls answer... thanks in advance...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on June 09, 2009, 04:58:42 AM
You make a spell object with that .png as the texture.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Heath Robinson on June 09, 2009, 12:47:12 PM
@Heath Robinson

Specify what you mean? Scoping...?

I meant this (http://en.wikipedia.org/wiki/Scope_(programming)).  In particular I wonder whether sub-routines, functions, and tasks operate inside their own independant scopes, with the alternative being that variables in one or more of these fall under the global namespace.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on June 09, 2009, 04:40:30 PM
Yes, they all have their own scopes.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on June 09, 2009, 05:22:51 PM
Code: [Select]
#TouhouDanmakufu
#Title[BROFIST]
#Text[Dodge five bros or you're not a bro]
#BGM[.\Unzan lol.mp3]
#PlayLevel[ULTRA RAPE]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = 0;
    let count = 0;
    let count2 = 0;
    let direction = 0;
    @Initialize {
SetLife(9001);
        SetTimer(30);
LoadUserShotData(GetCurrentScriptDirectory ~ "shot.txt");
SetShotAutoDeleteClip(500,500,500,500)
    }

    @MainLoop {     
        if(frame==2){
    CreateShot01(60, -300, 50, 90+(1*count), 300, 0);
            CreateShot01(390, -300, 50, 90-(1*count), 300, 0);
    frame = 0;
    count2++;
    if(direction==0){
        count++;
        }
            if(count==5){
        direction = 1;
        count--;
                }
        if(direction==1){
        count--;
        }
            if(count==-5){
        direction = 0;
        count++;
        }
            }
if(count2==5){
    CreateShot01(GetX, -300, 2, GetAngleToPlayer, RED01, 0);
    count2 = 0;
            }
        frame++;
    }

    @DrawLoop {
    }

    @Finalize {
    }

    @BackGround {
    }
}
GetAngleToPlayer seems to be failing in this script. If I move about 1.5 characters to the left or right, the small red shots aim to the other side of me and don't ever come close of hitting...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 09, 2009, 06:04:23 PM
Code: [Select]
#TouhouDanmakufu
#Title[BROFIST]
#Text[Dodge five bros or you're not a bro]
#BGM[.\Unzan lol.mp3]
#PlayLevel[ULTRA RAPE]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = 0;
    let count = 0;
    let count2 = 0;
    let direction = 0;
    @Initialize {
SetLife(9001);
        SetTimer(30);
LoadUserShotData(GetCurrentScriptDirectory ~ "shot.txt");
SetShotAutoDeleteClip(500,500,500,500)
    }

    @MainLoop {     
        if(frame==2){
    CreateShot01(60, -300, 50, 90+(1*count), 300, 0);
            CreateShot01(390, -300, 50, 90-(1*count), 300, 0);
    frame = 0;
    count2++;
    if(direction==0){
        count++;
        }
            if(count==5){
        direction = 1;
        count--;
                }
        if(direction==1){
        count--;
        }
            if(count==-5){
        direction = 0;
        count++;
        }
            }
if(count2==5){
    CreateShot01(GetX, -300, 2, GetAngleToPlayer, RED01, 0);
    count2 = 0;
            }
        frame++;
    }

    @DrawLoop {
    }

    @Finalize {
    }

    @BackGround {
    }
}
GetAngleToPlayer seems to be failing in this script. If I move about 1.5 characters to the left or right, the small red shots aim to the other side of me and don't ever come close of hitting...

From what I've heard, GetAngleToPlayer gets the angle from the enemy to the player, not the bullet to the player. However, yes, some people have said otherwise. (I, though, feel this script proves that it gets from the enemy.) To fix it, just do atan2(GetPlayerY - *insert the Y location of the bullet here*, GetPlayerX - *insert the X location of the bullet here*) and you have the angle from the bullet to the player!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on June 09, 2009, 06:06:57 PM
From what I've heard, GetAngleToPlayer gets the angle from the enemy to the player, not the bullet to the player. However, yes, some people have said otherwise. (I, though, feel this script proves that it gets from the enemy.) To fix it, just do atan2(GetPlayerY - *insert the Y location of the bullet here*, GetPlayerX - *insert the X location of the bullet here*) and you have the angle from the bullet to the player!
Sweet. Thanks!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on June 09, 2009, 07:40:29 PM
For regular bullets, there is another way to make them aim towards the player. That is, the command SetShotDirectionType(PLAYER);. After this command, bullets will have their angle adjusted not towards the right side of the field but towards the player, meaning that any bullet with an angle of 0 will aim towards the player. After you fired the bullet call SetShotDirectionType(ABSOLUTE); to return to the regular way of firing bullets.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on June 09, 2009, 11:44:25 PM
SetShotDirectionType(Player) is particularly useful for CreateShotA bullets with multiple steps, as bullets made with it are capable of adjusting the angle to the player dynamically; the angle formula would only shoot it where the player was when the bullet was fired.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 12, 2009, 06:03:09 PM
I have two questions:

1: Given an amount of angles between two points, how can I easily figure out how much I need to increase the angle by to put something directly in the middle of those two points?

Basically, I have a script where many yellow lasers spin around the boss in one direction, while an equal amount of red lasers spin in the other direction. Eventually, they slow down and stop, and they can either be lined up on each other perfectly, or the red lasers will be positioned in between the yellowss. When I had 36 lasers, I increased the angle by 10, and I found that increasing the angles of the red ones by 45 (though it'd probably be better on a smaller amount) got them to be perfectly in the middle of the yellow ones. However, now that I've lowered the laser count to 24 of each color, I find that I need to change the angle for the reds. Problem is, I cannot figure out the "middle angle" here. So, to put my question in another way...

[Angle 135]    o    [Angle 105]

How do I find the middle angle, the "o", given the angles 105 and 135? I KNOW it would come from trigonometry, but sad to say, I never really got to learn that...how sad. (Please don't ask.)

2: I know there's a function that will return the angle of a line between two given points, but how would I go about using that angle and the positions of the points to deduce the distance between said points? Basically, I'm looking to try to see if I could maybe recreate the gravitational pull effect of Utsuho's last spellcard in SA... Not actually wanting to recreate that spellcard, just the effect. I just feel like trying to make a script that has that since it'd be fun to play.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Delpolo on June 12, 2009, 06:33:58 PM
1: If you have 24 lasers, each laser has 360/24 degrees between each, or 15 degrees. Half of that is 7.5 degrees. (With 36 lasers, you could have increased it by only 5 degrees.) In other words, the middle of two angles is half the angle difference, plus the lower angle ((A2-A1)/2+A1, wher A1 and A2 are the angles).

2: You don't need the angle to calculate the distance between two points. All you need is the X and Y distance between the two points, then use the Pythagorean theorem to get the distance. In other words, "((X1-X2)^2+(Y1-Y2)^2)^0.5" (where X1 and Y1 are the X and Y couple of one point, and X2 and Y2 are for the other point) should work.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 12, 2009, 06:54:02 PM
1: If you have 24 lasers, each laser has 360/24 degrees between each, or 15 degrees. Half of that is 7.5 degrees. (With 36 lasers, you could have increased it by only 5 degrees.) In other words, the middle of two angles is half the angle difference, plus the lower angle ((A2-A1)/2+A1, wher A1 and A2 are the angles).

2: You don't need the angle to calculate the distance between two points. All you need is the X and Y distance between the two points, then use the Pythagorean theorem to get the distance. In other words, "((X1-X2)^2+(Y1-Y2)^2)^0.5" (where X1 and Y1 are the X and Y couple of one point, and X2 and Y2 are for the other point) should work.

1: I tried 7.5, but that honestly didn't make it work. It makes the red lasers hug near the yellow lasers. Thus is my problem. All I'm really doing is this, basically:

Yellow Lasers: variable Angle, which increases by 15 each time a laser is created
Red Lasers: Same as Yellow, but before the lasers are even created, a variable "c" is created and set to "AngleChange[rand_int(0, 5)]". This is AngleChange:

let AngleChange = [7.5, 7.5, 7.5, 7.5, 0, 0];
(The zeroes are so the Red Lasers may line up with the Yellow ones, but most likely WON'T.)

So, the formula for Red Lasers is merely "Angle+c". This worked fine with 36 lasers and c = 45 from AngleChange, but now, it won't put it in between them.

2: Oh geez, Pythagorean Theorem... Thanks, I'll try that. ...but I need the angle, anyways, since I then have to change the X and Y positions of the player according to the angle to the other point! (The distance is only needed for checks to make sure the player doesn't go past the point.)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Delpolo on June 12, 2009, 07:54:15 PM
For the angle between 2 points, once you have X1-X2 (which would be X3) and Y1-Y2 (or X3), then use "atan2(Y3, X3)" to get the angle (unless they're over each other).

As for the lasers... I'm sorry, but I don't know the problem. You could possibly post the script so that someone else could help, though.

EDIT- Iryan, it's not 12 reds and 12 yellows. He says in his post:
[...]now that I've lowered the laser count to 24 of each color[...]
So it should be 7.5 to add, but if that doesn't work, then it must be something else.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on June 12, 2009, 09:18:32 PM
24 lasers... do you mean 12 red and 12 yellow ones? In that case the difference has to be 15?.


As for being sucked towards a point at a given speed, well...

v = speed
x, y = point of suckitude

Code: [Select]
angle=atan2(y-GetPlayerY, x-GetPlayerX);
SetPlayerX(GetPlayerX+v*cos(angle));
SetPlayerY(GetPlayerY+v*sin(angle));

That should do the trick.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on June 12, 2009, 09:48:44 PM
1. Is there any particular reason why I can't get CreateEnemyFromScript to work for stage scripts? Or do I just have to make an entirely separate file for my generic enemies and use CreateEnemyFromFile?

2. What would I have to learn in order to make a "background object", like a tree or mountain? I already figured out drawing in 3D, but it would be a pain to do everything with just variables...

3. Can anyone provide me with an example event script? I tried a few times, but it just doesn't work for me :(
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 12, 2009, 11:09:41 PM
Okay, here's my code:

Code: [Select]
#TouhouDanmakufu
#Title[Sun Spin]
#Text[]
#Image[]
#BackGround[Default]
#PlayLevel[]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
//let BossImage = GetCurrentScriptDirectory ~ "boss_yukari.png";
//let BossCutIn = GetCurrentScriptDirectory ~ "Yukari.png";
let frame = -60;
let frame2 = -20;
let Angle = 0;
let Angle2 = 0;
//let ShotSFX = "script\sfx\shot.wav";
//let LaserSFX = "script\sfx\laser.wav";
let delay = 80;
let AngleSave = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let AngleSave2 = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let AngleChange = [7.5, 7.5, 7.5, 7.5, 0, 0];

@Initialize
{
shotinit;
//LoadGraphic(BossImage);
SetLife(1024);
SetDamageRate(10,2);
SetTimer(152);
SetInvincibility(30);
//CutIn(YOUMU, "Sun Spin", BossCutIn, 0, 0, 256, 320);
SetScore(70000);
SetEnemyMarker(true);
MagicCircle(true);
SetMovePosition02(GetCenterX,GetCenterY-100,30);
}

@MainLoop
{
SetCollisionA(GetX(),GetY(),32);
SetCollisionB(GetX(),GetY(),24);
if(frame == 0)
{
let laser = 0;
let i = 0;
let c = AngleChange[rand_int(0, 5)];
loop(24)
{

CreateLaserB(laser, 200, 10, YELLOW01, 150);
SetLaserDataB(laser, 0, 0, 0, 0, 0, 2, Angle, 2);
SetLaserDataB(laser, 460, 0, 0, 0, NULL, 1.5, NULL, 1.5);
SetLaserDataB(laser, 500, 0, 0, 0, NULL, 1, NULL, 1);
SetLaserDataB(laser, 540, 0, 0, 0, NULL, 0.5, NULL, 0.5);
SetLaserDataB(laser, 580, 0, 0, 0, NULL, 0, NULL, 0);
SetShotKillTime(laser, 680);
//PlaySE(LaserSFX);
FireShot(laser);
laser++;
CreateLaserB(laser, 200, 10, RED01, 150);
SetLaserDataB(laser, 0, 0, 0, 0, 0, -2, (Angle+c), -2);
SetLaserDataB(laser, 460, 0, 0, 0, NULL, -1.5, NULL, -1.5);
SetLaserDataB(laser, 500, 0, 0, 0, NULL, -1, NULL, -1);
SetLaserDataB(laser, 540, 0, 0, 0, NULL, -0.5, NULL, -0.5);
SetLaserDataB(laser, 580, 0, 0, 0, NULL, 0, NULL, 0);
SetShotKillTime(laser, 680);
FireShot(laser);
laser++;
AngleSave[i] = Angle;
AngleSave2[i] = (Angle+c);
Angle += 15;
i++;
}
}
if(frame >= 580 && frame < 640)
{
if(frame%5 == 0)
{
let i = 0;
let shot = 0;
let curve = rand(0.5, 1);
loop(24)
{
CreateShotA(shot, GetX, GetY, 25);
SetShotDataA(shot, 0, 6, AngleSave[i], 0, 0, 0, YELLOW05);
SetShotDataA(shot, 10, NULL, NULL, 0, 0, 0, YELLOW05);
SetShotDirectionType(PLAYER);
SetShotDataA(shot, 30, NULL, NULL, 0, -1, 0, YELLOW05);
SetShotDataA(shot, delay, NULL, 0, 0, 0.1, 8, YELLOW05);
FireShot(shot);
shot++;
SetShotDirectionType(ABSOLUTE);
CreateShotA(shot, GetX, GetY, 25);
SetShotDataA(shot, 0, 6, AngleSave2[i], 0, 0, 0, RED05);
SetShotDataA(shot, 10, NULL, NULL, 0, 0, 0, RED05);
SetShotDirectionType(PLAYER);
SetShotDataA(shot, 30, NULL, NULL, 0, -1, 0, RED05);
SetShotDataA(shot, delay, NULL, 0, 0, 0.1, 8, RED05);
FireShot(shot);
SetShotDirectionType(ABSOLUTE);
i++;
}
delay += 20;
}
}
if(frame2 == 0)
{
SetMovePositionRandom01(100, 15, 15, GetCenterX - 130, GetCenterY - 150, GetCenterX + 130, GetCenterY - 35);
frame2 = -20;
}
frame++;
if(frame < 550)
{
frame2++;
}
if(frame == 710)
{
frame = 0;
delay = 80;
}
}

@DrawLoop
{
//SetTexture(BossImage);
//SetGraphicRect(40,33,91,94);
//DrawGraphic(GetX, GetY);
}

@Finalize
{
//DeleteGraphic(BossImage);
}
}

(I commented out all the SFX and graphics-related stuff because I don't really want to upload the same things over and over. It's just annoying.)

I honestly can't see what's wrong here. Also, somehow, the bullets I spawn at the end don't even appear at the right place anymore, though they do when I spawn 36 lasers of each color... (I reduced it to 24 because 72 lasers plus 72 bullets every 5 frames when they appear lags Danmakufu for me...)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on June 12, 2009, 11:26:08 PM
Uuuuuh...


The laser sets spin in different directions...

The total angle one set spins is...

(460*2 + 40*1.5 + 40*1 + 40*0.5) = 980 + 60 + 40 + 20 = 1100

As the sets spin in different directions, the difference in the end is 2200. Every full 360 degrees don't matter.
360*6 = 2160; 2200-2160= 40.

Thus, your angle differs by 40 by default. Thus, c has to equal half the difference between two lasers -40. Which, in case of 24 lasers, would be (360/24)/2 -40 =  7.5 -40 = -32.5


...at least I think so.

I cannot test it without restarting the PC, and it is about 2 am over here, so I'm too lazy.  :P
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 12, 2009, 11:40:24 PM
Ah, thanks! That PARTIALLY fixes it... I say "PARTIALLY" because it sometimes goes off-angle...probably due to those 0's I have. (Maybe changing them to 40 would be better?)

Also, I still have a problem with the bullets not shooting at the correct locations! Any idea why?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on June 12, 2009, 11:45:19 PM
Ah, thanks! That PARTIALLY fixes it... I say "PARTIALLY" because it sometimes goes off-angle...probably due to those 0's I have. (Maybe changing them to 40 would be better?)
Exactly. Change all zeros to 40.


Quote
Also, I still have a problem with the bullets not shooting at the correct locations! Any idea why?
I don't really know how you want your bullets to behave, but I am pretty certain that whatever you want to achieve would be easier if you attached the bullets to the lasers with AddShot instead.


Well, you say the bullets don't spawn where you want them to? Where do you want them to appear? They all should spawn at GetX/GetY, which is the position of the boss, and nothing about the lasers should be able to change this...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 13, 2009, 12:01:30 AM
No no, they spawn WHERE I want them to- they just don't SHOOT out AT the ANGLES I want them to, which are the exact angles those lasers are pointing, therefore, they run along the lasers. Also, I kinda hate AddShot when working with multiple shots. I don't think I ever did get it working correctly... Not sure.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on June 13, 2009, 12:03:30 AM
Ah, just the angles. Give me a minute...

As I said, the first set of lasers rotates by 1100, the second by -1100 degrees.
The closest multiple of 360? would be 1080.

Thus you have to subtract 20 degrees from the firing angle of the first set of bullets and have to add 20 degrees to the firing angle of the second.
Or possibly the other way round. One of those variants should work. Test it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 13, 2009, 12:15:52 AM
2: I know there's a function that will return the angle of a line between two given points, but how would I go about using that angle and the positions of the points to deduce the distance between said points? Basically, I'm looking to try to see if I could maybe recreate the gravitational pull effect of Utsuho's last spellcard in SA... Not actually wanting to recreate that spellcard, just the effect. I just feel like trying to make a script that has that since it'd be fun to play.

Utsuho's psuedo-gravity:

      PlayerAngle = atan2(GetCenterY - GetPlayerY, GetCenterX - GetPlayerX); //ANGLE FORMULA!
      PlayerDistance = ((GetPlayerX - GetCenterX)^2 + (GetPlayerY - GetCenterY)^2)^0.5; //DISTANCE FORMULA!
      SetPlayerX(GetCenterX - (PlayerDistance - gravity)*cos(PlayerAngle)); //GRAVITY FOR X!
      SetPlayerY(GetCenterY - (PlayerDistance - gravity)*sin(PlayerAngle)); //GRAVITY FOR Y!

Declare PlayerAngle = 0;, PlayerDistance = 0; and gravity = the distance you want the player to move per frame. The rate at which Utsuho pulls you in at the very start of Subterranean Sun is approximately 0.5 pixels per frame, thus gravity = 0.5;. This gravity code will suck the player towards the center of the screen (GetCenterX, GetCenterY). Replace all of those values for any point you wish the player to move to (like say, GetX, GetY to always move towards the boss). Call those four lines of code every @MainLoop (like SetCollisionA/B).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on June 13, 2009, 01:08:04 AM
... if I knew that SetPlayerX/Y existed, that would have made my life SO much easier.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 13, 2009, 02:02:56 AM
We hide information from you so that you'll keep coming back here to talk to us :(
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on June 13, 2009, 10:10:54 AM
@ Pikaguy:

Sorry, I'm stupid. You should change the zeros to - 40 instead of 40.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on June 13, 2009, 02:02:52 PM
I actually figured out the answer to my question on my own. Turns out you can't comment out stuff before you define #TouhouDanmakufu. Wewl, I now have just about the prettiest animation script anyone has ever seen. All I need is the shot data and the spellcards and... augh.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on June 13, 2009, 02:53:56 PM
So hey I found something out last night and I guess I'll post it here.

As you may or may not have noticed most of the shot definition files people have made for shot_all don't actually include all the bullets, so I was working on a complete one and having trouble getting the dark bullets to work right.

Turns out, in a shot definition script the maximum number of bullets you can have is 255. If you give a shot an ID of more than 255 and try to call it in a script, it will instead call the last bullet defined in the script.

(I can still squeeze all of shot_all into one definition script, just need to change my numbering system.)

So in the unlikely event that you are attempting to make a shot definition script with a shot ID of more than 255...now you know.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on June 14, 2009, 03:33:09 AM
Arg how do I put a spellcard file with a stage file?

Arg stage files in general and confusing the hell out of me
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 14, 2009, 04:17:54 AM
Though I've already talked to you about it over MSN, I'll post the link to my "stage tutorial" for anybody else wondering how to create stage files:

http://www.shrinemaiden.org/forum/index.php?topic=382.msg12998#msg12998
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Tracedragon on June 15, 2009, 11:21:39 PM
Hello. I have a question on Danmakufu in regards to bullet control.

Let us say that in a spellcard, I have:
Code: [Select]
CreateShot01(GetX, GetY, 1, GetAngleToPlayer, BLUE03, 0);And I want to change it so that it fires 03-type bullets in random alternating colors.
How would I go about doing this?

In a player script, I can use:
Code: [Select]
CreatePlayerShot01(GetPlayerX(), GetPlayerY(), 5, rand(1,5), 1, 2, rand(1,2));
However, used in a spellcard,
Code: [Select]
CreateShot01(GetX, GetY, 1, GetAngleToPlayer, rand(RED03, ORANGE03, YELLOW03, GREEN03, BLUE03, TEAL03, PURPLE03), 0);doesn't seem to work.

Any other ways I can go about doing this?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on June 15, 2009, 11:55:44 PM
Make an array.

let randcolor = [RED03, ORANGE03, YELLOW03, GREEN03, AQUA03, BLUE03, PURPLE03];
CreateShot01(GetX, GetY, 1, GetAngleToPlayer, randcolor[trunc(rand(0,6))], 0);

by the way it's aqua not teal

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on June 16, 2009, 12:04:32 AM
This is really sad but,

how do you use the ascent function?

Also, how do you move your boss around?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on June 16, 2009, 12:18:38 AM
Ascent is basically the same as looping, but while increasing a variable each loop. You don't even need to declare the variable first with "let variable = number" or anything. For example...

ascent(shotspeed in 0..5)
{CreateShot01(GetX,GetY,2+shotspeed/2,GetAngleToPlayer,RED01,30);}

...would create a line of shots towards the player.

As for movement, check this page (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Motion_Functions) and look at the SetMovePosition functions. They are pretty self explanatory.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on June 16, 2009, 12:19:05 AM
ascent(x in y..z){

}

x is a new variable created only for the loop. It starts out as y, then when it reaches the end it increases by one until it equals z. y and z are numbers, obv.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on June 16, 2009, 12:21:19 AM
Thanks. Also, can you help me to get this to work?

Code: [Select]
#TouhouDanmakufu
#Title[how do I shot bullets?]
#Text[lol i dunno]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = 0;
    @Initialize {
        SetLife(100);
        SetEnemyMarker(true);
        SetDamageRate(3, 3);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 24);
        if(frame==99-GetEnemyLife()){
CreateShot01(GetX, GetY, 3, 0, RED01, 10);
CreateShot01(GetX, GetY, 3, 45, RED01, 10);
CreateShot01(GetX, GetY, 3, 90, RED01, 10);
CreateShot01(GetX, GetY, 3, 135, RED01, 10);
CreateShot01(GetX, GetY, 3, 180, RED01, 10);
CreateShot01(GetX, GetY, 3, 225, RED01, 10);
CreateShot01(GetX, GetY, 3, 270, RED01, 10);
CreateShot01(GetX, GetY, 3, 315, RED01, 10);
CreateShot01(GetX, GetY, 3, 360, RED01, 10);

CreateShot01(GetX, GetY, 6, 0, BLUE01, 10);
CreateShot01(GetX, GetY, 6, 45, BLUE01, 10);
CreateShot01(GetX, GetY, 6, 90, BLUE01, 10);
CreateShot01(GetX, GetY, 6, 135, BLUE01, 10);
CreateShot01(GetX, GetY, 6, 180, BLUE01, 10);
CreateShot01(GetX, GetY, 6, 225, BLUE01, 10);
CreateShot01(GetX, GetY, 6, 270, BLUE01, 10);
CreateShot01(GetX, GetY, 6, 315, BLUE01, 10);
CreateShot01(GetX, GetY, 6, 360, BLUE01, 10);
            frame = 0;
        }
        frame++;
    }

    @DrawLoop {       
    }

    @Finalize {
    }
}

It doesn't shoot out bullets for some reason.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 16, 2009, 12:43:32 AM
It will skip over the correct frame value. Remove "frame++;" from your mainloop and it might fire, but only a few times, provided the player characters don't do a decimal amount of damage, which is almost guarenteed. Truncate GetEnemyLife with:

trunc(GetEnemyLife);

...So that it will always be an integer, but even then the script won't fire bullets many times. I would just avoid GetEnemyLife, especially when used in conjunction with "==", because most of the time it will either be a decimal or skip over the value you're looking for. Use something like "<=" or ">=", but avoid adding and subtracting changing numbers because it's too hard to tell when bullets will shoot.

Actually, I would rethink how you want to approach this script, it'll take many an hour and headache to get it to work... If you even get that far.

Also, to Drake: rand_int(0, 6) is much easier to use than trunc(rand(0, 6)), for your records.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on June 16, 2009, 02:23:36 AM
How do you set a global effect for a plural script? (e.g. a constant weak field of gravity for an entire bossfight... that's not at all what I want to use, but eh, it might be fun for somebody. I forget what I was actually trying to do... but yeah, halp?)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 16, 2009, 03:02:40 AM
Make it a stage script instead, but immediately call the plural script so that it acts the same as a plural. In the stage script you can make tasks to add effects like gravity and whatnot that are active throughout the battle.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on June 16, 2009, 03:30:07 AM
Also, to Drake: rand_int(0, 6) is much easier to use than trunc(rand(0, 6)), for your records.
Oh. I knew that, I just C+P from an old file.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on June 16, 2009, 09:58:03 PM
Is it possible to put variables within strings?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on June 16, 2009, 10:00:07 PM
string = "text" + variable + "text";
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 16, 2009, 10:17:35 PM
You wish that worked.

Code: [Select]
#TouhouDanmakufu
#Title[ffffffftextfffffff]
#Text[ffffff]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {

let res = 0;
let strings;

    @Initialize {
        SetLife(6000);
        SetTimer(120);
        SetScore(1000000);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        yield;
        res++;
    }

    @DrawLoop {
strings = "Hi there " + res + " ffffff";
DrawText(strings, 37, 425, 12, 255);
    }

    @Finalize {
    }
}

No idea what I'm doing lalalala I hate drawing things in Danmakufu lalalala
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Tracedragon on June 17, 2009, 12:06:33 AM
Make it a stage script instead, but immediately call the plural script so that it acts the same as a plural. In the stage script you can make tasks to add effects like gravity and whatnot that are active throughout the battle.

Or you can include a common script function in each spellcard in the plural, if you really need it as a "plural". :P
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on June 17, 2009, 01:00:59 AM
string = "text" + variable + "text";

Not sure if it works with non-string variables, but to concatenate strings you use the tilde (~), not the plus sign:

Code: [Select]
let string_a = "hello";
let string_b = "world";
let result = string_a ~ " " ~ string_b ~ "!";
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on June 17, 2009, 02:32:05 AM
Basically I was wondering if it was possible to do something like

ascent(i in 1..20){
   somethingsomestuffblahblahcode(ry... GetCurrentScriptDirectory ~ "i.png";}

I was thinking if there was a way so I can get the "i" in "i.png" to work with ascent so I don't have to take up 20 lines (or more) to load stuff.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on June 17, 2009, 02:53:34 AM
Quick question wrt drawing functions. Supposing I wanted to do something like... Reimu-A's bomb from SA. How would I accomplish that scrolliness that the waves do? It takes one little 'ripple' graphic, then loops that, moving through these triangular 'windows'... eeh, go see it for yourself. oxo
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on June 17, 2009, 05:09:37 AM
Mind you, I haven't actually tried this so this is theoretical, but I'm pretty sure this is how.

First you gotta make an effect object using PRIMITIVE_FAN. Vertex 0 should be in the center, and the other vertexes form the outside rim. Make sure vertex 1 and the last vertex touch to complete the shape.

Then you're gonna want to put some SetVertexUV shenanigans in a loop. Basically if you make a triangle with vertex 0 as one corner, the even vertexes as the second, and the odd vertexes as the third, you'll make a wedge of the image that gets patterned repeatedly around the center vertex. Then you scroll the positions of the SetVertexUV as the loop goes on, like just +1 to the y values each loop or something, and each wedge will repeat the scrolling image, and since they all scroll towards vertex 0 it'll create a vortexy thing. That oughta do it.

(http://img198.imageshack.us/img198/8184/visualaid.png)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 17, 2009, 07:06:56 PM
Okay, I'm having some problems here. Really annoying ones. Okay, technically one single problem, but still...

Code: [Select]
script_enemy_main
{
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
let BossImage = GetCurrentScriptDirectory ~ "boss_remilia.png";
let BossCutIn = GetCurrentScriptDirectory ~ "Remilia.png";
let frame = -100;
let frame2 = -90;
let frame3 = -90;
let frame4 = -90;
let frame5 = -90;
let frame6 = -90;
let move = -240;
let anim_frame = 0;
let Angle = 90;
let Angle2 = 90;
//let ShotSFX = "script\sfx\shot.wav";
//let LaserSFX = "script\sfx\laser.wav";
let Movecount = 0;
let BAT = [0, 0, 0, 0, 0];

@Initialize
{
shotinit;
LoadGraphic(BossImage);
SetLife(2120);
SetTimer(32);
SetInvincibility(30);
SetEnemyMarker(true);
MagicCircle(false);
SetMovePosition02(GetCenterX, 90, 30);
}

@MainLoop
{
anim_frame++;
AddLife(GetCommonDataDefault("Life", 0));
SetCollisionA(GetX(),GetY(),32);
SetCollisionB(GetX(),GetY(),24);
if(move == 0)
{
if(Movecount == 0)
{
SetMovePosition02(120, 126, 30);
Movecount = 1;
}
else if(Movecount == 1)
{
SetMovePosition02(GetCenterX - 53, 105, 30);
Movecount = 2;
}
else if(Movecount == 2)
{
SetMovePosition02(GetCenterX, 90, 30);
Movecount = 0;
}
move = -160;
}
if(frame == 0)
{
if(Movecount == 0)
{
loop(20)
{
CreateShotA(0, GetX, GetY, 20);
CreateShotA(1, GetX, GetY, 20);
CreateShotA(2, GetX, GetY, 20);
SetShotDataA(0, 0, 3, Angle, 0, 0, 0, RED02);
SetShotDataA(1, 0, 3, Angle, 0, 0, 0, RED02);
SetShotDataA(2, 0, 3, Angle, 0, 0, 0, RED02);
SetShotDirectionType(PLAYER);
SetShotDataA(0, 20, 0, 0, 0, 0, 0, WHITE02);
SetShotDataA(1, 40, 0, 0, 0, 0, 0, WHITE02);
SetShotDataA(2, 60, 0, 0, 0, 0, 0, WHITE02);
SetShotDataA(0, 180, NULL, NULL, 0, 0.2, 5, RED02);
SetShotDataA(1, 140, NULL, NULL, 0, 0.2, 5, RED02);
SetShotDataA(2, 100, NULL, NULL, 0, 0.2, 5, RED02);
FireShot(0);
FireShot(1);
FireShot(2);
SetShotDirectionType(ABSOLUTE);
Angle += 18;
}
}
else if(Movecount == 1)
{
}
else if(Movecount == 2)
{
}
frame = -120;
}
if(frame2 == 0)
{
let array = [0, 40, 0];
BAT[0] = 1;
CreateEnemyFromFile(GetCurrentScriptDirectory ~ "Bat1.txt", GetX, GetY + 40, 0, 90, array);
frame2 = -90;
}
if(frame3 == 0)
{
BAT[1] = 1;
let array = [-25, 35, 1];
CreateEnemyFromFile(GetCurrentScriptDirectory ~ "Bat1.txt", GetX - 25, GetY + 35, 0, 90, array);
frame3 = -90;
}
if(frame4 == 0)
{
BAT[2] = 1;
let array = [25, 35, 2];
CreateEnemyFromFile(GetCurrentScriptDirectory ~ "Bat1.txt", GetX + 25, GetY + 35, 0, 90, array);
frame4 = -90;
}
if(frame5 == 0)
{
BAT[3] = 1;
let array = [-35, 20, 3];
CreateEnemyFromFile(GetCurrentScriptDirectory ~ "Bat1.txt", GetX - 35, GetY + 20, 0, 90, array);
frame5 = -90;
}
if(frame6 == 0)
{
BAT[4] = 1;
let array = [35, 20, 4];
CreateEnemyFromFile(GetCurrentScriptDirectory ~ "Bat1.txt", GetX + 35, GetY + 20, 0, 90, array);
frame6 = -90;
}
frame++;
move++;
if(BAT[0] == 0)
{
if(frame2 == -30)
{
CreateShotA(255, GetX, GetY + 40, 30);
SetShotDataA(255, 0, 0, 0, 0, 0, 0, WHITE02);
SetShotKillTime(255, 0);
FireShot(255);
}
frame2++;
}
if(BAT[1] == 0)
{
if(frame3 == -30)
{
CreateShotA(255, GetX - 25, GetY + 35, 30);
SetShotDataA(255, 0, 0, 0, 0, 0, 0, WHITE02);
SetShotKillTime(255, 0);
FireShot(255);
}
frame3++;
}
if(BAT[2] == 0)
{
if(frame4 == -30)
{
CreateShotA(255, GetX + 25, GetY + 35, 30);
SetShotDataA(255, 0, 0, 0, 0, 0, 0, WHITE02);
SetShotKillTime(255, 0);
FireShot(255);
}
frame4++;
}
if(BAT[3] == 0)
{
if(frame5 == -30)
{
CreateShotA(255, GetX - 35, GetY + 20, 30);
SetShotDataA(255, 0, 0, 0, 0, 0, 0, WHITE02);
SetShotKillTime(255, 0);
FireShot(255);
}
frame5++;
}
if(BAT[4] == 0)
{
if(frame6 == -30)
{
CreateShotA(255, GetX + 35, GetY + 20, 30);
SetShotDataA(255, 0, 0, 0, 0, 0, 0, WHITE02);
SetShotKillTime(255, 0);
FireShot(255);
}
frame6++;
}
if(GetCommonDataDefault("Fami1", 0) == 1)
{
BAT[0] = 0;
SetCommonData("Fami1", 0);
}
if(GetCommonDataDefault("Fami2", 0) == 1)
{
BAT[1] = 0;
SetCommonData("Fami2", 0);
}
if(GetCommonDataDefault("Fami3", 0) == 1)
{
BAT[2] = 0;
SetCommonData("Fami3", 0);
}
if(GetCommonDataDefault("Fami4", 0) == 1)
{
BAT[3] = 0;
SetCommonData("Fami4", 0);
}
if(GetCommonDataDefault("Fami5", 0) == 1)
{
BAT[4] = 0;
SetCommonData("Fami5", 0);
}
}

@DrawLoop
{
SetTexture(BossImage);
if(anim_frame >= 0 && anim_frame < 8)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,31,95,94);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 8 && anim_frame < 16)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,159,95,222);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 16 && anim_frame < 24)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,287,95,350);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 24 && anim_frame < 32)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,415,95,478);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 32)
{
anim_frame = 0;
}
DrawGraphic(GetX, GetY);
}

@Finalize
{
DeleteGraphic(BossImage);
}
}

Code: [Select]
script_enemy_main
{
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
let BossImage = GetCurrentScriptDirectory ~ "servant.png";
let frame = -30;
let frame2 = -30;
let anim_frame = 0;
let Angle = 0;
let Angle2 = 0;
let ShotSFX = "script\sfx\shot.wav";
let LaserSFX = "script\sfx\laser.wav";
let PrevLife = 200;

@Initialize
{
shotinit;
LoadGraphic(BossImage);
SetLife(200);
SetDamageRate(100, 100);
//SetDamageRateEx(100,100,100,40);
}

@MainLoop
{
SetCommonData("Life", GetLife() - PrevLife);
SetX(GetEnemyX + GetArgument[0]);
SetY(GetEnemyY + GetArgument[1]);
anim_frame++;
SetCollisionA(GetX(),GetY(),32);
SetCollisionB(GetX(),GetY(),24);
PrevLife = GetLife();
if(frame == 0)
{
if(GetArgument[2] == 0)
{
CreateShot01(GetX, GetY, 5, 90, RED05, 5);
}
if(GetArgument[2] == 1)
{
CreateShot01(GetX, GetY, 5, 87, RED11, 5);
CreateShot01(GetX, GetY, 5, 100, RED11, 5);
CreateShot01(GetX, GetY, 5, 115, RED11, 5);
}
if(GetArgument[2] == 2)
{
CreateShot01(GetX, GetY, 5, 93, RED11, 5);
CreateShot01(GetX, GetY, 5, 80, RED11, 5);
CreateShot01(GetX, GetY, 5, 65, RED11, 5);
}
if(GetArgument[2] == 3)
{
CreateShot01(GetX, GetY, 5, 115, RED11, 5);
CreateShot01(GetX, GetY, 5, 135, RED11, 5);
CreateShot01(GetX, GetY, 5, 157, RED11, 5);
}
if(GetArgument[2] == 4)
{
CreateShot01(GetX, GetY, 5, 65, RED11, 5);
CreateShot01(GetX, GetY, 5, 45, RED11, 5);
CreateShot01(GetX, GetY, 5, 22, RED11, 5);
}
frame = -10;
}
if(frame2 == 0)
{
if(GetArgument[2] == 0)
{
loop(6)
{
CreateShotA(0, GetX, GetY, 5);
SetShotDataA(0, 0, 5, Angle, 1, 0, 0, RED01);
SetShotDirectionType(PLAYER);
SetShotDataA(0, 30, 5, 0, 0, 0, 0, RED01);
FireShot(0);
SetShotDirectionType(ABSOLUTE);
Angle += 60;
}
}
frame2 = -30;
}
frame++;
frame2++;
}

@DrawLoop
{
SetTexture(BossImage);
if(anim_frame >= 0 && anim_frame < 8)
{
SetGraphicRect(1,40,31,56);
}
if(anim_frame >= 8 && anim_frame < 16)
{
SetGraphicRect(33,40,63,57);
}
if(anim_frame >= 16 && anim_frame < 24)
{
SetGraphicRect(65,40,95,57);
}
if(anim_frame >= 24 && anim_frame < 32)
{
SetGraphicRect(97,40,127,57);
}
if(anim_frame >= 32)
{
anim_frame = 0;
}
DrawGraphic(GetX, GetY);
}

@Finalize
{
if(GetArgument[2] == 0)
{
SetCommonData("Fami1", 1);
}
if(GetArgument[2] == 1)
{
SetCommonData("Fami2", 1);
}
if(GetArgument[2] == 2)
{
SetCommonData("Fami3", 1);
}
if(GetArgument[2] == 3)
{
SetCommonData("Fami4", 1);
}
if(GetArgument[2] == 4)
{
SetCommonData("Fami5", 1);
}
DeleteGraphic(BossImage);
}
}


(For the picture files, get them from CtC, as that's where the ones I'm using are from.)

Okay, so the problem is, no matter what I do, shooting the bats will NOT damage the boss. I started with SetDamageRateEx, as that worked with an enemy spawned by a spellcard I made, but that didn't do anything, so I decided to fall back to my old method of AddLife and Common Data, but THAT doesn't do anything, either! Like despite setting it, it's ALWAYS zero. I KNOW that it works, because it worked on that other enemy I previously mentioned, before I realized exactly what SetDamageRateEx did, but why is it not working for THIS enemy? I don't want the player to have to destroy the bats before they can hit Remilia, because that would pretty much MAKE them run out of time, because the bats are blocking your attacks on Remilia...thus, it takes far too long to be able to slightly hurt her. Help, please? (Also, there's a reason the life is 2120- it's a bit of a joke. Kudos to you if you can actually figure out its meaning. Without help.)


EDIT: I just realized why the AddLife method isn't working: Because I'm spawning five Bats! Each is returning 0 on life difference when not being attacked, so if you're not attacking all at once, you're not hurting Remilia! Easy fix! But I doubt that's why SetDamageRateEx is failing...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on June 18, 2009, 01:14:57 AM
Basically I was wondering if it was possible to do something like

ascent(i in 1..20){
   somethingsomestuffblahblahcode(ry... GetCurrentScriptDirectory ~ "i.png";}

I was thinking if there was a way so I can get the "i" in "i.png" to work with ascent so I don't have to take up 20 lines (or more) to load stuff.

I just played around with code for a few minutes, and here's the solution.  There's two pieces to it.

Piece 1: A function to get an integer to a string

You can normally translate a number to a string by using ToString().  However, that always leaves several decimal places, even if it doesn't need them (for instance, the number 1 gets written as "1.0000000" or such).

However, I wrote this little function to get only the part before the decimal point:

Code: [Select]
// IntString()
// Takes as an argument a single number.
// Returns the integer part of that number, as a string.
// By Nuclear Cheese
function IntString(number)
{
   let str = ToString(number);
   let str2 = "";
   let i = 0;
   while (str[i] != '.')
   {
      str2 = str2 ~ [str[i]];
      i++;
   }
   return(str2);
}

I think I first wrote this function for the (now defunct :-\) EoAD project we had going for a while.  Basically, you pass it a number, and it returns the string equivalent, without the decimal places.

Calling IntString(1) will return the string "1"

Note: in case you don't know, you put the function declaration (the above code) inside your script_enemy_main or script_stage_main, but outside of any of the more specific pieces such as @MainLoop ... so it looks something like this:
Code: [Select]
script_enemy_main
{
   function IntString()
   {
      // The above code.
   }

   @Initialize
   {
      // Setup stuff.
   }

   @MainLoop
   {
      // Fun stuff.
   }

   @DrawLoop
   {
      // Ooh shiny!
   }

   @Finalize
   {
      // Stuff go boom.
   }
}


Piece 2: Generating the file names

With the before piece of code in place, your code for creating the file names becomes something like this:

Code: [Select]
ascent (i in 1..20)
{
   let file_name = GetCurrentScriptDirectory() ~ IntString(i) ~ ".png";
   // do stuff with the file name
}

This will generate file names "1.png", "2.png", etc in the current directory, and then do whatever you need with them.


I hope this helps!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on June 18, 2009, 03:16:47 AM
Basically I was wondering if it was possible to do something like

ascent(i in 1..20){
   somethingsomestuffblahblahcode(ry... GetCurrentScriptDirectory ~ "i.png";}

I was thinking if there was a way so I can get the "i" in "i.png" to work with ascent so I don't have to take up 20 lines (or more) to load stuff.

I just played around with code for a few minutes, and here's the solution.  There's two pieces to it.

Piece 1: A function to get an integer to a string

You can normally translate a number to a string by using ToString().  However, that always leaves several decimal places, even if it doesn't need them (for instance, the number 1 gets written as "1.0000000" or such).

However, I wrote this little function to get only the part before the decimal point:

Code: [Select]
// IntString()
// Takes as an argument a single number.
// Returns the integer part of that number, as a string.
// By Nuclear Cheese
function IntString(number)
{
   let str = ToString(number);
   let str2 = "";
   let i = 0;
   while (str[i] != '.')
   {
      str2 = str2 ~ [str[i]];
      i++;
   }
   return(str2);
}

I think I first wrote this function for the (now defunct :-\) EoAD project we had going for a while.  Basically, you pass it a number, and it returns the string equivalent, without the decimal places.

Calling IntString(1) will return the string "1"

Note: in case you don't know, you put the function declaration (the above code) inside your script_enemy_main or script_stage_main, but outside of any of the more specific pieces such as @MainLoop ... so it looks something like this:
Code: [Select]
script_enemy_main
{
   function IntString()
   {
      // The above code.
   }

   @Initialize
   {
      // Setup stuff.
   }

   @MainLoop
   {
      // Fun stuff.
   }

   @DrawLoop
   {
      // Ooh shiny!
   }

   @Finalize
   {
      // Stuff go boom.
   }
}


Piece 2: Generating the file names

With the before piece of code in place, your code for creating the file names becomes something like this:

Code: [Select]
ascent (i in 1..20)
{
   let file_name = GetCurrentScriptDirectory() ~ IntString(i) ~ ".png";
   // do stuff with the file name
}

This will generate file names "1.png", "2.png", etc in the current directory, and then do whatever you need with them.


I hope this helps!
Perfect :D


I wonder if it's possible to do something like this with varaible names as well...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 18, 2009, 04:29:19 AM
New question: Is there ANY way I can make BOTH the 3rd and last parameters of SetLaserDataA, related to angles, angle towards the player's location? For some reason, SetShotDirectionType(PLAYER) only affects the last parameter, which determines WHERE it goes! However, I also want the laser to be angled VISUALLY towards the player, too! Nothing I do will get me this. I can use atan2 and GetAngleToPlayer, but from what I heard, those only return correctly for these bullets and lasers (or at all, for that matter) on the exact frame you create them on! Therefore, I cannot find a single way to make the laser aim at the player. I want to avoid using objects if possible, though. Is there a way to use CreateLaserA and have both angles aim towards the player?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on June 18, 2009, 04:50:02 AM
SetShotDirectionType(PLAYER) is the only way to get CreateShot/LaserA to dynamically calculate the angle to the player, so if that doesn't work, no. You'll have to make an object laser.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on June 18, 2009, 03:47:34 PM
is there any way i can use alpha values on images that are additive blended? I want to create something like reimu's shadow in IN. i use a task and i had to put the yield in the drawloop so when you press the spacebar all is screwed.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 19, 2009, 05:52:03 PM
SetShotDirectionType(PLAYER) is the only way to get CreateShot/LaserA to dynamically calculate the angle to the player, so if that doesn't work, no. You'll have to make an object laser.

Okay, I made the Object Laser, but I overlooked one thing: You can't set a speed on a laser. If you do, it ignores it. I need a way to make it move towards the player's position at the time it was thrown. I tried using the gravity thing that I asked for earlier in this thread, but every time I try to reverse any part of it to where it's affecting the ENEMY instead of the player, everything messes up! When used on this laser...

-If you're directly below the boss, nothing happens to the laser other than it centers on the boss's X, but the source goes behind the boss. What.
-If you're off in the far corners, the laser mysteriously vanishes.


Here's the script:

Code: [Select]
#TouhouDanmakufu
#Title[Scarlet Sign "Gungnir Windmill"]
#Text[]
#Image[]
#BackGround[Default]
#PlayLevel[]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
let BossImage = GetCurrentScriptDirectory ~ "boss_remilia.png";
let BossCutIn = GetCurrentScriptDirectory ~ "Remilia.png";
let frame = -100;
let frame2 = -100;
let anim_frame = 0;
let Angle = 90;
let Angle2 = 90;
let ShotSFX = "script\sfx\shot.wav";
let LaserSFX = "script\sfx\laser.wav";
let IsGungnir = false;
let Gungnir = [];
let IsThrow = false;
let Distance = 0;
let LasAng = 0;
let LasSpd = 2;

task GungnirSpin
{
let i = 0;
while (i < length(Gungnir))
{
if (Obj_BeDeleted(Gungnir[i]))
{
Gungnir = erase(Gungnir, i);
i--;
}
else if(IsThrow)
{
Obj_SetX(Gungnir[i], (GetX - (Distance - LasSpd)*cos(LasAng))); //LasSpd FOR X!
Obj_SetY(Gungnir[i],(GetY - (Distance - LasSpd)*sin(LasAng))); //LasSpd FOR Y!
}
else if(frame < 381 && frame > -1)
{
if(frame < 240)
{
Obj_SetAngle(Gungnir[i], Obj_GetAngle(Gungnir[i]) + 3);
}
if(frame == 240)
{
Obj_SetAngle(Gungnir[i], 270);
}
if(frame == 380)
{
LasAng = atan2(GetPlayerY - Obj_GetY(Gungnir[i]), GetPlayerX - Obj_GetX(Gungnir[i])); //ANGLE FORMULA!
Distance = ((Obj_GetX(Gungnir[i]) - GetPlayerX)^2 + (Obj_GetY(Gungnir[i] - GetPlayerY)^2)^0.5); //DISTANCE FORMULA!
Obj_SetAngle(Gungnir[i], atan2(GetPlayerY - Obj_GetY(Gungnir[i]), GetPlayerX - Obj_GetX(Gungnir[i])));
IsThrow = true;
}
}
i++;
}
}

@Initialize
{
shotinit;
LoadGraphic(BossImage);
SetLife(400);
SetDamageRate(10,5);
SetTimer(62);
SetInvincibility(30);
CutIn(YOUMU, "Devil Sign "\""Scarlet Streak"\", BossCutIn, 0, 0, 256, 320);
SetScore(70000);
SetEnemyMarker(true);
MagicCircle(true);
SetMovePosition02(GetCenterX,90,30);
CreateEnemyFromFile(GetCurrentScriptDirectory ~ "LaserEnem.txt", GetCenterX, GetCenterY, 0, 0, 0);
}

@MainLoop
{
GungnirSpin;
anim_frame++;
SetShotAutoDeleteClip(200, 200, 200, 200);
SetCollisionA(GetX(),GetY(),32);
SetCollisionB(GetX(),GetY(),24);
if(frame == 0)
{
IsGungnir = true;
let obj = Obj_Create(OBJ_LASER);
ObjLaser_SetLength(obj, 300);
ObjLaser_SetWidth(obj, 30);
Obj_SetPosition(obj, GetX+10, GetY-5);
Obj_SetAngle(obj, 270);
Gungnir = Gungnir ~ [obj];

}
if(frame2 == 380)
{
IsGungnir = false;
frame2 = -40;
}
frame++;
frame2++;
}

@DrawLoop
{
SetTexture(BossImage);
if(anim_frame >= 0 && anim_frame < 8)
{
if(GetSpeedX()==0 && !IsGungnir)
{
SetGraphicRect(31,31,95,94);
}
else if(GetSpeedX()>0 && !IsGungnir)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0 || IsGungnir)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 8 && anim_frame < 16)
{
if(GetSpeedX()==0 && !IsGungnir)
{
SetGraphicRect(31,159,95,222);
}
else if(GetSpeedX()>0 && !IsGungnir)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0 || IsGungnir)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 16 && anim_frame < 24)
{
if(GetSpeedX()==0 && !IsGungnir)
{
SetGraphicRect(31,287,95,350);
}
else if(GetSpeedX()>0 && !IsGungnir)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0 || IsGungnir)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 24 && anim_frame < 32)
{
if(GetSpeedX()==0 && !IsGungnir)
{
SetGraphicRect(31,415,95,478);
}
else if(GetSpeedX()>0 && !IsGungnir)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0 || IsGungnir)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 32)
{
anim_frame = 0;
}
DrawGraphic(GetX, GetY);
}

@Finalize
{
DeleteGraphic(BossImage);
}
}

The enemy that comes with it can be ignored if you choose, but here's its code, anyways:

Code: [Select]
script_enemy_main
{
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
let BossImage = GetCurrentScriptDirectory ~ "servant.png";
let frame = -60;
let frame2 = -120;
let Angle = 60;
let Angle2 = 0;
let ShotSFX = "script\sfx\shot.wav";
let LaserSFX = "script\sfx\laser.wav";

@Initialize
{
shotinit;
LoadGraphic(BossImage);
SetLife(200);
SetDamageRate(100, 100);
}

@MainLoop
{
if(frame == 0)
{
CreateLaserB(0, 200, 20, RED01, 60);
SetLaserDataB(0, 0, 0, 100, 0, 60, 2, 208, 2);
FireShot(0);

CreateLaserB(1, 200, 20, RED01, 60);
SetLaserDataB(1, 0, 0, 100, 0, 180, 2, 328, 2);
FireShot(1);

CreateLaserB(2, 200, 20, RED01, 60);
SetLaserDataB(2, 0, 0, 100, 0, 300, 2, 88, 2);
FireShot(2);
}
if(frame2 == 0)
{
CreateShotA(0, GetX, GetY, 5);
SetShotDataA(0, 0, 4, Angle, -1, 0, 0, SP02);
CreateShotA(1, GetX, GetY, 5);
SetShotDataA(1, 0, 4, Angle+120, -1, 0, 0, SP02);
CreateShotA(2, GetX, GetY, 5);
SetShotDataA(2, 0, 4, Angle+240, -1, 0, 0, SP02);
SetShotKillTime(0, 360);
SetShotKillTime(1, 360);
SetShotKillTime(2, 360);
FireShot(0);
FireShot(1);
FireShot(2);
Angle += 13;
frame2 = -3;
}
frame++;
frame2++;
}

@DrawLoop
{
SetTexture(BossImage);
SetGraphicRect(7,165,8,166);
DrawGraphic(GetX, GetY);
}

@Finalize
{
DeleteGraphic(BossImage);
}
}

I'd appreciate ANY help you can give me on getting this to throw at the player at a certain speed (I want speed 8 here). Thanks...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: randomdragoon on June 19, 2009, 07:05:15 PM
SetShotDirectionType(PLAYER) is the only way to get CreateShot/LaserA to dynamically calculate the angle to the player, so if that doesn't work, no. You'll have to make an object laser.

You can use atan2(Y-GetPlayerY, GetPlayerX-X) to dynamically get the direction to the player, no? Where X and Y are the coordinates where the bullet starts from.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on June 19, 2009, 10:57:49 PM
You can use atan2(Y-GetPlayerY, GetPlayerX-X) to dynamically get the direction to the player, no? Where X and Y are the coordinates where the bullet starts from.
Not with SetShotDataA. It will always give you the angle for the time the bulelt is fired, not for the time when this angle should actually be evaluated.


@ Pikaguy:
Simple.
obj=id of the object
v=movement speed
ang=movement angle

Put this in the while loop:
Code: [Select]
Obj_SetPosition(obj, Obj_GetX(obj)+v*cos(ang),  Obj_GetY(obj)+v*sin(ang));
That should work.  ;)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 20, 2009, 12:22:51 AM
@ Pikaguy:
Simple.
obj=id of the object
v=movement speed
ang=movement angle

Put this in the while loop:
Code: [Select]
Obj_SetPosition(obj, Obj_GetX(obj)+v*cos(ang),  Obj_GetY(obj)+v*sin(ang));
That should work.  ;)

Oh wow, and I actually already had that code from when I tried to spin things around a point. Never realized I could use it like THAT. ...nor did I even think to use it at all in this situation... I'll remember this for the next time I need to manually move something to a specific point. Thanks!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 21, 2009, 11:02:16 PM
Sorry to doublepost, but I need help badly...

Code: [Select]
#TouhouDanmakufu
#Title[Red Magic]
#Text[]
#Image[]
#BackGround[Default]
#PlayLevel[]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
let BossImage = GetCurrentScriptDirectory ~ "boss_remilia.png";
let BossCutIn = GetCurrentScriptDirectory ~ "Remilia.png";
let frame = -100;
let frame2 = -100;
let frame3 = -100;
let frame4 = -100;
let frame5 = -100;
let anim_frame = 0;
let Angle = 0;
let Angle2 = 0;
let Angle3 = 0;
let Timer = [];
let Wave = [];
let ShotSFX = "script\sfx\se_tan00.wav";
let LaserSFX = "script\sfx\se_lazer00.wav";
let RedMagic = [];
let RedMagic2 = [];
let Bounce = [];
let DoRedMagic = false;
let Count = -1;
let yes = 0;

task Reflect
{
let i = 0;
while (i < length(RedMagic))
{
if (Obj_BeDeleted(RedMagic[i]))
{
RedMagic = erase(RedMagic, i);
Bounce = erase(Bounce, i);
Timer = erase(Timer, i);
i--;
}
else if(Bounce[i] > 0)
{
if(Obj_GetX(RedMagic[i]) <= GetClipMinX() || Obj_GetX(RedMagic[i]) >= GetClipMaxX())
{
Obj_SetAngle(RedMagic[i], 180-Obj_GetAngle(RedMagic[i]));
Bounce[i] = Bounce[i] - 1;
}
if(Obj_GetY(RedMagic[i]) <= GetClipMinY() || Obj_GetY(RedMagic[i]) >= GetClipMaxY())
{
Obj_SetAngle(RedMagic[i], 360-Obj_GetAngle(RedMagic[i]));
Bounce[i] = Bounce[i] - 1;
}
if(frame4%15 == 0)
{
if(Timer[i] < 15)
{
Timer[i] = 138;
}
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, Obj_GetX(RedMagic[i]), Obj_GetY(RedMagic[i]));
Obj_SetAngle(obj, (Angle + Angle2) + Angle3);
Obj_SetSpeed(obj, 0);
ObjShot_SetDelay(obj, 40);
ObjLaser_SetWidth(obj, Count);
ObjShot_SetGraphic(obj, RED01);
RedMagic2 = RedMagic2 ~ [obj];
if(Timer[i] > 108 && Count > 0)
{
Wave = Wave ~ [Count-1];
}
else{Wave = Wave ~ [Count];}
Angle3 += 2;
Timer[i] =  Timer[i] - 15;
}
}
i++;
}
}

task Red
{
let i = 0;
while (i < length(RedMagic2))
{
if(Wave[i] != Count)
{
yes = Wave[i];
}
if (Obj_BeDeleted(RedMagic2[i]) || frame5 == 210)
{
RedMagic2 = erase(RedMagic2, i);
Wave = erase(Wave, i);
i--;
}
else if(frame5 >= 180 && Wave[i] == Count - 1)
{
if(frame5 < 210)
{
Obj_SetAngle(RedMagic2[i], Obj_GetAngle(RedMagic2[i]) + 3);
}
if(Obj_GetSpeed(RedMagic2[i]) < 1)
{
Obj_SetSpeed(RedMagic2[i], Obj_GetSpeed(RedMagic2[i]) + 0.2);
}
}
i++;
}
}

@Initialize
{
shotinit;
LoadGraphic(BossImage);
SetLife(1000);
SetDamageRate(10,5);
SetTimer(202);
SetInvincibility(30);
CutIn(YOUMU, "Red Magic", BossCutIn, 0, 0, 256, 320);
SetScore(70000);
SetEnemyMarker(true);
MagicCircle(true);
SetMovePosition02(GetCenterX,90,30);
}

@MainLoop
{
Reflect;
Red;
anim_frame++;
SetCollisionA(GetX(),GetY(),32);
SetCollisionB(GetX(),GetY(),24);
if(frame2 == 0)
{
Count++;
loop(10)
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, GetX, GetY);
Obj_SetAngle(obj, Angle + Angle2);
Obj_SetSpeed(obj, 2);
ObjShot_SetGraphic(obj, PURPLE03);
RedMagic = RedMagic ~ [obj];
Bounce = Bounce ~ [1];
Timer = Timer ~ [138];
Angle += 36;
}
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, GetX, GetY);
Obj_SetAngle(obj, Angle);
Obj_SetSpeed(obj, 0);
ObjShot_SetDelay(obj, 30);
ObjShot_SetGraphic(obj, RED01);
RedMagic2 = RedMagic2 ~ [obj];
if(Count == 0)
{
Wave = Wave ~ [Count-1];
}
else{Wave = Wave ~ [Count];}
Angle2 += 7;
frame2 = -180;
SetMovePositionRandom01(65, 20, 10, GetClipMinX + 50, GetClipMinY + 50, GetClipMaxX - 50, GetClipMinY + 170);
}
if(frame5 == 210)
{
frame5 = 30;
}
frame++;
frame2++;
frame3++;
frame4++;
frame5++;
}

@DrawLoop
{
SetTexture(BossImage);
if(anim_frame >= 0 && anim_frame < 8)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,31,95,94);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 8 && anim_frame < 16)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,159,95,222);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 16 && anim_frame < 24)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,287,95,350);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 24 && anim_frame < 32)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,415,95,478);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 32)
{
anim_frame = 0;
}
DrawGraphic(GetX, GetY);
DrawText(ToString(yes), GetPlayerX + 20, GetPlayerY, 15, 255);
}

@Finalize
{
DeleteGraphic(BossImage);
}
}

I'm trying to copy Red Magic, as you can see, though I don't care about it being perfect. (Too many people may have great experience foiling Red Magic, after all!) Anyways, my problem is that Count variable. Despite the debug DrawText I used (I picked "yes" as a variable for no reason whatsoever), I cannot pinpoint the problem... See, I'm using Count as a wave counter, so bullets from the previous wave don't change angles when the next wave moves, if they're still onscreen at that time. However, when the next wave is spawned, the inner 2 or 3 rings, counting the center bullet, DON'T MOVE! I can't figure out why! I seriously need help with this, please!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 21, 2009, 11:49:55 PM
The last few bullets of a wave will also not move on occasion, if that helps your debugging process. I can't see the problem either, though I'm having a hard time wrapping my head around the cavalcade of arrays you've constructed...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 22, 2009, 12:56:20 AM
The last few bullets of a wave will also not move on occasion, if that helps your debugging process. I can't see the problem either, though I'm having a hard time wrapping my head around the cavalcade of arrays you've constructed...

Oh yeah, that's intentional, somewhat. The original Red Magic did that for some bullets, too. And sorry about the arrays... Is there anything I can do to help with that?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 22, 2009, 02:12:26 AM
Not at all, it's my fault -- I just don't work with arrays beyond selecting a random color for a bullet, so this is a bit advanced for me. Hopefully I can get the jist of it enough to understand what's going on in your txt file... If somebody else doesn't first, hehe.

EDIT: A possible workaround is to have the bullets force move into a NULL angle (or random, failing that) after a set period of time after spawning, at least to prevent them from staying on the screen. I'm not seeing what's making them not move properly though.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on June 22, 2009, 03:02:28 AM
For some odd reason or another, when I used some part of a code in two different scripts, the same result does not occur.


Code: [Select]
#TouhouDanmakufu
#Title[Blazing Wheel of Hell]
#Text[Round and Round it goes. When it stops, nobody knows.]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_remilia.png";

let count = 540;
let count2 = -120;

@Initialize {
SetLife(2500);
SetTimer(60);
SetScore(10000000);

SetMovePosition02(225, 200, 60);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 100, 100);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);
SetShotAutoDeleteClip(400, 400, 400, 400);

if(count == 600) {
ascent( i in 0..1050)
{
                CreateShotA(i, GetX, GetY, 10);
                SetShotDataA(i, 0+i*0.5, 2, i*93, 0, -0.05, 0, RED04);
                SetShotDirectionType(PLAYER);
                SetShotDataA(i, 60+i*0.5, 3, 0, 0, -0.05, 0, RED04);
                SetShotDataA(i, 120+i*0.5, 9, 0, 0, -0.05, 0, RED04);
                SetShotDataA(i, 180+i*0.5, 9, 0, 0, 0, 9, RED04);
                SetShotDirectionType(ABSOLUTE);
                FireShot(i);
}
count=0;
}



if(count2 == 60){
ascent( j in 0..9)
{
                CreateShotA(j, GetX, GetY, 10);
                SetShotDirectionType(ABSOLUTE);
                SetShotDataA(j, 0, 2, rand(0, 360), 0, -0.05, 0.5, GREEN01);
                SetShotDirectionType(ABSOLUTE);
                FireShot(j);
}
count2 = 0;
}

count++;
count2++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}

Code: [Select]
#TouhouDanmakufu
#Title[Spawn Test]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_remilia.png";

let count = 0;
let a = 0;

@Initialize {
SetLife(2500);
SetTimer(60);
SetScore(10000000);

SetMovePosition01(GetCenterX, GetClipMinY + 120, 120);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 100, 100);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 60) {
ascent( i in 0..120)
{
                CreateShotA(i, GetX + 100*cos(a), GetY + 100*sin(a), 10);
                SetShotDataA(i, i*0.5, 2, i*37.01, 0, 0, 2, GREEN01);
                SetShotDirectionType(ABSOLUTE);
                FireShot(i);

a += 37.01;
}
count=0;
}


count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}

Code: [Select]
#TouhouDanmakufu
#Title[Spawn 3]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_remilia.png";

let count = 0;
let a = 0;

@Initialize {
SetLife(2500);
SetTimer(60);
SetScore(10000000);

SetMovePosition01(GetCenterX, GetClipMinY + 120, 120);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 100, 100);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 60) {
ascent( i in 0..120)
{
                CreateShotA(i, GetX + 100*cos(a), GetY + 100*sin(a), 10);
                SetShotDataA(i, 0+i*0.5, 0, i*a, 0, 0, 0, GREEN01);
                SetShotDataA(i, 30+i*0.5, 2, i*a, 0, 0, 2, GREEN01);
                SetShotDirectionType(ABSOLUTE);
                FireShot(i);

a += 33;
}
count=0;
}


count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}




See, in the first script, all of the bullets in | ascent( i in... ) | appear in their delayed order, while the bullets in the second and third scripts in the same area appear all at once as red bullets, THEN start to fire off in their order of delay. I want the second and third scripts to function like the first script. Why are they all appearing at once instead of individually?




Or how do I at least make it so that the first/whichever bullet in the i.d. changes angle as well?

Take this script, for example. Half of the bullets are thrown around in a ribbon in varied angles, while the other half of the bullets fly directly to the right, i.e. angle 0:

Code: [Select]
#TouhouDanmakufu
#Title[Spawn 4]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_remilia.png";

let count = -60;
let a = 0;

@Initialize {
SetLife(2500);
SetTimer(60);
SetScore(10000000);

SetMovePosition01(GetCenterX, GetClipMinY + 120, 120);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 100, 100);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 1) {
ascent( i in 0..2)
{
                CreateShotA(i, GetX + 100*cos(a), GetY + 100*sin(a), 10);
                SetShotDataA(i, i*0.5, 2, i*a, 0, 0, 2, GREEN01);
                SetShotDirectionType(ABSOLUTE);
                FireShot(i);

a += 13.01;
}
count=0;
}


count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 22, 2009, 03:24:30 AM
Do not multiply your delay field by a decimal, make sure that the number in the second parameter of SetShotDataA is an integer greater than or equal to 0 or it will not function properly. Because your delay comes out to a decimal fairly often, it does wierd stuff (don'tcha wish it just flagged an error, like when you try to make it negative?). Also note that you should always called the bullet's motion as it spawns (the 0th frame), or even more wierd stuff could happen. The reason for the former is because you can't tell Danmakufu to process something on a half frame. Multiply your second parameter by a positive integer and it should actually give you results, however correct or otherwise they may be.

At least I think that's what's happening. Colon backslash forwardslash.

Wait, no, this is fucked. I must be really tired.

Oh fucking ass buckets I'm an idiot. When you ascent(i in 0..2) for the last script, the first numerical value you place on i is 0, which is multiplied in your angular parameter and thus gives you an angle of 0. You could say (i+1)*a so that the first bullet will still have an angle other than 0.


Agghhh that was so simple. Time for sleep.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on June 22, 2009, 03:45:06 AM
Well, I don't want the bullets to delay that long before appearing and firing (every frame). Say, in the second script's case, I want the bullets to appear where they are, but I want all 120 of the bullets to appear within 60 frames.

That is why I asked the latter, second question at the bottom of my previous post, because that is what led me to asking the first question in the first place.


However, the explanation in the bottom half of your post really helped and worked. Thank you.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 22, 2009, 06:12:32 PM
Not at all, it's my fault -- I just don't work with arrays beyond selecting a random color for a bullet, so this is a bit advanced for me. Hopefully I can get the jist of it enough to understand what's going on in your txt file... If somebody else doesn't first, hehe.

EDIT: A possible workaround is to have the bullets force move into a NULL angle (or random, failing that) after a set period of time after spawning, at least to prevent them from staying on the screen. I'm not seeing what's making them not move properly though.

Thanks for the idea, but I FINALLY solved my problem. I realized that the problem was that at frame5 == 210, I was deleting some of the bullets in the arrays, thus, this screwed up some things. After removing that and some other things I did to kinda counter that, I finally had it fixed.


Oh, and after changing the thing in the RedMagic task about Bounce > 0 to where it affects the code that makes the orbs bounce off the walls and NOT the code spawning the small, red bullets, the spellcard suddenly became difficult. Heh heh heh... PERFECT.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: stillsatellite on June 23, 2009, 07:03:05 AM
Hello, I have a question regarding Danmakufu...

How would you make a bit of a code that affects all of the bullets on the screen, regardless of the type of bullet used?

For example, if I wanted all of the bullets onscreen to change speed, how would I do that?

 
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on June 23, 2009, 07:13:46 AM
Quote
How would you make a bit of a code that affects all of the bullets on the screen, regardless of the type of bullet used?

For example, if I wanted all of the bullets onscreen to change speed, how would I do that?

Sorry, there are no functions of this sort. Different bullet functions are processed in different ways, and generally you cannot affect a non-object bullet after it's been fired. Either you're going to need to set up all your bullets as CreateShotA with data that will cause them all to change speed at the same time, or you're going to need to make them all object bullets that use a global variable to determine when to change speed.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: stillsatellite on June 23, 2009, 08:52:01 AM
Oh...  D:

Well, thanks anyway.

*Sulks*



*Then starts to code*
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on June 23, 2009, 02:42:57 PM
Hey, I have a question.  What's the difference with
Code: [Select]
#TouhouDanmakufu
#Title[Bullets]
#Text[test script for bullets]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = 0;
    @Initialize {
        SetLife(1000);
        SetEnemyMarker(true);
    }

   @MainLoop {
      SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 24);

        if(frame==60){


            CreateShotA(1, GetX, GetY, 10);
SetShotDataA(1, 0, 5, 0, 2.2, 0, 5, RED03);
SetShotDataA(1, 60, 5, 132, 0, 0.1, 8, RED03);
ascent(i in 1..60){
    CreateShotA(2, 0, 0, 30);
    SetShotDataA_XY(2, 0, rand(-1, 1), rand(-1, -4), 0, 0.1, 0, 3, RED01);
    AddShot(i*2, 1, 2, 0);
    AddShot(i*2, 2, 1, 0);

frame = 0;
}


FireShot(1);


        }


        frame++;

    }

    @DrawLoop {       
    }

    @Finalize {
    }
}

And

Code: [Select]
#TouhouDanmakufu
#Title[Bullets]
#Text[test script for bullets]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = 0;
    @Initialize {
        SetLife(1000);
        SetEnemyMarker(true);
    }

   @MainLoop {
      SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 24);

        if(frame==60){


            CreateShotA(1, GetX, GetY, 10);
SetShotDataA(1, 0, 5, 0, 2.2, 0, 5, RED03);
SetShotDataA(1, 60, 5, 132, 0, 0.1, 8, RED03);
ascent(i in 1..60){
    CreateShotA(2, 0, 0, 30);
    SetShotDataA_XY(2, 0, rand(-1, 1), rand(-1, -4), 0, 0.1, 0, 3, RED01);
    AddShot(i*2, 1, 2, 0);
    AddShot(i*2, 2, 1, 0);


FireShot(1);

frame = 0;
}




        }


        frame++;

    }

    @DrawLoop {       
    }

    @Finalize {
    }
}

I know its the 'FireShot(1);', but why would it make a difference if I'd put it in with the same brackets as 'frame = 0' or outside of them?  What's exactly going on?

Obviously it makes  a huge difference, and I find it confusing as to why.  Any help?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on June 23, 2009, 02:50:25 PM
If it's in the brackets, it's fired every 60 frames since it's only run when frame==60. Outside the brackets, then it gets fired every single frame instead.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on June 23, 2009, 03:35:35 PM
@ Suikama 

Thanks alot.  I see what you mean, that makes things a lot more simple...

Oh, one other question.  I can't seam to get the Boss thing down.  I mean, I can make the boss move and all, but as for the boss graphics and making the boss move in correspondence to the spells etc.
I can only get one image, and it's static.  I want it to be more lifelike, (move arms, lean on air, etc)  What can I do?
Can anyone give me a code or something?  Thanks in advance.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 23, 2009, 04:49:15 PM
You have to get information on which direction the boss is moving, then set an image in correspondance. GetSpeedX will yield a positive value if the boss is moving right, or a negative value if the boss is moving left. If the boss is horizontally stationary, then the value will be 0. So using this information, we can "animate" the boss by changing her graphic depending on her horizontal speed:


@DrawLoop{
SetTexture(BossRumia);
if(GetSpeedX==0){
   SetGraphicRect(0, 0, 64, 64);
}
if(GetSpeedX>0){
   SetGraphicRect(64, 0, 128, 64);
}
if(GetSpeedX<0){
   SetGraphicRect(128, 0, 192, 64);
}
DrawGraphic(GetX, GetY);
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on June 23, 2009, 04:51:36 PM
Oh man I didn't know about GetSpeedX, all this time I've been doing bullshit like checking the direction of random movement and passing variables. D:
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on June 23, 2009, 05:02:11 PM
You have to get information on which direction the boss is moving, then set an image in correspondance. GetSpeedX will yield a positive value if the boss is moving right, or a negative value if the boss is moving left. If the boss is horizontally stationary, then the value will be 0. So using this information, we can "animate" the boss by changing her graphic depending on her horizontal speed:


@DrawLoop{
SetTexture(BossRumia);
if(GetSpeedX==0){
   SetGraphicRect(0, 0, 64, 64);
}
if(GetSpeedX>0){
   SetGraphicRect(64, 0, 128, 64);
}
if(GetSpeedX<0){
   SetGraphicRect(128, 0, 192, 64);
}
DrawGraphic(GetX, GetY);
}

Ahh, thanks, this was helpful, and it worked.  But what if I want to set an animation for when the boss isn't moving, but rather during a spellcard, in correspondance to the bullets.  Like lets say, Mokou's "Immortal Bird Flying Phoenix" spellcard.  How can that be arranged?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on June 23, 2009, 06:19:00 PM
Ahh, thanks, this was helpful, and it worked.  But what if I want to set an animation for when the boss isn't moving, but rather during a spellcard, in correspondance to the bullets.  Like lets say, Mokou's "Immortal Bird Flying Phoenix" spellcard.  How can that be arranged?

Simple. Start a variable to count animation, for example, "anim_frame". Increase this variable as you wish, and in your draw loop, check if it's equal to certain values. If it is, check your GetSpeedX stuff. So like, for me, I tend to increase it every frame, and for things that animate every 4 frames, I check if the value is greater than or equal to 0, but less than 4, then greater than or equal to 4, but less than 8, etc. 4 frames of animation tells me to reset the value at 12, so...

You get the idea, right? I hope I explained it well enough...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on June 23, 2009, 06:46:46 PM

Simple. Start a variable to count animation, for example, "anim_frame". Increase this variable as you wish, and in your draw loop, check if it's equal to certain values. If it is, check your GetSpeedX stuff. So like, for me, I tend to increase it every frame, and for things that animate every 4 frames, I check if the value is greater than or equal to 0, but less than 4, then greater than or equal to 4, but less than 8, etc. 4 frames of animation tells me to reset the value at 12, so...

You get the idea, right? I hope I explained it well enough...

Uh, sort of.  Can you please give me an code example to make it more clear?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on June 23, 2009, 07:01:20 PM
Pikaguy900 is just talking about standard boss animation loops to make the boss seem more life-like (which, by the way, is probably easier to accomplish using modular division.... But I digress). To get the boss to do a standard animation in correspondance to bullets firing (like Mokou's hand raising), you're going to need to do a bit of dicking around. This is only because you can't draw things in the @MainLoop. I find it easier to do this using tasks, but I'll spare you that headache for today and just show you how to using conditional statements in your @MainLoop.

For Mokou, you'll notice that she raises her hand a few frames before she starts firing bullets. So to mimic this, we'll say something like this:

@MainLoop{
frame++;

if(frame==50){
 anim = 1;
}

if(frame==60){
 loop(60){
  CreateShot01(GetX, GetY, 3, GetAngleToPlayer, RED01, 0);
 }
}

if(frame==70){
 loop(60){
  CreateShot01(GetX, GetY, 3, GetAngleToPlayer, RED01, 0);
 }
}

if(frame==80){
 anim = 0;
 frame = 0;
}

}

@DrawLoop{
 SetTexture(boss);
 if(anim==1){
  SetGraphicRect(0, 0, 64, 64);
 }
 if(anim==0){
  SetGraphicRect(64, 0, 128, 64);
 }
}

So this way, we set a variable to equal 1 right before shooting our bullets, then in our @DrawLoop we constantly check for that variable. If it equals a certain value, we set her graphic to be something else, otherwise we set it to her default graphic. Is this understandable? I'm not sure if I'm being clear.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on June 24, 2009, 01:01:33 AM
@Naut

Yes, very clear.  Thanks alot, you've been very helpful.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 03, 2009, 06:25:09 AM
Code: [Select]
#TouhouDanmakufu[Player]
#ScriptVersion[2]
#Menu[Reimu D]
#Text[Hakurei Reimu ?u一点集中攻撃力重視型?v

?uアブソルジョンニードル?v
        ?uAbsolution Needle?v

?u完敗乱舞?v
         ?uWild Annihilation Dance?v]
#Image[.\sl_pl00.png]
#ReplayName[ReimuD]
#include_function ".\common.txt"

script_player_main{

let c = GetCurrentScriptDirectory();
let bNextShot = false;

@Initialize{
LoadGraphic(c~"pl00.png");
LoadPlayerShotData(c~"plshot00.txt");
                                          SetPlayerLifeImage(c~"pl00.png", 222, 302, 234, 314);
SetSpeed(4, 1.5);
}

@MainLoop{
SetIntersectionCircle(GetPlayerX, GetPlayerY, 2);
yield;
}
@Missed{}
@SpellCard{
SetSpeed(4, 1.5);
UseSpellCard("WildAnnihilationDance", 0);
}
@DrawLoop{
SetTexture(c~"pl00.png");
if(IsPressLeft()==true){
SetGraphicRect(240, 73, 275, 150);
}else if(IsPressRight()==true){
SetGraphicRect(248, 126, 272, 176);
}else{
SetGraphicRect(22, 27.5, 42, 60.5);
}
DrawGraphic(GetPlayerX(), GetPlayerY());
}

@Finalize{}
}

script_spell WildAnnihilationDance{

@Initialize{
}
@MainLoop{
}
@Finalize{
}
}
y not workin
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 03, 2009, 09:27:32 PM
#include_function can go outside script_player_main? News to me.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 03, 2009, 10:07:16 PM
Sorry, I meant that it doesn't show up on Danmakufu's list of players.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 03, 2009, 10:45:40 PM
Probably in the wrong folder, it shows up for me.

(http://i641.photobucket.com/albums/uu134/Nautth/ccccccccc.jpg)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 05, 2009, 04:38:12 AM
The problem was that I encoded it in Unicode. Oh well, no Japanese for me, as I can't find a UTF8-to-messy-ANSI converter.

New question, is it actually possible for drawings to overlap things such as bullets and more importantly, the default hitbox? I know Stuffman said some stuff about SetEffectLayer before, but the wiki says it only works with Concentrate, and Josette's hitbox doesn't overlap the default, either.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 05, 2009, 05:29:13 AM
When I was talking about layers earlier we were talking about whether it was possible to draw on top of the frame, which it's not; however for any layer below that, SetEffectLayer or whatever it's called works fine. So you can draw on different layers but they have to be effect objects.

I don't know what layer the default hitbox dot is on, I'll have to try that as a workaround.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 06, 2009, 12:48:26 AM
Oh dammit, then. Well, originally I was painfully making Effect Objects, but I found that I couldn't rotate them properly at all because of the xyz coordinates. But if the only way to get the nice hitbox is make an effect object...

Then again, I might be able to make an object bullet with no collision and a hitbox graphic. That might work.


I'm making a perfect UFO-style Reimu. I have the option movement patterns, option rotation, entire neutral sprite animation, right sprite, left sprite, and the focus circle complete with bouncing entry and such. It's makes me squeal every time I finish something.
EDIT:
(http://img269.imageshack.us/img269/1071/68993540.png)
atai wa genius desu
EDIT: Gonna need super tweaking. When it rotates it ends up going in a small circle, or when I press a direction it gets set off. Probably because it goes before MainLoop instead of after...?
EDIT: Practically, it works well. I need to get rid of the other hitbox graphic, though.


EDIT: Er, how exactly would I go about using an image that when it's loaded, is already turned on it's side? I'm using a shot graphic from Reimu's sheet that's turned 90 degrees, and I need it straight. Obviously without editing the sprite sheet as I don't want to calculate new coordinates for everything. I tried graphic_rotation even though I knew it wouldn't work, but eh.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 06, 2009, 02:12:56 AM
ObjEffect_SetAngle(object id, x angle, y angle, z angle);

???

Alternatively, yeah, you'll need to edit the spritesheet and calculate new verticies. This is why I don't do object effects.


EDIT:

And uh...
I don't know what layer the default hitbox dot is on, I'll have to try that as a workaround.

Layer three, unfortunately. With the rest of the damn sprite. It's under items (4), bullets (5), events (6) and the foreground (7). If you guys are making a better hitbox, might I recommend layer 6 or 7, so that it is above mostly everything (think Okuu, Hell's Tokamak Reactor, lots of Additive blends and shit but your hitbox is still clearly visible above everything. Like that). That would be my personal choice, anyway.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 06, 2009, 05:53:30 AM
By the way controlling the hitbox as an Object Bullet lets it stay above all the danmaku and the default hitbox like it should be.

<3

But yeah goddammit and stuff
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 06, 2009, 08:01:27 AM
I have been fooling around with the @DrawLoop section in scripts to add the animating spellcircle for my cards. As I am a person of paying more attention to detail, I was wonder HOW THE HELL do you make your sprites animate in appearance?
(http://i41.tinypic.com/1zznk3s.jpg)

Just like every Touhou game the bosses/chars have sprite ranges for animating. But whatever I seem to do it won't work proper.

I tried already to make it animate with counting frames. Rough example below:

Code: [Select]
if(frame == 20) { SetGraphicRect(1st sprite in animation range) }
if(frame == 40) { SetGraphicRect(2nd sprite in animation range) }

But I fail horribly at it. What is the method for using a range of sprites to make it animate?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 06, 2009, 03:21:22 PM
I think the only problem with your way is that the GraphicRect has to be chosen anew every time the sprite is drawn, so you have to change first "==" to "<=" and add as a second condition for the second one for the variable to be higher than twenty. It should work out fine, then.

Code: [Select]
if(frame <= 20) { SetGraphicRect(1st sprite in animation range) }
if(frame <= 40&&frame>20) { SetGraphicRect(2nd sprite in animation range) }

Or maybe it won't, I have no idea. But that is what I would try.  :V
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 06, 2009, 05:11:12 PM
Code: [Select]
@DrawLoop{
SetTexture(c~"pl00.png");
SetAlpha(255);
SetGraphicScale(1,1);

//Draw player
SetGraphicAngle(0,0,0);
if(IsPressRight()==true){
SetGraphicRect(228, 102, 260, 146);
}else if(IsPressLeft()==true){
SetGraphicRect(230, 53, 261, 97);
}else{
if(drawcount<10){SetGraphicRect(5, 3, 38, 51);}
if(drawcount>=10 && drawcount<20){SetGraphicRect(37, 3, 70, 51);}
if(drawcount>=20 && drawcount<30){SetGraphicRect(69, 3, 102, 51);}
if(drawcount>=30 && drawcount<40){SetGraphicRect(101, 3, 134, 51);}
if(drawcount>=40 && drawcount<50){SetGraphicRect(134, 3, 165, 51);}
if(drawcount>=50 && drawcount<60){SetGraphicRect(165, 3, 198, 51);}
if(drawcount>=60 && drawcount<70){SetGraphicRect(198, 3, 229, 51);}
if(drawcount>=70 && drawcount<80){SetGraphicRect(228, 3, 262, 51);}
}
DrawGraphic(GetPlayerX, GetPlayerY);

drawcount++;
if(drawcount>=80){drawcount=0;}
Here's a sample of Reimu's DrawLoop. Hope it helps.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 06, 2009, 06:24:26 PM
That certainly helped alot thanks Iryan and Drake. I was using only the first part of the if statement and forgetting the "<" framecount to keep it animated within those frames. Now I just need to find a smooth speed for the animation. I am very satisfied with my Afro boss, perhaps I'll continue to create a mini plural script (though I am quite bad at pattern creating =.=)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 06, 2009, 08:52:19 PM
I need some help here... I'm trying to make an attack where the boss fires a ring of eight object bullets around itself, and when it hits the edges of the screen, these bullets are deleted and replaced with two object bullets that go back in the direction the original one came from, but at opposite 45-degree angles. Like this:

_ <-- Wall

| <-- Bullet

 |
 |
V
_
/\ <-- New bullets spawned when the original hits the wall

Am I making it clear enough? Anyways, when I took the code I already had for reflecting bullets and made new object bullets spawn into the same array of bullets, the game suddenly froze when one of the original bullets hit the walls.

Code: [Select]
task MirrorLaser
{
let i = 0;
while (i < length(Fate))
{
if (Obj_BeDeleted(Fate[i]))
{
Fate = erase(Fate, i);
i--;
}
else
{
if(Obj_GetX(Fate[i]) <= GetClipMinX() || Obj_GetX(Fate[i]) >= GetClipMaxX())
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj, (Obj_GetAngle(Fate[i]) + 180) + 45);
Obj_SetSpeed(obj, 2);
ObjShot_SetGraphic(obj, AQUA05);
Fate = Fate ~ [obj];

let obj2 = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj2, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj2, (Obj_GetAngle(Fate[i]) + 180) - 45);
Obj_SetSpeed(obj2, 2);
ObjShot_SetGraphic(obj2, AQUA05);
Fate = Fate ~ [obj2];
}
if(Obj_GetY(Fate[i]) <= GetClipMinY() || Obj_GetY(Fate[i]) >= GetClipMaxY())
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj, (Obj_GetAngle(Fate[i]) + 270) + 45);
Obj_SetSpeed(obj, 2);
ObjShot_SetGraphic(obj, AQUA05);
Fate = Fate ~ [obj];

let obj2 = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj2, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj2, (Obj_GetAngle(Fate[i]) + 270) - 45);
Obj_SetSpeed(obj2, 2);
ObjShot_SetGraphic(obj2, AQUA05);
Fate = Fate ~ [obj2];
}
}
i++;
}
}

(I wanted to make it a laser to begin with, but since I'm not comfortable with moving object lasers manually, I'm just going to make a custom bullet and make it long like a laser.)

Please help.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on July 06, 2009, 09:25:00 PM
I know this is a really simple question, but how do I properly use arrays?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 06, 2009, 09:52:41 PM
let arr = [1, 5, 7];

and then access each with arr[number]. arr[2] would equal 5.

EDIT: I just realized Obj_IsIntersected just detects if the object is in line with the enemy. How would I go about testing bullet collision?
EDIT: Enumerating every enemy and using Collision_Obj_Obj(obj, enemy) doesn't work either because en enemy is not an object.
EDIT: Neither does enumerating every enemy, finding each ID and checking (obj, enemyID).
EDIT: Neither does activating Obj_SetCollisionToObject.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on July 07, 2009, 12:44:58 AM
Okay. Then how would I be able to fire a bullet, say, with a randomized angle of either -10, 0, or 10, but ONLY one of those numbers, using an array?


What I am trying to do here is apparently invalid:

Code: [Select]
#TouhouDanmakufu
#Title[Laser Test]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_remilia.png";

let count = -60;
let count2 = 0;
let a = 0;
let b = 0;
let c = [-10, 0, 10];

@Initialize {
SetLife(2000);
SetTimer(60);
SetScore(10000000);
LoadUserShotData(GetCurrentScriptDirectory~"UserShotData.txt");

SetEnemyMarker(true);

SetMovePosition02(225, 160, 60);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 100, 100);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 10) {

PlaySE("script\Remilia Spell Cards\sfx\Laser2.wav");

CreateLaser01(GetX, GetY, 6, GetAngleToPlayer + c[rand(1, 2, 3)], 80, 20, RED04, 10);
CreateLaser01(GetX, GetY, 6, GetAngleToPlayer - 30 + c[rand(1, 2, 3)], 80, 20, BLUE04, 10);
CreateLaser01(GetX, GetY, 6, GetAngleToPlayer + 30 + c[rand(1, 2, 3)], 80, 20, BLUE04, 10);
CreateLaser01(GetX, GetY, 6, GetAngleToPlayer - 90 + c[rand(1, 2, 3)], 80, 20, GREEN04, 10);
CreateLaser01(GetX, GetY, 6, GetAngleToPlayer + 90 + c[rand(1, 2, 3)], 80, 20, GREEN04, 10);

count=0
}




if(count2 == 120){
loop(2){
CreateShot01(GetX, GetY, 3, a+180, GREEN31, 10);
CreateShot01(GetX, GetY, 3, b, GREEN31, 10);

a += 360/2;
a += 7;

b += 360/2;
b -= 7;
}



count2 = 117;
}
count++;
count2++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 07, 2009, 12:54:03 AM
Frazer: Rand doesn't work that way. You use it like this:


rand([lowest number you want], [highest number you want])

However, you want rand_int, not rand. Why? Rand returns not just whole numbers, but decimals, too. This will mess up your arrays... rand_int is forced to be a whole number.

Also, access arrays by starting with 0. So, the first entry is Entry 0, and the third is Entry 2. Therefore, what you want is this:

CreateLaser01(GetX, GetY, 6, GetAngleToPlayer + c[rand_int(0, 2)], 80, 20, RED04, 10);

That should get the randomization working.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 07, 2009, 02:52:59 AM
@Pikaguy:

Post your whole script please, I can't really see what's wrong other than it contains no yield; function. Also, something you might want to try before I get back to you is to make the bullets your spawning their own task, so instead of inside the object bullet you start making others, you could have two different tasks that just call upon eachother. Gets rid of dicking around, anyway. Like this:

task Bullet{
let obj = ....
....
....
while(! Obj_BeDeleted(obj)){
if(obj_GetX(obj) <= GetClipMinX || Obj_GetX >= GetClipMinX){
  Reflector(Obj_GetAngle(obj));
  Reflector2(Obj_GetAngle(obj));
  Obj_Delete(obj); //or whatever this function is called...
}
yield;
}
}

task Reflector(a){
 let obj = ...
...
Obj_SetAngle(obj, a - 45);
...
while blah blah, object bullet shit.{
}
}

task Reflector2(aa){
 let obj = ...
...
Obj_SetAngle(obj, a + 45);
...
while blah blah, more object bullet shit.{
}
}



...


@Drake:
You're trying to detect collision between an enemy and a bullet? If you're just trying to have the bullet damage the enemy:

(http://i641.photobucket.com/albums/uu134/Nautth/ddddddd.jpg)

If you're trying to have something else happen when an enemy and a bullet collide, you could make the enemies Objects and animate them with verticies, have them spawn bullets and move around using the while(!Obj_BeDeleted(obj)) loop and so on, then detect collision between two objects. Otherwise, I haven't the slightest.

And uh, arr[2] = 7.

<3


....



@Frazer:

(rand_int(-1, 1))*10 = -10, 0 or 10.

CreateShot01(GetX, GetY, 3, GetAngleToPlayer + (rand_int(-1, 1)*10), RED01, 0);

For any other random sets of numbers, use arrays, as pikaguy900 and Drake have already explained.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 07, 2009, 05:19:58 AM
And uh, arr[2] = 7
wait fuck


And of course I'd be able to just have it damage the enemy, I just use Obj_SetDamage, lol. I'm animating the bullets once they hit a target. Upon hitting the enemy the bullet slows down, changes graphic, alpha settings, etcetcetc. I have most of the effects done; the only thing is I can't get exactly how it hits the target. I can't use objects because I want the character to be usable in most scripts.

Although you have given me a plausible idea.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 07, 2009, 07:23:01 AM
Hmmm there seems to be something wrong with my animating sprites. It animates correctly but in between certain images I see it "flickering" like an unwanted GraphicRect sprite but there is no incorrect coordinates.

I cannot post the code atm =S
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 07, 2009, 02:52:05 PM
Naut: It works perfectly fine without a yield. I use this code every time I deal with arrays of objects, it has NEVER given me any problems in RUNNING what is in it. Why should it have a yield? It ends the minute it is done checking the array, which is what is supposed to happen...

Also, I can't really seperate them, because I'll be spawning two more object bullets when the new ones hit walls! Therefore, I eventually run back into the same situation I'm in right now... (Also, before you ask, no, I am NOT intending for them to split infinitely, I just want to get the splitting to work, first of all...)

In any case:

Code: [Select]
#TouhouDanmakufu
#Title[Reflection of a Fate Sealed with Scarlet]
#Text[]
#Image[]
#BackGround[Default]
#PlayLevel[]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
let BossImage = GetCurrentScriptDirectory ~ "boss_remilia.png";
let BossCutIn = GetCurrentScriptDirectory ~ "Remilia.png";
let frame = -100;
let frame2 = -100;
let anim_frame = 0;
let Angle = 0;
let ShotSFX = "script\sfx\shot.wav";
let LaserSFX = "script\sfx\laser.wav";
let Fate = [];
let Mirror = [];
let ang = 0;

task RotMirror
{
let i = 0;
while (i < length(Mirror))
{
if (Obj_BeDeleted(Mirror[i]))
{
Mirror = erase(Mirror, i);
i--;
}
else
{
}
i++;
}
}

task MirrorLaser
{
let i = 0;
while (i < length(Fate))
{
if (Obj_BeDeleted(Fate[i]))
{
Fate = erase(Fate, i);
i--;
}
else
{
if(Obj_GetX(Fate[i]) <= GetClipMinX() || Obj_GetX(Fate[i]) >= GetClipMaxX())
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj, (Obj_GetAngle(Fate[i]) + 180) + 45);
Obj_SetSpeed(obj, 2);
ObjShot_SetGraphic(obj, AQUA05);
Fate = Fate ~ [obj];

let obj2 = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj2, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj2, (Obj_GetAngle(Fate[i]) + 180) - 45);
Obj_SetSpeed(obj2, 2);
ObjShot_SetGraphic(obj2, AQUA05);
Fate = Fate ~ [obj2];
}
if(Obj_GetY(Fate[i]) <= GetClipMinY() || Obj_GetY(Fate[i]) >= GetClipMaxY())
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj, (Obj_GetAngle(Fate[i]) + 270) + 45);
Obj_SetSpeed(obj, 2);
ObjShot_SetGraphic(obj, AQUA05);
Fate = Fate ~ [obj];

let obj2 = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj2, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj2, (Obj_GetAngle(Fate[i]) + 270) - 45);
Obj_SetSpeed(obj2, 2);
ObjShot_SetGraphic(obj2, AQUA05);
Fate = Fate ~ [obj2];
}
}
i++;
}
}

@Initialize
{
shotinit;
LoadGraphic(BossImage);
SetLife(400);
SetDamageRate(0,0);
SetTimer(72);
SetInvincibility(30);
SetDurableSpellCard();
CutIn(YOUMU, "Reflection of a Fate Sealed with Scarlet", BossCutIn, 0, 0, 256, 320);
SetScore(70000);
SetEnemyMarker(true);
MagicCircle(true);
SetMovePosition02(GetCenterX,130,30);
}

@MainLoop
{
MirrorLaser;
anim_frame++;
SetCollisionA(GetX(),GetY(),32);
SetCollisionB(GetX(),GetY(),24);
if(frame == 0)
{
loop(8)
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, GetX, GetY);
Obj_SetAngle(obj, Angle);
Obj_SetSpeed(obj, 2);
ObjShot_SetGraphic(obj, AQUA04);
Fate = Fate ~ [obj];
Angle += 45;
}
//PlaySE(LaserSFX);

}
frame++;
frame2++;
}

@DrawLoop
{
SetTexture(BossImage);
if(anim_frame >= 0 && anim_frame < 8)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,31,95,94);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 8 && anim_frame < 16)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,159,95,222);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 16 && anim_frame < 24)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,287,95,350);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 24 && anim_frame < 32)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,415,95,478);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 32)
{
anim_frame = 0;
}
DrawGraphic(GetX, GetY);
}

@Finalize
{
DeleteGraphic(BossImage);
}
}

I love keeping secrets. :( Also, the Mirror task is because my plan is to have 4 large objects, mirrors, spinning around the boss, and have the bullets reflect off THOSE instead of the walls. So basically, the point is that the mirrors will continually split the bullets, and if any bullets slip through the cracks, you get to dodge... I'll find a way to make it balanced so things actually come towards you instead of away from you consistently...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 07, 2009, 03:20:12 PM
@Drake:
And of course I'd be able to just have it damage the enemy, I just use Obj_SetDamage, lol.


Didn't think you were talking about a player script, my bad.

I'm animating the bullets once they hit a target. Upon hitting the enemy the bullet slows down, changes graphic, alpha settings, etcetcetc. I have most of the effects done; the only thing is I can't get exactly how it hits the target. I can't use objects because I want the character to be usable in most scripts.

Player scripts ruin my possible solution... Augh. I've no idea.

Although you have given me a plausible idea.

Glad I helped in some way at least.


@pikaguy900:
Naut: It works perfectly fine without a yield. I use this code every time I deal with arrays of objects, it has NEVER given me any problems in RUNNING what is in it. Why should it have a yield? It ends the minute it is done checking the array, which is what is supposed to happen...

Shows how much I know about arrays.

I could be completely wrong, but according to what I see:
The bullet (Fate) hits the wall, the task checks if the bullet (Fate) hits the wall, the bullet creates two more bullets on the same position under that same array (Fate) as instructed by the task, the task continues to check if Fate is colliding with the wall and sees that there are two more bullets colliding with it and then continues to spawn more bullets on top of the new ones in an endless loop. Something like that?

Anyways, here's working code. I delete Fate the same frame that it hits the wall, but after I spawn the new bullets because I don't want the task to keep enumerating Fate, but I also want the new bullets to not be spawned in a bad zone (GetClipMinY + 1, etc.) as well as be able to get the coordinates of Fate. Uh... It should make sense when you see it in code:

Code: [Select]
#TouhouDanmakufu
#Title[Reflection of a Fate Sealed with Scarlet]
#Text[]
#Image[]
#BackGround[Default]
#PlayLevel[]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{
   #include_function "lib\SHOT_REPLACE\shot_replace.dnh"
   let BossImage = GetCurrentScriptDirectory ~ "boss_remilia.png";
   let BossCutIn = GetCurrentScriptDirectory ~ "Remilia.png";
   let frame = -100;
   let frame2 = -100;
   let anim_frame = 0;
   let Angle = 0;
   let ShotSFX = "script\sfx\shot.wav";
   let LaserSFX = "script\sfx\laser.wav";
   let Fate = [];
   let Mirror = [];
   let ang = 0;

   task RotMirror
   {
      let i = 0;
      while (i < length(Mirror))
      {
         if (Obj_BeDeleted(Mirror[i]))
         {
            Mirror = erase(Mirror, i);
            i--;
         }
         else
         {
         }
         i++;
      }
   }

   task MirrorLaser
   {
      let i = 0;
      while (i < length(Fate))
      {
         if (Obj_BeDeleted(Fate[i]))
         {
            Fate = erase(Fate, i);
            i--;
         }
         else
         {
            if(Obj_GetX(Fate[i]) <= GetClipMinX())
            {
               let obj = Obj_Create(OBJ_SHOT);
               Obj_SetPosition(obj, GetClipMinX + 1, Obj_GetY(Fate[i]));
               Obj_SetAngle(obj, (Obj_GetAngle(Fate[i]) + 180) + 45);
               Obj_SetSpeed(obj, 2);
               ObjShot_SetGraphic(obj, AQUA05);

               let obj2 = Obj_Create(OBJ_SHOT);
               Obj_SetPosition(obj2, GetClipMinX + 1, Obj_GetY(Fate[i]));
               Obj_SetAngle(obj2, (Obj_GetAngle(Fate[i]) + 180) - 45);
               Obj_SetSpeed(obj2, 2);
               ObjShot_SetGraphic(obj2, AQUA05);
   Obj_Delete(Fate[i]);
               Fate = Fate ~ [obj];
               Fate = Fate ~ [obj2];
            }
if(Obj_GetX(Fate[i]) >= GetClipMaxX())
{
               let obj = Obj_Create(OBJ_SHOT);
               Obj_SetPosition(obj, GetClipMaxX - 1, Obj_GetY(Fate[i]));
               Obj_SetAngle(obj, (Obj_GetAngle(Fate[i]) + 180) + 45);
               Obj_SetSpeed(obj, 2);
               ObjShot_SetGraphic(obj, AQUA05);

               let obj2 = Obj_Create(OBJ_SHOT);
               Obj_SetPosition(obj2, GetClipMaxX - 1, Obj_GetY(Fate[i]));
               Obj_SetAngle(obj2, (Obj_GetAngle(Fate[i]) + 180) - 45);
               Obj_SetSpeed(obj2, 2);
               ObjShot_SetGraphic(obj2, AQUA05);
   Obj_Delete(Fate[i]);
               Fate = Fate ~ [obj];
               Fate = Fate ~ [obj2];
}
            if(Obj_GetY(Fate[i]) <= GetClipMinY())
            {
               let obj = Obj_Create(OBJ_SHOT);
               Obj_SetPosition(obj, Obj_GetX(Fate[i]),GetClipMinY + 1);
               Obj_SetAngle(obj, (Obj_GetAngle(Fate[i]) + 180) + 45);
               Obj_SetSpeed(obj, 2);
               ObjShot_SetGraphic(obj, AQUA05);

               let obj2 = Obj_Create(OBJ_SHOT);
               Obj_SetPosition(obj2, Obj_GetX(Fate[i]), GetClipMinY + 1);
               Obj_SetAngle(obj2, (Obj_GetAngle(Fate[i]) + 180) - 45);
               Obj_SetSpeed(obj2, 2);
               ObjShot_SetGraphic(obj2, AQUA05);
   Obj_Delete(Fate[i]);
               Fate = Fate ~ [obj];
               Fate = Fate ~ [obj2];
            }
if(Obj_GetY(Fate[i]) >= GetClipMaxY())
{
               let obj = Obj_Create(OBJ_SHOT);
               Obj_SetPosition(obj, Obj_GetX(Fate[i]), GetClipMaxY - 1);
               Obj_SetAngle(obj, (Obj_GetAngle(Fate[i]) + 180) + 45);
               Obj_SetSpeed(obj, 2);
               ObjShot_SetGraphic(obj, AQUA05);

               let obj2 = Obj_Create(OBJ_SHOT);
               Obj_SetPosition(obj2, Obj_GetX(Fate[i]), GetClipMaxY - 1);
               Obj_SetAngle(obj2, (Obj_GetAngle(Fate[i]) + 180) - 45);
               Obj_SetSpeed(obj2, 2);
               ObjShot_SetGraphic(obj2, AQUA05);
   Obj_Delete(Fate[i]);
               Fate = Fate ~ [obj];
               Fate = Fate ~ [obj2];
}
         }
         i++;
      }
   }

   @Initialize
   {
      shotinit;
      LoadGraphic(BossImage);
      SetLife(400);
      SetDamageRate(0,0);
      SetTimer(72);
      SetInvincibility(30);
      SetDurableSpellCard();
      CutIn(YOUMU, "Reflection of a Fate Sealed with Scarlet", BossCutIn, 0, 0, 256, 320);
      SetScore(70000);
      SetEnemyMarker(true);
      MagicCircle(true);
      SetMovePosition02(GetCenterX,130,30);
   }

   @MainLoop
   {
      MirrorLaser;
      anim_frame++;
      SetCollisionA(GetX(),GetY(),32);
      SetCollisionB(GetX(),GetY(),24);
      if(frame == 0)
      {
         loop(8)
         {
            let obj = Obj_Create(OBJ_SHOT);
            Obj_SetPosition(obj, GetX, GetY);
            Obj_SetAngle(obj, Angle);
            Obj_SetSpeed(obj, 2);
            ObjShot_SetGraphic(obj, AQUA04);
            Fate = Fate ~ [obj];
            Angle += 45;
         }
         //PlaySE(LaserSFX);

      }
      frame++;
      frame2++;
   }

   @DrawLoop
   {
      SetTexture(BossImage);
      if(anim_frame >= 0 && anim_frame < 8)
      {
         if(GetSpeedX()==0)
         {
            SetGraphicRect(31,31,95,94);
         }
         else if(GetSpeedX()>0)
         {
            SetGraphicRect(286,415,352,478);
         }
         else if(GetSpeedX()<0)
         {
            SetGraphicRect(286,159,348,222);
         }
      }
      if(anim_frame >= 8 && anim_frame < 16)
      {
         if(GetSpeedX()==0)
         {
            SetGraphicRect(31,159,95,222);
         }
         else if(GetSpeedX()>0)
         {
            SetGraphicRect(286,415,352,478);
         }
         else if(GetSpeedX()<0)
         {
            SetGraphicRect(286,159,348,222);
         }
      }
      if(anim_frame >= 16 && anim_frame < 24)
      {
         if(GetSpeedX()==0)
         {
            SetGraphicRect(31,287,95,350);
         }
         else if(GetSpeedX()>0)
         {
            SetGraphicRect(286,415,352,478);
         }
         else if(GetSpeedX()<0)
         {
            SetGraphicRect(286,159,348,222);
         }
      }
      if(anim_frame >= 24 && anim_frame < 32)
      {
         if(GetSpeedX()==0)
         {
            SetGraphicRect(31,415,95,478);
         }
         else if(GetSpeedX()>0)
         {
            SetGraphicRect(286,415,352,478);
         }
         else if(GetSpeedX()<0)
         {
            SetGraphicRect(286,159,348,222);
         }
      }
      if(anim_frame >= 32)
      {
         anim_frame = 0;
      }
      DrawGraphic(GetX, GetY);
   }

   @Finalize
   {
      DeleteGraphic(BossImage);
   }
}

Keep in mind that because the new bullets are created under the same array (Fate), once they hit walls and the angle they produce is a bad angle (when their angle +- 45 still throws them into walls, which will happen often) they will start spawning a multitude of bullets in the same direction every frame, which will cause your computer to slow down and crash. However, since you said you're going to make them collide with lasers, this shouldn't be a problem (interestingly enough, it still might make more bullets than you expect, be careful). So, this script doesn't really work correctly, but once you change it for lasers it should be pretty close.



@Helepolis:
Check to make sure your operators don't overlap or skip a frame (<= and >), as this will create a brief one frame flicker. If you're positive they're accurate, post the code as soon as you're able and we'll see what we can do.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 07, 2009, 03:59:02 PM
@Helepolis:
Check to make sure your operators don't overlap or skip a frame (<= and >), as this will create a brief one frame flicker. If you're positive they're accurate, post the code as soon as you're able and we'll see what we can do.

Nope I am sure I didn't overlap any frames. Or my eyes gone bad =.=
The flickering is this image:
(http://i31.tinypic.com/wjfgrd.jpg)

And the code. I posted full drawloop as there are also spellcircle animations in there.
Code: [Select]
   
@DrawLoop {
// spellcircle animation
SetTexture(spellcircle);
SetGraphicRect(385,337,512,464);
SetAlpha(255);
SetGraphicAngle(0,0,draai);
SetGraphicScale(p,p);
DrawGraphic(GetX, GetY);

SetTexture(spellcircle2);
SetGraphicRect(0,0,128,128);
SetAlpha(155);
        //SetColor(255,0,255);
SetGraphicAngle(0,0,-draai2);
SetGraphicScale(2.5,2.5);
DrawGraphic(GetX, GetY);

SetTexture(spellcircle3);
SetGraphicRect(128,0,256,128);
SetAlpha(155);
        //SetColor(255,0,255);
SetGraphicAngle(0,0,draai2);
SetGraphicScale(3,3);
DrawGraphic(GetX, GetY);

draai+=3;
draai2+=5;

if(s==0){p+=0.01; if(p>2.00){s=1;} }
if(s==1){p-=0.01; if(p<1.50){s=0;} }

if(draai>360){draai=0;}
if(draai2>360){draai2=0;}

// Afro drawing + animation
SetTexture(CSD~ "system\arap.png");
SetAlpha(255);
SetGraphicAngle(0,0,0);
SetGraphicScale(1,1);
SetRenderState(ALPHA);

if(int(GetSpeedX())==0){
if(attack==0){
if(arapanm2<10){SetGraphicRect(0,0,82,112);}
if(arapanm2>10 && arapanm2<15){SetGraphicRect(82,0,162,112);}
if(arapanm2>20 && arapanm2<25){SetGraphicRect(162,0,242,112);}
if(arapanm2>25){SetGraphicRect(242,0,322,112);}
}
if(attack==1){SetGraphicRect(242,224,318,335);}
}
if(GetSpeedX()>0){
if(arapanm<10){SetGraphicRect(0,112,64,223);}
if(arapanm>10 && arapanm<20){SetGraphicRect(64,112,128,223);}
if(arapanm>20 && arapanm<30){SetGraphicRect(128,112,192,223);}
if(arapanm>30 && arapanm<40){SetGraphicRect(192,112,256,223);}
if(arapanm>40 && arapanm<50){SetGraphicRect(256,112,320,223);}
if(arapanm>50 && arapanm<60){SetGraphicRect(320,112,384,223);}
if(arapanm>60 && arapanm<70){SetGraphicRect(384,112,448,223);}
if(arapanm>70){SetGraphicRect(448,112,512,223);}
}
if(GetSpeedX()<0){
if(arapanm<10){SetGraphicRect(0,112,64,223);}
if(arapanm>10 && arapanm<20){SetGraphicRect(64,112,128,223);}
if(arapanm>20 && arapanm<30){SetGraphicRect(128,112,192,223);}
if(arapanm>30 && arapanm<40){SetGraphicRect(192,112,256,223);}
if(arapanm>40 && arapanm<50){SetGraphicRect(256,112,320,223);}
if(arapanm>50 && arapanm<60){SetGraphicRect(320,112,384,223);}
if(arapanm>60 && arapanm<70){SetGraphicRect(384,112,448,223);}
if(arapanm>70){SetGraphicRect(448,112,512,223);}
}
if(GetSpeedY()<0){
if(arapanm<10){SetGraphicRect(0,112,64,223);}
if(arapanm>10 && arapanm<20){SetGraphicRect(64,112,128,223);}
if(arapanm>20 && arapanm<30){SetGraphicRect(128,112,192,223);}
if(arapanm>30 && arapanm<40){SetGraphicRect(192,112,256,223);}
if(arapanm>40 && arapanm<50){SetGraphicRect(256,112,320,223);}
if(arapanm>50 && arapanm<60){SetGraphicRect(320,112,384,223);}
if(arapanm>60 && arapanm<70){SetGraphicRect(384,112,448,223);}
if(arapanm>70){SetGraphicRect(448,112,512,223);}
}
        DrawGraphic(GetX, GetY);
arapanm++;
if(arapanm>80){arapanm=0;}
arapanm2+=0.5;
if(arapanm2>25){arapanm2=0;}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 07, 2009, 04:09:46 PM
Naut: Okay, I get what you said... Yeah, it happened. And sadly, I want to avoid this, 'cause I'm pretty sure it WILL happen when I try the mirrors thing. Oh well, nothing I can do about it. I wish I had a way I could avoid this, but I don't want to spawn the bullets in the exact same directions each time, I want it to be based on where the bullet is going...and still split. Do you have any ideas, even if they require rethinking how I code this? As it is right now, I just know that eventually, a bullet is going to go at such an angle that it will spawn a bullet that shoots right back at the mirrors, just like with the wall right now.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 07, 2009, 04:39:17 PM
@ Helepolis:

Found it!


         if(arapanm2<10){SetGraphicRect(0,0,82,112);}
         if(arapanm2>10 && arapanm2<15){SetGraphicRect(82,0,162,112);}
         if(arapanm2>20 && arapanm2<25){SetGraphicRect(162,0,242,112);}
         if(arapanm2>25){SetGraphicRect(242,0,322,112);}


If arapanm2 is between 15 and 20, the last set GraphicRect is used, which is 
   SetGraphicRect(128,0,256,128);
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 07, 2009, 05:04:57 PM
@ Helepolis:

Found it!

         if(arapanm2<10){SetGraphicRect(0,0,82,112);}
         if(arapanm2>10 && arapanm2<15){SetGraphicRect(82,0,162,112);}
         if(arapanm2>20 && arapanm2<25){SetGraphicRect(162,0,242,112);}
         if(arapanm2>25){SetGraphicRect(242,0,322,112);}

If arapanm2 is between 15 and 20, the last set GraphicRect is used, which is 
   SetGraphicRect(128,0,256,128);

Nope it is still flickering and there is nothing in between. The sprite moves 80 xcoordinates in the range. It is only mere 4 sprites. But the same happens for  X < and X > or Y > <  movements. While those have no gaps in them.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 07, 2009, 05:26:35 PM
Well, the human eye usually cannot recognize single pictures at a rate of 60 per second. Pictures with a rate of (60/4)=15 per second on the other hand can easily be perceived. That may explain why the flickering isn't recognized then.


Ummm, in the code you posted there is a one frame gap between every different animation, as you used only "<X" and ">X", which means that for a value equal to X, there won't be a proper graphic rect.

Instead of...
    if(frame<10){ A; }
    if(frame>10&&frame<20){ B; }
    etc.
...you should type...
    if(frame<=10){ A; }
    if(frame>10&&frame<=20){ B; }
    etc.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 07, 2009, 06:12:11 PM
According to Naut he said not to overlap operators. And the flickering is not the image dissapearing but as shown above in the image: As if a wrong GraphicRect coordinates are given but infact there is not.

I'll still try it out, as it does looks like that is the problem.


Edit: My eyes must be turning bad. As I guess Naut tried to point out same thing but Iryan's explanation was easier to understand? Ohwell. It works like a charm now, perfect animation. Now I can finally focus on the spellcard instead of details =P
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 07, 2009, 06:32:11 PM
Yeah, that's what I meant. Iryan isn't overlapping them by the way... But as long as you understand then it's all good.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 07, 2009, 06:35:49 PM
Overlapping operators would be like x>=25 and x<=25. Both will check for 25 and suicide.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 07, 2009, 08:20:31 PM
Ah overlapping like that. Now I fully get it. Damn how much I was cursing my self for two days trying to figure out a way to animate this proper as the solution was actually extremely easy =.=

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 08, 2009, 02:25:26 AM
First of all,

(http://img376.imageshack.us/img376/6306/22909631.png)

Second of all,

Code: [Select]
task Target{
let f = 0;
ascent(enemy in EnumEnemyBegin..EnumEnemyEnd){
let enemyID = EnumEnemyGetID(enemy);
let target = Obj_Create(OBJ_SHOT);
Obj_SetX(target, GetEnemyInfo(enemyID, ENEMY_X));
Obj_SetY(target, GetEnemyInfo(enemyID, ENEMY_Y));
Obj_SetSpeed(target, 0);
Obj_SetCollisionToPlayer(target, false);
ObjShot_SetBombResist(target, true);
ObjShot_SetGraphic(target, 101);
while(!Obj_BeDeleted(target)){
Obj_SetX(target, GetEnemyInfo(enemyID, ENEMY_X));
Obj_SetY(target, GetEnemyInfo(enemyID, ENEMY_Y));
f++;
if(f>2){Obj_Delete(target);}
yield;
}
}
}

I'm a sneaky little bastard :D (thanks naut btw)

I'll change the graphic to something different and make it invisible, of course. My problem now is that I'm not quite sure how I would increase the size of the object depending on the boss' bullet collision hitbox. I'll probably need to make it an effect object and use ObjEffect_SetScale, but I'm not quite sure.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 08, 2009, 02:42:32 AM
First of all,
[hiitobakusu.png]

Delicious.

(thanks naut btw)

Anytime brah.

I'll change the graphic to something different and make it invisible, of course. My problem now is that I'm not quite sure how I would increase the size of the object depending on the boss' bullet collision hitbox. I'll probably need to make it an effect object and use ObjEffect_SetScale, but I'm not quite sure.

I'm not following where you're going with this, but yes. Very yes.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 08, 2009, 02:54:15 AM
The above code spawns a nullified object shot on top of an enemy and follows it around. (Actually up to now it only gets one enemy at a time, will need to fix that)

I want to make a graphic that changes sizes depending on SetCollisionA. This way, I check if player bullets contact with the targeting object with SetCollision_Obj_Obj. This way, I can tell exactly when the bullets hit the boss and animate the bullets accordingly.

tl;dr I need to make a circle that changes sizes depending on SetCollisionA.

EDIT: rage danmaq
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 08, 2009, 03:06:25 AM
I need to make a circle that changes sizes depending on SetCollisionA.

As far as I know, you can't change something based on it's size because it's not information that you can get. The only way I can think of getting this information is to make a function that will copy the enemy's script into a text string, then enumerate the characters inside the text file up until it reaches "SetCollisionA", delete everything beforehand in the text string, then enumerate again until it reaches a number, delete everything before the number, copy the number into another string, convert it from a string to a value and then base your graphic expansion on the number yielded. This sounds like alot to do every frame though, not to mention is probably not possible.

You can get if SetCollisionA exists though, because Reimu_A's homing amulets will only target enemies with hitboxes, but God only knows what fucking function gets this information.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 08, 2009, 11:40:53 AM
Maybe I'm not understanding what you're trying to do, but can't you just make a variable and use it to set SetCollisionA's value, and just have the object check that variable too?

As for scaling a shot to fit it, you could make it a laser instead of a shot and just give it equal height and width, but I forget how object lasers work and whether that would look weird or not. If that's no good yeah you should just use an effect object.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 08, 2009, 05:14:14 PM
Object laser will work better than my method, thanks.

But the problem with setting a variable to SetCollisionA is that all this is a player script. So I would have to somehow access the variable in the enemy script from the player script, which doesn't work without CommonData. And either way I'd have to edit the enemy script, which is what I'm trying to avoid. I'm trying to make this character as accessible as possible.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on July 08, 2009, 08:01:23 PM
I have yet another question (and I always have many).


I tried making a new style of attack (although somewhat similar to Mokou's).

Code: [Select]
#TouhouDanmakufu
#Title[New Spellcard]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\thC\IMAGE\CHAR\DOT\boss_remilia.png";

let count = -60;
let count2 = 0;
let x = 30;
let y = 20;
let a = 0;
let b = 0;

@Initialize {
SetLife(2000);
SetTimer(60);
SetScore(10000000);
LoadUserShotData(GetCurrentScriptDirectory~"UserShotData.txt");

SetEnemyMarker(true);

SetMovePosition02(225, 160, 60);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 100, 100);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 2) {

SetShotDirectionType(PLAYER);

CreateShotA(1, x, y, 10);
SetShotDataA(1, 0, 0, 0, 0, 0, 0, GREEN04);
SetShotDataA(1, 11, 0, NULL, 0, 0.025, 3, GREEN04);


if(x == 30 && y == 20){
x += 5;
y += 0;
}

if(x == 410 && y == 20){
x += 0;
y += 5;
}

if(x == 410 && y == 460){
x -= 5;
y += 0;
}

if(x == 30 && y == 460){
x += 0;
y -= 5;
}


FireShot(1);


count=0
}




if(count2 == 120){
loop(2){
CreateShot01(GetX, GetY, 3, a+180, GREEN31, 10);
CreateShot01(GetX, GetY, 3, b, GREEN31, 10);

a += 360/2;
a += 10;

b += 360/2;
b -= 10;
}



count2 = 117;
}
count++;
count2++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}


Code: [Select]
if(x == 30 && y == 20){
x += 5;
y += 0;
}

if(x == 410 && y == 20){
x += 0;
y += 5;
}

if(x == 410 && y == 460){
x -= 5;
y += 0;
}

if(x == 30 && y == 460){
x += 0;
y -= 5;
}


The x += and y += cancel each other out even though none of the other conditions are met. How come this is happening? What would be the proper way for this to work correctly?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 08, 2009, 08:23:49 PM
Unless I am missing something, on the first main loop the condition x == 30 && y == 20 is true, causing x to become 35. From then on, none of if-brackets will ever be performed.


Maybe you are looking for ">=" and "<=" instead of "=="?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on July 08, 2009, 08:59:58 PM
Oh, right. I forgot about that (that in this case, only the first main loop counts).

I apologize.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on July 09, 2009, 10:17:51 AM
I have a question...

is it possible to get data, like a certain variable, from another script every frame, so that you could also use that same variable on that enemy? (the variable is used in both scripts at the same time)

for example... you have a boss that spawns familiars using the CreateEnemyFromFile function and the familiars have to use a certain variable in the boss' script that the boss also uses, but you can't just copy paste the calculation cause it's randomized at some points.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 09, 2009, 03:37:13 PM
You need to use the CommonData (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Miscellaneous_Functions#Common_Data_Functions) functions. You use them to declare variables that exist globally.

For instance, in your boss script you would say
Code: [Select]
SetCommonData("bossvariable",variable);And in the familiar script you can access it with
Code: [Select]
GetCommonData("bossvariable");
This will work fine in your mainloops.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 09, 2009, 08:44:47 PM
I decided to scrap my original idea for the Fate spellcard, and now I have this:

Code: [Select]
#TouhouDanmakufu
#Title[Reflection of a Fate Broken with Scarlet]
#Text[]
#Image[]
#BackGround[Default]
#PlayLevel[]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
let BossImage = GetCurrentScriptDirectory ~ "boss_remilia.png";
let BossCutIn = GetCurrentScriptDirectory ~ "Remilia.png";
let frame = -100;
let frame2 = -100;
let anim_frame = 0;
let Angle = 0;
let ShotSFX = "script\sfx\shot.wav";
let LaserSFX = "script\sfx\laser.wav";
let Fate = [];
let Fate2 = [];
let Break = [];
let Angle2 = 0;

task ReflectingFate
{
let i = 0;
while (i < length(Fate))
{
if (Obj_BeDeleted(Fate[i]))
{
Fate = erase(Fate, i);
i--;
}
else
{
if(Obj_GetX(Fate[i]) <= GetClipMinX() || Obj_GetX(Fate[i]) >= GetClipMaxX())
{
Obj_SetAngle(Fate[i], 180-Obj_GetAngle(Fate[i]));
}
if(Obj_GetY(Fate[i]) <= GetClipMinY() || Obj_GetY(Fate[i]) >= GetClipMaxY())
{
Obj_SetAngle(Fate[i], 360-Obj_GetAngle(Fate[i]));
}
let e = 0;
while(e < length(Break) && !Obj_BeDeleted(Fate[i]))
{
if(Collision_Obj_Obj(Fate[i], Break[e]) == true)
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj, (Obj_GetAngle(Fate[i]) + 360) + 45);
Obj_SetSpeed(obj, 2);
ObjShot_SetGraphic(obj, AQUA05);
Fate2 = Fate2 ~ [obj];

let obj2 = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj2, Obj_GetX(Fate[i]), Obj_GetY(Fate[i]));
Obj_SetAngle(obj2, (Obj_GetAngle(Fate[i]) + 360) - 45);
Obj_SetSpeed(obj2, 2);
ObjShot_SetGraphic(obj2, AQUA05);
Fate2 = Fate2 ~ [obj2];
Obj_Delete(Fate[i]);
}
e++;
}
}
i++;
}
}

task BrokenFate
{
let h = 0;
while (h < length(Fate2))
{
if (Obj_BeDeleted(Fate2[h]))
{
Fate2 = erase(Fate2, h);
h--;
}
else
{
if(Obj_GetY(Fate2[h]) <= GetClipMinY())
{
Obj_SetAngle(Fate2[h], 360-Obj_GetAngle(Fate2[h]));
}
let e = 0;
while(e < length(Break) && !Obj_BeDeleted(Fate2[h]))
{
if(Collision_Obj_Obj(Fate2[h], Break[e]) == true)
{
Obj_SetAngle(Fate2[h], 180-Obj_GetAngle(Fate2[h]));
}
e++;
}
}
h++;
}
}

@Initialize
{
shotinit;
LoadGraphic(BossImage);
SetLife(400);
SetDamageRate(0,0);
SetTimer(72);
SetDurableSpellCard();
CutIn(YOUMU, "Reflection of a Fate Broken with Scarlet", BossCutIn, 0, 0, 256, 320);
SetScore(70000);
SetEnemyMarker(true);
MagicCircle(true);
SetMovePosition02(GetCenterX,130,30);
}

@MainLoop
{
ReflectingFate;
BrokenFate;
anim_frame++;
SetCollisionB(GetX(),GetY(),24);
if(frame == 0)
{
loop(8)
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, GetX, GetY);
Obj_SetAngle(obj, Angle);
Obj_SetSpeed(obj, 2);
ObjShot_SetGraphic(obj, AQUA04);
Fate = Fate ~ [obj];
Angle += 45;
}
Angle += 22.5;
frame = -100;

}
if(frame2 >= 60 && frame2 < 100)
{
if(frame2%5 == 0)
{
loop(8)
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, GetX, GetY);
Obj_SetAngle(obj, Angle2);
Obj_SetSpeed(obj, 4);
ObjShot_SetGraphic(obj, RED32);
Break = Break ~ [obj];

Angle2 += 45;
}
Angle2 += 22.5;
//PlaySE(LaserSFX);
}
}
if(frame2 >= 100)
{
frame2 -= 100;
}
frame++;
frame2++;
}

@DrawLoop
{
SetTexture(BossImage);
if(anim_frame >= 0 && anim_frame < 8)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,31,95,94);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 8 && anim_frame < 16)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,159,95,222);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 16 && anim_frame < 24)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,287,95,350);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 24 && anim_frame < 32)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,415,95,478);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(anim_frame >= 32)
{
anim_frame = 0;
}
DrawGraphic(GetX, GetY);
}

@Finalize
{
DeleteGraphic(BossImage);
}
}

Of course, I wouldn't be posting here if I didn't have a problem... The problem is that while everything works as I want them to, EVERYTHING SLOWS DOWN SO MUCH. I have no idea why... Is it solely because of the tasks? Or what? I just can't tell.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 09, 2009, 09:27:51 PM
Holy fucking shiiiiiiiiiiIIIIIIIIIIIIIIIIIIIIT. I have a quad core and my computer was crying on that. Too much reflecting causes major slowdown. When I made my Mokou script I originally had the white glowing orbs reflect (oh baby), which created a giant mesh of particles but slowed down even the sturdiest of computers, so I had to scrap that and throw fireballs with it instead. Point: Reflecting takes a lot of processing, for whatever reason. Especially if more than a few bullets are updating their information during a span of a few frames (like your script).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 09, 2009, 09:57:30 PM
Oh, I didn't know that... Problem is, without reflecting, there's really not much point to this spellcard at all...

...Also, I've had more reflecting bullets than this spawn at once, and that never gave me slowdown... *points to Armageddon Matter script* I need more ideas, then... I still want the splitting to happen when the bullets get sliced, but without reflecting, there's no point to it, because the bullets won't even go to the player then... Unless I find some good and easy way to make them fly up, then fall down. (I'm not good with "gravity" effects like that, though... Any advice on some simple ways to do it?)

EDIT: Okay, it can't be the reflecting alone. I am now going to assume it is the Collision_Obj_Obj because when I comment out all the reflecting stuff, I still get big slowdown eventually, even when many bullets begin leaving the screen...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 10, 2009, 03:11:30 AM
Likely.

My reflecting example was 40x worse than what yours is, so that is a very plausable assumption. Collision_Obj_Obj is pretty eff'd to begin with, so reflecting based on that can't really yield nice results in bulk. That is, the collision lasts for more than one frame and thus things get processed for a needlessly long time. Try having the bullets reflect only once (implement a counter to check if the bullets have already reflected) and see if that helps. Or ignore that idea if you really want them to keep reflecting.... Which is probably not a good idea in the first place. Ever play Light Sign "Reflection, Refraction" for longer than 15 seconds? Yeah.

Simple way to do gravity effects is CreateShot12 with a positive y-acceleration and a negative y-velocity (will rise upwards and slowly fall downwards). Another way is to use CreateShotA's that have angular velocity to point them downward... But that's needlessly complex when you can indicate a vertical component (gravity) with CreateShot12 or SetShotDataA_XY.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 10, 2009, 04:19:05 AM
Eh, thanks, Naut, but nevermind. Yes, the problem was Collision_Obj_Obj, but without that, my whole spellcard was ruined... Thus, I decided to just change the spellcard altogether. Now it's those knives whirling around while large, white bullets appear every so often from the boss, angling downward. Four in each direction they go in, which is two, so eight bullets. Each stops at a certain distance, and after 270 frames after spawning, they create a ring 16 smaller bullets EACH (8 x 16) and zoom at the player. :D  I have yet to beat it without dying. It is perfect! ;D It's easy to dodge, yet not.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on July 10, 2009, 10:10:44 AM
You need to use the CommonData (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Miscellaneous_Functions#Common_Data_Functions) functions. You use them to declare variables that exist globally.

For instance, in your boss script you would say
Code: [Select]
SetCommonData("bossvariable",variable);And in the familiar script you can access it with
Code: [Select]
GetCommonData("bossvariable");
This will work fine in your mainloops.

Thanks! that worked!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on July 11, 2009, 01:29:49 AM
Supposing I had eight object bullets I made, and I had defined a function that fired a set of bullets from each object bullet. How do I have the function select the coordinates of one bullet of the eight, and fire it, each frame, and not fire from the remaining eight frames? It's more complicated than you'd realize. The most I have right now is something like this:
Code: [Select]
#TouhouDanmakufu
#Title[Nonspell Somethingerother]
#Text[Somethingerother Nonspell is Somethingerotherrrrrr]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let ImgBoss = "script\img\ExRumia.png";
let frame = 0;


    @Initialize {
        SetLife(2000);
        SetTimer(50);
        SetScore(1000000);

        SetMovePosition02(GetCenterX, GetClipMinY + 120, 120);
        CutIn(YOUMU, "Test Sign "\""Test"\", "", 0, 0, 0, 0);

        LoadGraphic(ImgBoss);
        SetTexture(ImgBoss);
        SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
if(frame == 120){
FSpheres;
frame = 0;
}
yield;
frame++;

    }

    @DrawLoop {
        DrawGraphic(GetX, GetY);
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
function FSpheres{
let ang = GetAngleToPlayer;
ascent(i in 0..8){
TSpheres(ang + i*45, i);
}
}
task TSpheres(let shotangle, let i){
let dist = 0;
let timer = 0;
let mod = 1;
let CX = GetX;
let CY = GetY;
let sphere_id = Obj_Create(OBJ_SHOT);
Obj_SetPosition(sphere_id, GetX, GetY);
ObjShot_SetDelay(sphere_id, 5);
ObjShot_SetBombResist(sphere_id, true);
ObjShot_SetGraphic(sphere_id, RED02);
while(Obj_BeDeleted(sphere_id) == false && timer <= 250){
Obj_SetPosition(sphere_id, GetX + dist*cos(shotangle), GetY + dist*sin(shotangle));
shotangle += mod;
dist+=0.2;
if(mod <= 4){mod += 0.2;}
timer++;
yield;
}
while(Obj_BeDeleted(sphere_id) == false && timer > 250){
let chase = GetAngleToPlayer;
loop{
Obj_SetPosition(sphere_id, CX + dist*cos(shotangle), CY + dist*sin(shotangle));
//I REALLY WANT SOMETHING HERE TO MAKE IT WORK
Bullet(shotangle, Obj_GetX(sphere_id), Obj_GetY(sphere_id));
CX += 2*cos(chase);
CY += 2*sin(chase);
shotangle += 4;
timer++;
yield;
}
}
}
function Bullet(b_angle, b_x, b_y){
let p = rand_int(1, 2);
alternative(p)
case(1){
loop(5){
CreateShot02(b_x, b_y, 10, b_angle - 20, -1, 3, RED56, 3);
b_angle += 10;
}
}
case(2){
loop(7){
CreateShot02(b_x, b_y, 10, b_angle - 30, -1, 2, GREEN56, 3);
b_angle += 10;
}
}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 11, 2009, 03:44:30 AM
Supposing I had eight object bullets I made, and I had defined a function that fired a set of bullets from each object bullet. How do I have the function select the coordinates of one bullet of the eight, and fire it, each frame, and not fire from the remaining eight frames? It's more complicated than you'd realize. The most I have right now is something like this:
Code: [Select]
#TouhouDanmakufu
#Title[Nonspell Somethingerother]
#Text[Somethingerother Nonspell is Somethingerotherrrrrr]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let ImgBoss = "script\img\ExRumia.png";
let frame = 0;


    @Initialize {
        SetLife(2000);
        SetTimer(50);
        SetScore(1000000);

        SetMovePosition02(GetCenterX, GetClipMinY + 120, 120);
        CutIn(YOUMU, "Test Sign "\""Test"\", "", 0, 0, 0, 0);

        LoadGraphic(ImgBoss);
        SetTexture(ImgBoss);
        SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
if(frame == 120){
FSpheres;
frame = 0;
}
yield;
frame++;

    }

    @DrawLoop {
        DrawGraphic(GetX, GetY);
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
function FSpheres{
let ang = GetAngleToPlayer;
ascent(i in 0..8){
TSpheres(ang + i*45, i);
}
}
task TSpheres(let shotangle, let i){
let dist = 0;
let timer = 0;
let mod = 1;
let CX = GetX;
let CY = GetY;
let sphere_id = Obj_Create(OBJ_SHOT);
Obj_SetPosition(sphere_id, GetX, GetY);
ObjShot_SetDelay(sphere_id, 5);
ObjShot_SetBombResist(sphere_id, true);
ObjShot_SetGraphic(sphere_id, RED02);
while(Obj_BeDeleted(sphere_id) == false && timer <= 250){
Obj_SetPosition(sphere_id, GetX + dist*cos(shotangle), GetY + dist*sin(shotangle));
shotangle += mod;
dist+=0.2;
if(mod <= 4){mod += 0.2;}
timer++;
yield;
}
while(Obj_BeDeleted(sphere_id) == false && timer > 250){
let chase = GetAngleToPlayer;
loop{
Obj_SetPosition(sphere_id, CX + dist*cos(shotangle), CY + dist*sin(shotangle));
//I REALLY WANT SOMETHING HERE TO MAKE IT WORK
Bullet(shotangle, Obj_GetX(sphere_id), Obj_GetY(sphere_id));
CX += 2*cos(chase);
CY += 2*sin(chase);
shotangle += 4;
timer++;
yield;
}
}
}
function Bullet(b_angle, b_x, b_y){
let p = rand_int(1, 2);
alternative(p)
case(1){
loop(5){
CreateShot02(b_x, b_y, 10, b_angle - 20, -1, 3, RED56, 3);
b_angle += 10;
}
}
case(2){
loop(7){
CreateShot02(b_x, b_y, 10, b_angle - 30, -1, 2, GREEN56, 3);
b_angle += 10;
}
}
}

If I'm understanding what you mean correctly, you want each object bullet to carry out the Bullet function per 8 frames but never at the same time as the others, right?
You can let a counter varible = 1 inside the TSpheres task and add 1 to it like the timer varible. After the counter++; statement, add a if(counter == 9){counter = 1;}
Then use if(counter == i){fire Bullet function}.
I think this should work...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on July 11, 2009, 03:52:16 AM
Hmm... See, the trouble is, I'm trying to randomize which bullet fires. Then, it kind of becomes a shot-inna-dark scenario (this is what I was planning originally, but I thought it would look weird). I need to have a rand_int(0, 8 ) called somewhere not within the task (or else it will be called eight times, coz of the while statement), and then contrast 'i' with that.

EDIT: I actually tried this, and it almost looks okay. It's impossible to win (I put WAAAAAY too many bullets in, will have to put a '&& timer%x' in with the 'if' statement you described), but there's a weirder problem. After the first bullet cluster exits the screen, bullets start SPEWING from the top left corner. Is there any way I could incorporate Obj_BeDeleted into the Bullet function, and make that... not happen? XD
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 11, 2009, 04:30:28 AM
After the first bullet cluster exits the screen, bullets start SPEWING from the top left corner. Is there any way I could incorporate Obj_BeDeleted into the Bullet function, and make that... not happen? XD

I'm not quite sure what's causing the top left bullets, something like the bullets are fired after the TSpheres are deleted, right?
I tried your script, and somehow, it worked fine after I incuded
   SetShotAutoDeleteClip(30, 30, 30, 30);
in the @Initialize.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 11, 2009, 04:46:54 AM
Hmm... Have you tried creating an array of object bullets? It's quite simple to make, and doesn't even need a task, or even a FUNCTION! Well, I think. I've tested with a subroutine, and it worked fine, since it requires no yields.... Anyways, the basic code you need is this:


Code: [Select]
sub BulletArray
{
    let i = 0
    while(i < length(Array))
    {
        if(Obj_BeDeleted(Array[i]))
        {
           Array = erase(Array, i);
           i--;
        }
        else
        {
            *do stuff to the bullet here*
        }
        i++;
    }
}

You need to make Array a global variable, of course. ("let Array = [];") When you want to add bullets, set up your object as normal, but instead of modifying it after that, do something like "Array = Array ~ [obj];" and modify it in the subroutine/function/task you check the array's value in and stuff, using "Array" to access a bullet ID. Doing "Array = Array ~ [obj];" creates a new area of the array you can get an index for and stores the value of what is in the brackets, obj in this case, to that position. Doing this effectively creates an array of bullets.

I hope that makes sense... I learned this from [whoever it was that made that Random Sign "Entropy" script, I forget who it was...].
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Darkblizer on July 11, 2009, 05:10:06 AM
EDIT: I actually tried this, and it almost looks okay. It's impossible to win (I put WAAAAAY too many bullets in, will have to put a '&& timer%x' in with the 'if' statement you described), but there's a weirder problem. After the first bullet cluster exits the screen, bullets start SPEWING from the top left corner. Is there any way I could incorporate Obj_BeDeleted into the Bullet function, and make that... not happen? XD
[/quote]

Oh, I had that problem. You're bullets don't stop moving (or don't delete, one or the other, I forget which is was) and (I think) when your bullets are deleted, they go to the top left corner.

What I did was made the bullets only move when they aren't deleted (At least, I'm pretty sure that's what I did..)

I'll be more sure about this on the weekend, but I know it goes something like that.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 11, 2009, 06:14:49 PM
Hey, I have a question. Nothing extremely important I need RIGHT NOW, but it's just something I'd like to have...

I'm working on a player script for Onthenet, and he wants some of the player's shots to have a small death effect when hitting enemuies, like how MarisaA's "tree" bullets explode into those green circles. The only way I can think of to get that would be to make those shots object bullets, check if they hit the boss, and if so, spawn another bullet that does no damage, animates for a bit, then dies... However, I'd like to know, are there any commands or anything I could use to have a bullet do that normally, without going through all the object stuff?

Thanks in advance, and once again, no rush for this info, it's just something small that he can live without if needed.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 11, 2009, 06:43:29 PM
That's what I've been working on with Reimu for the past week.

It can be done, but I still can't figure out how to detect hitbox collision for every enemy.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 11, 2009, 06:45:21 PM
I'm pretty sure it'll have to be object bullets. The only way to track normal bullet collision is through enemy scripts, and it only gets whether they've been hit or not, not where the bullet was.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 11, 2009, 08:07:06 PM
EDIT: Found my problem... I was using whole numbers (i.e., 5) when I meant to use DECIMALS (i.e., 0.5)... Oops. Now it works perfectly!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 12, 2009, 05:13:50 PM
Hiya guys, I'm rather new to this programming stuff (I don't think RPGmaker counts as programming), and I have a few questions for you...

My problem is this:

(http://i32.photobucket.com/albums/d49/puremrz/danmakufuprob1.png)

I want a bullet to spawn 100 pixels left of the boss (which is currently in the center of the screen, but not visible), and it has to be aimed at the player from the spot where the bullet appears, not where the boss is. Is there a code for that? GetAngleToPlayer only makes it aim at me from the boss' perspective.

This is what the simple shot looks like now:
Code: [Select]
CreateLaser01(GetX-100, GetY, 3, GetAngleToPlayer, 200, 10, RED02, 0);
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 12, 2009, 06:24:01 PM
This is a very simple problem, and one that many people have often. Fortunately, the solution is simple, too. There's two methods you can use, both restated here before:

1: atan2. It works, as I heard it, by getting the angle from 0, 0 to the position you supply (such as GetPlayerX, GetPlayerY). However, this doesn't work in the default method, but there's a simple formula to make it work right:

atan2([Y of Target Point (where it goes to)] - [Y of Source Point (where it spawns from)], [X of Target Point] - [X of Source Point])

Thus, in your example, it'd be like this:

atan2(GetPlayerY - GetY, GetPlayerX - (GetX - 100))

That would check the angle at GetX-100, GetY, and angle to the player from there, instead of from GetX, GetY. The same can also be done in reverse (enemy minus player) for player shots to make them home in on bosses, but that, as far as I know, is the ONLY way to make them do such a thing with mere angles.

2: The absolute simplest method: SetShotDirectionType(PLAYER); That is all you have to do to make a shot get the angle to the player as Angle 0. In fact, this is the only method you can use on CreateShotA that will dynamically change according to where the player is at that point, whereas normally, you only get the value at the exact frame the bullet was spawned. This does not work for Player shots.

And that's what I know. Is there anything confusing about that? I stink at explaining half the time...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 12, 2009, 06:54:28 PM
This is a very simple problem, and one that many people have often. Fortunately, the solution is simple, too. There's two methods you can use, both restated here before:

1: atan2. It works, as I heard it, by getting the angle from 0, 0 to the position you supply (such as GetPlayerX, GetPlayerY). However, this doesn't work in the default method, but there's a simple formula to make it work right:

atan2([Y of Target Point (where it goes to)] - [Y of Source Point (where it spawns from)], [X of Target Point] - [X of Source Point])

Thus, in your example, it'd be like this:

atan2(GetPlayerY - GetY, GetPlayerX - (GetX - 100))

That would check the angle at GetX-100, GetY, and angle to the player from there, instead of from GetX, GetY. The same can also be done in reverse (enemy minus player) for player shots to make them home in on bosses, but that, as far as I know, is the ONLY way to make them do such a thing with mere angles.

2: The absolute simplest method: SetShotDirectionType(PLAYER); That is all you have to do to make a shot get the angle to the player as Angle 0. In fact, this is the only method you can use on CreateShotA that will dynamically change according to where the player is at that point, whereas normally, you only get the value at the exact frame the bullet was spawned. This does not work for Player shots.

And that's what I know. Is there anything confusing about that? I stink at explaining half the time...


Ah, it works now, I tried both of them and they did what I wanted. Thanks! ^_^

I've only used Danmakufu for a few days, still figuring out how things work. It would be nice if I could make at least one whole stage with it (or a whole game). Well, I only have two spellcards so far (Which I concider to be awesome).


Oh, another thing. Is there a space-saving time to make multiple bullets appear after each other, from a moving spot, in a span of, say, 100 frames, with 3 frames between each bullet?

In other words...

Code: [Select]
if(frame==3){
CreateShot01(GetX, GetY, 4, GetAngleToPlayer, RED01, 0);
frame=0;
}
if(frame==6){
CreateShot01(GetX, GetY, 4, GetAngleToPlayer, RED01, 0);
frame=0;
}
if(frame==9){
CreateShot01(GetX, GetY, 4, GetAngleToPlayer, RED01, 0);
frame=0;
}

etc...

It's quite a drag to make such long scripts for simple shots as this.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 12, 2009, 07:00:24 PM
Code: [Select]
   if(frame%3==0){
   CreateShot01(GetX, GetY, 4, GetAngleToPlayer, RED01, 0);
   }

Actually you could have just gotten rid of the bulk on yours if you wanted.

Code: [Select]
   if(frame==3){
   CreateShot01(GetX, GetY, 4, GetAngleToPlayer, RED01, 0);
   frame=0;
   }

But the former would let you do other things dependent on 'frame'.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on July 12, 2009, 07:03:39 PM
Slightly more detailed than Drake's response:

if (frame%3 == 0 && frame > *start frame* && frame < *end frame*){CreateShot01(GetX, GetY, 4, GetAngleToPlayer, RED01, 0);}

% works by dividing the number and getting the remainder, which will equal 0 if it divides cleanly. And in case you didn't know, && is and, || is or.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 12, 2009, 07:21:04 PM
Aha! I thought it had to do with dividing, I just couldn't find out how to actually make that work. But Drake's answer helped me out, thanks!
Onthenet's confused me even more though, can you write it in a codebox? Because I can't slice it apart to pieces that work, without getting error messages in Danmakufu.



Okay, last one for today, unless I find more questions really fast. :V
Another really common one I bet, but anyway:

I know how to make normal circles work (Read: I know where I left the txt file that has the code in it), but how do you get them to spin while moving outward?
I see it a lot in Touhou, for example Suwako's last spellcard (http://www.youtube.com/watch?v=JD7iT3wuJQ0) has only that, but I'm not having luck finding the code for it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 12, 2009, 07:40:32 PM
Do you know how to create a bullet with angular velocity? If not, look at the danmakufu basics tutorial by Blargel (http://www.shrinemaiden.org/forum/index.php?topic=30.0) and you will know.

Then, if you do know how to create bullets with an angular velocity, to create spinning bulletrings you just have to create a regular bullet ring and then give every bullet the same angular velocity. just make sure that it is small enough for the bullets not being able to go full circle and return to their starting point.

I believe Suwako's last spell's bullets are programmed in a way so that their angular velocity decreases over time, but I don't exactly know to which degree. You'd have to tinker with the numbers a little, I guess.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 12, 2009, 08:02:48 PM
Modulus works this way. Take for example the frame%3==0.

frame = 1
1/3 = 0.33
33 is not zero, so nothing happens.

frame = 2
2/3 = 0.66
66 is not zero, so nothing happens.

frame = 3
3/3 = 1(.0)
It's 0, so the statement is true.

frame = 12
12/3 = 4(.0)
Statement is true.

frame = 25
25/3 = 8.33
Nothing happens.

Get it? Onthenet's is just if you want to do something for a set time and then stop.

Code: [Select]
if(frame%3==0 && frame>300 && frame<600){
    CreateShot01(GetX, GetY, 4, GetAngleToPlayer, RED01, 0);
}

It will wait 300 frames, then fire every 3 frames for another 300 frames.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 12, 2009, 08:07:01 PM
Do you know how to create a bullet with angular velocity? If not, look at the danmakufu basics tutorial by Blargel (http://www.shrinemaiden.org/forum/index.php?topic=30.0) and you will know.

Then, if you do know how to create bullets with an angular velocity, to create spinning bulletrings you just have to create a regular bullet ring and then give every bullet the same angular velocity. just make sure that it is small enough for the bullets not being able to go full circle and return to their starting point.

I believe Suwako's last spell's bullets are programmed in a way so that their angular velocity decreases over time, but I don't exactly know to which degree. You'd have to tinker with the numbers a little, I guess.


I got that far, but the thing is, I can't find a way to link created shots with the circle.

This are the bits and piece I have so far:

Code: [Select]
if(frame==20){
CreateShotA(1, GetX, GetY, 0);
SetShotDataA(1, 30, 2, GetAngleToPlayer, 1, 0, 7, RED02);
}



if(frame==60){
let a   = 0;
let num = 24; //
        loop(num)
{
CreateShot01(GetX, GetY, 3, a+GetAngleToPlayer, RED01, 0);
a += 360/num;
}



if(frame==60){
FireShot(1);
frame=0;
}
}


In short: I made a big spinning bullet script and a circle script split in 3. Right now it shoots a circle with no special movement, and a single spinning bullet.
How do I modify it so it will replace the normal moving bullets with the new spinning bullets?




Drake:
Ah, okay. I found my own way to do that as well:

Code: [Select]
if(frame%6==0){
if(frame<=60){
CreateShot01(GetX, GetY, 4, GetAngleToPlayer, RED01, 0);
    }
}

if(frame==120){
frame=0;
}

As long as the frames not above 60 it won't shoot.

But the other way seems interesting too, thanks for sharing!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 12, 2009, 08:28:50 PM
I got that far, but the thing is, I can't find a way to link created shots with the circle.

This are the bits and piece I have so far:

Code: [Select]
if(frame==20){
CreateShotA(1, GetX, GetY, 0);
SetShotDataA(1, 30, 2, GetAngleToPlayer, 1, 0, 7, RED02);
}



if(frame==60){
let a   = 0;
let num = 24; //
        loop(num)
{
CreateShot01(GetX, GetY, 3, a+GetAngleToPlayer, RED01, 0);
a += 360/num;
}



if(frame==60){
FireShot(1);
frame=0;
}
}

In short: I made a big spinning bullet script and a circle script split in 3. Right now it shoots a circle with no special movement, and a single spinning bullet.
How do I modify it so it will replace the normal moving bullets with the new spinning bullets?
Umm...
If you think that your code should create a ring that spirals outwards, you probably didn't understand how the ShotA commands work properly.  You have to create a bullet with CreateShotA, configure its behaviour using SetShotDataA and then fire it with FireShotA. You have to repeat this three steps for every single bullet.

Thus, a correct version of the code would look like this:

Code: [Select]
if(frame==60){
let a   = 0;
let num = 24; //
        loop(num){
             CreateShotA(1, GetX, GetY, 0);
             SetShotDataA(1, 0, 2, GetAngleToPlayer+a, 0.5, 0, 7, RED02);
                     FireShot(1);
     a += 360/num;
}
       }
This, or at least a variation of this, should work.



On an entirely different note, am I the only one who uses the ascent function? All you other folks seem to always create regular loops in which a variable is increased. Am I missing something here?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 12, 2009, 08:35:38 PM
Thank you, now it works the way I want it :D
There was no sample script for this that explained it enough, so I had no idea it worked like this. I would never have guessed ^^;
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 12, 2009, 09:00:31 PM
You use ascent when you need a temporary variable, and usually for spawning mass amounts of bullets. When you have something that you need for more than one event, you increment it.

Well, more or less. It's pretty situational.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on July 13, 2009, 01:58:19 AM
On an entirely different note, am I the only one who uses the ascent function? All you other folks seem to always create regular loops in which a variable is increased. Am I missing something here?

I've noticed that some people use ascent, while others (like myself) just use the while ... ++ loop construct.  It's really a matter of preference.  It's Danmakufu's equivalent to the typical for loop structure.

Personally, coming from a C/C++ background, I find ascent's syntax a bit strange, so I don't use it.  But there's really no reason to choose one over the other when both could be applied.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 13, 2009, 02:17:23 AM
On an entirely different note, am I the only one who uses the ascent function? All you other folks seem to always create regular loops in which a variable is increased. Am I missing something here?

Pretty much what NC said. It's personal preference, which runs wild in Danmakufu. You can achieve the same results with while, loop, ascent, decent, ctrl v... Same issue with if and alternative/case (which almost nobody uses, probably because it isn't taught anywhere). I for one completely ignore the @MainLoop nowadays and just build everything in a myriad of tasks, while I see most people still operate using conditional statements in @MainLoop. Pikaguy900 uses an impressive amount of arrays in his scripts. It's all personal preference, since almost everything in Danmakufu can be done in at least two different ways.

Kinda makes reading other people's scripts confusing...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 13, 2009, 03:00:38 AM
Yeah I'm actually in the same boat as Cheese, I'm used to a different syntax on for loops and I never feel like looking up how to do ascent.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 13, 2009, 08:31:01 AM
I have a question regarding the reflecting/bouncing lasers from walls. I did the most stupid (and easiest) thing to copypaste the entire code from Touhou wiki. I was busy trying to recreate the laser show attack from Afro dude in Uwabami breakers.

So it works, very nice but the lasers keep on bouncing everytime they hit the wall or ceiling. How do I make the lasers bounce maximum 1 time against either ceiling/wall. So basicly: Laser is shot: bounces once against the ceiling or walls and then leaves the screen (can be either ceiling/wall/floor)

Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 13, 2009, 10:02:26 AM
Here's another simple one:
How do you make indestructible bullets that can survive both bombs, and the player when losing a life?
Is it as simple as CreateShot and adding a few commands, or does it need more than that?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 13, 2009, 12:44:21 PM
I have a question regarding the reflecting/bouncing lasers from walls. I did the most stupid (and easiest) thing to copypaste the entire code from Touhou wiki. I was busy trying to recreate the laser show attack from Afro dude in Uwabami breakers.

So it works, very nice but the lasers keep on bouncing everytime they hit the wall or ceiling. How do I make the lasers bounce maximum 1 time against either ceiling/wall. So basicly: Laser is shot: bounces once against the ceiling or walls and then leaves the screen (can be either ceiling/wall/floor)

If you created a task which shoots one bouncing laser,
Inside the task:
let notyetbounced = true;
if(notyetbounced)
{*insert whatever bounce codes*
notyetbounced = false;}


Here's another simple one:
How do you make indestructible bullets that can survive both bombs, and the player when losing a life?
Is it as simple as CreateShot and adding a few commands, or does it need more than that?

I think it can only be done by using Object Bullets?
Check out the awesome tutorial by Naut and Iryan : http://www.shrinemaiden.org/forum/index.php?topic=865.0
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 13, 2009, 02:09:44 PM
If you created a task which shoots one bouncing laser,
Inside the task:
let notyetbounced = true;
if(notyetbounced)
{*insert whatever bounce codes*
notyetbounced = false;}

Made 0 sense.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 13, 2009, 03:28:29 PM
If you created a task which shoots one bouncing laser,
Inside the task:
let notyetbounced = true;
if(notyetbounced)
{*insert whatever bounce codes*
notyetbounced = false;}

Made 0 sense.


Errmm...

Well, I suppose those bouncing lasers are Object Lasers, right?
There have to be some kind of condition statement like if(laser touches sides){bounce it}?
If we declare a boolean varible (such as NotYetBounced) = true inside a task (I don't know... I'm assuming each laser is created via a task :x)
and that the laser will only bounce while the boolean is true (that is, something like if((laser touches sides) && (NotYetBounced))
and that NotYetBounced will be assigned as false after the bounce code.
Then after bouncing once, the condition statement will no longer be true, and thus the laser won't bounce the next time it touches the sides.
If you wanted the lasers to bounce twice or more before leaving, you can use something like a counter varible, and add 1 to it each time a laser is bounced, and only carry out the bounce codes when that counter is smaller than a certain number, that is, bounced less than a certain amount of times.

I hope I'm understanding what you want and you're understanding what I'm saying. :x
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 13, 2009, 05:56:58 PM
Ah yes it is somehow starting to make sense. It is indeed a Object Laser (normal lasers cannot perform this unless you like want to script 4000 lines for a single bounce)

Anyway there are three tasks on wiki:
Code: [Select]
// Reflection laser
//     x      : x-coordinate
//     y      : y-coordinate
//     v      : velocity
//     angle  : initial direction angle
//     maxLen : max. length
//     width  : width
//     graphic: garphic of bullet
task TReflectionLaser(x, y, v, angle, maxLen, width, graphic) {
    // adjust the angle
    while(angle >= 180) { angle -= 360; }
    while(angle < -180) { angle += 360; }

    // bullet object
    let obj = Obj_Create(OBJ_LASER);

    // initial settings
    Obj_SetPosition   (obj, x, y);
    Obj_SetAngle      (obj, angle);
    ObjLaser_SetWidth (obj, width);
    ObjShot_SetGraphic(obj, graphic);
    ObjLaser_SetSource(obj, false);

    TReflectionLaser_Lengthen(obj, maxLen, v);
    TReflectionLaser_Move    (obj, x, y, v, angle);

    while(! Obj_BeDeleted(obj)) {
        x = Obj_GetX(obj);
        y = Obj_GetY(obj);

        // reflection detection
        if(angle < 0 && y < GetClipMinY) {
            // ceil
            TReflectionLaser(x, y, v, -angle, maxLen, width, graphic);
            break;
        } else if(((-90 < angle && angle < 90) && x > GetClipMaxX) ||
                   ((angle < -90 || 90 < angle) && x < GetClipMinX))
        {
            // wall
            TReflectionLaser(x, y, v, 180 - angle, maxLen, width, graphic);
            break;
        }
        yield;
    }
}

// lengthen the object laser
task TReflectionLaser_Lengthen(obj, maxLen, v) {
    let len = 0;
    let max = floor(maxLen / v);
    let i   = 0;

    while(! Obj_BeDeleted(obj)) {
        // When the length is negative,
        // the laser extends backward.
        ObjLaser_SetLength(obj, -len);
        yield;

        if(i < max) {
            len += v;
            i++;
        } else if(i == max) {
            ObjLaser_SetLength(obj, -maxLen);
            break;
        }
    }
}

// move the object laser
// Since Obj_SetSpeed is ignored in case of object laser,
// the motion needs to be controlled by Obj_SetPosition.
task TReflectionLaser_Move(obj, x, y, v, angle) {
    let vx = v * cos(angle);
    let vy = v * sin(angle);

    while(! Obj_BeDeleted(obj)) {
        Obj_SetPosition(obj, x, y);
        yield;

        x += vx;
        y += vy;
    }
}

So I should add the bounce boolean, as you said, at the reflection detection in the first task?

I added a  let bounce = true;  and  while(! bounce ==false) and concealed it with brackets. Well it works but all the lasers now don't bounce at all. I must add an extra parameter to the Task line so each laser gets tagged with a bounce value =.= But I have no idea how to achieve this as programming at these kind of situations never been my strongest side ( hence why I copypasted this code)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 13, 2009, 07:53:10 PM
I'd assume it's because you did "while(! bounce == false)"... That's a double-negative, so it's probably returning true from that... After all, if it's false that it's false, it HAS to be true that it's true, right? :/ Either way, I don't see the code you said is in there, so would you please post the WHOLE script, with all your added stuff included? After all, the error could be in another part of your script entirely!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 13, 2009, 08:15:18 PM
You don't get it: This is the entire code for the laser. The only extra code I have is a  looping task that summons the laser with the attributes like you summon a Laser01. I am asking where should I add what, such as I have no clue what to do =.=

And (! bounce == false) is the same as (! object_deleted) aka: As long as the bounce is not false -> execute the following script in other words bounce detecting.

Plus I said it works but the lasers don't bounce anymore when one laser hits the wall/ceiling. Because I don't know how to give each laser a bounce attribute. Right now they share the same variabel as it is local inside the task =.=
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on July 13, 2009, 08:47:52 PM
And (! bounce == false) is the same as (! object_deleted) aka: As long as the bounce is not false -> execute the following script in other words bounce detecting.
Then shouldn't be simpler to do "While (bounce==true)"? After all Booleans can only be True, False or Null.
Or even, if Danmakufu is really as similar as Java as I think, then "while (bounce)" should be enough.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 13, 2009, 09:20:21 PM
The statement is not the issue =,= the mechanism is.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 13, 2009, 09:35:35 PM
First off: The statement kinda IS a problem. See, you have both ! and == false. BOTH are checking for false, so logcically, I would assume, it's trying to check for if it's TRUE, not false. You really should only use one check for false and true. (True = "Bounce == true" or just "Bounce"; False = "!Bounce" or "Bounce == false")

Second: Well, there's two ways I could think of that might work the way you want it...


1: Arrays.
2: Make the bounce variable be started as one of the task's variables (like the first one's x, y, etc.), so each task will have its own "Bounce" variable that you can set to be true or false as needed. Considering how your lasers are right now, this would probably be the better method for you.

But I dunno.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 14, 2009, 01:21:45 AM
You don't get it: This is the entire code for the laser. The only extra code I have is a  looping task that summons the laser with the attributes like you summon a Laser01. I am asking where should I add what, such as I have no clue what to do =.=

And (! bounce == false) is the same as (! object_deleted) aka: As long as the bounce is not false -> execute the following script in other words bounce detecting.

Plus I said it works but the lasers don't bounce anymore when one laser hits the wall/ceiling. Because I don't know how to give each laser a bounce attribute. Right now they share the same variabel as it is local inside the task =.=

task TReflectionLaser(x, y, v, angle, maxLen, width, graphic) {
    // adjust the angle
    while(angle >= 180) { angle -= 360; }
    while(angle < -180) { angle += 360; }

    let NotYetBounced = true; //The laser had not yet bounced, so it's true.
    // bullet object
    let obj = Obj_Create(OBJ_LASER);

    // initial settings
    Obj_SetPosition   (obj, x, y);
    Obj_SetAngle      (obj, angle);
    ObjLaser_SetWidth (obj, width);
    ObjShot_SetGraphic(obj, graphic);
    ObjLaser_SetSource(obj, false);

    TReflectionLaser_Lengthen(obj, maxLen, v);
    TReflectionLaser_Move    (obj, x, y, v, angle);

    while(! Obj_BeDeleted(obj)) {
        x = Obj_GetX(obj);
        y = Obj_GetY(obj);

        //Now, I bracket up this whole thing with another if condition statement
        //If the laser has yet to bounce, then it has "Not Yet Bounced", the reflection detection will be carried out

        if(NotYetBounced)
        {
        // reflection detection
        if(angle < 0 && y < GetClipMinY) {
            // ceil
            TReflectionLaser(x, y, v, -angle, maxLen, width, graphic);
            NotYetBounced = false;
            break;
        } else if(((-90 < angle && angle < 90) && x > GetClipMaxX) ||
                   ((angle < -90 || 90 < angle) && x < GetClipMinX))
        {
            // wall
            TReflectionLaser(x, y, v, 180 - angle, maxLen, width, graphic);
            NotYetBounced = false;
            //Now here and the ceiling detection above, since this part of the statement inside the if condition statement is only carried out when the laser satisfies the condition, that is, going to bounce, I'm going to change the NotYetBounced boolean to false here, as it's... well... false, since it isn't really Yet to bounce anymore. Since it is false right now, and this Boolean is declared outside the while(!Obj_BeDeleted(obj)) loop, it is only carried out at the BEGINNING of the task, just before the object laser is created, this way, this local boolean of the task will remain to take the value "false". So, since the first reflection detection, the laser will never even get to the reflection detection part, as it is stopped at the if(NotYetBounced).
            break;
        }
        }
        yield;
    }
}

Not using code tags so you can see what I editing more easily.
I'm not sure if this works (didn't test it), but... you get the idea. :P
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 14, 2009, 06:27:55 AM
I appreciate the help you people give but I have the feeling people do not read it carefully. Or I am extremely bad at explaining.

Pikaguy, logically it makes no sense indeed to use such statements, but like I said the statement is not the issue here.

Thaws, I already tried that and I said that a local var does not work. If I take out the var and place it in @Initialize then it doesn't work either.

Like Pika said in his 2nd point (which I repeated twice), the variabel needs to be a parameter and linked to the object Laser. Though how?!?!?!?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 14, 2009, 07:18:59 AM
I appreciate the help you people give but I have the feeling people do not read it carefully. Or I am extremely bad at explaining.

Pikaguy, logically it makes no sense indeed to use such statements, but like I said the statement is not the issue here.

Thaws, I already tried that and I said that a local var does not work. If I take out the var and place it in @Initialize then it doesn't work either.

Like Thaws said in his 2nd point (which I repeated twice), the variabel needs to be a parameter and linked to the object Laser. Though how?!?!?!?

I looked at the code mroe closely and realised my mistake :P using a parameter instead shouldn't be too hard though...
I never tried referring a task itself inside the task, but this should work.


//When creating a laser, enter 0 for the parameter of counter.

task TReflectionLaser(x, y, v, angle, maxLen, width, graphic, counter) {
    // adjust the angle
    while(angle >= 180) { angle -= 360; }
    while(angle < -180) { angle += 360; }

    // bullet object
    let obj = Obj_Create(OBJ_LASER);

    // initial settings
    Obj_SetPosition   (obj, x, y);
    Obj_SetAngle      (obj, angle);
    ObjLaser_SetWidth (obj, width);
    ObjShot_SetGraphic(obj, graphic);
    ObjLaser_SetSource(obj, false);

    TReflectionLaser_Lengthen(obj, maxLen, v);
    TReflectionLaser_Move    (obj, x, y, v, angle);

    while(! Obj_BeDeleted(obj)) {
        x = Obj_GetX(obj);
        y = Obj_GetY(obj);

        if(counter < *insert number of time you want it to bounce*)
        {
        // reflection detection
        if(angle < 0 && y < GetClipMinY) {
            // ceil
            TReflectionLaser(x, y, v, -angle, maxLen, width, graphic, counter+1);
            break;
        } else if(((-90 < angle && angle < 90) && x > GetClipMaxX) ||
                   ((angle < -90 || 90 < angle) && x < GetClipMinX))
        {
            // wall
            TReflectionLaser(x, y, v, 180 - angle, maxLen, width, graphic, counter+1);
            break;
        }
        }
        yield;
    }
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 14, 2009, 04:02:03 PM
That worked like a charm Thaws. That was exactly the issue I was looking for. adding the counter+1 behind the paremeters in the detection section.

Now I just need to find out how to make this more beautiful, as the laser that is going to be reflected or leaves the screen suddenly dissapears instead of shrinking.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 14, 2009, 05:38:06 PM
Okay, no matter what I do, I can not get circleshots that don't shoot from the same spot to work. I copied the exact examples posted in the tutorials, and I still keep getting error messages. The best thing I got to appear was one single bullet aiming south-east. But any further step I take ends in errors, even if I use the examples shown.

I want to make a circle that appears around the player and then shrinks in on you, so according to the examples I found, my code should look something like this:

Code: [Select]
if(frame==60){
let a   = 0;
let num = 360;
       
loop(num)
{
CreateShot02(GetPlayerX + 100*cos(60), GetPlayerY + 100*sin(60), -1, a+GetAngleToPlayer, 0.02, -3, RED01, 0);
a += 360/num;
}
}

...Except that it doesn't work.

How do I change this to a working shot?
And can someone post an example shot involving sinus and cosinus that will work?


This is the example from the tutorial, which worked for me only once, but after that completely rejects me if I try to use it again:

Code: [Select]
if(frame==120){
   loop(36){
      CreateShot01(GetX + 60*cos(angle), GetY + 60*sin(angle), 3, angle, BLUE12, 12);
      angle += 360/36;
   }
   angle += 4;
   frame = 112;
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 14, 2009, 06:45:42 PM
Make it like this:

if(frame==120){
   let u = 60;
   loop(36){
      CreateShot01(GetPlayerX + u*cos(angle), GetPlayerY + u*sin(angle), 3, angle, BLUE12, 12);
      angle += 360/36;
      u--;
   }
   angle += 4;
   frame = 112;
}

The u = the radius which will shrink because of u--; If you want to make it shrink faster use a higher value like u-=2; etc. If you want to expand the circle use u++;

Just becareful that eachtime the loop is executed the Circle will be spawned on your current position. You can lock the last X and Y position if you put these into a variabel before calling the loop.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 14, 2009, 06:53:22 PM
Make it like this:

if(frame==120){
   let u = 60;
   loop(36){
      CreateShot01(GetPlayerX + u*cos(angle), GetPlayerY + u*sin(angle), 3, angle, BLUE12, 12);
      angle += 360/36;
      u--;
   }
   angle += 4;
   frame = 112;
}

The u = the radius which will shrink because of u--; If you want to make it shrink faster use a higher value like u-=2; etc. If you want to expand the circle use u++;

Just becareful that eachtime the loop is executed the Circle will be spawned on your current position. You can lock the last X and Y position if you put these into a variabel before calling the loop.



I just copied the exact code into my main loop, but still:

(http://i32.photobucket.com/albums/d49/puremrz/errorhatesme.png)

Can anything besides this piece of the script not want to cooperate with it?

My full file looks like this:

Code: [Select]
#TouhouDanmakufu
#Title[Sinus Cosinus circles]
#Text[Test]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {

let frame = 0;
let count=0;
let cx=GetCenterX();
let changing = 0;


    @Initialize {
SetScore(30000);
SetLife(300);
SetDamageRate(10,10);
SetTimer(60);

SetGraphicRect(1,1,64,64);
SetInvincibility(30);

SetMovePosition02(cx,224,240);
Concentration01(150);
CutIn(YOUMU,"Test "\""Test"\", 0,0,0,0,0);

   }

    @MainLoop {

SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

frame++;


if(frame==120){
  let u = 60;
   loop(36){
      CreateShot01(GetPlayerX + u*cos(angle), GetPlayerY + u*sin(angle), 3, angle, BLUE12, 12);
      angle += 360/36;
      u--;
   }
   angle += 4;
   frame = 112;
}



    }

    @DrawLoop {       
    }

    @Finalize {
    }
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on July 14, 2009, 07:01:12 PM
Maybe writing an actual angle would work better than using (angle).
Because you know, that's a placeholder.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 14, 2009, 07:05:50 PM
That or he forgot to declare it. Declare: let angle = 0; in your script and it is done.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 14, 2009, 07:13:33 PM
That almost did it.

It doesn't error now, although it doesn't work as I hoped. The player is not surrounded by a circle, but something that looks more like a shell. The circle doesn't form a complete loop.

(http://i32.photobucket.com/albums/d49/puremrz/stillhatesme.png)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 14, 2009, 07:42:57 PM
I really can't help you right now because I don't know what the hell you want to do.

MSPaint drawing, stat.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 14, 2009, 07:46:59 PM
I want to make a circle that appears around the player and then shrinks in on you

So, like...

(http://i32.photobucket.com/albums/d49/puremrz/this.png)

..this, because I'm a sadist.
Right now it forms anything besides a nice circle.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 14, 2009, 07:52:50 PM
Try this:

Code: [Select]
ang=rand(0, 360);
ascent(i in 0..n){
   CreateShotA(1, GetPlayerX+r*cos(ang+360*i/n), GetPlayerY+r*sin(ang+360*i/n), 10);
   SetShotDataA(1, 0, 0, ang+360*i/n + 180, 0, 0.05, 2, BLUE11);
   FireShot(1);
}

n = number of bullets
r = radius of the circle

The variable "ang" has to be created in the beginning of the script, of course. It exists solely to randomize the alignment of the ring a little.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 14, 2009, 08:12:38 PM
Try this:

Code: [Select]
ang=rand(0, 360);
ascent(i in 0..n){
   CreateShotA(1, GetPlayerX+r*cos(ang+360*i/n), GetPlayerY+r*sin(ang+360*i/n), 10);
   SetShotDataA(1, 0, 0, ang+360*i/n + 180, 0, 0.05, 2, BLUE11);
   FireShot(1);
}

n = number of bullets
r = radius of the circle

The variable "ang" has to be created in the beginning of the script, of course. It exists solely to randomize the alignment of the ring a little.


It still errors. *cries*
Can somebody put down the code of a complete file, instead of just a part, and confirm the techniques which work best?
With just these small bits and pieces it's easy to make mistakes or to oversee things that other people do in a different way.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 14, 2009, 08:25:26 PM
D'oh!

You refer to a variable of the name "angle" in your script, but you don't have created a variable of that name with the command "let angle=0;".

Also, your code cannot create a circle as you have the variable "u" which regulates the radius decrease with every spawned bullet, causing the pattern to look like a spiral.

If I go into your code and fix it, it looks something like this:

Code: [Select]
#TouhouDanmakufu
#Title[Sinus Cosinus circles]
#Text[Test]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {

   let frame = 0;
   let angle = rand(0, 360);
   let count=0;
   let cx=GetCenterX();
   let changing = 0;
   let u = 60;


    @Initialize {
      SetScore(30000);
      SetLife(300);
      SetDamageRate(10,10);
      SetTimer(60);

      SetGraphicRect(1,1,64,64);
      SetInvincibility(30);

      SetMovePosition02(cx,224,240);
      Concentration01(150);
      CutIn(YOUMU,"Test "\""Test"\", 0,0,0,0,0);

   }
   
    @MainLoop {

SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

frame++;


if(frame==120){
   loop(36){
      CreateShot01(GetPlayerX + u*cos(angle), GetPlayerY + u*sin(angle), 3, angle, BLUE12, 12);
      angle += 360/36;
   }
   angle += 4;
   frame = 112;
}



    }

    @DrawLoop {       
    }

    @Finalize {
    }
}

Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 14, 2009, 08:36:14 PM
D'oh!

You refer to a variable of the name "angle" in your script, but you don't have created a variable of that name with the command "let angle=0;".

Also, your code cannot create a circle as you have the variable "u" which regulates the radius decrease with every spawned bullet, causing the pattern to look like a spiral.

If I go into your code and fix it, it looks something like this:

Code: [Select]
#TouhouDanmakufu
#Title[Sinus Cosinus circles]
#Text[Test]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {

   let frame = 0;
   let angle = rand(0, 360);
   let count=0;
   let cx=GetCenterX();
   let changing = 0;
   let u = 60;


    @Initialize {
      SetScore(30000);
      SetLife(300);
      SetDamageRate(10,10);
      SetTimer(60);

      SetGraphicRect(1,1,64,64);
      SetInvincibility(30);

      SetMovePosition02(cx,224,240);
      Concentration01(150);
      CutIn(YOUMU,"Test "\""Test"\", 0,0,0,0,0);

   }
   
    @MainLoop {

SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

frame++;


if(frame==120){
   loop(36){
      CreateShot01(GetPlayerX + u*cos(angle), GetPlayerY + u*sin(angle), 3, angle, BLUE12, 12);
      angle += 360/36;
   }
   angle += 4;
   frame = 112;
}



    }

    @DrawLoop {       
    }

    @Finalize {
    }
}



The angle variable was a remainder of an old script, but I forgot to remove it ^^;

Ah, but it actually works now! I should be able to change this into a CreateShot2 so it can accelerate and do more mean tricks. Or lasers... *drool*
I'm so glad these sinus/cosinus circles work. *cries Mannosuke tears*
Those two together with tangens have always hated me, during math classes too. But those classes were nothing compared to Danmakufu ^^;
Thanks a bunch, now I can sleep without fear again! ;D
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 14, 2009, 08:41:06 PM
Actually keep it as ShotDataA as ShotDataA allows more control such as first making it move slowly then faster. If you modify the 0.05 you can increase the acceleration.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 15, 2009, 09:24:12 AM
Hmmm reading the Intermediate tutorial about Events and stages did succeeded in making a dialogue and a stage but I somehow cannot seem to end the dialogue aswell as making the boss spawn after the dialogue. Right now as it is in my script it spawns directly during the dialogue.


Edit: NVM, Forum effect detected! I was writing getEventStep with a lower g instead of capital G =.=
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 15, 2009, 03:28:56 PM
if(OnEvent==true){yield;}

Might be a bit easier than using GetEventStep....
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 15, 2009, 03:50:54 PM
I do have one question. What is the general reason for danmakufu (a plurar script) to slowdown after like 2 non-spells and 2 spellcards and eventually receiving critical error and it shuts down. As currently I am having it and before I didn't except I cannot remember what exactly I have added or not so what are things to watch out for?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 15, 2009, 07:18:22 PM
If you don't delete any data on Finalize, it could build up. Or maybe objects don't entirely dissapear, or something of the sort. Something is lingering in your script.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 15, 2009, 07:46:30 PM
Stuffman discovered the error on IRC. It was inside my stage script afterall.

?20:57:12? <Stuffman> Okay! I think I fixed it Helepolis
?20:57:46? <Stuffman> First, move BeginShowDown from @MainLoop to the end of @Initialize
?20:58:47? <Stuffman> Then go to BeginShowDown and put a loop(60){yield;} before CreateEnemyBossFromFile, you need to do this because if you try to load the boss too fast it fails
?20:58:58? <Helepolis> rgr
?21:04:49? <Stuffman> Yeah see what was happening was, in your stage it was calling BeginShowDown every loop, so over the course of the fight it builds up a million of those tasks
?21:04:53? <Stuffman> And it causes slowdown
?21:05:00? <Helepolis> That is perhaps also why the next Afro spawned
?21:05:07? <Helepolis> it was waiting for the enemyzero probably
?21:05:12? <Stuffman> Yeah
?21:03:56? <Helepolis> Awesome Stuffman.
?21:04:08? <Helepolis> Thanks ( '_' )=b
?21:04:11? <Stuffman> That fixed it for you too right?
?21:04:16? <Helepolis> Like a charm.

So there you see that somehow the most annoying things are caused by the most simple. =S
Thanks all though who helped.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 15, 2009, 07:51:15 PM
Oh god lol.

I had a similar thing with enemy targeting for Reimu. It kept spawning targeting objects every frame for every enemy, and it slowed down really, really fast.
Title: Problems concerning subroutines, functions and tasks
Post by: Henry on July 16, 2009, 12:14:55 PM
It may be a little bit silly to ask:

If I what to simplify statements using subroutine, for example:
(only MainLoop is shown for convenience)
Code: [Select]
@MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);

        if(frame%10==0&&frame>0) {
            CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 30, RED02, 0);
            CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 20, RED02, 0);
            CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 10, RED02, 0);
            CreateShot01(GetX, GetY, 3, GetAngleToPlayer, RED02, 0);
            CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 10, RED02, 0);
            CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 20, RED02, 0);
            CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 30, RED02, 0);
        }
        frame++;
}

then I attempted to use the following statements:
Code: [Select]
#TouhouDanmakufu
#Title[... "..."]
#Text[Test script for subroutine]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let ImgBoss = "script\img\ExRumia.png";

    let frame = -120;
    @Initialize {
       SetLife(3000);
       SetTimer(120);
       SetScore(1000000);
       SetDurableSpellCard();
       SetDamageRate(50,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "... "\""..."\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);

        if(frame%10==0&&frame>0) {
            firebullets;
        }
        frame++;
    }

    @DrawLoop {
        DrawGraphic(GetX, GetY);
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
}
sub firebullets{
   CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 30, RED02, 0);
   CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 20, RED02, 0);
   CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 10, RED02, 0);
   CreateShot01(GetX, GetY, 3, GetAngleToPlayer, RED02, 0);
   CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 10, RED02, 0);
   CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 20, RED02, 0);
   CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 30, RED02, 0);
}
However, this is unsuccessful. I would like to ask that if we want to use subroutine/function/task, where should I put the sub{}/function(){}/task() block?
Also, when is the statement "yield;" used?

P.S. If I have some statements (such as background setting in a stage) to use, can I put the statements in a function in a new file, then I call them in the files I would like to apply to?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on July 16, 2009, 01:42:49 PM
The sub/function/task should be before the last bracket "}" which is after @finalize but before you end the script which is what the last "}" does, or before the @initialize... "yield;" is used for tasks...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 16, 2009, 02:37:30 PM
thanks a lot. However, I also see that we can use #include_function, should it be put after @finalize or before the @initialize?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on July 17, 2009, 01:24:34 AM
I think it should be before the "script_enemy_main" part where you put the:
#TouhouDanmakufu
#Title[...]
#Text[...]
#Image[...]
#ScriptVersion[2]

that's where I've seen people placing it... but I'm not sure since I've never used that...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 17, 2009, 01:35:00 AM
Before @Initialize is where I usually put anything outside of @Loops (tasks, #includes, global variables) but it doesn't actually matter. Whenever you want it to be seen, included, or delcared. The reason why i put it before everything is so you can see the things I'm going to be using before you actually dive into the script, instead of "wtf is this parameter I haven't seen this".
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on July 17, 2009, 01:55:39 AM
One very pointless thing:
How do you make it so that Danmakufu will let a boss drop a power item things? As in, one of those blocks with the "P" on them?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 17, 2009, 02:09:09 AM
There aren't any measurements of Power in Danmakufu, so if you're aiming to make a player with different capabilities at different levels, you're going to have to make custom objects.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 17, 2009, 04:08:49 AM
Code: [Select]
#TouhouDanmakufu
#Title[... "..."]
#Text[Test script for tasks]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let ImgBoss = "script\img\ExRumia.png";
    let frame = -120;
    @Initialize {
       SetLife(3000);
       SetTimer(120);
       SetScore(1000000);
       SetDurableSpellCard();
       SetDamageRate(50,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "... "\""..."\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
       LoadUserShotData(GetCurrentScriptDirectory~"images\shot_All.txt");
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);

        if(frame%10==0&&frame>0) {
            yield;
        }
        frame++;
    }

    @DrawLoop {
        DrawGraphic(GetX, GetY);
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
    task fireshot3{
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 30, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 20, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 10, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 10, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 20, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 30, RED02, 0);
       yield;
    }
}
Why these statements don't work?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 17, 2009, 04:14:41 AM
You need to actually call fireshot3. You've declared it but you aren't using it anywhere.

Add fireshot3(); to your @MainLoop, just above the yield.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 17, 2009, 04:57:21 AM
Code: [Select]
#TouhouDanmakufu
#Title[... "..."]
#Text[Test script for tasks]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let ImgBoss = "script\img\ExRumia.png";
    let frame = -120;
    @Initialize {
       SetLife(3000);
       SetTimer(120);
       SetScore(1000000);
       SetDurableSpellCard();
       SetDamageRate(50,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "... "\""..."\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
       LoadUserShotData(GetCurrentScriptDirectory~"images\shot_All.txt");
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);

        if(frame%10==0&&frame>0) {
            yield;
        }
        frame++;
    }

    @DrawLoop {
        DrawGraphic(GetX, GetY);
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
    task fireshot3{
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 30, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 20, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer - 10, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 10, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 20, RED02, 0);
       CreateShot01(GetX, GetY, 3, GetAngleToPlayer + 30, RED02, 0);
       yield;
    }
}
Why these statements don't work?

By the way, the yield command at the end of the task here and at the MainLoop is unnecessary actually, the yield is only needed when you want to pause the task for a moment (such as create a bunch of bullets that appear one by one not simultaneously) or "cut off" a loop so that Danmakufu will process stuff in the MainLoop as well (and to prevent a never ending loop in certain situations).

Just letting you know...so you don't think yield; as something that's just someting you just include in your task because the guide says so or whatever...

Sorry if you already know about these though... if so, then just ignore this post. :P
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 17, 2009, 05:57:43 AM
nevermind.

I REALLY think yield; is some most-powerful statements in the script because I see SO many scripts containing it. lol

Thanks a lot :)

P.S. Is there a time limit for the background music used?
I have 2 version of a music.
1 is 2.93MB (6:24 length)
Another is 4.16 MB (4:32 length)
I can use the 4:32 version but not the 6:24 version, why?

P.S. the 6:24 version is MONO, can DMF play mono music?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 17, 2009, 05:04:09 PM
What filetype are they? I had a lot of trouble getting OGGs to work in Danmakufu.

Danmakufu has very buggy sound code, I can't get any of the commands that are supposed to stop the music to work for some reason.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 17, 2009, 08:42:20 PM
I can use the 4:32 version but not the 6:24 version, why?

Filetypes, variable bitrates, Danmakufu being a bitch.... Any of the above really. Try converting it to .wav (will be a massive file), it should play then. .mp3 usually works as well, so throw it through a few music converters and see if it works then.

Danmakufu has very buggy sound code, I can't get any of the commands that are supposed to stop the music to work for some reason.

DeleteMusic(music);

I don't dick around with any of this StopSE bullshit or anything, I just get rid of the damn file to stop it from playing. Works like a charm for me.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 18, 2009, 11:33:00 AM
Question regarding the bouncing object asers on wiki.

The lasers dissapear upon impact so I added a line which OnTheNet suggested me: SetShotAutoDeleteClip(GetClipMinX,GetClipMinY,GetClipMaxX,GetClipMaxY);

However the right side of the gamefield works like a charm. The lasers no longer instant dissapear but go "inside" the wall as if they are being reflected. However the left side of the game field is not looking beautiful as the lasers instant dissapear. I even tried to add a negative value in the Left / Top bound but no results.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 18, 2009, 11:46:08 AM
Question regarding the bouncing object asers on wiki.

The lasers dissapear upon impact so I added a line which OnTheNet suggested me: SetShotAutoDeleteClip(GetClipMinX,GetClipMinY,GetClipMaxX,GetClipMaxY);

However the right side of the gamefield works like a charm. The lasers no longer instant dissapear but go "inside" the wall as if they are being reflected. However the left side of the game field is not looking beautiful as the lasers instant dissapear. I even tried to add a negative value in the Left / Top bound but no results.

Try something like
SetShotAutoDeleteClip(100, 100, 100, 100);
or larger.
It seems that this function's parameters actually means that the bullet deletion border on the respective sides will be *inserted number* away from the edge of the game field.

This is why the right side works, because the border for detection of deleting bullets is now 448 (value of GetClipMaxX) away from the right edge of the game field.

It got me so confused when I tried to use it for the first time too. >_>
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 18, 2009, 02:55:32 PM
Ah, 100,100,100,100 was not enough but adding 300 solved the problem. Now the lasers don't dissapear but flow into the wall. Now it looks much more beautiful ^^ .
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 18, 2009, 09:41:25 PM
Hey, does anyone know how to make a boss enemy stay on-screen after it's defeated, then leave the screen afterwards? I'd like to have this be done to a familiar enemy in one of my spellcards that isn't spawned by the boss, but instead just comes onto the screen like the boss itself does, then, after the spellcard is defeated, said enemy doesn't blow up, but instead just leaves the screen, like CtC somehow did. I'd look in CtC's scripts for an answer, but last time I did, I found a whole bunch of calls to other files, barely even finding what I wanted... I don't think it's worth it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 19, 2009, 01:36:04 AM
Stage file. ->
Spawning enemies and such. ->
Spawn your midboss plural file. ->
On the last script of your plural file, at the very end (When GetEnemyLife<=0), set two sets of common data: the boss's last x and y position. ->
The same frame the plural file ends, spawn an enemy with the same graphic as the midboss on the common data coordinates you saved. Have the enemy's script only have SetMovePosition or something in it so that it moves off screen and kills itself without having that big-assed explosion effect you always see.

Thats what I can think of that will work relatively well. The other way I thought of was to have the rest of the stage programmed into the last file of the plural script, like this:

Plural file script: the last script in it only has the boss move offscreen, then the script proceeds into a task that plays out like a stage; Spawning enemies and whatnot. The only problem I can think of is that homing character scripts might still try to target the offscreen boss, or you might have a problem getting rid of the healthbar (I don't know the function offhand).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on July 19, 2009, 02:13:20 PM
hello, i have a question :/
i want to create a c4 bomb attack for the playable character Rumia so i needed a button to use and GetKeyState says there's an user-defined key available... how can I define this user-defined key?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on July 19, 2009, 04:59:45 PM
For some reason when I try to load my danmakufu script, it has an error. I'm just trying to get the enemy to show.  :V

Code: [Select]
#TouhouDanmakufu
#Title[Queen's Demise "De-Coronation"]
#Text[De-Coronation]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let imgExRumia=GetCurrentScriptDirectory~"img\ExRumia.png";
let imgExRumiaBack=GetCurrentScriptDirectory~"img\ExRumiaBack.png";
    @Initialize {
SetMovePosition02(cx,60,60);
SetGraphicRect(1,1,64,64);
        LoadGraphic(imgExRumia);
LoadGraphic(imgExRumiaBack);
        SetLife(100);
        SetDamageRate(10, 10);
        SetTimer(50);
        SetInvincibility(5);
        CutIn(YOUMU, Queen's Demise "De-Coronation", imgExRumiaBack, 0, 0, 200, 600);
        SetScore(500000);
        SetEnemyMarker(true);
        SetDurableSpellCard;
        MagicCircle(false);
        SetEffectForZeroLife(180, 100, 1);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 24);
        if(frame==60){
            CreateShot01(GetX, GetY, 3, GetAngleToPlayer, RED01, 10);
            frame = 0;
        }
        frame++;
    }

    @DrawLoop {
SetAlpha(255);
SetTexture(imgExRumia);
DrawGraphic(GetX(),GetY());
       
    }

    @Finalize {
    }
}

Any help? I'm using the default rumia texture.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 19, 2009, 05:33:55 PM
The problem is in your cutin. Whenever you're putting in text for a function it needs to be in quotes. So instead of
CutIn(YOUMU, Queen's Demise "De-Coronation", imgExRumiaBack, 0, 0, 200, 600);
it should be
CutIn(YOUMU, "Queen's Demise [De-Coronation]", imgExRumiaBack, 0, 0, 200, 600);
It's giving you an error because the whole thing wasn't specified as a string, and it doesn't know what a "Queen's Demise" is.

Also, you need to declare cx and frame.

Quote
i want to create a c4 bomb attack for the playable character Rumia so i needed a button to use and GetKeyState says there's an user-defined key available... how can I define this user-defined key?
The user-defined key is just a miscellaneous key; it's like the shot key or the bomb key, except it doesn't do anything normally. It's just there if a programmer wants to use it. It's set to whatever the player sets it to in their config, I forget what key it is by default. The code for it for GetKeyState is VK_USER.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on July 19, 2009, 05:41:54 PM
Thanks! With a few other bug fixes it worked.

Also, this isn't a needed question, but I'm not really getting how people do the Particle of Wave and Particle spellcard because of all the crossing back.

Also, what are the dimensions of the visible field?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 19, 2009, 06:18:34 PM
hello, i have a question :/
i want to create a c4 bomb attack for the playable character Rumia so i needed a button to use and GetKeyState says there's an user-defined key available... how can I define this user-defined key?
As Stuffman said, it's in the config, and it's defaulted to the C key, for future reference. (Just be careful when using it, though, as I have a habit of accidentally Bombing when I mean to hit C...)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 19, 2009, 08:25:23 PM
Also, this isn't a needed question, but I'm not really getting how people do the Particle of Wave and Particle spellcard because of all the crossing back.

CreateShot01(GetX, GetY, 3, angle, RED12, 10);
angle+=var;
var++;


Essentially you're just incrementing by an incrementing variable, which looks like it doubles back once it gets so high in value, but it really doesn't.


Also, what are the dimensions of the visible field?

(http://i641.photobucket.com/albums/uu134/Nautth/DanmakufuWindow.jpg)

The red area is where the player can move around freely, the black area is the visible playing field.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on July 19, 2009, 09:11:33 PM
2 things I noticed, which I'm going to try to fix by myself. One does not annoy me, the other one does.

1. It repeats. However , it's spread out over a long period of time.
2. The more streams you add, the faster it repeats, to where you can easily find safespots  >:(
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 19, 2009, 09:17:04 PM
Yes, it does repeat, because when you're incrementing by a nice number it will eventually divide out evenly by 360. Usually I increment by about 0.1 or less to spread out the pattern more, as well as get rid of the safe spots. Incrementing by 1 is quite high for Border of Wave and Particle.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on July 19, 2009, 09:37:13 PM
Thanks for the help, and I have one more thing I need help with.
Code: [Select]
#TouhouDanmakufu
#Title[Queen's Demise "De-Coronation"]
#Text[De-Coronation]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let imgExRumia=GetCurrentScriptDirectory~"img\ExRumia.png";
let imgExRumiaBack=GetCurrentScriptDirectory~"img\ExRumiaBack.png";
let frame=0;
    @Initialize {
        LoadGraphic(imgExRumia);
SetGraphicRect(1,1,64,64);
LoadGraphic(imgExRumiaBack);
        SetLife(100);
        SetDamageRate(1, 1);
        SetTimer(50);
        SetInvincibility(5);
CutIn(YOUMU, "Queen's Demise [De-Coronation]", imgExRumia, 0, 0, 50, 60);
        SetScore(500000);
        SetEnemyMarker(true);
        SetDurableSpellCard;
        MagicCircle(false);
        SetEffectForZeroLife(180, 100, 1);
SetMovePosition01(224,100,100)
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 24);
if(frame==GetEnemyLife()){
CreateShot01(GetX, GetY, 3, rand(1,360), RED03, 10);
frame=0;
}
frame++;




    }

    @DrawLoop {
SetGraphicRect(64,64,127,127);
SetAlpha(255);
SetTexture(imgExRumia);
DrawGraphic(GetX(),GetY());
       
    }

    @Finalize {
    }
}

When I damage the enemy, it stops shooting.

Any help?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 19, 2009, 10:52:45 PM
Frame is an integer, but most players don't do damage in integers. For instance if a boss has 49.5 life, it won't shoot on either frame 49 or 50, and thus won't shoot at all.

Try the floor() function, which removes any decimals.
if(frame==floor(GetEnemyLife())){...

EDIT: Actually ceil() would be better since it won't make the boss stop shooting with less than 1 life. (It rounds up instead of down)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 20, 2009, 02:28:12 PM
I am a totally newbie on Shot Objects...

Code: [Select]
#TouhouDanmakufu
#Title[QED "Ripples of 495 Years"]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let ImgBoss = "script\img\ExRumia.png";
    let frame = -120;
    let i;
    let angle=[];
    @Initialize {
       SetLife(3000);
       SetTimer(120);
       SetScore(1000000);
       SetDurableSpellCard();
       SetDamageRate(50,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "QED "\""Ripples of 495 Years"\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
       LoadUserShotData(GetCurrentScriptDirectory~"images\shot_All.txt");
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        if(frame==10) {
           ascent(i in 0..64){
             Obj_Create(OBJ_SHOT);
             Obj_SetPosition(i, GetX, GetY);
             Obj_SetSpeed=1;
             angle=angle~(i*360/64);
             Obj_SetAngle(i, angle[i]);
             ObjShot_SetGraphic(i, 45);
           }
        }
        if(frame>10){
           ascent(i in 0..64){
              if(Obj_GetX(i)==GetClipMaxX||Obj_GetX(i)==GetClipMaxX){
                 angle[i]=180-angle[i];
                 Obj_SetAngle(i, angle[i]);
              }
              if(Obj_GetY(i)==GetClipMaxY||Obj_GetY(i)==GetClipMaxY){
                 angle[i]=-angle[i];
                 Obj_SetAngle(i, angle[i]);
              }
           }
        }
        frame++;
    }

    @DrawLoop {
        DrawGraphic(GetX, GetY);
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
}
Why when I run this script, after the boss show up, it freezes?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 20, 2009, 02:47:25 PM
Well...

Your code contains the nonsensical command Obj_SetSpeed=1; for once. It should read Obj_SetSpeed(i, 1);, and even then I am not entirely shure it will work. While it is possible to code objects in the main loop, this is not recommended unkess you want to refer to a specific object colliding with another specific object, which you don't. Instead, you tell danmakufu to create a minor script that runs beside the main loop which is called a task. How tasks are coded and how you create object bullets using them can be found in the Intermediate Danmakufu Tutorial (http://www.shrinemaiden.org/forum/index.php?topic=865.0) anout one third down the page. It even directly explains how you create a bullet that bounces off of the borders of the playing field. ;)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on July 21, 2009, 02:08:56 AM
Well...

Your code contains the nonsensical command Obj_SetSpeed=1; for once. It should read Obj_SetSpeed(i, 1);, and even then I am not entirely shure it will work. While it is possible to code objects in the main loop, this is not recommended unkess you want to refer to a specific object colliding with another specific object, which you don't. Instead, you tell danmakufu to create a minor script that runs beside the main loop which is called a task. How tasks are coded and how you create object bullets using them can be found in the Intermediate Danmakufu Tutorial (http://www.shrinemaiden.org/forum/index.php?topic=865.0) anout one third down the page. It even directly explains how you create a bullet that bounces off of the borders of the playing field. ;)

While I'm not trying to be an elitist jerk ... I highly recommend against using tasks in the manner you're suggesting.  It's very inefficient, and will start to bring down the game's performance before too long.

Instead, I recommend using an array to keep track of object shots, as demonstrated in my object shot tutorial (http://dmf.shrinemaiden.org/wiki/index.php?title=Nuclear_Cheese%27s_Shot_Object_Tutorial).  It's a bit harder to chew at first, but its a much better approach in the long run.

To be fair, you could use a single task to control all object shots as in the tutorial, but honestly, I prefer to just do it in @MainLoop directly.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on July 21, 2009, 02:26:51 AM
I recommend using an array
Now that you mention this, is it posible to use Linked Lists?
(A list made of Nodes, that works like an array but without a limit of objects)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on July 21, 2009, 03:10:41 AM
I am a totally newbie on Shot Objects...

Code: [Select]
t3h codezWhy when I run this script, after the boss show up, it freezes?

I got a chance to look over your code, and I've found a few issues.

1) As Iryan pointed out, Obj_SetSpeed = 1 isn't the way to set object speed.  Instead, use Obj_SetSpeed(i, 1)

2) More importantly, when you use Obj_Create(OBJ_SHOT) you need to store the value that it returns, and use that as the object ID to pass the other Obj_ functions.  Have you seen the object shot tutorial I made (linked in my previous post)?  It might help you get a better grip on using these.


Overall, it looks like you're trying to assume that the object shots you create are given the IDs 0 through 64 ... this is a bad assumption and is very likely what is causing the crash.  You need to use and store the IDs returned from Obj_Create(OBJ_SHOT) in order to properly refer to the object shots.  Again, you can reference my object shot tutorial (linked in my previous post) for some basis on this.

Another hint - you don't need to store the angle of each shot.  You can get is using the shot's ID with the function Obj_GetAngle().


Unfortunately, I don't really have the time to get into a more in-dept debugging of it.  I need to at least try and get some sleep for work :-\
If you're still having trouble, I might be able to help out at a more detailed level sometime later in the week, assuming work leaves me with a decent amount of thought capacity :P


Hope this helps!


I recommend using an array
Now that you mention this, is it posible to use Linked Lists?
(A list made of Nodes, that works like an array but without a limit of objects)

Linked lists, by the standard definition, are not possible in Danmakufu.  You'd need a reference type (pointers) to achieve this.

However, this is a moot point, since arrays in Danmakufu are dynamically resizable* (in that regard, they kind of are like linked lists).

The linked tutorial above gives a quick rundown of it, but here's the basics:

Declare your initial array:
Code: [Select]
let zomg_array = [999, 1234, 55555];You probably know this by now.

Add an element to the end of the array:
Code: [Select]
zomg_array = zomg_array ~ [7];Effectively, the ~ combines the two lists into one, larger list.

Remove an element from an array:
Code: [Select]
zomg_array = erase(zomg_array, 2);erase gives the list, with the indexed element removed.


You can do lots of complex stuff with arrays like this.  However, one limitation, if I remember correctly, is that arrays must be homogenous - that is, all elements of the array must be the same type.  So having an array such as:
Code: [Select]
let bad_array = [123, 'lol', 456, ':V', 789];wouldn't work.



*Technicality: okay, so really they're not, but you can easily create 'derivatives', so it works practically the same :V
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on July 21, 2009, 03:13:05 AM
And I was starting to overthink stuff due to the limits arrays can have :V
Thanks!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 21, 2009, 12:03:26 PM
This is the modified version of the buggy script (your guess is correct, Danmakufu still freezes)

Code: [Select]
#TouhouDanmakufu
#Title[QED "Ripples of 495 Years"]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let ImgBoss = "script\img\ExRumia.png";
    let frame = -120;
    let i;
    let angle=[];
    let no=[];
    @Initialize {
       SetLife(3000);
       SetTimer(120);
       SetScore(1000000);
       SetDurableSpellCard();
       SetDamageRate(50,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "QED "\""Ripples of 495 Years"\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
       LoadUserShotData(GetCurrentScriptDirectory~"images\shot_All.txt");
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        if(frame==10) {
           ascent(i in 0..64){
             no=no~(Obj_Create(OBJ_SHOT));
             Obj_SetPosition(no[i], GetX, GetY);
             Obj_SetSpeed(no[i],1);
             angle=angle~(i*360/64);
             Obj_SetAngle(no[i], angle[i]);
             ObjShot_SetGraphic(no[i], 45);
           }
        }
        if(frame>10){
           ascent(i in 0..64){
              if(Obj_GetX(no[i])==GetClipMaxX||Obj_GetX(no[i])==GetClipMaxX){
                 angle[i]=180-angle[i];
                 Obj_SetAngle(no[i], angle[i]);
              }
              if(Obj_GetY(no[i])==GetClipMaxY||Obj_GetY(no[i])==GetClipMaxY){
                 angle[i]=-angle[i];
                 Obj_SetAngle(no[i], angle[i]);
              }
           }
        }
        frame++;
    }

    @DrawLoop {
        DrawGraphic(GetX, GetY);
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
}
(Replying Iryan's comment)Also, can I use a function instead of a task to make shot obj as function is faster than tasks...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on July 21, 2009, 02:16:56 PM
@ Henry:
Well, to make your bullets bounce off of something, properties of the bullet have to be checked after it has been fired. The advantage of tasks compared to mere functions is that you can have them work along the main loop for a desired amount of time, which enables you to check these properties. A function is a one-shot command. You call it once and it is executed on the frame it is called without a recurring effect later on that could check for the object's properties.
So no, you cannot just take a task, turn it into a function and expect it to do the same work.

What you can do is define several functions that are called inside your main loop each frame and which check for the properties of your bullets, basically just like the script you already posted, only with functions. However, I don't think this is neccessary as it wouldn't make your code any shorter, I think.

@ NC:
While I'm not trying to be an elitist jerk ... I highly recommend against using tasks in the manner you're suggesting.  It's very inefficient, and will start to bring down the game's performance before too long.

Instead, I recommend using an array to keep track of object shots, as demonstrated in my object shot tutorial (http://dmf.shrinemaiden.org/wiki/index.php?title=Nuclear_Cheese%27s_Shot_Object_Tutorial).  It's a bit harder to chew at first, but its a much better approach in the long run.

To be fair, you could use a single task to control all object shots as in the tutorial, but honestly, I prefer to just do it in @MainLoop directly.
Hum? Having about 60 object bullets on the screen simultaneously that don't even have complex code to perform every frame will slow down the game too much? I never had problems or noticed other people's complains regarding performance on cards that had a nothing but a relativley high count of simple object bullets. 64 isn't even that high of a number...

I guess I am misinterpreting what you say, because I don't understand how using tasks for object bullets which don't interact with one another is such a huge disadvantage. Everyone does it, to my knowledge. They don't seem to slow the game down by a noticable margin compared to otherwise identical bullets coded into the main loop. On the other hand, the reduced complexity and improved clarity of the script strikes me as an advantage of the task bullets. The only reason for me to code the objects in the main loop is if you want to refer to specific bullets, especially if you want two or more objects to interact.

I frankly don't quite understand you here.  :-\
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 21, 2009, 02:48:11 PM
I think NC was trying to mean that if your computer's performance is not very well, 64 obj bullets does make a difference.

Sorry if I mis-interpreted NC's words.

P.S. I am not so familiar with tasks... even looked at the Intermediate Tutorial
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 21, 2009, 08:38:30 PM
I find that coding them in tasks only affects performance when the bullets are actually doing something (reflecting, detecting collision with other bullets, whatever). Otherwise the difference is negligable, at best. This is with (semi-)extensive testing on both an 8GHz/4GB Ram/Vista 64bit and a 2.66Ghz/1GB Ram/XP 32bit/7 years old. Neither detected noticable differences in processing speed whether or not things were processed using yield; trees in tasks or using conditional statements in the @MainLoop.

I bold collision with other bullets just because it batshit's up processing speed no matter what you do.

So uh, unless you've got some other testing going on then I'm seeing no disadvantage to using tasks (even though the wiki also says they slow down your computer.... I've yet to see proof). As far as I know, the math and memory involved with task creation/maintaining is not very heavy at all, since so far the only thing I've seen that affects computer performance by a fair degree is object property changing (you know, reflecting, collision...) and additive blending.

Unless I'm horribly mistaken and my computers just run abnormally fast for no real reason.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on July 22, 2009, 12:32:31 AM
I find that coding them in tasks only affects performance when the bullets are actually doing something (reflecting, detecting collision with other bullets, whatever). Otherwise the difference is negligable, at best. This is with (semi-)extensive testing on both an 8GHz/4GB Ram/Vista 64bit and a 2.66Ghz/1GB Ram/XP 32bit/7 years old. Neither detected noticable differences in processing speed whether or not things were processed using yield; trees in tasks or using conditional statements in the @MainLoop.

I bold collision with other bullets just because it batshit's up processing speed no matter what you do.

So uh, unless you've got some other testing going on then I'm seeing no disadvantage to using tasks (even though the wiki also says they slow down your computer.... I've yet to see proof). As far as I know, the math and memory involved with task creation/maintaining is not very heavy at all, since so far the only thing I've seen that affects computer performance by a fair degree is object property changing (you know, reflecting, collision...) and additive blending.

Unless I'm horribly mistaken and my computers just run abnormally fast for no real reason.

Okay, I admit I probably exaggerated the effect that using tasks like that would have in Danmakufu.  Probably comes from the fact that threads (which tasks are supposed to be like) in programming are non-trivial.


detecting collision with other bullets

But this is where the most fun can be had with object bullets!


Hum? Having about 60 object bullets on the screen simultaneously that don't even have complex code to perform every frame will slow down the game too much? I never had problems or noticed other people's complains regarding performance on cards that had a nothing but a relativley high count of simple object bullets. 64 isn't even that high of a number...

I guess I am misinterpreting what you say, because I don't understand how using tasks for object bullets which don't interact with one another is such a huge disadvantage. Everyone does it, to my knowledge. They don't seem to slow the game down by a noticable margin compared to otherwise identical bullets coded into the main loop. On the other hand, the reduced complexity and improved clarity of the script strikes me as an advantage of the task bullets. The only reason for me to code the objects in the main loop is if you want to refer to specific bullets, especially if you want two or more objects to interact.

I frankly don't quite understand you here.  :-\

Honestly, I disagree with you on the clarity point.  Using yield to switch between tasks suddenly creates multiple "entry points" for each piece of code (including the @MainLoop) - this makes it harder to track where the code goes.
Plus, as with any multi-threaded processing, it opens you up to ambiguity in the overall execution order of all pieces of code running.  Not as much as preemptive threading/multitasking, but the risk is still there.

As far as basic code clarity is concerned, this can be dealt with pretty easily with a few things:
1) Proper and consistent code structure and indentation.
2) Break up your functionality into functions that are called from @MainLoop, and it'll look a lot more like your divided-into-tasks approach.
3) Comments.  Properly commented messy code is, in most cases, more readable than uncommented structured code.


In the end, though, it probably just all comes down to personal bias.  Personally, I don't really like Danmakufu's tasks setup to begin with.  Using tasks (specifically, yield) changes the semantics of the @MainLoop from a function that gets called once per frame to a function that loops on its own.  This strikes me as kind-of odd in its own way, if you ask me.

Secondly (and somewhat related to the first point), is the whole use of the yield statement to switch tasks.  The way I see it, if you've created a bunch of tasks, you're going to want them all working in parallel, right?  So why do we need to explicitly say, in each one, "okay, time to let the next one on the CPU"?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 22, 2009, 01:35:57 AM
If I use tasks for obj bullets, should I use these statements for the Mainloop?

Code: [Select]
@MainLoop{
   SetCollisionA(...);
   SetCollisionB(...);
   yield;
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on July 22, 2009, 03:09:53 AM
There aren't any measurements of Power in Danmakufu, so if you're aiming to make a player with different capabilities at different levels, you're going to have to make custom objects.
Like effect objects or something?
I see it in the official games and Touhou Mushuugeki (CtC), so yeah.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 22, 2009, 03:39:21 AM
Secondly (and somewhat related to the first point), is the whole use of the yield statement to switch tasks.  The way I see it, if you've created a bunch of tasks, you're going to want them all working in parallel, right?  So why do we need to explicitly say, in each one, "okay, time to let the next one on the CPU"?

I think of it more like "okay, take a break from this and move on to this, then you can continue where you left off the next frame". This way I can easily plan out what happens, in order, during a spellcard. As a matter of fact, my @MainLoops nowadays only have the two necessary lines of collision detection, as well as yield;. I have everything planned out in order, frame by frame (with intense use of the God tier loop function).

detecting collision with other bullets

But this is where the most fun can be had with object bullets!

The most fun, as well as the most CPU annihilating. I agree completely though, easily the best function in regards to object coding (even though I don't use it much...).

In the end, though, it probably just all comes down to personal bias.

Considering the negligable difference in processing speed, I would have to agree with you there. Too much is set on personal preference in Danmakufu (didn't I rant about this somewhere else? (http://www.shrinemaiden.org/forum/index.php?topic=296.msg41031#msg41031)), but I guess it's good and bad. Good that you have your own code, bad that you can't read anybody else's.


There aren't any measurements of Power in Danmakufu, so if you're aiming to make a player with different capabilities at different levels, you're going to have to make custom objects.
Like effect objects or something?
I see it in the official games and Touhou Mushuugeki (CtC), so yeah.

Hmmm, if you can't think of how you could accomplish a power system in Danmakufu then I would suggest not trying it. This is only because it would require some massive amount of interlaced coding between player scripts and spell card/stage scripts (we're talking CommonData up the yingyang), so it would require a plethora of time, planning and worst of all: thinking. Chances are if you can't think of how to do it right now then you haven't done enough of the latter two, which can be fixed by pouring more effort into the foremost listed. Think Stuffman's PoSR, he made custom point items, could you not make custom power items?

If I use tasks for obj bullets, should I use these statements for the Mainloop?

Code: [Select]
@MainLoop{
   SetCollisionA(...);
   SetCollisionB(...);
   yield;
}

Technically you could get away with only those three lines of code in your @MainLoop (seriously), but have a task start in @Initialize that plans out your whole attack (this is actually my method of coding nowadays, so feel free to ask questions about it if you'd like to try it out).

Usually people just do the standard frame++;, if(frame==60){spawn object bullets that run seperately in tasks alongside the @MainLoop}.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 22, 2009, 03:55:53 AM
It should be possible to make working power items. Once I'm finished most of Reimu I was going to attempt it myself, as you could just leave a default Power setting for most cards and have a dynamic Power with spellcards made for it. Shuffling through stages and spellcards shouldn't be a problem as most coding would be done in the player script.

You would have a CommonData of Power that initializes in the player script. The CommonData would change if you died. Then a task in the spellcard would spawn power items and when they're hit, get the data and increase it. [EDIT: considering the objects would disappear after the spellcard finishes, you would have them spawn at the beginning, so when played it would look as if they appeared because you beat the card. Incidentally, this might require more CommonData if you need to track whether or not it was captured, etc) A per-frame task in the player script would be constantly getting the data and change a variable that controls your shot patterns and such. If there's a spellcard with no CommonData in it it, GetCommonData would return the string "NoData". You check in the same per-frame task if there is NoData, and if so your CommonData just stays at the default.
\(゜∀゜)/

Effect Objects would be ideal considering you can put them on a high graphic level, check player collision and other such things. You could use Shot Objects if you find it easier, though it might require a few workarounds.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on July 23, 2009, 12:39:57 AM
Time for a durr durr moment for me. =D Okay, first off, as I'm just curious: is it possible to make C Lasers with Object Shots (read: object lasers)?

And to the meat of the issue: how exactly would one code a gradually homing shot? I... ew, I deleted it, so I'll try to summarize below. I'll just list what's in the 'while(Obj_BeDeleted(obj)==false){}' statement.
Code: [Select]
while(Obj_BeDeleted(obj)==false){
let p_angle = atan2(Obj_GetY(obj)-GetPlayerY, Obj_GetX(obj)-GetPlayerX);
if(p_angle > Obj_GetAngle(obj)-5){
  Obj_SetAngle(obj, Obj_GetAngle(obj)+5);
}
if(p_angle < Obj_GetAngle(obj)-5){
  Obj_SetAngle(obj, Obj_GetAngle(obj)-5);
}
}
I know the bullet won't home in fully, I had a more complex code that incremented the bullet's turn more if the player was waaay out of the way of the bullet, but that's not where the problem lies. There's this weird little problem in that if I pass by a certain... point of the bullet, I'm not entirely sure where, it will basically freak out. It will curve away from me, and eventually drifts in the complete opposite direction. I tried putting absolute value signs around the two arguments in atan2, but that didn't do the trick. That just made it WORSE (it would start drifting away with even less provocation).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 23, 2009, 03:12:04 AM
Try inputting something to normalize the angles to a positive value:

while(p_angle < 0){ p_angle+=360; }
while(p_angle > 360){ p_angle-=360; }

Not entirely sure if this will help, but I know that this is a recurring problem with homing shots and this code is always involved, so yeah.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on July 23, 2009, 04:01:57 AM
Oh, good thinking! Yeah, that would definitely confuse the code... heh, this is totally the root of my problem. Naut, you're the greatest. =D

Oh, right, and something that's been bugging me... are variables global? i.e. if I call 'var' in @Initialize, will it be recognized in @Mainloop (or more importantly, will 'var' in, say, a hypothetical Task1 overlap with a 'var' called in a hypothetical Task2?)

EDIT: Bleh, that didn't fix it after all. Now the bullets chase after a mystery angle that is directly away from me if I'm outside this weird 'line of sight' they seem to have. I think it may have something to do with the 'homing' part of the script...
Code: [Select]
#TouhouDanmakufu
#Title[Homing Shots]
#Text[Test script]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let ImgBoss = "script\img\ExRumia.png";
T1;

    @Initialize {
        SetLife(2000);
        SetTimer(50);
        SetScore(1000000);

        SetMovePosition02(GetCenterX, GetClipMinY + 120, 120);
        CutIn(YOUMU, "Test Sign "\""Test"\", "", 0, 0, 0, 0);

        LoadGraphic(ImgBoss);
        SetTexture(ImgBoss);
        SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
yield;

    }

    @DrawLoop {
        DrawGraphic(GetX, GetY);
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
task T1{
loop(120){yield;}
loop{
TMain;
loop(120){yield;}
}
}
task TMain{
loop(120){yield;}
loop{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, GetX, GetY);
Obj_SetSpeed(obj, 3);
Obj_SetAngle(obj, rand(135, 215));
ObjShot_SetGraphic(obj, WHITE02);
while(Obj_BeDeleted(obj) == false){
let p_angle = atan2((|Obj_GetY(obj)-GetPlayerY|), (|Obj_GetX(obj)-GetPlayerX|));
if(p_angle > Obj_GetAngle(obj)-5){
Obj_SetAngle(obj, Obj_GetAngle(obj)+5);
}
if(p_angle < Obj_GetAngle(obj)-5){
Obj_SetAngle(obj, Obj_GetAngle(obj)-5);
}
while(p_angle < 0){ p_angle+=360; }
while(p_angle > 360){ p_angle-=360; }
yield;
}
}
}
}
This was kind of a lift-and-paste, I just wanted to see if it would work. o-o I'd puzzle over it some more myself, but I know it's been done somewhere on this board, and I was never that good at geometry (especially in the weird coordinate system Danmakufu uses, which always trips me up). Oh, and I know that in this code it waits to generate the next few bullets until Obj_BeDeleted(obj) becomes true and the while statement is broken, but I was gonna fix that by using a function to trip the TMain housed in the Mainloop. For now, I just want these damn bullets to follow my ass! D=<
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 23, 2009, 04:23:23 AM
Variables are contained within the braces you declare them in. So if you declare a variable in @Initialize, it can only be used in @Initialize and will raise an error if used outside. If you declare them in script_enemy_main, then they are used in script_enemy_main (what we refer to as "global variables"). This is a very good thing though, because if you need to run multiple of the same task and not worry about variables adding multiple times, you can simply declare the variable inside the task and it will only exist inside of that one task, even if multiple instances of the task are running simultaneously.

So I can make a task that runs something like this:

task Bullats(speed){
    let a = GetAngleToPlayer;
    loop(20){
        CreateShot01(GetX, GetY, speed, a, RED01, 0);
        a+=18;
        yield;
    }
}

and then say somewhere in @MainLoop:

if(frame==60){
    Bullats(3);
    Bullats(4);
    Bullats(5);
    frame = 0;
}

And not have to worry about the variable "a" stacking three times every frame, since to Danmakufu it only exists inside of those individual tasks.

Edit: And uh, here's some homing bullet code for you to steal: http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Object_Bullets

AND! You were supposed to put that code I mentioned inbetween the declaration and the if statements. But whatever, it still probably wont work.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on July 23, 2009, 04:26:54 AM
Okay, that's a relief (I've been renaming variables over and over again to make sure that wouldn't happen). Now, to work on these bullets.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 23, 2009, 06:53:31 AM
It's been a while, but I got another burning question:
I want to create tasks so I can do reflecting shots and indestructable bullets, but the tutorial on this board doesn't have a full script example, just bits and pieces you have to glue together. And that just won't work, no matter how I try it.
Can someone post a full sample file that has a reflection and/or indestructable-bullet script in it?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 23, 2009, 07:44:18 AM
That is odd, the tutorial posted here on Motk is not bits of pieces glued together but a step by step explaining understanding how an object task is build.

You can also checkthe Touhou Wiki of Danmakufu where an copy/past able example of lasers and bullets are written.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 23, 2009, 10:38:51 AM
The thing is, there's no complete script as an end-result in that tutorial, only the Task part.
Also, some contents keep changing. One moment it's:
Code: [Select]
task NameOfTheTask(put, variables, here) {
And the next it's:
Code: [Select]
task Testtask(a, b, c) {Which confuses me even more D:

Ah, but someone has got to have a script on their computer which uses tasks in the way I wanted, so I'd appreciate it if you would share it with me.


Oh, while I'm here. Is there a command that can relocate the player? I was trying to make reversed movement (left=right), but I could not find a way to change the player's location and/or movement.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 23, 2009, 02:11:27 PM
The thing is, there's no complete script as an end-result in that tutorial, only the Task part.
Also, some contents keep changing. One moment it's:
Code: [Select]
task NameOfTheTask(put, variables, here) {
And the next it's:
Code: [Select]
task Testtask(a, b, c) {Which confuses me even more D:

Ah, but someone has got to have a script on their computer which uses tasks in the way I wanted, so I'd appreciate it if you would share it with me.

What do you mean it is not complete or endresult? It is the entire code for the reflection laser or bullet. You just need to call/spawn the bullet by using the Taskname inside a loop/seperate task.

I'll post my code I used for my Uwabami Breakers - Dance contest non-card when I am at home as I am currently at work. (Or if you are impatient, you can download the scripts and check 'Afro03.txt' in there. )
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 23, 2009, 02:33:17 PM
Oh, while I'm here. Is there a command that can relocate the player? I was trying to make reversed movement (left=right), but I could not find a way to change the player's location and/or movement.

I made one just a few days ago O_O!
Code: [Select]
#TouhouDanmakufu
#Title[Mirror Sign"Reverse Direction"]
#Text[]
#BackGround[Default]
#PlayLevel[Normal]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
let ImgBoss = "script\img\ExRumia.png";

let frame = 0;
let framem = 0;
let phase = 1;

let playerv;
let dista = 20;
let pic = WHITEI02;

let bullets = [ ];


    @Initialize {
        shotinit;
        LoadGraphic(ImgBoss);
        CutIn(YOUMU, "Mirror Sign"\""Reverse Direction"\", "", 0, 0, 0, 0);
        SetLife(2000);
        SetDamageRate(100, 100);
        SetTimer(40);
        SetInvincibility(120);
        SetScore(500000);
        SetEnemyMarker(true);
        Concentration02(60);
        SetMovePosition03(GetCenterX, 100, 10, 10);
    }

    @MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 24);

if(phase >= 1)
{
if(frame == 2)
{
ascent(i in -1..2)
{
let obj=Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, GetX, GetY);
Obj_SetAngle(obj, GetAngleToPlayer+i*dista);
Obj_SetSpeed(obj, 7);
ObjShot_SetGraphic(obj, pic);
ObjShot_SetDelay(obj, 0);
bullets = bullets ~ [obj];
}
dista -= 0.1;
frame = 0;
}

if(phase == 2)
{
if((GetKeyState(VK_SLOWMOVE) == KEY_HOLD) || (GetKeyState(VK_SLOWMOVE) == KEY_PUSH))
{
playerv = GetPlayerInfo(PLAYER_SPEED_LOW);
}else
{
playerv = GetPlayerInfo(PLAYER_SPEED_HIGH);
}
if((GetKeyState(VK_LEFT) == KEY_HOLD) || (GetKeyState(VK_LEFT) == KEY_PUSH))
{
SetPlayerX(GetPlayerX + playerv*2);
}
if((GetKeyState(VK_RIGHT) == KEY_HOLD) || (GetKeyState(VK_RIGHT) == KEY_PUSH))
{
SetPlayerX(GetPlayerX - playerv*2);
}
}

if(framem == 160)
{
    Concentration02(30);
}
if(framem == 200)
{
ascent(i in 0..length(bullets))
{
Obj_SetPosition(bullets[i], 448-Obj_GetX(bullets[i]), Obj_GetY(bullets[i]));
Obj_SetAngle(bullets[i], 180-Obj_GetAngle(bullets[i]));
ObjShot_SetGraphic(bullets[i], WHITE02);
}
dista = 20;
pic = WHITE02;
phase = 2;
}
if(framem == 360)
{
    Concentration02(30);
}
if(framem == 400)
{
ascent(i in 0..length(bullets))
{
Obj_SetPosition(bullets[i], 448-Obj_GetX(bullets[i]), Obj_GetY(bullets[i]));
Obj_SetAngle(bullets[i], 180-Obj_GetAngle(bullets[i]));
ObjShot_SetGraphic(bullets[i], WHITEI02);
}
dista = 20;
pic = WHITEI02;
phase = 1;
framem = 0;
}
framem ++;
frame ++;
}

yield;
}


    @DrawLoop {
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 64, 64);
DrawGraphic(GetX, GetY);
    }

    @Finalize {
    }

}

Hope it helped.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 23, 2009, 02:39:13 PM
Ah, so it is possible after all! I'll try this out when I finally get the chance, thanks!

Edit:
Ah, it seems to look for the shot replacements, but once that's solves it errors some more about "shotinit;" and "WHITEI02"
But I solved that, so the real important part of the script is:

Code: [Select]
let playerv=0;

if(frame>1){
 if((GetKeyState(VK_SLOWMOVE) == KEY_HOLD) || (GetKeyState(VK_SLOWMOVE) == KEY_PUSH))
         {
            playerv = GetPlayerInfo(PLAYER_SPEED_LOW);
         }else
         {
            playerv = GetPlayerInfo(PLAYER_SPEED_HIGH);
         }
         if((GetKeyState(VK_LEFT) == KEY_HOLD) || (GetKeyState(VK_LEFT) == KEY_PUSH))
         {
            SetPlayerX(GetPlayerX + playerv*2);
         }
         if((GetKeyState(VK_RIGHT) == KEY_HOLD) || (GetKeyState(VK_RIGHT) == KEY_PUSH))
         {
            SetPlayerX(GetPlayerX - playerv*2);
}
}


It's very similiar to what I tried, except that I tried moving the player with GetPlayerX, which is wrong ofcourse!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on July 23, 2009, 08:33:34 PM
Am I able to put this in a task, subroutine, function, etc. so I will be able to save space instead of copying and pasting whenever it needs to be called? I am making a spellcard, but it requires this to be called up numerous times:



Code: [Select]
if(s < 0.0035){
accelerate = 1;
}

if(s > 0.035){
accelerate = 0;
}

if(accelerate == 1){
s += 0.0035;
}

if(accelerate == 0){
s -= 0.0035;
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on July 23, 2009, 09:01:16 PM
Subroutines are exactly what you want to use. They let you call up a part of the script whenever you want. Just put this somewhere outside of the @Loops, but still inside the boss script (after @Finalize is a good idea)...

Code: [Select]
sub callthisfunction
{
if(s < 0.0035){
accelerate = 1;
}

if(s > 0.035){
accelerate = 0;
}

if(accelerate == 1){
s += 0.0035;
}

if(accelerate == 0){
s -= 0.0035;
}
}

...then just use callthisfunction; anywhere to use it again.

Functions basically work the same, you can also provide a number of variables for the function to use.

Code: [Select]
function shootredbullet(speed)
{
CreateShot01(GetX,GetY,speed,GetAngleToPlayer,RED01,30);
}

You could put shootredbullet(4); to shoot a red bullet at that speed. You can use more variables, just separate them with commas. Be sure not to name them the same as your declared variables, as this can lead to confusing situations.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on July 23, 2009, 09:47:54 PM
I understand. Thank you very much.

Another question about functions: Can I put more than one bullet in the same function, or is only one bullet allowed per function?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 23, 2009, 10:09:56 PM
You can put a near endless amount of information inside of a subroutine/function/task, it needn't be bullets either.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on July 23, 2009, 10:30:51 PM
Okay. Thank you.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on July 24, 2009, 10:12:52 PM
Blaaaargh. I almost had it! The homing code I mean. The trouble is when I cross the 180 degree line relative to the bullet, it starts looping around in the opposite direction. I'm attributing this to a mysterious change in sign, but I can't seem to iron out that problem. I'm pretty sure it's because I'm using p_angle > Obj_GetAngle(obj) or what have you. That argument gets fucked up when the 180 line is crossed (coz atan2 loops around into -180 and starts counting up from there)... so what do I do now?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 24, 2009, 10:37:01 PM
Here's a blurb of code Drake wrote up for Josette Y's homing shot that may be helpful:

angle is the current angle of the object shot, maxTraverse is the maximum number of degrees the shot can turn each frame.
Code: [Select]
let direction=atan2(GetEnemyY-Obj_GetY(objb), GetEnemyX-Obj_GetX(objb));
let difference = direction - angle;
while(difference >= 180) { difference -= 360; }
while(difference < -180) { difference += 360; }
let diffAbsolute = (|difference|);
if(diffAbsolute < maxTraverse) {
angle = direction;
} else {
angle += maxTraverse * difference / diffAbsolute;
}
Obj_SetAngle(objb, angle);

Of particular interest is those while loops, which will force the angle into the -180~180 range and make it work with other calculations correctly.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 25, 2009, 12:22:48 AM
Try inputting something to normalize the angles to a positive value:

while(p_angle < 0){ p_angle+=360; }
while(p_angle > 360){ p_angle-=360; }

Of particular interest is those while loops, which will force the angle into the -180~180 range and make it work with other calculations correctly.

Oh God
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 25, 2009, 12:45:34 AM
naut made a booboo
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Primula on July 26, 2009, 02:41:17 AM
However,this script keeps crashing on me because I was editing the dialogue.


Code: [Select]
#ScriptVersion[2]
script_enemy_main{
#include_function "script\WalkerScript\Tenshi\BgControl.txt";
let ImgBoss = "script\WalkerScript\img\TenshiBoss.png";
let count = 0;
let bgm = false;
task Behavior(){
yield;
while( GetEventStep() != 1 ){ yield; }
PlaySE("script\WalkerScript\sound\charge2.mp3");
SetColor(250,50,50);
Concentration01(120);
SetColor(255,255,255);
SetMovePosition03( GetCenterX(), GetCenterY() - 100, 20, 5 );
SetEnemyMarker( true );
while( GetEventStep() != 2 ){ yield; }
while( GetEventStep() != 3 ){ yield; }
bgm = true;
PlayMusic("script\WalkerScript\sound\Hisouten.mp3");


}
@Initialize{
DeleteMusic("script\WalkerScript\sound\Tenshi.mp3");
SetLife( 1 );
DeleteEnemyShotToItem( ALL );
CollectItems;
SetDamageRate( 0, 0 );
SetX( GetCenterX );
SetY( -128 );
CreateEventFromScript( "Talk" );
Behavior();



      }
@MainLoop{
if( !OnEvent() && bgm ){ AddLife( -1 ); }
yield;
count++;
}
@DrawLoop{


BgScrollEx2(TenshiBG3, 0, -0.01, 2,255);
BgScrollEx(TenshiBG4, 0, -10, 1, 25);
                  LoadGraphic(ImgBoss);
                  SetTexture(ImgBoss);
SetGraphicRect( 0, 0, 48, 66 );
DrawGraphic(GetX, GetY);

}
}
script_event Talk{
let imgplayerdeh=GetCurrentScriptDirectory~"img\Marisa8.png";
let imgplayermad=GetCurrentScriptDirectory~"img\Marisa5.png";
let imgplayersad=GetCurrentScriptDirectory~"img\Marisa6.png";
let imgplayerblah=GetCurrentScriptDirectory~"img\Marisa7.png";
let imgenemyglad=GetCurrentScriptDirectory~"img\Tensi.png";
let imgenemymad=GetCurrentScriptDirectory~"img\Tenshi.png";
let imgenemyblah=GetCurrentScriptDirectory~"img\TenshiCutIn.png";
@Initialize{
LoadGraphic(imgplayerdeh);
LoadGraphic(imgplayermad);
LoadGraphic(imgplayersad);
LoadGraphic(imgplayerblah);
LoadGraphic(imgenemyglad);
LoadGraphic(imgenemymad);
LoadGraphic(imgenemyblah);
}

@MainLoop{
SetChar(LEFT,imgplayersad);SetGraphicRect(LEFT,0,0,167,439);
MoveChar(LEFT,FRONT);
TextOut( "\c[GREEN]Finally... it's over." );
SetChar(LEFT,imgplayerblah);SetGraphicRect(LEFT,0,0,167,439);
TextOut( "\c[GREEN]I should go back home, it's freezing here." );
MoveChar(LEFT,BACK);
SetStep( 1 );
TextOut( "\c[BLUE]Yes, it's very cold but..." );
SetStep( 2 );
Wait( 60 );
SetStep( 3 );
SetChar(RIGHT,imgenemyglad);SetGraphicRect(RIGHT,0,0,240,393);
MoveChar(RIGHT,FRONT);
TextOut( "\c[BLUE]You're very close to the Heaven..." );
                MoveChar(RIGHT,BACK);
                SetChar(LEFT,imgplayermad);SetGraphicRect(LEFT,0,0,167,439);
MoveChar(LEFT,FRONT);
TextOut( "\c[GREEN]Oh no... You are still alive?!" );
MoveChar(LEFT,BACK);
SetChar(RIGHT,imgenemyblah);SetGraphicRect(RIGHT,0,0,240,393);
MoveChar(RIGHT,FRONT);
TextOut( "\c[BLUE]Yes." );
                MoveChar(RIGHT,BACK);
                        SetStep( 4 );
SetChar(LEFT,imgplayerblah);SetGraphicRect(LEFT,0,0,167,439);
MoveChar(LEFT,FRONT)
TextOut( "\c[GREEN]What are you trying to do!?");
SetChar(LEFT,imgplayerdeh);SetGraphicRect(LEFT,0,0,167,439);
TextOut( "\c[GREEN]Please stop! I'm tired!");
MoveChar(LEFT,BACK);
SetChar(RIGHT,imgenemyblah);SetGraphicRect(RIGHT,0,0,240,393);
MoveChar(RIGHT,FRONT);
TextOut( "\c[BLUE]So you want a rest?.\nThen you will have a rest..." );
SetChar(RIGHT,imgenemymad);SetGraphicRect(RIGHT,0,0,240,393);
TextOut( "\c[BLUE]Forever... in the Heaven!!!" );
                        SetStep( 5 );
}
@Finalize{
DeleteGraphic(imgplayerdeh);
DeleteGraphic(imgplayermad);
DeleteGraphic(imgplayersad);
DeleteGraphic(imgplayerblah);
DeleteGraphic(imgenemyglad);
DeleteGraphic(imgenemymad);
DeleteGraphic(imgenemyblah);
}
}

Sorry Walker,I just want to fool around with scripts..(and used Stuffman's dialogues for bases) D8
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Johnny Walker on July 26, 2009, 06:10:44 AM
However,this script keeps crashing on me because I was editing the dialogue.

<heregoesacode>

Sorry Walker,I just want to fool around with scripts..(and used Stuffman's dialogues for bases) D8
Don't worry. Feel free to use anything I've created (or modified 8D). They're just for fun.

Aaand... You forgot a ";" in the middle line of:
Code: [Select]
SetChar(LEFT,imgplayerblah);SetGraphicRect(LEFT,0,0,167,439);
MoveChar(LEFT,FRONT) <---
TextOut( "\c[GREEN]What are you trying to do!?");

Fixed:

Code: [Select]
#ScriptVersion[2]
script_enemy_main{
#include_function "script\WalkerScript\Tenshi\BgControl.txt";
let ImgBoss = "script\WalkerScript\img\TenshiBoss.png";
let count = 0;
let bgm = false;
task Behavior(){
yield;
while( GetEventStep() != 1 ){ yield; }
PlaySE("script\WalkerScript\sound\charge2.mp3");
SetColor(250,50,50);
Concentration01(120);
SetColor(255,255,255);
SetMovePosition03( GetCenterX(), GetCenterY() - 100, 20, 5 );
SetEnemyMarker( true );
while( GetEventStep() != 2 ){ yield; }
while( GetEventStep() != 3 ){ yield; }
bgm = true;
PlayMusic("script\WalkerScript\sound\Hisouten.mp3");


}
@Initialize{
DeleteMusic("script\WalkerScript\sound\Tenshi.mp3");
SetLife( 1 );
DeleteEnemyShotToItem( ALL );
CollectItems;
SetDamageRate( 0, 0 );
SetX( GetCenterX );
SetY( -128 );
CreateEventFromScript( "Talk" );
Behavior();



      }
@MainLoop{
if( !OnEvent() && bgm ){ AddLife( -1 ); }
yield;
count++;
}
@DrawLoop{


BgScrollEx2(TenshiBG3, 0, -0.01, 2,255);
BgScrollEx(TenshiBG4, 0, -10, 1, 25);
                  LoadGraphic(ImgBoss);
                  SetTexture(ImgBoss);
SetGraphicRect( 0, 0, 48, 66 );
DrawGraphic(GetX, GetY);

}
}
script_event Talk{
let imgplayerdeh=GetCurrentScriptDirectory~"img\Marisa8.png";
let imgplayermad=GetCurrentScriptDirectory~"img\Marisa5.png";
let imgplayersad=GetCurrentScriptDirectory~"img\Marisa6.png";
let imgplayerblah=GetCurrentScriptDirectory~"img\Marisa7.png";
let imgenemyglad=GetCurrentScriptDirectory~"img\Tensi.png";
let imgenemymad=GetCurrentScriptDirectory~"img\Tenshi.png";
let imgenemyblah=GetCurrentScriptDirectory~"img\TenshiCutIn.png";
@Initialize{
LoadGraphic(imgplayerdeh);
LoadGraphic(imgplayermad);
LoadGraphic(imgplayersad);
LoadGraphic(imgplayerblah);
LoadGraphic(imgenemyglad);
LoadGraphic(imgenemymad);
LoadGraphic(imgenemyblah);
}

@MainLoop{
SetChar(LEFT,imgplayersad);SetGraphicRect(LEFT,0,0,167,439);
MoveChar(LEFT,FRONT);
TextOut( "\c[GREEN]Finally... it's over." );
SetChar(LEFT,imgplayerblah);SetGraphicRect(LEFT,0,0,167,439);
TextOut( "\c[GREEN]I should go back home, it's freezing here." );
MoveChar(LEFT,BACK);
SetStep( 1 );
TextOut( "\c[BLUE]Yes, it's very cold but..." );
SetStep( 2 );
Wait( 60 );
SetStep( 3 );
SetChar(RIGHT,imgenemyglad);SetGraphicRect(RIGHT,0,0,240,393);
MoveChar(RIGHT,FRONT);
TextOut( "\c[BLUE]You're very close to the Heaven..." );
                MoveChar(RIGHT,BACK);
                SetChar(LEFT,imgplayermad);SetGraphicRect(LEFT,0,0,167,439);
MoveChar(LEFT,FRONT);
TextOut( "\c[GREEN]Oh no... You are still alive?!" );
MoveChar(LEFT,BACK);
SetChar(RIGHT,imgenemyblah);SetGraphicRect(RIGHT,0,0,240,393);
MoveChar(RIGHT,FRONT);
TextOut( "\c[BLUE]Yes." );
                MoveChar(RIGHT,BACK);
                        SetStep( 4 );
SetChar(LEFT,imgplayerblah);SetGraphicRect(LEFT,0,0,167,439);
MoveChar(LEFT,FRONT);
TextOut( "\c[GREEN]What are you trying to do!?");
SetChar(LEFT,imgplayerdeh);SetGraphicRect(LEFT,0,0,167,439);
TextOut( "\c[GREEN]Please stop! I'm tired!");
MoveChar(LEFT,BACK);
SetChar(RIGHT,imgenemyblah);SetGraphicRect(RIGHT,0,0,240,393);
MoveChar(RIGHT,FRONT);
TextOut( "\c[BLUE]So you want a rest?.\nThen you will have a rest..." );
SetChar(RIGHT,imgenemymad);SetGraphicRect(RIGHT,0,0,240,393);
TextOut( "\c[BLUE]Forever... in the Heaven!!!" );
                        SetStep( 5 );
}
@Finalize{
DeleteGraphic(imgplayerdeh);
DeleteGraphic(imgplayermad);
DeleteGraphic(imgplayersad);
DeleteGraphic(imgplayerblah);
DeleteGraphic(imgenemyglad);
DeleteGraphic(imgenemymad);
DeleteGraphic(imgenemyblah);
}
}

Title: Re: Danmakufu Q&A/Problem Thread
Post by: KomeijiKoishi on July 26, 2009, 11:33:10 AM
Question:
You know that rand(x, y) always takes any number between x and y. But is there a function which only allows exactly TWO things to choose?
For example: A bullet should either curve to the left or the right, but with the same curve variable.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 26, 2009, 12:42:53 PM
yes, you can use rand_int(A,B) to choose integers between A and B, inclusively.

Use this algorithm:

-1^(rand_int(0,1))*[curve angle]
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Primula on July 26, 2009, 12:44:13 PM
Ahh I see~Thank you Walker!

Edit:Oh wait I'm solving my other problem sorry~
Title: Re: Danmakufu Q&A/Problem Thread
Post by: 8lue Wizard on July 26, 2009, 09:20:41 PM
So, I'm trying to create a custom bullet according to the template on TouhouWiki (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_User-defined_Bullets), but it's not working. I don't get any error messages, and the resultant bullets have hit detection (which doesn't happen if I just stick a random unused identifier in), but no graphic.

>.>
<.<

OUENDAN!!!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 27, 2009, 11:29:22 AM
Question:

Is it possible in Danmakufu to detect which player has been chosen at the character select screen? So I can call this inside the stage script to perform different dialogues. Like if Reimu --> Dialogue1  if Marisa --> Dialogue 2

Awnser to:
So, I'm trying to create a custom bullet according to the template on TouhouWiki (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_User-defined_Bullets), but it's not working. I don't get any error messages, and the resultant bullets have hit detection (which doesn't happen if I just stick a random unused identifier in), but no graphic.

>.>
<.<

OUENDAN!!!
Having no graphics can cause alot of things afaik:
- did you loaded your custom bullets with example: let <var>   = GetCurrentScriptDirectory"<pathtocustombullets.txt"; and LoadUserShotData(<var>)
- Did you make sure the GraphicRect is set proper?

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 27, 2009, 01:41:39 PM
Question:

Is it possible in Danmakufu to detect which player has been chosen at the character select screen? So I can call this inside the stage script to perform different dialogues. Like if Reimu --> Dialogue1  if Marisa --> Dialogue 2

Yes, of course you can :)

use GetPlayerType() as in:
Code: [Select]
if(GetPlayerType==REIMU_A||GetPlayerType==REIMU_B){
   }else{
}

My question: Can I use addshot for obj bullets?

Code: [Select]
#TouhouDanmakufu
#Title[Metal Sign "Metal Fatigue High Level"]
#Text[Remake of metal fatigue in stage 4 of EoSD with reflecting bullets]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = -120;
    let bg = GetCurrentScriptDirectory~"images\Bossbggrey.jpg";
    let random;
    let i;
    let j;
    #include_function "..\drawing.txt"
    @Initialize {
       SetLife(1500);
       SetTimer(60);
       SetScore(1000000);
       SetDamageRate(25,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "Metal Sign "\""Arrows of Venus"\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        if(frame%60==0&&frame>0) {
           random=rand(0,360);
           ascent(i in 0..8){
      CreateShotA(0, GetX, GetY, 0);
      SetShotDataA(0, 0, 2, GetAngleToPlayer+i*360/8, 0, 0, 2, 27);
      SetShotDataA(0, 30, 2, GetAngleToPlayer+i*360/8, 0, -0.1, 0, 27);
      SetShotKillTime(0, 71);
              ascent(j in 0..8){
                 Bullet(2, random+i*360/8+GetAngleToPlayer, 0);
              }
      FireShot(0);
           }
        }
        frame++;
        yield;
    }

    @DrawLoop {
       bossSC;
    }
    @BackGround{
       backgroundSC;
    }
    task Bullet(speed,angle,delay){
       let obj=Obj_Create(OBJ_SHOT);
       Obj_SetPosition(obj, GetX+cos(GetAngleToPlayer+i*360/8)*80, GetY+cos(GetAngleToPlayer+i*360/8)*80);
       Obj_SetAngle(obj, angle);
       Obj_SetSpeed(obj, speed);
       ObjShot_SetGraphic(obj, 27);
       ObjShot_SetDelay  (obj, delay);
       while(Obj_BeDeleted(obj)==false){
          ObjShot_SetBombResist (obj, true);
          if(Obj_GetX(obj)<GetClipMinX||Obj_GetX(obj)>GetClipMaxX){
             Obj_SetAngle(obj, 180-Obj_GetAngle(obj));
             if(Obj_GetX(obj)<GetClipMinX){
                Obj_SetX(obj, Obj_GetX(obj)+0.1);
             }else{
                Obj_SetX(obj, Obj_GetX(obj)-0.1);
             }
             ObjShot_SetGraphic(obj, 27);
          }
          if(Obj_GetY(obj)<GetClipMinY){
             Obj_SetAngle(obj, -Obj_GetAngle(obj));
             if(Obj_GetY(obj)<GetClipMinY){
                Obj_SetY(obj, Obj_GetY(obj)+0.1);
             }
             ObjShot_SetGraphic(obj, 27);
          }
  AddShot(70,0,obj,0);
          yield;
       }
    }
    @Finalize {
        DeleteGraphic(ImgBoss);
    }
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on July 27, 2009, 01:45:41 PM
Code: [Select]
if(GetPlayerType==REIMU_A||GetPlayerType==REIMU_B){
   }else{
}
}
Afaik you can make it shorter by
Code: [Select]
if(GetPlayerType==REIMU){
code goes here}else{
moar code goes here}
Remember that you can refer to both REIMU_A and REIMU_B as REIMU.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: 8lue Wizard on July 27, 2009, 02:59:28 PM
Ah~ Never mind. I did a spot check for typos and it works now. I probably had a letter somewhere with the wrong capitalization.

...too bad it look so ugly. *goes to fix*


Also, how do you view replays?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 27, 2009, 03:26:40 PM
My question: Can I use addshot for obj bullets?

I'm not sure if you can or not, but why would you need to?
You can get the X and Y coordinate of the Object Bullet with Obj_GetX and Obj_GetY respectively.
Then you can just shoot bullets or do whatever with those coordinates.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 27, 2009, 05:16:17 PM
@Henry & The Sword that cleaves evil,

Thank you both. Now I can further implement Reimu as playable character in my game.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on July 27, 2009, 05:23:57 PM
Y' welcome.
Now I have a doubt: When calling shot IDs, the ID name is a string, or an integer?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 27, 2009, 05:46:43 PM
Integers.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on July 27, 2009, 05:49:29 PM
However, you can set a variable to that integer, if you don't want to memorize as much. This is how the shot replace script works, since all the shot names like RED01 are actually just variables that equal the matching shot ID.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on July 27, 2009, 05:51:07 PM
Integers.
However, you can set a variable to that integer, if you don't want to memorize as much. This is how the shot replace script works, since all the shot names like RED01 are actually just variables that equal the matching shot ID.
Fuck yes, just what I wanted.
Thanks, guys.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 28, 2009, 12:38:32 AM
aghgghghh i need help
I did a bunch of editing to try and have both the player bullet variables and target variable in the same task so that they could reference each other. It's not working because the collision detection function is done while the bullet isn't deleted. The thing is that because they both work on a different BeDeleted segment.

Like what the fuck do I have to smash the entire target code into the option bullet code? I'm just posting the entire goddamn thing.

Code: [Select]
#TouhouDanmakufu[Player]
#ScriptVersion[2]
#Menu[Reimu D2]
#Text[Hakurei Reimu type D
            ?uConcentrated attack type?v

Shot:   ?uAbsolution Needle?v

Bomb: ?uWild Annihilation Dance?v]
#Image[.\sl_pl00.png]
#ReplayName[ReimuD2]

script_player_main{

#include_function ".\common.txt"
let c = GetCurrentScriptDirectory();
let bNextShot = false;
let optiona = 0;
let focusalpha = 0;
let focussize = 1;
let drawcount = 0;
let shotcount = -1;
let rad = 45;

task DrawHitbox(){
let hitbox = Obj_Create(OBJ_SHOT);
Obj_SetSpeed(hitbox,0);
Obj_SetCollisionToPlayer(hitbox, false);
ObjShot_SetBombResist(hitbox, true);
ObjShot_SetGraphic(hitbox, 100);
while(!Obj_BeDeleted(hitbox)){

if(IsPressRight()==true){
if(IsPressDown()==true){ Obj_SetPosition(hitbox, GetPlayerX+1, GetPlayerY+1); //Right+Down
}else if(IsPressUp()==true){ Obj_SetPosition(hitbox, GetPlayerX+1, GetPlayerY-2); //Right+Up
}else{ Obj_SetPosition(hitbox, GetPlayerX+1, GetPlayerY);} //Right

}else if(IsPressLeft()==true){
if(IsPressDown()==true){ Obj_SetPosition(hitbox, GetPlayerX-2, GetPlayerY+1); //Left+Down
}else if(IsPressUp()==true){ Obj_SetPosition(hitbox, GetPlayerX-2, GetPlayerY-2); //Left+Up
}else{ Obj_SetPosition(hitbox, GetPlayerX-2, GetPlayerY);} //Left

}else if(IsPressDown()==true){ Obj_SetPosition(hitbox, GetPlayerX, GetPlayerY+1); //Down

}else if(IsPressUp()==true){ Obj_SetPosition(hitbox, GetPlayerX, GetPlayerY-2); //Up

}else{ Obj_SetPosition(hitbox, GetPlayerX, GetPlayerY); //Neutral
}
Obj_SetAngle(hitbox, optiona);
Obj_SetAlpha(hitbox, focusalpha);
yield;
}
}

task OptionScript{
if(IsPressShot()==true && shotcount==-1){shotcount=0;}
if(IsPressSlow()==true){rad = 20;}else{rad = 45;}
if(shotcount%5 == 0){
PlaySE(c~"se_plst00.wav");
let r = rand(-5,5);
ShotScript(GetPlayerX+8, GetPlayerY-10, GetPlayerX+(rad*cos(optiona)), GetPlayerY+(rad*sin(optiona)), r, true);
r = rand(-5,5);
ShotScript(GetPlayerX-8, GetPlayerY-10, GetPlayerX+(rad*cos(optiona)), GetPlayerY-(rad*sin(optiona)), r, true);
r = rand(-5,5);
ShotScript(0, 0, GetPlayerX-(rad*cos(optiona)), GetPlayerY+(rad*sin(optiona)), r, false);
r = rand(-5,5);
ShotScript(0, 0, GetPlayerX-(rad*cos(optiona)), GetPlayerY-(rad*sin(optiona)), r, false);
}
if(shotcount>=0){shotcount++;}
if(shotcount>=5){shotcount=-1;}
yield;
}

task ShotScript(x1,y1,x2,y2,r,m){
//TARGET
let f = 0;
ascent(enemy in EnumEnemyBegin..EnumEnemyEnd){
let enemyID = EnumEnemyGetID(enemy);
let target = Obj_Create(OBJ_LASER);
Obj_SetX(target, GetEnemyInfo(enemyID, ENEMY_X));
Obj_SetY(target, GetEnemyInfo(enemyID, ENEMY_Y));
Obj_SetSpeed(target, 0);
Obj_SetCollisionToPlayer(target, false);
ObjShot_SetBombResist(target, true);
ObjShot_SetGraphic(target, 101);
ObjLaser_SetLength(target, 100);
ObjLaser_SetWidth(target, 500);
ObjLaser_SetSource(target, false);
while(!Obj_BeDeleted(target)){
Obj_SetX(target, GetEnemyInfo(enemyID, ENEMY_X));
Obj_SetY(target, GetEnemyInfo(enemyID, ENEMY_Y));
f++;
if(f>2){Obj_Delete(target);}
yield;
}
}
//MAIN BULLET
if(m==true){
let g = 103;
let i = -2;
let a = 115;
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, x1, y1);
Obj_SetAngle(obj, 270);
ObjShot_SetGraphic(obj, g);
Obj_SetAlpha(obj, a);
Obj_SetSpeed(obj, 10);
ObjShot_SetBombResist(obj, true);
ObjShot_SetDamage(obj, 1);
ObjShot_SetPenetration(obj, 10);
Obj_SetCollisionToObject(obj, true);
while(!Obj_BeDeleted(obj)){
/*if(Collision_Obj_Obj(obj,obj)==true){
i = 0;
}else{
g = 103;
}*/
if(i>=0){
ObjShot_SetDamage(obj, 0);
i++;
a-=3;
}
if(i>=0 && i<6){
g = 104;
Obj_SetSpeed(obj, 1.5);
}else if(i>=6 && i<12){
a = 35;
g = 105;
Obj_SetSpeed(obj, 1.5);
}else if(i>16){
Obj_Delete(obj);
}
ObjShot_SetGraphic(obj, g);
Obj_SetAlpha(obj, a);
yield;
}
}
//OPTION BULLET
let g = 101;
let i = -2;
let a = 170;
let opt = Obj_Create(OBJ_SHOT);
Obj_SetPosition(opt, x2, y2);
Obj_SetAngle(opt, 270);
ObjShot_SetGraphic(opt, g);
Obj_SetAlpha(opt, a);
Obj_SetSpeed(opt, 10);
ObjShot_SetBombResist(opt, true);
ObjShot_SetDamage(opt, 0.7);
ObjShot_SetPenetration(opt, 10);
while(!Obj_BeDeleted(opt)){
//if(Obj_IsIntersected(opt)==true){
if(Collision_Obj_Obj(opt,target)==true){
i = 0;
a = 220;
Obj_SetAngle(opt, 270+r);
}else{
g = 101;
}
if(i>=0){
ObjShot_SetDamage(opt, 0);
Obj_SetSpeed(opt, 1.5);
i++;
g = 102;
a-=2;
}
if(i>16){
Obj_Delete(opt);
}
ObjShot_SetGraphic(opt, g);
Obj_SetAlpha(opt, a);
yield;
}
}

@Initialize{
LoadGraphic(c~"pl00.png");
LoadPlayerShotData(c~"plshot00.txt");
                                          SetPlayerLifeImage(c~"pl00.png", 213, 293, 247, 325);
SetRibirthFrame(15);
SetSpeed(4, 1.5);
DrawHitbox;
}

@MainLoop{
drawcount++;
SetIntersectionCircle(GetPlayerX, GetPlayerY, 1);
optiona+=3; if(optiona>=360){optiona = 0;}
OptionScript;
yield;
}
@Missed{}
@SpellCard{
SetSpeed(4, 1.5);
UseSpellCard("WildAnnihilationDance", 0);
}
@DrawLoop{
SetTexture(c~"pl00.png");
SetAlpha(255);
SetGraphicScale(1,1);

//Draw player
SetGraphicAngle(0,0,0);
if(IsPressRight()==true){
SetGraphicRect(228, 102, 260, 146);
}else if(IsPressLeft()==true){
SetGraphicRect(230, 53, 261, 97);
}else{
if(drawcount<10){SetGraphicRect(5, 3, 38, 51);}
if(drawcount>=10 && drawcount<20){SetGraphicRect(37, 3, 70, 51);}
if(drawcount>=20 && drawcount<30){SetGraphicRect(69, 3, 102, 51);}
if(drawcount>=30 && drawcount<40){SetGraphicRect(101, 3, 134, 51);}
if(drawcount>=40 && drawcount<50){SetGraphicRect(134, 3, 165, 51);}
if(drawcount>=50 && drawcount<60){SetGraphicRect(165, 3, 198, 51);}
if(drawcount>=60 && drawcount<70){SetGraphicRect(198, 3, 229, 51);}
if(drawcount>=70 && drawcount<80){SetGraphicRect(228, 3, 262, 51);}
}
DrawGraphic(GetPlayerX, GetPlayerY);

//Draw options
SetGraphicRect(70, 148, 84, 162);
SetGraphicAngle(0,0,optiona*-1);

DrawGraphic(GetPlayerX+(rad*cos(optiona)), GetPlayerY+(rad*sin(optiona)));
DrawGraphic(GetPlayerX+(rad*cos(optiona)), GetPlayerY-(rad*sin(optiona)));
DrawGraphic(GetPlayerX-(rad*cos(optiona)), GetPlayerY+(rad*sin(optiona)));
DrawGraphic(GetPlayerX-(rad*cos(optiona)), GetPlayerY-(rad*sin(optiona)));

//Draw focus circle
if(IsPressSlow==true){
focusalpha+=30;
if(focusalpha>250){focusalpha=250;}
}else{
focusalpha-=30;
if(focusalpha<0){focusalpha=0;}
}
if(focusalpha>210){
focussize-=0.04;
if(focussize<=1){focussize=1;}
}else{
focussize = (focusalpha/240)+0.4;
}
SetAlpha(focusalpha);
SetGraphicRect(213, 151, 285, 213);
SetGraphicScale(focussize, focussize);
SetGraphicAngle(0,0,0);
DrawGraphic(GetPlayerX, GetPlayerY);
/*SetGraphicScale(1,1);
SetGraphicAngle(0,0,optiona);
DrawGraphic(GetPlayerX, GetPlayerY);*/

drawcount++;
if(drawcount>=80){drawcount=0;}
}

@Finalize{}
}

script_spell WildAnnihilationDance{
let frame = 0;
@Initialize{
SetPlayerInvincibility(120);
DeleteEnemyShotToItem(SHOT);
CollectItems;
}
@MainLoop{
frame++;
if(frame>120){End;}
yield;
}
@Finalize{
}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 28, 2009, 10:58:44 AM
@Henry & The Sword that cleaves evil,

Thank you both. Now I can further implement Reimu as playable character in my game.

Also, as a reminder: If you want to use
Code: [Select]
if(GetPlayerType==REIMU){
   spell card 1
}else{
   spell card 2
}
to make plural script or stage like Patchouli's or Satori's (different spell card in respect to different players), you will end up getting a life bar (for boss) divided into 2 but only 1 spell is playable.

I used another spell card, including 2 spell card versions, separated with an if...else... control statement.
Code: [Select]
if(GetPlayerType==REIMU_A||GetPlayerType==REIMU_B){
   }else{
}
}
Afaik you can make it shorter by
Code: [Select]
if(GetPlayerType==REIMU){
code goes here}else{
moar code goes here}
Remember that you can refer to both REIMU_A and REIMU_B as REIMU.
However, I tried that, it doesn't work for me. :(

Sorry, Drake. I don't know about player scripts and I cannot answer your question :(
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 28, 2009, 03:45:49 PM
I'm having a problem. I'm trying to make some enemy familiars loop around the boss in a bit of an diagonal oval shape, but I can't seem to make it do that. My current method for familiars involves using things like this:

Code: [Select]
famix1 = GetX+famidist*cos(famiang1);
famiy1 = GetY+famidist*sin(famiang1);
famix2 = GetX+famidist*cos(famiang2);
famiy2 = GetY+famidist*sin(famiang2);
famiang1 += 2;
famiang2 -= 2;

Stuff like that. Well, for familiars you can't hit, that is. (I don't see why they should all be killable.) I just want to use this code to make it loop around the boss in an oval shape, that's all. (Also, I'd rather not use any other method. Doesn't make sense to do it a more complicated way. XD)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 28, 2009, 03:48:46 PM
@Henry & The Sword that cleaves evil,

Thank you both. Now I can further implement Reimu as playable character in my game.

Also, as a reminder: If you want to use
Code: [Select]
if(GetPlayerType==REIMU){
   spell card 1
}else{
   spell card 2
}
to make plural script or stage like Patchouli's or Satori's (different spell card in respect to different players), you will end up getting a life bar (for boss) divided into 2 but only 1 spell is playable.

I used another spell card, including 2 spell card versions, separated with an if...else... control statement.

I only used it for my Dialogue script and it works perfect. I am not planning in making spellcards like Satori or Patchouli. Reimu and Marisa share the same enemy spellcards.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on July 28, 2009, 06:39:43 PM
would it be possible to use such an if statement in a plural file?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on July 28, 2009, 07:45:01 PM
No, make a stage script that calls on serparate plural files based on conditional statements.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on July 29, 2009, 12:54:12 PM
Em...
There are some spell card in the Touhou Series which is VERY difficult to remake, or even to get the algorithm.

I'm trying to remake something like Orin's "Blazing Wheel", then I encounter problems:

1. The starting position of the bullet is changing.
2. The speed of the bullets are different.
3. There is surely accelerations on the bullets :( (It can be considered a Danmakufu Question, right?)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on July 30, 2009, 04:50:03 AM
For Object-Object collision comparisons, do they have to be in the same task, or can I have two tasks for two different object bullets, and house the comparison blurb in, say, the MainLoop?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on July 30, 2009, 05:16:27 AM
For Object-Object collision comparisons, do they have to be in the same task, or can I have two tasks for two different object bullets, and house the comparison blurb in, say, the MainLoop?
No.

Only if both objects are created in the same task (then the collision comparison can only be used inside the task as well), or both objects are created in the @MainLoop can they be used for collision comparisons.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 30, 2009, 05:47:37 AM
Actually, it still only works when the variables are the same or some other exceptions. Even if two object bullets with different names are in the same task, if collision detection is called afterward then it looks for the objects, but only for the first frame because the detection isn't called in any while loops. The task runs once and then runs next frame on different objects.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on July 30, 2009, 07:15:25 AM
ahhh these questions are big and confusing! ??? ??? ??? i feel sad asking this but, how do you fire a laser? i try to scrypt them but they do not appear on the screen. ??? im stump'd
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 30, 2009, 01:06:30 PM
ahhh these questions are big and confusing! ??? ??? ??? i feel sad asking this but, how do you fire a laser? i try to scrypt them but they do not appear on the screen. ??? im stump'd


Try this as a shot:

Code: [Select]
if(frame==60){
CreateLaser01(GetX,GetY,2,GetAngleToPlayer,200,20,RED01,0);
}


Can you tell which part is missing in your code?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 30, 2009, 06:58:08 PM
Two question:

I copied like 1on1 the 96% Great Galaxy of Spiritus spellcard from Uwabami. However, if you die there , the entire screen doesn't gets cleared (Like Kanako's SUPERB VERY LOVABLE VOWG spellcard).

So how is this excactly done upon death of the character? I know I have to use the function: 'DeleteShotsinCircle' but how can I call this upon dying?

2nd: How do I spawn a waving row of bullets. Like Sanae's card with the river thing, except horizontal while the bullets spawn from left and move to the right =S.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 30, 2009, 07:04:41 PM
Sanae's card is actually just a bunch of lasers superimposed on each other. They all have a set length, and it just spawns new ones every few frames. If you bomb it, watch as you see each laser spawn.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 30, 2009, 07:17:52 PM
Sanae's card is actually just a bunch of lasers superimposed on each other. They all have a set length, and it just spawns new ones every few frames. If you bomb it, watch as you see each laser spawn.

So I should do the same for the bullets? Like spawn bullet at MaxY, next one like -10 etc untill reaching a parabole shape?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 30, 2009, 07:22:13 PM
Yeah, that sounds right. Then after the last one is finished, go back to the first, but alter the first bullet by another value, so it offsets the entire 'wave'. And so on so forth.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 30, 2009, 07:44:16 PM
Right, that works great. Now I just need to use this to create a relative easy-patternized noncard.

What about the 1st question regarding 'Upon death = clear radius of bullets '
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 30, 2009, 08:14:49 PM
if(OnPlayerMissed==true){delete shots etc}

alternatively,

When initializing variables,
let lives = GetPlayerLife;
let nextlives = GetPlayerLife;


And then each frame,
lives = GetPlayerLife;
if (lives < nextlives){
        nextlives = GetPlayerLife;
        delete shots etc
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 30, 2009, 08:50:39 PM
if(OnPlayerMissed==true){delete shots etc}

alternatively,

When initializing variables,
let lives = GetPlayerLife;
let nextlives = GetPlayerLife;


And then each frame,
lives = GetPlayerLife;
if (lives < nextlives){
        nextlives = GetPlayerLife;
        delete shots etc
}


The first one did the job.

   if(OnPlayerMissed==true){DeleteEnemyShotInCircle(ALL,GetPlayerX,GetPlayerY,112);}
   if(OnBomb==true){DeleteEnemyShotInCircle(ALL,GetPlayerX,GetPlayerY,112);}

Thanks alot Drake. I am getting closer on releasing my v3 of my Showdown contest with one excact imitated card from Uwabami breakers (96% spiritus), playable Reimu, added sprites, tweaked spellcards and a Lunatic mode.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on July 31, 2009, 03:33:05 AM
ahhh these questions are big and confusing! ??? ??? ??? i feel sad asking this but, how do you fire a laser? i try to scrypt them but they do not appear on the screen. ??? im stump'd
T_T my danmakufu hates me, i tryed the script u gave me but it Didn't work >_<;!!!!!!!
i cant tell what is wrong with it to, i dont even get an error message. an what is FireShot used for? ???
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 31, 2009, 03:38:33 AM
Read some tutorials thank you bye. (http://www.shrinemaiden.org/forum/index.php?topic=30.0)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on July 31, 2009, 03:49:47 AM
Read some tutorials thank you bye. (http://www.shrinemaiden.org/forum/index.php?topic=30.0)
Ive already read it, tryed it, and Failed T_T MISERABLY
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Johnny Walker on July 31, 2009, 04:00:32 AM
Ive already read it, tryed it, and Failed T_T MISERABLY
There is a very basic script in the Basic Tutorial who helped me a lot to learn a lot of danmakufu stuff. It's very very useful.
Or you can Download some other scripts and modify them little by little to see what happens with each line each time you change it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on July 31, 2009, 04:52:51 AM
Does anyone know the exact coordinates for everything that's in system.png? I've already figured out the life bar, event text box, Nullify box, Bomb icon, boss marker, things-that-fly-around-boss, and the HITBOX. (If I'm looking at it correctly, the area is 4, 91 for top-left corner and 9, 96 for bottom-right corner for the hitbox. I do recall someone mentioning that they wanted to get rid of this~) However, I'm having trouble with some other things, such as the invincibility circle for the player, the bars under the spellcard names, and the various ONE-PIXEL-TALL PIECES of the lifebar seperators. (If I've sized this file right, the thing is spread out to various locations one row of pixels at a time, with each turned about 90 degrees...in some direction, can't tell which. Seriously, what's up with that?) I'd honestly like some help with this... I'd love to have an accurate mapping of the system.png file so people can easily edit it.

For reference, this is what I did to the poor file:

(http://i244.photobucket.com/albums/gg13/MatthewPZC/snapshot044a.jpg)
(http://i244.photobucket.com/albums/gg13/MatthewPZC/snapshot043b.jpg)
(I swear I did this for laughs. HONESTLY! D: )


:D (Needs an awesomeface smiley. :/ )


For other reference, here's the coordinates I currently have, in case anyone would like to know that currently doesn't:

Format:
Piece: Left,Top;Right,Bottom

Hitbox: 4,91;9,96
Lifebars: 0,0;127,11
Bomb icon: 1,64;16,81
Nullify box: 0,180;?,198 (I cannot figure out exactly where it ends on the right, because if I put it where it seems to end, I somehow get a blotch of black where I'm using the 0,0,0 color, which should be invisible in Danmakufu... Or maybe it's just me not seeing it well. Can't tell. In any case, what SEEMS to be the end is about...127. But I'd honestly advise putting it around 3 for the left bounce and 124 for the right bound, as there's no reason to actually stretch it across the whole thing.)
Boss marker: 1,160;48,174
Things-that-fly-around-boss (What the heck ARE these things...?): 0,134;22,156

...and that's currently all I've figured out so far! ...I bet others here have already figured out all this stuff before I did, though. :P
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 31, 2009, 05:21:34 AM
Yeah. I found some of them out after someone mentioned it a while back. Hitbox is useful if you just want to get rid of the terrible icantseethis one, but being only five pixels wide is hindering. I've toyed around with the bomb icon and position marker before but it really doesn't matter much to me so I keep them at default.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 31, 2009, 05:31:29 AM
For other reference, here's the coordinates I currently have, in case anyone would like to know that currently doesn't:

Format:
Piece: Left,Top;Right,Bottom

Hitbox: 4,91;9,96
Lifebars: 0,0;127,11
Bomb icon: 1,64;16,81
Nullify box: 0,180;?,198 (I cannot figure out exactly where it ends on the right, because if I put it where it seems to end, I somehow get a blotch of black where I'm using the 0,0,0 color, which should be invisible in Danmakufu... Or maybe it's just me not seeing it well. Can't tell. In any case, what SEEMS to be the end is about...127. But I'd honestly advise putting it around 3 for the left bounce and 124 for the right bound, as there's no reason to actually stretch it across the whole thing.)
Boss marker: 1,160;48,174
Things-that-fly-around-boss (What the heck ARE these things...?): 0,134;22,156

...and that's currently all I've figured out so far! ...I bet others here have already figured out all this stuff before I did, though. :P
Awesome! I have been looking for a few of these. Was going to ask a question also regarding this but it seems you already have them. Especially the hitbox is very useful.

The things  that fly around the boss are just magical effects, look at the original Touhou games.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on July 31, 2009, 04:15:29 PM
How are you able to spawn enemies inside spell cards?

and then how are you able to take them from one card the the next?

After this I'll have my first boss ready.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 31, 2009, 04:23:26 PM
How are you able to spawn enemies inside spell cards?

and then how are you able to take them from one card the the next?

After this I'll have my first boss ready.

Enemies are often marked as familiars. If you want to spawn them you need to use CreateEnemyFromScript. But what do you mean with "take them to the next?" Like using them in the next spellcard aswell? In that case using CreateEnemyFromFile would be more sufficient. So you need to declare the enemies once inside a txt file and can be called from any other spellcard (Hence how stages also work).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on July 31, 2009, 04:44:03 PM
Aha, thanks.

Also, out of curiosity, what file type do 3d objects have to be?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 31, 2009, 04:54:13 PM
Danmakufu's 3D functions are nowhere near that sophisticated. You can't import models or anything, you'll need to manually rotate and draw each polygon using the 3D drawing functions. Nuclear Cheese's tutorial on the matter is the best way to get a grasp of how they work.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on July 31, 2009, 05:15:54 PM
I just read it.

I can't see how you were able to make those mountains.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on July 31, 2009, 06:13:19 PM
Ok, while making my boss I encountered a problem

I'm trying to get a wave of bullets to spawn again and again each time faster.

Code: [Select]
#TouhouDanmakufu
#Title[Darkness Sign "Blind from the Bottom"]
#Text[De-Coronation]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
let angle2 = 500;
let angle = 0;
   let imgExRumia=GetCurrentScriptDirectory~"img\ExRumia.png";
   let imgExRumiaBack=GetCurrentScriptDirectory~"img\ExRumiaBack.png";
    let frame = 0;
@Initialize {
SetMovePosition01(224,120,10);
   SetGraphicRect(1,1,64,64);
        LoadGraphic(imgExRumia);
   LoadGraphic(imgExRumiaBack);
        SetLife(1);
        SetDamageRate(0, 0);
        SetTimer(30);
        CutIn(YOUMU, "Darkness Sign [Blind from the Bottom]", imgExRumia, 0, 0, 200, 600);
        SetScore(500000);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 24);
        if(frame==angle2){
CreateShot01(rand(1,448), 1, 7, 90, RED12, 20);
CreateShot01(rand(1,448), 1, 6, 90, RED12, 20);
CreateShot01(rand(1,448), 1, 5, 90, RED12, 20);
CreateShot01(rand(1,448), 1, 4, 90, RED12, 20);
CreateShot01(rand(1,448), 1, 3, 90, RED12, 20);
CreateShot01(rand(1,448), 1, 2, 90, RED12, 20);
            frame = 0;
        }
if(angle2<0){
angle2=1;
}

        frame++;
angle++;
angle2--;
    }

    @DrawLoop {
      SetAlpha(255);
      SetTexture(imgExRumia);
SetGraphicRect(0,0,64,64);
      DrawGraphic(GetX(),GetY());
       
    }
    @BackGround {
SetTexture(imgExRumiaBack);
SetGraphicRect(0,0,384,448);
DrawGraphic(224,240);
}

    @Finalize {
    }
}

Anyone know what's wrong with that?

Sorry for being such a noob  :V
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on July 31, 2009, 06:25:13 PM
Quote
I can't see how you were able to make those mountains.
The trick is that the polygons the mountains are made of are not actually triangles. The image itself used for them is square, with the non-triangular part blacked out for transparency.

Creating the mountains with that texture was a matter of trial and error, I started by laying one texture out at an angle, then adding another and fiddling with its position and angle until its edge was close enough to the first to look like they were joined. Every mountain is the same, just drawn repeatedly at different positions and heights.

Quote
Ok, while making my boss I encountered a problem
You need to think about what's happening each loop. Frame starts at 0 and angle2 starts at 500. Frame goes up each loop and angle2 goes down, so they should meet at frame==250 the first time. Frame resets at 0 and angle2 keeps going down, next time they meet at frame==125. Reset again, meeting halfway they would need to meet at frame==62.5 which obviously can't happen, so you don't get any more shots. Also, eventually frame2 goes below 0, and doesn't get reset to 1 until after the if loop so that won't help.

I'd advise not having frame2 decrease every loop, only when shots are fired.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabblecorento on July 31, 2009, 06:52:35 PM
Mmk, thanks for the help!

With a ton of editing, I changed it to it decreases by 1 every shot fired, and angle 2 is 60.

It works fine now. (I can't get into the spirit of danmakufu very well...)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 31, 2009, 08:37:52 PM
I'm in despair! I'm trying to make a conversation work, but I keep being told something is wrong with SetChar.
I have loaded the graphic and stored in a variable of the right name, so nothing is wrong there.

It looks like this now:

script_enemy_main has:
let Kurumi = (GetCurrentScriptDirectory~"img\Kurumi Big.png");

Initialize has:
LoadGraphic(Kurumi);

And the rest is:

Code: [Select]
if(frame==120){
SetChar(LEFT,Kurumi);
SetGraphicRect(LEFT,0,0,130,200);
MoveChar(LEFT,FRONT);
TextOutA("\c[GREEN]I'm just here to test stuff.");
}
Yet, every time something seems to be wrong with SetChar. What could it be?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 31, 2009, 08:38:47 PM
@ puremrz,
You have to create dialogues in events, not enemies. (not sure if this is correct). That is how I did it in my game. Like:

To call: CreateEventFromScript("nameoftheevent");

Code: [Select]
script_event nameoftheevent{
      declare vars here

       initialize{
            load stuff here
       }

       mainloop {
             talking goes here
       }

       finalize {
              delete stuff goes here
       }
}

You can call the event inside the enemy script. So that is not a problem. Also the ( ) around decleration of Kurumi is not needed.

-------------------------
General comment: Is it me or is working with:

function wait(w){
   loop(w){
      yield;
   }
}

Much easier to handle tasks and routines? I was firstly also working with if(frame==bla){fire bla} etc. However the overview becomes pretty bad with more complex patterns. When I learned this function from examples I started using it forever.

Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 31, 2009, 08:46:16 PM
Ah, I've been looking through afro to see how conversations work. But I can't find out how you made one script summon another.

Edit: Gah, you edited yourself while I was posting D:
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 31, 2009, 08:50:10 PM
The boss is created within Afrostage.txt

Which calls the Afroboss.txt with the plural list of spellcards, and you will notice: AfroDialogue01.txt in there which is called first.

It is kind of chain linking but this is only required when you create a stage. You don't need a stage unless you want to change the background. You need to have a script_event  and CreateEvent function, that is all.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on July 31, 2009, 09:35:59 PM
Can you post a sample file of the minimum required data to make one person say one line of text?
The amount of data in Afro is confusing, I can no longer see what information I need and what I don't need. Does it HAVE to be multiple files, or is there a possibility you can put the talk in the same txt as the happenings before and after the talk?
I tried so much, and Danmakufu crashed in every possible way while I was busy. That's why I need a clean file with only the necessary data in it, so I can see what went wrong all those times.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on July 31, 2009, 10:33:33 PM
Minimum required is nothing more than a plural script and one dialogue script.

This inside your plural:
#ScriptPathData
#ScriptPath[.\Dialogue01.txt]
#ScriptPath[.\Nonspell01.txt]
#ScriptPath[.\SpellCard01.txt]


Dialogue01.txt
Code: [Select]
script_enemy_main{

    let boss = GetCurrentBlabla

@Initialize{
SetLife(1);
SetDamageRate(1,1);
LoadGraphic(boss);
CreateEventFromScript("talk");
}

@MainLoop{
if(GetEventStep==1){AddLife(-10);}
yield;
}
@DrawLoop{
SetTexture(boss);
SetAlpha(255);
        etc etc...
DrawGraphic(GetX, GetY);
}

    @BackGround
    {

    }
}

script_event talk{
let CSD = GetCurrentScriptDirectory;
let FACE = CSD ~ "<<pathname>>";

@Initialize{
LoadGraphic(FACE);
}
@MainLoop{
SetChar(LEFT,FACE);SetGraphicRect(LEFT,0,0,128,256);
MoveChar(LEFT,FRONT);
TextOutA("\c[RED]Testing bla bla bla");
SetStep(1);
}
@Finalize{
DeleteGraphic(stuff);
}
}

What happens here is when you load your plural file it will call the Dialogue01 first. Which will simply show your boss popping up and inmediately activate the event because it calls for CreateEvent. This Dialogue acts like a dummy spellcard which will wait untill the dialogue reaches SetEventStep 1. This will trigger the -10 life in the MainLoop killing the dummy spellcard and instantly calling the next line in the plural script.

This way it looks like your boss stops talking and starts attacking. I hope that was clear enough.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on July 31, 2009, 10:49:00 PM
What does GetKeyState(VK_USER) do, and what is a user-defined key?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on July 31, 2009, 10:54:18 PM
It defaults to C, but I can't recall if you can change it or not.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on August 01, 2009, 08:37:13 AM
Minimum required is nothing more than a plural script and one dialogue script.

This inside your plural:
#ScriptPathData
#ScriptPath[.\Dialogue01.txt]
#ScriptPath[.\Nonspell01.txt]
#ScriptPath[.\SpellCard01.txt]


Dialogue01.txt
Code: [Select]
script_enemy_main{

    let boss = GetCurrentBlabla

@Initialize{
SetLife(1);
SetDamageRate(1,1);
LoadGraphic(boss);
CreateEventFromScript("talk");
}

@MainLoop{
if(GetEventStep==1){AddLife(-10);}
yield;
}
@DrawLoop{
SetTexture(boss);
SetAlpha(255);
        etc etc...
DrawGraphic(GetX, GetY);
}

    @BackGround
    {

    }
}

script_event talk{
let CSD = GetCurrentScriptDirectory;
let FACE = CSD ~ "<<pathname>>";

@Initialize{
LoadGraphic(FACE);
}
@MainLoop{
SetChar(LEFT,FACE);SetGraphicRect(LEFT,0,0,128,256);
MoveChar(LEFT,FRONT);
TextOutA("\c[RED]Testing bla bla bla");
SetStep(1);
}
@Finalize{
DeleteGraphic(stuff);
}
}

What happens here is when you load your plural file it will call the Dialogue01 first. Which will simply show your boss popping up and inmediately activate the event because it calls for CreateEvent. This Dialogue acts like a dummy spellcard which will wait untill the dialogue reaches SetEventStep 1. This will trigger the -10 life in the MainLoop killing the dummy spellcard and instantly calling the next line in the plural script.

This way it looks like your boss stops talking and starts attacking. I hope that was clear enough.


Thank you, I finally got it working after some minor problems. Now I'm one step closer to making a full game :3
All left now is to make the graphics (no problem there, I can draw :P), learn how to make 3d backgrounds, make my own playable character, and to finally understand the reflecting bullet business. ^^;
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on August 01, 2009, 07:47:36 PM
is there anything special about the first 8 spells of an extra stage boss? 9 is survival and 10 is a build-up card, but i just cant find the special things of those before that.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 01, 2009, 08:05:17 PM
Recently a lesser survival card shows up, but if MoF it was 8th and in SA it was 5th.

Extra midbosses have 3 spellcards.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on August 01, 2009, 08:33:00 PM
not counting pcb
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on August 03, 2009, 01:32:21 AM
Okay, I know I've asked for this before, but when I tested the code I was given, it never worked the way it was supposed to.


I need some code that makes objects home in on enemies gradually some time after they're fired, like the built-in ReimuA. As I said, I asked for this before, and someone gave me code for it, but I just tested it and it didn't home in at all. It angled a bit, but that's all it did- no homing. It's all this figuring out exactly which direction to move in that gets me. I have some idea how to do it, but right now, as I try, I keep getting confused as I think about it...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 01:39:24 AM
http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Object_Bullets

First example.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Primula on August 03, 2009, 02:14:11 AM
Code: [Select]
#TouhouDanmakufu
#Title[Random Insanities,"Mindless Knowledge"]
#Text[Ehhh]
#Image[]
#BackGround[IceMountain]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let BossImg = "script\ExRumia\img\ExRumia.png";
    let BossCutIn = GetCurrentScriptDirectory~"img\RumiaCutin.png";
    let frame = -120;

    @Initialize {
        SetLife(350);
        SetTimer(60);
        SetDamageRate(10, 0);
        SetScore(3333333.33);
        CutIn(KOUMA, "Random Insanities"\""Mindless Knowledge"\", "", 0, 0, 0, 0);

}

  @MainLoop {
      if(frame == 60) {
         speed = 2;
         loop(5) {
            CreateShot01(GetX, GetY, speed, GetAngleToPlayer+10, RED01, 10);
            CreateShot01(GetX, GetY, speed, GetAngleToPlayer, RED01, 10);
            CreateShot01(GetX, GetY, speed, GetAngleToPlayer-10, RED01, 10);
            speed += 0.2;
            }
         frame = 0;

        }
        frame++;
    }   

    @DrawLoop {

       SetTexture(BossImage);
       SetGraphicRect(0, 0, 64, 64);
       DrawGraphic(GetX, GetY);
      
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
}
}

I've been trying to do a bullet pattern that does
        
   / l \
  /  l  \
 /   l   \
/    l    \

and tried to use other scripts as bases..But the script keeps crashing.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 02:23:54 AM
You didn't declare the variable "speed".



My turn for a question I suppose. So I'm making a player script bomb, which works all fine and well until it finishes. I have "End;" declared at the end of the "run" task, which according to the player script tutorial, should end the spellcard. It does, along with the whole player script, causing Danmakufu to crash. So if I take out "End" at the end of my bomb task, once I bomb, I'm never allowed to bomb again. Ever. Even if I die.

Uhhh, any ideas, or do I have to post the script? End isn't declared anywhere else in the script, and is inside the spell card's braces, inside the "run" task (as per Stuffman's tutorial, as far as I can see). Any reason why the whole player script (and thus Danmakufu) would crash? I took a look at other player scripts and I'm supposedly following the same format.

Also, don't get me started on how annoying it was that I forgot to capitalize the "c" in @SpellCard. The problems that caused me were endless.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on August 03, 2009, 02:31:38 AM
http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Object_Bullets

First example.

Oh wow, I had no idea that existed... It works, but there's a slight problem- it doesn't really home in that much. Rather, it aims. Basically, if you're at a position where the shots will go behind the enemy before its turn makes it go into the enemy, it most likely WON'T hit the enemy at all...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 02:33:15 AM
Increase the max traverse angle.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 03, 2009, 02:37:11 AM
Please post the script, Naut. The only thing that makes sense currently is if you managed to call End outside of the spell. It might be repeating the function somehow, causing the player script to end.

Or PM me because I already know who you're making.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 02:38:33 AM
Anybody who follows my YouTube account should know who I'm making, but whatever.

Expect a PM.

Sent.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on August 03, 2009, 02:48:28 AM
Increase the max traverse angle.

Problem with that is that it needs to get pretty high before it'll get fixed that way, and by that time, it doesn't look pretty "gradual" anymore. Darn it. I've tried changing the traverse angle partway through the movement, but for some reason, it doesn't seem to take effect then. :/

EDIT: Nevermind, it takes effect, but it's still really slow to work to be useful. Hmm... I need more ideas on how I could tackle this...

EDIT2: Oh cool, I finally fixed it. Yay.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 02:53:21 AM
maxTraverse+=number;
number+=0.01;


??


Yay.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on August 03, 2009, 02:59:19 AM
maxTraverse+=number;
number+=0.01;


??


Yay.

Not even that helps at high speeds. For some reason, none of this really works well when the speed is set higher than 6 and I try to have some delay in the homing. That is, make it home in AFTER it goes out a bit. Now, if I take out that delay, it'll most likely work exactly as I want it...

EDIT: Fixed now, it's just as I want it. Yay :D
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Primula on August 03, 2009, 03:07:09 AM
Ah, thanks Naut for mentioning the speed part, I also dug deeper into the other script to see what I also missed.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 03, 2009, 04:12:04 AM
Well, it's not just the End function. I used a different method that I always use and it still doesn't work. I did notice that the graphic doesn't actually lose any alpha value, even though it says to.

Also I updated your spritesheet because it was terrible lol. You're never supposed to open a 32-bit image with transparency in Paint, man.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 04:28:00 AM
This is why I use black.png as my background. Graphics aren't my thing, yo.

Also, you've noticed my other problem (though wasn't as serious, so I've left it alone until now):

Obj_SetAlpha doesn't fucking do anything.

Not the first time this has happened, either. Switching between Alpha and Additive blending doesn't change whether or not SetAlpha works either, it just blends them all together with 255 alpha, or draws one on top of the other, respectively. The other case I hinted towards was that the function doesn't affect my fucking frog dot explosions either. Piss me off.

On another note, I can't get the animation data to work for the snake shots, the image just doesn't appear (however, if I just set a rect, it does! Fancy that!?). Anybody got an example shot data sheet that I can take a look at that uses animation data, 'cause the ones I've been using aren't proving useful, evidently.

Code: [Select]
ShotData{
id=4
render=ADD
alpha=160
angular_velocity=0
animation_data={4, 25, 162, 35, 222}
animation_data={4, 38, 162, 49, 222}
animation_data={4, 52, 162, 63, 222}
animation_data={4, 66, 162, 77, 222}
}

Goddamn I'm running in to some heavy problems with player characters.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 03, 2009, 04:31:09 AM
Code: [Select]
ShotData{
   id=4
   render=ADD
   alpha=160
   angular_velocity=0
   AnimationData{
      animation_data={4, 25, 162, 35, 222}
      animation_data={4, 38, 162, 49, 222}
      animation_data={4, 52, 162, 63, 222}
      animation_data={4, 66, 162, 77, 222}
      }
   }
lawl

Also I've been messing around with it and I really can't tell what's wrong. For all intensive purposes, it's totally fine.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 04:36:28 AM
Code: [Select]
ShotData{
   id=4
   render=ADD
   alpha=160
   angular_velocity=0
   AnimationData{
      animation_data={4, 25, 162, 35, 222}
      animation_data={4, 38, 162, 49, 222}
      animation_data={4, 52, 162, 63, 222}
      animation_data={4, 66, 162, 77, 222}
      }
   }
lawl

(http://i641.photobucket.com/albums/uu134/Nautth/TOKENIZER.jpg)

Also I've been messing around with it and I really can't tell what's wrong. For all intensive purposes, it's totally fine.

Fuck this shit, anybody else wanna have a go at this faggotry?

http://www.mediafire.com/?nqmnkihtndt

Add "End;" right after "loop(360){yield;}" in the "run" task, at the bottom of the script to see Danmakufu crash six seconds after you press x. Leave it alone to never bomb more than once. Also, please have a look at how Obj_SetAlpha DOES NOTHING OH GOD WHAT NOW.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 03, 2009, 04:47:42 AM
Remove the spaces between the numbers, maybe. It says something's wrong with the tokens.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 04:52:27 AM
Yeah, I put in the wrong braces. Should be (), not {}. Well good, at least that problem has a known solution, and is now fixed. But the End problem is destroying me, with the SetAlpha problem being the salt in my open wounds.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on August 03, 2009, 03:05:58 PM
I was just working on a spellcard script in which you face  3 enemies at once, when i stumbled upon this problem: only when you hit the parent enemy, the boss takes correct damage... when you hit one of the slave enemies the boss takes only 1/10 of the total damage dealt...

the parent has this:
        SetLife(500);
        SetDamageRateEx(20, 10,100,100);
the childs have this:
        SetLife(5000);
        SetDamageRateEx(100, 100,10000,10000); < i tried everything but i get the same result, even with this

what should i do?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on August 03, 2009, 05:32:15 PM
Found your problem Naut, you're gonna cry when you realize how stupid it is.

It's not the bomb, it's the cutin. You're using the same image for the cutin as you are for her sprite, and I suspect CutIn loads the image you specify and then deletes it when it's done. So it was deleting Sanae's spritesheet when you hit End, resulting in an error a few moments later. I figured this out when I realized Sanae's options got whitebox'd after the spellcard ended.

This all could've been averted if you took 10 seconds to google a Sanae pic :V

Oh and yeah Obj_SetAlpha doesn't work. Sucks right? You need to use DrawGraphic if you want transparency.

Oh wait, HURR, I've done this before with Josette B's unfocused card

Obj_SetAlpha is for shot objects, there's a different function for effect objects. What you need is ObjEffect_SetVertexColor. Aside from applying color filters, it also has an argument for setting the alpha of each vertex. So you just need to set each vertex to the desired alpha. Kind of a pain in the ass but it works.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 03, 2009, 06:09:14 PM
FUUUUUUUCCCCKKKKKKKK WOW
THAT WAS SO STUPID

He eventually needed to use SetVertexColor anyways, but I guess he would have tried to fix this problem anyways, so :V

Also quick

(http://img18.imageshack.us/img18/2383/facepl02no.png)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Primula on August 03, 2009, 06:47:08 PM
NO THIS LOL
(http://i487.photobucket.com/albums/rr239/Sachouli/Tasogare%20Frontier/swr_sanae1.jpg) or
(http://i487.photobucket.com/albums/rr239/Sachouli/Tasogare%20Frontier/swr_sanae.png)

Just kiddin ~ Just kiddin ~ But Tasofro shoulda use these pictures for the upcoming game, along with another picture of China and Cirno D8
Gonna make SanaeA Naut? Just kidding, again.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 08:15:34 PM
Found your problem Naut, you're gonna cry when you realize how stupid it is.

It's not the bomb, it's the cutin. You're using the same image for the cutin as you are for her sprite, and I suspect CutIn loads the image you specify and then deletes it when it's done.
...
This all could've been averted if you took 10 seconds to google a Sanae pic :V

MY LIFE IS FORFEIT

Obj_SetAlpha is for shot objects, there's a different function for effect objects. What you need is ObjEffect_SetVertexColor. Aside from applying color filters, it also has an argument for setting the alpha of each vertex. So you just need to set each vertex to the desired alpha. Kind of a pain in the ass but it works.

Eww. Well that blows.

NO THIS LOL
[Xbax heug green pictars]

Too large, heh.

Gonna make SanaeA Naut? Just kidding, again.

(http://i641.photobucket.com/albums/uu134/Nautth/sanaeA.jpg)

I'll be using Drake's lovely sanae Cut in. Thanks for the help, bros.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 03, 2009, 08:27:01 PM
I see snakes in that picture.

Is there an easier btw to change the hitbox for Marisa and Reimu in Danmakufu? Or are by any chance the txt files for their character info available :S
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 03, 2009, 08:45:06 PM
Oh yeah I forgot the updated sprite sheet. You might have to change some alpha values.

Most of the rects should be the same. Snakes might be a pixel outwards. Hitbox is two pixels bigger and Nuke is different.

(http://img27.imageshack.us/img27/6913/sanaeo.png)

Also, note that her main shot changes color and angle depending on how far away they are from her. There are two red diamonds first, then four each of yellow squares, green diamonds, aqua squares, blue diamonnds; and I'm assuming purple squares to fit Danmakufu's hueg play area.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 03, 2009, 08:48:02 PM
Ballin'.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: hyperbolic colin on August 03, 2009, 08:56:51 PM
Also, note that her main shot changes color and angle depending on how far away they are from her. There are two red diamonds first, then four each of yellow squares, green diamonds, aqua squares, blue diamonnds; and I'm assuming purple squares to fit Danmakufu's hueg play area.

*...thinks of Lucky Charms danmaku...*   :D
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Danielu Yoshikoto on August 03, 2009, 09:37:12 PM
Oh noes my Spellcards broke...

Long story short:
I tried working on a ExReimu, everyone who is a friend of me on youtube might know about it already...
for some reason the spellcards don?t want to work anymore...
They only display the cut-it and the spellcard name (and bonus).

in the zip i added a non-spell working and a not working spellcard.

the spellcard should have the balck-blue yingyang BG like the non-spell but there should also be tiles in front of it (semi-transparent) but also a spinning ying-yang orb behind reimu (whice also indicates the radius of SetCollisionB). and that?s about it. i just don?t know why they don?t work... Danmakufu gave out an error saying something about script_enemy_main [{...}]
i don?t know why it did...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 03, 2009, 10:45:28 PM
Never mind, just one.

Code: [Select]
        MagicCircle(true);
        LoadUserShotData(ExDANMAKU);
        SetMovePosition02(GetCenterX, GetClipMinY + 120, 120);
    }

    @MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 64);
and
Code: [Select]
    @Finalize {
        if(GotSpellCardBonus){
        loop(30){
            CreateItem(ITEM_SCORE,GetX+rand(-50,50),GetY+rand(-50,50));
}
            PlaySE(GetCurrentScriptDirectory~"SFX\SpellBonus.wav");
        }
    }

    @BackGround {
    }
}
You just misplaced a bracket.
Look for these things, man >:|
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Danielu Yoshikoto on August 03, 2009, 11:07:49 PM
Never mind, just one.

Code: [Select]
        MagicCircle(true);
        LoadUserShotData(ExDANMAKU);
        SetMovePosition02(GetCenterX, GetClipMinY + 120, 120);
    }

    @MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 64);
and
Code: [Select]
    @Finalize {
        if(GotSpellCardBonus){
        loop(30){
            CreateItem(ITEM_SCORE,GetX+rand(-50,50),GetY+rand(-50,50));
}
            PlaySE(GetCurrentScriptDirectory~"SFX\SpellBonus.wav");
        }
    }

    @BackGround {
    }
}
You just misplaced a bracket.
Look for these things, man >:|

i actually did but... i tried changing that, but it didn?t do anything else
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 03, 2009, 11:36:40 PM
The only one that didn't work for me right away was Danmaku Firework, and that was solved just by what was posted above.

Everything works properly.

Code: [Select]
#TouhouDanmakufu
#Title[Spell01]
#Text[]
#BackGround[User(\background.png, 1, 1)]
#BGM[.\bgm.ogg]
#PlayLevel[Work in Progress]
#ScriptVersion[2]

script_enemy_main {
    let ImgBackground = GetCurrentScriptDirectory~"ReimuBackLast.png";
    let Yingyang = GetCurrentScriptDirectory~"ReimuSpellBack.png";
    let BgOverlay = GetCurrentScriptDirectory~"Spell1bg.png";
    let BossImage = GetCurrentScriptDirectory~"PlayerBoss.png";
    let BossCutIn = GetCurrentScriptDirectory~"ReimuCutIn.png";
    let Frame = -120;
    let ANGA = 0;
    let Rotate = 0;
    let bgscroll=0;
    let fadein=0;
    let ExDANMAKU = GetCurrentScriptDirectory~"supershot.txt";
    let ShotA = GetCurrentScriptDirectory~"\SFX\Shot1.wav";
    let ShotB = GetCurrentScriptDirectory~"\SFX\Shot2.wav";
    let ShotC = GetCurrentScriptDirectory~"\SFX\Shot3.wav";
    let ShotD = GetCurrentScriptDirectory~"\SFX\se_power0.wav";
    @Initialize {
SetAlpha(255);
        SetLife(500);
        SetDamageRate(16, 4);
        SetTimer(50);
        SetInvincibility(120);
        LoadGraphic(ImgBackground);
        LoadGraphic(BgOverlay);
        LoadGraphic(Yingyang);
        LoadGraphic(BossImage);
        CutIn(YOUMU, "Light Sign - Danmaku Firework", BossCutIn, 0, 0, 192, 320);
        SetScore(5000000);
        SetEnemyMarker(true);
        Concentration01(120);
        MagicCircle(true);
        LoadUserShotData(ExDANMAKU);
        SetMovePosition02(GetCenterX, GetClipMinY + 120, 120);
    }

    @MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 64);

        if(Frame<=9&&Frame>=0){
loop(8){
        CreateShotA(1, GetX, GetY, 0);
        SetShotDataA(1, 0, 1, GetAngle, 3, 0, 0, 35);
        SetShotDataA(1, 120, 2, rand(-60,240), 0, 0, 0, 172);

FireShot(1);
}
}

        if(Frame==10){
SetMovePosition03(rand(GetClipMinX + 50, GetClipMaxX - 50), rand(GetClipMinY + 30, GetClipMinY + 120), 8, 3);
        }

        if(Frame<=39&&Frame>=30){
loop(8){
        CreateShotA(1, GetX, GetY, 0);
        SetShotDataA(1, 0, 1, GetAngle, -3, 0, 0, 39);
        SetShotDataA(1, 120, 2, rand(-60,240), 0, 0, 0, 173);

FireShot(1);
}
}

        if(Frame==40){
SetMovePosition03(rand(GetClipMinX + 50, GetClipMaxX - 50), rand(GetClipMinY + 30, GetClipMinY + 120), 8, 3);
        }

        if(Frame==59){
        Frame=-1;
        }

    Frame++;
    Rotate++;
    }

    @DrawLoop{
SetTexture(ImgBackground);
SetGraphicRect(0, 0, 348, 448);
SetGraphicScale(1.2, 1.2);
SetGraphicAngle(0, 0, 0);
SetAlpha(255);
DrawGraphic(GetCenterX, GetCenterY);

SetTexture(BgOverlay);
SetAlpha(fadein);
SetGraphicScale(1,1);
SetGraphicRect(0,0,1400,1400);
SetGraphicAngle(0, 0, 0);
DrawGraphic(GetCenterX()+bgscroll,GetCenterY()+bgscroll);
SetAlpha(fadein/2);
DrawGraphic(GetCenterX()-bgscroll,GetCenterY()-64+bgscroll);

SetTexture(Yingyang);
SetGraphicRect(0, 0, 64, 64);
SetGraphicScale(2,2);
SetAlpha(127);
SetGraphicAngle(0, 0, Rotate);
DrawGraphic(GetX, GetY);

        SetTexture(BossImage);
SetGraphicScale(1, 1);
SetGraphicAngle(0, 0, 0);
SetAlpha(255);
if(GetSpeedX()==0){SetGraphicRect(0,64,64,128);}
else if(GetSpeedX()>0){SetGraphicRect(128,64,192,128);}
else if(GetSpeedX()<0){SetGraphicRect(64,64,128,128);}
        DrawGraphic(GetX, GetY);
DrawText(" ", 36, 30, 11, 255);
        bgscroll++;
if(bgscroll>=256){bgscroll=0;}
if(fadein<100){fadein++;}
    }

    @Finalize {
        if(GotSpellCardBonus){
        loop(30){
            CreateItem(ITEM_SCORE,GetX+rand(-50,50),GetY+rand(-50,50));
}
            PlaySE(GetCurrentScriptDirectory~"SFX\SpellBonus.wav");
        }
    }

    @BackGround {
    }
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on August 04, 2009, 12:12:13 AM
For other reference, here's the coordinates I currently have, in case anyone would like to know that currently doesn't:

Format:
Piece: Left,Top;Right,Bottom

Hitbox: 4,91;9,96
Lifebars: 0,0;127,11
Bomb icon: 1,64;16,81
Nullify box: 0,180;?,198 (I cannot figure out exactly where it ends on the right, because if I put it where it seems to end, I somehow get a blotch of black where I'm using the 0,0,0 color, which should be invisible in Danmakufu... Or maybe it's just me not seeing it well. Can't tell. In any case, what SEEMS to be the end is about...127. But I'd honestly advise putting it around 3 for the left bounce and 124 for the right bound, as there's no reason to actually stretch it across the whole thing.)
Boss marker: 1,160;48,174
Things-that-fly-around-boss (What the heck ARE these things...?): 0,134;22,156

...and that's currently all I've figured out so far! ...I bet others here have already figured out all this stuff before I did, though. :P
Awesome! I have been looking for a few of these. Was going to ask a question also regarding this but it seems you already have them. Especially the hitbox is very useful.

The things  that fly around the boss are just magical effects, look at the original Touhou games.
I found the coordinates for the event box and the spell lines, not to mention the invincibility box already. Who got the life bar separators already?

Invincibility: 1, 384, 126, 510
Spell lines:  player spell: 0, 38, 259, 44   enemy spell: 0, 45 259, 51
Event Box: 0, 26, about 125, 33? (I'm still vfiguring out the right boundary for the event box, also I just can't figure it the bottom bound.)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on August 04, 2009, 01:19:36 AM
I found the coordinates for the event box and the spell lines, not to mention the invincibility box already. Who got the life bar separators already?

Invincibility: 1, 384, 126, 510
Spell lines:  player spell: 0, 38, 259, 44   enemy spell: 0, 45 259, 51
Event Box: 0, 26, about 125, 33? (I'm still vfiguring out the right boundary for the event box, also I just can't figure it the bottom bound.)

Oh, forgot to mention the Event Box. I already found that, too. The right boundary is the same as the right boundary of the lifebar, and the bottom bound is...35. Yes. Thanks for finding the spell lines and invincibility cirlce, though!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 04, 2009, 01:30:41 AM
Also, note that her main shot changes color and angle depending on how far away they are from her. There are two red diamonds first, then four each of yellow squares, green diamonds, aqua squares, blue diamonnds; and I'm assuming purple squares to fit Danmakufu's hueg play area.

I have no idea how to easily create this effect, aside from controlling the bullets frame by frame.

Please tell me there is another way.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 04, 2009, 03:58:06 AM
Here you go.

(http://img269.imageshack.us/img269/6126/sanae.png)

Replace her ID1 shot with

Code: [Select]
ShotData{
id=1
render = ALPHA
alpha = 250
angular_velocity = 0
AnimationData{
animation_data=(2, 200, 150, 218, 168)
animation_data=(4, 202, 173, 216, 187)
animation_data=(4, 200, 193, 218, 211)
animation_data=(4, 221, 152, 235, 166)
animation_data=(4, 220, 172, 238, 190)
animation_data=(4, 222, 195, 236, 209)
}
}

It was... actually harder than I thought just to turn the damn thing 45 degrees.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 04, 2009, 04:23:52 AM
Thanks. And yeah, I only use MSPaint, so the way you did it wasn't even an option for me.

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 04, 2009, 04:27:28 AM
no i mean i literally sprited the diamonds by hand
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 04, 2009, 04:43:03 AM
Well I was planning on keeping my sanity so...

Yeah, thanks.

Another question (non-stop today, it seems):
How do I remove that annoying time stop whenever you bomb. I know it's possible...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 04, 2009, 06:53:36 AM
It's the CutIn function. You can just take it out if you want, but if you want the actual cut-in without the stop you can make an effect object for it or something.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 04, 2009, 12:11:04 PM
Drake, I noticed you are using the white button hitbox. Though how did you manage to hide the Danmakufu regular hitbox when focussing? It keeps appearing over my own one =.=
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on August 04, 2009, 03:23:53 PM
Thanks for not helping me.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 04, 2009, 05:23:30 PM
Drake, I noticed you are using the white button hitbox. Though how did you manage to hide the Danmakufu regular hitbox when focussing? It keeps appearing over my own one =.=
Naut used an effect object. I originally thought that was the best way, but I had tons of trouble rotating it and the like. Drawing graphics isn't going to do anything, which is probably what you're currently doing. I used an object shot. The bullet shows up over the hitbox and even other bullets too.

Thanks for not helping me.
I dunno lol. Never worked with more than one enemy, and I don't think you'd find many places where they aren't just helpers.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 04, 2009, 05:33:46 PM
Naut used an effect object. I originally thought that was the best way, but I had tons of trouble rotating it and the like. Drawing graphics isn't going to do anything, which is probably what you're currently doing. I used an object shot. The bullet shows up over the hitbox and even other bullets too.
That is a smart solution ** smacks forehead ** why didn't I thought of that.

Now I just a way to figure out the excact stuff for MarisaB danmakufu shottype.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 05, 2009, 12:16:33 AM
Naut used an effect object. I originally thought that was the best way, but I had tons of trouble rotating it and the like.

Don't get me started. Rotating it about any axis throws it off center for some reason, so I'll probably be using an object shot as well. Bleh.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on August 05, 2009, 02:59:55 PM
Hi.
If I would like to output some text onto the screen (not in dialogue format), what function should I use? Also, how can I put variable(numerical data .etc) as text?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 05, 2009, 03:05:16 PM
If you want to draw a string, then use this:
Code: [Select]
DrawText("string", x, y, fontsize, alpha);
You can also draw the value of a variable:
Code: [Select]
DrawText(variable, x, y, fontsize, alpha);
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 05, 2009, 08:22:37 PM
Yay I got the hitbox bullet working it even sticks around with the player. Except the I have to move the sprite to a white transparant bg instead of the black I am using now to make it show better  :V

Now I just need to add some lasers and her Masterspark spellcard.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 07, 2009, 02:55:02 AM
If I wanted to get an argument that tested whether an object shot created by the player intersected an enemy, would I use Obj_IsIntersected? Or is that only for testing if the player is intersecting an enemy shot?

Note: I am receiving a Mysterious Japanese Error Message(tm) that is scolding me about something on the line when I am asking if Obj_IsIntersected(obj) == true. MYSTERY. Unless it's actually BeIntersected and the wiki is a liar.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 07, 2009, 03:08:19 AM
IsIntersected takes note of the enemy's hitbox and the statement is true if the object is in it's x range.

Chances are you don't have enemy hitbox detection or something. It's not what you want, anyways.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 07, 2009, 03:30:40 AM
Oh christ, then I'm gonna have to do that stupid ascent of enemy id's, and acquire their x and y coordinates then, huh. I'm trying to make a shot death animation (e.g. an explosion), is there a better way to do it, o venerable Gods of Danmakufu?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on August 07, 2009, 03:29:21 PM
What is the bug of this Spell Card Statement?

Code: [Select]
#TouhouDanmakufu
#Title[Sun Sign "Royal Flare"]
#Text[]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = -120;
    let bg = GetCurrentScriptDirectory~"images\Bossbgsunwood.jpg";
    let i;
    let j;
    let max=6;
    let max2=9;
    let max3=6;
    let random;
    let temp;
    let time;
    #include_function "..\drawing.txt"
    @Initialize {
       SetLife(1500);
       SetTimer(120);
       SetScore(1000000);
       SetDurableSpellCard();
       SetDamageRate(25,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "Sun Sign "\""Royal Flare"\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        if(frame>0){
           if(frame==30){
      time=30+GetCenterX-GetX+5;
      ascent(i in 0..8){
CreateShotA(0, GetX+cos(i*360/8)*10, GetY+sin(i*360/8)*10, 10);
SetShotDataA(0, 0, 1, 90, 0, 0, 1, 226);
SetShotDataA(0, GetCenterX-(GetX+cos(i*360/8)*10)-5, 1, 90, 0, -0.1, 0, 226);
FireShot(0);
      }
   }
   [b][color=red]if(frame>time&&(frame-time)%90==0){ //bug is at here[/color][/b]
      temp=GetAngleToPlayer;
      ascent(i in 0..20){
ascent(j in 0..8){
            SunBullet(temp+j*360/8,10,3*i);
}
      }
   }
        }
        frame++;
yield;
    }

    @DrawLoop {
       bossSC;
    }
    @BackGround{
       backgroundSC;
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
    task SunBullet(baseangle, step, delay){
       let frame2;
       loop(delay){
  frame2++;
  yield;
       }
       temp+=rand(-1,1);
       let obj=Obj_Create(OBJ_SHOT);
       Obj_SetPosition(obj, GetX, GetY);
       Obj_SetAngle(obj, baseangle);
       Obj_SetSpeed(obj, 0);
       ObjShot_SetGraphic(obj, 49);
       ObjShot_SetDelay  (obj, 10);
       while(Obj_BeDeleted(obj)==false){
  if(frame2==70){
     Obj_SetAngle(obj, baseangle-60);
  }
  frame2++;
  yield;
       }
   }
}
(drawing.txt include bossSC and backgroundSC)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on August 07, 2009, 05:49:41 PM
It thinks "time" is a string. Just change let time; to let time=0; so it doesn't trip up on that. Danmakufu doesn't have seperate variable types for some reason so be sure to set a starting value for each one you declare.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 08, 2009, 02:07:02 AM
Code: [Select]
task TShot(let x, let y, let a){
let obj = Obj_Create(OBJ_SHOT);
let count = -2;
ObjShot_SetGraphic(obj, 1);
Obj_SetSpeed(obj, 8);
Obj_SetAngle(obj, a);
Obj_SetPosition(obj, x, y);
ObjShot_SetDamage(obj, 1);
ObjShot_SetPenetration(obj, 4);
if(BCollision(Obj_GetX(obj), Obj_GetY(obj)) == true && count <= 0 && !Obj_BeDeleted(Obj)){
ObjShot_SetGraphic(obj, 1d1);
yield;
ObjShot_SetGraphic(obj, 1d2);
yield;
ObjShot_SetGraphic(obj, 1d3);
yield;
}
}

Okay, what the HELL is wrong with my script? An error message keeps popping up at the if(BCollision...) line, and I don't know what the problem is. Also, what should I use for checking if a bullet is coinciding with an enemy x and y coordinates? Should I use the method outlined in Stuffman's Sakuya A tutorial to ascend through the enemy IDs and pick the ones that are coincident with the bullet coordinates, or should I do something else?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 08, 2009, 02:13:40 AM
It would help if we knew what BCollision did.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 08, 2009, 02:23:21 AM
ARGH, sorry, forgot to mention. Is just a function I defined that does what I described above, and returns true or false. Here:
Code: [Select]
function BCollision(let x, let y){
let enemy_target = -1;
let enum_x=0;
let enum_y=0;
let i = 0;
ascent(i in EnumEnemyBegin..EnumEnemyEnd) {
enemy_target=EnumEnemyGetID(i);
enum_x = GetEnemyInfo(enemy_target, ENEMY_X);
enum_y = GetEnemyInfo(enemy_target, ENEMY_Y);
if((enum_x <= x+5 && enum_x >= x-5) && (enum_y <= y+5 && enum_y >= y-5)){
return true;
}else{return false;}
}
    }
Title: Re: Danmakufu Q&A/Problem Thread
Post by: 8lue Wizard on August 08, 2009, 02:49:13 AM
Quote
let obj
...
!Obj_BeDeleted(Obj)

I see a misplaced capitalization.

...Also, "== true" is redundant, and my programmer's sense is screaming that the BeDeleted check should go first (not that it'd cause an error in this instance... probably :-\). 
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 08, 2009, 02:54:25 AM
What, it's case sensitive? wtf... okay, that's good to know. The thing is, I doubt there would be too many enemies spawned outside the clip boundaries... but just in case, yeah, it's probably good to take care of that.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 08, 2009, 02:58:37 AM
What, it's case sensitive? wtf... okay, that's good to know.

Everything is case sensitive in Danmakufu, it counts as a different letter to the computer. let a; and let A; are two compltely different variables, independant of eachother. Pain in the ass really, but it makes sense.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on August 08, 2009, 12:13:19 PM
Yep, surely it does :P

Code: [Select]
#TouhouDanmakufu
#Title[Sun Sign "Royal Flare"]
#Text[]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = -120;
    let bg = GetCurrentScriptDirectory~"images\Bossbgsunwood.jpg";
    let i;
    let j;
    let max=6;
    let max2=9;
    let max3=6;
    let random;
    let temp;
    let time=0;
    #include_function "..\drawing.txt"
    @Initialize {
       SetLife(1500);
       SetTimer(120);
       SetScore(1000000);
       SetDurableSpellCard();
       SetDamageRate(25,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "Sun Sign "\""Royal Flare"\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        if(frame>0){
           if(frame==30){
      time=30+GetCenterY-GetY+5;
      ascent(i in 0..8){
CreateShotA(0, GetX+cos(i*360/8)*10, GetY+sin(i*360/8)*10, 10);
SetShotDataA(0, 0, 1, 90, 0, 0, 1, 226);
SetShotDataA(0, GetCenterY-GetY-5, 1, 90, 0, -0.1, 0, 226);
FireShot(0);
      }
   }
   if(frame>time&&(frame-time)%90==0){
      temp=GetAngleToPlayer;
      ascent(i in 0..20){
ascent(j in 0..8){
            SunBullet(temp+j*360/8,10*i,3*i);
}
      }
   }
        }
        frame++;
yield;
    }

    @DrawLoop {
       bossSC;
    }
    @BackGround{
       backgroundSC;
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }
    task SunBullet(angle, distance, delay){
       let frame2=0;
       loop(delay){
  frame2++;
  yield;
       }
       temp+=rand(-1,1);
       let obj=Obj_Create(OBJ_SHOT);
       Obj_SetPosition(obj, GetCenterX+distance*cos(angle), GetCenterY+distance*sin(angle));
       Obj_SetAngle(obj, angle);
       Obj_SetSpeed(obj, 0);
       ObjShot_SetGraphic(obj, 49);
       ObjShot_SetDelay  (obj, 10);
       while(Obj_BeDeleted(obj)==false){
  if(frame2==70){
     Obj_SetSpeed(obj, 1);
  }
  frame2++;
  yield;
       }
   }
}
Why the obj bullets are not fired? (Thanks for your helps btw)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on August 08, 2009, 02:11:13 PM
       ObjShot_SetGraphic(obj, 49);

Maybe the shot id 49 isn't defined properly by the script you included. Maybe it is an invisible 1x1 pixel graphic by accident, or something.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on August 08, 2009, 02:52:40 PM
How does one make a laser shot for a player?

is there like a CreatePlayerLaser01 function (like the CreatePlayerShot01) or do I have to use functions or tasks, or is there a certain way to make CreatePlayerShot01 to fire lasers?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on August 08, 2009, 03:03:10 PM
I found out the problem! (The time is a floating point and floating point should not be run in the % operation)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 08, 2009, 04:06:06 PM
How does one make a laser shot for a player?

is there like a CreatePlayerLaser01 function (like the CreatePlayerShot01) or do I have to use functions or tasks, or is there a certain way to make CreatePlayerShot01 to fire lasers?
You need to use object lasers, I think. I'm not sure if this is possible, but I do know that OBJ_SHOT when defined for a player script counts as a player bullet, not an enemy bullet... so maybe the same principle applies to OBJ_LASERs? Give it a try... though I'm not sure how it would behave. If it doesn't work, then just create a laser graphic and set it as an object shot with infinite penetration (and low damage, of course)

Actually, my question remains: would using a comparison between GetEnemyX and Obj_GetX(obj) be an effective way of testing bullet collision?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 08, 2009, 08:29:08 PM
No. The bullet disappears too fast. I tried it before and it failed.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 08, 2009, 08:55:14 PM
The only effective way to "get bullet collision" is to make an object bullet with 1 penetration, then after it's while(!Obj_BeDelete(bullet)){} loop you have another animation or effect happen. That way, it's like something happening as the bullet hits an enemy (for example, the explosion effect on Sanae B's frog bullets).

task bullet{
  let obj = Obj_Create(OBJ_SHOT);
  //etc.

  while(!Obj_BeDeleted(obj)){
    //do stuff;
    yield;
  }

  let obj2 = Obj_Create(OBJ_SHOT);
  //etc.

  while(!Obj_BeDeleted(obj2)){
    //do more stuff;
    yield;
  }
}

Like that.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 08, 2009, 11:10:53 PM
Ick... oh well, an inelegant solution to a finicky program. =\ Thanks, Naut, Drake.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on August 10, 2009, 12:17:43 AM
Does anyone know how how I can make a spinning bullet? And control its speed (how fast it rotates)?
Also, how to set a random X/Y coordinate, in a given area (lets say, to make a bullet spawn anywhere from a  so-and-so X and so-and-so Y)?

Giving an example script would really help.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 10, 2009, 12:23:50 AM
Uh for spinning bullets you probably have to do something in #UserShotData to make it animated or something like that. I'm not sure exactly.

To spawn something in a certain area, use the rand(a,b) or rand_int(a,b) functions and put them in the x and y parts of the CreateShot function. Set a and b appropriately to get the area you want.

Example:
CreateShot01(GetX + rand(-100,100), GetY+rand(-100,100), other, stuff, goes ,here);
This spawns a bullet in a random square area around the boss that is 200 x 200 pixels in size (I think lol)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on August 10, 2009, 12:48:28 AM
Ah, thank you very much. Oh, and I found it. Apparently, it was angular_velocity at LoadUserShotData.

Thank you very much.  Oh, and one more thing. I was meaning to look this up but couldn't find it. What is the "i" parameter?  I see it being used here and there in some scripts, but I don't know what it does exactly. I tried experimenting, but couldn't figure it out.  I'll show you.
Code: [Select]
#TouhouDanmakufu
#Title[Bullets]
#Text[test script for bullets]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = 0;
    @Initialize {
        SetLife(1000);
        SetEnemyMarker(true);
    }

   @MainLoop {
      SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 24);

        if(frame==60){


            CreateShotA(1, GetX, GetY, 10);
SetShotDataA(1, 0, 5, 0, 2.2, 0, 5, RED03);
SetShotDataA(1, 60, 5, 132, 0, 0.1, 8, RED03);
ascent(i in 1..60){
    CreateShotA(2, 0, 0, 30);
    SetShotDataA_XY(2, 0, rand(-1, 1), rand(-1, -4), 0, 0.1, 0, 3, RED01);
    AddShot(i*2, 1, 2, 0);
    AddShot(i*2, 2, 1, 0);

frame = 0;
}


FireShot(1);


        }


        frame++;

    }

    @DrawLoop {       
    }

    @Finalize {
    }
}

You can see it in AddShot, the first parameter.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 10, 2009, 12:52:56 AM
The i is a variable and comes from the ascent(i in x..y){}

Basically every time ascent loops, it increments the i value while it's still between x and y and you can use that variable without having to increment it yourself.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: DgBarca on August 10, 2009, 01:04:08 AM
Code: [Select]
[size=1]#TouhouDanmakufu
#Title[Seconde Pyramid]
#Text[Blabla]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main{


   let imgExRumia="script\img\ExRumia.png";
   let frame = 0;
   let count = 0;
   let count2 = 0;
   let frame2 = 0;
   let angle = 0;
   let angle2 = 0;
   let angle3 = 0;
   let angle4 = 0;
   let a = 0;
   let b = 0;
   let u = 0;
   let angleAcc = 0;
   let radius = 0;
   #include_function "lib\SHOT_REPLACE\shot_replace.dnh";
   
   
   @Initialize{
      SetLife(8000);
      SetTimer(60);
      shotinit;
      SetInvincibility(30);
      LoadGraphic(imgExRumia);
      SetMovePosition02(GetCenterX, GetCenterY -100, 120);
 
            SetPlayerInvincibility(320);
   }
   
   @MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
   frame++;
   count++;
   count2++;
   frame2++;
   a=GetAngleToPlayer;



   
   if(count > 120 && count%20==0){
   loop(2){
CreateShot01(GetX+75*cos(angle),GetY-10*sin(angle), 2, angle+90, RED02, 20);
CreateShot01(GetX+75*cos(angle),GetY-10*sin(angle), 2, angle+180+90, RED02, 20);
CreateShot01(GetX+75*cos(angle),GetY-10*sin(angle), 2, angle2, BLUE02, 20);
CreateShot01(GetX+75*cos(angle),GetY-10*sin(angle), 2, angle2+180, BLUE02, 20);

CreateShot01(GetX-75*cos(angle),GetY-10*sin(angle), 2, -angle+90, RED02, 20);
CreateShot01(GetX-75*cos(angle),GetY-10*sin(angle), 2, -angle+180+90, RED02, 20);
CreateShot01(GetX-75*cos(angle),GetY-10*sin(angle), 2, -angle2, BLUE02, 20);
CreateShot01(GetX-75*cos(angle),GetY-10*sin(angle), 2, -angle2+180, BLUE02, 20);

CreateShot01(GetX-0*cos(angle),(GetY-75*sin(angle))+75, 2, -90+angle, RED02, 20);
CreateShot01(GetX-0*cos(angle),(GetY-75*sin(angle))+75, 2, 90+angle, RED02, 20);
CreateShot01(GetX-0*cos(angle),(GetY-75*sin(angle))+75, 2, 90+angle2, BLUE02, 20);
CreateShot01(GetX-0*cos(angle),(GetY-75*sin(angle))+75, 2, -90+angle2, BLUE02, 20);

angle += (45/(45/3));
angle2 += -(45/(45/3));
}

      }
     
      if(count == 120){
      loop(4){
      CreateShotA(1,GetX,GetY, 0);
SetShotDataA(1,0,0,90,0,0,0,PURPLE51);
SetShotDataA(1,80,1,angle3,0,0,0,PURPLE51);
SetShotDataA(1,120,0,angle3,0,0,0,PURPLE51);
SetShotKillTime(1,240);
loop(1){
CreateLaserC(2,0,0,12,40,BLUE21,60);
SetLaserDataC(2,0,3,GetAngleToPlayer,0,0,0);
SetShotKillTime(2,240);
AddShot(120,1,2,0);
angle4 += 360/1;
}
   FireShot(1);
angle3 += 360/4;
}
}
if(count == 480){
count = 119;
}

}

   @DrawLoop{
      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetTexture(imgExRumia);
      SetGraphicRect(64,1,127,64);
      DrawGraphic(GetX,GetY);
   }
     
   @Finalize
   {
      DeleteGraphic(imgExRumia);
   }
}[/size]
It is a newbish question but how I get the 4 laser to go on the Player direction ?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 10, 2009, 01:18:33 AM
GetAngleToPlayer won't work in this case, because it gets that value at the time when the shot is fired, from the boss to the player, instead of when the SetLaserData "activates", from anywhere to the player.

Try this:
Code: [Select]
            CreateLaserC(2,0,0,12,40,BLUE21,60);
            SetShotDirectionType(PLAYER);
            SetLaserDataC(2,0,3,0,0,0,0);
            SetShotDirectionType(ABSOLUTE);
            SetShotKillTime(2,240);
            AddShot(120,1,2,0);

Using SetShotDirectionType(PLAYER); will make any shot, fired from anywhere, aimed at the player when you use 0 as the angle.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on August 10, 2009, 03:41:26 AM
I have another question, and I've been trying very hard to get this right. But I just seem to never get it...
Suppose this is in the Mainloop.
Code: [Select]
@MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
   frame++;
   
   if(frame==120){
   
      loop(36){
         CreateShot01(GetX + 50, GetY + 50, 3, angle, BLUE12, 0);
         angle += 360/36;
      }
     
      angle = 0;
      frame = 100;
   }
What I'm trying to do is, get a random X and Y coordinate, so the bullets that shockwave out do it within 50 frames of the boss randomly.  The problem is, if I put in
Code: [Select]
CreateShot01(GetX + rand(-50, 50), GetY + rand(-50, 50), 3, angle, BLUE12, 0); The random value for the X and Y coordinates are different, and I don't even have a circle anymore. How can I make it so the random value set for X and Y is the same?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 10, 2009, 04:01:47 AM
What I'm trying to do is, get a random X and Y coordinate, so the bullets that shockwave out do it within 50 frames of the boss randomly.  The problem is, if I put in
Code: [Select]
CreateShot01(GetX + rand(-50, 50), GetY + rand(-50, 50), 3, angle, BLUE12, 0); The random value for the X and Y coordinates are different, and I don't even have a circle anymore. How can I make it so the random value set for X and Y is the same?
You can declare a set value (Like let random;), and inside of the main loop (Try to do it right before calling it) write random = rand(-50, 50); .
Then, when using your createshot01, you call it like this:
Code: [Select]
CreateShot01(GetX + random, GetY + random, 3, angle, BLUE12, 0);Thus, you're using the same number in both coordinates, and for the next shot, the value will be randomized again.
The full example would look like this:

let random =0; //To make sure that random will be considered like an integer and not a string
@MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
   frame++;
   if(frame==120){
    //if you call random = rand(-50, 50); here, all 36 shots will be spawned from the same point, and the next batch of shots will appear on another point inside of the "space" you want it to.
      loop(36){
 //if you call random = rand(-50, 50); here, every shot will be spawned from a different spot. It won't be a circle anymore, but now that I think it, it would look awesome.
         CreateShot01(GetX + 50, GetY + 50, 3, angle, BLUE12, 0);
         angle += 360/36;
      }
     
      angle = 0;
      frame = 100;
   }[/code]
And that's it, I think.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on August 10, 2009, 05:19:50 AM
But that leaves a problem, because if I do it like this...
Code: [Select]
   let random = 0;
@MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
   frame++;
   
   if(frame==120){
   
     random = rand(-50, 50);


      loop(36){
         CreateShot01(GetX + random, GetY + random, 3, angle, RED01, 0);
         CreateShot01(GetX + random, GetY + random, 3, angle, BLUE12, 0);


         angle += 360/36;
      }
     
      angle = 0;
      frame = 100;
   }

....and I want to shoot 2 different shots in that same pattern, instead of just 1 (but both spawning at different points) it's impossible, isn't it?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 10, 2009, 05:29:03 AM
   let random = 0;
@MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
   frame++;
   if(frame==120){
       loop(2){doit;}
       frame = 100;
       }
   }

   task doit{
     random = rand(-50, 50);
     loop(36){
         CreateShot01(GetX + random, GetY + random, 3, angle, RED01, 0);
         CreateShot01(GetX + random, GetY + random, 3, angle, BLUE12, 0);
         angle += 360/36;
     }
     angle = 0;
   }
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 10, 2009, 01:13:20 PM
   let random = 0;
@MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
   frame++;
   if(frame==120){
       loop(2){doit;}
       frame = 100;
       }
   }

   task doit{
     random = rand(-50, 50);
     loop(36){
         CreateShot01(GetX + random, GetY + random, 3, angle, RED01, 0);
         CreateShot01(GetX + random, GetY + random, 3, angle, BLUE12, 0);
         angle += 360/36;
     }
     angle = 0;
   }

If you use the same random variable for both the x and y, wouldn't it only make bullets in a diagonal line relative to the boss? Plus, just using rand(-50,50) will create bullets in a square area around the boss, not in a circle.

Code: [Select]
@MainLoop
     {
     SetCollisionA(GetX, GetY, 32);
     SetCollisionB(GetX, GetY, 16);
     frame++;
     if(frame==120)
         {
         doit(RED01);
         doit(BLUE01); //Does the function again with a different color.
         frame = 60;
         }
     }

function doit(color)
     {
     let radius = rand(0,100); //How far away the ring will be from the boss.
     let angle1 = rand(0,360); //The direction from the boss the bullets will be fired from.
     let angle2 = rand(0,360); //Makes the relative angle of the bullets random.
     loop(36)
         {
         CreateShot01(GetX + cos(angle1)*radius, GetY + sin(angle1)*radius, 2, angle2, color, 10);
         angle2 += 360/36;
         }
     }

A bit more confusing, but once you get how cos and sin work, they're really useful for creating bullets from points relative to the boss, rather than directly from it.

Additional note: If you declare a variable within a loop, task, function, etc., it will only exist inside of it.

VVV Below example pic is no longer correct, since I edited my post VVV
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 10, 2009, 09:33:42 PM
Updated my collision script, but the shots aren't progressing through their respective sprites on contact. Am I doing something wrong again? (I think the problem is in the 'return' statements, which is really annoying, since THWiki doesn't really give a very satisfactory explanation of it)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: DgBarca on August 10, 2009, 09:50:50 PM
I have tried and tried, but no way to reproduce Keine BG.
I suck at BG  :V ! (Any solution ?)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 10, 2009, 10:09:32 PM
Er... have you tried using the sprite rips? I mean, it's just a scrolling BG and a static BG, one over the other.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: DgBarca on August 10, 2009, 10:10:37 PM
Spri...ho I just forgot them...sorry
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 10, 2009, 10:26:54 PM
... yeah. I'm assuming you have them, then?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: DgBarca on August 10, 2009, 10:32:18 PM
Yes...but they were in a completely lost folder.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on August 12, 2009, 05:42:34 PM
I got another one!

How do you change the... Um... This part:

(http://i32.photobucket.com/albums/d49/puremrz/thing.png)

And would you be able to change it midgame?

Oh, and changing the sfx that are built in Danmakufu, how to? (They're just too damn loud. I sometimes have my sound up, and the sound of a starting spellcard nearly throws me out of my chair then...)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 12, 2009, 06:12:11 PM
I got another one!

How do you change the... Um... This part:

(http://i32.photobucket.com/albums/d49/puremrz/thing.png)

And would you be able to change it midgame?

Oh, and changing the sfx that are built in Danmakufu, how to? (They're just too damn loud. I sometimes have my sound up, and the sound of a starting spellcard nearly throws me out of my chair then...)
To change the preset ingame images, you put image files in a folder caled 'img' in the root folder of danmakufu. The images have to hve a specific name to change a specific thing. In particular, make an image called STG_Frame.png and put it in that folder to change the frame. To change the sfx I believe the same thin applies but for a folder called sfx.

As for the names of each thing, I think it was posted a while back in a topic of a collection of info from the old forums or something.

Finally yes it is possible to change the frame ingame. How you do it I have no clue but Shinki does it at the very end of Phantom Romance.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on August 12, 2009, 06:33:42 PM
To change the preset ingame images, you put image files in a folder caled 'img' in the root folder of danmakufu. The images have to hve a specific name to change a specific thing. In particular, make an image called STG_Frame.png and put it in that folder to change the frame. To change the sfx I believe the same thin applies but for a folder called sfx.

As for the names of each thing, I think it was posted a while back in a topic of a collection of info from the old forums or something.

Finally yes it is possible to change the frame ingame. How you do it I have no clue but Shinki does it at the very end of Phantom Romance.

Ah, the background thing helped :D
It's kinda flashing a bit, but that's probably because that background is still transparent.

Do you have any idea where that topic could be? That info would make a nice addition to the wiki's. (And me)

Edit: Ah, http://www.shrinemaiden.org/forum/index.php?topic=166.msg2626#msg2626 nevermind that part of my post then.

Though, by looking in Concealed the Conclusion, it seems that you can have more than 1 background by calling them STG_Frame.png and STG_Frame_2.png, but that needs more trying out. After all, I have no clue how to call those into your game!
Maybe it has to do with index.dnh...



Oh, but who/where is Shinki? Gotta ask how to change that background!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 12, 2009, 10:22:46 PM
To change the preset ingame images, you put image files in a folder caled 'img' in the root folder of danmakufu. The images have to hve a specific name to change a specific thing. In particular, make an image called STG_Frame.png and put it in that folder to change the frame. To change the sfx I believe the same thin applies but for a folder called sfx.

As for the names of each thing, I think it was posted a while back in a topic of a collection of info from the old forums or something.

Finally yes it is possible to change the frame ingame. How you do it I have no clue but Shinki does it at the very end of Phantom Romance.

Ah, the background thing helped :D
It's kinda flashing a bit, but that's probably because that background is still transparent.

Do you have any idea where that topic could be? That info would make a nice addition to the wiki's. (And me)

Edit: Ah, http://www.shrinemaiden.org/forum/index.php?topic=166.msg2626#msg2626 nevermind that part of my post then.

Though, by looking in Concealed the Conclusion, it seems that you can have more than 1 background by calling them STG_Frame.png and STG_Frame_2.png, but that needs more trying out. After all, I have no clue how to call those into your game!
Maybe it has to do with index.dnh...



Oh, but who/where is Shinki? Gotta ask how to change that background!
Uh... Shinki as in http://touhou.wikia.com/wiki/Shinki

Isn't it sad PC98?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on August 13, 2009, 06:34:28 AM
Uh... Shinki as in http://touhou.wikia.com/wiki/Shinki

Isn't it sad PC98?

Ohhh, :P
I thought you meant Shinki "a fellow Danmakufu user"
But since the Touhou games are programmed by ZUN, they work differently than Danmakufu, so I guess it's not possible.

However, I once messed around with mist and it affected the outer frame as well, so could there perhaps be a way to draw images over the layer of that border?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 13, 2009, 05:57:45 PM
I have two questions, one deals with bullet graphics and the other with return statements, since I still can't seem to get the bullets to progress through their deletion frames on contact with the enemy (or even near the enemy, for that matter).
First off, bullet graphics. How exactly does Danmakufu determine the transparency of a given pixel? I tried using sprite rips from PoFV for my Yuka PC's bullets, but they ended up looking all blotchy and awful. I'm assuming this is because Danmakufu normalized all transparencies to 100% on loading the .png, so if there is a way for me to get a proper transparency going here, that would be marvelous.
As for the actual deletion frames themselves:
Code: [Select]
function TShot(let x, let y, let a){
let i;
let j = 0;
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, GetPlayerX, GetPlayerY);
Obj_SetAlpha(obj, 128);
ObjShot_SetGraphic(obj, 3);
Obj_SetSpeed(obj, 3);
Obj_SetAngle(obj, a);
ObjShot_SetDamage(obj, 2);
ObjShot_SetPenetration(obj, 6);
while(((Obj_GetX(obj)-GetEnemyX)^2 + (Obj_GetY(obj)-GetEnemyY)^2)^0.5 < 64){
//while(!Obj_BeDeleted(obj)){
loop(3){yield;}
ObjShot_SetGraphic(obj, 3);
loop(3){yield;}
ObjShot_SetGraphic(obj, 4);
loop(3){yield;}
ObjShot_SetGraphic(obj, 5);
loop(5){yield;}
break;
//}
}
}
function BCollision(let x, let y){
let ex = GetEnemyX;
let ey = GetEnemyY;
let r;
if(IsBossExisting){
r = 32;
} else {r = 16;} //Really clumsy, I know, but there is no diagnostic that detects if an enemy is a boss based on enemy ID, so I made an assumption.
if(((x - ex)^2+(y-ey)^2)^0.5 <= r){
return 1;
} else {return 0;}
}
As you might be able to infer, I'm trying to have Yuka's shots progress through a short animation before they die on contact with an enemy. This code has basically been bastardized to all hell as I've tried numerous things with it (BCollision isn't even called anymore), and so I ask once again if there are any ideas. This really should work, but I can't get it to do what I want at all.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: P♂ zeal on August 13, 2009, 11:55:20 PM
how exactly would one go about using Collision_obj_obj correctly? The touhou wiki is very vague on it's use, and only momentarily refers to it without having any information.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on August 14, 2009, 01:30:38 AM
It must be called in the same set of brackets that houses two object bullets, normally within a task. So... here, let me illustrate.
Code: [Select]
task T{
let obj1 = Create_Obj(OBJ_SHOT);
let obj2 = Create_Obj(OBJ_SHOT);
//Insert your various starting dataz for each object shot
Obj_SetCollisionToObject(obj1, true);
Obj_SetCollisionToObject(obj2, true);
while(Collision_Obj_Obj(obj1, obj2){
  //Insert fun things
}

Make sense? You need to tell DMF to look for collisions between the two objects with Obj_SetCollisionToObject on each, then if they have collided, do stuff to them. I'm not sure if you have to call it on one or both, I'm assuming on only one but I went with both here because DMF likes to be finicky.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on August 14, 2009, 01:43:28 PM
-Is it possible to draw stuff over the borderlayer of the screen?

-And how do you load images for more than 1 file in the background? When I try to do that, only the last loaded image shows up.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on August 14, 2009, 04:00:10 PM
Ffff I did it again.

Anyway:
Quote
-Is it possible to draw stuff over the borderlayer of the screen?
It's possible but we don't know how. At the very least, it's possible to change the frame mid-script since it was done in Phantasm Romance.

Quote
-And how do you load images for more than 1 file in the background? When I try to do that, only the last loaded image shows up.
You're probably doing something wrong, either the first few images have the incorrect paths specified or you're using the same variable for all of them or something like that.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 14, 2009, 06:07:49 PM
You should read the drawing order from Nuclear Cheese on wiki. It explains how to load things in order to make them all appear proper. Drawing order (like images/characters etc) is a pain and requires carefully planning (just look how big my @DrawLoop is in my afro boss. (perhaps bit newbish programmed but yea)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on August 14, 2009, 08:13:23 PM
Fixed it now, the drawing order wasn't right in the end.

I looked through Phantasm Romance, but it had the frame I made myself while playing, so I couldn't figure out exactly when it was supposed to change. Hmmm!

*Copying all of his Danmakufu files to prepare for starting his own full game* Argh, takes so long ;_;
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 16, 2009, 06:13:16 PM
Hello! How do fire the bullets at random, is it in the Direction of fire you put rand(0, 360)? and will that fire anywhere between 0 degrees and 360 degrees?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on August 16, 2009, 06:18:39 PM
Yes, exactly.

Also, welcome.  :)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 16, 2009, 07:39:10 PM
nyaaaa~! Hi again! Ive read throught the turorials but i cant seem to firue out how to get the bullets to curve...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 16, 2009, 07:46:06 PM
Making the bullets travel in a curve requires you to modify the angle acceleration.

You can either use CreateShotA or Objectbullets (again here you need to read the wiki as it is all explained which parameter does what)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on August 17, 2009, 06:00:37 PM
Yet another question asked by the newbie at Danmakufu:
How does the rate system work, and can it be changed in some way?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 17, 2009, 06:05:13 PM
Do you mean the damage rate?

If yes: read if no: stop reading =P

It is also like written in the wiki (do people even read the wiki?) You can use SetDamageRate and SetDamageRateEx. The first having only two paremeters (multiplier on shots, bomb multiplier) second have four where the first two are similar and 3rd and 4th are multiplies for slaves/familiars.

Edit:
Wrong explained, DamageRate 100 = full 100% damage. Lower means less damage, higher means multiplied.
Default is 100,100 for SetDamageRate and 100,100,0,0 for SetDamageRateEx
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 17, 2009, 06:18:50 PM
Yet another question asked by the newbie at Danmakufu:
How does the rate system work, and can it be changed in some way?
It increases whenever you do almost anything (shoot/cap spell/etc) and goes down if you die and maybe if you bomb (not sure). The only thing it affects as far as I know is the spellcard bonus.

I'm pretty sure there's a function that turns it off.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on August 17, 2009, 06:32:53 PM
Yet another question asked by the newbie at Danmakufu:
How does the rate system work, and can it be changed in some way?
It increases whenever you do almost anything (shoot/cap spell/etc) and goes down if you die and maybe if you bomb (not sure). The only thing it affects as far as I know is the spellcard bonus.

I'm pretty sure there's a function that turns it off.
Ok, There's a SetRateScoreSystemEnable; function, and that's all I knowwhere I can do stuff with it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 17, 2009, 10:41:34 PM
Ok ive figured out how to fire randomly but can you fire randomly in a specified direction?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 17, 2009, 11:15:27 PM
The angles that danmakufu uses start at 0 being the right side, and goes clockwise. So a randomish downwards shot would be rand(70,110) or 90+rand(-20,20). Feel free to use variables inside of the rand function, like rand(-shotrange,shotrange). This would increase the possible range as the variable shotrange increases.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 17, 2009, 11:26:20 PM
How do you make the sprites for the bosses? (and thanks Onthenet)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 18, 2009, 12:48:49 AM
Here's how I usually do it:

Before @Initialize:
Code: [Select]
let Sprite = "scriptdirectory\sprite.png";
In @Initialize:
Code: [Select]
LoadGraphic(Sprite);
In @DrawLoop:
Code: [Select]
SetAlpha(255);
SetGraphicScale(1,1);
SetGraphicAngle(0,0,0);
SetTexture(Sprite);
SetGraphicRect(0,0,64,64); //Change this to fit your sprite.
DrawGraphic(GetX, GetY);

Now for my question...

Anyone have problems playing specific MP3s in Danmakufu as background music? Half the MP3s I want to use just don't play for some reason, without bringing up an error or anything. Is there anything I can do to edit the MP3 and make it work (without making it into a huge WAV file)?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 18, 2009, 12:58:50 AM
Anyone have problems playing specific MP3s in Danmakufu as background music? Half the MP3s I want to use just don't play for some reason, without bringing up an error or anything. Is there anything I can do to edit the MP3 and make it work (without making it into a huge WAV file)?
I've heard about this a lot of times. Seems like in some computers (Or all the time, not sure) Danmakufu likes to fuck with your music, specially MP3 and OGG files. So yeah, the only way to get sure music is through WAV.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 18, 2009, 01:06:41 AM
Does the problem stem from something in the actual MP3 though? I'm just wondering why it only happens to certain songs...

I guess I'll have to look for either another version of the MP3 or choose another song altogether. The WAV (after converting with Audacity) is 30 MB, so that's a definite no.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on August 18, 2009, 04:49:32 AM
Here's one I've been working on for quite a long time now:
How would the time stopping in Yukari's final spell in Touhou Youyoumu be replicated? TimeStop only stops the bullets, player, and/or background, so yeah.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 18, 2009, 05:01:09 AM
Time stopping... in Danmaku Bounded Field? :V
I think you're mistaking this with other spellcard.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on August 18, 2009, 05:57:32 AM
Time stopping... in Danmaku Bounded Field? :V
I think you're mistaking this with other spellcard.
No, I'm pretty sure it's Y's A: DBF. Like when the player character gets killed, the magic thing around Yukari stops spinning and the timer stops counting down, until the player loses all of her invincibility.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 18, 2009, 12:15:29 PM
Time stopping... in Danmaku Bounded Field? :V
I think you're mistaking this with other spellcard.
No, I'm pretty sure it's Y's A: DBF. Like when the player character gets killed, the magic thing around Yukari stops spinning and the timer stops counting down, until the player loses all of her invincibility.
Oh, you mean THAT kind of timestop. I'm pretty sure that to do that effect, you can call a modification on the familiar's movement when the player dies. And since it's a familiar, you can use the familiar script to make it stop shooting as well while the player's invincible.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on August 19, 2009, 12:04:22 AM
OK, I've used Get Time of Player Invincibility, but I also want the timer to stop counting down, so yeah.  :yukkuri:
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 19, 2009, 01:59:58 AM
What exactly does SetGraphicRect do and what are teh prerimiters(spelling?)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on August 19, 2009, 02:11:59 AM
What exactly does SetGraphicRect do and what are teh prerimiters(spelling?)

This command, along with many other drawing-related commands, is covered in my Drawing Tutorial (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Nuclear_Cheese%27s_Drawing_Tutorial).
Basically, it tells Danmakufu what part of the image you want to draw on the screen.

Its parameters are, in order, the left, top, right, and bottom coordinates of the area of the image you want to use.  For example, if you wanted to use the rectangle from (5, 8) to (19, 27), you would use the command:

SetGraphicRect(5, 8, 19, 27);



If you haven't seen it, by the way, there's a stickied thread in this subforum with links to several tutorials we've written up.


Hope this helps!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on August 20, 2009, 03:01:58 PM
I am trying to make a 3d background in danmakufu like that of stage 5 in EoSD, with fog. but whenever i try to use fog, everything becomes ugly and bad. i am using the right distances. i have tried every distance and every color, even when i call SetFog, but it still looks ugly. what should i do?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on August 20, 2009, 05:31:23 PM
Nothing. Fog function sucks. Stop using it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on August 20, 2009, 05:40:15 PM
I have to do a ridiculous amount of fucking around with fog to make it work in every script I use it. It's particularly bad with a scrolling camera because it won't stay in place and it makes the stage loop incorrectly. In fact, in Stage 5 of PoSR, to make it work right I made the whole stage scroll instead of the camera.

There are other tricks you can use to get fog-like effects, like dimming/lightening polygons the further they are from the camera, or just using a series of low-alpha polygons as a filter like old PoSR used to have.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 21, 2009, 12:06:56 AM
Does anyone know where i can find sprite rips from the Touhou Games?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 21, 2009, 12:32:30 AM
Does anyone know where i can find sprite rips from the Touhou Games?
Drake: http://www.shrinemaiden.org/forum/index.php?topic=197.0
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 21, 2009, 03:01:50 AM
Thank you Suikama and Drake. i feel bad asking so many questions but, how would someone get the sprites to move in place? like in the game...My attampts have failed T_T
Title: Re: Danmakufu Q&A/Problem Thread
Post by: ?q on August 21, 2009, 05:54:11 PM
Okay, I'm being more retarded than usual.

I'm trying to do a pattern where the bullets spiral inward, and then back out.  It's... not working, to say the least.

If someone could show me how to do an inward spiral I would be most appreciative.  I could probably pick it up from there.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 21, 2009, 05:59:11 PM
CreateShot01(GetX+cos(angle)*radius,GetY+sin(angle)*radius,1,angle+180,RED01,30);

You'll likely need to change the SetShotAutoDeleteClip settings to make it take up the whole screen without some bullets disappearing.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 22, 2009, 12:38:19 AM
Thank you Suikama and Drake. i feel bad asking so many questions but, how would someone get the sprites to move in place? like in the game...My attampts have failed T_T
You mean like animate them? You pretty much gotta do that manually with if statements and stuff.

The basic gist of it is if the boss isn't moving, then you cycle through the stading frames of the character, which would be something like if getbossvelocity(not a real function, I forgot the real name for it >_>) is 0 then every like 5 or so frames change the sprite to the next one. And if the boss is moving left or right, which would be something like if getbossvelocity(lol fake function) is positive or negative, then change the sprite to a left/right moving one.

Uh... I have little experience with this so I hope someone else who has actually done this before can help clear it up more.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: ?q on August 22, 2009, 12:44:02 AM
CreateShot01(GetX+cos(angle)*radius,GetY+sin(angle)*radius,1,angle+180,RED01,30);

You'll likely need to change the SetShotAutoDeleteClip settings to make it take up the whole screen without some bullets disappearing.
I'm... not sure we're talking about the same thing.

What if I want to make a bullet go in a circle?  Would I have to use an Object bullet?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 22, 2009, 12:50:01 AM
Oh, you meant make each individual bullet go in a spiral towards a point? I would make an object bullet, and set its position to (centerx+cos(angle)*radius,centery+sin(angle)*radius) each frame, while reducing the radius and increasing/decreasing the angle. If you're using a non-round bullet, just set its angle to angle+90 or angle-90 each frame so it looks like it's facing the right direction. I could make an example if this explanation isn't enough, it's nothing TOO complicated :P
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 22, 2009, 12:50:51 AM
CreateShot01(GetX+cos(angle)*radius,GetY+sin(angle)*radius,1,angle+180,RED01,30);

You'll likely need to change the SetShotAutoDeleteClip settings to make it take up the whole screen without some bullets disappearing.
I'm... not sure we're talking about the same thing.

What if I want to make a bullet go in a circle?  Would I have to use an Object bullet?
You'd need to either have a good understanding of trigonometry or read the intermediate bullet tutorial.

Or you could make an object bullet and try to get it to curve in a circle but the results probably won't be pretty.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 22, 2009, 01:11:02 PM
Thank you Suikama and Drake. i feel bad asking so many questions but, how would someone get the sprites to move in place? like in the game...My attampts have failed T_T
You mean like animate them? You pretty much gotta do that manually with if statements and stuff.

The basic gist of it is if the boss isn't moving, then you cycle through the stading frames of the character, which would be something like if getbossvelocity(not a real function, I forgot the real name for it >_>) is 0 then every like 5 or so frames change the sprite to the next one. And if the boss is moving left or right, which would be something like if getbossvelocity(lol fake function) is positive or negative, then change the sprite to a left/right moving one.

Uh... I have little experience with this so I hope someone else who has actually done this before can help clear it up more.
I found this script online that makes Chen spin and animate in place, but im haveing EXTREAM problems figuring things out....

#include_function "lib\SHOT_REPLACE\shot_replace.dnh"

let csd = GetCurrentScriptDirectory;
let ChenSprite = csd~"img\ChenSprite.png";
let ChenCutin = csd~"img\ChenCutin.png";
let SpellBG = csd~"img\SpellBG.png";
let timeo1 = csd~"se\timeout.wav";
let timeo2 = csd~"se\timeout02.wav";
let BellSE = csd~"se\bell.wav";
let ShotSE = csd~"se\shot.wav";
let SlaveSE = csd~"se\slave.wav";
let LaserSE = csd~"se\laser.wav";
let ChargeSE = csd~"se\charge.wav";
let spellcard = 0;
let bgalpha = 0;
let timerframe = 0;
let aniy = 0;
let status = 0;
let graphicangle = 0;

sub timer
{
if (timerframe == 0)
   {
   if (GetTimer > 4 && GetTimer <= 10)
      {PlaySE(timeo1);}
   if (GetTimer <= 4)
      {PlaySE(timeo2);}
   timerframe = -60;
   }
timerframe++;
}

sub animate
{
if (status == 0) //Chen Normal Pose
   {
   SetGraphicRect(0,floor(aniy)*128,128,floor(aniy)*128+128);

   if (aniy+0.1 <= 2)
      {aniy += 0.1;}
   else
      {aniy = 0;}
   }

if (status == 1) //Chen Spinning
   {

   if (GetAngle > 90 && GetAngle < 180)
      {SetGraphicRect(256,floor(aniy)*128,384,floor(aniy)*128+128); graphicangle -= 30;}
   else
      {SetGraphicRect(256,floor(aniy)*128+256,384,floor(aniy)*128+384); graphicangle += 30;}

   if (aniy+0.05 <= 0)
      {aniy += 0.05;}
   else
      {aniy = 1;}

   SetGraphicAngle(0,0,graphicangle);
   }
else
   {SetGraphicAngle(0,0,0);}
}

sub initialize
{
shotinit;
LoadGraphic(ChenSprite);
LoadGraphic(SpellBG);
LoadSE(timeo1);
LoadSE(timeo2);
LoadSE(BellSE);
LoadSE(ShotSE);
LoadSE(SlaveSE);
LoadSE(LaserSE);
LoadSE(ChargeSE);
}

sub mainloop
{
if (spellcard <= 1)
   {
   SetCollisionA(GetX,GetY,32);
   SetCollisionB(GetX,GetY,24);
   }
timer;
}

sub finalize
{
status = 0;
if (spellcard >= 1)
   {
   loop(15)
      {CreateItem(ITEM_SCORE,GetX+rand(-64,64),GetY+rand(-64,64));}
   }
DeleteGraphic(ChenSprite);
DeleteGraphic(SpellBG);
}

sub drawloop
{
if (spellcard >= 1)
   {
   SetGraphicAngle(0,0,0);
   SetAlpha(bgalpha);   
   SetTexture(SpellBG);
   SetGraphicRect(0,0,512,512);
   DrawGraphic(GetCenterX,GetCenterY);
   if (bgalpha < 255)
      {bgalpha += 7.5;}
   }

if (spellcard <= 1)
{SetAlpha(255);}
else
{SetAlpha(128);}
SetTexture(ChenSprite);
animate;
DrawGraphic(GetX,GetY);
DrawText("Chen Yakumo", 36, 39, 12, 225);
}

and sorry i dont know how to make that box thing you can put things in...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 22, 2009, 06:36:26 PM
You could have PM'd me if you didn't understand my Chen script :P

Basically, I just set the variable status to 1 if Chen should be spinning, and 0 if she is doing her idle animation. For the spinning, it just chooses a pose and set the graphic angle to graphicangle which changes each frame. If she's idle, it sets her pose based on aniy. I use floor(aniy) to make it into a non-decimal, so that you don't end up with half of one pose and half of another. Once it reaches the end, it goes back to the first pose.

All of these are in subs, which means you can use this code by including the function and putting mainloop;, drawloop;, etc. in the boss script.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 22, 2009, 07:54:41 PM
You could have PM'd me if you didn't understand my Chen script :P

Basically, I just set the variable status to 1 if Chen should be spinning, and 0 if she is doing her idle animation. For the spinning, it just chooses a pose and set the graphic angle to graphicangle which changes each frame. If she's idle, it sets her pose based on aniy. I use floor(aniy) to make it into a non-decimal, so that you don't end up with half of one pose and half of another. Once it reaches the end, it goes back to the first pose.

All of these are in subs, which means you can use this code by including the function and putting mainloop;, drawloop;, etc. in the boss script.
Thanks and im terribly sorry about that T_T.. but what would i copy to make my character animate in place?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 22, 2009, 08:00:38 PM
If your poses are arranged vertically, like in CtC:
Code: [Select]
SetGraphicRect(0,floor(aniy)*spriteheight,128,floor(aniy)*spriteheight+spriteheight);
if (aniy+0.1 <= framecount){aniy += 0.1;}
else{aniy = 0;}
Otherwise:
Code: [Select]
SetGraphicRect(floor(anix)*spritewidth,0,floor(anix)*spritewidth+spritewidth,128);
if (anix+0.1 <= framecount){anix += 0.1;}
else{anix = 0;}

Replace spriteheight/spritewidth with the dimensions of the sprite, and replace framecount with the number of possible poses. If you want a slower animation, change 0.1 to 0.05. Conversely, change it to 0.2 for a faster one (remember to change the part in the if statement as well, or else weird things happen).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Primula on August 22, 2009, 09:43:27 PM
Hmmm..I'm editing Blargel's Patchy dialogues, but it doesn't seem to work..



Code: [Select]
script_event Talk{
   let imgplayerdeh=GetCurrentScriptDirectory~"img\ReimuW4.png";
   let imgplayermad=GetCurrentScriptDirectory~"img\ReimuW5.png";
   @Initialize{
      LoadGraphic(imgplayerdeh);
      LoadGraphic(imgplayermad);
@MainLoop{
alternative( GetPlayerType() )
case( REIMU_A, REIMU_B )
SetStep( 1 );
TextOutB( 120, "\c[RED]Are you the one?" );
SetChar( LEFT, imgplayerdeh );
SetGraphicRect( LEFT, 1, 1, 192, 320 );
TextOutB( 120, "\c[BLUE]The one what?\nAnd where's your hair ribbon?" );
      MoveChar(LEFT,FRONT);
TextOutB( 120, "\c[RED]Maybe if I defeat you!" );
SetChar( LEFT, imgplayerdeh );
SetGraphicRect( LEFT, 1, 1, 192, 320 );
TextOutB( 120, "\c[BLUE]Are you listening?" );
SetStep( 2 );
End();
}
case( MARISA_A, MARISA_B ){
SetStep( 1 );
TextOutB( 120, "\c[RED]Are you the one?" );
TextOutB( 120, "\c[BLUE]The one what?\nAnd where's your hair ribbon?" );
TextOutB( 120, "\c[RED]Maybe if I defeat you!" );
TextOutB( 120, "\c[BLUE]Are you listening?" );
SetStep( 2 );
End();
}
   }
   @Finalize{
      DeleteGraphic(imgplayerdeh);
      DeleteGraphic(imgplayermad);
}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 22, 2009, 10:17:35 PM
What part doesn't work? Does it give an error or does it simply not appear? (too lazy to check :V)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Primula on August 22, 2009, 10:23:48 PM
An error D8
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 22, 2009, 11:57:26 PM
You forgot curly braces for your first case.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Primula on August 23, 2009, 12:01:23 AM
Errr..Where do I put that? -brick'd-
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 23, 2009, 12:03:15 AM
case( REIMU_A, REIMU_B )

Should have a "{" after it.

Funny thing is you did it with case( MARISA_A, MARISA_B ){
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Primula on August 23, 2009, 12:30:23 AM
Oh thanks   :-X
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 23, 2009, 01:16:21 PM
how exactly does if(timer==) works? if you wanted to fire a bullet would you put:
if(timer==90){
   then(frame%50==0){ 
         shotstuff and movements,
      }


?????
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on August 23, 2009, 02:19:57 PM
"timer" and "frame" and "count" are just generic variables people might call a variable used to keep track of time.

You have to declare it first, like "let timer=0;" at the top of your script_enemy_main, and then at the end of your @MainLoop you have a "timer++;" which will increase the timer by one every loop.

So, once you have that set up, you can say "if(timer==90){" to create a conditional that will happen once 90 loops have processed in your script. This is how you control the timing of your attacks. At the end of @MainLoop you'll usually have something like "if(timer>180){timer=0;}" where the script is done with all its attacks after 180 loops, so it resets back to 0 and starts counting again to re-use the code.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on August 23, 2009, 02:21:09 PM
You don't have to type a "then" statement. All you have to do is to type

if( conditions ){
    actions
}

I don't know what you wanted to do with the "(frame%50==0)". If you wanted to have more than one neccessary condition, you could just type

if(timer==90&&timer%50==0){

}

or

if(timer==90){ if(timer%50==0){      } }

Although the following actions would never happen, just because the number 90 is not devidable by 50 without creating a remainder.


Edit: Dang, lunardial'd by Stuffman again!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on August 23, 2009, 02:31:15 PM
Quote
Edit: Dang, lunardial'd by Stuffman again!
http://www.youtube.com/watch?v=9a_dELVs-U8 (http://www.youtube.com/watch?v=9a_dELVs-U8)

Yeah you do bring up a point I forgot to mention. If you don't know, the "%" operator, called modulus, divides the number you give it and checks the remainder. So if you have "if(timer%50==0){" that will go off every time the timer is evenly divisible by 50, so it'll work on frame 0,50,100, etc without you resetting the timer.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 23, 2009, 02:38:16 PM
huh, that makes sense to an extent, but will the statement work to; when the timer reaches 90 seconds, to be able to fire at a rate of %50, because thats the only way i seem to be able to fire lasers :yukkuri:
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on August 23, 2009, 02:55:11 PM
Oh I see. You want "if(timer>=90 && timer%50==0){". If it's "timer==90" then it will only work when it's exactly 90. You want it to work at 90 and from then on.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 23, 2009, 11:23:25 PM
Quote
Edit: Dang, lunardial'd by Stuffman again!
http://www.youtube.com/watch?v=9a_dELVs-U8 (http://www.youtube.com/watch?v=9a_dELVs-U8)

Yeah you do bring up a point I forgot to mention. If you don't know, the "%" operator, called modulus, divides the number you give it and checks the remainder. So if you have "if(timer%50==0){" that will go off every time the timer is evenly divisible by 50, so it'll work on frame 0,50,100, etc without you resetting the timer.

I was wondering, if i were to just use frame==50, would i still be able to fire lasers? an woulthe modulus work at any number?

as for your video lol
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 23, 2009, 11:41:19 PM
I was wondering, if i were to just use frame==50, would i still be able to fire lasers? an woulthe modulus work at any number?
% would work in any case. As for ==, you'd need to reset frame to 0 after firing, or it would only fire once.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 23, 2009, 11:45:36 PM
ok now i got a Question on Boss Movement,

i found this code on a different fourm:

if(frame==120){
 SetMovePositionRandom01(rand(10, 50), rand(10, 50), 2, 100, 40, 348, 150);
 frame = 60;
}

but its not working, my cara just stays in one place, know whats wrong?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 23, 2009, 11:47:32 PM
I did not respond via PM fast enough, evidently. Curses.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 24, 2009, 01:32:40 AM
 :toot: excuse me for my ⑨ moment, where does SetShotKillTime go?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: P♂ zeal on August 24, 2009, 01:39:55 AM
:toot: excuse me for my ⑨ moment, where does SetShotKillTime go?
anytime between the CreateShot and FireShot of the bullet you want to be killed
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 24, 2009, 01:52:42 AM
:toot: excuse me for my ⑨ moment, where does SetShotKillTime go?
anytime between the CreateShot and FireShot of the bullet you want to be killed

what if there is no FireShot?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 24, 2009, 01:59:19 AM
Then your bullet will not shoot.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 24, 2009, 02:04:49 AM
Then your bullet will not shoot.
but its just a regular CreateShot01...

mokou mokou moko moko moko mokou ka~!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on August 24, 2009, 02:11:14 AM
SetShotKillTime will only work with CreateShotA bullets (and must be called before the bullet is fired using FireShot). So if you want to create a bullet that will delete itself after a certain amount of time, you would have to make a CreateShotA or an object shot.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 24, 2009, 02:27:04 AM
im having a 9 night, im sorry but you will have to remind me how to make a CreateShotA....
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on August 24, 2009, 12:59:14 PM
Ok. Yum, tasty copypasta:


CreateShotA
This is much more complicated than any of the previous bullet creation functions. This one actually needs to be coupled with two to five other functions in order for it to work. The related functions are SetShotDataA, SetShotDataA_XY, SetShotKillTime,  FireShot, and AddShot. First I'm going to explain what each of these functions do and then show examples on how they work in conjunction to control a bullet.

CreateShotA initializes one of these types of bullets and makes you give the bullet a number identity for you to refer to it later in the other functions. It also asks for the starting position and delay time for the bullet. For example, CreateShotA(1, GetX, GetY, 10); would create a bullet with an ID number of 1, starting at point (GetX, GetY), with a delay of 10.

SetShotDataA gives detailed instructions to the bullet on how to behave. Here, after identifying which shot you want to control via the ID number, you can control speed, angle, angular velocity, acceleration, max/min speed, and graphic. Angular velocity is a new parameter unique to CreateShotA bullets that changes the angle of the bullet every frame by the value indicated. The cool thing about these shots is that SetShotDataA also has one more parameter that determines the time after shooting that the settings for speed, angle, angular velocity, etc. actually affect the bullet. This means that if you call this function once to set the behavior at frame 0, you can call it again to set the behavior at frame 60, or 83, or any other frame after 0. There is no limit to how many times SetShotDataA can be called for one bullet either, which gives you incredible control over the bullet. For now, as a simple example, SetShotDataA(1, 0, 5, GetAngleToPlayer, 0.1, -0.08, 2, RED01); would tell the bullet with the ID number 1 to, at the time 0 frames after being shot (immediately), to go at a speed of 5 pixels per frame, straight at the player initially but turning 0.1 degrees every frame, decelerating at 0.08 pixels per frame per frame until it reaches a speed of 2 pixels per frame, with the bullet graphic of a small red bullet. If you would like to see an example with multiple SetShotDataA functions, then scroll down a bit.

SetShotDataA_XY works the same way as normal SetShotDataA except that instead of controlling angle directly, you control it with x- and y-velocities and accelerations, much like CreateShot12. For example, SetShotDataA_XY(1, 30, 1, -2.5, 0, 0.1, 1, 5, RED01); tells the bullet with ID 1 to, at 30 frames after being shot, move with a horizontal velocity of 1 to the right and with a vertical velocity of 2.5 upwards, with no horizontal acceleration and a vertical acceleration downward with a max speed of 5 pixels per frame, and with a bullet graphic of a small red bullet.

SetShotKillTime tells the bullet when to delete itself. If it isn't called, the bullet will delete itself after moving out of the playing field like a normal bullet. If it doesn't have this function called AND doesn't move off the playing field, it will never be deleted. This function is easy to use, as it only has two parameters: bullet ID and time. For example, SetShotKillTime(1, 120); tells the bullet with ID of 1 to get deleted after 120 frames.

FireShot tells the bullet to actually be fired after all the all the settings are configured. Yes, that means that you define the behavior of the bullet before it actually ever enters the playing field so all SetShotDataA functions and the SetShotKillTime function if desired must be called before FireShot is called. As an example, FireShot(1); fires the bullet with ID of 1 and all functions referring to that bullet will no longer work. In fact, now that the bullet has been fired, the ID of 1 is freed up and CreateShotA(1, GetX, GetY, 10); can be called again without raising an error.

AddShot is similar to FireShot in that the bullet it refers to must be configured before it is added and the ID is freed up after it is added. The difference is that AddShot is used to fire a shot from another CreateShotA. The shot must be added to the target bullet before that bullet is fired as well, which makes this feature somewhat confusing to some people. One way to think of this is that you're building a bullet rather than controlling it frame by frame. Anyway, for the sake of this example, pretend I had created a bullet with an ID of 2 and configured it already. AddShot(60, 1, 2, 0); would cause the bullet with ID of 1 to fire the bullet with ID of 2 from its current position 60 frames after bullet ID 1 had been fired. Note that the extra parameter is completely useless at the moment and only has use when the firing shot is actually a laser.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on August 26, 2009, 04:55:37 AM
This has been on my mind for a while now, and I have been trying to re-create it. Bah, curse my obsession with Mokou :V

Anyway, is there a way to recreate the 'pulsing' effect on Mokou's spellcards?
(http://i694.photobucket.com/albums/vv301/Mokou/th013.jpg)

I've been trying to get it down but failed horribly at every attempt.
All I know is that there are two layers of the Phoenix. One is alpha rendering and the other is ADD. From the looks of it, it just sets, and then expands/fades, and repeats, while the Alpha rendered one just stays put.
If it gets done right, I think it would look really cool danmakufu, especially with an awesome spellcard designed for Mokou.

Also, one more thing. The magic circle that sets and spins around the boss, and shrinks in correspondence to the timer... I can't seem to find the right function(s) needed to set my own. I have the new one drawn out and ready to go, but I don't know how to make it take effect. Any help?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on August 26, 2009, 10:44:40 AM
Question... How do you set a spell card as a survival spell card?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 26, 2009, 11:08:04 AM
IIRC you just have to call SetDurable; for the bonus part, and put the hitbox somewhere outside of the game box. (Or do not declare a hitbox size at all, but this may fail.)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on August 26, 2009, 12:56:47 PM
IIRC you just have to call SetDurable; for the bonus part, and put the hitbox somewhere outside of the game box. (Or do not declare a hitbox size at all, but this may fail.)

Thanks... that worked... and by the way, declaring no hitbox size does work.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 27, 2009, 02:05:29 AM
Ok i actually have two questions, one: Is there a way to recreate the lasers  in Satori's uhhh.... Terrible Souviner....haha easy spell.....
And two: is there a way to freeze the bullets on screen like in Perfect Freeze?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 27, 2009, 02:10:57 AM
Ok i actually have two questions, one: Is there a way to recreate the lasers  in Satori's uhhh.... Terrible Souviner....haha easy spell.....
Just make the base move and spin accordingly while it's on the delay frames, unil it reaches the player's position.
And two: is there a way to freeze the bullets on screen like in Perfect Freeze?
Just use SetShotDataA to turn the bullet's speed to 0 and to change their graphic, if that's what you need.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 27, 2009, 02:19:27 AM
Ok i actually have two questions, one: Is there a way to recreate the lasers  in Satori's uhhh.... Terrible Souviner....haha easy spell.....
Just make the base move and spin accordingly while it's on the delay frames, unil it reaches the player's position.

the ones that trap you? not the one that homes on you?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 27, 2009, 02:22:11 AM
Ok i actually have two questions, one: Is there a way to recreate the lasers  in Satori's uhhh.... Terrible Souviner....haha easy spell.....
Just make the base move and spin accordingly while it's on the delay frames, unil it reaches the player's position.

the ones that trap you? not the one that homes on you?
No, that's not what I meant.
The homing ones stop when they reach your position, and then they track you.
The other ones just keep spinning until the delay frames end and stop while shooting.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 27, 2009, 02:24:43 AM
Ok i actually have two questions, one: Is there a way to recreate the lasers  in Satori's uhhh.... Terrible Souviner....haha easy spell.....
Just make the base move and spin accordingly while it's on the delay frames, unil it reaches the player's position.

the ones that trap you? not the one that homes on you?
No, that's not what I meant.
The homing ones stop when they reach your position, and then they track you.
The other ones just keep spinning until the delay frames end and stop while shooting.

Is that a C laser or what? and what if the boss is moving?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 27, 2009, 02:28:28 AM
No, that's not what I meant.
The homing ones stop when they reach your position, and then they track you.
The other ones just keep spinning until the delay frames end and stop while shooting.

Is that a C laser or what? and what if the boss is moving?
No, no. The C lasers are the curvy ones. You can do easily this with A or B lasers. About the movement, well, it wouldn't be an exact copy, but you could use the position of the boss o calculate he movement of the Laser's base.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 27, 2009, 02:32:15 AM
No, that's not what I meant.
The homing ones stop when they reach your position, and then they track you.
The other ones just keep spinning until the delay frames end and stop while shooting.

Is that a C laser or what? and what if the boss is moving?
No, no. The C lasers are the curvy ones. You can do easily this with A or B lasers. About the movement, well, it wouldn't be an exact copy, but you could use the position of the boss o calculate he movement of the Laser's base.

I tried those but they pretty much left a blob and shot out and disappeared :\ I tried the Installed ones and they just were a blur...

oh, and thanks for your help :)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 28, 2009, 04:08:27 AM
Is it possible to draw a black object?

Danmakufu keeps cuting out all the black when I try to draw a black object...

Edit: Alright found out how to do it. Just gotta change it very slightly from pure black.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on August 28, 2009, 04:27:53 AM
Is it possible to draw a black object?

Danmakufu keeps cuting out all the black when I try to draw a black object...

Edit: Alright found out how to do it. Just gotta change it very slightly from pure black.

Yeah.

Just to clarify, if you have an image with pure black (RGB 0,0,0), Danmakufu treats that as transparency (probably a simple way to cover for the fact that several image formats lack a transparency channel).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on August 28, 2009, 03:22:16 PM
Oh, question: How are people able to do things like show how many point items you need for the next Extend on the border? I've never seen a function that allows this at all, and I'd like to know how it's done.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on August 28, 2009, 04:09:54 PM
Quote
Oh, question: How are people able to do things like show how many point items you need for the next Extend on the border? I've never seen a function that allows this at all, and I'd like to know how it's done.

You use the SetNormPoint function. Yes, its name is woefully undescriptive.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 28, 2009, 05:47:32 PM
Hi i have another question, is there a way to have the boss wait to fire untill specified, but not delayed?,  like start the attack after so much time?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: RavenEngie on August 28, 2009, 06:02:52 PM
How do you mean, like the pause at the start of a spellcard, a pause between waves of bullets, or what?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 28, 2009, 06:08:13 PM
How do you mean, like the pause at the start of a spellcard, a pause between waves of bullets, or what?
at the start
Title: Re: Danmakufu Q&A/Problem Thread
Post by: RavenEngie on August 28, 2009, 06:18:01 PM
Just put the variable that you use to make things happen at a lower value (or higher, if you make it go down once a frame).

Like this.

Code: [Select]
script_enemy_main{

        let frame = -120;

        everything else you need;

        @MainLoop{

              if(frame > 0 && whateverelse){
                      stuff happens;
              }
         frame ++;
}

Now there'll be a two-second pause between 'stuff happens' and the start of whatever.
That's what you meant, right?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on August 28, 2009, 10:23:09 PM
Just put the variable that you use to make things happen at a lower value (or higher, if you make it go down once a frame).

Like this.

Code: [Select]
script_enemy_main{

        let frame = -120;

        everything else you need;

        @MainLoop{

              if(frame > 0 && whateverelse){
                      stuff happens;
              }
         frame ++;
}

Now there'll be a two-second pause between 'stuff happens' and the start of whatever.
That's what you meant, right?
Nah, I have a better idea. How about make a dummy script that does nothing except draw the boss adn if needed, move the boss?

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on August 28, 2009, 11:11:24 PM
Quote
Oh, question: How are people able to do things like show how many point items you need for the next Extend on the border? I've never seen a function that allows this at all, and I'd like to know how it's done.

You use the SetNormPoint function. Yes, its name is woefully undescriptive.

It gets even better.

Based on my recent experience (NTSD), All SetNormPoint does is display the threshold value.  Apparently you need to put code in yourself to actually give the player an extra life.

... unless I royally screwed something up somewhere :V
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 29, 2009, 12:44:12 AM
Just put the variable that you use to make things happen at a lower value (or higher, if you make it go down once a frame).

Like this.

Code: [Select]
script_enemy_main{

        let frame = -120;

        everything else you need;

        @MainLoop{

              if(frame > 0 && whateverelse){
                      stuff happens;
              }
         frame ++;
}

Now there'll be a two-second pause between 'stuff happens' and the start of whatever.
That's what you meant, right?
Nah, I have a better idea. How about make a dummy script that does nothing except draw the boss adn if needed, move the boss?

hahaha how would i do that?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on August 29, 2009, 01:55:33 AM
Just put the variable that you use to make things happen at a lower value (or higher, if you make it go down once a frame).

Like this.

Code: [Select]
script_enemy_main{

        let frame = -120;

        everything else you need;

        @MainLoop{

              if(frame > 0 && whateverelse){
                      stuff happens;
              }
         frame ++;
}

Now there'll be a two-second pause between 'stuff happens' and the start of whatever.
That's what you meant, right?
Nah, I have a better idea. How about make a dummy script that does nothing except draw the boss adn if needed, move the boss?

hahaha how would i do that?
Code: [Select]
script_enemy_main{
let frame = -180;
@Initialize{
//Load graphics and other initialization stuff
SetLife(10000);
SetTimer(99);
//Expert;
}

@MainLoop{
frame++;
if(frame == -180) { Concentration01(120); }
if(frame == 0) { AddLife(-100001); }
}

@DrawLoop{
//Draw the boss here
}

@Finalize
{
//Delete graphics and other finalization stuff
}

}

I think...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on August 29, 2009, 01:56:37 AM
Time stopping... in Danmaku Bounded Field? :V
I think you're mistaking this with other spellcard.
No, I'm pretty sure it's Y's A: DBF. Like when the player character gets killed, the magic thing around Yukari stops spinning and the timer stops counting down, until the player loses all of her invincibility.
Oh, you mean THAT kind of timestop. I'm pretty sure that to do that effect, you can call a modification on the familiar's movement when the player dies. And since it's a familiar, you can use the familiar script to make it stop shooting as well while the player's invincible.

No, i want the timer to stop counting down...

Aaaand, done.

Code: [Select]
if(GetTimeOfPlayerInvincibility != 0 || OnBomb) {
SetDamageRate(0, 0);
SetTimer(GetTimer+1);
}

Why didn't I think of that months ago?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 29, 2009, 02:55:00 PM
I have been extremely busy again revising my afro boss. Tweaked alot of things but ONE thing is still bothering me which I failed to change.

How do a create a fountain effect for bullets:
- Bullets spawn up with random direction
- Each bullet has a random de-acceleration time ( some fast , some slow )
- Bullets fall down at a random speed in the same arched path they made during the de-acceleration

A picture show what I want to achieve:
(http://i29.tinypic.com/209lo3d.png) (basicly a parabole for each bullet)

Right now I have this:
Code: [Select]
CreateShotA(1,70,460,20);
SetShotDataA(1,0,6,rand(265,275),0,0,0,221);
SetShotDataA(1,30,5,rand(260,280),0,0,0,221);
SetShotDataA(1,80,3,NULL,0,0,0,221);
SetShotDataA(1,100,rand(0.2,2.5),rand(60,120),0,0,0,221);
FireShot(1);

CreateShotA(2,70,460,20);
SetShotDataA(2,0,6,rand(265,275),0,0,0,46);
SetShotDataA(2,30,5,rand(260,280),0,0,0,46);
SetShotDataA(2,80,3,NULL,0,0,0,46);
SetShotDataA(2,100,rand(0.2,2.5),rand(60,120),0,0,0,46);
FireShot(2);
But this looks extremely ugly as the bullets sudden change direction (using the angle). I want to make this a fluent fountain effect just like in the original Uwabami game. A reference to my replay with the spellcard in action:
http://www.youtube.com/watch?v=ZNMcYDtHiBI&fmt=18#t=1m38s
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on August 29, 2009, 03:18:04 PM
I'm thinking it would be best to use the XY versions of CreateShot and SetShotData for this. Also, don't forget you can use both the normal SetShotData and the XY version on the same bullet (although it's hard to keep the direction and speed constant).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on August 29, 2009, 03:27:29 PM
CreateShotA(1, x, y, 0);
SetShotDataA_XY(1, 0, v*cos(angle), v*sin(angle), acc, 0, 5, 0, graphic);
FireShot(1);

x,y = starting position
v = starting speed
angle = firing angle of the bullet; should be between -90? and +90?
acc = downward acceleration, or gravity; should be between 0.01 and 0.1


That should do fine.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 29, 2009, 03:51:43 PM
It is coming close, except the bullets fly away like this :V

SetShotDataA_XY(1,0,3*cos(rand(265,275)),3*sin(rand(265,275)),0.05,0,5,0,221);

(http://i27.tinypic.com/14iexit.png)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on August 29, 2009, 04:13:36 PM
ARGH!

Stupid me, always confusing the x and y axis! (Axiss? Axises? Axii? Axen? Who cares?)

It has to be:

SetShotDataA_XY(1,0,3*cos(rand(265,275)),3*sin(rand(265,275)),0,0.05,0,5,221);

If the bullets accelerate towards the right side of the filed instead of the bottom, well...  :V
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on August 29, 2009, 07:03:40 PM
I'm in despair once again!

I'm trying to make a circle of reflecting bullets, but the best I got is a script for a very unefficient horizontal reflection.

This is what I made of the object shots:

Code: [Select]
if(frame==100){
loop(10){
circle[a]=Obj_Create(OBJ_SHOT);
Obj_SetPosition(circle[a],GetX,GetY);
Obj_SetSpeed(circle[a],2);
Obj_SetAngle(circle[a],-30+angle);
ObjShot_SetBombResist(circle[a],true);
ObjShot_SetGraphic(circle[a],RED01);

angle+=36;
a+=1;
}
}

if(frame>100){
a=0;
loop(10){
if(Obj_GetX(circle[a])<GetClipMinX) {
Obj_SetAngle(circle[a],180-Obj_GetAngle(circle[a]) );
Obj_SetX(circle[a],Obj_GetX(circle[a])+0.1);
}
if(Obj_GetX(circle[a])>GetClipMaxX) {
Obj_SetAngle(circle[a], 180-Obj_GetAngle(circle[a]) );
Obj_SetX(circle[a],Obj_GetX(circle[a])-0.1);
}
if(Obj_GetY(circle[a])<GetClipMinY) {
Obj_SetAngle(circle[a],180-Obj_GetAngle(circle[a]) );
Obj_SetY(circle[a],Obj_GetY(circle[a])+0.1);
}
if(Obj_GetY(circle[a])>GetClipMaxY) {
Obj_SetAngle(circle[a], 180-Obj_GetAngle(circle[a]) );
Obj_SetY(circle[a],Obj_GetY(circle[a])-0.1);
}
a+=1;
}
}

Or the whole script:

Code: [Select]
#TouhouDanmakufu
#Title[*** (Lunatic)]
#Text[(***)]
#Player[FREE]
#Image[script\Images\Faces\.png]
#ScriptVersion[2]

script_enemy_main {

let circle=[0,1,2,3,4,5,6,7,8,9,10,11,12,13];
let angle=0;
let a=0;
let usespell=0;
let bgfade=0;
let frame=0;
let time=0;
let timercount=0;
let cx=GetCenterX;
let cy=GetCenterY;
let enemylife=0;
let lowhealth1=("script\SoundEffects\lowhealth1.wav");
let lowhealth2=("script\SoundEffects\lowhealth2.wav");
let timeout1=("script\SoundEffects\timeout1.wav");
let timeout2=("script\SoundEffects\timeout2.wav");
let BG1=("\script\Images\BackgroundLayers\kurumi1.png");
let Portrait=("\script\Images\Faces\TomokoNorm1.png");
let Boss=("\script\Images\CharacterSprites\KurumiNorm.png");

@Initialize{
LoadUserShotData("script\shots\Shots1Pos1.txt");
LoadGraphic(Boss);
LoadGraphic(BG1);
LoadGraphic(Portrait);
LoadSE(lowhealth1);
LoadSE(lowhealth2);
LoadSE(timeout1);
LoadSE(timeout2);

CutIn(YOUMU,""\"""\",Portrait,0,0,200,520);
SetScore(500000);
SetLife(500);
SetTimer(50);
SetGraphicRect(0,0,96,96);
SetInvincibility(30);
SetDamageRate(10,10);
SetEnemyMarker(true);
MagicCircle(true);
SetColor(255,160,200);
Concentration01(60);
Concentration02(60);
SetColor(255, 255, 255);
SetEffectForZeroLife(60,100,1);
SetMovePosition02(cx,cy-100,50);
// LastSpell;
}

@MainLoop {

SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

SetShotAutoDeleteClip(64,64,64,64);



if(frame==100){
loop(10){
circle[a]=Obj_Create(OBJ_SHOT);
Obj_SetPosition(circle[a],GetX,GetY);
Obj_SetSpeed(circle[a],2);
Obj_SetAngle(circle[a],-30+angle);
ObjShot_SetBombResist(circle[a],true);
ObjShot_SetGraphic(circle[a],RED01);

angle+=36;
a+=1;
}
}

if(frame>100){
a=0;
loop(10){
if(Obj_GetX(circle[a])<GetClipMinX) {
Obj_SetAngle(circle[a],180-Obj_GetAngle(circle[a]) );
Obj_SetX(circle[a],Obj_GetX(circle[a])+0.1);
}
if(Obj_GetX(circle[a])>GetClipMaxX) {
Obj_SetAngle(circle[a], 180-Obj_GetAngle(circle[a]) );
Obj_SetX(circle[a],Obj_GetX(circle[a])-0.1);
}
if(Obj_GetY(circle[a])<GetClipMinY) {
Obj_SetAngle(circle[a],180-Obj_GetAngle(circle[a]) );
Obj_SetY(circle[a],Obj_GetY(circle[a])+0.1);
}
if(Obj_GetY(circle[a])>GetClipMaxY) {
Obj_SetAngle(circle[a], 180-Obj_GetAngle(circle[a]) );
Obj_SetY(circle[a],Obj_GetY(circle[a])-0.1);
}
a+=1;
}
}


time++;
frame++;

if(GetLife<50 && (time-3)%4==0){ enemylife=GetLife; }
if(GetLife<enemylife && (time-0)%4==0){ PlaySE(lowhealth1);
 }
if(GetLife<enemylife && (time-2)%4==0){ PlaySE(lowhealth2);
 }

if(GetTimer<=10 && GetTimer>3 && time%60==0){ PlaySE(timeout1); }
if(GetTimer<=3 && time%60==0 && timercount<3){ PlaySE(timeout2);
 timercount+=1; }

}

@BackGround{
if(bgfade<70){bgfade+=5;}

SetGraphicRect(0,0,512,512);
SetGraphicScale(1.5,1.5);
SetTexture(BG1);
SetAlpha(50);
SetColor(255,255,255);
SetRenderState(ALPHA);
SetGraphicAngle(0,0,-(time/3));
DrawGraphic(cx,cy);
}

@DrawLoop{
SetGraphicRect(1,1,96,96);
SetGraphicScale(1,1);
SetTexture(Boss);
SetGraphicAngle(0, 0, 0);
SetColor(255,255,255);
SetRenderState(ALPHA);
SetGraphicAngle(0, 0, 0);

if(usespell>0){SetGraphicRect(288,0,384,96);
DrawGraphic(GetX, GetY);}

if(usespell==0){if(GetSpeedX==0){SetGraphicRect(0,0,96,96);}
else if(GetSpeedX>0){SetGraphicRect(192,0,288,96);}
else if(GetSpeedX<0){SetGraphicRect(96,0,192,96);}
DrawGraphic(GetX, GetY);}}
}

@Finalize{
DeleteGraphic(Portrait);
DeleteGraphic(Boss);
DeleteSE(lowhealth1);
DeleteSE(lowhealth2);
DeleteSE(timeout1);
DeleteSE(timeout2);
}

}

I also would like to know how you can let arrays fill themselves for easy mass modifying. Because "let circle=[0,1,2,3,4,5,6,7,8,9,10...etc" doesn't look very neat, and if you want to have more than 300 bullets on the screen at once, doing it this way will take forever.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 29, 2009, 07:19:14 PM
Thank you Iryan :x it works like a charm now. I just had to fool more with the speed and acceleration to make it more perfect.

It had a huge impact on the diffuclty of the spellcard, I had to test alot.   :V
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on August 29, 2009, 07:20:43 PM
I also would like to know how you can let arrays fill themselves for easy mass modifying. Because "let circle=[0,1,2,3,4,5,6,7,8,9,10...etc" doesn't look very neat, and if you want to have more than 300 bullets on the screen at once, doing it this way will take forever.
~ combines stuff. Use it to add items into arrays.

eg.
let array1 = [a]
array2 = array1 ~ "b"

Now array2 is ["a", "b"]


If you want to mass add stuff, use ascent.

eg.
let array1 = []
ascent(i in 0.. 10){
    array1= array1 ~ i
    }

Now array1 is [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 30, 2009, 05:25:30 PM
im trying to recreate the backround on Satori' Spell cards but i cant seem to get the other pictur to draw..or spin for tat matter... ive tried BGSpin and set at up, but nothing happens..
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 30, 2009, 05:40:33 PM
im trying to recreate the backround on Satori' Spell cards but i cant seem to get the other pictur to draw..or spin for tat matter... ive tried BGSpin and set at up, but nothing happens..

Have you read Nuclear cheese's drawing tutorial? It explains like clearly how to layer backgrounds in the @BackGround Loop. The first BG in the loop will be at the bottom. The next one will overlap the first. etc.

For tilting/spinning things you need to use: SetGraphicAngle(0,0,<variabel>); where the variabel gets increased by the value you want at the end of.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 30, 2009, 05:55:23 PM
im trying to recreate the backround on Satori' Spell cards but i cant seem to get the other pictur to draw..or spin for tat matter... ive tried BGSpin and set at up, but nothing happens..

Have you read Nuclear cheese's drawing tutorial? It explains like clearly how to layer backgrounds in the @BackGround Loop. The first BG in the loop will be at the bottom. The next one will overlap the first. etc.

For tilting/spinning things you need to use: SetGraphicAngle(0,0,<variabel>); where the variabel gets increased by the value you want at the end of.

yes ive read the drawing tutorial, but m not sure what the code is fr it
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on August 30, 2009, 06:08:58 PM
Try this for each BG you add to the BackGround

   SetTexture();
   SetRenderState();
   SetAlpha();
   SetGraphicRect();
   SetGraphicScale();
   SetGraphicAngle();
   DrawGraphic(GetCenterX, GetCenterY);

Always end with DrawGraphic then start the 2nd BG you want as top layer repeating the above.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on August 31, 2009, 02:31:41 AM
Just put the variable that you use to make things happen at a lower value (or higher, if you make it go down once a frame).

Like this.

Code: [Select]
script_enemy_main{

        let frame = -120;

        everything else you need;

        @MainLoop{

              if(frame > 0 && whateverelse){
                      stuff happens;
              }
         frame ++;
}

Now there'll be a two-second pause between 'stuff happens' and the start of whatever.
That's what you meant, right?
Nah, I have a better idea. How about make a dummy script that does nothing except draw the boss adn if needed, move the boss?

hahaha how would i do that?
Code: [Select]
script_enemy_main{
let frame = -180;
@Initialize{
//Load graphics and other initialization stuff
SetLife(10000);
SetTimer(99);
//Expert;
}

@MainLoop{
frame++;
if(frame == -180) { Concentration01(120); }
if(frame == 0) { AddLife(-100001); }
}

@DrawLoop{
//Draw the boss here
}

@Finalize
{
//Delete graphics and other finalization stuff
}

}

I think...
I tried that and it just straght forward went into the next atack

sorry for the errors, mediction is effecting my head.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on August 31, 2009, 05:21:21 AM
Can anyone figure out a way to get the SFX's in Touhou games?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on August 31, 2009, 05:33:45 AM
Can anyone figure out a way to get the SFX's in Touhou games?
Here be them. (http://www.shrinemaiden.org/forum/index.php?topic=197.0)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: DgBarca on September 01, 2009, 12:06:00 AM
Replays desync on this (http://www.mediafire.com/download.php?mirmz3lzqwf), it is not fun
AT ALL
I can't find what desync
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 01, 2009, 04:17:43 PM
Replays desync on this (http://www.mediafire.com/download.php?mirmz3lzqwf), it is not fun
AT ALL
I can't find what desync

When I saved my replay it shows 2 replays with the same name, date, time but one is called #01 and one is called User. The 01 one is out of sync somehow but the User replay is not.

Though the question is, how do I get two replays suddenly?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: DgBarca on September 01, 2009, 04:59:14 PM
This is too strange...HELP I can't show it to my friends >_<

Also I have made a [url+http://www.mediafire.com/download.php?guzchdqmymw]New Version[/url] (with normal mode, comment on my topic :3) and it is still desync.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 01, 2009, 07:01:37 PM

~ combines stuff. Use it to add items into arrays.

eg.
let array1 = [a]
array2 = array1 ~ "b"

Now array2 is ["a", "b"]


If you want to mass add stuff, use ascent.

eg.
let array1 = []
ascent(i in 0.. 10){
    array1= array1 ~ i
    }

Now array1 is [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].


I find that way hard to understand without a sample. x_x
I've looked into tuturials such as this http://dmf.shrinemaiden.org/wiki/index.php?title=Nuclear_Cheese%27s_Shot_Object_Tutorial , but the example script given is way too complicated to get a grip on.

I can somehow only make one bullet change properties, but when trying the same with multiple bullets, none respond to the changes.

I have this small test script here:

Code: [Select]
enemy=Obj_Create(OBJ_SHOT);
Obj_SetPosition(enemy,GetClipMinX+100,GetClipMinY+100);
Obj_SetSpeed(enemy,3);
Obj_SetAngle(enemy,90);
ObjShot_SetGraphic(enemy,RED01);
Obj_SetAutoDelete(enemy,true);
enemies = enemies ~ [enemy];

if(Obj_GetY(enemies)==200){
Obj_SetAngle(enemies,270);
}

But what I really want is:
-Have a new shot appear every X time or when an old one is deleted.
-Have them change direction so they move around the edges of the screen.
-Have them shoot stuff at you. :3
-The ability to individually make a change.

Yet all it can do now is making a long stream on bullets that only go downwards.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on September 02, 2009, 12:17:44 AM

~ combines stuff. Use it to add items into arrays.

eg.
let array1 = [a]
array2 = array1 ~ "b"

Now array2 is ["a", "b"]


If you want to mass add stuff, use ascent.

eg.
let array1 = []
ascent(i in 0.. 10){
    array1= array1 ~ i
    }

Now array1 is [0, 1, 2, 3, 4, 5, 6, 7, 8, 9].


I find that way hard to understand without a sample. x_x
I've looked into tuturials such as this http://dmf.shrinemaiden.org/wiki/index.php?title=Nuclear_Cheese%27s_Shot_Object_Tutorial , but the example script given is way too complicated to get a grip on.

I can somehow only make one bullet change properties, but when trying the same with multiple bullets, none respond to the changes.

I have this small test script here:

Code: [Select]
enemy=Obj_Create(OBJ_SHOT);
Obj_SetPosition(enemy,GetClipMinX+100,GetClipMinY+100);
Obj_SetSpeed(enemy,3);
Obj_SetAngle(enemy,90);
ObjShot_SetGraphic(enemy,RED01);
Obj_SetAutoDelete(enemy,true);
enemies = enemies ~ [enemy];

if(Obj_GetY(enemies)==200){
Obj_SetAngle(enemies,270);
}

But what I really want is:
-Have a new shot appear every X time or when an old one is deleted.
-Have them change direction so they move around the edges of the screen.
-Have them shoot stuff at you. :3
-The ability to individually make a change.

Yet all it can do now is making a long stream on bullets that only go downwards.


In the code you have there, I presume that enemies is an array meant to hold a list of object shots you want to manipulate, correct?

You can't use the Obj_GetY, Obj_SetAngle, etc. commands on an array.  Rather, you need to grab each item in the array and use the commands on each individually.


Within the tutorial you linked above, I gave a framework for using arrays of object shots.  To translate it to the code example you have above, it would be something like this:

Code: [Select]
let enemies = [];

// stuff

@Initialize
{
   // stuff
}

@MainLoop
{
   // stuff
   if (we_should_spawn_a_shot)
   {
      let enemy=Obj_Create(OBJ_SHOT);
      Obj_SetPosition(enemy,GetClipMinX+100,GetClipMinY+100);
      Obj_SetSpeed(enemy,3);
      Obj_SetAngle(enemy,90);
      ObjShot_SetGraphic(enemy,RED01);
      Obj_SetAutoDelete(enemy,true);
      enemies = enemies ~ [enemy];
   }

   let i = 0;
   while (i < length(enemies))
   {
      if (Obj_BeDeleted(enemies[i]))
      {
         enemies= erase(enemies, i);
         i--;
      }
      else
      {
         let obj = enemies[i];
         // Do object processing for the object identified by obj
         if(Obj_GetY(obj)==200){
            Obj_SetAngle(obj, 270);
         }
      }
      i++;
   }
}

(Disclaimer: I didn't actually test this code; I only wrote in the relevant parts.  Given the rest of a script around it, it should work)

The important part here, in order to get each bullet to process correctly, is where it says
let obj = enemies[ i ];

This pulls each object's ID from the array, so we can work with that individual object.


Also, another thing which is an issue in your code is the comparison itself:
if(Obj_GetY(obj)==200)

I'm pretty certain Danmakufu uses floating point numbers for positions.  Floating point numbers can be prone to error due to rounding and such, so it is possible that the Y position of the bullet never hits exactly 200, but rather hits something like 199.999999 - in this case the if will never trigger because it will pass right by 200.

In fact, with the values you've given, the Y coordinate will probably never hit 200 exactly.  I believe GetClipMinY returns the value 0, so you're starting your bullet at the Y coordinate of 100, moving straight downwards at 3 pixels per frame.  If you do the math, the Y coordinate of the bullet is, per frame:
100, 103, 106, 109 ... 187, 190 193, 196, 199, 202
At this rate, even if floating point error doesn't come into play you're still never going to hit 200 exactly.

There is a better way to handle this condition.  Since your bullets start off moving downward, and reverse direction once they hit Y = 200 (to go upwards), you can simply change the if to check if the Y position is at least 200:
if(Obj_GetY(obj)>=200)

With this, even if the bullet doesn't hit Y=200 exactly, it will still reverse direction.



Hopefully, this'll help you get going.



(PS - that array example in the Object Shot tutorial is meant more to give people a framework to throw their object shot processing code into, rather than as a tutorial on arrays themselves.  Perhaps another tutorial is in order?)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 02, 2009, 10:35:10 AM
Thanks! I tried it out, and it works like a charm!


I don't think any of the wiki's have a clear explanation on ascent/descent, their uses are quite puzzling.

Small simple sample scripts (try saying that 3 times) of important parts of danmakufu would be a great addition to the wiki. Many existing samples are a bit too overwhelming/complex for newbies. And it's those kind of people who need the wiki!
If it's an okay idea, I can help. I'm rather new, so I can point out what needs more clarification and what things are too confusing.



On a side-note. There's no square root function, is there?
I thought up a way to make squares instead of circles, but Pythagoras' theorem can't do much without square roots.
I wonder how other people did square shots, because I've seen it before in a video.
Well, I can calculate the angle/speed for each bullet with a bit of time, but...

Edit: Nevermind that. I think this will do the job of making a square:

Code: [Select]
if(frame%80==0 && frame>60){
let angle=0;
let direction=0;
let shape=4;   //changeable -- the number of edges. 3 is a triangle, 4 is a square, etc.
let centerspeed=2;   //changeable -- the speed in the center of the square. (each edge is 1.41 times this speed)
let size=5;   //changeable -- number of bullets on each half of a side of the square
let shapeloop=360/shape;
let variablespeed=0;
let side=(shapeloop/2)/size;
loop(size){
variablespeed+=(1.41421356/shapeloop)*side;
angle+=side;
loop(shape){
CreateShot01(GetX,GetY,centerspeed+variablespeed,direction+angle,RED01,0);
CreateShot01(GetX,GetY,centerspeed+variablespeed,direction-angle,RED01,0);
direction+=shapeloop;
}
}
loop(shape){
CreateShot01(GetX,GetY,centerspeed,direction,RED01,0);
direction+=shapeloop;
}
}

This makes any shape, including square, but the edges are slightly curved.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 02, 2009, 02:02:13 PM
On a side-note. There's no square root function, is there?

Square root = ^0.5

4^0.5 = 2.
16^0.5 = 4.

Cubic root = ^(1/3) (inaccurate)

27^(1/3) = 3.

Quartic root = ^0.25

16^0.25 = 2.

Etc.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 02, 2009, 05:17:50 PM
On a side-note. There's no square root function, is there?

Square root = ^0.5

4^0.5 = 2.
16^0.5 = 4.

Cubic root = ^(1/3) (inaccurate)

27^(1/3) = 3.

Quartic root = ^0.25

16^0.25 = 2.

Etc.

Oh, I had no idea that worked too!
The script I just posted works, but the sides are slightly curved. Which makes a nice pattern too, but I guess I really need to use that square root then.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on September 04, 2009, 11:38:11 PM
yay! another question from some one whocan rarely figure things out by himself  :-\
is there a way to recreate Okuu's Nuclear Bullets?, ive read the User Bullets tutorial, and i dont understand it, bt i kno i is an animated bullet...any sugesions?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 05, 2009, 01:18:05 PM
@demonbman You mean the big mofo red bullets?

It is not an animated bullet. They are two sprites covering eachother having a ALPHA and ADD value I think making it "glow". You need to first rip the sprite for it from SA then create your own shotscript in order to add the bullet to your shotdata.

After that you can use it for your Object Bullet to imitate it like making it shrink or grow. Tackle it 1 by 1. First go rip the bullet and add it as a custom shot (user bullet / shotdata)

-----------------

I got a question regarding commondata as whatever I do. It doesn't seems to be right. Here is the deal:

I got this object Laser which starts at the bottom of the screen. I want to influence the Y position by an task inside a familiar. Therefor using commondata is here required I believe. How can I store an variabel inside a CommonData and call that variabel inside a task? I had this as a startout:
Code: [Select]
---------------- declared in Enemy Main
let laserY = 430;
SetCommonData("rising",laserY);

-------------- A task inside the familiar
some task{
      let x = 0;
      while(x<100){
           SetCommonData("rising",laserY-x);
            x++;
      }
      yield;
}

---------- somewhere inside the Obj Laser
      Obj_SetY(obj,GetCommonData("rising",laserY);

I am doing something terribly wrong I believe.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 05, 2009, 10:18:00 PM
Yes, mostly because you don't seem to know the parameters of the CommonData functions! SetCommonData needs you to name the common data and then set a value to it. GetCommonData only needs you to mention the name of the common data you're getting.

Thus:

SetCommonData("awesome", 2);

later on....

CreateShot01(GetX, GetY, GetCommonData("awesome"), GetAngleToPlayer, RED01, 0);

Shoots a bullet with a velocity of 2 at the player.

Other useful information about common data. (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Miscellaneous_Functions)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on September 06, 2009, 08:51:58 AM
So I want to create an attack that uses familiars that can be shot. Shooting the is supposed to destroy them and damage the parent enemy. So I put SetDamageRateEx(50, 50, 50, 25); into the script of the familiar and summoned him with CreateEnemyFromFile. Everything about the familiar works as intended, save for one thing:

Even though the boss has no sort of invincibility and can be harmed by your shots like normal, shooting the familiar doesn't damage the boss and I have no idea why. Does SetDamageRateEx only work correctly with enemies summoned with CreateEnemyFromScript, maybe? I have no idea.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 06, 2009, 09:28:16 AM
So I want to create an attack that uses familiars that can be shot. Shooting the is supposed to destroy them and damage the parent enemy. So I put SetDamageRateEx(50, 50, 50, 25); into the script of the familiar and summoned him with CreateEnemyFromFile. Everything about the familiar works as intended, save for one thing:

Even though the boss has no sort of invincibility and can be harmed by your shots like normal, shooting the familiar doesn't damage the boss and I have no idea why. Does SetDamageRateEx only work correctly with enemies summoned with CreateEnemyFromScript, maybe? I have no idea.

Incidentally, I created such a script a few days ago. It goes like this:

-The familiar has a common data in its main loop:
Code: [Select]
SetCommonData(1,GetHitCount);
You can make more than one familiar/enemy:
Code: [Select]
SetCommonData(2,GetHitCount);

-And the actual boss has this:
Code: [Select]
AddLife(-(GetCommonData(1)/2));
If you're using more enemies, write it like this:
Code: [Select]
AddLife(-((GetCommonData(1)+GetCommonData(2))/2));
You might want to change the "divided by 2" at the end by another number, because familiars would deal different amounts of damage than normal shots would. But increasing the health meter works too.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on September 06, 2009, 10:19:22 AM
So there is a function for something that doesn't do what it is supposed to do so you have to work around it?
...
Well, its danmakufu. Figures...  :V

Thanks for the advice.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 06, 2009, 01:46:20 PM
Yes, mostly because you don't seem to know the parameters of the CommonData functions! SetCommonData needs you to name the common data and then set a value to it. GetCommonData only needs you to mention the name of the common data you're getting.

Thus:

SetCommonData("awesome", 2);

later on....

CreateShot01(GetX, GetY, GetCommonData("awesome"), GetAngleToPlayer, RED01, 0);

Shoots a bullet with a velocity of 2 at the player.

Other useful information about common data. (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Miscellaneous_Functions)

Yay, so that is how it is done. And I was like smashing my desk and pulling out my hair while the solution was frikken simple. =.=
I read the wiki but I was puzzled. I even looked at examples in other people's scripts and still was puzzled. Seriously the Wiki has such fuzzy examples and explanation. . .
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 06, 2009, 02:43:21 PM
Oh goody, I walked past Effect Objects before, and quickly ran when I saw words like
ObjEffect_SetVertexXY and ObjEffect_SetPrimitiveType.
But now I need to use them!

All I really want is a normal image of a 1:1 scale to appear on screen.
But there doesn't seem to be a normal coordinates command like SetGraphicRect(0,0,144,144);
I've looked through Nuclear Cheese's tutorial, which somewhat helped me. But like hell I can understand this part:

Code: [Select]
          ObjEffect_SetTexture(objid, imagefile);

          ObjEffect_SetPrimitiveType(objid, PRIMITIVE_TRIANGLELIST);

          ObjEffect_CreateVertex(objid, 3);

          ObjEffect_SetVertexXY(objid, 0, -20, -20);
          ObjEffect_SetVertexUV(objid, 0, 0, 0);

          ObjEffect_SetVertexXY(objid, 1, 20, 0);
          ObjEffect_SetVertexUV(objid, 1, 255, 127);

          ObjEffect_SetVertexXY(objid, 2, -20, 20);
          ObjEffect_SetVertexUV(objid, 2, 127, 255);

I applied that to the code I have now, and it works, but it makes a shape of it that I'm not looking for. How can I make it a regular square of 144x144?

This is what I have now:

Code: [Select]
let broom=(Obj_Create(OBJ_EFFECT));
Obj_SetPosition(broom,GetX,GetY);
ObjEffect_SetLayer(broom,3);
ObjEffect_SetAngle(broom,0,0,0);
ObjEffect_SetTexture(broom,broom1); (it's properly linked to an image)

if(frame>60){
ObjEffect_SetAngle(broom,0,0,time*3);
}

Just as a test, I wanted this to start spinning after 60 frames.

But when I paste NC's sample in the code I have now, I get this:

(http://i32.photobucket.com/albums/d49/puremrz/itsgettingdustyinhere.png)
(She's already sitting on a broom, but that's just the enemy's graphic, not the broom I want to spin around)

-It keeps creating more and more images.
-And they're definitely not square. D:


How can I fix this, and how exactly do those vertices options change the shape of the graphic?


(By the way, I edited ObjEffect_SetLayer in the wiki. Layer 8 draws over the frame while layer 7 still draws below. Useful too, especially when I get the answer to the question above. :P)



Edit: Nevermind that anymore, I somehow figured it out. The wiki needs a better explanation for this! Really!

So if anyone wants a sample on how to draw a square with Object Effects:

Code: [Select]
if(frame==30){
broom=(Obj_Create(OBJ_EFFECT));

Obj_SetPosition(broom,cx,cy-16);
ObjEffect_SetLayer(broom,3);
ObjEffect_SetAngle(broom,0,0,0);
ObjEffect_SetTexture(broom, broom1);

ObjEffect_SetPrimitiveType(broom,PRIMITIVE_TRIANGLEFAN);

ObjEffect_CreateVertex(broom,4);

ObjEffect_SetVertexXY(broom,3,72,72);
ObjEffect_SetVertexUV(broom,0,0,0);

ObjEffect_SetVertexXY(broom,2,-72,72);
ObjEffect_SetVertexUV(broom,1,144,0);

ObjEffect_SetVertexXY(broom,1,72,-72);
ObjEffect_SetVertexUV(broom,2,0,144);

ObjEffect_SetVertexXY(broom,0,-72,-72);
ObjEffect_SetVertexUV(broom,3,144,144);
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on September 06, 2009, 03:42:18 PM
here's soemthing i've worked on for a couple of weeks:

How would you imitate Koishi's 反応「妖怪ポリグラフ」? (the polygraph one.)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on September 06, 2009, 03:49:41 PM
Give me an hour...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on September 06, 2009, 04:03:01 PM
here's soemthing i've worked on for a couple of weeks:

How would you imitate Koishi's 反応「妖怪ポリグラフ」? (the polygraph one.)
Fairly easily, I would think. Bombproof C Lasers that rotate, and faster depending on the time. Then some simple trig based on the player's position and copied to the rest of the lasers, and spawn bullets based on that, which delete themselves after a while.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Iryan on September 06, 2009, 04:20:03 PM
Done. I'm fairly shure that there will be some error-causing typoes in there, but as I don't have Japanese settings on I can't test it right now without rebooting. Might fix any errors inside later today...

Edit: Fixed the errors. It is still somewhat different, but I think I know how to fix that. Just give me another 30-60 minutes...

Edit2: There you have it. The only remaining differences should be minor number juggling and of course SA having way superior graphics and effects which I can't replicate.  :V

Code: [Select]
#TouhouDanmakufu
#Title[Stuff 94 - polygraph]
#Text[bla]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let BossImage = "script\img\ExRumia.png";
    let BossCutIn = "script\img\ExRumia.png";

    let frame = -300;
    let angv=0;

    let color1 = [RED11, BLUE11, RED11, BLUE11, RED11, BLUE11, RED11, BLUE11];
    let color2 = [RED23, BLUE23, RED23, BLUE23, RED23, BLUE23, RED23, BLUE23];

    @Initialize {
        LoadGraphic(BossImage);
        SetLife(2500);
        SetDamageRate(0, 0);
        SetTimer(60);
        SetMovePosition02(GetCenterX,GetCenterY,60);
        SetEnemyMarker(true);
        SetDurableSpellCard;
    }

    @MainLoop {

        SetCollisionA(GetX, GetY, 24);
        SetCollisionB(GetX, GetY, 24);


        if(frame==-120){
           ascent(k in 0..8){ Tlaser(22.5+45*k, color1[k], color2[k]); }
        }

        if(frame==0){ angv=1/5; }

        if(frame>0){ angv+=0.000125; }

        frame++;

        yield;
    }

    @DrawLoop {

if(GetSpeedX()==0){SetGraphicRect(64,1,127,64);}
else if(GetSpeedX()>0){SetGraphicRect(192,1,255,64);}
else if(GetSpeedX()<0){SetGraphicRect(128,1,191,64);}
        SetTexture(BossImage);
        DrawGraphic(GetX, GetY);
       
    }

    @Finalize {
    }

    task Tlaser(ang, graph1, graph2){
        let obj=Obj_Create(OBJ_LASER);
        Obj_SetPosition(obj, GetCenterX, GetCenterY);
        Obj_SetAngle(obj, ang);
        Obj_SetSpeed(obj, 0);
        ObjShot_SetGraphic(obj, graph1);
        ObjLaser_SetLength(obj, 1000);
        ObjLaser_SetWidth(obj, 16);


        let timer=-180;
        let distance;
        let px;
        let py;

        while(Obj_BeDeleted(obj)==false){

            yield;
            timer++;

            Obj_SetAngle(obj, Obj_GetAngle(obj)-angv);

            if(timer>0&&timer%7==0){
                distance=( (GetPlayerX-GetCenterX)^2 + (GetPlayerY-GetCenterY)^2 )^0.5;

                px=GetCenterX+distance*cos(Obj_GetAngle(obj));
                if(px<GetClipMinX+8){ px=GetClipMinX+8; }
                if(px>GetClipMaxX-8){ px=GetClipMaxX-8; }

                py=GetCenterY+distance*sin(Obj_GetAngle(obj));
                if(py<GetClipMinY+8){ py=GetClipMinY+8; }
                if(py>GetClipMaxY-8){ py=GetClipMaxY-8; }

                CreateShotA(1, px, py, 1);
                SetShotDataA(1, 0, 0, Obj_GetAngle(obj)-90, 0, 0, 0, graph2);
                SetShotKillTime(1, ceil(45/angv)-2);
                FireShot(1);

            }
        }
       
    }

}

Shows yet again that the difficult part is not to script your patterns but to think of patterns to script.
...damn...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on September 06, 2009, 08:43:18 PM
Oh goody, I walked past Effect Objects before, and quickly ran when I saw words like
ObjEffect_SetVertexXY and ObjEffect_SetPrimitiveType.
But now I need to use them!

All I really want is a normal image of a 1:1 scale to appear on screen.
But there doesn't seem to be a normal coordinates command like SetGraphicRect(0,0,144,144);
I've looked through Nuclear Cheese's tutorial, which somewhat helped me. But like hell I can understand this part:

Code: [Select]
          ObjEffect_SetTexture(objid, imagefile);

          ObjEffect_SetPrimitiveType(objid, PRIMITIVE_TRIANGLELIST);

          ObjEffect_CreateVertex(objid, 3);

          ObjEffect_SetVertexXY(objid, 0, -20, -20);
          ObjEffect_SetVertexUV(objid, 0, 0, 0);

          ObjEffect_SetVertexXY(objid, 1, 20, 0);
          ObjEffect_SetVertexUV(objid, 1, 255, 127);

          ObjEffect_SetVertexXY(objid, 2, -20, 20);
          ObjEffect_SetVertexUV(objid, 2, 127, 255);

I applied that to the code I have now, and it works, but it makes a shape of it that I'm not looking for. How can I make it a regular square of 144x144?

This is what I have now:

Code: [Select]
let broom=(Obj_Create(OBJ_EFFECT));
Obj_SetPosition(broom,GetX,GetY);
ObjEffect_SetLayer(broom,3);
ObjEffect_SetAngle(broom,0,0,0);
ObjEffect_SetTexture(broom,broom1); (it's properly linked to an image)

if(frame>60){
ObjEffect_SetAngle(broom,0,0,time*3);
}

Just as a test, I wanted this to start spinning after 60 frames.

But when I paste NC's sample in the code I have now, I get this:

<picture>
(She's already sitting on a broom, but that's just the enemy's graphic, not the broom I want to spin around)

-It keeps creating more and more images.
-And they're definitely not square. D:


How can I fix this, and how exactly do those vertices options change the shape of the graphic?


(By the way, I edited ObjEffect_SetLayer in the wiki. Layer 8 draws over the frame while layer 7 still draws below. Useful too, especially when I get the answer to the question above. :P)



Edit: Nevermind that anymore, I somehow figured it out. The wiki needs a better explanation for this! Really!

So if anyone wants a sample on how to draw a square with Object Effects:

Code: [Select]
if(frame==30){
broom=(Obj_Create(OBJ_EFFECT));

Obj_SetPosition(broom,cx,cy-16);
ObjEffect_SetLayer(broom,3);
ObjEffect_SetAngle(broom,0,0,0);
ObjEffect_SetTexture(broom, broom1);

ObjEffect_SetPrimitiveType(broom,PRIMITIVE_TRIANGLEFAN);

ObjEffect_CreateVertex(broom,4);

ObjEffect_SetVertexXY(broom,3,72,72);
ObjEffect_SetVertexUV(broom,0,0,0);

ObjEffect_SetVertexXY(broom,2,-72,72);
ObjEffect_SetVertexUV(broom,1,144,0);

ObjEffect_SetVertexXY(broom,1,72,-72);
ObjEffect_SetVertexUV(broom,2,0,144);

ObjEffect_SetVertexXY(broom,0,-72,-72);
ObjEffect_SetVertexUV(broom,3,144,144);
}


It seems my Effect Object tutorial could use a bit of clarification ... hmm ...


But, to be honest, wouldn't it just be easier to draw the broom using the simple drawing commands?  Something like:

Code: [Select]
SetGraphic("broom.png");
SetGraphicAngle(0, 0, rotation);
SetGraphicRect(0, 0, 144, 144);
DrawGraphic(broom_x, broom_y);
(Note: the above code would be placed in your script's @DrawLoop)

If you just want to draw a square/rectangular graphic, I think that should do what you need sufficiently.  Unless you're going for some effect that I'm not seeing at the moment ...



Effect objects are very complicated beasts ... I sure as hell wouldn't have understood them if it wasn't for the face that I've already worked with 3D graphics programming for a while.  Their use is probably unnecessary for most things; mainly, you'd want to use them for drawing irregular shapes and such.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 06, 2009, 09:04:54 PM
I figured it out now. :3
The main reason I need to do it this way is so I can choose which layer I will draw on. Because there are a few cases where I want stuff to appear above the player, and sometimes even above the subscreen frame.
Unfortunately, you can't pick the layer by using the DrawGraphic method, it always appears below the player and enemy.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 07, 2009, 06:10:15 PM
Something totally out of the question but =P

What is Danmakufu in japanese?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on September 07, 2009, 06:27:41 PM
弾幕風 = bullet curtain "method". Or style or function or whatever.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 07, 2009, 06:41:10 PM
Ah, now I can put this in front of my touhou moves + tags. =) Thanks Drake.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on September 08, 2009, 03:34:30 AM
This will probably be a difficult thing for anyone to help me with, but I'd appreciate some help...

Suwako Player (http://www.mediafire.com/?j0xz52nwyjm) (Everything but cutin drawn by yours truly, and yes, that other Suwako is freaking huge- it's the original, and I'm keeping it for massive laughs later on...)

Okay, the problem is simple- the frogs fire normally. No problem! Well, until you start moving around and bringing them out of synch. Eventually, some of them will take TWICE as long to finish exploding. That is, the explosions will fully animate twice before finally vanishing. I don't know if this is due to the explosions getting spawned twice or what, but I know that it's not what should be happening, and it actually doesn't happen normally, as far as I know...

(Also, I know that when they leave the play area, the explosions appear in semi-random positions... I'm more worried about fixing this double-explosion problem than putting checks for if they're out of the playfield when they explode. I'm also not concerned with the fact that I have six tasks. I'm not going to put them into one until all this works perfectly.)


(and yes, the explosions DO appear when the frogs hit the enemy. It was much easier than you'd think, too, just make them appear when the frog vanishes... No need to do any silly Collision checks with other objects...)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on September 08, 2009, 03:45:47 AM
Yes, yes, let's all laugh at Drake for trying to find a extraordinary difficult solution to an easy problem.

;_;
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 08, 2009, 03:57:50 AM
So the shots are supposed to go out of sync? You just want the bomb animation to not play a trillion times? Make each section of the bomb animation a different bullet graphic. Instead of:

Code: [Select]
ShotData
{
id = 3
render = ADD
alpha=210
angular_velocity = 0
AnimationData
{
animation_data = (3, 176, 28, 228, 77)
animation_data = (3, 235, 28, 287, 77)
animation_data = (3, 299, 28, 351, 77)
animation_data = (3, 358, 28, 410, 77)
animation_data = (3, 421, 28, 473, 77)
animation_data = (3, 482, 28, 534, 77)
animation_data = (3, 535, 28, 587, 77)
}
}

Have something like:
Code: [Select]
ShotData
{
id = 3
render = ADD
alpha=210
angular_velocity = 0
rect = (3, 176, 28, 228)
}
ShotData
{
id = 4
render = ADD
alpha=210
angular_velocity = 0
rect = (3, 235, 28, 287)
}
ShotData
{
id = 5
render = ADD
alpha=210
angular_velocity = 0
rect = (3, 299, 28, 351)
}
....//etc.

And in your froggy tasks, have them appear for so many frames. Like so:

Code: [Select]
loop(3){
ObjShot_SetGraphic(Explo6, 3);
yield;
}
loop(3){
ObjShot_SetGraphic(Explo6, 4);
yield;
}
loop(3){
ObjShot_SetGraphic(Explo6, 5);
yield;
}
...//etc...

I have an example script if this isn't clear.
This way the task will just be suspended when you die or something, and the animation will stop until you respawn and the task can continue. Looks wierd, but you can try it to see if you like it more.

Yes, yes, let's all laugh at Drake for trying to find a extraordinary difficult solution to an easy problem.

;_;

Sorry brah, meant no offense ;_;
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on September 08, 2009, 04:10:03 AM
Alright, Naut, I'll try that... and oddly enough, I was THINKING about it earlier...

Drake: I wasn't even laughing in my head. :> In fact, as I was posting it, the only think related to you I was thinking of was "Hey wait, now this solves Drake's problem! Awesome! :D" And I mean that in a GOOD way!

EDIT: Well, the code you told me to use is fine, but... The stuff now ALWAYS animates twice, but only if I hold the shot button. In fact, it'll loop like this if I do that:

1. Animate twice, stop a few frames into a third
2. Vanish without an explosion upon refiring
3. Repeat

However, if I merely PRESS the shot key and immediately release it, it animates once, but if I try to press it before it will refire, but at a time where it'll fire again before the "shotCount" resets to -1, when the next set fires, they'll go too far- all the way to the enemy, from the bottom of the screen! The next shots after that mess up, too- some explode immediately, but LOWER than where the frogs should start... They'd explode right about where the player is. The others still explode sooner than they should (less than a second afterward), but not immediately. This is seriously perplexing.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on September 08, 2009, 04:24:00 AM
How do i make the effect that a white orb moves across the screen firing bullets, like the ones in Flan's Cranberry Trap, would i have to make a enemy script that goes across the screen or what?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on September 08, 2009, 04:27:18 AM
You just need a position, an enemy isn't needed. Make it an object bullet that follows an x and y coordinate each frame, and just make instructions for the x and y positions.

Or you could use CreateShotA_XY instead and fire off AddShots.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 08, 2009, 08:37:16 AM
Question, I am probably going to get Yukari gapped for this crazy method but let us see. Here is the case:

CASE SOLVED - Thanks Naut on IRC


- I am using a familiar which is spawned from a file "fam.txt"

- However, the boundaries for the GraphicRect and texture are passed to the file by a seperate Function file ("famfunction.txt"). The famfunction.txt contains basicly a task which is called inside your main file with parameters.

- Here is the deal. The boundaries work fine but somehow I cannot seem to pass the texture path for it.

-------------------- In the main file
let famimg = CSD ~ <path>;
fammer(<parameters>,famimg,<parameters>);   <--- this is a function task declared in famfunction.txt
#include_function famfunction.txt   <---- logical else you cannot call the function

-------------------- in the function file
function fammer(<parameters>,img,<parameters>){
let getImg = img <-- retreiving from the parameters
SetCommonData("leftBoundary",left);   <--- retreiving parameters etc for all 4 values

CreateEnemyFromFile(CSD~"fam.txt", GetX, GetY, 0, 0, getImg);  <-- ! Note the argument!
}


-------------------- Inside fam.txt
script_enemy_main {
    let familiarImg = GetArgument;  <--- ! Note here the argument from create is get!
#include_function famfunction.txt   <---- logical else it wouldn't know

~~~~~~~~

Problem: the image is not being get. And Danmakufu doesn't likes GetCommonData here, it makes it instantly crash
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 09, 2009, 12:06:30 AM
<3
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 09, 2009, 04:21:28 PM
Doublepost, bitches.

How does @Background work and what functions can be passed in it?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on September 09, 2009, 04:44:30 PM
Functionally I'm pretty sure @Background is exactly the same as @DrawLoop, except in terms of priority. @Background is executed before @DrawLoop so anything you draw in it will be below all other graphics. Also, I think @Background might have less priority in terms of processor power? When I hit the fast forward key the background doesn't move as fast as the play field, or something like that.

@Background is really more for organization purposes, clarifying what's stage graphics and what's character graphics. It's also unusual to use @Background in a spellcard script, as making a background in a stage script will pass it to any spellcards.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 09, 2009, 05:04:31 PM
It's also unusual to use @Background in a spellcard script, as making a background in a stage script will pass it to any spellcards.
What if you want to change the background after a few spellcards, like with Marisa's/Reimu's IN "running away". CommonData?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on September 09, 2009, 05:18:04 PM
Well in IN's case it would actually be easy because technically the first part of the fight is a midboss, since it ends and you go into normal stage mode again; you would just set a variable in the stage script at that point to make the background behave differently.

If you wanted to change the background in the middle of a plural file though...well personally I would just use commondata for the stage @Background to reference, but yeah you could put a special background into the spellcard. Though that does raise the question to me, will spellcard @Background positions carry over between spellcards or will they reset each time a new attack comes up? I would assume they don't so that's another reason to save @Background for the stage script.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 09, 2009, 07:30:17 PM
I asked because I can't draw text in @Background for a stage script. Thought it might be different.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on September 10, 2009, 12:34:33 AM
is there a way to make a bullet start at..lets say x=200, is there a way i can like make it fire +10 every time? so it would first fire at 200, then 210, 220, 230...and so on an so on?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on September 10, 2009, 12:41:10 AM
ascent(i in 0..10){
    CreateShot01(200+(i*10), 0, 3, 0, RED01, 5);
}

add pauses and such
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 10, 2009, 02:35:20 AM
Can anyone tell me about how to make Talking events in Danmakufu, is the 'yield;' statement required? (i'm totally lost)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 10, 2009, 02:38:40 AM
Hello Henry. (http://www.shrinemaiden.org/forum/index.php?topic=865.msg31787#msg31787)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 10, 2009, 02:53:59 AM
However, this script is non-functional (boss image won't display)

Code: [Select]
script_enemy_main{
   let ImgBoss = "..\images\patchouli.png";
   let bg = "";
   let frame=0;
   SetX(GetCenterX);
   SetY(GetClipMinY+120);
   @Initialize{
      SetLife(1);
      SetDamageRate(0,0);
      LoadGraphic(ImgBoss);
      CreateEventFromScript("talk");
      MagicCircle(false);
   }

   @MainLoop{
   }
   @DrawLoop{
      if(frame>50){
      LoadGraphic(ImgBoss);
      SetTexture(ImgBoss);
      SetGraphicAngle(0, 0, 0);
      SetGraphicRect(49*floor(2-absolute(frame/15-2)), 0,49*floor(3-absolute(frame/15-2)), 80);
      SetGraphicScale(1, 1);
      if(frame>0){
         DrawGraphic(GetX, GetY+sin(frame*3)*10);
      }else{
         DrawGraphic(GetX, GetY);
      }
      }
      frame++;
   }
}

script_event talk{
   let imgPatchy = "..\images\imgPatchy.png";
   let imgReimu = "..\images\imgReimu.png";
   let imgMarisa = "..\images\imgMarisa.png";
   @MainLoop{
alternative( GetPlayerType() )
case( MARISA_A, MARISA_B ){
   TextOut("\c[BLUE]...Hey...");
   SetChar(RIGHT,imgPatchy);
           SetGraphicRect(RIGHT,1,1,127,255);
   MoveChar(RIGHT,FRONT);
           SetNameFromText(RIGHT,TEXT_RED,"Patchouli Knowledge","The Unmoving Great Library");
   TextOut("\c[BLUE]Hi Marisa!\nYou want to 'borrow' books again?");
           DeleteName(RIGHT);
   SetChar(LEFT,imgMarisa);
           SetGraphicRect(LEFT,127,1,255,255);
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   TextOut("\c[RED]Well... You seem to want to aruge it a lot...");
   TextOut("\c[RED]In fact, I am treated as a thief each time I enter the mansion.");
   TextOut("\c[RED]Even the Aya accused me of that!!!");
           MoveChar(RIGHT,FRONT);
   MoveChar(LEFT,BACK);
   SetChar(RIGHT,imgPatchy);
           SetGraphicRect(RIGHT,127,1,255,255);
   TextOut("\c[BLUE]You are.");
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   SetChar(LEFT,imgMarisa);
           SetGraphicRect(LEFT,1,1,127,255);
   TextOut("\c[RED]Anyway, I'll be free to enter or leave this mansion freely if I defeat you.");
   TextOut("\c[RED]And every time along with my leaving, I'll borrow 10 books.");
           MoveChar(RIGHT,FRONT);
   MoveChar(LEFT,BACK);
           SetGraphicRect(RIGHT,1,1,127,255);
   SetChar(RIGHT,imgPatchy);
   TextOut("\c[BLUE]You must be dreaming.\nYou won't defeat me.");
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   SetChar(LEFT,imgMarisa);
           SetGraphicRect(LEFT,127,1,255,255);
   TextOut("\c[RED]We'll see. Just like I defeated you many times ago!");
           End();
}
   }
}

All images have been declared properly but when I use Marisa, the boss image won't display. :(
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 10, 2009, 07:56:06 AM
You are not loading your graphics. Where is your @initialize?.

Code: [Select]
script_event showdown{
let CSD = GetCurrentScriptDirectory;

let ReiNorm = CSD ~ "system\ReiNorm.png";
let ReiBoos = CSD ~ "system\ReiBoos.png";
let ReiHo = CSD ~ "system\ReiHo.png";
let ReiOk = CSD ~ "system\ReiOk.png";
let ReiTel = CSD ~ "system\ReiTel.png";
let ReiSch = CSD ~ "system\ReiSch.png";
let ReiOpm = CSD ~ "system\ReiOpm.png";
let ReiAtt = CSD ~ "system\ReiAtt.png";

let AfroNorm = CSD ~ "system\AfroNorm.png";
let AfroSch = CSD ~ "system\AfroSch.png";
let AfroBoos = CSD ~ "system\AfroBoos.png";

@Initialize{    <-------- THIS IS NEEDED YO.
LoadGraphic(ReiNorm);   <----- LOADZ ZE GRAPHICS.
LoadGraphic(ReiHo);
LoadGraphic(ReiBoos);
LoadGraphic(ReiOk);
LoadGraphic(ReiTel);
LoadGraphic(ReiSch);
LoadGraphic(ReiOpm);
LoadGraphic(ReiAtt);

LoadGraphic(AfroNorm);
LoadGraphic(AfroSch);
LoadGraphic(AfroBoos);
}

@MainLoop{
if(GetPlayerType==REIMU_A || GetPlayerType==REIMU_B){
SetChar(LEFT,ReiHo);SetGraphicRect(LEFT,0,0,128,256);
MoveChar(LEFT,FRONT);
TextOutA("\c[RED]I can't see a thing. Is this really the place Marisa told me?");
MoveChar(LEFT,BACK);
TextOutA("\c[BLUE]A Shrine Maiden? Ha ha ha ha!");
SetChar(LEFT,ReiBoos);SetGraphicRect(LEFT,0,0,128,256);
MoveChar(LEFT,FRONT);

Don't forget to end with @Finalize also deleting them from memory.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 10, 2009, 12:06:14 PM
This is the edited code, but the ImgBoss does not show up (it exists).
Code: [Select]
script_enemy_main{
   let ImgBoss = "..\images\patchouli.png";
   let bg = "";
   let frame=0;
   SetX(GetCenterX);
   SetY(GetClipMinY+120);
   @Initialize{
      SetLife(1);
      SetDamageRate(0,0);
      LoadGraphic(ImgBoss);
      CreateEventFromScript("talk");
      MagicCircle(false);
   }

   @MainLoop{
      yield;
   }
   @DrawLoop{
      if(frame>50){
         LoadGraphic(ImgBoss);
         SetTexture(ImgBoss);
         SetGraphicAngle(0, 0, 0);
         SetGraphicRect(49*floor(2-absolute(frame/15-2)), 0,49*floor(3-absolute(frame/15-2)), 80);
         SetGraphicScale(1, 1);
         DrawGraphic(GetX, GetY+sin(frame*3)*10);
      }
      frame++;
   }
   @Finalize{
      DeleteGraphic(ImgBoss);
   }
}

script_event talk{
   let imgPatchy = "..\images\imgPatchy.png";
   let imgReimu = "..\images\imgReimu.png";
   let imgMarisa = "..\images\imgMarisa.png";
   @Initialize{
      LoadGraphic(imgPatchy);
      LoadGraphic(imgReimu);
      LoadGraphic(imgMarisa);
   }
   @MainLoop{
alternative( GetPlayerType() )
/*case( REIMU_A, REIMU_B ){
   TextOut("\c[BLUE]Hey, I know you...");
   SetChar(RIGHT,imgCirno);
           SetGraphicRect(RIGHT,1,1,127,255);
   MoveChar(RIGHT,FRONT);
           SetNameFromText(RIGHT,TEXT_RED,"Cirno","Math Teacher");
   TextOut("\c[BLUE]Hey Rumia!\nHow are you?");
           DeleteName(RIGHT);
   SetChar(LEFT,imgRumia);
           SetGraphicRect(LEFT,127,1,255,255);
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   TextOut("\c[RED]Let's see...\nI'm hungry!");
   SetChar(LEFT,imgRumia2);
           SetGraphicRect(LEFT,1,1,127,255);
   TextOut("\c[RED]May I eat you?");
           MoveChar(RIGHT,FRONT);
   MoveChar(LEFT,BACK);
           SetGraphicRect(RIGHT,127,1,255,255);
   TextOut("\c[BLUE]No...");
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   SetChar(LEFT,imgRumia);
           SetGraphicRect(LEFT,1,1,127,255);
   TextOut("\c[RED]Anyway, I'm lost here.\nWhere AM I?");
           MoveChar(RIGHT,FRONT);
   MoveChar(LEFT,BACK);
           SetGraphicRect(RIGHT,1,1,127,255);
   TextOut("\c[BLUE]Seems we're in space!\nCool, isn't it?");
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   SetChar(LEFT,imgRumia2);
           SetGraphicRect(LEFT,127,1,255,255);
   TextOut("\c[RED]Hell, no!");
   SetChar(LEFT,imgRumia);
           SetGraphicRect(LEFT,1,1,127,255);
   TextOut("\c[RED]If you don't mind I'm\ngoing to find the cause of this.");
           MoveChar(RIGHT,FRONT);
   MoveChar(LEFT,BACK);
   TextOut("\c[BLUE]I found out already...\nWhen remilia was defeated...");
   TextOut("\c[BLUE]She ordered Sakuya to warp a planet\nin front of the sun to block the light.");
   TextOut("\c[BLUE]It seems Sakuya accidently \nwarped us into the infinite, too.");
           End();
}*/
case( MARISA_A, MARISA_B ){
   TextOut("\c[BLUE]...Hey...");
   SetChar(RIGHT,imgPatchy);
           SetGraphicRect(RIGHT,1,1,127,255);
   MoveChar(RIGHT,FRONT);
           SetNameFromText(RIGHT,TEXT_RED,"Patchouli Knowledge","The Unmoving Great Library");
   TextOut("\c[BLUE]Hi Marisa!\nYou want to 'borrow' books again?");
           DeleteName(RIGHT);
   SetChar(LEFT,imgMarisa);
           SetGraphicRect(LEFT,127,1,255,255);
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   TextOut("\c[RED]Well... You seem to want to aruge it a lot...");
   TextOut("\c[RED]In fact, I am treated as a thief each time I enter the mansion.");
   TextOut("\c[RED]Even the Aya accused me of that!!!");
           MoveChar(RIGHT,FRONT);
   MoveChar(LEFT,BACK);
   SetChar(RIGHT,imgPatchy);
           SetGraphicRect(RIGHT,127,1,255,255);
   TextOut("\c[BLUE]You are.");
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   SetChar(LEFT,imgMarisa);
           SetGraphicRect(LEFT,1,1,127,255);
   TextOut("\c[RED]Anyway, I'll be free to enter or leave this mansion freely if I defeat you.");
   TextOut("\c[RED]And every time along with my leaving, I'll borrow 10 books.");
           MoveChar(RIGHT,FRONT);
   MoveChar(LEFT,BACK);
           SetGraphicRect(RIGHT,1,1,127,255);
   SetChar(RIGHT,imgPatchy);
   TextOut("\c[BLUE]You must be dreaming.\nYou won't defeat me.");
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   SetChar(LEFT,imgMarisa);
           SetGraphicRect(LEFT,127,1,255,255);
   TextOut("\c[RED]We'll see. Just like I defeated you many times ago!");
           End();
}
yield;
   }
   @Finalize{
      DeleteGraphic(imgMarisa);
      DeleteGraphic(imgPatchy);
      DeleteGraphic(imgReimu);
   }
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on September 10, 2009, 03:07:24 PM
You have two dots in your main folder locator thingy. It's not "..\etc", it's ".\etc".
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on September 10, 2009, 11:02:36 PM
I believe there's no way to change the difficulty in the middle of a script.
Anways... :yukkuri:
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on September 10, 2009, 11:42:24 PM
I believe there's no way to change the difficulty in the middle of a script.
Anways... :yukkuri:
Uh actually I'm pretty sure it's possible. Depends on how you want to do it though.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 11, 2009, 12:18:43 AM
I believed that .\ and ..\ are the same, and it worked for my other scripts (using the same images and resources in the same folder)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on September 11, 2009, 02:52:46 AM
I believe there's no way to change the difficulty in the middle of a script.
Anways... :yukkuri:
Uh actually I'm pretty sure it's possible. Depends on how you want to do it though.

Oh, I mean the text displayed by #PlayLevel[blah blah blah].

Is it changable mid-game?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on September 11, 2009, 03:00:21 AM
I believe there's no way to change the difficulty in the middle of a script.
Anways... :yukkuri:
Uh actually I'm pretty sure it's possible. Depends on how you want to do it though.

Oh, I mean the text displayed by #PlayLevel[blah blah blah].

Is it changable mid-game?
Midscript I guess not, but you could have a stage script with multiple spellcard scripts in it, and have different #PlayLevel strings for each spellcard or something.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on September 11, 2009, 03:06:45 AM
im having trouble using Tasks now...
Im trying to get this task to work and it wont >_< the script_enemy_main
error comes up.. here is the script:

Code: [Select]
#TouhouDanmakufu
#Title[Task & Loop Test]
#Text[Task Test]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = 0;
    let angle = 0;
    let BossImage = "script\img\ExRumia.png";
    let BossCutIn = "script\img\ExRumia.png";
    @Initialize {
        LoadGraphic(BossImage);
        SetLife(100);
        SetDamageRate(10, 10);
        SetTimer(50);
SetMovePosition02(GetCenterX, GetCenterY - 100, 120);
        SetInvincibility(30);
        CutIn(YOUMU, "Spellcard Name", BossCutIn, 0, 0, 200, 600);
        SetScore(500000);
        SetEnemyMarker(true);
        SetDurableSpellCard;
        Concentration01(60);
        Concentration02(60);
        MagicCircle(false);
        SetEffectForZeroLife(180, 100, 1);
    }

@MainLoop{
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);
frame++;

if(frame==10){

loop(100){
CreateShot01(GetX, GetY, 3, 180+angle, BLUE12, 0);
angle += 180/100;

}

angle = 0;
frame = 0;
}
if(frame==60){
Bullet(GetX, GetY, 3, 10);
yeild;
frame = 0;
}
}


    @DrawLoop {
        SetTexture(BossImage);
        DrawGraphic(GetX, GetY);
       
    }

    @Finalize {
    }
task Bullet(x, y, v, angle) {
      let obj=Obj_Create(OBJ_SHOT);

      Obj_SetPosition(obj, x, y);
      Obj_SetAngle(obj, angle);
      Obj_SetSpeed(obj, v);
      ObjShot_SetGraphic(obj, RED01);
      ObjShot_SetDelay  (obj, 0);
      ObjShot_SetBombResist (obj, true);

      while(Obj_BeDeleted(obj)==false) {

              if(Obj_GetX(obj)<GetClipMinX) {
                     Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) );
                     Obj_SetX(obj,  Obj_GetX(obj) + 0.1);
              }

              if(Obj_GetX(obj)>GetClipMaxX) {
                     Obj_SetAngle(obj, 180 - Obj_GetAngle(obj) );
                     Obj_SetX(obj,  Obj_GetX(obj) - 0.1);
              }

              yield;
       }



Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 11, 2009, 03:09:10 AM
Yuo misspelt to yield; into yeild; in the @MainLoop and a } is missing.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on September 11, 2009, 03:09:29 AM
It would help if you at least looked at your script instead of just coming here going "oh no it doesn't work immediately"

"yield" is spelled wrong in the MainLoop, and should be called every frame, not just at 60.
Also, you're missing a } at the end of your script.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 11, 2009, 03:16:47 AM
Btw, after frame==10, you set frame=0.
Then the if(frame==60){} can never be run.

Also:

Code: [Select]
script_enemy_main{
   let ImgBoss = GetCurrentScriptDirectory~"images\patchouli.png";
   let bg = "";
   let frame=0;
   let event=1;
   SetX(GetCenterX);
   SetY(GetClipMinY+120);
   @Initialize{
      SetLife(1);
      SetDamageRate(0,0);
      CreateEventFromScript("talk");
      MagicCircle(false);
   }

   @MainLoop{
      frame++;
      if(frame==50){
loop(3){
    Concentration01(100);
    Explosion01(GetX,GetY,5.5,0.2,255);
    SetColor(255,255,255);
}
      }
      if(event==0){
SetLife(-1);
      }
   }
   @DrawLoop{
      if(frame>75){
         LoadGraphic(ImgBoss);
         SetTexture(ImgBoss);
         SetGraphicAngle(0, 0, 0);
         SetGraphicRect(49*floor(2-absolute(frame/15-2)), 0,49*floor(3-absolute(frame/15-2)), 80);
         SetGraphicScale(1, 1);
         DrawGraphic(GetX, GetY+sin(frame*3)*10);
      }
   }
   @Finalize{
      DeleteGraphic(ImgBoss);
   }
}

script_event talk{
   let imgPatchy = "..\images\imgPatchy.png";
   let imgReimu = "..\images\imgReimu.png";
   let imgMarisa = "..\images\imgMarisa.png";
   let event=1;
   @Initialize{
      LoadGraphic(imgPatchy);
      LoadGraphic(imgReimu);
      LoadGraphic(imgMarisa);
   }
   @MainLoop{
alternative( GetPlayerType() )
case( MARISA_A, MARISA_B ){
   TextOutA("\c[BLUE]...Hey...");
   SetChar(RIGHT,imgPatchy);
           SetGraphicRect(RIGHT,1,1,127,255);
   MoveChar(RIGHT,FRONT);
           SetNameFromText(RIGHT,TEXT_RED,"Patchouli Knowledge","The Unmoving Great Library");
   TextOutA("\c[BLUE]Hi Marisa!\nYou want to 'borrow' books again?");
           DeleteName(RIGHT);
   SetChar(LEFT,imgMarisa);
           SetGraphicRect(LEFT,127,1,255,255);
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   TextOutA("\c[RED]Well... You seem to want to aruge it a lot...");
   TextOutA("\c[RED]In fact, I am treated as a thief each time I enter the mansion.");
   TextOutA("\c[RED]Even the Aya accused me of that!!!");
           MoveChar(RIGHT,FRONT);
   MoveChar(LEFT,BACK);
   SetChar(RIGHT,imgPatchy);
           SetGraphicRect(RIGHT,127,1,255,255);
   TextOutA("\c[BLUE]You are.");
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   SetChar(LEFT,imgMarisa);
           SetGraphicRect(LEFT,1,1,127,255);
   TextOutA("\c[RED]Anyway, I'll be free to enter or leave this mansion freely if I defeat you.");
   TextOutA("\c[RED]And every time along with my leaving, I'll borrow 10 books.");
           MoveChar(RIGHT,FRONT);
   MoveChar(LEFT,BACK);
           SetGraphicRect(RIGHT,1,1,127,255);
   SetChar(RIGHT,imgPatchy);
   TextOutA("\c[BLUE]You must be dreaming.\nYou won't defeat me.");
           MoveChar(LEFT,FRONT);
   MoveChar(RIGHT,BACK);
   SetChar(LEFT,imgMarisa);
           SetGraphicRect(LEFT,127,1,255,255);
   TextOutA("\c[RED]We'll see. Just like I defeated you many times ago!");
}
End();
        event=0;
   }
   @Finalize{
      DeleteGraphic(imgMarisa);
      DeleteGraphic(imgPatchy);
      DeleteGraphic(imgReimu);
   }
}

The enemy is displayed but the event doesn't end. The whole plural script stucks there. Why?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 11, 2009, 06:06:26 AM
The enemy is displayed but the event doesn't end. The whole plural script stucks there. Why?
Your dialogue file is setup terribly wrong

1) Give the boss 1 or 10 life.
2) Remove that End(); line. It is wrong.
3) In the 'event_script' section set the following line where you want the dialogue to end and the fight to start:  SetStep(x);  where x is a number. Example: SetStep(1); ( multiple steps are possible ).
4) In the 'enemy_script_main' set an if-statement listening to the step. if(GetEventStep==1){AddLife-50;}

So what happens here? The dialogue is spoken and SetStep is set to '1'. In the MainLoop, the statement will become true, thus it will subtract 50 life off the boss. The boss is 'killed' and the next line in the plural script is called.

Your plural script should also look like this:
#ScriptPath[.\Dialogue01.txt]  <--- Dialogue
#ScriptPath[.\Noncard01.txt]
#ScriptPath[.\Spellcard01.txt]
#ScriptNextStep
..

See my Afro boss which is done excactly the same.

( ps didn't I explained you this before somewhere on page 17 or so ? )
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 11, 2009, 10:33:46 AM
The problem is finally solved...

(It seems that it was not me and I didn't intend to make a talking script as I did not even know about yield;)

Thank, Helepolis
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on September 12, 2009, 03:20:47 AM
I have a question... how do you make the screen shake? like when minamitu murasa's anchors hit the edge of the screen... tnx in advance
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on September 12, 2009, 03:25:39 AM
My guess is you have to basically redraw everything; the background, the boss, the player, etc. I'm not sure how you would get the bullets to shake unless you used object bullets or something... But yeah if you tried it this way it would take ages.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on September 12, 2009, 03:40:22 AM
I have a question... how do you make the screen shake? like when minamitu murasa's anchors hit the edge of the screen... tnx in advance
Code: [Select]
let variable = 0;
let shakeboolean = false;
let xshake = 0;
let yshake = 0;

...

@Initialize {
...
LoadImage("script\img\thisistheimage.png");
...
}
@MainLoop {
...
if(insert some conditions here) {
shakeboolean = true;
} else {
shakeboolean = false;
}
if(shakeboolean == true) {
statements to alter xshake and yshake;
} else {
xshake = 0; yshake = 0;
}
...
}

...

@BackGround {
SetTexture("script\img\thisistheimage.png");
SetGraphicRect(left, top, right, bottom);
otherstuff;
DrawGraphic(x-coordinate to put the center of the image + xshake, y-coordinate to put the center of the image + yshake);

I think...  :-[
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on September 12, 2009, 03:43:06 AM
That would only make the background shake, not the whole screen.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on September 12, 2009, 04:16:09 AM
Thanks! even though it's only making the background shake... I think I could use this... I don't really need the other things to shake anymore...  ;D
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 12, 2009, 05:12:55 AM
The Select() function in Danmakufu can only allow 2 choice.

Is there anyway to make more than 2 choice? (In event script)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 12, 2009, 07:37:48 AM
The only quite close immitated shaking I have seen was in CaSercan's EoSD Phantasm game. Meiling used a laser attack which shakes before it breaks into bullets. I was quite impressed by the effect.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on September 13, 2009, 05:45:36 AM
That would only make the background shake, not the whole screen.
But if you want everything shake, you also need to make the bullets shake, too, and would be annoying, wouildn't it?
Um.. yeah.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: skutieos on September 13, 2009, 06:59:18 PM
Im trying to run it, I installed applocale, and Japanese wasn't on the drop down list. Then I tried installing the japanese language files from the windows XP cd. It installed fine (I think) but Japanese is still not on the list. What should I do?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 13, 2009, 07:33:06 PM
Im trying to run it, I installed applocale, and Japanese wasn't on the drop down list. Then I tried installing the japanese language files from the windows XP cd. It installed fine (I think) but Japanese is still not on the list. What should I do?

Did you look all the way at the bottom? It's written in Japanese characters, so try using the last option if that looks unreadable to you.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: skutieos on September 13, 2009, 08:02:42 PM
Im trying to run it, I installed applocale, and Japanese wasn't on the drop down list. Then I tried installing the japanese language files from the windows XP cd. It installed fine (I think) but Japanese is still not on the list. What should I do?

Did you look all the way at the bottom? It's written in Japanese characters, so try using the last option if that looks unreadable to you.

Yes, I tried all the ones at the bottom, every time it said something like "your system can't run that language" or something.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on September 14, 2009, 01:49:10 AM
When using #include_script, is there any way to actually change the included script from the script that receives the data or does it only take everything from the script adn make a copy of it in the script with #include_script in it?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on September 15, 2009, 12:57:47 AM
I know there IS a way to enable/disable shooting/bombing, but is there a way to get whether shooting/bombing is enabled/disabled?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on September 15, 2009, 02:31:16 AM
I know there IS a way to enable/disable shooting/bombing, but is there a way to get whether shooting/bombing is enabled/disabled?
Since enabling/disabling shooting/bombing is manual, you can simply make a variable (like isDisabled or something) and make it True whenever you enable and False when ever you disable.

Then just pull out that variable when you want to know if it's enabled or disabled.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on September 15, 2009, 04:21:53 AM
The Select() function in Danmakufu can only allow 2 choice.

Is there anyway to make more than 2 choice? (In event script)

Actually, no, but...

Code: [Select]
#TouhouDanmakufu
#Title[MENU FTW]
#Text[This is the description. Did you know that? Oh, sorry.]
#Player[FREE]
#ScriptVersion[2]
script_enemy_main {
    let number = 0;
    let orange = [255, 142, 78];
    let white = 255;
    let r1 = 0; let g1 = 0; let b1 = 0;
    let r2 = 0; let g2 = 0; let b2 = 0;
    let r3 = 0; let g3 = 0; let b3 = 0;
    @Initialize {
        SetLife(1);
    }

    @MainLoop {
    //////////////////////////////////
    ForbidBomb(true); ForbidShot(true);
    ///////////////////////////////////
    if(number == 0) {
    r1 = white; g1 = white; b1 = white;
    r2 = orange[0]; g2 = orange[1]; b2 = orange[2];
    r3 = orange[0]; g3 = orange[1]; b3 = orange[2];
    }
    if(number == 1) {
    r2 = white; g2 = white; b2 = white;
    r1 = orange[0]; g1 = orange[1]; b1 = orange[2];
    r3 = orange[0]; g3 = orange[1]; b3 = orange[2];
    }
    if(number == 2) {
    r3 = white; g3 = white; b3 = white;
    r1 = orange[0]; g1 = orange[1]; b1 = orange[2];
    r2 = orange[0]; g2 = orange[1]; b2 = orange[2];
    }
    ///////////////////////////////////
    if(number < 0) {
    number = 0;
    }
    if(number > 2) {
    number = 2;
    }
    if(GetKeyState(VK_UP) == KEY_PUSH) {
    number--;
    }
    if(GetKeyState(VK_DOWN) == KEY_PUSH) {
    number++;
    }
    //////////////////////////////////
    if(GetKeyState(VK_SHOT)==KEY_PUSH) {
VanishEnemy;
    //Here you put stuff that happens depending what the variable "number" finally is, blah, blah, blah
    }
    }
    @DrawLoop {
               SetFontColor(r1, g1, b1, r1, g1, b1);
DrawText("The first choice", 40, 45, 20, 255);
               SetFontColor(r2, g2, b2, r2, g2, b2);
DrawText("Choice 2", 40, 65, 20, 255);
               SetFontColor(r3, g3, b3, r3, g3, b3);
DrawText("Choice 3", 40, 85, 20, 255);
    }

    @Finalize {
    ForbidBomb(false); ForbidShot(false);
    SetPlayerX(GetCenterX); SetPlayerY(GetClipMaxY-75);
    }
}

But I think I did something entirely wrong here...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 15, 2009, 10:32:30 AM
Maybe the player shouldn't move when making the choice.
Thanks for your help.
I'm thinking in this way now :)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Lishy1 on September 15, 2009, 01:35:51 PM
As of yesterday, danmakufu just started crashing with a majority of scripts. Both player AND boss.
even the default danmakufu exrumia, as well as the ctc chars, even rumia itself.
I'm using applocal and it crashes whenever you get to the select screen. Such as the exrumia folder when browsing via directory, or the char select screen.
I've made sure I had applocal in japanese for Danmakufu.

Yeah, this has only been happening since yesterday
 I don't know what caused it, but all I did was install the dll needed to play touhou 11, and something I used to rip primeus gfx from mugen(Though I uninstalled it)

I tried reinstalling danmakufu fresh, with only the defaults like the rumia scripts. But the problem still persists.
Specifically, the crash is a "send error report" crap. Not even an error.

I have no clue why this is happening and only recently. But this is a very bad PC that has been becoming worse and worse over time. I wouldn't be surprised if it is my pc since I doubt the original danmakufu is corrupt. Still. Has anyone heard of this problem before?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 15, 2009, 03:11:33 PM
When using #include_script, is there any way to actually change the included script from the script that receives the data or does it only take everything from the script adn make a copy of it in the script with #include_script in it?

Permanently, not really, but if you used an intricate series of Set- and Get-CommonData, then you could probably do it. Wouldn't be feasable for more than one script though.

@Lishy:
Have you tried setting your computer's localization to Japanese (in the control panel)? Might screw over some other programs though. Generally if you have an old computer and it's fucking up everwhere, it's time to get a new one.
Title: corrupt music
Post by: Infy♫ on September 15, 2009, 05:33:48 PM
I've got like, 7 albums of awesome music with some songs which really fit shooting games. however when i try to use these songs for danmakufu, it often crashes with no warning.
what can i do to fix this? converting them to ogg format simply doesnt help.
Title: Re: corrupt music
Post by: Johnny Walker on September 15, 2009, 06:56:31 PM
I've got like, 7 albums of awesome music with some songs which really fit shooting games. however when i try to use these songs for danmakufu, it often crashes with no warning.
what can i do to fix this? converting them to ogg format simply doesnt help.

Try converting the files to "44Khz -128 kpbs (or less) - Stereo " . That works for me.
I use 96kbps for a 'nice quality-low weight relationship' in my scripts.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Lishy1 on September 16, 2009, 01:25:09 AM
So I got my new vista hp laptop and I installed danmakufu.
Problem? It takes a long time to load up, only ending up to be (Not responding) then it gets the "send error message" crash error that usually happens when something crashes.
I have both the Japanese IME and and applocal. But even if I use either of them, it still crashes.

Other times, it opens as a process shown in task manager, but technically doesn't "open", if you know what I mean.

.......Halp?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Johnny Walker on September 16, 2009, 08:27:57 AM
Well. I have a little problem creating a "Dream Bonus" like function (Base stolen(?) from Naut's Yuka Kazami Extra Graze Bonus).
I want to put a penalty for bomb use but I can't do it well.
Here's the base code for a stage script:

Code: [Select]
@MainLoop(){
//Dreamer Bonus
Dream = (GetGraze*20);//Test number
if(Dream >=100){Dream = 100;}
if(Dream >= 100 && DreamMax == true){
        DeleteEnemyShotToItem(SHOT);
        DreamMax = false;
                }
if(Dream < 100 && DreamMax == false){DreamMax = true;}
if(Dream<=0){Dream = 0;}

if(OnBomb==true){Dream-=20}  // <-----THIS?
yield;

}

And here is the problem:

Every time I bomb, the line works, but when the "OnBomb==true" dissapears, that "Dream-=20" too.

Let me explain:

1 - Graze: Dream at 50 %.
2 - Bomb: Dream  -20% = 30%
3 - Bomb Ends... Dream at 50 % again...


The Drawing functions...
Code: [Select]

@DrawTopObject{
      let string = "" ~ ToString(Dream);
      let n = 0.0;
      let res = "";

      while (n < length(string) && string[n] != '.'){

         res = res ~ ToString(string[n]);
         n++;

      }

//Draw Text
if(Dream<=99){DrawText(res , 37, 425, 12, 255);}
if(Dream>=100){DrawText("MAX" , 37, 425, 12, 255);}
DrawText("%" , 65, 425, 12, 255);
DrawText("Dreamer Bonus:", 37, 410, 12, 255);

}


I know I'm doing it wrong, but I can't find any solution.
This is making me crazy. Please, help me MoTK. Thank you.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 16, 2009, 01:58:24 PM
I'm not entirely sure what you're trying to accomplish (some fusion between Mystic Square and Subterranean Animism's point system?), but it seems to me that the reason your Dream bonus keeps maxing after you bomb is because Dream keeps getting set to 100 (Dream = GetGraze*20) as long as you have more than 5 graze. So even though you're setting it lower during the bomb phase, it keeps getting set back to normal every frame, and will always be maxed so long as you remain above 5 graze.

To accomplish what I think you're trying to do, you would need to find the difference between your graze a few frames beforehand and your current graze (which would likely involve tasks), this way your Dream bonus would actually drop if you aren't actively grazing.

EDIT:
Something like this maybe...?

Code: [Select]
#TouhouDanmakufu
#Title[gggggggg]
#Text[ggggg]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {

    let ImgBoss = "script\img\ExRumia.png";
let Dream = 0;
let DreamMax = true;
let g2 = 0;
let h = 250;

    @Initialize {
        SetLife(6000);
        SetTimer(120);
        SetScore(1000000);
        SetMovePosition02(GetCenterX, GetCenterY - 120, 120);
        SetDamageRate(75, 0);
        LoadGraphic(ImgBoss);
Grazer;
    }

    @MainLoop {
Grazer;
CreateShot01(GetX, GetY, 3, 0, RED01, 10);
   Dream = g2;
   if(Dream >=100){Dream = 100;}
   if(Dream >= 100 && DreamMax == true){
           DeleteEnemyShotToItem(SHOT);
           DreamMax = false;
   }
   if(Dream < 100 && DreamMax == false){DreamMax = true;}
   if(Dream<=0){Dream = 0;}

   if(OnBomb==true){Dream-=20; DreamMax=true;}  // <-----THIS?
      yield;   
   

        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        yield;
       
    }

    @DrawLoop {
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 64, 64);
        DrawGraphic(GetX, GetY);
let string = "" ~ ToString(Dream);
      let n = 0.0;
      let res = "";

      while (n < length(string) && string[n] != '.'){

         res = res ~ ToString(string[n]);
         n++;
   
      }
   
   //Draw Text
   if(Dream<=99){DrawText(res , 37, 425, 12, 255);}
   if(Dream>=100){DrawText("MAX" , 37, 425, 12, 255);}
   DrawText("%" , 65, 425, 12, 255);
   DrawText("Dreamer Bonus:", 37, 410, 12, 255);

}

task Grazer{
let g = GetGraze;
loop(h){yield;}
g2 = GetGraze - g;
if(g2==0){
h--;
}
if(g2>0){
h++;
}
if(h<=250){
h=250;
}
if(h>=450){
h=450;
}
}


    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }


The line of bullets is to graze off of and test the code's effects.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 16, 2009, 02:43:17 PM
Talking about the 'multiple choice' event:

Code: [Select]
#TouhouDanmakufu
#Title[Menu test]
#Text[This is the description. Did you know that? Oh, sorry.]
#Player[FREE]
#ScriptVersion[2]
script_enemy_main {
    let ImgBoss = GetCurrentScriptDirectory~"images\patchouli.png";
    let bg = "";
    let frame=0;
    let number = 0;
    let orange = [255, 142, 78];
    let white = 255;
    let finish=0;
    let r1 = 0; let g1 = 0; let b1 = 0;
    let r2 = 0; let g2 = 0; let b2 = 0;
    let r3 = 0; let g3 = 0; let b3 = 0;
    let r=[0,0,0,0,0];
    let g=[0,0,0,0,0];
    let b=[0,0,0,0,0];
    let x=GetPlayerX;
    let y=GetPlayerY;
    SetX(GetCenterX);
    SetY(GetClipMinY+120);
    @Initialize {
       SetLife(1);
       MagicCircle(false);
    }

    @MainLoop {
       ForbidBomb(true);
       ForbidShot(true);
       SetPlayerX(x);
       SetPlayerY(y);
       ascent(i in 0..5){
  r[i]=orange[0];
  g[i]=orange[1];
  b[i]=orange[2];
       }
       r[number]=255;
       g[number]=255;
       b[number]=255;
       if(GetKeyState(VK_UP)==KEY_PUSH && number>0) {
          number--;
       }
       if(GetKeyState(VK_DOWN)==KEY_PUSH && number<4) {
          number++;
       }
       if(GetKeyState(VK_SHOT)==KEY_PUSH){
  alternative(number)
  case(0){
  }
  case(1){
  }
  case(2){
  }
  case(3){
  }
  case(4){
  }
  finish=1;
       }
       frame++;
       if(finish==1){AddLife(-10);}
    }
    @DrawLoop{
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicAngle(0, 0, 0);
       SetGraphicRect(49*floor(2-absolute(frame/15-2)), 0, 49*floor(3-absolute(frame/15-2)), 80);
       SetGraphicScale(1, 1);
       DrawGraphic(GetX, GetY);
       SetFontColor(r[0], g[0], b[0], r[0], g[0], b[0]);
       DrawText("Choice 1", GetClipMinX+60, GetClipMaxY-120, 15, 255);
       SetFontColor(r[1], g[1], b[1], r[1], g[1], b[1]);
       DrawText("Choice 2", GetClipMinX+60, GetClipMaxY-105, 15, 255);
       SetFontColor(r[2], g[2], b[2], r[2], g[2], b[2]);
       DrawText("Choice 3", GetClipMinX+60, GetClipMaxY-90, 15, 255);
       SetFontColor(r[3], g[3], b[3], r[3], g[3], b[3]);
       DrawText("Choice 4", GetClipMinX+60, GetClipMaxY-75, 15, 255);
       SetFontColor(r[4], g[4], b[4], r[4], g[4], b[4]);
       DrawText("Choice 5", GetClipMinX+60, GetClipMaxY-60, 15, 255);
    }
    @Finalize {
       ForbidBomb(false);
       ForbidShot(false);
    }
}
(Note that this is not an event script)
The above demonstrates how 5 choices can be made (modified from above), but still you cannot use #ScriptPath[...] inside the alternative control statement.
The (probably) only way to solve the problem is to use SetCommonData? (Can SetCommonData be used in plural script?)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Lishy1 on September 16, 2009, 06:17:54 PM
So I got my new vista hp laptop and I installed danmakufu.
Problem? It takes a long time to load up, only ending up to be (Not responding) then it gets the "send error message" crash error that usually happens when something crashes.
I have both the Japanese IME and and applocal. But even if I use either of them, it still crashes.

Other times, it opens as a process shown in task manager, but technically doesn't "open", if you know what I mean.

.......Halp?
Just for the sake of providing more info and that someone will have a greater chance of helping me, here's the problem details:
Problem signature:
  Problem Event Name:   APPCRASH
  Application Name:   th_dnh.exe
  Application Version:   0.0.0.0
  Application Timestamp:   45293ba4
  Fault Module Name:   th_dnh.exe
  Fault Module Version:   0.0.0.0
  Fault Module Timestamp:   45293ba4
  Exception Code:   c0000005
  Exception Offset:   000050ac
  OS Version:   6.0.6001.2.1.0.768.2
  Locale ID:   4105
  Additional Information 1:   7484
  Additional Information 2:   44aabdaab8bebc883a520397c81b786c
  Additional Information 3:   b637
  Additional Information 4:   d8a80cf26ab7da46d94762599887f105

That probably won't help, but meh. Maybe...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Johnny Walker on September 16, 2009, 06:29:04 PM
I'm not entirely sure what you're trying to accomplish (some fusion between Mystic Square and Subterranean Animism's point system?), but it seems to me that the reason your Dream bonus keeps maxing after you bomb is because Dream keeps getting set to 100 (Dream = GetGraze*20) as long as you have more than 5 graze. So even though you're setting it lower during the bomb phase, it keeps getting set back to normal every frame, and will always be maxed so long as you remain above 5 graze.

To accomplish what I think you're trying to do, you would need to find the difference between your graze a few frames beforehand and your current graze (which would likely involve tasks), this way your Dream bonus would actually drop if you aren't actively grazing.

<code here>

The line of bullets is to graze off of and test the code's effects.

Very thank you Naut! You saved my script. I love you D:
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 16, 2009, 07:52:19 PM
I love you too <3
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Lopsidation on September 16, 2009, 08:43:23 PM
Right now I'm trying to script a series of cards for Youmu where each of the bullets are half-ghosts, so you only die if you're hitting two of them at once.
My plan is to make the player invincible and manually test collisions with each bullet.
1. How do you make the player invincible without making them destroy every bullet they touch?
2. Will the manual collision detection slow Danmakufu down horribly?
3. Is there any way to make the bullets slightly trasparent so you can better see where two of them overlap?
4. Or is this just generally a terrible idea?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on September 17, 2009, 02:50:07 AM
Talking about the 'multiple choice' event:

Code: [Select]
#TouhouDanmakufu
#Title[Menu test]
#Text[This is the description. Did you know that? Oh, sorry.]
#Player[FREE]
#ScriptVersion[2]
script_enemy_main {
    let ImgBoss = GetCurrentScriptDirectory~"images\patchouli.png";
    let bg = "";
    let frame=0;
    let number = 0;
    let orange = [255, 142, 78];
    let white = 255;
    let finish=0;
    let r1 = 0; let g1 = 0; let b1 = 0;
    let r2 = 0; let g2 = 0; let b2 = 0;
    let r3 = 0; let g3 = 0; let b3 = 0;
    let r=[0,0,0,0,0];
    let g=[0,0,0,0,0];
    let b=[0,0,0,0,0];
    let x=GetPlayerX;
    let y=GetPlayerY;
    SetX(GetCenterX);
    SetY(GetClipMinY+120);
    @Initialize {
       SetLife(1);
       MagicCircle(false);
    }

    @MainLoop {
       ForbidBomb(true);
       ForbidShot(true);
       SetPlayerX(x);
       SetPlayerY(y);
       ascent(i in 0..5){
  r[i]=orange[0];
  g[i]=orange[1];
  b[i]=orange[2];
       }
       r[number]=255;
       g[number]=255;
       b[number]=255;
       if(GetKeyState(VK_UP)==KEY_PUSH && number>0) {
          number--;
       }
       if(GetKeyState(VK_DOWN)==KEY_PUSH && number<4) {
          number++;
       }
       if(GetKeyState(VK_SHOT)==KEY_PUSH){
  alternative(number)
  case(0){
  }
  case(1){
  }
  case(2){
  }
  case(3){
  }
  case(4){
  }
  finish=1;
       }
       frame++;
       if(finish==1){AddLife(-10);}
    }
    @DrawLoop{
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicAngle(0, 0, 0);
       SetGraphicRect(49*floor(2-absolute(frame/15-2)), 0, 49*floor(3-absolute(frame/15-2)), 80);
       SetGraphicScale(1, 1);
       DrawGraphic(GetX, GetY);
       SetFontColor(r[0], g[0], b[0], r[0], g[0], b[0]);
       DrawText("Choice 1", GetClipMinX+60, GetClipMaxY-120, 15, 255);
       SetFontColor(r[1], g[1], b[1], r[1], g[1], b[1]);
       DrawText("Choice 2", GetClipMinX+60, GetClipMaxY-105, 15, 255);
       SetFontColor(r[2], g[2], b[2], r[2], g[2], b[2]);
       DrawText("Choice 3", GetClipMinX+60, GetClipMaxY-90, 15, 255);
       SetFontColor(r[3], g[3], b[3], r[3], g[3], b[3]);
       DrawText("Choice 4", GetClipMinX+60, GetClipMaxY-75, 15, 255);
       SetFontColor(r[4], g[4], b[4], r[4], g[4], b[4]);
       DrawText("Choice 5", GetClipMinX+60, GetClipMaxY-60, 15, 255);
    }
    @Finalize {
       ForbidBomb(false);
       ForbidShot(false);
    }
}
(Note that this is not an event script)
The above demonstrates how 5 choices can be made (modified from above), but still you cannot use #ScriptPath[...] inside the alternative control statement.
The (probably) only way to solve the problem is to use SetCommonData? (Can SetCommonData be used in plural script?)

#ScriptPath[] as in the one you use in the plural scripts...? (insert here: a colon followed by a capital V)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 17, 2009, 08:16:07 AM
Yes. (As I'm making a project, when in the middle of the fight, players are asked with 'choice' to choose, then the spell card changes according to the choice)

Right now I'm trying to script a series of cards for Youmu where each of the bullets are half-ghosts, so you only die if you're hitting two of them at once.
My plan is to make the player invincible and manually test collisions with each bullet.
1. How do you make the player invincible without making them destroy every bullet they touch?
2. Will the manual collision detection slow Danmakufu down horribly?
3. Is there any way to make the bullets slightly trasparent so you can better see where two of them overlap?
4. Or is this just generally a terrible idea?
To your first problem, you can use ShootDownPlayer (in here (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Miscellaneous_Functions) even the bullets is destroyed.

2. You will need to detect collision for all bullets and player, this (well, of course) slows down Danmakufu a lot.

3. You can use object bullets (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Object_Control_Functions#Obj_SetAlpha) to make them transparent and also to detect their collision.

4. This idea is not bad, don't worry. It is cool if you can make it correctly and neatly. But bear in mind that the difficulty is lowered as player has to hit 2 bullets simultaneously to die.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on September 17, 2009, 05:07:27 PM
Lopsidation: I think the best way to do that card is, rather than comparing every bullet's position against every other, have each bullet just check for its own collision against the player, and if it's true have it set a variable declaring it; then the other bullet type can check for collision and if that variable is true, you know they're both hitting and you can use ShootDownPlayer.

Also, be sure to set the variable to false each loop before running through the collision detections so that it's being unset once a bullet isn't on you anymore.

Oh one more thing, I don't know how you plan to do it but make sure it's somehow communicated to the player that touching two bullets is what will kill them; if I started playing a card with transparent bullets that didn't hit me I probably wouldn't be able to figure out why I was dying.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 17, 2009, 07:32:36 PM
I have a question regarding reflecting bullets.
I set up this piece of script:

Code: [Select]
if(Obj_GetX(obj)<=GetClipMinX) {
Obj_SetAngle(obj,180-Obj_GetAngle(obj));
Obj_SetX(obj,Obj_GetX(obj)+0.1);
}
if(Obj_GetX(obj)>=GetClipMaxX) {
Obj_SetAngle(obj,180-Obj_GetAngle(obj));
Obj_SetY(obj,Obj_GetY(obj)-0.1);
}

//The above reflect horizontally. Below is supposed to do it vertically, except it doesn't.

if(Obj_GetY(obj)<=GetClipMinY) {
Obj_SetAngle(obj,180+Obj_GetAngle(obj));
Obj_SetY(obj,Obj_GetY(obj)-0.1);
}
if(Obj_GetY(obj)>=GetClipMaxY) {
Obj_SetAngle(obj,180+Obj_GetAngle(obj));
Obj_SetX(obj,Obj_GetX(obj)+0.1);
}

I tried doing all sorts of stuff to enable vertical reflection, but whatever I try, the outcome it either:
-The bullets sink into the top/bottom of the screen upon contact.
Or -They reflect, but in the exact opposite direction for both Y and X, and not just Y alone.

What did I do wrong?

As for the whole script, it goes something likes this...:

Code: [Select]
#TouhouDanmakufu
#Title[Test 2]
#Text[(***)]
#Player[FREE]
#Image[script\Images\Faces\.png]
#ScriptVersion[2]

script_enemy_main {

let angle=0;
let shift=0;
let enemies=[];
let usespell=0;
let bgfade=0;
let frame=0;
let time=0;
let timercount=0;
let cx=GetCenterX;
let cy=GetCenterY;
let enemylife=0;
let lowhealth1=("script\SoundEffects\lowhealth1.wav");
let lowhealth2=("script\SoundEffects\lowhealth2.wav");
let timeout1=("script\SoundEffects\timeout1.wav");
let timeout2=("script\SoundEffects\timeout2.wav");
let BG1=("\script\Images\BackgroundLayers\kurumi1.png");
let Portrait=("\script\Images\Faces\KurumiNorm1.png");
let Boss=("\script\Images\CharacterSprites\KurumiNorm.png");

@Initialize{
LoadUserShotData("script\shots\Shots1Pos.txt");
LoadGraphic(Boss);
LoadGraphic(BG1);
LoadGraphic(Portrait);
LoadSE(lowhealth1);
LoadSE(lowhealth2);
LoadSE(timeout1);
LoadSE(timeout2);

CutIn(YOUMU,""\"""\",Portrait,0,0,200,520);
SetScore(500000);
SetLife(500);
SetTimer(50);
SetGraphicRect(0,0,96,96);
SetInvincibility(30);
SetDamageRate(10,10);
SetEnemyMarker(true);
MagicCircle(true);
SetColor(255,160,200);
Concentration01(60);
Concentration02(60);
SetColor(255, 255, 255);
SetEffectForZeroLife(60,100,1);
SetMovePosition02(cx,cy-170,50);
// LastSpell;
}

@MainLoop {

SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

SetShotAutoDeleteClip(64,64,64,64);



if(frame%80==0 && frame>60){
loop(30){
let enemy=Obj_Create(OBJ_SHOT);
Obj_SetPosition(enemy,cx,cy);
ObjShot_SetGraphic(enemy,RED01);
Obj_SetSpeed(enemy,2);
Obj_SetAngle(enemy,shift+angle);
Obj_SetAutoDelete(enemy,true);

enemies=enemies~[enemy];
angle+=360/30;
}
cx=rand(GetClipMinX+50,GetClipMaxX-50);
cy=rand(GetClipMinY+50,GetClipMaxY-200);
shift+=1;
}
let i=0;
while (i<length(enemies)){
if(Obj_BeDeleted(enemies[i])){
enemies=erase(enemies,i);
i--;
}
else{
let obj=enemies[i];
if(Obj_GetX(obj)<=GetClipMinX) {
Obj_SetAngle(obj,180-Obj_GetAngle(obj));
Obj_SetX(obj,Obj_GetX(obj)+0.1);
}
if(Obj_GetX(obj)>=GetClipMaxX) {
Obj_SetAngle(obj,180-Obj_GetAngle(obj));
Obj_SetY(obj,Obj_GetY(obj)-0.1);
}

if(Obj_GetY(obj)<=GetClipMinY) {
Obj_SetAngle(obj,180+Obj_GetAngle(obj));
Obj_SetY(obj,Obj_GetY(obj)-0.1);
}
if(Obj_GetY(obj)>=GetClipMaxY) {
Obj_SetAngle(obj,180+Obj_GetAngle(obj));
Obj_SetX(obj,Obj_GetX(obj)+0.1);
}



}
i++;
}




time++;
frame++;

if(GetLife<50 && (time-3)%4==0){ enemylife=GetLife; }
if(GetLife<enemylife && (time-0)%4==0){ PlaySE(lowhealth1);
 }
if(GetLife<enemylife && (time-2)%4==0){ PlaySE(lowhealth2);
 }

if(GetTimer<=10 && GetTimer>3 && time%60==0){ PlaySE(timeout1); }
if(GetTimer<=3 && time%60==0 && timercount<3){ PlaySE(timeout2);
 timercount+=1; }

}

@BackGround{
if(bgfade<70){bgfade+=5;}

SetGraphicRect(0,0,512,512);
SetGraphicScale(1.5,1.5);
SetTexture(BG1);
SetAlpha(50);
SetColor(255,255,255);
SetRenderState(ALPHA);
SetGraphicAngle(0,0,-(time/3));
DrawGraphic(cx,cy);
}

@DrawLoop{
SetGraphicRect(1,1,96,96);
SetGraphicScale(1,1);
SetTexture(Boss);
SetGraphicAngle(0, 0, 0);
SetColor(255,255,255);
SetRenderState(ALPHA);
SetGraphicAngle(0, 0, 0);

if(usespell>0){SetGraphicRect(288,0,384,96);
DrawGraphic(GetX, GetY);}

if(usespell==0){if(GetSpeedX==0){SetGraphicRect(0,0,96,96);}
else if(GetSpeedX>0){SetGraphicRect(192,0,288,96);}
else if(GetSpeedX<0){SetGraphicRect(96,0,192,96);}
DrawGraphic(GetX, GetY);}}
}

@Finalize{
DeleteGraphic(Portrait);
DeleteGraphic(Boss);
DeleteSE(lowhealth1);
DeleteSE(lowhealth2);
DeleteSE(timeout1);
DeleteSE(timeout2);
}

}


Which reminds me of my 2nd question:
What do I need to do to make each sepparate bullet take another action after a certain amount of frames of existance?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on September 17, 2009, 07:42:28 PM
I have a question regarding reflecting bullets.
Reflecting bullets is a bit strange. For reflection off of the sides, you have it right, but for the top and bottom, you need to make it Obj_SetAngle(obj,-Obj_GetAngle(obj));. I agree, it's a bit hard to wrap your head around how that works :P
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 17, 2009, 07:58:01 PM
I have a question regarding reflecting bullets.
Reflecting bullets is a bit strange. For reflection off of the sides, you have it right, but for the top and bottom, you need to make it Obj_SetAngle(obj,-Obj_GetAngle(obj));. I agree, it's a bit hard to wrap your head around how that works :P

Ah! I was so close! But I really didn't expect that you had to remove the 180 degrees thing.
Thanks man, I'll be sure to make a fun spellcard out of that info. ^_^v


Oh, just in case my whole previous post won't be forgotten now I got this answered. I have a 2nd question too:

What do I need to do to make each sepparate object bullet take another action after a certain amount of frames of existance? :3 (See previous post for the script)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on September 17, 2009, 08:09:39 PM
Code: [Select]
task objectbullet
{
let obj = Obj_Create(OBJ_SHOT);
let count = 200;
setting bullet stuff, blah blah;
while (count > 100)
{
do stuff;
count--;
yield;
}
loop(howlongyouwanttowait){yield;}
while(count > 0)
{
do more stuff;
count--;
yield;
}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 17, 2009, 10:26:59 PM
So... how do you make the screen shake? Bullets, player, and all (for a set amount of frames)?  Is there a way to do it without going through too much trouble?

A code would be nice.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 18, 2009, 12:25:01 AM
I bet you'll have to use tasks, and a variable shaking=1 (or 0), which indicates the shaking is occurring.

Then mark all bullet current position just before shaking (using e.g. xtemp, ytemp), then

Obj_SetPosition(xtemp+rand(-10,10), ytemp+rand(-10,10)); (for shots and lasers)

And SetPlayerX and SetPlayerY in similar way.

The background can be also shaked as well...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on September 18, 2009, 12:46:30 AM
The problem with your idea Henry is that everything will not just shake, but move around completely randomly. This would mess up most bullet patterns as well as cause random clipdeaths for an unlucky player. I see what you're trying to do with the "xtemp" variable, but how would you make your bullet move and shake at the same time (without some trig anyways)? Realistically, shaking the background is pretty much the only thing you can do without causing the player to get annoyed.
Code: [Select]
if (shaking == true){DrawGraphic(GetCenterX+rand(-4,4),GetCenterY+rand(-4,4));}
else{DrawGraphic(GetCenterX,GetCenterY);}
Just declare a variable "shaking", and set it to "true" whenever you want the effect.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on September 18, 2009, 01:04:28 AM
You could make the player shake too.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 18, 2009, 01:39:05 AM
Em.

As in marisa's SC's, the player, bullets, background all shake in the same direction.

another variable can be used to determine the shaking x=rand(-10,10), y=rand(-10,10);

Then I made this to demonstrate shaking of player and bullets:

Code: [Select]
#TouhouDanmakufu
#Title[Shaking "Vision error"]
#Text[...]
#Player[FREE]
#ScriptVersion[2]
script_enemy_main{
   let ImgBoss = "script\img\ExRumia.png";
   let frame = -120;
   let MAX=30;
   let i;
   let j;
   let x;
   let y;
   let xtemp=0;
   let ytemp=0;
   let playerX;
   let playerY;
   let shaking=0;
   @Initialize{
      SetLife(4000);
      SetTimer(60);
      SetScore(1000000);
      SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
      CutIn(YOUMU, "Shaking "\""Vision error"\", "", 0, 0, 0, 0);
      LoadGraphic(ImgBoss);
      SetTexture(ImgBoss);
      SetGraphicRect(0, 0, 64, 64);
      LoadUserShotData(GetCurrentScriptDirectory~"images\shot_All.txt");
   }
   @MainLoop{
      SetCollisionA(GetX, GetY, 32);
      SetCollisionB(GetX, GetY, 16);
      if(frame%80==20&&frame>0){
         ascent(i in 0..MAX){
            ascent(j in 0..8){
               Bullet(2, GetAngleToPlayer+i*360/MAX, j*8);
            }
         }
      }
      if(frame%240==40){
         shaking=1;
      }
      if(frame%240==140){
shaking=0;
      }
      if(frame%240>=40&&frame%240<140){
playerX=GetPlayerX-xtemp;
playerY=GetPlayerY-ytemp;
      }
      if(shaking==1){
xtemp=rand(-10,10);
ytemp=rand(-10,10);
SetPlayerX(playerX+xtemp);
SetPlayerY(playerY+ytemp);
      }
      frame++;
      yield;
   }
   @DrawLoop{
      DrawGraphic(GetX,GetY);
   }
   @Finalize{
      DeleteGraphic(ImgBoss);
   }
   task Bullet(v, angle, delay){
      loop(delay){yield;}
      let obj=Obj_Create(OBJ_SHOT);
      Obj_SetPosition(obj, GetEnemyX, GetEnemyY);
      Obj_SetSpeed(obj,0);
      Obj_SetAngle(obj,angle);
      ObjShot_SetGraphic(obj, 57);
      ObjShot_SetDelay(obj, 10);
      let objX=Obj_GetX(obj);
      let objY=Obj_GetY(obj);
      while(Obj_BeDeleted(obj)==false){
if(shaking==0){
    Obj_SetPosition(obj, objX, objY);
}else{
    Obj_SetPosition(obj, objX+xtemp, objY+ytemp);
}
objX+=cos(angle)*v;
objY+=sin(angle)*v;
yield;
      }
   }
}
The bullets does not shake in the way as same as the player. Why?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on September 18, 2009, 12:11:23 PM
I'm having another idea about the shaking thing.

(bullets is a array of bullets)
Code: [Select]
task shake(duration)
{
let sframe = 0;
while (sframe < duration)
{
xtemp=rand(-10,10);
    ytemp=rand(-10,10);
    SetPlayerX(GetPlayerX+xtemp);
    SetPlayerY(GetPlayerY+ytemp);
ascent(i in 0..length(bullets)-1)
{
Obj_SetPosition(bullets[i], Obj_GetX(bullets[i])+xtemp, Obj_GetY(bullets[i])+ytemp);
}
sframe++;
yield;

    SetPlayerX(GetPlayerX-xtemp);
    SetPlayerY(GetPlayerY-ytemp);
ascent(i in 0..length(bullets)-1)
{
Obj_SetPosition(bullets[i], Obj_GetX(bullets[i])-xtemp, Obj_GetY(bullets[i])-ytemp);
}
sframe++;
yield;
}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 18, 2009, 01:28:58 PM
Both your and my segment has a fundamental problem: The boss is not moved and this leads to distortion of bullet patterns.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 18, 2009, 01:40:01 PM
You know, this whole screen shaking thing should be MUCH easier because it has been used so many times in Anaki script ( yes , that one. ).

I downloaded the aniki script and started analysing it yesterday but stopped because it was bed time.

It seriously should be easier somehow.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on September 18, 2009, 01:48:34 PM
Both your and my segment has a fundamental problem: The boss is not moved and this leads to distortion of bullet patterns.

SetX(GetX + xtemp);
SetY(GetY + ytemp);

Problem solved.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 18, 2009, 02:45:20 PM
(Can you post the whole script here? I'm having problem in successfully making it :()

Code: [Select]
#TouhouDanmakufu
#Title[Moon-Metal Sign "Sunshine reflector"]
#Text[The danmaku version of the card with same name in SWR]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = -120;
    let bg = GetCurrentScriptDirectory~"images\Bossbggrey.jpg";
    let random;
    let i;
    let j;
    let radius;
    let bullets=[];
    let size=0;
    #include_function "..\drawing.txt"
    @Initialize {
       SetLife(1500);
       SetTimer(60);
       SetScore(1000000);
       SetDamageRate(25,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "Moon-Metal Sign "\""Sunshine reflector"\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        if(frame==60){
           ascent(i in 0..6){
      Laser(GetX+cos(GetAngleToPlayer+i*360/6)*60, GetY+sin(GetAngleToPlayer+i*360/6)*60, GetAngleToPlayer+i*360/6-120, 60, 0, 60, 1);
      Laser(GetX+cos(GetAngleToPlayer+i*360/6)*60, GetY+sin(GetAngleToPlayer+i*360/6)*60, GetAngleToPlayer+i*360/6, 60, 0, 60, 2);
              ascent(j in 0..6){
                 
              }
           }
        }
if(frame==120){
   ascent(i in 0..7){
      ascent(j in 0..6){
ShootBullet(GetX, GetY, 1, GetAngleToPlayer+i*360/7, 10+j*5, 11, size);
      }
   }
}
        frame++;
        yield;
    }

    @DrawLoop {
       bossSC;
    }
    @BackGround{
       backgroundSC;
    }
    task Laser(x,y,angle,length,delay,delay2,type){
       loop(delay){yield;}
       let obj=Obj_Create(OBJ_LASER);
       Obj_SetPosition(obj, x, y);
       Obj_SetAngle(obj, angle);
       Obj_SetSpeed(obj, 0);
       ObjLaser_SetLength(obj, length);
       ObjLaser_SetWidth(obj, 10);
       ObjLaser_SetSource(obj, false);
       ObjShot_SetGraphic(obj, 160);
       Obj_SetCollisionToObject(obj,true);
       if(type==2){
          ObjShot_SetGraphic(obj, 158);
       }
       if(type==3){
  ObjShot_SetGraphic(obj, 153);
       }

       ObjShot_SetDelay  (obj, delay2);
       while(Obj_BeDeleted(obj)==false&&frame>120){
  ascent(i in 0..size){
             if(Collision_Obj_Obj(obj, bullets[i])==1){
        if(type==2){
   Obj_SetAngle(bullets[i], 2*Obj_GetAngle(obj)-Obj_GetAngle(bullets[i]));
}
if(type==3){
   ShootBullet(Obj_GetX(bullets[i]), Obj_GetY(bullets[i]), 1, 2*Obj_GetAngle(obj)-Obj_GetAngle(bullets[i]), 0, 11, size);
}
     }
  }
          yield;
       }
    }
    task ShootBullet(x,y,v,angle,delay,type,store){
       loop(delay){yield;}
       let obj=Obj_Create(OBJ_SHOT);
       Obj_SetPosition(obj, x, y);
       Obj_SetAngle(obj, angle);
       Obj_SetSpeed(obj, v);
       ObjShot_SetGraphic(obj, 160);
       Obj_SetCollisionToObject(obj,true);
       bullets ~ obj; //problems here
       size++;
    }
    @Finalize {
        DeleteGraphic(ImgBoss);
    }
}

Thing I would like to make here:

1. 3 types of lasers: white, red and blue
2. Bullets do the following action:
if it hits white laser, just pass through it.
if it hits blue laser, it reflects.
if it hits red laser, not only it reflects, a new bullet is generated, continuing the bullets last motion.

I bet there is a very serious problem in the algorithm, is the spell card a bad idea? (with wrong segment marked)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 21, 2009, 03:38:42 AM
Excuse my noobishness, but I just don't understand why this script won't run

Code: [Select]
#TouhouDanmakufu
#Title[Why doesn't this one work?]
#Text[Using loop to spawn bullets in a circular pattern.]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{


   let imgExRumia="script\ExRumia\img\ExRumia.png";
   let frame = 0;
   let angle = 0;
   
   
   @Initialize{
      SetLife(1500);
      SetTimer(60);
      SetInvincibility(30);
      LoadGraphic(imgExRumia); //Load the boss graphic.
      SetMovePosition02(GetCenterX, GetCenterY - 100, 120);
      hitit;
   }
   
   @MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
 



   
   }

   @DrawLoop{
     

      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetTexture(imgExRumia);
      SetGraphicRect(64,1,127,64);
      DrawGraphic(GetX,GetY);
   }
     
   @Finalize
   {
   DeleteGraphic(imgExRumia);
   }

              task hitit{
                            loop(120){yield}
            loop{
       loop(36){CreateShot01(GetX + 60*cos(angle), GetY + 60*sin(angle), 3, angle, BLUE12, 12);
                    angle += 360/36;}   
                                            loop(6){yield;}
                                     
                   }
                          }
}             
   



When this one does--
Code: [Select]
#TouhouDanmakufu
#Title[Spawning Bullets in a Circle intermediate]
#Text[Using loop to spawn bullets in a circular pattern.]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main{


   let imgExRumia="script\ExRumia\img\ExRumia.png";
   let frame = 0;
   let angle = 0;
   
   
   @Initialize{
      SetLife(1500);
      SetTimer(60);
      SetInvincibility(30);
      LoadGraphic(imgExRumia); //Load the boss graphic.
      SetMovePosition02(GetCenterX, GetCenterY - 100, 120); //Move the boss to the top center of the screen.
   }
   
   @MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
   frame++;
   
if(frame==118){
   hitit;
   angle += 4;
   frame = 112;
   
}
   
   
   }

   @DrawLoop{
     
      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetTexture(imgExRumia);
      SetGraphicRect(64,1,127,64);
      DrawGraphic(GetX,GetY);
   }
     
   @Finalize
   {
      DeleteGraphic(imgExRumia);
   }


 task hitit{
   loop(36){
                                             CreateShot01(GetX + 60*cos(angle), GetY + 60*sin(angle), 3, angle, BLUE12, 12);
                                             angle += 360/36;
}
}
}
}



It makes no sense, it's an almost exact reproduction. It's a very easy script, but I just can't get past it. How can I make it so it will load the stuff I want @initialize?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on September 21, 2009, 03:52:15 AM
put a yield in your mainloop goddammit


aksdfksjbgljasdbljabldjsf
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 21, 2009, 04:18:59 AM
In fact I still think yield; is not a very good function to use, so if it is not necessary, I don't use it :)

My above script is edited:

Code: [Select]
#TouhouDanmakufu
#Title[Moon-Metal Sign "Sunshine reflector"]
#Text[The danmaku version of the card with same name in SWR]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = -120;
    let random;
    let i;
    let j;
    let radius;
    let bullets=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
    let size=0;
    let ImgBoss = "script\img\ExRumia.png";
    LoadUserShotData(GetCurrentScriptDirectory~"images\shot_All.txt");
    @Initialize {
       SetLife(1500);
       SetTimer(60);
       SetScore(1000000);
       SetDamageRate(25,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "Moon-Metal Sign "\""Sunshine reflector"\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        if(frame==60){
           ascent(i in 0..6){
      Laser(cos(i*360/6)*60, sin(i*360/6)*60, GetAngleToPlayer, i*360/6-120, 60, 0, 60, 1);
      Laser(cos(i*360/6)*60, sin(i*360/6)*60, GetAngleToPlayer, i*360/6, 60, 10, 60, 2);
              ascent(j in 0..6){
Laser(cos(i*360/6)*180+cos(j*360/6)*60, sin(i*360/6)*180+sin(j*360/6)*60, GetAngleToPlayer, j*360/6-120, 60, 20, 60, 3);
              }
      Laser(cos(i*360/6)*60, sin(i*360/6)*180, GetAngleToPlayer, i*360/6-120, 60, 30, 60, 2);
      Laser(cos(i*360/6)*300, sin(i*360/6)*180, GetAngleToPlayer, i*360/6+60, 60, 40, 60, 2);

           }
        }
if(frame==120){
   ascent(i in 0..7){
      ascent(j in 0..6){
ShootBullet(GetX, GetY, 1, GetAngleToPlayer+i*360/7, 10+j*5, 11);
      }
   }
}
        frame++;
        yield;
    }

    @DrawLoop {
       DrawGraphic(GetX,GetY);
    }
    task Laser(x,y,slant,angle,length,delay,delay2,type){
       loop(delay){yield;}
       let obj=Obj_Create(OBJ_LASER);
       Obj_SetPosition(obj, GetX+cos(slant)*x-y*sin(slant), GetY+sin(slant)*x+y*cos(slant));
       Obj_SetAngle(obj, slant+angle);
       Obj_SetSpeed(obj, 0);
       ObjLaser_SetLength(obj, length);
       ObjLaser_SetWidth(obj, 10);
       ObjLaser_SetSource(obj, false);
       Obj_SetCollisionToObject(obj,true);
       bullets[size]=obj;
       if(type==1){
  ObjShot_SetGraphic(obj, 96);
       }
       if(type==2){
          ObjShot_SetGraphic(obj, 94);
       }
       if(type==3){
  ObjShot_SetGraphic(obj, 89);
       }
       ObjShot_SetDelay  (obj, delay2);
       while(Obj_BeDeleted(obj)==false&&frame>120){
          yield;
       }
       size++;
    }
    task ShootBullet(x,y,v,angle,delay,type){
       loop(delay){yield;}
       let obj=Obj_Create(OBJ_SHOT);
       Obj_SetPosition(obj, x, y);
       Obj_SetAngle(obj, angle);
       Obj_SetSpeed(obj, v);
       ObjShot_SetGraphic(obj, 11);
       Obj_SetCollisionToObject(obj,true);
       while(Obj_BeDeleted(obj)==false&&frame>120){
  ascent(i in 0..size){
             if(Collision_Obj_Obj(obj, bullets[i])==1){ //bug here
        if(type==2){
   Obj_SetAngle(obj, 2*Obj_GetAngle(obj)-Obj_GetAngle(bullets[i]));
}
if(type==3){
   ShootBullet(Obj_GetX(obj), Obj_GetY(obj), 1, 2*Obj_GetAngle(bullets[i])-Obj_GetAngle(obj), 0, 11);
}
     }
  }
          yield;
       }
    }
    @Finalize {
        DeleteGraphic(ImgBoss);
    }
}

It requires the CtC shot_all.txt and the corresponding image to work.
Can anyone try to find why there is a bug?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on September 21, 2009, 04:55:34 AM
Here, have a useful page.

http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Translated_Error_Messages

Your error message reads, variables of different types are being compared. I believe the problem is that you are reading if Collision_Obj_Obj==1, while I don't think true/false returns work that way. That is, 1 is always true, but true is not always 1. Just remove the ==1 and the if statement will register it as true/false just fine. That makes the script stop crashing but I don't know if it's actually running correctly since I didn't bother to put the shot_all in there.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on September 21, 2009, 05:09:54 AM
I live!! I have a question regarding shot angles,GetAngleToPlayer just gets the angle of the player, is there some part of a code or something to fire directly at the player? or will i need to create a task bullet or laser??
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 21, 2009, 08:07:22 AM
I am amazed people try to use a task function but still use their mainloop as the leading code ( such as in if frame == x then do -> )

Ohwell, everybodies style I guess.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 21, 2009, 12:27:23 PM
Here, have a useful page.

http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Translated_Error_Messages

Your error message reads, variables of different types are being compared. I believe the problem is that you are reading if Collision_Obj_Obj==1, while I don't think true/false returns work that way. That is, 1 is always true, but true is not always 1. Just remove the ==1 and the if statement will register it as true/false just fine. That makes the script stop crashing but I don't know if it's actually running correctly since I didn't bother to put the shot_all in there.
Thanks for your help.
However, my computer cannot display Japanese properly (My computer displays Chinese properly but when I use Applocale, Danmakufu crashes :() So that the translated error message may not be so helpful for me. :(
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 21, 2009, 04:09:05 PM
Yeah no problem guys I got this. Don't confuse yourselves or anything trying to figure this mofo out -- I got it covered.

I live!! I have a question regarding shot angles,GetAngleToPlayer just gets the angle of the player, is there some part of a code or something to fire directly at the player? or will i need to create a task bullet or laser??

GetAngleToPlayer gets the angle from the boss to the player. So if you're shooting a bullet spawned on the boss' position (GetX, GetY) and you use the function GetAngleToPlayer as your angle parameter, then the bullet will be fired towards the player. However, if the bullet is spawned on some other location other than the boss', then GetAngleToPlayer will not work. It does not get the angle from the bullet to the player.

If you want to get the angle from the bullet to the player, then you must use atan2(Player's Y - Bullet's Y, Player's X - Bullet's X).

For example, if you spawned a bullet on the coordinates (200, 300), then the angle from (200, 300) to (GetPlayerX, GetPlayerY) would be calculated like so:
atan2(GetPlayerY - 300, GetPlayerX - 200);

So the bullet's code would look like:
CreateShot01(200, 300, 3, atan2(GetPlayerY - 300, GetPlayerX - 200), RED01, 0);

Another example, bullet spawned on (10, 340):
CreateShot01(10, 340, 2, atan2(GetPlayerY - 340, GetPlayerX - 10), BLUE02, 0);

Etc.
Other useless information. (http://www.shrinemaiden.org/forum/index.php?topic=296.msg7444#msg7444)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on September 21, 2009, 05:09:10 PM
Thank you Naut that worked like a charm :) but now im having another issue, i want to fire a ring of bullets that spread out, then stop, ive tried using the loop function with CreateShotAs and realized after half an hour that wouldnt work, so what would i do? never mind DgBarca helped me with it :)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: shazbot on September 21, 2009, 10:51:06 PM
hello, I have literally downloaded danmakufu 3 days before this post and have been reading the tuts, however I have a reoccurring problem, movement, I cannot seem to get the boss to move no matter where,how, or with what I place the SetMovePosition functions; placing the answer in a full script would be helpful, I'm sorry if this has already been brought up, 25 pages is a wee to much to sift through.

EDIT: see new post
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 22, 2009, 12:23:22 AM
Thank you Naut that worked like a charm :) but now im having another issue, i want to fire a ring of bullets that spread out, then stop, ive tried using the loop function with CreateShotAs and realized after half an hour that wouldnt work, so what would i do? never mind DgBarca helped me with it :)

Yes, that works.
ascent(i in 0..24){
  CreateShotA(0, GetX, GetY, 10); //fire from boss
  SetShotDataA(0, 0, 2, i*360/24+*any constant here, e.g. GetAngleToPlayer*, 0, -0.05, 0, *your graphic here*);
  FireShot(0); //don't miss this
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 22, 2009, 12:24:57 AM
hello, I have literally downloaded danmakufu 3 days before this post and have been reading the tuts, however I have a reoccurring problem, movement, I cannot seem to get the boss to move no matter where,how, or with what I place the SetMovePosition functions; placing the answer in a full script would be helpful, I'm sorry if this has already been brought up, 25 pages is a wee to much to sift through.
Try downloading scripts. If it doesn't work, reinstall Danmakufu.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 22, 2009, 05:49:46 AM
hello, I have literally downloaded danmakufu 3 days before this post and have been reading the tuts, however I have a reoccurring problem, movement, I cannot seem to get the boss to move no matter where,how, or with what I place the SetMovePosition functions; placing the answer in a full script would be helpful, I'm sorry if this has already been brought up, 25 pages is a wee to much to sift through.

Post your script here between  code  tags so we can see it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 22, 2009, 08:06:28 AM
Hi everyone.

If I need to create a Shot-Laser Collision, which that the shot divides into 2: 1 continue its motion, another is reflected and the function for the shot is FireShot(x,y,angle,delaybeforeappearance,fadeindelay).

If I use
if(Collision_obj_obj(bullet, laser)==0){
FireShot(Get_ObjX(bullet), Get_ObjY(bullet), reflected angle, 0, 0);
}

It fails because the Created Bullet also collides with the laser.

is that anyway to solve the problem?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on September 22, 2009, 10:00:06 AM
Hi everyone.

If I need to create a Shot-Laser Collision, which that the shot divides into 2: 1 continue its motion, another is reflected and the function for the shot is FireShot(x,y,angle,delaybeforeappearance,fadeindelay).

If I use
if(Collision_obj_obj(bullet, laser)==0){
FireShot(Get_ObjX(bullet), Get_ObjY(bullet), reflected angle, 0, 0);
}

It fails because the Created Bullet also collides with the laser.

is that anyway to solve the problem?

A simple method would be to not do any collison checking until the bullet has been spawned for over 60frames or something.

So add a frame varible with frame++; somewhere then use
if((Collision_obj_obj(bullet, laser)==0)&&(frame > 60)){
FireShot(Get_ObjX(bullet), Get_ObjY(bullet), reflected angle, 0, 0);
}

Something like that.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 22, 2009, 01:39:09 PM
This solution is charming, thanks Thaws :)

P.S.
Code: [Select]
#TouhouDanmakufu
#Title[Moon-Metal Sign "Sunshine reflector"]
#Text[The danmaku version of the card with same name in SWR]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = -120;
    let bg = GetCurrentScriptDirectory~"images\Bossbggrey.jpg";
    let random;
    let i;
    let j;
    let radius;
    let bullets=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
    let laser=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];
    let size=0;
    #include_function "..\drawing.txt"
    @Initialize {
       SetLife(1500);
       SetTimer(60);
       SetScore(1000000);
       SetDamageRate(25,0);
       SetMovePosition02(GetCenterX, GetClipMinY+120, 120);
       SetInvincibility(120);
       Concentration01(120);
       PlaySE(GetCurrentScriptDirectory~"SFX\Charge.wav");
       CutIn(YOUMU, "Moon-Metal Sign "\""Sunshine reflector"\", "", 0, 0, 0, 0);
       LoadGraphic(ImgBoss);
       SetTexture(ImgBoss);
       SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 16);
        if(frame==60){
           ascent(i in 0..6){
      ascent(j in 0..2){
         Laser(60, 0, GetAngleToPlayer+i*60, -120*j, 60, 0, 60, 1-j);
      }
              ascent(j in 0..2){
Laser(60, 60*3^0.5, GetAngleToPlayer+i*360/6, 120*j, 60, 20, 60, 2);
Laser(30, 90*3^0.5, GetAngleToPlayer+i*360/6, 180-120*j, 60, 30, 60, 1);
              }
           }
        }
if(frame%120==0&&frame>0){
   random=rand(0,360);
   ascent(i in 0..8){
      ascent(j in 0..4){
ShootBullet(GetX, GetY, 3, random+i*360/8+45, 10+j*6);
      }
   }
}
        frame++;
        yield;
    }

    @DrawLoop {
       bossSC;
    }
    @BackGround{
       backgroundSC;
    }
    task Laser(x,y,slant,angle,length,delay,delay2,type){
       loop(delay){yield;}
       let obj=Obj_Create(OBJ_LASER);
       let type2=type;
       Obj_SetPosition(obj, GetX+cos(slant)*x-y*sin(slant), GetY+sin(slant)*x+y*cos(slant));
       Obj_SetAngle(obj, slant+angle);
       Obj_SetSpeed(obj, 0);
       ObjLaser_SetLength(obj, length);
       ObjLaser_SetWidth(obj, 10);
       ObjLaser_SetSource(obj, false);
       Obj_SetCollisionToObject(obj,true);
       bullets[size]=obj;
       laser[size]=type2;
       size++;
       if(type2==0){
  ObjShot_SetGraphic(obj, 160-8);
       }
       if(type2==1){
          ObjShot_SetGraphic(obj, 158-8);
       }
       if(type2==2){
  ObjShot_SetGraphic(obj, 153-8);
       }
       ObjShot_SetDelay  (obj, delay2);
       while(Obj_BeDeleted(obj)==false){
  if(frame%250==0){
     type2=0;
             laser[size]=type2;
     ObjShot_SetGraphic(obj, 160-8);
  }
  if(frame%250==125){
     type2=type;
     laser[size]=type2;
             if(type2==0){
  ObjShot_SetGraphic(obj, 160-8);
             }
             if(type2==1){
                ObjShot_SetGraphic(obj, 158-8);
             }
             if(type2==2){
  ObjShot_SetGraphic(obj, 153-8);
             }
  }
          yield;
       }
    }
    task ShootBullet(x,y,v,angle,delay){
       loop(delay){yield;}
       let obj=Obj_Create(OBJ_SHOT);
       let count=1;
       let frame2=0;
       Obj_SetPosition(obj, x, y);
       Obj_SetAngle(obj, angle);
       Obj_SetSpeed(obj, v);
       ObjShot_SetGraphic(obj, 11);
       Obj_SetCollisionToObject(obj,true);
       while(Obj_BeDeleted(obj)==false){
  ascent(i in 0..size){
             if(Collision_Obj_Obj(obj, bullets[i])&&frame2>10&&count>0){
        if(laser[i]==1){
   Obj_SetAngle(obj, 2*Obj_GetAngle(bullets[i])-Obj_GetAngle(obj));
}
if(laser[i]==2){
   ShootBullet(Obj_GetX(obj)+cos(Obj_GetAngle(bullets[i])), Obj_GetY(obj)+sin(Obj_GetAngle(bullets[i])), v, 2*Obj_GetAngle(bullets[i])-Obj_GetAngle(obj), 0);
   count--;
}
     }
  }
  frame2++;
          yield;
       }
    }
    @Finalize {
        DeleteGraphic(ImgBoss);
    }
}

Is there anyway to make it faster?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: shazbot on September 22, 2009, 07:10:54 PM
oh nevermind it seems the problem was the copypasta-ed full script not what I was inputting, I may have deleted one too many things when trying to remove the attack, sorry for any inconvenience.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 22, 2009, 07:23:38 PM
put a yield in your mainloop goddammit


aksdfksjbgljasdbljabldjsf


I don't understand. Why does it work when I put in "yield;", but not when I don't?
I thought yield is a subfunction that delays frames.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 22, 2009, 08:18:47 PM
We have tutorials, good sir. (http://www.shrinemaiden.org/forum/index.php?topic=865.msg31779#msg31779)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on September 22, 2009, 11:42:17 PM
Yield basically tells a script to stop and look for another task it should be working on. If you don't have one in @MainLoop, it will only execute a task up to its first yield, after which it will be completely forgotten. By looping yield, it tells a task to stop and check for others a certain number of frames before continuing.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 23, 2009, 09:38:02 PM
Question: How can you play multiple stages? Putting them in a plural file won't work, so what is the right way to call them?
I want to make a main menu, but that's kinda pointless if you can't play stages afterwards!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kilgamayan on September 23, 2009, 09:42:52 PM
Question: How can you play multiple stages? Putting them in a plural file won't work, so what is the right way to call them?
I want to make a main menu, but that's kinda pointless if you can't play stages afterwards!

Congratulations on post 77777.

Unfortunately, I have no actual answer to your question. :V
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on September 23, 2009, 11:17:47 PM
Question: How can you play multiple stages? Putting them in a plural file won't work, so what is the right way to call them?
I want to make a main menu, but that's kinda pointless if you can't play stages afterwards!

main menu enemy to mess with DrawText and common data functions → multiple tasks for multiple difficulties and stages → mess with if statements in the stage script → make each task execute the next task
...Sorry if I messed something up.


Like this, I think.

Code: [Select]
script_stage_main{

 function Wait(let frames){
   loop(frames){yield;}
 }
 function WaitForZeroEnemy{
  while(GetEnemyNum != 0){yield;}
 }
 task select{
 //spawn main menu enemy;
 //spawn another menu enemy if you want because I did for the game I'm making;
 if(blahblahblahstatement) {
 stageE1;
 } else if(blah) {
 stageN1;
 } else if(blahthisistrue) {
 stageH1;
 } else if(blahblahblahblahtrueblahblah) {
 stageL1;
 } else if(truestatement) {
 stageEX;
 } else if(thisstatementistrue) {
 stagePHAN;
 }
 }
 task stageE1{
 //abcdefg stuff to spawn enemies for this stage;
 stageE2;
 }
 task stageE2{
 //abcdefg stuff to spawn enemies for this stage;
 stageE3;
 }
 task stageE3{
 //abcdefg stuff to spawn enemies for this stage;
 stageE4;
 }
 task stageE4{
 //abcdefg stuff to spawn enemies for this stage;
 stageE5;
 }
 task stageE5{
 //abcdefg stuff to spawn enemies for this stage;
 stageE6;
 }
 task stageE6{
 CopyPasta(FTW);
 Clear;
 }
 task stageN1{
 //abcdefg stuff to spawn enemies for this stage;
 stageN2;
 }
 task stageN2{
 //abcdefg stuff to spawn enemies for this stage;
 stageN3;
 }
 task stageN3{
 //abcdefg stuff to spawn enemies for this stage;
 stageN4;
 }
 task stageN4{
 //abcdefg stuff to spawn enemies for this stage;
 stageN5;
 }
 task stageN5{
 //abcdefg stuff to spawn enemies for this stage;
 stageN6;
 }
 task stageN6{
 //enemies;
 Clear;
 }
 task stageH1{
 //abcdefg stuff to spawn enemies for this stage;
 stageH2;
 }
 task stageH2{
 //abcdefg stuff to spawn enemies for this stage;
 stageH3;
 }
 task stageH3{
 //abcdefg stuff to spawn enemies for this stage;
 stageH4;
 }
 task stageH4{
 //abcdefg stuff to spawn enemies for this stage;
 stageH5;
 }
 task stageH5{
 //abcdefg stuff to spawn enemies for this stage;
 stageH6;
 }
 task stageH6{
 //lots of copy-pasting;
 Clear;
 }
 task stageL1{
 //abcdefg stuff to spawn enemies for this stage;
 stageL2;
 }
 task stageL2{
 //abcdefg stuff to spawn enemies for this stage;
 stageL3;
 }
 task stageL3{
 //abcdefg stuff to spawn enemies for this stage;
 stageL4;
 }
 task stageL4{
 //abcdefg stuff to spawn enemies for this stage;
 stageL5;
 }
 task stageL5{
 //abcdefg stuff to spawn enemies for this stage;
 stageL6;
 }
 task stageL6{
 //enemies;
 Clear;
 }
 task stageEX {
 //abcdefg stuff to spawn enemies for the EX stage;
 Clear;
 }
 task stagePHAN {
 //abcdefg stuff to spawn enemies for the Phantasm stage;
 Clear; //OMFG this script is long even without enemies
 }

  @Initialize{
 select;
  }
 @MainLoop{
   //Feel(Free, To, Make, This, Script, Shorter);
   yield;
  }
  @Background{

  }
  @Finalize{

  }
  //Shell copied from Naut;
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on September 24, 2009, 01:55:44 AM
Question: How can you play multiple stages? Putting them in a plural file won't work, so what is the right way to call them?
I want to make a main menu, but that's kinda pointless if you can't play stages afterwards!

main menu enemy to mess with DrawText and common data functions → multiple tasks for multiple difficulties and stages → mess with if statements in the stage script → make each task execute the next task
...Sorry if I messed something up.


Like this, I think.

Code: [Select]
t3h codez

This looks a lot like what I put together for the (now defunct) EoAD project - basically, each stage has its own function which is called from the top-level stage's @MainLoop.

Here's a couple things from my implementation that could improve on your sample ...
- Separate each stage's function to a separate script file, and include them in your main script file.  This allows you to keep things a bit more organized.
- Rather than a separate function for each difficulty, as it looks like you did in your sample, I recommend using common data to set a difficulty variable globally, and then adjusting factors as need be in each stage function.



Also, you can use the @Background of your main script to draw menus and such.  I normally do that with menus, and keep an in_menu variable to track whether we're currently in a menu or not.


Oh, and of course, I didn't use tasks 'cause I hate them.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on September 24, 2009, 04:09:57 AM
i just have a quick question about all of the things you put in if(frame???400)
the ??? being

!=
=!

i read the tutorial on these and i dont quite get how these work,
 if 28!=4 is true i think, if frame28!=4 how the @#$@ does that work?
and sorry if my question is confusing
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 24, 2009, 08:40:53 AM
i just have a quick question about all of the things you put in if(frame???400)
the ??? being

!=
=!

i read the tutorial on these and i dont quite get how these work,
 if 28!=4 is true i think, if frame28!=4 how the @#$@ does that work?
and sorry if my question is confusing

I'm not quite sure what you mean, but != means "if not"
So you probably mean:
Code: [Select]
if(frame!=4){ *stuff* }Which would cause "stuff" to happen on every frame, except on frame 4 (which is probably barely noticable). So you might want to combine it. Like:
Code: [Select]
if(frame!=4 && frame<20){ *stuff* }Or something like that.

My favorite way of making things happen is:
Code: [Select]
if(frame%20==0){ *stuff* }Which would make "stuff" happen every 20 frame, including the very first.

Oh, and =! only raises errors, != is the right way.




Anyhoo, back to my question:
I haven't dealt with functions before. Functions are another kind of sepparate files you can call on, right?
I have a Stage file here, so would it be possible to summon that by using a function? If so, how? The wiki on functions doesn't help me understand it much. D:
Making a main menu is not a problem, it's just that one little piece of "playing the stage" I'm missing.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 24, 2009, 02:06:39 PM
you can simply declare variables, use tasks, subroutines or functions in another text file (e.g. "example.txt")

then you can use:
#include_function "..\example.txt"

to include all things in it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 24, 2009, 02:20:19 PM
you can simply declare variables, use tasks, subroutines or functions in another text file (e.g. "example.txt")

then you can use:
#include_function "..\example.txt"

to include all things in it.

Geting closer. I have things set up like this right now:
Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Masahiro Main Menu]
#Text[Meep]
#Player[FREE]
#ScriptVersion[2]

#include_function "script\Stage 1.txt"

script_stage_main{
*stuff*

And after certain events I want to load said stage, so I put this down:
Code: [Select]
CreateEnemyBossFromFile("script\Stage 1.txt",cx,cy,0,0,NULL);Which ofcourse gives errors. That's probably not it, eh? Together with CreateEnemyFromFile it's the only piece of code that I can find where you can link to another file. What would be the right thing to put there instead?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 24, 2009, 02:31:22 PM
Geting closer. I have things set up like this right now:
Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Masahiro Main Menu]
#Text[Meep]
#Player[FREE]
#ScriptVersion[2]

#include_function "script\Stage 1.txt"

script_stage_main{
*stuff*

And after certain events I want to load said stage, so I put this down:
Code: [Select]
CreateEnemyBossFromFile("script\Stage 1.txt",cx,cy,0,0,NULL);Which ofcourse gives errors. That's probably not it, eh? Together with CreateEnemyFromFile it's the only piece of code that I can find where you can link to another file. What would be the right thing to put there instead?

Em... For me I would put the #include_function inside the script_stage_main, probably before initialize.
And I don't know much about stage scripts :( sorry for that
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 24, 2009, 02:36:14 PM
Tried that too, but it gives other errors. I'll wait for someone else to answer it then :3
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 24, 2009, 03:38:38 PM
#include_function just includes a script filled with information as if you wrote it down in your current script. So for stage1.txt you could have a task inside of it somewhere that loks like this:

Code: [Select]
task stage1{
//lololololololol
loop(infinity){
yield;}
//lololololololol
}

Then you could call upon that task in your main script:
Code: [Select]
if(frame==200){
stage1;
}

So at frame 200, the main file would play the task "stage1" as if you declared it in the current script.

Erm, remember that functions cannot use yield and tasks can, which is why I used them isntead of "function". Same applies for "sub". (http://www.shrinemaiden.org/forum/index.php?topic=296.msg6747#msg6747)

Take a look at the CtC shot replace script to see how include function works. Declaring shotinit; in a script just loads shot data that you called upon using #include_function ".\lib\SHOT_REPLACE\shot_replace.dnh";
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 24, 2009, 04:59:31 PM
And so I did:

It seems to actually call for the stage now, but I get this error:

(http://i32.photobucket.com/albums/d49/puremrz/awbugger.png)

Could this be because I have to remove a few parts of the stage script before it will work? I tried removing everything that comes before script_stage_main{, but then I just get the same error starting from that point.


#include_function just includes a script filled with information as if you wrote it down in your current script. So for stage1.txt you could have a task inside of it somewhere that loks like this:

Code: [Select]
task stage1{
//lololololololol
loop(infinity){
yield;}
//lololololololol
}

Then you could call upon that task in your main script:
Code: [Select]
if(frame==200){
stage1;
}

So at frame 200, the main file would play the task "stage1" as if you declared it in the current script.

Erm, remember that functions cannot use yield and tasks can, which is why I used them isntead of "function". Same applies for "sub". (http://www.shrinemaiden.org/forum/index.php?topic=296.msg6747#msg6747)

Take a look at the CtC shot replace script to see how include function works. Declaring shotinit; in a script just loads shot data that you called upon using #include_function ".\lib\SHOT_REPLACE\shot_replace.dnh";
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 24, 2009, 06:11:56 PM
stage1.txt:

Code: [Select]

let boss = GetCurrentScriptDirectory~"keinekamishirasawa.txt";
let enemy = GetCurrentScriptDirectory~"enemy1.txt";

task stage1{
loop(60){yield;}
loop(10){
   CreateEnemyFromFile(enemy, rand(50, 398), -20, 90, rand(2, 6), 0);
   loop(20){yield;}
   }
while(GetEnemyNum>0){
   yield;
   }
loop(30){yield;}
CreateEnemyBossFromFile(boss, 500, 0, 0, 0, 0);
while(IsBossExisting==true){
   yield;
   }
loop(120){yield;}
Clear;
}


This is all you need in the stage1.txt file, in it's entirety. No need for @MainLoop or any of that shit, just the functions, declarations, tasks or whatever. Then in your main file (the file you're declaring #include_function in) you could declare stage1 anywhere in the script and it will then play through the task stage1, since the file reads it as if you declared it within script_stage_main{}.

Erm, hopefully this is clear, heh.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 24, 2009, 06:18:38 PM
Hm, so if I want to use a background, I can make a sepparate file for that too? I'll go mess with it for a bit...

Conclusion: A Stage script would be better defined as a Game script. Ne?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 24, 2009, 06:20:38 PM
You can make a separate file for anything declarable in the main file (read: everything).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 24, 2009, 06:59:06 PM
My brain is fighting hard to prevent me from understanding, but I think I finally got it.
Although this progress has led me to another problem.

This is as far as I made it:

Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Masahiro Main Menu]
#Text[Meep]
#Player[FREE]
#ScriptVersion[2]

script_stage_main{

#include_function "script\mainmenu ssm.txt"
#include_function "script\mainmenu init.txt"

mainmenussm;

@Initialize{
mainmenuinit;
}

*the rest*

The two files include:
Code: [Select]
task mainmenussm{

let easy=1;
let normal=0;
let hard=0;
let choice=("script\SoundEffects\choice.wav");
etc

}

and

Code: [Select]
task mainmenuinit{

LoadSE(choice);
LoadSE(confirm);
LoadSE(cancel);
etc

}

But when I try it out, Danmakufu tells me I hadn't set a variable for the "choice" sound effect, while I just loaded that from the first file.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 24, 2009, 07:02:55 PM
You don't need to make a task to declare variables. Remember that tasks have their own scope, so when you declare a variable inside a task, it only exists inside that task. Just simply stating "let choice = whatever;" outside the task is fine (see: my previous example).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 24, 2009, 07:24:54 PM
Zomg, it finally worked! There's one downside with it though, I have to declare all variables for all stages in one single file. That can get messy... Let's see if I can find a way around that.

Edit: Dayumn, I was right about the messy variables. I was experiencing crashing errors for over an hour because of a doublenamed variable! >_<
And hour is very long if Danmakufu keeps crashing :P

You don't need to make a task to declare variables. Remember that tasks have their own scope, so when you declare a variable inside a task, it only exists inside that task. Just simply stating "let choice = whatever;" outside the task is fine (see: my previous example).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on September 25, 2009, 12:46:25 AM
yay! another question about SetShotDataAs! I remember hearing about some sort of "return statement" does that make the bullet go back to the boss? or if not how do you have bullets return to the boss?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 25, 2009, 02:50:27 AM
yay! another question about SetShotDataAs! I remember hearing about some sort of "return statement" does that make the bullet go back to the boss? or if not how do you have bullets return to the boss?

hey...
no return is needed...
SetShotDataA(bullet_id, delay_frame, velocity, angle-180 (if linear), ...);
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on September 25, 2009, 08:37:38 AM
yay! another question about SetShotDataAs! I remember hearing about some sort of "return statement" does that make the bullet go back to the boss? or if not how do you have bullets return to the boss?

"Return" is a general programming term; returns are data that are produced from functions that allow you to treat the function itself like a number (or in some cases, a string).

For instance, GetAngleToPlayer returns the angle from the boss to the player, so you can put it in mathematical statements. For instance,  n=GetAngleToPlayer. This won't work with a function that doesn't return anything, like, say, n=CreateShot01.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 25, 2009, 09:44:11 AM
Is there a way to jump from one part of the script to the other? After certain events, @Initialize will contain new data, and I want the script to replay from that moment on.

Code: [Select]
@Initialize{
if(GetCommonData(5)==-1) { initmain; }
if(GetCommonData(5)>=0) { init1; }
yield;
}

@MainLoop{
if(GetCommonData(5)==-1) { mlmain; }
if(GetCommonData(5)>=0) { ml1; }
yield;
}

@BackGround{
if(GetCommonData(5)>=0) { bag1; }
yield;
}
Like this, CommonData(5) starts as -1, but at the end of the script, it becomes a bigger number. So I want to reload the whole script for each stage, since it's not possible to load a second stage file after clearing the first..


Really, making a stage alone sucks, but Danmakufu's lack of "You cleared this stage, now load the next" is completely retarded.
A stage file shouldn't be called like that if you can only run one of them. *rage*
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 25, 2009, 01:54:10 PM
Make a plural file that plays the stages file in succession. Or make a task that will wait until the stage is finished, then plays it again with the updated common data.

Code: [Select]
task stages{
stage1;
while(stage1playing==true){
   //just set a variable to true while your stage is playing, and at the end set it to false to make this statement work.
   yield;
}
stage1;
while(stage1playing==true){
   yield;
}
stage2;
while(stage2playing==true){
   yield;
}
Clear;
}

Something like that. This also solves your "you cleared a stage, load the next" problem. That is, if you didn't like my plural file + stages in succession idea at first...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 25, 2009, 02:41:10 PM
When I make a plural file and try to load a stage script, it say something about setting the enemy's health, and then crashes. So it won't allow you to load a stage from a plural.

When I make a task out of the stage and try to load that from another stage, it gives me the error you get when your } count is wrong. And crashes afterwards, even if the { and } count is completely right.

Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Thing]
#Text[]
#Player[FREE]
#ScriptVersion[2]

#include_function "script\Stages\Stage 1b.txt"

stage;
This is the whole file where I try loading the stages from.

Code: [Select]
task stage{

script_stage_main{

@Initialize{
}

@MainLoop{
}

@BackGround{
}

@DrawLoop{
}

@Finalize{
}
}
}
This is what I'm loading.
Even though there's nothing in there, Danmakufu won't accept it and crashes. It's like you can't put @Initialize & friends in a task.



I tried your other ways too:
Code: [Select]
@Initialize{
if(GetCommonData(5)==0) { initmain; }
yield;
}

@MainLoop{
if(GetCommonData(5)==0) { mlmain; }
yield;
}
it somewhat works, although it gave me countless problems related to variables it claimed not to have, while I created those right before calling the task. And I can't load Initialize a 2nd or 3rd time, so this won't work.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on September 25, 2009, 02:48:53 PM
Eh, could be me ( replying from work ) but task stage and putting script_stage_main is not liked by Danmakufu. Or am I wrong here.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 25, 2009, 03:38:22 PM
Ahhhhhh! When I said my example script was the entirety of stage1.txt -- I MEANT IT. That is seriously all you need to put in the file. Just the task! No script_stage_main, no @Initialize, nothing! Just the task! All the @Initialize portions and whatnot happens in the main file! You can load all your graphics and whatever else in the main file! So delete all of that @Initialize and stage_script_main shit and just program your stage using yield; and CreateEnemyFromScript functions in the task. Run the task in your main file, just like my example script. Viola!

Also, come on IRC (http://www.shrinemaiden.org/forum/index.php?topic=18.0)! It's so much easier to explain this stuff in real time, since I'm clearly not doing this subject justice, haha.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on September 25, 2009, 03:54:06 PM
Eh, could be me ( replying from work ) but task stage and putting script_stage_main is not liked by Danmakufu. Or am I wrong here.

Nope :<

Now I tried this instead:
Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Thing]
#Text[]
#Player[FREE]
#ScriptVersion[2]

#include_function "script\Stages\Stage 1b.txt"

script_stage_main{

stage1load;

}

And then the task file has the whole stage minus the part before script_stage_main and the last }
In other words, these two, when merged, form the exact same file of a stage that normally would work.

When loading that, Danmakufu goes like
(http://i32.photobucket.com/albums/d49/puremrz/morebugger.png)
and closes the stage (It doesn't crash, that's a breakthrough. No really, I've had to restart it so many times last two days, if I got a cent for each crash, I'd be able to buy a very expensive icecream now.
Removing stage1load; results in an empty typical screen. Which is ofcourse more pleasant than that windows error sound followed by "Would you like to send this error report so that Microsoft can point at you and laugh?"


It's like Danmakufu isn't made to play more than one stage at a time. The only way I can find around it is to use SaveCommondata and then manually load each stage. How did those people from CtC do it? I can't make sense out of their scripts, it's like it's written with a completely different language than Danmakufu uses.



Naut: Warning - while you were typing a new reply has been posted. You may wish to review your post.
That warning thing is pretty useful.

Oh bugger, but I'll post this anyway.
I think I tried doing that with the entire stage as well. But I can try again, maybe it works this time.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 25, 2009, 04:04:30 PM
Main stage file:

Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Stage lokloooloolol]
#Text[OMGOMGOMGOGM]
#Player[FREE]
#ScriptVersion[2]

script_stage_main{
   #include_function "script\Stages\Stage 1b.txt";

   @Initialize{
      stage1load;
   }

   @MainLoop{
      yield;
   }

   @Finalize{

   }
}

Stage 1b.txt:

Code: [Select]

let boss = GetCurrentScriptDirectory~"keinekamishirasawa.txt";
let enemy = GetCurrentScriptDirectory~"enemy1.txt";

task stage1load{
loop(60){yield;}
loop(10){
   CreateEnemyFromFile(enemy, rand(50, 398), -20, 90, rand(2, 6), 0);
   loop(20){yield;}
   }
while(GetEnemyNum>0){
   yield;
   }
loop(30){yield;}
CreateEnemyBossFromFile(boss, 500, 0, 0, 0, 0);
while(IsBossExisting==true){
   yield;
   }
loop(120){yield;}
Clear;
}

This will run, provided you have the files I declared (just substitute your own or whatever).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 25, 2009, 04:16:14 PM
Ah shit, you use @MainLoop. Okay, let's make a second @MainLoop.

mainstage.txt:

Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Stage lokloooloolol]
#Text[OMGOMGOMGOGM]
#Player[FREE]
#ScriptVersion[2]

script_stage_main{
   #include_function "script\Stages\Stage 1b.txt";

   @Initialize{
      stage1load;
   }

   @MainLoop{
      yield;
   }

   @Finalize{

   }
}

Stage 1b.txt:

Code: [Select]

task stage1load{

let frame = 0;
let enemy = GetCurrentScriptDirectory~"enemy.txt";
let boss = GetCurrentScriptDirectory~"rigorunaitobagu.txt";


loop{
   frame++;

   if(frame==40){
      CreateEnemyFromFile(enemy, rand(50, 398), -20, 90, rand(2, 6), 0);
   }

   if(frame==60){
      loop(6){
         CreateEnemyFromFile(enemy, rand(50, 398), -20, 90, rand(2, 6), 0);
      }
   }

   if(frame==120){
      CreateEnemyBossFromFile(boss, 500, 0, 0, 0, 0);
   }

   if(IsBossExisting==true){
      frame--;
   }

   if(frame==200){
      Clear;
   }
   yield;
}

}

Something like that. As you can see, we loop the whole task permanently, just like @MainLoop (it doesn't crash because we yield; everytime we loop, so every frame. Make sure you remember the yield!). This way you can implement your conditional statement way of coding.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on September 26, 2009, 02:29:13 PM
yay! another question about SetShotDataAs! I remember hearing about some sort of "return statement" does that make the bullet go back to the boss? or if not how do you have bullets return to the boss?

hey...
no return is needed...
SetShotDataA(bullet_id, delay_frame, velocity, angle-180 (if linear), ...);

What if the first data is the angle is random? would angle still work?
....
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on September 26, 2009, 02:42:51 PM
Instead of using rand(0,360) for the bullet angle, set a variable to rand(0,360), and use that variable.

Example:
Code: [Select]
loop(10)
{
let angle = rand(0,360);
CreateShotA(0,GetX,GetY,10);
SetShotDataA(0,0,2,angle,0,0,0,RED01);
SetShotDataA(0,60,4,angle+180,0,0,0,BLUE01);
FireShot(0);
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on September 27, 2009, 12:33:52 AM
Does anyone have any suggestions on how I could put an effect object above player bullets, but below ENEMY ones? If I put it on the Bullet layer, it ends up going above ALL bullets, not just player bullets... I basically just want to emulate the official Touhou fact that the player sprite goes above player bullets, but NOT enemy bullets. Sadly, this seems impossible right now. (Why did they make the player go below its own bullets? That's a terrible idea, IMO, because I can't make bullets spawn directly below the player without getting distracted BY those bullets going over the player graphics!)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 27, 2009, 04:06:40 AM
Does anyone have any suggestions on how I could put an effect object above player bullets, but below ENEMY ones?

ObjEffect_SetLayer(obj, 3);

Any object effect you set on any layer will be placed above everything on that current layer, but below everything on the next layer. So the player is layer 3 and the bullets are layer 4, so the effect is in between them. Does this not work? (Player bullets are layer four as well, aren't they...?)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on September 27, 2009, 02:57:11 PM
Yeah, Player Bullets are on the "Bullets" layer... Which is ABOVE the player layer. (If they were below it, then I wouldn't even be trying to use an effect object. XD) That's the problem. The only possible way to make them go below the player is to recode every single shot into an effect object. Oh gosh, how annoying it'd be to make it vanish when it hit the enemy, too.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 28, 2009, 12:08:16 AM
I've been working on this for a while, and I just don't quite get it...

I'm trying to rewrite the one of the tutorial's patterns to load @Initialize to get a better understanding of Danmakufu. It's quite simple, but it keeps throwing me off when I try to simplify it. 
Code: [Select]
#TouhouDanmakufu
#Title[Waves]
#Text[Using INIT to spawn bullets in a circular pattern.]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{


   let imgExRumia="script\ExRumia\img\ExRumia.png";
   let frame = 0;
   let frame2 = 0;
   let angle = 0;
   let radius = 60;
   let angleAcc=0;
   
   
   @Initialize{
      SetLife(1500);
      SetTimer(60);
      SetInvincibility(30);
      LoadGraphic(imgExRumia);
      SetMovePosition02(GetCenterX, GetCenterY - 100, 120);
      hitit;
   }
   
   @MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
 
   yield;

SetPlayerInvincibility(20000);
   
   }

   @DrawLoop{
     

      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetTexture(imgExRumia);
      SetGraphicRect(64,1,127,64);
      DrawGraphic(GetX,GetY);
   }
     
   @Finalize
   {
   DeleteGraphic(imgExRumia);
   }
   

   task hitit{


       loop(120){yield;}

      loop{
      loop(70){
      loop(5){
         CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, angle, BLUE12, 12);
                                             angle += 360/5;}
                       
            angle+=angleAcc;
            angleAcc+=0.05;

            radius++;
            yield;}
loop(4){
 loop(70){
      loop(5){
         CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, angle, BLUE12, 12);
                                             angle += 360/5;}
                       
            angle+=angleAcc;
            angleAcc+=0.05;
            radius--;
            yield;}
}
loop(3){
         loop(70){
      loop(5){
         CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, angle, BLUE12, 12);
                                             angle += 360/5;}
                       
            angle+=angleAcc;
            angleAcc+=0.05;
            radius++;
            yield;}                 

}
                     
}

           
 
}
}

Why can't I just
Code: [Select]
angle+=0.05; instead of
Code: [Select]
angle+=angleAcc;
angleAcc+=0.05;

The way I see it, I'm telling it to do the same thing both ways. But I get a different pattern when I simplify it.  Where did I go wrong?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on September 28, 2009, 12:14:12 AM
angle+=0.05; will increase the angle by 0.05 by every frame.

But
angle+=angleAcc;
angleAcc+=0.05
does NOT.
It will increase the angle first by 0.05, then 0.1, then 0.15 etc, hence why it's called angleAcc (For acceleration).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 28, 2009, 12:30:01 AM
angle+=0.05; will increase the angle by 0.05 by every frame.

But
angle+=angleAcc;
angleAcc+=0.05
does NOT.
It will increase the angle first by 0.05, then 0.1, then 0.15 etc, hence why it's called angleAcc (For acceleration).

But that just doesn't make sense.

If angle+=angleAcc
and angleAcc+=0.01

Then that means angle += (angle+0.01)

Danmakufu kinda crashes when I plug that in. Why?
And I don't have to use the variable "angleAcc" for it to work.  I could replace the that variable to anything else, as long as I replace it everywhere it's placed.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on September 28, 2009, 12:38:00 AM
Then that means angle += (angle+0.01)
Nope. You forget angleAcc is a variable too. Whenever angleAcc+= is called, it is increased, and then angle+=angleAcc; adds everything.

So for instance if you ran
angle+=angleAcc;
angleAcc+=0.05
it would go something like this assuming both variables are 0 (although this is arbitrary).

First run of the loop.
angle+=angleAcc;
Now it looks for variable angleAcc, which is 0, and adds it to itself, so angle is still 0.
angleAcc+=0.05
Now angleAcc is incremented by 0.05. Now we are left with angle still at 0 and angleAcc at 0.05.

Second loop.
angle+=angleAcc;
Now angle is 0.05.
angleAcc+=0.05
Now angleAcc is 0.10.

Third loop.
angle+=angleAcc;
The current value of angleAcc is 0.10, not 0.05, so now angle is 0.15, not 0.1, hence it accelerated.
angleAcc+=0.05
Now angleAcc is 0.15.

And so on
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 28, 2009, 01:22:23 AM
But why does it crash when I put in
angle+=(angle+0.05);  ?
Initially, the angle is 0. (it's loaded @initialize and has error if deleted).

So first loop should be

It already has the angle loaded, which is 0, then angle is called at the bullet's fire, so it shouldn't run an error. Then near the end of the loop, it should run angle+=angle+(0.05);
in this case,    angle=0+(0.05) , the 0 got from @Initialize like used in the bullets.

So angle should be left 0.05.
And repeat the loop.

So at the beginning of the new loop, it should load
angle=0.05, which is used for the next arrange of bullets looped
and near the end of the loop, it should add 0.05 to itself (thus making angle=0.1) , so after the bullet is fired and reads
angle+=(angle+(0.05)), it should read  (angle=0.05+(0.05).   So after the statement, it should conclude angle=0.1

And likewise, third loop, it should use 0.1 as the angle for the bullets and all.

then near the end of the loop, it adds angle+=(angle+0.05). In this case, angle=(0.1+0.05)
and conclude angle=0.15

and repeat so on.

Why the crash?


Here's an example.
Code: [Select]
#TouhouDanmakufu
#Title[Waves]
#Text[Using INIT to spawn bullets in a circular pattern.]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{


   let imgExRumia="script\ExRumia\img\ExRumia.png";
   let frame = 0;
   let frame2 = 0;
   let angle=0;
   let radius = 60;
   let angleAcc=0;
   
   
   @Initialize{
      SetLife(1500);
      SetTimer(60);
      SetInvincibility(30);
      LoadGraphic(imgExRumia);
      SetMovePosition02(GetCenterX, GetCenterY - 100, 120);
      hitit;
   }
   
   @MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
 
   yield;

SetPlayerInvincibility(20000);
   
   }

   @DrawLoop{
     

      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetTexture(imgExRumia);
      SetGraphicRect(64,1,127,64);
      DrawGraphic(GetX,GetY);
   }
     
   @Finalize
   {
   DeleteGraphic(imgExRumia);
   }
   

   task hitit{


       loop(120){yield;}


      loop(1){
      loop{
         CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, angle, BLUE12, 12);
                                 angle += (angle+5);  loop(3){yield;}         
                       


       
           
           

}


}
                     
}

           
 
}
}

It works for a little while, and will work longer when the yield is looped more.  But it will "crash", if you only loop yield once.  See for yourself.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 28, 2009, 01:50:06 AM
No...
angle+=angle+(0.05); is:
1. angle=0, angle+=0+(0.05); => angle+=0.05, angle=0+0.05; angle=0.05

2. angle=0.05, angle+=0.05+0.05 => angle+=0.1, angle=0.05+0.1=0.15;

So you are just using the angle+=0.05 and angle=angle+0.05, which has the same meaning after all, at the same time, of course it is wrong.

Quote
It already has the angle loaded, which is 0, then angle is called at the bullet's fire, so it shouldn't run an error. Then near the end of the loop, it should run angle+=angle+(0.05);
in this case,    angle=0+(0.05) , the 0 got from @Initialize like used in the bullets.

You see, += does not mean = (assignment).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 28, 2009, 02:25:20 AM

So you are just using the angle+=0.05 and angle=angle+0.05, which has the same meaning after all, at the same time, of course it is wrong.

I know that angle+=0.05 means that it adds 0.05 to the angle when the statement is read.  What I meant was what the angle was after that statement, the one used after the first loop.

Say, Initial angle is 0.

Code: [Select]
      loop(2){
         CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, angle, BLUE12, 12);
                      loop(20){yield;}        angle+=30;
             }

The first angle used, the one to fire the bullets, is 0.  Near the end of the loop, it adds 30 to itself.
So the angle at the end of the loop is 30.  Angle=30

So the next loop of bullets fired would be equivalent to
CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, 30, BLUE12, 12);





Now here's what bothers me.  Say initial angle is 0.05, and the code is

     
Code: [Select]
loop{
         CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, angle, BLUE12, 12);
                      loop(3){yield;}        angle+=angle;
             }


It should add angle to itself angle+=angle;   The statement read should be 0.05+=0.05   ,leaving angle=0.1 at the end.
So the angle used to fire the bullets at next loop should be 0.01

So 2nd loop of bullets should be equivalent to
CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, 0.01, BLUE12, 12);

then, it should read angle+=angle;    The statement read should be 0.1+=0.1       leaving angle=0.2 at the end
So the angle fired t the next loop should be 0.2

And with the same pattern, the third loop of fired bullets should read
CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, 0.2, BLUE12, 12);
and the loop after that
CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, 0.4, BLUE12, 12);



But it doesn't do that.  It crashes.
I don't know why.
Code: [Select]
#TouhouDanmakufu
#Title[Waves]
#Text[Using INIT to spawn bullets in a circular pattern.]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main
{


   let imgExRumia="script\ExRumia\img\ExRumia.png";
   let frame = 0;
   let frame2 = 0;
   let angle=0.05;
   let radius = 60;
   let angleAcc=0;
   
   
   @Initialize{
      SetLife(1500);
      SetTimer(60);
      SetInvincibility(30);
      LoadGraphic(imgExRumia);
      SetMovePosition02(GetCenterX, GetCenterY - 100, 120);
      hitit;
   }
   
   @MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
 
   yield;

SetPlayerInvincibility(20000);
   
   }

   @DrawLoop{
     

      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetTexture(imgExRumia);
      SetGraphicRect(64,1,127,64);
      DrawGraphic(GetX,GetY);
   }
     
   @Finalize
   {
   DeleteGraphic(imgExRumia);
   }
   

   task hitit{


       loop(120){yield;}


      loop{
         CreateShot01(GetX + radius*cos(angle), GetY + radius*sin(angle), 3, angle, BLUE12, 12);
                      loop(3){yield;}        angle+=angle;
             }
}


}
                     
}

           
 
}
}

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 28, 2009, 02:39:36 AM
hey, you didn't declare angle!  :o

On the other hand, why do you set the player to be invincible? :P
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 28, 2009, 02:53:34 AM
hey, you didn't declare angle!  :o


It's @initialize

On the other hand, why do you set the player to be invincible? :P


Because I took the original and converted it so everything was loaded @initialize.
I had it arranged so I had to have one yield in there for it to work so I can see exactly where the bullets were spawn, and didn't want to go through the whole trouble of rewriting the script so it spawned where it supposed to, then yielded, instead of making it skip a few angles due to the yield and then spawn

Anyway, I got down to that simple script there, and forgot about invincibility. Oops :V


I think I found my problem.  Once it got to angle+=angle  and angle got to a high number like 100, I'd get crazy results.  200 next frame, then 400, then 800.  I could see why it would crash after about 90 frames.  Spinning the angle 20,000+degrees would probably take more than 1/60th of a second.


Anyway, thanks for your help.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 28, 2009, 05:10:56 AM
Oh no... I didn't see your angle... sorry for that.

and, in my opinion, if uses of tasks are ont necessary, I don't use it. It is because this surely lowers the readability of the segments.

on the other hand, your variable angle, can be expressed in 0.5*2^(times of operation-1), you can simply use it.

And to prevent the value from going too large, use % (taking remainder) like:

angle+=angle;
angle%=360;
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on September 28, 2009, 08:41:45 AM
Spinning the angle 20,000+degrees would probably take more than 1/60th of a second.

I know you have no problem with the script now, but I just feel like pointing this out:
Spinning the angle 20 000+ degrees is extremely easy for the computer, it goes something like Current angle = 100500 --> Current Angle + 20000 = 120500 --> Update graphic so it faces angle 120500, the program does not attemp to spin the angle 1 degree by 1 degree for 20000 times or something that makes changing the angle by 20000 degrees more difficult than by 10.

I guess that the problem here is that your number exceeded the number of bits an integer variable can store. If you angle started off as 2, then 1 second later, it'll be 2^60 already, so you can imagine why the script died.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 28, 2009, 01:46:52 PM
So using angle%=360; is efficient and simple to solve the problem :)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 28, 2009, 08:06:58 PM
Another question.

I'm curious, is there a way to reduce or add ADDframe by frame?

Code: [Select]
SetAlpha(255); is the minimum opacity, so can I make it completely transparent if the value was set at 0.
I know there's a way to change the opacity depending on the frames.  If you have this set up @initialize

Code: [Select]
@initialize{
let variable = 0;
}


and this in @drawloop

Code: [Select]
SetAlpha(variable);
variable+=10;
if(variable==200){variable=0;}

You'll have a "pulsing" effect when the stuff is drawn.
What I want, is that same "pulsing" effect set with ADD rendering.


Any ideas?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on September 29, 2009, 12:22:30 AM
This is simple if the bullet itself is in ADD rendering...
else you may use
SetRenderState(ADD) (I doubt whether it works, some computer at school cannot open danmakufu)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on September 29, 2009, 12:44:11 AM
Quick question, what exactly does GetPlayerScriptName return? I can't seem to get it to recognize my player script in an if statement...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 29, 2009, 01:20:11 AM
The name you declared for replays, if I remember correctly (string).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: canobiecrazy on September 29, 2009, 02:24:48 AM
Im having a problem trying to start this game...

I try to install Applocale and I get the error,

"There is a problem with this Windows Installer package. A program required to complete could not be run."

Yes I have Vista, I have no idea what to do. Please someone help! :-[
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Jana on September 29, 2009, 02:26:49 AM
Applocale just plain doesn't work with Vista. It's XP only.

Quick Edit: Changing your system locale to Japanese will let you execute Danmakufu, if you don't mind that.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: canobiecrazy on September 29, 2009, 02:31:19 AM
Ahh, thanks! Let me try that... Lets see if it works..
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on September 29, 2009, 02:35:57 AM
Actually you can force Applocale to install in Vista.
Just do it through the command console or Task Manager (I'm not sure which one) and be sure of applying Admin Rights.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: canobiecrazy on September 29, 2009, 02:42:21 AM
BAHHH!!!

I used the Japanese Locale, changed my location to japan, and installed all japanese language fonts and it still dosent work! :-[
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 29, 2009, 05:14:39 AM
This is simple if the bullet itself is in ADD rendering...
else you may use
SetRenderState(ADD) (I doubt whether it works, some computer at school cannot open danmakufu)

Well, yeah, I know that.  But what I'm looking for is some kind of ADD value the same way I get an Alpha value.


Kinda like SetAlpha(255);

Except for ADDITIVE blending.   SetADD(255);
or any other value I want.  I'd like to get that "pulsing" effect I said earlier. It'll make some pretty cool effects.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on September 29, 2009, 08:22:31 AM
You want SetColor. The brightness of ADD type blending isn't determined by transparency, it's determined by how bright the colors of the image are. Therefore, by dimming the image with SetColor (by reducing the R,G,B values equally) you make it more transparent.

As a side note, boy howdy are you obsessed with recreating that phoenix background. To get ahead of what will probably be a question in the future, use SetGraphicScale to make the size of the ADD phoenix pulse along with its brightness.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Infy♫ on September 29, 2009, 02:42:02 PM
FOG
GOD DAMN FOG
ARRRRRRRGH I HATE IT
IT PRODUCES THE SAME UGLY ERRORS EVERY TIME
THE FOG COMES WITH THE BACKGROUNDS AS THEY GET CLOSER TO THE PLAYER CHARACTER >.>
wtf is this. and dont give stupid answers without actually testing it please. seriously.

i also got more problems with it. the alpha value does not let you see the underlying things.

this is my test script for today:
http://www.mediafire.com/?sharekey=f105d62fce2408b20dec85adfe0a530ae04e75f6e8ebb871
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on September 29, 2009, 09:19:28 PM
Applocale just plain doesn't work with Vista. It's XP only.

Or not. I've used applocale on two different systems running Vista, and it's worked perfectly for months now. I don't know how people are fucking this up, it's pretty straight forward (read: exactly the same) as XP, despite it saying otherwise. Do people not run things as administratior (or are not the default admin of their computer)? This is the only problem I can see. You can also run things under XP settings using Vista, so there is no excuse. Maybe torrenting Vista is a bad idea guys.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on September 29, 2009, 09:51:24 PM
You want SetColor. The brightness of ADD type blending isn't determined by transparency, it's determined by how bright the colors of the image are. Therefore, by dimming the image with SetColor (by reducing the R,G,B values equally) you make it more transparent.

As a side note, boy howdy are you obsessed with recreating that phoenix background. To get ahead of what will probably be a question in the future, use SetGraphicScale to make the size of the ADD phoenix pulse along with its brightness.

haha thanks.  And yeah... I'm kinda recreating the IN extra stage. ;D  I already had the GraphicScale part down perfectly, all I needed was what you said, so thanks.

So far, I got the things I finished were Keine's spellcards, 3 of Mokou's spellcards, the Phoenix effect(as soon as I'm done), and Mokou's BG.

The toughest part will probably be the whole blowing up/resurrection thing.  Looping yield doesn't work @finalize, so I'm going to have to find another way to delay the frames when the boss blows up.

By the looks of it, I may have to set the effects @initialize of the next spell, cause I don't know any function that I can use if(boss's life is 0){stuff happens;} in the current spellcard.  Oh well.

Title: Re: Danmakufu Q&A/Problem Thread
Post by: canobiecrazy on September 29, 2009, 10:44:02 PM
I got it working, just had to disable my UAC...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 01, 2009, 11:09:58 AM
I've encountered a very weird problem.

The same Spell Card I made is put in 2 different folders with the same source materials. But one of those works perfectly whilst another caused significant slow down.

Can somebody explain this?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: canobiecrazy on October 01, 2009, 08:48:35 PM
Im having a problem with this script.. I cant get shot replace to work. Can anyone tell me whats wrong with it?

Quote
   
   
   @Initialize{
      SetLife(1500);
      SetTimer(60);
shotinit;
      SetInvincibility(30);
      LoadGraphic(imgExRumia); //Load the boss graphic.
      SetMovePosition02(GetCenterX, GetCenterY - 100, 120); //Move the boss to the top center

of the screen.
   }
   
   @MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
   frame++;
   
   if(frame==120){
   
      loop(150){
         CreateShot01(GetX, GetY, 7, angle, RED52, 0);
         angle += 780/50;
      }
     
      angle = 0;
      frame = 60;
   }
   
   
   }

   @DrawLoop{
      //All this foolishness pertains to drawing the boss. Ignore everything in @Drawloop

unless you have read and understand Nuclear Cheese's Drawing Tutorial.
      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetTexture(imgExRumia);
      SetGraphicRect(64,1,127,64);
      DrawGraphic(GetX,GetY);
   }
     
   @Finalize
   {
      DeleteGraphic(imgExRumia);
   }
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on October 01, 2009, 08:53:28 PM
Im having a problem with this script.. I cant get shot replace to work. Can anyone tell me whats wrong with it?
Just looking...
Did you use #include_function "libSHOT_REPLACEshot_replace.dnh"; ?
Did you have all the // comments on one line?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on October 01, 2009, 08:55:16 PM
Did you remember to use...

#include_function "lib\SHOT_REPLACE\shot_replace.dnh"

...right above @Initialize? This grabs all of the code inside of the shot replace script, so that it can be called using shotinit. Also, a 150 bullet ring at speed 7 sounds insane. The average bullet speed is between 1 and 4, and 36 bullets per ring is a fair amount if you're aiming for a normal level script.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: canobiecrazy on October 01, 2009, 09:12:09 PM
Thanks for the help, I figured it out. Now I have a new question. How do I add another CreateShot01? I want to add a homing shot so the player cant stay in one safe spot for the entire attack.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on October 01, 2009, 09:20:26 PM
Use GetAngleToPlayer for the bullet angle if you want it to be aimed at the player. An actually homing shot would require knowledge of object bullets. I wouldn't mind walking you through it via PM, but it's relatively advanced.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 03, 2009, 01:37:24 PM
I am currently immitating the burning aura for bosses and such, however my code seems to cause Danmakufu to clog up and eventually get extreme FPS dropping after a while.

My method is the follow:
- An effect object task that spawns 1 particle using currently a 128x128 texture which is a light particle.
- The task is called within a loop which spawns the particle at random x-offset causing a nice burning aura/flame
- The effect objects scale down during the loop inside the task.

Here is the code for the loop which is inside the effect task.
Code: [Select]

loop {
Obj_SetPosition(obj,x,y);   
        ObjEffect_SetScale(obj, sx, sy);  // scaling
ObjEffect_SetAngle(obj,0,0,dir); // dir
  ObjEffect_SetVertexColor(obj,0,alphret,255,255,255);
ObjEffect_SetVertexColor(obj,1,alphret,255,255,255);
  ObjEffect_SetVertexColor(obj,2,alphret,255,255,255);
  ObjEffect_SetVertexColor(obj,3,alphret,255,255,255);
alphret-=5;  // this is for decreashing alpha value
y-=3; 
dir+=5;
sx-=0.01;  // scales down
sy-=0.01;   // scales down
if(c==60){Obj_Delete(obj);}   // after 60 frames delete the object.
c++;
yield;
}

But it still causes FPS drop =,= why ?

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 03, 2009, 03:22:42 PM
Is the loop terminating correctly once the object is deleted? I dunno I can't see the code around it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 03, 2009, 03:35:51 PM
There is nothing after the loop , only a } which is the end of the task. The loop is terminated correctly?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 03, 2009, 03:41:43 PM
Wait, is it actually a loop and not a while? With no number of iterations specified? If you do that the loop won't end, right? It should be like, loop(61){ shouldn't it?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 03, 2009, 04:44:05 PM
Should I replace it with   while(!Obj_BeDeleted)? 

I think indeed the loop is a problem. Let me go try that out.

Edit:

while(!Obj_BeDeleted) fixed the problem. Note to self: "Dnh does not like loops in effects and objects if it is not killed proper"
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 03, 2009, 09:49:13 PM
ok i have a few questions, while i was messing with angle+= i came across something ive ever seen before

 
Code: [Select]
#TouhouDanmakufu
#Title[Freaky Bullets]
#Text[]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
    let frame = 0;
    let angle = 0;
#include_function "lib\SHOT_REPLACE\shot_replace.dnh"
    @Initialize {
SetMovePosition02(GetCenterX, GetCenterY-120, 120);
        SetLife(900);
        SetDamageRate(100, 50);
        SetTimer(600);
        SetScore(50000);
        SetEnemyMarker(false);
        Concentration01(60);
        Concentration02(60);
        MagicCircle(false);
shotinit;
    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 32);
        SetCollisionB(GetX, GetY, 24);
    frame++;
if(frame%1==0){
angle+=17493;
CreateShot01(GetX,GetY,2,angle+10,AQUA56,0);
CreateShot01(GetX,GetY,2,angle+20,RED56,0);
CreateShot01(GetX,GetY,2,angle+30,BLUE56,0);
CreateShot01(GetX,GetY,2,angle+40,PURPLE56,0);
CreateShot01(GetX,GetY,2,angle+50,ORANGE56,0);
CreateShot01(GetX,GetY,2,angle+60,WHITE56,0);
CreateShot01(GetX,GetY,2,angle,YELLOW56,0);
CreateShot01(GetX,GetY,2,angle+70,GREEN56,0);
}
    }

@DrawLoop{
}

@Finalize
{
}
}

Causes HUGE bullets to fill the screen, why is this?

and also, angle+= only makes the bullets go clockwise, it there a way to make them go counterclockwise? i tried putting the number at the end of angle+= negative butno such results, any ideas?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 03, 2009, 10:24:40 PM
Someone was talking about this earlier today in IRC, for some reason putting a gigantic value in the angle causes some sort of overflow that makes the shot weird out.

The inverse to += is -=, naturally.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 03, 2009, 10:34:12 PM
Alright, I have a problem.  I wanted to make a stage script, but I don't think I should have started off the way I did.

I made my spellcards, tested them, they worked, etc etc.  I put them together with a plural script, then I said "bah, I'll just make a stage altogether".

Just when I thought I had this Danmakufu down, it started getting really irritating.


I was putting together a stage script composed of plural scripts for the boss's spellcards.
I wanted the Stage to have it's own background, and the boss's spellcards have its own, depending on whether it was a pre-spellcard or not.

I wanted just a few things I put in the stage script, and build off of that as I go.  I started off very simple.


Code: [Select]
#TouhouDanmakufu[Stage]
#Title[Mokou Stage]
#Text[The stage, Mokou is the boss.]
#Player[FREE]
#ScriptVersion[2]

script_stage_main{

              let background3 = GetCurrentScriptDirectory~"background3.png";




@Initialize{

      LoadGraphic(background3);
      immortal;

}

@Mainloop{
yield;
}



@DrawLoop{
}



@BackGround{

      SetTexture(background3);
      SetGraphicAngle(0,0,0);
      SetGraphicRect(0, 0, 384, 448);
      SetGraphicScale(1,1);
      DrawGraphic(GetCenterX, GetCenterY);

}


@Finalize{
DeleteGraphic(background3);
}


task immortal{
             
          }



}
Everything worked nicely, the background loaded, no crash.
Then I put in the path for the plural script that lead to the boss's spellcards.

Code: [Select]
task immortal{
             
          CreateEnemyBossFromFile(GetCurrentScriptDirectory ~ "Plural.txt",GetCenterX,0,2,90,NULL);
            }

It didn't load.  No error either, but it was just as if I never put in anything at all. To find out where I went wrong, I decided to replace the string for the plural script, to the individual spell script which I tested and worked when loaded by itself (it also had its own background for that spellcard, so it should have loaded too).
But it didn't.  Just the blank stage, with the background which I commanded for the stage script to load.
What's going on here? Why don't my scripts load?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 04, 2009, 01:30:58 AM
- Try putting a loop(60){yield;} in front of the CreateBoss line. Functions can fail sometimes if you try to load them instantly when the script starts. This will put a bit of delay in front of it.
- Filenames are case sensitive, make sure the file isn't called plural.txt rather than Plural.txt
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 04, 2009, 02:17:12 AM
- Try putting a loop(60){yield;} in front of the CreateBoss line. Functions can fail sometimes if you try to load them instantly when the script starts. This will put a bit of delay in front of it.
- Filenames are case sensitive, make sure the file isn't called plural.txt rather than Plural.txt


It didn't work.
Maybe I'm missing something.  Can you bring out/upload a very simple stage script that loads a plural script for me?  Maybe I'm missing something.  Nothing seems to be working for me anymore.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 04, 2009, 02:22:09 AM
OH.

MainLoop. Not Mainloop. Capitalize the L. No yield, no task.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 04, 2009, 02:33:35 AM
OH.

MainLoop. Not Mainloop. Capitalize the L. No yield, no task.


Stuffman, you did it again.

akakldfja;kdja;skfjal;sfjskl;
Title: Re: Danmakufu Q&A/Problem Thread
Post by: canobiecrazy on October 04, 2009, 03:13:07 AM
Something is wrong with this script and I have no idea what....

Code: [Select]
#TouhouDanmakufu
#Title[Laxative Sign "Suppository Toss"]
#Text[Reisen throws a bunch of suppositorys.]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main{
 #include_function "lib\SHOT_REPLACE\shot_replace.dnh"
   let imgExRumia="script\ExRumia\img\ExRumia.png";
   let frame = 0;
   let angle = 0;
   @Initialize{
      shotinit;
      SetLife(1500);
      SetTimer(60);
      SetInvincibility(30);
      CutIn(YOUMU, "Laxative Sign "Suppository Toss", BossCutIn, 0, 0, 200, 600);
      LoadGraphic(imgExRumia); //Load the boss graphic.
      SetMovePosition02(GetCenterX, GetCenterY - 100, 120); //Move the boss to the top center

of the screen.
   }
   
   @MainLoop{
   SetCollisionA(GetX, GetY, 32);
   SetCollisionB(GetX, GetY, 16);
   frame++;
   
   if(frame==120){
   
      loop(150){
         CreateShot01(GetX, GetY, 7, angle, WHITE52, 0);
         angle += 780/50;
         CreateShot01(GetX, GetY, 3, GetAngleToPlayer, WHITE52, 10);
         Frame = 0;
      }
     
      angle = 0;
      frame = 60;
   }
   
   
   }

   @DrawLoop{
      //All this foolishness pertains to drawing the boss. Ignore everything in @Drawloop

unless you have read and understand Nuclear Cheese's Drawing Tutorial.
      SetColor(255,255,255);
      SetRenderState(ALPHA);
      SetTexture(imgExRumia);
      SetGraphicRect(64,1,127,64);
      DrawGraphic(GetX,GetY);
   }
     
   @Finalize
   {
      DeleteGraphic(imgExRumia);
   }
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on October 04, 2009, 03:34:13 AM
You capitalized "frame" inside of your 150 loop. Remember, Danmakufu is picky about cases.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: canobiecrazy on October 04, 2009, 03:47:09 AM
You capitalized "frame" inside of your 150 loop. Remember, Danmakufu is picky about cases.

Ahhh! Thank you! It works now, I just removed the line

 CutIn(YOUMU, "Laxative Sign "Suppository Toss", BossCutIn, 0, 0, 200, 600);

And changed that to a lower case f and it works fine now. Thank you.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 06, 2009, 10:34:51 AM
3D drawing is fun ze! NOT.

I don't know if anybody ever did this before. I made a full cubical room in 3D drawing. The room looks nice and dandy. Now my genius idea was to move the camera around inside the room giving it a flight sensation. ( Altering SetViewTo and SetViewFrom parameters )

However, when the camera moves forward like 512 pixels, it resets and reverses 180 degree moving backwards. I cannot show anything yet here because I am at work.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on October 06, 2009, 11:08:43 AM
Hm, are you moving the entire stage, or only the camera? I have only done forward/backward movement by stage-scrolling so I can't say for sure that the camera may have a distance limit to it. As for the 180 turn, no clue o_O Try changing the scrolling speed, see what difference that makes.

3D drawing is fun ze! NOT.

I don't know if anybody ever did this before. I made a full cubical room in 3D drawing. The room looks nice and dandy. Now my genius idea was to move the camera around inside the room giving it a flight sensation. ( Altering SetViewTo and SetViewFrom parameters )

However, when the camera moves forward like 512 pixels, it resets and reverses 180 degree moving backwards. I cannot show anything yet here because I am at work.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 06, 2009, 11:33:36 AM
I am not scrolling the 3D images, I am only moving the camera view around. It is hard to explain. I will try to create a movie, please wait warmly.


Download little movie here (http://www.taihou.nl/weird3D.mp4) and see what happens.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 06, 2009, 05:33:44 PM
I have a strange urge to play Doom again...

Anyway it might've been some kind of math error? Seeing the code would be better, as well as knowing how the camera is supposed to move. Do you want it to turn when it reaches the wall or something?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 07, 2009, 12:57:52 AM
is there a way to have a follow a player around? Like keep checking where the player is? ive tried making CreateShotA's and multiple SetShots that tell the bullet to always GetAngleToPlayer,
but it only goes in the one direction, and ive also tried setting a variable for GetAngleToPlayer, and that has failed as well.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on October 07, 2009, 01:00:26 AM
Make an object bullet and get the angle to the player using arctangent every frame
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 07, 2009, 01:03:31 AM
Make an object bullet and get the angle to the player using arctangent every frame

aahh! object bullets!! grr..those are the ones you make using tasks right?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on October 07, 2009, 01:08:20 AM
aahh! object bullets!! grr..those are the ones you make using tasks right?
Yep
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 07, 2009, 01:20:07 AM
Yep
a quick question about tasks, if there are these:
Bullet(x, y, v, angle)
what does this mean? its not defined in the turorial.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on October 07, 2009, 01:25:49 AM
Yep

Hint - you don't need to use tasks for object shots.  That's how I use them in the tutorial I write (http://dmf.shrinemaiden.org/wiki/index.php?title=Nuclear_Cheese%27s_Shot_Object_Tutorial)

Personally, I hate Danmakufu's task setup, and avoid it whenever possible.  But that's just me.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 07, 2009, 01:34:39 AM
Hint - you don't need to use tasks for object shots.  That's how I use them in the tutorial I write (http://dmf.shrinemaiden.org/wiki/index.php?title=Nuclear_Cheese%27s_Shot_Object_Tutorial)

Personally, I hate Danmakufu's task setup, and avoid it whenever possible.  But that's just me.
lol right as i found it, that really is kind of messy how its set up, i want to try to make multiple of
them so i tried looping them and only one followed the player.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 07, 2009, 05:44:18 AM
I have a strange urge to play Doom again...

Anyway it might've been some kind of math error? Seeing the code would be better, as well as knowing how the camera is supposed to move. Do you want it to turn when it reaches the wall or something?

I want to perform a circle inside the big room but let alone the circle, even just going straight forward messes it up. Here is the code.

Note that f++ is disabled. So the 3D objects are not scrolling.

Code: [Select]
flight+=5;

// pre stuff
WriteZBuffer(true);
      UseZBuffer(true);
SetViewTo(0,256,0);
SetViewFrom(1024+flight,270,0);
SetPerspectiveClip(0,8000);

// Normal bg
if(dc<10){SetTexture(bg);}
if(dc>=10 && dc<20){SetTexture(bg2);}
if(dc>=20 && dc<30){SetTexture(bg3);}
if(dc>=30 && dc<40){SetTexture(bg4);}
if(dc>=40 && dc<50){SetTexture(bg5);}
SetRenderState(ALPHA);
SetAlpha(255);
SetColor(255,255,255);
SetGraphicRect(0,0,768,512);
SetGraphicAngle(180,0,0);
SetGraphicScale(0.1,0.1);
DrawGraphic3D(0,gview,0);

//SetFog(0,3000,0,0,0);

makevloer(0,0,-1024+f);
makevloer(1024,0,-1024+f);
makevloer(2048,0,-1024+f);

makevloer(0,0,f);
makevloer2(1024,0,f);
makevloer(2048,0,f);

makevloer(0,0,1024+f);
makevloer(1024,0,1024+f);
makevloer(2048,0,1024+f);

// centraal plafon
makeplafoncenter(0,800,-1024+f);
makeplafoncenter(1024,800,-1024+f);
makeplafoncenter(2048,800,-1024+f);

makeplafoncenter(0,800,f);
makeplafoncenter(1024,800,f);
makeplafoncenter(2048,800,f);

makeplafoncenter(0,800,1024+f);
makeplafoncenter(1024,800,1024+f);
makeplafoncenter(2048,800,1024+f);

// links
makemuur(-512,192,-1024+f,90);
makemuur(-512,192,f,90);
makemuur(-512,192,1024+f,90);

// voor
makemuur(0,192,-1536+f,0);
makemuur(1024,192,-1536+f,0);
makemuur(2048,192,-1536+f,0);

// rechts
makemuur(2560,192,-1024+f,90);
makemuur(2560,192,f,90);
makemuur(2560,192,1024+f,90);

// achter
makemuur(0,192,1536+f,0);
makemuur(1024,192,1536+f,0);
makemuur(2048,192,1536+f,0);

// plafon links
makeplafon(-336,616,-1024+f,90);
makeplafon(-336,616,f,90);
makeplafon(-336,616,1024+f,90);

// plafon voor
makeplafon(0,616,-1352+f,0);
makeplafon(1024,616,-1352+f,0);
makeplafon(2048,616,-1352+f,0);

// plafon rechts
makeplafon(2384,616,-1024+f,270);
makeplafon(2384,616,f,270);
makeplafon(2384,616,1024+f,270);

// plafon achter
makeplafon(0,616,1352+f,180);
makeplafon(1024,616,1352+f,180);
makeplafon(2048,616,1352+f,180);

        //f++;
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Lawence Codye on October 07, 2009, 03:32:01 PM
I need help bad...my player's unfocused bullets do more then her focused bullets do...can't seem to fix this...& yes, I tried but I'm new with this script type.  I get to this point & brickwall...could someone download my script below...
http://www.mediafire.com/?sharekey=388cf395c6d90a0a391d7d881749d3a7487d47f3656e0f0f4ad239450a8c1cf1 (http://www.mediafire.com/?sharekey=388cf395c6d90a0a391d7d881749d3a7487d47f3656e0f0f4ad239450a8c1cf1)
& find what's causing this possibly...please...thank you...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 07, 2009, 05:08:24 PM
Well... You're shooting 17 bullets every eight frames when unfocused versus three bullets every six frames when focused. Though the three bullets have slightly more damage per bullet (3.0 vs 2.5), you're still doing 17*2.5=42.5 damage every 8 frames when unfocused, versus 3*3=9 damage every 6 frames. That's a difference of...

(60/8)*42.5 = 318.75 dps unfocused; shotgun.

(60/6)*9 = 90 dps focused; shotgun.

Or an overall difference of 318.75/90 = 3.54167 times more damage per second.

Well that's good and all, so where did you screw up. The answer lies in your @MainLoop: the while(i<=3){} statements. For focused movement, you declare i=3 before beginning the while statement, meaning the statement is preformed once, so three bullets are fired every six frames (player and both options). For unfocused, you declare i=-3 before starting the while statement, meaning the the action is preformed seven times as i is incremented every while statement. For your options, the condition is only preformed five times since you declare i=-2 and have a while statement while(i<=2){}, meaning 17 bullets are fired every eight frames (5+5+7=17). Simply fix your negatives for the i declarations before the while statements for your player shots and both options -- this should give you relatively close dps for focused and unfocused movement, save for the damage differences between the shots (3.0 vs 2.5) as well as the different firerate (7.5 times/second vs 10 times/second).

Hopefully I explained this clearly, I didn't want to include code snippets since you only have the six while statements...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 07, 2009, 05:15:49 PM
Oh, Helepolis; I think the problem is that you want to scroll your SetViewTo rather than your SetViewFrom.

SetViewTo=what your camera is looking at
SetViewFrom=where your camera is looking at it from

You're going to want to maintain the same camera distance (probably) and just move it around so I would have your SetViewTo scale instead. I don't know if that's actually the source of your problem, it's just another thing you could try that could make it go away  :V

Note: You WILL have to change the angle on SetViewFrom when you go to add the turning.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on October 07, 2009, 07:27:02 PM
Hm! I'm trying to recreate the effect of Utsuho's 2nd spell where the bullets shrink as time passes.
So far I cough this up:

Code: [Select]
if(frame%10==0 && frame>60){
shot=(Obj_Create(OBJ_EFFECT));
Obj_SetCollisionToPlayer(shot,true);
Obj_SetPosition(shot,cx+rand(-150,150),miny);
ObjEffect_SetLayer(shot,5); Obj_SetAngle(shot,90);
Obj_SetSpeed(shot,2);
ObjEffect_SetTexture(shot,GRbullet);
ObjEffect_SetPrimitiveType(shot,PRIMITIVE_TRIANGLESTRIP);
ObjEffect_CreateVertex(shot,4);
ObjEffect_SetScale(shot,1,1);
ObjEffect_SetVertexXY(shot,0,-128,-128); ObjEffect_SetVertexUV(shot,0,0,0);
ObjEffect_SetVertexXY(shot,1,128,-128); ObjEffect_SetVertexUV(shot,1,256,0);
ObjEffect_SetVertexXY(shot,2,-128,128); ObjEffect_SetVertexUV(shot,2,0,256);
ObjEffect_SetVertexXY(shot,3,128,128); ObjEffect_SetVertexUV(shot,3,256,256);
hitbox=hitbox~[shot];
}
let i=0;
while (i<length(hitbox)){
SetCollisionB(Obj_GetX(hitbox[i]),Obj_GetY(hitbox[i]),100);
if(Obj_BeDeleted(hitbox[i])){
hitbox=erase(hitbox,i);
i--;
}
else{
ObjEffect_SetScale(hitbox[i],1-?,1-?);
}
i++;
}

But I can't seem to find a way to make each individual bullet shrink over time. Any ideas?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 07, 2009, 08:10:04 PM
And this is why you should use tasks :V because object bullets written in task receive individual parameters when spawned.

@Stuffman,

Haven't been able to try out your suggestion. Going to bed soon. Will do it tommorow and update you about it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on October 08, 2009, 01:57:26 AM
And this is why you should use arrays :V

Fixed that for you. :D

Sorry, I just really hate Danmakufu's tasks that much.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 08, 2009, 02:35:56 AM
Sorry, I just really hate Danmakufu's tasks that much.

LOL, but how can you check collision with arrays? A lot of searching is required... (but still faster than tasks?)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 08, 2009, 06:46:00 AM
Sorry, I just really hate Danmakufu's tasks that much.

But I love em ! And Arrays are also an option ye. But whatever floats yours boat.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on October 08, 2009, 06:50:49 AM
And this is why you should use tasks :V because object bullets written in task receive individual parameters when spawned.

So you know how to fix it then? =|
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 08, 2009, 07:11:40 AM
So you know how to fix it then? =|

I can only tell you the tasking method as I have no expirience with the array method.

task shrinkingbullet(x,y,v,dir,graphic,delay,scale){
   let shot = Obj_Createshotect(OBJ_EFFECT);

   Obj_SetPosition(shot,x,y);
   Obj_SetSpeed(shot,v);
   ...
   etc etc... (

   <I forgot the code for the scale (please look it up on wiki, which is the starting scale.>


   while(!Obj_BeDeleted){

      < Here the code for shrinking the bullet over time >

        }

}


Now somewhere in your MainLoop you simply call: shrinkingbullet(......); and fill the parameters like where you want it to spawn, speed, dir etc etc.

And that's it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 08, 2009, 02:08:06 PM
Hi.
In the stage tutorial, a function WaitforZeroEnemy is used.
However, if the player cannot kill all the enemies, the stage stuck there.
What can be the solution to this?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 08, 2009, 02:28:49 PM
Hi.
In the stage tutorial, a function WaitforZeroEnemy is used.
However, if the player cannot kill all the enemies, the stage stuck there.
What can be the solution to this?

Are you using enemies that move inside the field and move out again? Like ZUN does in his most games. If you make the enemies move off the screen, it would be wise to make them vanish or delete so.

Or when the boss enters the screen you can kill off all enemies like ZUN also does.

Bullets are autodeleted off the screen, but cannot say the same about enemies.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 08, 2009, 02:44:09 PM
My idea is that:
let count=2;
if(the enemy cross the border, entering the screen area){count--;}
if(the enemy cross the border, leaving the screen area){count--;}
if(count==0){VanishEnemy;}

I'll work it out.

P.S. It works, but the items are spawn anyway. This problem can be easily solved.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Aphid on October 08, 2009, 03:25:20 PM
It took me long enough, but I got something that does what I want it to do, it's still got one problem though, framerate. Essentially I'd like this code to run at least 400% faster than it does now. Any tips on how?;

This code is in a separate file loaded using #include_script.
In addition, in @MainLoop, there is one statement of RedAimingShots(f).
There's also an f++ in MainLoop, of course.

Currently, the code works perfectly as far as the bullet pattern is concerned.
Currently, the code slows down even a decent computer to a crawl.

Code: [Select]

task CreateShotRed(let x, let y, let speed, let angle)
{
let counter =0;
  let objr = Obj_Create(OBJ_SHOT);
  ArrayShotRed = ArrayShotRed ~ [objr];
Obj_SetX(objr, x);
Obj_SetY(objr, y);
Obj_SetSpeed(objr, speed);
Obj_SetAngle(objr, angle);
ObjShot_SetGraphic(objr, RED02);

while( !Obj_BeDeleted(objr))
{




if(counter > (GetCenterX()*speed*cos((angle))-x*speed*cos

((angle))+GetCenterY()*speed*sin((angle))-y*speed*sin((angle))+0.5*

(speed^2*(8*GetCenterX()*x-4*(x^2+y*(-2* GetCenterY()+y))+4*((GetCenterX()-

x)*cos((angle))+(GetCenterY()-y)*sin((angle)))^2))^0.5)/speed^2) {

ObjShot_Delete(objr);
break;
}
counter++;
yield;
}
let iterator = 0;
loop(length(ArrayShotRed))
{
if(ArrayShotRed[iterator] == objr)
{
ArrayShotRed = erase(ArrayShotRed, iterator);
break;
}
iterator++;
}

}
task CollisionShotsBlue(let x, let y, let speed, let angle)
{
let count=0;
let objb = Obj_Create(OBJ_SHOT);
Obj_SetX(objb, x);
Obj_SetY(objb, y);
Obj_SetSpeed(objb, speed);
Obj_SetAngle(objb, angle);
ObjShot_SetGraphic(objb, BLUE01);
ObjShot_SetDelay(objb, 0);

while( !Obj_BeDeleted(objb))
{
let iteratortwo=0;
loop(length(ArrayShotRed))
{
if(Collision_Obj_Obj(ArrayShotRed[iteratortwo],

objb) == true)
{
CreateShotA(100, x + cos(angle) * speed * count, y +

sin(angle) * speed * count, 0);
SetShotDataA(100, 0, speed * 2, -angle, 0, 0, 20,

RED01);
FireShot(100);
Obj_Delete(objb);
}
iteratortwo++;
}

if(count == 300)
{
ObjShot_FadeDelete(objb);
break;
}
count++;
yield;
}


}


task RedAimingShots(let ftwo) {
ascent(i in 0..36)
{
if(ftwo == 7860 + 60 * i)
{
CreateShotA(2, 224, 30, 0);
SetShotDataA(2, 0, 3.1415 * 210 / 52.5, 0, 180 / 52.5, 0, 20,

RED03);
SetShotDataA(2, 60, NULL, NULL, 0, 0, 20, RED03);
FireShot(2);
CreateShotA(2, 224, 30, 0);
SetShotDataA(2, 0, 3.1415 * 210 / 52.5, 180, -180 / 52.5, 0, 20,

RED03);
SetShotDataA(2, 60, NULL, NULL, 0, 0, 20, RED03);
FireShot(2);
}
ascent(k in 1..4) {
if(ftwo == 7860 + 60 * i + 15 * k) {
let Rthree =  ((GetPlayerX - GetCenterX - 210 * sin(51.428 * k))^2 +

(GetPlayerY - GetCenterY + 210 * cos(51.428 * k))^2)^0.5;
let angthree = atan2((GetPlayerY - GetCenterY + 210 * cos(51.428 *

k)),(GetPlayerX - GetCenterX - 210 * sin(51.428 * k)));
CreateShotRed(224 + 210 * cos(51.428 * k - 90), 240 + 210 * sin

(51.428 * k - 90), Rthree / 90, angthree);
let Rthree =  ((GetPlayerX - GetCenterX + 210 * sin(51.428 * k))^2 +

(GetPlayerY - GetCenterY + 210 * cos(51.428 * k))^2)^0.5;
let angthree = atan2((GetPlayerY - GetCenterY + 210 * cos(51.428 *

k)),(GetPlayerX - GetCenterX + 210 * sin(51.428 * k)));
CreateShotRed(224 - 210 * cos(51.428 * k - 90), 240 + 210 * sin

(51.428 * k - 90), Rthree / 90, angthree);

ascent(j in 0..90) {
CollisionShotsBlue(GetCenterX, GetCenterY, 1, 4 * j + k + atan2

((GetPlayerY - GetCenterY),(GetPlayerX - GetCenterX)))
}
}
}
}
}


Essentially, it uses up two arrays. Had a third array but I scrapped that idea (which was giving the angle of the blue bullets turned red the angle of the bullet that had caused that +- rand10), and simply changed it to reverse angle. The latter didn't make much of a visual diffrence but it saved me one array.

anyways, I went with larger bullets (90) and had the whole thing erase unneeded spaces from both two object bullet groups. (I.e. all bullets going outside of a circle with radius 300 or so from the centerX, centerY space are checked for deletion each frame).

As for the large formulae, here's an idea of what they do.
"         if(count == 300)"
300: The speed is 1, so that puts it outside of the circle.

((GetPlayerX - GetCenterX - 210 * sin(51.428 * k))^2 + (GetPlayerY - GetCenterY + 210 * cos(51.428 * k))^2)^0.5
Basically gives the distance between each k-th spawn point for the reds and the player.

atan2((GetPlayerY - GetCenterY + 210 * cos(51.428 * k)),(GetPlayerX - GetCenterX - 210 * sin(51.428 * k)));
Same, Angle.

if(counter > (GetCenterX()*speed*cos((angle))-x*speed*cos((angle))+GetCenterY()*speed*sin((angle))-y*speed*sin((angle))+0.5*(speed^2*(8*GetCenterX()*x-4*(x^2+y*(-2* GetCenterY()+y))+4*((GetCenterX()-x)*cos((angle))+(GetCenterY()-y)*sin((angle)))^2))^0.5)/speed^2)

Well, um... this basically calculates how long a red bullet will at most need to stay in the array. I mean, it calculates the time it would take for a red bullet to move outside of the boundary set by my circle. It's a result from a quadratic polynomial in 't'.

As for a potential hint to the solution, it seems that the speed of this script is directly proportional to:
- The amount of blue bullets onscreen ==> This is a good sign, it means that the evaluations whether or not a bullet needs to be removed to save processor power are not hogging said processor power.
- The amount of Red Bullets onscreen ==> once again, same reason.

I'm still a bit stuck here what else I can do to make it run at 60fps flat without having to change the pattern in any way.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 08, 2009, 04:28:36 PM
@Stuffman,

Haven't been able to try out your suggestion. Going to bed soon. Will do it tommorow and update you about it.

You were right, using the SetViewTo is better, it works now and I can make a 90 degree turn and keep heading. But I just discovered I need to enlarge my disco stage because when I turn the camera is too far away I end up outside the room :V. Or adjust my SetViewFrom more closer to the center point.

=D thanks.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 08, 2009, 06:26:44 PM
Aphid, post your main file as well, I'm having trouble getting it to even run. It errors on f (so I then declared f = 0;), then on ArrayShotRed (so I declared let ArrayShotRed = []; ), then on ObjShot_Delete(objr) (so I changed it to Obj_Delete(objr); ).

Well now it runs.... But nothing happens. Yes, I have f++; and AimedRedShot(f) in @MainLoop.

So yeah, post the code, please. Or PM it if you'd rather.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: puremrz on October 08, 2009, 07:24:50 PM
I can only tell you the tasking method as I have no expirience with the array method.

task shrinkingbullet(x,y,v,dir,graphic,delay,scale){
   let shot = Obj_Createshotect(OBJ_EFFECT);

   Obj_SetPosition(shot,x,y);
   Obj_SetSpeed(shot,v);
   ...
   etc etc... (

   <I forgot the code for the scale (please look it up on wiki, which is the starting scale.>


   while(!Obj_BeDeleted){

      < Here the code for shrinking the bullet over time >

        }

}


Now somewhere in your MainLoop you simply call: shrinkingbullet(......); and fill the parameters like where you want it to spawn, speed, dir etc etc.

And that's it.

Putting that in my script gave both me and Danmakufu nightmares (There's something that I just can't learn about tasks. And that's getting them to work D:)
But I found my own way around it. Of course without tasks, as usual for me. (That makes us task/array rivals, bwahahah) :P

Code: [Select]
if(frame%10==0 && frame>60){
let i=0;
shot=(Obj_Create(OBJ_EFFECT));
Obj_SetCollisionToPlayer(shot,true);
Obj_SetPosition(shot,cx+rand(-150,150),rand(0,30));
ObjEffect_SetLayer(shot,4); Obj_SetAngle(shot,90);
Obj_SetSpeed(shot,3);
ObjEffect_SetTexture(shot,GRbullet);
ObjEffect_SetPrimitiveType(shot,PRIMITIVE_TRIANGLESTRIP);
ObjEffect_CreateVertex(shot,4);
ObjEffect_SetScale(shot,1,1);
ObjEffect_SetVertexXY(shot,0,-128,-128); ObjEffect_SetVertexUV(shot,0,0,0);
ObjEffect_SetVertexXY(shot,1,128,-128); ObjEffect_SetVertexUV(shot,1,256,0);
ObjEffect_SetVertexXY(shot,2,-128,128); ObjEffect_SetVertexUV(shot,2,0,256);
ObjEffect_SetVertexXY(shot,3,128,128); ObjEffect_SetVertexUV(shot,3,256,256);
ObjEffect_SetVertexColor(shot,0,200,255,255,255); ObjEffect_SetVertexColor(shot,1,200,255,255,255);
ObjEffect_SetVertexColor(shot,2,200,255,255,255); ObjEffect_SetVertexColor(shot,3,200,255,255,255);
hitbox=hitbox~[shot];
}
if(frame>50){
let i=0;
shrink=shrink~[shot];
while (i<length(hitbox)){
if(Obj_BeDeleted(hitbox[i])){
hitbox=erase(hitbox,i);
i--;
}
else{
ObjEffect_SetAngle(hitbox[i],0,0,time*5);
shrink[i]=1-(Obj_GetY(hitbox[i])/500);
SetCollisionB(Obj_GetX(hitbox[i]),Obj_GetY(hitbox[i]),shrink[i]*70);
ObjEffect_SetScale(hitbox[i],shrink[i],shrink[i]);
}
i++;
}

}

Bullets shrink as they move down (cough Utsuho 2 cough). But it depends on their Y, and not on the time spent on the field. It's probably just a minor change, but I can't think of a way to give each their own timer.


Sorry, I just really hate Danmakufu's tasks that much.

<3
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Aphid on October 08, 2009, 09:19:04 PM
Aphid, post your main file as well, I'm having trouble getting it to even run. It errors on f (so I then declared f = 0;), then on ArrayShotRed (so I declared let ArrayShotRed = []; ), then on ObjShot_Delete(objr) (so I changed it to Obj_Delete(objr); ).

Well now it runs.... But nothing happens. Yes, I have f++; and AimedRedShot(f) in @MainLoop.

So yeah, post the code, please. Or PM it if you'd rather.
I'm not very surprised you didn't get it to work with just f++. f, in my code, is a long-running counter from a couple previous code sections. It's actually at like 6000 or so when the script starts so you'd be expected to see nothing for two minutes, yes. If I ever wanted an overarching theme linked to f it would be easier to implement that way. Oh and it's reducing the amount of math I have to do when calculating frames for each note's time. (the thing's linked to music  ;))

Right, if you want to make the whole thing as it is here on my pc... errhm... well you'd need a couple more files. 'neways, you'll need to call the code about the circle CIRCS.txt, the last bit from the previous post was BLUERED.txt. Oh, and you'll also need "HorizontalFamiliarCircle.txt".
I've tried to comment out all the references to extra files and/or delete those lines but there could be a couple left.

Before you try running it, make sure you do have math.h on your system's main C compiler (some extra math functions):

incoming walls of code.

Code: [Select]

/*Danmakufu Pattern No.1. Remi @ Beethoven's 8th Sonata (The "Grande Sonate Path鑼ique").*/
/*1st Movement. (first movement)*/

#TouhouDanmakufu
#include<math.h>   
#Title[Allegro Repeated]
#Text[First Movement, first fast part]
/*#Image[.\remi1.jpg]*/
/*#BackGround[User(.\bg.png, 1, 1)]*/
#PlayLevel[Phantasm]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {

#include_function "lib\SHOT_REPLACE\shot_replace.dnh";
#include_script ".\CIRCS.txt";
   
    /*let BI=GetCurrentScriptDirectory~"BIM1.jpg";
    let BCI=GetCurrentScriptDirectory~"Remi3.jpg";*/
    let f=5400;
    let g=0;
    let ang=0;
    let z=0;
    let h=0;
    let lz=0;
    let W = "STRING";
    let Q = "zero";
    let Z = "zero";
    let hg = 0;
let ArrayShotRed = [];
let ArrayShotRedTwo = [];

function GetDistance(x1, y1, x2, y2)
{
    return ((x1-x2)^2 + (y1-y2)^2)^0.5
}
function ScarletShoot(SCAX, SCAY, SCAV, SCAA, DELAY)
{
CreateShot01(SCAX, SCAY, SCAV, SCAA, RED03, DELAY);
ascent(i in 0..3) {
CreateShot02(SCAX, SCAY, SCAV - 0.1 - 0.1 * i, SCAA + rand(-15, 15), - 0.003 * i, 0.2, RED02, DELAY);
}
ascent(j in 0..24) {
CreateShot02(SCAX, SCAY, SCAV - 0.25 - 0.025 * j, SCAA + rand(-25, 25), -0.0005 * j, 0.2, RED04, DELAY);
}

}


@Initialize {

// LoadUserShotData(GetCurrentScriptDirectory~"udb2.txt");
// LoadGraphic(BI);
SetLife(1000000);
        SetDamageRate(100,0);
        SetTimer(123);
        SetInvincibility(60);
// CutIn(YOUMU, "Scarlet Sign "\""Allegro"\", BCI, 0, 0, 420, 400);
      SetScore(4320000);
        SetEnemyMarker(true);
        SetDurableSpellCard;
SetY(40);
shotinit;
}

@MainLoop {
SetCollisionA(GetX, GetY, 42);
        SetCollisionB(GetX, GetY, 42);
if(f == 5400) {

SetMovePosition02(GetCenterX, 40, 20);
ascent(q in 0..3) {
ascent(h in 1..4) {
CreateLaserB(1, 500, 20, RED01, 45);
SetLaserDataB(1, 0, 0, 0, 0, 45 * q + 15 * h, 0, 45 * q + 15 * h, 0);
SetShotKillTime(1, 120);
FireShot(1);
}
}
}
if(f == 12000) {
hg = 20; }

if(f == 5460){
HCircleFamiliar(1, BLUE03, f, 1, 0, 960);
HCircleFamiliar(1, BLUE03, f, -1,0, 960);
HCircleFamiliar(1, RED03, f, 1,90, 960);
HCircleFamiliar(1, RED03, f, -1,90, 960);
}
if(f == 6900){
HCircleFamiliar(1, BLUE03, f, 1, 0, 840);
HCircleFamiliar(1, BLUE03, f, -1,0,  840);
HCircleFamiliar(1, RED03, f, 1,90, 840);
HCircleFamiliar(1, RED03, f, -1,90, 840);
}


if (((f > 5459 && f < 6421) || (f > 6899 && f < 7741)) && round(f / 15) - f / 15 == 0)
{

ascent(q in 0..3) {
ascent(h in 0..3) {
let i = 0;
CreateShot01(GetX + 180 * sin(f / 3), GetY, 4, 58 + 24 * h + 8 * q, BLUE11, 0);
CreateShot01(GetX - 180 * sin(f / 3), GetY, 4, 58 + 24 * h + 8 * q, BLUE11, 0);
CreateShot01(GetX + 180 * sin(f / 3 + 2.5), GetY, 4, 58 + 24 * h + 8 * q, BLUE11, 7.5);
CreateShot01(GetX - 180 * sin(f / 3 + 2.5), GetY, 4, 58 + 24 * h + 8 * q, BLUE11, 7.5);
CreateShotA(1, GetX + 180 * cos(f / 3), GetY, 0);
if(q == 2) {
i = 0;
}
else {
i = 1;
}

SetShotDataA(1, 0, 3, 90, 0, 0, 3, RED02);
SetShotDataA(1, 60, 3, 70 + 20 * h, (-1)^q * 1.6 * i, 0, 10, RED01);
SetShotDataA(1, 90, NULL, NULL, 0, 0, 10, RED01);
FireShot(1);
CreateShotA(1, GetX - 180 * cos(f / 3), GetY, 0);
SetShotDataA(1, 0, 3, 90, 0, 0, 3, RED02);
SetShotDataA(1, 60, 3, 70 + 20 * h, (-1)^q * 1.6 * i, 0, 10, RED01);
SetShotDataA(1, 90, NULL, NULL, 0, 0, 10, RED01);
FireShot(1);
}
}
}
if(f == 5505 || f == 5985) {
ascent(i in 1..34) {
CreateShot02(GetX, GetY, 8, GetAngleToPlayer + 10 + 10 * i, -0.02, 4, RED02, 0);
}
}
if(f == 5520 || f == 6000) {

ascent(i in 1..34) {
CreateShot02(GetX, GetY, 8, GetAngleToPlayer + 10 + 10 * i, -0.02, 4, ORANGE02, 0);
}
}
if(f == 5535 || f == 5625 || f == 6015 || f == 6105) {

ascent(i in 1..34) {
CreateShot02(GetX, GetY, 8, GetAngleToPlayer + 10 + 10 * i, -0.02, 4, YELLOW02, 0);
}
}
if(f == 5550 || f == 5640 || f == 6030 || f == 6120) {

ascent(i in 1..34) {
CreateShot02(GetX, GetY, 8, GetAngleToPlayer + 10 + 10 * i, -0.02, 4, GREEN02, 0);
}
}
if(f == 5565 || f == 5655 || f == 6045 || f == 6135) {

ascent(i in 1..34) {
CreateShot02(GetX, GetY, 8, GetAngleToPlayer + 10 + 10 * i, -0.02, 4, AQUA02, 0);
}
}
if(f == 5580 || f == 5670 || f == 6060 || f == 6150) {

ascent(i in 1..34) {
CreateShot02(GetX, GetY, 8, GetAngleToPlayer + 10 + 10 * i, -0.02, 4, BLUE02, 0);
}
}
if(f == 5595 || f == 5685 || f == 6075 || f == 6165) {

ascent(i in 1..34) {
CreateShot02(GetX, GetY, 8, GetAngleToPlayer + 10 + 10 * i, -0.02, 4, PURPLE02, 0);
}
}

if(f == 5700 || f == 5760 || f == 5820 || f == 5880 || f == 6180 || f == 6240 || f == 6300 || f == 6360 || f == 6420) {
ascent(l in 0..5) {
ascent(k in 0..3) {
ascent(i in 0..8) {
CreateShotA(1, GetX, GetY, 0);
SetShotDataA(1, 2 * i, 4, GetAngleToPlayer - (30 + 15 * l), 2 + l, 0, 10, YELLOW11);
ascent(j in 0..10) {
SetShotDataA(1, 30 * j + 30 + 2 * i, 4, NULL, (2 + l) * (-1) ^ (j + 1), 0, 10, YELLOW11);
}
FireShot(1);
CreateShotA(1, GetX, GetY, 0);
SetShotDataA(1, 2 * i, 4, GetAngleToPlayer + (30 + 15 * l), -2 - l, 0, 10, YELLOW11);
ascent(j in 0..10) {
SetShotDataA(1, 30 * j + 30 + 2 * i, 4, NULL, (2 + l) * (-1) ^ (j), 0, 10, YELLOW11);
}
FireShot(1);
}

}
}
}

if(f == 5730 || f == 5790 || f == 5850 || f == 5910 || f == 6210 || f == 6270 || f == 6330 || f == 6420) {
ascent(m in 0..2){
ascent(l in 0..5) {
ascent(k in 0..3) {
ascent(i in 0..8) {
CreateShotA(1, GetX, GetY, 0);
SetShotDataA(1, 2 * i, 4, GetAngleToPlayer - 30 * (-1) ^ m - (30 + 15 * l), 2 + l, 0, 10, YELLOW11);
ascent(j in 0..10) {
SetShotDataA(1, 30 * j + 30 + 2 * i, 4, NULL, (2 + l) * (-1) ^ (j + 1), 0, 10, YELLOW11);
}
FireShot(1);
CreateShotA(1, GetX, GetY, 0);
SetShotDataA(1, 2 * i, 4, GetAngleToPlayer  - 30 * (-1) ^ m + (30 + 15 * l), -2 - l, 0, 10, YELLOW11);
ascent(j in 0..10) {
SetShotDataA(1, 30 * j + 30 + 2 * i, 4, NULL, (2 + l) * (-1) ^ (j), 0, 10, YELLOW11);
}
FireShot(1);
}

}
}
}
}
if (f == 6420 || f == 6435 || f == 6450 || f == 6465
||  f == 6660 || f == 6675 || f == 6690 || f == 6705)
{
ascent(i in 0..3) {
CreateShotA(62, GetX, GetY, 0);
SetShotDataA(62, 0, 2, 65 + 25 * i, 0, 0, 5, RED02);
ascent(k in 0..2) {
ascent(l in 0..12) {
ascent(m in 0..3) {
CreateShotA(63, 0, 0, 0);
SetShotDataA(63, 0, 1.5 + 0.5 * m, l * 30 + 65 + 25 * i + f * 0.5, 2 * -1 ^ k, 0.01, 5, RED12);
SetShotDataA(63, 15, NULL, NULL, 0, 0.01, 5, RED12);
SetShotKillTime(63, 360);
AddShot(60, 62, 63, 0);
}
}
}
FireShot(62);
}
}
if(f == 6780 || f == 6540) {
ascent(i in 0..4) {
CreateShot01(GetX, GetY, 3, 90 * i, RED03, 0);
}
}
if(f == 6390 || f == 6630) {
ascent(i in 0..6) {
ascent(j in 0..6) {
CreateLaserA(65, 210 + 180 * cos(60 * i), 240 + 180 * sin(60 * i), 400, 15, YELLOW01, 60);
SetLaserDataA(65, 0, 60 * j, 0, 0, 0, 0);
SetShotKillTime(65, 120);
ascent(k in 0..6) {
CreateShotA(66, 0, 0, 0);
SetShotDataA(66, 0, 1.5, 60 * j + 10 * k, 0.5, 0.02, 6, AQUA04);
AddShot(90, 65, 66, 0);
}
FireShot(65);
}
}
}


if(f == 6450 || f == 6690) {
ascent(i in 0..6) {
ascent(j in 0..6) {
CreateLaserA(65, 210 + 180 * cos(60 * i + 30), 240 + 180 * sin(60 * i + 30), 400, 15, YELLOW01, 60);
SetLaserDataA(65, 0, 60 * j + 30, 0, 0, 0, 0);
SetShotKillTime(65, 120);
ascent(k in 0..6) {
CreateShotA(66, 0, 0, 0);
SetShotDataA(66, 0, 1.5, 60 * j + 10 * k + 30, -0.5, 0.02, 6, AQUA04);
AddShot(90, 65, 66, 0);
}
FireShot(65);
}
}
}
if(f == 6540 || f == 6780) {
ascent(n in 0..2) {
ascent(i in 0..7) {
CreateShot01(GetX, GetY, 2 + n, 51 * i, RED02, 0);
CreateShot01(GetX, GetY, 2 + n, 51 * i, RED02, 0);
ascent(j in 0..10) {
CreateShotA(67, GetX, GetY, 7.5 * i);
SetShotDataA(67, 0, 1.2, 36 * j + 0.5 * i ^ 2, -1 ^ n, 0.02, 2, RED12);
SetShotDataA(67, 15 + i * 15, 2, NULL, 0, 0.05, 5, RED12);
ascent(l in 0..16) {
CreateShotA(68, 0, 0, 0);
SetShotDataA(68, 0, 2 + 0.1 * j, j * 5 + i * 30 + n * 180, 0, 0, 6, RED05);
AddShot(7.5 * l, 67, 68, 0);
}
FireShot(67);
}
}
}
}
ascent(j in 0..9) {
if(f == 6900 + 15 * j)
{
ascent(i in 0..40) {
ascent(j in 0..2) {
CreateShotA(70, GetX, GetY, 0);
SetShotDataA(70, 0, 3.5, 9 * i + GetAngleToPlayer, j, 0, 5, RED23);
SetShotDataA(70, 15, NULL, NULL, 0, 0, 5, RED23);
FireShot(70)
}
CreateShot01(GetX, GetY, 3.5,  9 * i + GetAngleToPlayer, RED32, 0);
}
}

if (f == 7140 + 15 * j)
{
ascent(i in 0..40) {
ascent(j in 0..2) {
CreateShotA(70, GetX, GetY, 0);
SetShotDataA(70, 0, 3.5, 9 * i + GetAngleToPlayer, j, 0, 5, RED23);
SetShotDataA(70, 15, NULL, NULL, 0, 0, 5, RED23);
FireShot(70)
}
CreateShot01(GetX, GetY, 3.5,  9 * i + GetAngleToPlayer, RED32, 0);
}
}

if (f == 7380 + 15 * j)
{
ascent(i in 0..40) {
ascent(j in 0..2) {
CreateShotA(70, GetX, GetY, 0);
SetShotDataA(70, 0, 3.5, 9 * i + GetAngleToPlayer, j, 0, 5, RED23);
SetShotDataA(70, 15, NULL, NULL, 0, 0, 5, RED23);
FireShot(70)
}
CreateShot01(GetX, GetY, 3.5,  9 * i + GetAngleToPlayer, RED32, 0);
}
}
}

if(f == 7530) {
ascent(i in 0..5) {
ascent(j in 0..4) {
ascent(k in 0..5) {
CreateShotA(7, GetX, GetY, 0);
SetShotDataA(7, 0, 1, 45 * i - 22.5, 0, 0, 10, BLUE03);
SetShotDataA(7, 30,  2 + j, NULL, sin(f) + 0.3 * (k - 3), 0, 10, PURPLE03);
SetShotDataA(7, 60, NULL, NULL, 0, 0.05, 10, BLUE03);
FireShot(7);
}
}
}
}

if(f == 7590) {

ascent(i in 0..5) {
ascent(j in 0..4) {
ascent(k in 0..5) {
CreateShotA(7, GetX, GetY, 0);
SetShotDataA(7, 0, 1, 45 * i - 22.5, 0, 0, 10, WHITE03);
SetShotDataA(7, 30,  2 + j, NULL, sin(f) + 0.3 * (k - 3), 0, 10, AQUA03);
SetShotDataA(7, 60, NULL, NULL, 0, 0.05, 10, WHITE03);
FireShot(7);
}
}
}
}
if(f == 7650)
{
ascent(i in 0..5) {
ascent(j in 0..4) {
ascent(k in 0..5) {
CreateShotA(7, GetX, GetY, 0);
SetShotDataA(7, 0, 1, 45 * i - 22.5, 0, 0, 10, YELLOW03);
SetShotDataA(7, 30,  2 + j, NULL, sin(f) + 0.3 * (k - 3), 0, 10, GREEN03);
SetShotDataA(7, 60, NULL, NULL, 0, 0.05, 10, YELLOW03);
FireShot(7);
}
}
}
}
if(f == 7710) {
ascent(i in 0..5) {
ascent(j in 0..4) {
ascent(k in 0..5) {
CreateShotA(7, GetX, GetY, 0);
SetShotDataA(7, 0, 1, 45 * i - 22.5, 0, 0, 10, RED03);
SetShotDataA(7, 30,  2 + j, NULL, sin(f) + 0.3 * (k - 3), 0, 10, ORANGE03);
SetShotDataA(7, 60, NULL, NULL, 0, 0.05, 10, RED03);
FireShot(7);
}
}
}
}

if(7800 < f) {
if(f < 10000) {
RedAimingShots(f);
}}


if(f == 9330 || f == 9570 || f == 9870)
{
ascent(i in 0..2) {
ascent(k in 0..2) {
ascent(j in 0..32) {
CreateShotA(9, 10, 10, 0);
SetShotDataA(9, 0, 2 + 0.1 * j, 20 * j, 0.2 * (-1 ^ k), 0.02 * (-1 ^ i), 3, RED04);
SetShotDataA(9, 60, 3, NULL, 0, 0, 3, RED04);
CreateShotA(10, 10, 410, 0);
SetShotDataA(10, 0, 2 + 0.1 * j, 20 * j, 0.2 * (-1 ^ k), 0.02 * (-1 ^ i), 3, RED04);
SetShotDataA(10, 60, 3, NULL, 0, 0, 3, RED04);
CreateShotA(11, 450, 410, 0);
SetShotDataA(11, 0, 2 + 0.1 * j, 20 * j, 0.2 * (-1 ^ k), 0.02 * (-1 ^ i), 3, RED04);
SetShotDataA(11, 60, 3, NULL, 0, 0, 3, RED04);
CreateShotA(12, 450, 10, 0);
SetShotDataA(12, 0, 2 + 0.1 * j, 20 * j, 0.2 * (-1 ^ k), 0.02 * (-1 ^ i), 3, RED04);
SetShotDataA(12, 60, 3, NULL, 0, 0, 3, RED04);
FireShot(9);
FireShot(10);
FireShot(11);
FireShot(12); }
}
}
}
if(f == 8220 || f == 8700 || f == 9180 || f == 9420 || f == 9660 || f == 9780 || f == 9900 || f == 10020)
{
CreateShot01(GetX, GetY, 3, 0, RED02, 0);
CreateShot01(GetX, GetY, 3, 0, RED02, 7.5);
CreateShot01(GetX, GetY, 3, 0, RED02, 15);
CreateShot01(GetX, GetY, 3, 180, RED02, 0);
CreateShot01(GetX, GetY, 3, 180, RED02, 7.5);
CreateShot01(GetX, GetY, 3, 180, RED02, 15);
}
if(f == 8250 || f == 8730 || f == 9210 || f == 9450 || f == 9690 || f == 9810 || f == 9930 || f == 10080)
{
CreateShot01(GetX, GetY, 3, 0, RED02, 0);
CreateShot01(GetX, GetY, 3, 0, RED02, 7.5);
CreateShot01(GetX, GetY, 3, 0, RED02, 15);
CreateShot01(GetX, GetY, 3, 180, RED02, 0);
CreateShot01(GetX, GetY, 3, 180, RED02, 7.5);
CreateShot01(GetX, GetY, 3, 180, RED02, 15);
}
if(f == 8280 || f == 8760 || f == 9240 || f == 9480 || f == 9720 || f == 9840 || f == 9960)
{

CreateShot01(GetX, GetY, 3, 0, RED02, 0);
CreateShot01(GetX, GetY, 3, 0, RED02, 7.5);
CreateShot01(GetX, GetY, 3, 0, RED02, 15);
CreateShot01(GetX, GetY, 3, 180, RED02, 0);
CreateShot01(GetX, GetY, 3, 180, RED02, 7.5);
CreateShot01(GetX, GetY, 3, 180, RED02, 15);
}
if(f == 9990) {
CreateShot01(GetX, GetY, 3, 0, RED02, 0);
CreateShot01(GetX, GetY, 3, 0, RED02, 7.5);
CreateShot01(GetX, GetY, 3, 0, RED02, 15);
CreateShot01(GetX, GetY, 3, 180, RED02, 0);
CreateShot01(GetX, GetY, 3, 180, RED02, 7.5);
CreateShot01(GetX, GetY, 3, 180, RED02, 15);
}
ascent(k in 0..3) {
if(f == 8310 + 15 * k|| f == 8790 + 15 * k || f == 9270 + 15 * k || f == 9510 + 15 * k || f == 9750 + 15 * k || f == 9870 + 15 * k || f == 10050 + k || f == 10110 + k)
{
CreateShot01(GetX, GetY, 3, 0, RED02, 0);
CreateShot01(GetX, GetY, 3, 0, RED02, 15);
CreateShot01(GetX, GetY, 3, 180, RED02, 0);
CreateShot01(GetX, GetY, 3, 180, RED02, 15);
}
}
if(f == 10140 || f == 10860) {
CreateShotA(11, 110, 130, 0);
SetShotDataA(11, 0, -3.887522571, 135, 1.5, 0, 20, RED03);
SetShotKillTime(11, 120);

CreateShotA(12, 110, 340, 0);
SetShotDataA(12, 0, -3.887522571, 45, 1.5, 0, 20, RED03);
SetShotKillTime(12, 120);

CreateShotA(13, 320, 340, 0);
SetShotDataA(13, 0, -3.887522571, -45, 1.5, 0, 20, RED03);
SetShotKillTime(13, 120);

CreateShotA(14, 320, 130, 0);
SetShotDataA(14, 0, -3.887522571, -135, 1.5, 0, 20, RED03);
SetShotKillTime(14, 120);

ascent(i in 0..4) {
ascent(j in 0..16) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (7.5 * j), 1.5 * (k - 2), 0, 20, GREEN21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, GREEN21);
AddShot(7.5 * j, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (7.5 * j), 3, 0, 20, GREEN21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, GREEN21);
AddShot(7.5 * j, 11 + i, 15, 0);
}

}
}
}

ascent(i in 0..4) {
ascent(j in 0..32) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (7.5 * j + 3.75), 1.5 * (k - 2), 0, 20, RED21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, RED21);
AddShot(3.75 + 7.5 * j, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (7.5 * j + 3.75), 3, 0, 20, RED21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, RED21);
AddShot(3.75 + 7.5 * j, 11 + i, 15, 0);
}

}
}
}
FireShot(11);
FireShot(12);
FireShot(13);
FireShot(14);
}
if(f == 10260 || f == 10980) {
CreateShotA(11, 110, 130, 0);
SetShotDataA(11, 0, -3.887522571, -45, -1.5, 0, 20, BLUE03);
SetShotKillTime(11, 120);

CreateShotA(12, 110, 340, 0);
SetShotDataA(12, 0, -3.887522571, -135, -1.5, 0, 20, BLUE03);
SetShotKillTime(12, 120);

CreateShotA(13, 320, 340, 0);
SetShotDataA(13, 0, -3.887522571, 135, -1.5, 0, 20, BLUE03);
SetShotKillTime(13, 120);

CreateShotA(14, 320, 130, 0);
SetShotDataA(14, 0, -3.887522571, 45, -1.5, 0, 20, BLUE03);
SetShotKillTime(14, 120);

ascent(i in 0..4) {
ascent(j in 0..16) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, -45 + 90 * i - 1.5 * (7.5 * j), 1.5 * (k - 2), 0, 20, YELLOW21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, YELLOW21);
AddShot(7.5 * j, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, -45 + 90 * i - 1.5 * (7.5 * j), 3, 0, 20, YELLOW21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, YELLOW21);
AddShot(7.5 * j, 11 + i, 15, 0);
}
}
}
}

ascent(i in 0..4) {
ascent(j in 0..32) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, -45 + 90 * i - 1.5 * (7.5 * j + 3.75), 1.5 * (k - 2), 0, 20, BLUE21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, BLUE21);
AddShot(3.75 + 7.5 * j, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, -45 + 90 * i - 1.5 * (7.5 * j + 3.75), 3, 0, 20, BLUE21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, BLUE21);
AddShot(3.75 + 7.5 * j, 11 + i, 15, 0);
}
}
}
}
FireShot(11);
FireShot(12);
FireShot(13);
FireShot(14);
}
if(f == 10380 || f == 11100)
{
CreateShotA(11, 110, 130, 0);
SetShotDataA(11, 0, -3.887522571, 135, 1.5, 0, 20, RED03);
SetShotKillTime(11, 360);

CreateShotA(12, 110, 340, 0);
SetShotDataA(12, 0, -3.887522571, 45, 1.5, 0, 20, RED03);
SetShotKillTime(12, 360);

CreateShotA(13, 320, 340, 0);
SetShotDataA(13, 0, -3.887522571, -45, 1.5, 0, 20, RED03);
SetShotKillTime(13, 360);

CreateShotA(14, 320, 130, 0);
SetShotDataA(14, 0, -3.887522571, -135, 1.5, 0, 20, RED03);
SetShotKillTime(14, 360);

ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, RED21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, RED21);
AddShot(3.75 * j, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, RED21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, RED21);
AddShot(3.75 * j, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, ORANGE21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, ORANGE21);
AddShot(3.75 * j + 30, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, ORANGE21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, ORANGE21);
AddShot(3.75 * j + 30, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, YELLOW21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, YELLOW21);
AddShot(3.75 * j + 60, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, YELLOW21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, YELLOW21);
AddShot(3.75 * j + 60, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, GREEN21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, YELLOW21);
AddShot(3.75 * j + 90, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, GREEN21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, YELLOW21);
AddShot(3.75 * j + 90, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, BLUE21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, BLUE21);
AddShot(3.75 * j + 120, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, BLUE21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, BLUE21);
AddShot(3.75 * j + 120, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, PURPLE21);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, PURPLE21);
AddShot(3.75 * j + 150, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, PURPLE21);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, PURPLE21);
AddShot(3.75 * j + 150, 11 + i, 15, 0);
}

}
}
}

ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, RED01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, RED01);
AddShot(3.75 * j + 180, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, RED01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, RED01);
AddShot(3.75 * j + 180, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, ORANGE01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, ORANGE01);
AddShot(3.75 * j + 210, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, ORANGE01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, ORANGE01);
AddShot(3.75 * j + 210, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, YELLOW01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, YELLOW01);
AddShot(3.75 * j + 240, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, YELLOW01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, YELLOW01);
AddShot(3.75 * j + 240, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, GREEN01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, YELLOW01);
AddShot(3.75 * j + 270, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, GREEN01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, YELLOW01);
AddShot(3.75 * j + 270, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, BLUE01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, BLUE01);
AddShot(3.75 * j + 300, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 135 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, BLUE01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, BLUE01);
AddShot(3.75 * j + 300, 11 + i, 15, 0);
}

}
}
}
ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, PURPLE01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, PURPLE01);
AddShot(3.75 * j + 330, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 + 90 * i + 1.5 * (3.75 * j), -3, 0, 20, PURPLE01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, PURPLE01);
AddShot(3.75 * j + 330, 11 + i, 15, 0);
}

}
}
}
FireShot(11);
FireShot(12);
FireShot(13);
FireShot(14);
}
if(f == 10740 || f == 11460) {
CreateShotA(11, 110, 130, 0);
SetShotDataA(11, 0, -3.887522571, -45, -1.5, 0, 20, BLUE03);
SetShotKillTime(11, 120);

CreateShotA(12, 110, 340, 0);
SetShotDataA(12, 0, -3.887522571, -135, -1.5, 0, 20, BLUE03);
SetShotKillTime(12, 120);

CreateShotA(13, 320, 340, 0);
SetShotDataA(13, 0, -3.887522571, 135, -1.5, 0, 20, BLUE03);
SetShotKillTime(13, 120);

CreateShotA(14, 320, 130, 0);
SetShotDataA(14, 0, -3.887522571, 45, -1.5, 0, 20, BLUE03);
SetShotKillTime(14, 120);

ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, -45 + 90 * i - 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, BLUE01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, BLUE01);
AddShot(3.75 * j, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, -45 + 90 * i - 1.5 * (3.75 * j), 3, 0, 20, BLUE01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, BLUE01);
AddShot(3.75 * j, 11 + i, 15, 0);
}

}
}
}

ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 * i - 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, GREEN01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, GREEN01);
AddShot(3.75 * j, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 * i - 1.5 * (3.75 * j), 3, 0, 20, GREEN01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, GREEN01);
AddShot(3.75 * j, 11 + i, 15, 0);
}

}
}
}


ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, -45 + 90 * i - 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, YELLOW01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, YELLOW01);
AddShot(3.75 * j, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, -45 + 90 * i - 1.5 * (3.75 * j), 3, 0, 20, YELLOW01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, YELLOW01);
AddShot(3.75 * j, 11 + i, 15, 0);
}

}
}
}


ascent(i in 0..4) {
ascent(j in 0..9) {
ascent(k in 0..6) {
if(k < 4) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 * i - 1.5 * (3.75 * j), 1.5 * (k - 2), 0, 20, ORANGE01);
SetShotDataA(15, 60, NULL, NULL, 0, 0, 20, ORANGE01);
AddShot(3.75 * j + 90, 11 + i, 15, 0);
}
if(k > 3) {
CreateShotA(15, 0, 0, 0);
SetShotDataA(15, 0, 3.887522571, 90 * i - 1.5 * (3.75 * j), 3, 0, 20, ORANGE01);
SetShotDataA(15, 60 * k - 180, NULL, NULL, 0, 0, 20, ORANGE01);
AddShot(3.75 * j + 90, 11 + i, 15, 0);
}

}
}
FireShot(11);
FireShot(12);
FireShot(13);
FireShot(14);
}
}

ascent(i in 0..48) {
if(f == 10140 + i * 30) {
ascent(k in 0..32) {
if(f == 10260 || f == 10290 || f == 10320 || f == 10350 || f == 10740 || f == 10770 || f == 10800 || f == 10830
|| f == 10980 || f == 11010 || f == 11040 || f == 11070 || f == 11460 || f == 11490 || f == 11520 || f == 11550)
{
Z = "BLUE12"
}
else
{
Z = "RED12"
}

CreateShotA(16, GetX, GetY, 0);
SetShotDataA(16, 0, 1.94, 10 * k + GetAngleToPlayer, -0.8, 0.01, 10, Z);
FireShot(16);
CreateShotA(17, GetX, GetY, 0);
SetShotDataA(17, 0, 1.94, 10 * k + GetAngleToPlayer, 0.8, 0.01, 10, Z);
FireShot(17);
}
}
}

ascent (i in 0..8) {
if(f == 11520 + 60 * i) {
SetMovePosition02(GetPlayerX, GetPlayerY, 60);
ascent(k in 0..30) {
CreateShot02(GetX, GetY, 0.4, 12 * k, 0.01, 3, RED01, 60);
}
}
}

if(f == 11490 || f == 11730) {
SetCircleLocationA(1, GetX, GetY, 1, 255, 30);
MoveCircleA01(1, GetCenterX, GetCenterY, 30, 30);
}
if(f == 11700 || f == 11940) {
FadeCircleA(1, 120);
}
if(f == 11460 || f == 11700){
ascent(i in 0..8) {
ascent(j in 0..8) {
CreateLaserC(21, GetCenterX, GetCenterY, 8, 30, RED04, 0);
SetLaserDataC(21, 0, 6, 45 + 45 * i, 0, 0, 25);
SetLaserDataC(21, 6 * j + 6, 3 * 3.1415 * (2 * j + 2) / 30, 135 + 45 * i, 1, 0, 25);
SetShotKillTime(21, 120);
FireShot(21);
} }
}

if(f == 11580 || f == 11820) {
ascent(i in 0..8) {
CreateShotA(18, GetCenterX, GetCenterY, 0);
SetShotDataA(18, 0, 18, 45 + 45 * i, 0, 0, 18, RED03);
SetShotDataA(18, 15, 10, -90 + 45 * i, 0, 0, 18, RED03);
ascent(j in 0..10) {
CreateShotA(19, 0, 0, 0);
SetShotDataA(19, 0, 9 * 3.1415 * (2 * j + 2) / 30, 135 + 45 * i, 3, 0, 25, RED04);
SetShotDataA(19, 15, NULL, NULL, 0, 0, 25, RED04);
ascent(k in 0..30) {
CreateShotA(20, 0, 0, 0);
SetShotDataA(20, 0, 0, -135 + 45 * i + 1.5 * k, 0, 0, 10, RED01);
SetShotDataA(20, 7.5 * k, NULL, NULL, 0.02 * (-1 ^ j), 0.02, 20, PURPLE01);
SetShotKillTime(20, 7.5 * k + 30 * 2 ^ 0.5 * (j + 2)^0.5);
AddShot(0.5 * k, 19, 20, 0); }
AddShot(2 * j + 2, 18, 19, 0);

}
FireShot(18);

}
}
if(f == 11980) {
SetMovePosition02(GetCenterX, 40, 20);
}
if(f == 12060) {
ScarletShoot(GetX, GetY, 3, GetAngleToPlayer, 0);
SetCircleLocationA(1, GetX, GetY, 1, 255, 30);
SetCircleLocationA(2, GetX, GetY, 1, 255, 30);
}
if(f == 12180) {
ScarletShoot(GetX, GetY, 3, GetAngleToPlayer, 0);
}
ascent(i in 0..10) {
if(f == 12060 + 180 * i) {
MoveCircleA01(1, GetCenterX - 140, 200 + 150 * -1 ^ i, 30, 0);
MoveCircleA01(2, GetCenterX + 140, 200 + 150 * -1 ^ i, 30, 0);
}
}
if(f == 12075 || f == 12195) {
ScarletShoot(GetX, GetY, 3, GetAngleToPlayer + 30, 0);
ScarletShoot(GetX, GetY, 3, GetAngleToPlayer - 30, 0);
}

ascent(j in 0..5) {
if(f == 12105 + 15 * j || f == 12225 + 15 * j)
{
ScarletShoot(GetX, GetY, 3, 2 * f + 30, 0);
ScarletShoot(GetX, GetY, 3, 2 * f - 30, 0);

}
}
ascent(j in 0..4) {
if(f == 12300 + 120 * j) {

if(j ==0 || j == 2) {
ScarletShoot(GetX, GetY, 3, 90, 0);
ScarletShoot(GetX, GetY, 3.2, 75, 0);
ScarletShoot(GetX, GetY, 3.5, 60, 0);
ScarletShoot(GetX, GetY, 3.2, 75, 0);
ScarletShoot(GetX, GetY, 3, 90, 0);
}

if(j == 1 || j == 3) {
ScarletShoot(GetX, GetY, 3, GetAngleToPlayer, 0);
ScarletShoot(GetX, GetY, 3.2, GetAngleToPlayer + 10, 0);
ScarletShoot(GetX, GetY, 3.2, GetAngleToPlayer - 10, 0);
}
}
}
if(f == 12300 || f == 12420 || f == 12540)
{
ascent(i in 0..10) {
ascent(j in 0..2) {
CreateLaserA(21, CAX[j + 1], CAY[j + 1], 600, 12, RED02, 60);
SetLaserDataA(21, 0, 20 * i, 0, 0, 0, 0);
ascent(k in 0..16) {
if(k != i && k != i + 180 && k != i - 180) {
ascent(l in 0..6) {
CreateShotA(22, 0, 0, 0);
SetShotDataA(22, 0, 1, 60 * l, 0.5 * (-1) ^ i, 0.01, 20, RED31);
AddShot(60, 21, 22, 280 * sin(180 - 20 * k) / sin(20 * k - (40 * i * (0.5 - j) + 180 * j)));
}
}
}
SetShotKillTime(21, 120);
FireShot(21);
}
}
}
if(f == 12660)
{

SetMovePosition02(GetCenterX, 40, 20);
ascent(i in 0..10) {
ascent(j in 0..2) {
CreateLaserA(21, CAX[j + 1], CAY[j + 1], 600, 12, BLUE02, 60);
SetLaserDataA(21, 0, 20 * i, 0, 0, 0, 0);
ascent(k in 0..16) {
if(k != i && k != i + 180 && k != i - 180) {
ascent(l in 0..15) {
CreateShotA(22, 0, 0, 0);
SetShotDataA(22, 0, 0.5, 24 * l, 0.5 * (-1) ^ i, 0.01, 20, BLUE31);
AddShot(60, 21, 22, 280 * sin(180 - 20 * k) / sin(20 * k - (40 * i * (0.5 - j) + 180 * j)));
}
}
}
SetShotKillTime(21, 120);
FireShot(21);
}
}
}
if(f > 12000 && f < 12660) {
SetMovePosition01(GetPlayerX, 40 + 100 * (sin((f - 12000) / 80)) ^ 2, 0.7);
}


/* Scoring Function: 2000 points per graze plus 75 points per life point of the boss taken off.*/
if(f > 10) {
AddScore(75 * (1000000 - GetLife() - h));
h = 1000000 - GetLife();
AddScore(2000 * (GetGraze - g));
g = GetGraze();
}
/* Count the counter up 1*/
f++;
/*yield*/
yield;

}
        @DrawLoop {
SetGraphicRect(1,1,64,64);
SetAlpha(255);
SetTexture(BI);
SetGraphicScale(1, 1);
SetGraphicAngle(0, 0, 0);
DrawGraphic(GetX(),GetY());
// CircleDraw;
/* Yield inside the Draw Loop yield;*/
}
@Finalize {
}

#include_script ".\BLUERED.txt";
#include_script ".\HorizontalFamiliarCircle.txt";

@Background {
}
}





Here is CIRCS.TXT.

Code: [Select]
/* Allow for 9 circles to be placed at the same time of one type (should be more than enough). */
/* This code will also not work on spell cards or battles longer than 60 million frames
(which is one million seconds, or uhm... some 100 something days, never mind that. */
/*You can assign any picture to the circles by adding let CIRCLEA = (...) into the
main variable initialization. Add the path to the image into (...).*/
/* Used circles are 80 x 80 pixels and are given a collision detection equal to that */
/* Put code link in function declaration part */

/*
    let CIRCLEA = GetCurrentScriptDirectory~"06_0313.jpg";
    let CIRCLEB = GetCurrentScriptDirectory~"06_0466.jpg";

LoadGraphic(CIRCLEA);
LoadGraphic(CIRCLEB);*/

let CAX = [0,0,0,0,0,0,0,0,0,0];
let CAY= [0,0,0,0,0,0,0,0,0,0];

let CBX= [0,0,0,0,0,0,0,0,0,0];
let CBY= [0,0,0,0,0,0,0,0,0,0];

let CAR= [0,0,0,0,0,0,0,0,0,0];
let CBR= [0,0,0,0,0,0,0,0,0,0];

let CAO= [0,0,0,0,0,0,0,0,0,0];
let CBO= [0,0,0,0,0,0,0,0,0,0];

let StoreFadeStartTimeCircleA = [60000000,60000000,60000000,60000000,60000000,60000000,60000000,60000000,60000000,60000000, 60000000];
let StoreFadeStartTimeCircleB = [60000000,60000000,60000000,60000000,60000000,60000000,60000000,60000000,60000000,60000000, 60000000];
let FadeTimeCircleA= [0,0,0,0,0,0,0,0,0,0];
let FadeTimeCircleB= [0,0,0,0,0,0,0,0,0,0];

let VXCA= [0,0,0,0,0,0,0,0,0,0];
let VYCA= [0,0,0,0,0,0,0,0,0,0];
let StopMoveA= [0,0,0,0,0,0,0,0,0,0];
let StartMoveA= [0,0,0,0,0,0,0,0,0,0];

let VXCB= [0,0,0,0,0,0,0,0,0,0];
let VYCB= [0,0,0,0,0,0,0,0,0,0];
let StopMoveB= [0,0,0,0,0,0,0,0,0,0];
let StartMoveB= [0,0,0,0,0,0,0,0,0,0];

let VCA= [0,0,0,0,0,0,0,0,0,0];
let AngA= [0,0,0,0,0,0,0,0,0,0];
let ACA= [0,0,0,0,0,0,0,0,0,0];
let AACA= [0,0,0,0,0,0,0,0,0,0];

let VCB= [0,0,0,0,0,0,0,0,0,0];
let AngB= [0,0,0,0,0,0,0,0,0,0];
let ACB= [0,0,0,0,0,0,0,0,0,0];
let AACB= [0,0,0,0,0,0,0,0,0,0];

let VXCA= [0,0,0,0,0,0,0,0,0,0];
let VYCA= [0,0,0,0,0,0,0,0,0,0];
let AXCA= [0,0,0,0,0,0,0,0,0,0];
let AYCA= [0,0,0,0,0,0,0,0,0,0];

let VXCB= [0,0,0,0,0,0,0,0,0,0];
let VYCB= [0,0,0,0,0,0,0,0,0,0];
let AXCB= [0,0,0,0,0,0,0,0,0,0];
let AYCB= [0,0,0,0,0,0,0,0,0,0];

let FADECA= [0,0,0,0,0,0,0,0,0,0];
let FADECB= [0,0,0,0,0,0,0,0,0,0];

let EXISTCA= [0,0,0,0,0,0,0,0,0,0];
let EXISTCB= [0,0,0,0,0,0,0,0,0,0];

let APPEARCA= [0,0,0,0,0,0,0,0,0,0];
let APPEARCB= [0,0,0,0,0,0,0,0,0,0];

let SCALECA= [0,0,0,0,0,0,0,0,0,0];
let SCALECB= [0,0,0,0,0,0,0,0,0,0];




let circledrawcount = 0;
/* Define a function which enables the use of the circle, with ID of 'CIRCLEIDA'.
Variables have long names, don't use these somewhere else. */

/* This function allows you to change the location of the circle and the rotational speed. */
/* The speed is in rotations per second, pick low numbers (i.e. surely <10.)*/
/* The opacity is between 0 and 255 (solid), the see-through of the circle */
/* The scaling duration is how long it will take before the circle has full (80x80) size. */


function SetCircleLocationA(CIRCLEIDA, XCIRCLEA, YCIRCLEA, VRCIRCLEA, OPACITYA, SCALEDURA) {
CAX[CIRCLEIDA] = XCIRCLEA;
CAY[CIRCLEIDA] = YCIRCLEA;
CAR[CIRCLEIDA] = VRCIRCLEA;
CAO[CIRCLEIDA] = OPACITYA;
EXISTCA[CIRCLEIDA] = 1;
SCALECA[CIRCLEIDA] = SCALEDURA;
APPEARCA[CIRCLEIDA] = circledrawcount;
}

function SetCircleLocationB(CIRCLEIDB, XCIRCLEB, YCIRCLEB, VRCIRCLEB, OPACITYB, SCALEDURB) {
CBX[CIRCLEIDB] = XCIRCLEB;
CBY[CIRCLEIDB] = YCIRCLEB;
CBR[CIRCLEIDB] = VRCIRCLEB;
CAO[CIRCLEIDB] = OPACITYB;
EXISTCB[CIRCLEIDB] = 1;
SCALECB[CIRCLEIDB] = SCALEDURB;
APPEARCB[CIRCLEIDB] = circledrawcount; }

/*
01 = function for moving the circle to some other place in a straight line in a defined time
Never fill in 0 for the time or you'll crash the program (Dividing by 0...).

02 = function for moving the circle a la CreateShotA, with angle and rotational accelleration,
velocity and accelleration specified.

03 = function for moving the circle a la CreateShotA_XY, with X and Y velocities and accellerations.

Note that the movement functions also have MOVETIME, which is the time it'll move (never to 0!),
and DELAY, which is self-explanatory.

Note: Multiple movement functions used together will cause unwanted results. Don't do.
*/

function MoveCircleA01(CIRCLEIDA, XMCIRCLEA, YMCIRCLEA, MOVETIME, DELAY){

VXCA[CIRCLEIDA] = (XMCIRCLEA - CAX[CIRCLEIDA]) / MOVETIME;
VYCA[CIRCLEIDA] = (YMCIRCLEA - CAY[CIRCLEIDA]) / MOVETIME;
StopMoveA[CIRCLEIDA] = circledrawcount + MOVETIME + DELAY;
StartMoveA[CIRCLEIDA] = circledrawcount + DELAY;
}
function MoveCircleA02(CIRCLEIDA, VA, ANGA, AANGA, AA, MOVETIME, DELAY) {

VCA[CIRCLEIDA] = VA;
AngA[CIRCLEIDA] = ANGA;
ACA[CIRCLEIDA] = AA;
AACA[CIRCLEIDA] = AANGA;
StopMoveA[CIRCLEIDA] = circledrawcount + MOVETIME + DELAY;
StartMoveA[CIRCLEIDA] = circledrawcount + DELAY;
}
function MoveCircleA03(CIRCLEIDA, VXA, VYA, AXA, AYA, MOVETIME, DELAY) {

VXCA[CIRCLEIDA] = VXA;
VYCA[CIRCLEIDA] = VYA;
AXCA[CIRCLEIDA] = AXA;
AYCA[CIRCLEIDA] = AYA;
StopMoveA[CIRCLEIDA] = circledrawcount + MOVETIME + DELAY;
StartMoveA[CIRCLEIDA] = circledrawcount + DELAY;
}
function MoveCircleB01(CIRCLEIDB, XMCIRCLEB, YMCIRCLEB, MOVETIME, DELAY){

VXCB[CIRCLEIDB] = (XMCIRCLEB - CBX[CIRCLEIDB]) / MOVETIME;
VYCB[CIRCLEIDB] = (YMCIRCLEB - CBY[CIRCLEIDB]) / MOVETIME;
StopMoveB[CIRCLEIDB] = circledrawcount + MOVETIME + DELAY;
StartMoveB[CIRCLEIDB] = circledrawcount + DELAY;
}
function MoveCircleB02(CIRCLEIDB, VB, ANGB, AANGB, AB, MOVETIME, DELAY) {

VCB[CIRCLEIDB] = VB;
AngB[CIRCLEIDB] = ANGB;
ACB[CIRCLEIDB] = AB;
AACB[CIRCLEIDB] = AANGB;
StopMoveB[CIRCLEIDB] = circledrawcount + MOVETIME + DELAY;
StartMoveB[CIRCLEIDB] = circledrawcount + DELAY;
}
function MoveCircleB03(CIRCLEIDB, VXB, VYB, AXB, AYB, MOVETIME, DELAY) {

VXCA[CIRCLEIDB] = VXB;
VYCA[CIRCLEIDB] = VYB;
AXCA[CIRCLEIDB] = AXB;
AYCA[CIRCLEIDB] = AYB;
StopMoveA[CIRCLEIDB] = circledrawcount + MOVETIME + DELAY;
StartMoveA[CIRCLEIDB] = circledrawcount + DELAY;
}
function FadeCircleA(CircleIDA, FADETIME) {

StoreFadeStartTimeCircleA[CircleIDA] = circledrawcount;
FADECA[CircleIDA] = CAO[CircleIDA] / FADETIME;
FadeTimeCircleA[CircleIDA] = FADETIME + 1;
}
function FadeCircleB(CircleIDB, FADETIME) {

StoreFadeStartTimeCircleB[CircleIDB] = circledrawcount;
FADECB[CircleIDB] = CAO[CircleIDB] / FADETIME;
FadeTimeCircleB[CircleIDB] = FADETIME + 1; }

/* This task must be included within the Draw Loop or this code will all have no effect but
computer slowdown. It does the following, in order:

1: Remove all faded circles and all circles moved off-board from play.
2: Check if circle 'n' exists.
3: If so, check if it's moving.
4: If so, add accellerations to velocities, and
5: add angular accellerations to the angle, and
6: add velocities to X- and Y- coordinations, transposed for angle if need be.
7: End of the bit within the movement check,
8: Check if the circle is fading,
9: if so, substract fade speed from opacity.
10: Note that you can fade partially by setting the circle again during the fade. Use CAX[n]
as X-coordinate to keep it positioned the same.
11: now draw the circle(s). 
12: Repeat the process for the B-Circles.
*/

task CircleDraw {


ascent(n in 0..9) {


if(CAO[n] < 1 || CAX[n] < 0 || CAX[n] > 500 || CAY[n] < 0 || CAY[n] > 500) {
EXISTCA[n]= 0;
}
if(CBO[n] < 1 || CBX[n] < 0 || CBX[n] > 500 || CBY[n] < 0 || CBY[n] > 500) {
EXISTCB[n]= 0;
}

if(EXISTCA[n] == 1) {

if(circledrawcount < StopMoveA[n] && circledrawcount > StartMoveA[n]) {
VCA[n] = VCA[n] + ACA[n];
AngA[n] = AngA[n] + AACA[n];
VXCA[n] = VXCA[n] + AXCA[n];
VYCA[n] = VYCA[n] + AYCA[n];
CAX[n] = CAX[n] + VCA[n] * cos(AngA[n]) + VXCA[n];
CAY[n] = CAY[n] + VCA[n] * sin(AngA[n]) + VYCA[n];
}
if(circledrawcount > StoreFadeStartTimeCircleA[n] && circledrawcount < FadeTimeCircleA[n] + StoreFadeStartTimeCircleA[n] + 1)
{
CAO[n] = CAO[n] - FADECA[n]
}
SetTexture(CIRCLEA);
SetGraphicRect(0, 0, 128, 128);
SetAlpha(CAO[n]);
SetGraphicAngle(0, 0, 180 + (circledrawcount - APPEARCA[n]) * CAR[n]);

if(circledrawcount > APPEARCA[n] + SCALECA[n]) {
SetGraphicScale(1, 1);
}
else {
SetGraphicScale((circledrawcount - APPEARCA[n]) / SCALECA[n], (circledrawcount - APPEARCA[n]) / SCALECA[n]);
}
DrawGraphic (CAX[n], CAY[n]);
SetCollisionA(CAX[n], CAY[n], 60);
}
if(EXISTCB[n] == 1) {

if(circledrawcount < StopMoveB[n] && circledrawcount > StartMoveB[n]) {
VCB[n] = VCB[n] + ACB[n];
AngB[n] = AngB[n] + AACB[n];
VXCB[n] = VXCB[n] + AXCB[n];
VYCB[n] = VYCB[n] + AYCB[n];
CBX[n] = CBX[n] + VCB[n] * cos(AngB[n]) + VXCB[n];
CBY[n] = CBY[n] + VCB[n] * sin(AngB[n]) + VYCB[n];
}
if(circledrawcount > StoreFadeStartTimeCircleB[n] && circledrawcount < FadeTimeCircleB[n] + StoreFadeStartTimeCircleB[n] + 1)
{
CBO[n] = CBO[n] - FADECB[n]
}
SetTexture(CIRCLEB);
SetGraphicRect(0, 0, 128, 128);
SetAlpha(CBO[n]);
SetGraphicAngle(0, 0, 180 + (circledrawcount - APPEARCB[n]) * CBR[n]);

if(circledrawcount > APPEARCB[n] + SCALECB[n]) {
SetGraphicScale(1, 1);
}
else {
SetGraphicScale((circledrawcount - APPEARCA[n]) / SCALECA[n], (circledrawcount - APPEARCA[n]) / SCALECA[n]);
}
DrawGraphic (CBX[n], CBY[n]);
SetCollisionA(CBX[n], CBY[n], 60);
}
}
circledrawcount++
}


and here is HorizontalFamiliarCircle.

Code: [Select]
task HCircleFamiliar(let num, let grf, let fc, let mult, let ang, let len)
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetX(obj, GetX);
Obj_SetY(obj, GetY);
ObjShot_SetGraphic(obj, grf);
ObjShot_SetDelay(obj, 0);
let fch = fc;
while( !Obj_BeDeleted(obj) )
{
fc++;
Obj_SetX(obj, GetX + mult * 180 * sin(f / 3 + ang));
if(fc - fch > len){
ObjShot_FadeDelete(obj);
break;
}
yield;
}
}




I'm glad I didn't add any sounds yet  ;D

As you can see a bit of a work in progress, still doing the shotdata.
By the way, I've tried to comment out any extra file entries. It should work like this.


Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on October 08, 2009, 10:35:28 PM
I'm trying to recreate MoF MarisaA's star shots, the ones that pulse in and out and make those explosions when they hit an enemy. I'm having trouble with the explosion itself...

I cannot make the thing grow and shrink without either making an effect object or manually editing the graphics to make MORE versions of the explosion that are larger or smaller. Problem with the effect object is, I CAN'T MAKE IT DEAL DAMAGE TO THE ENEMY! I need help with this, please! It's extremely annoying, and since it's a player shot, not a spellcard object, I can't use a spell object...

The code for the objects:

Code: [Select]
task CreatePlayerShot03(x, y, speed, angle, power, ShotG, ShotA, epower, EffectA, EffectTime)
{
let EffectX = 0;
let EffectY = 0;
let Shot = Obj_Create(OBJ_SHOT);
Obj_SetPosition(Shot, x, y);
ObjShot_SetDamage(Shot, power);
ObjShot_SetPenetration(Shot, 1);
ObjShot_SetGraphic(Shot, ShotG);
Obj_SetSpeed(Shot, speed);
Obj_SetAngle(Shot, angle);
Obj_SetAlpha(Shot, ShotA);
while(!Obj_BeDeleted(Shot))
{
EffectX = Obj_GetX(Shot);
EffectY = Obj_GetY(Shot);
yield;
}
if(Obj_BeDeleted(Shot) && EffectX >= 0 && EffectY >= 0 && EffectX <= GetClipMaxX && EffectY <= GetClipMaxY)
{
let size = 30;
let grow = true;
let Effect = Obj_Create(OBJ_EFFECT);
ObjEffect_SetTexture(Effect,imgPlayer);
ObjEffect_SetRenderState(Effect,ALPHA);
ObjEffect_CreateVertex(Effect,4);
Obj_SetAlpha(Effect, EffectA);
ObjShot_SetDamage(Effect, epower);
ObjEffect_CreateVertex(Effect,4);
ObjEffect_SetPrimitiveType(Effect,PRIMITIVE_TRIANGLEFAN);
while(size > 0)
{
if(grow)
{
size+=5;
}
if(!grow)
{
size-=5;
}
if(size>=50)
{
grow = false;
}
ObjEffect_SetVertexUV(Effect,0,1,193);
ObjEffect_SetVertexUV(Effect,1,62,193);
ObjEffect_SetVertexUV(Effect,2,62,254);
ObjEffect_SetVertexUV(Effect,3,1,254);

ObjEffect_SetVertexXY(Effect,0,EffectX+(size*cos(135+270)),EffectY+(size*sin(135+270)));
ObjEffect_SetVertexXY(Effect,1,EffectX+(size*cos(225+270)),EffectY+(size*sin(225+270)));
ObjEffect_SetVertexXY(Effect,2,EffectX+(size*cos(315+270)),EffectY+(size*sin(315+270)));
ObjEffect_SetVertexXY(Effect,3,EffectX+(size*cos(45+270)),EffectY+(size*sin(45+270)));
yield;
}
Obj_Delete(Effect);
}
}

...also I cannot seem to make it look anything like the one in MoF. MoF's is very faded, but this is just...ugh.

It looks like this. (http://i244.photobucket.com/albums/gg13/MatthewPZC/snapshot053b.jpg)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 09, 2009, 02:49:34 AM
Is there anyway I can change the background music sometime in a stage?

If I used a #BGM[] block and I use PlayMusic(), the music in Playmusic() will be played instead of the music in BGM?

Also,

Code: [Select]
script_enemy_main
{
   let frame=0;
   let frame2=0;
   let count=2;
   let count2=1;
   let i;
   let j;
   let ytemp;
   let random;
   #include_function ".\enemydrawing.txt"
   LoadUserShotData(GetCurrentScriptDirectory~"images\shot_All.txt");
   @Initialize
   {
      SetLife(100);
      SetGraphicRect(0,0,32,32);
   }
   @MainLoop
   {
      SetCollisionA(GetX, GetY, 32);
      SetCollisionB(GetX, GetY, 16);
ytemp=rand(GetClipMinY+60, GetCenterY-30);
if(frame==0){
    SetMovePosition03(GetX, ytemp, 1, 3);
}
if(GetY==ytemp){
    frame2++;
}
if(frame2>60&&count2==1){
    SetMovePosition03(GetX, GetClipMinY-40, 1, 3);
    count2--;
}
if(frame%60>=40&&frame%3==0){
    CreateShot01(GetX, GetY, 5, GetAngleToPlayer, 9, 10);
}
      frame++;
      if((GetX-GetClipMinX)^2<=(GetSpeed/2)||(GetX-GetClipMaxX)^2<=(GetSpeed/2)||(GetY-GetClipMinY)^2<=(GetSpeed/2)||(GetY-GetClipMaxY)^2<=(GetSpeed/2)){
         count--;
      }
      if(count==0){
VanishEnemy;
      }
   }
   @DrawLoop{drawenemy(1);}
   @Finalize{
      if(count!=0){
         loop(8){
    CreateItem(ITEM_SCORE,GetX+rand(-80,80),GetY+rand(-80,80));
         }
      }
   }
}

Why doesn't the enemy go up after a period of time?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 09, 2009, 04:43:11 AM
It's just an endless shitstorm of questions!
@Aphid:
After quite a while of thought, it occurred to me that the problem lies in the fundamental action you're taking: collision between two bullets. Not only that, but on such a large scale. Unfortunately, Danmakufu fails at manual collision detection on a large scale (or at least how we code it) so as far as I know, there is nothing you can do to improve the speed of your script by any significant degree. Granted, you are spawning an ass-tonne of object bullets, so yeah. Best advice I can give is to cut back on the collision between bullets. Your script looks fucking amazing, but if it takes my computer twice the amount of time to process a frame than is alotted, then what you're doing is probably a bit excessive (re: spawn less bullets).

Something you could ponder on: if all the bullets change action (spawn the CreateShotA in the same frame and delete themselves, as opposed to over the course of many frames) the fps lag is not as noticable. This only works for collision between bullets as far as I can tell, since normally spawning many bullets in one frame is frowned upon. The logic I suppose is that it doesn't cause your framerate to drop on average, instead you just see a brief pause. Anyway, I'm only mentioning this because when I sit in the middle of the screen during that part (thus causing the RED02's to hit the BLUE01's during the same frame or so) the fps lag is far less noticable than when I'm somewhere else on the screen and the RED02's are hitting BLUE01's nearly every frame. Perhaps it's a different direction you could go with for this section of the script, not to discourage what you've made so far. Which, by the way, is fucking awesome.


@pikaguy900:
For the faded transparency issue, use ObjEffect_SetVertexColor(Effect, [0-3], 100, 255, 255, 255); the last third parameter is the alpha value of the object. Repeat for all four verticies, of course. As for the pulsing issue, you have a few options. Firstly, you could do as you said -- make AnimationData for a bigger and smaller star, which unfortunately means dicking around with the graphics. Another option is to spawn an ObjEffect on top of the ObjShot, which you can make pulse rather easily using verticies. Make it update it's position every frame and get deleted as the ObjShot is. The latter option sounds easier to me, and shouldn't cause much slowdown since you're not spawning that many ObjEffects (to compare, my Sanae B's Wily Toad bomb spawns hundreds of effect objects which make up the green electricity. So far, from everybody I've asked, nobody has noticed any slowdown. You should be fine to spawn an ObjEffect on each shot).


@Henry:
PlayMusic() will override #BGM, yes. Might I suggest playing a mute file for your #BGM and just manually starting the music in your script anyway, since how fast people's computers load the script will affect how far into the song they are while they play, since the song in #BGM starts playing before @Initialize. Where as if you delcared PlayMusic pretty much anywhere, the music would start playing after everything is loaded and the fps spike has passed.

For your second question, you use the function rand which will generate a random floating point number between the two values you've assigned. The number will have many many decimal points. The enemy does not move because she will never be specifically on that point, to the decimal place, even if you tell her to move there. This is because Danmakufu has a nasty habit of rounding numbers off when all is said and done. A more accurate function to use would be rand_int, which pulls a random integer from between the assigned values, just as rand pulls a random real number. It is far more likely that the enemy will move to a point (0, 10) rather than (0, 10.37178592). Granted, you might want to get rid of the decimals when pulling the boss' coordinates anyways, since, for the very reason I just explained, it might be unlikely for the boss to be on those specific coordinates. I haven't tested that yet, but just in case, try using:
Code: [Select]
if(round(GetY)==round(ytemp)){
    frame2++;
}

Instead of your current code:
Code: [Select]
    if(GetY==ytemp){
       frame2++;
    }

That should get things working.

EDIT: Fixed my poor memory
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on October 09, 2009, 12:07:23 PM
Question...  ;D sorry if this seems stupid but...

If I used the "#BackGround[User(put whatever here)]" for a background at the start of the script... then combine 2 or more spell cards that use this in one plural or stage file, but each card uses a different picture... is it possible to still load the backgrounds, or do I have to put all the backgrounds in the @DrawLoop? because I can't seem to figure out how to scroll the image, tiling it as it goes, like how #BackGround does it, in @DrawLoop...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nimono on October 09, 2009, 01:04:12 PM
@pikaguy900:
For the faded transparency issue, use ObjEffect_SetVertexColor(Effect, [0-3], 255, 255, 255, 100); the last parameter is the alpha value of the object. Repeat for all four verticies, of course. As for the pulsing issue, you have a few options. Firstly, you could do as you said -- make AnimationData for a bigger and smaller star, which unfortunately means dicking around with the graphics. Another option is to spawn an ObjEffect on top of the ObjShot, which you can make pulse rather easily using verticies. Make it update it's position every frame and get deleted as the ObjShot is. The latter option sounds easier to me, and shouldn't cause much slowdown since you're not spawning that many ObjEffects (to compare, my Sanae B's Wily Toad bomb spawns hundreds of effect objects which make up the green electricity. So far, from everybody I've asked, nobody has noticed any slowdown. You should be fine to spawn an ObjEffect on each shot).

I didn't know SetVertexColor set an alpha, too... I'll use that, thanks.

I'm not really sure the ObjShot thing would help for the EXPLOSION. It'd definitely help with the STAR, yeah, but the EXPLOSION the star creates... Uhh... I don't really know if ZUN made its hitbox grow and shrink with the graphics, but I'd assume he did... I know it'd give it a hitbox, though, and at that is at least SOMETHING I want...

Of course, another alternative I have is to see if I can call a Spell script without actually triggering spell functions. I'm 99.99999999999999999999999999999999999999999% sure I can...and I'm 100% sure it'd solve all my problems.

EDIT: Naut, it was the FIRST parameter after the Vertex index, not the LAST. :P It still doesn't look right, for some reason. I don't get why it won't look anything like what it does in-game in MoF... What the heck did he do to it...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Aphid on October 09, 2009, 02:15:12 PM
@naut.

I've also found out something while making a diffrent script yesterday. If I could replace the task in the script I presented then with a function it could probably solve everything. For example, here is a master script with two slave scripts. The second slave runs significantly slower than the primary (which I'm using now) whilst what I'm doing is exactly the same. The cinch? I used a task. Seems NuclearCheese was right about those tasks being poorly coded  :).

Remember talking about those roses? Many math functions for interesting patterns want numbers out of Q, the set of fractions (better yet, R, but that's kind of impossible), while doing ascent(...) or loop(f++) constructions leaves us with something from N. So if I want to get a large possible pattern choice with them all very diffrent and I'm using some kind of sine based function (like, a rose curve like here), or a Fourier series or something similar, it's a very good idea to essentially make some kind of algorithm that does that. So I did

This script has two interesting math functions worth a look at.
gcd(a,b) provides the greatest common denominator for a and b.
NtoQ(N) provides you with a number from the set Q of fractions as a two-value array for each number out of the set N of whole numbers. WARNING: do not put in Large or Very Large numbers, this will crash your pc. Don't try anything over one million, seriously (dorh, it will loop more than one billion times or so).  Basically, have a look at this diagram;

1-A2-B3-F4-G
1/2-C2/2-E3/2-H4/2
1/3-D2/3-I3/34/3
1/4-J2/43/44/4

Following A-B-C-D-E-F-G-H-I-J-... you can see what I mean. If you continue 'walking' through the two-dimensional matrix like that you'll eventually reach every number in the (positive part of) Q. So this nice little table maps N on Q. It's just that there's a whole lot of double values. So essentially, I made an algorithm that does the same little walk (the trick is to think modulus 2), and then provide some conditionals. There's some annotiations that explain the steps in more detail. Interestingly, doing just this doesn't get rid of the doubles. How do I get rid of such numbers as 2/4, 6/8, 12/14, which have already appeared before as 1/2, 3/4, and 6/7? They all have one thing in common though, their gcd is not equal to one. For all the other numbers the gcd is one. So I made a simple change to the script, which had a while-loop that basically counted the number of loops remaining until we've 'used up' N (so it loops N times), while doing one step of the diagram each loop. Each time the gcd would be non-equal one I'd add one to W, the remainder counter. Essentially it means that the code effectively 'skipped' these parts of the diagram. (The gcd thing I made is just Euclid's algorithm.).

That together with the polar parametrization of a rose curve, adjusted to do one whole loop in a set six seconds, made it possible to make this card. It is infinitely long and has a near-infinite amount of patterns (like 10^(10^6), or in other words leave it running until the end of time and it will STILL not very likely generate two identical patterns). On my PC, the version using a function and CreateShotA for the small bullets runs at over 200 fps, while the version using object bullets has problems passing 30 (unacceptable).

Master & Slave (high-efficiency), EDIT: made some aesthetic changes to make the pattern more easily viewable by colouring.

Code: [Select]
/*Danmakufu Pattern No.2. Roses.
(c) Aphid, ZUN, CtC team. */
#TouhouDanmakufu
#include<math.h>   
#Title[Roses]
#Text[Roses]
#Image[.\ykari.jpg]
/*#BackGround[User(.\bg.png, 1, 1)]*/
#PlayLevel[Phantasm]
#Player[FREE]
#ScriptVersion[3]
script_enemy_main {
#include_function "lib\SHOT_REPLACE\shot_replace.dnh";
#include_script ".\RosisRosis.txt";
    let BI=GetCurrentScriptDirectory~"boss_yukari.png";
    let BCI=GetCurrentScriptDirectory~"Yukari.png";
    let f=1000;
    let g=0;
    let ang=0;
    let z=0;
    let h=0;
    let lz=0;
    let W = "STRING";
    let Q = "zero";
    let Z = "zero";
@Initialize {
shotinit;
LoadGraphic(BI);
SetLife(1000000);
        SetDamageRate(0,0);
        SetInvincibility(60);
CutIn(YOUMU, "Infinite multiple Boundary "\""Roses"\", BCI,

0, 0, 420, 400);
      SetScore(4320000);
        SetEnemyMarker(true);
        SetDurableSpellCard;
SetY(60);
}
@MainLoop {
SetCollisionA(GetX, GetY, 42);
        SetCollisionB(GetX, GetY, 42);
if(f == 1080) {
RosisRosis(GetCenterX, GetCenterY, 0, f, PURPLE03, RED23,

ORANGE23, YELLOW23, GREEN23, AQUA23, BLUE23 ,1,1080, 1, 1);
RosisRosis(GetCenterX, GetCenterY, 0, f,  PURPLE03, RED23,

ORANGE23, YELLOW23, GREEN23, AQUA23, BLUE23 ,1,1080, 1, -1);
}
if(f%180 == 120){
ascent(i in 0..8){
ascent(j in 0..10){
CreateShotA(1, (GetCenterX + (200 + 12 * j) * cos(60*i+30)),

GetCenterY + (200 + 12*j) * sin(60*i+30), 60);
SetShotDataA(1, 0, (200 + 12*j) * 2 * 3.1415 / 180, 60 * i +

120, 2, 0, 50, PURPLE04);
SetShotKillTime(1, 180);
FireShot(1);
}}}
if(f%1080 == 0){
SetMovePositionRandom01(65, 20, 10, 50, 50, GetClipMaxX -

50, GetClipMinY + 170);
}
/* Scoring Function: 2000 points per graze plus 75 points per life point of

the boss taken off.*/
if(f > 10) {
AddScore(75 * (1000000 - GetLife() - h));
h = 1000000 - GetLife();
AddScore(2000 * (GetGraze - g));
g = GetGraze();
}
yield;
/* Count the counter up 1*/
f++
}
        @DrawLoop {
SetTexture(BI);
if(f%32 >= 0 && f%32 < 8)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,31,95,94);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(f%32 >= 8 && f%32 < 16)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,159,95,222);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(f%32 >= 16 && f%32 < 24)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,287,95,350);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(f%32 >= 24 && f%32 < 32)
{
if(GetSpeedX()==0)
{
SetGraphicRect(543,31,607,94);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
DrawGraphic(GetX(),GetY());
DrawText("WAVE:"~inttostring(floor(f/1080)), 40, 30, 20, 255)
}
@Finalize {
}
@Background {
}
function inttostring(number)
{
   let str = ToString(number);
   let str2 = "";
   let i = 0;
   while (str[i] != '.')
   {
      str2 = str2 ~ [str[i]];
      i++;
   }
   return(str2);
}
}

Code: [Select]
/* RosisRosis functions. Math & Bullet, Aphid  Ver IV*/

function gcd(a, b){
let array = [a, b];
let arrayb = [0];
let swap = 0;
/* first check if a > b. If not, swap 'em. */
if(a < b){
swap = a;
a = b;
b = swap;
}
let a = absolute(trunc(a));
let b = absolute(trunc(b)); /* if you add non-positive integers this thing otherwise crashes your pc's.*/
let count = 0;
loop{
count++; /* keep a count on the amount of elements in the array.*/
arrayb[0] = array[count-1] % array[count];
array=array~arrayb;
if (array[count+1] == 0){
break; /*apply the euclidian algorithm (don't keep track of stuff though that's too hard on the pc */
}
}
let G = array[count];
return G
}

function NtoQ(N){
let W = N - 1;
if (N > 0) {
W = trunc(N) - 1;
} else {
W = trunc(N * -1) - 1;}
let a = 1;
let b = 1;
while(W > 0){
/* if W is zero, we're done with the diagram!*/
/* determine if we go to the right in the diagram.*/
if (b == 1 && a%2 == 1){
W=W-1;
a++;
}
/* now determine if we go down in the diagram.*/
else if (a == 1 && (b%2 == 2 || b%2 == 0)){
W=W-1;
b++;
}
/* now determine whether we're going down-left.*/
else if ((a + b) % 2 == 1){
W=W-1;
b++;
a=a-1;
}
/* well, we're going up-right now.*/
else if ((a + b) % 2 != 1){
W=W-1;
a++;
b=b-1;
}
/* now determine whether or not we've hit a double number. For example, 4/2 = 2/1 so we want to skip those numbers. These numbers have in common that their greatest

common denominator is greater than one so we sort by that. If that is so, we will have to 'skip' this number, in other words ADD one to W.
*/
if(gcd(a, b) != 1){
W++;
}
}
let Q = [a, b];
return Q
}

function Accbullet(x, y, ang, grf, grf2, grf3, grf4, grf5, grf6, invspeed, vel){
CreateShotA(1, x, y, 0);
SetShotDataA(1, 0, 0, ang, 0, 0, 0, grf);
SetShotDataA(1, 80, 0, ang, 0, 0, 0, grf2);
SetShotDataA(1, 160, 0, ang, 0, 0, 0, grf3);
SetShotDataA(1, 240 / invspeed, NULL, NULL, 0, vel * 120 / 46200, 20, grf4);
SetShotDataA(1, 360 / invspeed, NULL, NULL, 0, vel * 120 / 46200, 20, grf5);
SetShotDataA(1, 480 / invspeed, NULL, NULL, 0, 0, 20, grf6);
FireShot(1);
}

task RosisRosis(let x, let y, let ang, let fc, let grf, let accgrf, let accgrf2, let accgrf3, accgrf4, accgrf5, accgrf6, let speed, let len, let accspd, let inv){
let obj = Obj_Create(OBJ_SHOT);
Obj_SetX(obj, x);
Obj_SetY(obj, y);
ObjShot_SetGraphic(obj, grf);
let fch = fc;
let u = trunc((fch - fc) / len);
let uold = 0;
let k = [1,1];
let theta = ang;
let Xpre = 0;
let Ypre = 0;
let newX = 0;
let newY = 0;
let Xaft = 0;
let strings = "";
let Yaft = 0;
let Angtrav = 0;
let radius = 1;
loop
{
if(Obj_GetY(obj) < 1){
obj = Obj_Create(OBJ_SHOT);
ObjShot_SetGraphic(obj, grf);
}

fch++;
Xpre = Obj_GetX(obj);
Ypre = Obj_GetY(obj);
theta = speed * (fch - fc) / 1.5 + ang;
if(fch%len == 1){
u++;
k = NtoQ(u);
}
radius = cos(theta * (k[0]));
newX = 200 * inv * radius * cos(theta * k[1]) + x;
newY = 200 * inv * radius * sin(theta * k[1]) + y;
Obj_SetX(obj, newX);
Obj_SetY(obj, newY);
Xaft = Obj_GetX(obj);
Yaft = Obj_GetY(obj);
Angtrav = atan2((Yaft - Ypre), (Xaft - Xpre));
Accbullet(Xaft, Yaft, Angtrav + 90, accgrf, accgrf2, accgrf3, accgrf4, accgrf5, accgrf6, accspd, fch%4+1);
Accbullet(Xaft + (Xaft - Xpre)/2, Yaft + (Yaft - Ypre)/2, Angtrav - 90, accgrf, accgrf2, accgrf3, accgrf4, accgrf5, accgrf6,  accspd, fch%4+1);
yield;
}
}







And the less efficient version for those who want to test it:
Master Code;

Code: [Select]
/*Danmakufu Pattern No.2. Roses.
(c) Aphid, ZUN, CtC team. */
#TouhouDanmakufu
#include<math.h>   
#Title[Roses]
#Text[Roses]
#Image[.\ykari.jpg]
/*#BackGround[User(.\bg.png, 1, 1)]*/
#PlayLevel[Phantasm]
#Player[FREE]
#ScriptVersion[2]
script_enemy_main {
#include_function "lib\SHOT_REPLACE\shot_replace.dnh";
#include_script ".\RosisRosis.txt";
    let BI=GetCurrentScriptDirectory~"boss_yukari.png";
    let BCI=GetCurrentScriptDirectory~"Yukari.png";
    let f=1000;
    let g=0;
    let ang=0;
    let z=0;
    let h=0;
    let lz=0;
    let W = "STRING";
    let Q = "zero";
    let Z = "zero";
@Initialize {
shotinit;
LoadGraphic(BI);
SetLife(1000000);
        SetDamageRate(0,0);
        SetInvincibility(60);
CutIn(YOUMU, "Infinite multiple Boundary "\""Roses"\", BCI,

0, 0, 420, 400);
      SetScore(4320000);
        SetEnemyMarker(true);
        SetDurableSpellCard;
SetY(60);
}
@MainLoop {
SetCollisionA(GetX, GetY, 42);
        SetCollisionB(GetX, GetY, 42);
if(f == 1080) {
RosisRosis(GetCenterX, GetCenterY, 0, f, PURPLE03,

GREEN23,1,1080, 1, 1);
RosisRosis(GetCenterX, GetCenterY, 0, f, PURPLE03,

BLUE23,1,1080, 1, -1);
}
if(f%180 == 120){
ascent(i in 0..8){
ascent(j in 0..10){
CreateShotA(1, (GetCenterX + (200 + 12 * j) * cos(60*i+30)),

GetCenterY + (200 + 12*j) * sin(60*i+30), 60);
SetShotDataA(1, 0, (200 + 12*j) * 2 * 3.1415 / 180, 60 * i +

120, 2, 0, 50, PURPLE04);
SetShotKillTime(1, 180);
FireShot(1);
}}}
if(f%1080 == 0){
SetMovePositionRandom01(65, 20, 10, 50, 50, GetClipMaxX -

50, GetClipMinY + 170);
}
/* Scoring Function: 2000 points per graze plus 75 points per life point of

the boss taken off.*/
if(f > 10) {
AddScore(75 * (1000000 - GetLife() - h));
h = 1000000 - GetLife();
AddScore(2000 * (GetGraze - g));
g = GetGraze();
}
yield;
/* Count the counter up 1*/
f++
}
        @DrawLoop {
SetTexture(BI);
if(f%32 >= 0 && f%32 < 8)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,31,95,94);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(f%32 >= 8 && f%32 < 16)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,159,95,222);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(f%32 >= 16 && f%32 < 24)
{
if(GetSpeedX()==0)
{
SetGraphicRect(31,287,95,350);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
if(f%32 >= 24 && f%32 < 32)
{
if(GetSpeedX()==0)
{
SetGraphicRect(543,31,607,94);
}
else if(GetSpeedX()>0)
{
SetGraphicRect(286,415,352,478);
}
else if(GetSpeedX()<0)
{
SetGraphicRect(286,159,348,222);
}
}
DrawGraphic(GetX(),GetY());
}
@Finalize {
}
@Background {
}
}




Code: [Select]
function gcd(a, b){
let array = [a, b];
let arrayb = [0];
let swap = 0;
/* first check if a > b. If not, swap 'em. */
if(a < b){
swap = a;
a = b;
b = swap;
}
let a = absolute(trunc(a));
let b = absolute(trunc(b)); /* if you add non-positive integers this thing otherwise crashes your pc's.*/
let count = 0;
loop{
count++; /* keep a count on the amount of elements in the array.*/
arrayb[0] = array[count-1] % array[count];
array=array~arrayb;
if (array[count+1] == 0){
break; /*apply the euclidian algorithm (don't keep track of stuff though that's too hard on the pc */
}
}
let G = array[count];
return G
}

function NtoQ(N){
let W = N - 1;
if (N > 0) {
W = trunc(N) - 1;
} else {
W = trunc(N * -1) - 1;}
let a = 1;
let b = 1;
while(W > 0){
/* if W is zero, we're done with the diagram!*/
/* determine if we go to the right in the diagram.*/
if (b == 1 && a%2 == 1){
W=W-1;
a++;
}
/* now determine if we go down in the diagram.*/
else if (a == 1 && (b%2 == 2 || b%2 == 0)){
W=W-1;
b++;
}
/* now determine whether we're going down-left.*/
else if ((a + b) % 2 == 1){
W=W-1;
b++;
a=a-1;
}
/* well, we're going up-right now.*/
else if ((a + b) % 2 != 1){
W=W-1;
a++;
b=b-1;
}
/* now determine whether or not we've hit a double number. For example, 4/2 = 2/1 so we want to skip those numbers. These numbers have in common that their greatest common denominator is greater than one so we sort by that. If that is so, we will have to 'skip' this number, in other words ADD one to W.
*/
if(gcd(a, b) != 1){
W++;
}
}
let Q = [a, b];
return Q
}

task Accbullet(x, y, ang, grf, invspeed, vel){
let obj = Obj_Create(OBJ_SHOT);
let Dist = 0;
let angle = ang;
let newx = 0;
let newy = 0;
Obj_SetX(obj, x);
Obj_SetY(obj, y);
Obj_SetAngle(obj, ang);
ObjShot_SetGraphic(obj, grf);
let counter = 0;
while( !Obj_BeDeleted(obj))
{
counter++;
angle = atan2(Obj_GetY(obj) - GetCenterY, Obj_GetX(obj) - GetCenterX);
Dist = ((Obj_GetX(obj) - GetCenterX)^2+(Obj_GetY(obj) - GetCenterY)^2)^0.5;
if(240 * invspeed < counter && counter < 480 * invspeed){
Obj_SetSpeed(obj, Obj_GetSpeed(obj) + vel * 120 / 46200);
}
else if (counter > 479 * invspeed) {
Obj_SetSpeed(obj, vel);
}
yield;
}}

task RosisRosis(let x, let y, let ang, let fc, let grf, let accgrf, let speed, let len, let accspd, let inv){
let obj = Obj_Create(OBJ_SHOT);
Obj_SetX(obj, x);
Obj_SetY(obj, y);
ObjShot_SetGraphic(obj, grf);
let fch = fc;
let u = trunc((fch - fc) / len);
let uold = 0;
let k = [1,1];
let theta = ang;
let Xpre = 0;
let Ypre = 0;
let newX = 0;
let newY = 0;
let Xaft = 0;
let strings = "";
let Yaft = 0;
let Angtrav = 0;
let radius = 1;
loop
{
if(Obj_GetY(obj) < 1){
obj = Obj_Create(OBJ_SHOT);
ObjShot_SetGraphic(obj, grf);
}

fch++;
Xpre = Obj_GetX(obj);
Ypre = Obj_GetY(obj);
theta = speed * (fch - fc) / 1.5 + ang;
if(fch%len == 1){
u++;
k = NtoQ(u);
}
radius = cos(theta * (k[0]));
newX = 200 * inv * radius * cos(theta * k[1]) + x;
newY = 200 * inv * radius * sin(theta * k[1]) + y;
Obj_SetX(obj, newX);
Obj_SetY(obj, newY);
Xaft = Obj_GetX(obj);
Yaft = Obj_GetY(obj);
Angtrav = atan2((Yaft - Ypre), (Xaft - Xpre));
Accbullet(Xaft, Yaft, Angtrav + 90, accgrf, accspd, fch%4+1);
Accbullet(Xaft, Yaft, Angtrav - 90, accgrf, accspd, fch%4+1);
yield;
}
}

Lesson of the day: Don't use Tasks if you don't have to. Same with object bullets.

By the way, the offending section in my code with the blue & red bullets could be changed so that there's no object collision detection in the sense that the program physically checks all the pixels each frame. There's an analytical solution to determine the time each induvidual blue bullet takes to be hit by a red bullet given their velocities. It's only for pre-spawned ones of course but that's not that big a problem. The bigger problem? The formula my computer gave me was 260MB of complex numbers   :-[... uhm scrap that. Running that 60.000ish times per second is going to take a tiny bit more processing power than collision detection  :D.

Edit: It needs sound. Just put on necrofantasia or something while running it.
By the way, for those who want some interesting food for thought: How many petals does the rose have you see 216000 (one hour) frames after the start of the spell?

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on October 10, 2009, 12:51:10 AM
For some reason @Missed only works once. I set it to play a sfx when I die, but it only plays the first time I die.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Lawence Codye on October 10, 2009, 09:57:14 AM
@Naut

Thanks, that solved the problem...

now...another question, anybody.  Is there a way to have 4 options on screen instead of just 2...cause if so, I need to ask how to go about doing this?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 10, 2009, 01:30:27 PM
Since there are no functions for that in Danmakufu, something like this, as discussed in P.24 of the thread, would be helpful.

Code: [Select]
#TouhouDanmakufu
#Title[MENU FTW]
#Text[This is the description. Did you know that? Oh, sorry.]
#Player[FREE]
#ScriptVersion[2]
script_enemy_main {
    let number = 0;
    let orange = [255, 142, 78];
    let white = 255;
    let r1 = 0; let g1 = 0; let b1 = 0;
    let r2 = 0; let g2 = 0; let b2 = 0;
    let r3 = 0; let g3 = 0; let b3 = 0;
    @Initialize {
        SetLife(1);
    }

    @MainLoop {
    //////////////////////////////////
    ForbidBomb(true); ForbidShot(true);
    ///////////////////////////////////
    if(number == 0) {
    r1 = white; g1 = white; b1 = white;
    r2 = orange[0]; g2 = orange[1]; b2 = orange[2];
    r3 = orange[0]; g3 = orange[1]; b3 = orange[2];
    }
    if(number == 1) {
    r2 = white; g2 = white; b2 = white;
    r1 = orange[0]; g1 = orange[1]; b1 = orange[2];
    r3 = orange[0]; g3 = orange[1]; b3 = orange[2];
    }
    if(number == 2) {
    r3 = white; g3 = white; b3 = white;
    r1 = orange[0]; g1 = orange[1]; b1 = orange[2];
    r2 = orange[0]; g2 = orange[1]; b2 = orange[2];
    }
    ///////////////////////////////////
    if(number < 0) {
    number = 0;
    }
    if(number > 2) {
    number = 2;
    }
    if(GetKeyState(VK_UP) == KEY_PUSH) {
    number--;
    }
    if(GetKeyState(VK_DOWN) == KEY_PUSH) {
    number++;
    }
    //////////////////////////////////
    if(GetKeyState(VK_SHOT)==KEY_PUSH) {
      VanishEnemy;
    //Here you put stuff that happens depending what the variable "number" finally is, blah, blah, blah
    }
    }
    @DrawLoop {
               SetFontColor(r1, g1, b1, r1, g1, b1);
   DrawText("The first choice", 40, 45, 20, 255);
               SetFontColor(r2, g2, b2, r2, g2, b2);
   DrawText("Choice 2", 40, 65, 20, 255);
               SetFontColor(r3, g3, b3, r3, g3, b3);
   DrawText("Choice 3", 40, 85, 20, 255);
    }

    @Finalize {
    ForbidBomb(false); ForbidShot(false);
    SetPlayerX(GetCenterX); SetPlayerY(GetClipMaxY-75);
    }
}

This shows three options. put something similar to this in a stage script would be OK.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Lawence Codye on October 10, 2009, 02:36:39 PM
...I meant for #TouhouDanmakufu[player] scripts...
Options that follow the player character around...how to make it so that there is 4 of those Options?
...I'm trying to make ReimuC from MoF...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 10, 2009, 09:37:17 PM
Darnit, why can't I get this thing down?


Alright, what I'm trying to do is make the bullets shoot bullets, so when the first pair of bullets hits the edge of the screen (min/max X Y coordinate), another pair of bullets fires in the opposite direction, and doesn't come back when it leaves the screen.

(Fujiwara "Flaw of Forgiving Shrine" is the best spellcard I can describe it as.  I'm making mine different, but same basic concept.)

AddShot isn't working for me because that's controlled by frames, and the second pair of bullets' coordinates fired will not be on the edge like I want it, if the boss that's firing the first pair of bullets moves a few pixels.  What to do?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on October 10, 2009, 09:54:24 PM
Use object bullets.

Here is an example code for a shot that creates some more shots after reaching the edge of the screen.

Code: [Select]
task bullet(x,y,angle)
{
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj,x,y);
Obj_SetAngle(obj,angle);
Obj_SetSpeed(obj,2);
ObjShot_SetGraphic(obj,BLUE56);
ObjShot_SetBombResist(obj,true);
ObjShot_SetDelay(obj,10);

while(Obj_GetX(obj) > GetClipMinX+16 && Obj_GetX(obj) < GetClipMaxX-16 && Obj_GetY(obj) > GetClipMinY+16 && Obj_GetY(obj) < GetClipMaxY-16) //While still in bounds, yield.
{yield;}

CreateShot01(Obj_GetX(obj),Obj_GetY(obj),1.5,angle+190,PURPLE56,10);
CreateShot01(Obj_GetX(obj),Obj_GetY(obj),1.5,angle+170,PURPLE56,10);



Obj_Delete(obj);

}

Remember to yield in your @MainLoop or else most of the code will be ignored!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 10, 2009, 11:17:11 PM
alright.

One question though, why does the yield in there have to be in brackets?


Whoops, nevermind.  Found it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 11, 2009, 01:07:43 AM
Code: [Select]
SetShotDirectionType(PLAYER);doesn't work with object bullets.  What can I use?  I'm not looking for
Code: [Select]
GetAngleToPlayer that is only useful for getting the boss's coordinates to the player, and is useless if I spawn the object shot away from the boss.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 11, 2009, 03:24:28 AM
@Fujiwara No Mokou:
Don't know how many times I've posted this:
atan2(Player's Y coordinate - Bullet's Y coordinate, Player's X coordinate - Bullet's X coordinate) will get the angle from the bullet (or any point) to the player.
Thus:
atan2(GetPlayerY - Obj_GetY(obj), GetPlayerX - Obj_GetX(obj))


@Aphid:
@naut.
I've also found out something while making a diffrent script yesterday. If I could replace the task in the script I presented then with a function it could probably solve everything. For example, here is a master script with two slave scripts. The second slave runs significantly slower than the primary (which I'm using now) whilst what I'm doing is exactly the same. The cinch? I used a task. Seems NuclearCheese was right about those tasks being poorly coded  :).

Eh, I know tasks will slow down your computer. Running @MainLoop copies a couple hundred times per frame versus only once? Yeah, I know. My argument was for coding basic attacks, in which case the slowdown is so negligable that it didn't matter since you would only have at most half a dozen tasks running, maybe a few more if you've got a few object bullets floating around (of which the object bullets still take more processing power than the actual tasks, as far as I can tell). Granted, I'm not very good at taking tasks out of anything, so... Yeah. My bad anyway. Also, why did you use tasks in the first place if you could just use the function command? The only useful thing about tasks is the use of yield;, so if you didn't need it...

I still should've taken a look at what you were actually doing with your object bullets, since if you could just make them as regular bullets then this problem would've been solved much faster. Should've known, argh!


@pikaguy900:
I'm still not seeing how throwing an ObjEffect over your ObjShot explosion as well as the bullets wouldn't solve everything. Why can't you do this?


@UltimaRepman:
@Naut
Thanks, that solved the problem...

I skimmed over that code tidbit quite a few times before noticing it. I could see how you were running in to problems, heh.

now...another question, anybody.  Is there a way to have 4 options on screen instead of just 2...cause if so, I need to ask how to go about doing this?

The exact same way you spawn two, just repeat two more times. If you're going by Stuffman's tutorial (http://www.shrinemaiden.org/forum/index.php?topic=210.0), just make if(position=="BLAH"){ do shit }, if(position=="LOL"){ do more shit }. Or something to that effect.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 11, 2009, 04:47:13 AM
If I use DrawGraphic(x,y); to draw an image, does the (0,0) of the image correspond to the (x,y) of the Danmakufu Window?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Johnny Walker on October 11, 2009, 05:05:23 AM
If I use DrawGraphic(x,y); to draw an image, does the (0,0) of the image correspond to the (x,y) of the Danmakufu Window?

Yes, my lord!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on October 11, 2009, 06:06:16 AM
Yes, my lord!
Isn't the middle of the image drawn on (x, y) not (0, 0)?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 11, 2009, 07:22:58 AM
Isn't the middle of the image drawn on (x, y) not (0, 0)?
I'm thinking of this also: in drawtext, (0,0) of the text -> (x,y)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Johnny Walker on October 11, 2009, 10:30:10 AM
Isn't the middle of the image drawn on (x, y) not (0, 0)?

Oh, you're right. I misunderstood the question.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 11, 2009, 06:23:35 PM
Alright, I've learned a lot here.  I've asked this question once before, but I might as well ask it again and rephrase it, seeing there are so many things you can do with danmakufu.

(http://img21.imageshack.us/img21/7359/captureln.png)
The magic circle that revolves around the boss, is there a way to change it?  Say, to a ripped sprite from one of the games, or your own?  I tried using my own circle, but it just wasn't...right.  It looks as if Danmakufu takes a flat, straight line and repeats it several times, and bends it into a circle. And reduces the area of that circle as time runs out, without changing the "height" of the image itself, except unless you either loose a life or use a bomb.  But I don't have the slightest clue how to do this.
(http://img49.imageshack.us/img49/9937/etama3.png)
Also, the cubes that revolve around the main boss. Can those be changed?  Or do I have to set up my own?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on October 11, 2009, 06:33:19 PM
Both of them can be replaced by saving an exterior file with the same name. I can't exactly remember where they're supposed to be positioned or the filename, though.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 11, 2009, 07:46:20 PM
Both of them can be replaced by saving an exterior file with the same name. I can't exactly remember where they're supposed to be positioned or the filename, though.

Well, looks like I'll have a lot of searching to do. Uh, can it be done manually though, like I asked?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 11, 2009, 08:08:36 PM
system.png has all the default graphics on it, (pathname /system/system.png if I remember correctly), includes things like the cut-in bar, the magic circle and those fucking squares. There were one or two of us trying to decipher where they were located on the image, so hopefully one of them strolls by to inform us.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 11, 2009, 10:58:18 PM
Yeah. That cut-in bar is so annoying. I really hope they do find this.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 12, 2009, 03:36:57 AM
Ah shit, double posting in two threads. Great. Well, yield; goes in the @MainLoop, not the @DrawLoop, canobiecrazy.

Ah we deleted his post, lovely.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on October 12, 2009, 04:06:05 PM
Is there actually a way to bend a linear graphic into a circle? It doesn't seem possible, but I'm just curious (I don't particularly need it for anything, unless I choose to come after the Magic Circle and make a replacement function).

And yeah, lol, I'm still alive.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: PT8Sceptile on October 12, 2009, 05:08:10 PM
Karfloozly, for the graphic bending thing, effect objects with a huge amount of vertices might work. If you place effect object vertices in the field in a different formation than how they are placed on the image, the image seemingly bends. A test I made:

Code: [Select]
task asdf() {
let objeff = Obj_Create(OBJ_EFFECT);
ObjEffect_SetTexture(objeff, GetCurrentScriptDirectory~"\Yingyang.png");
ObjEffect_SetRenderState(objeff, ALPHA);
ObjEffect_SetLayer(objeff, 3);
ObjEffect_CreateVertex(objeff, 10);
ObjEffect_SetPrimitiveType(objeff,PRIMITIVE_TRIANGLEFAN);
ObjEffect_SetVertexUV(objeff, 0, 40, 40);
ObjEffect_SetVertexUV(objeff, 1, 0, 0);
ObjEffect_SetVertexUV(objeff, 2, 0, 40);
ObjEffect_SetVertexUV(objeff, 3, 0, 80);
ObjEffect_SetVertexUV(objeff, 4, 40, 80);
ObjEffect_SetVertexUV(objeff, 5, 80, 80);
ObjEffect_SetVertexUV(objeff, 6, 80, 40);
ObjEffect_SetVertexUV(objeff, 7, 80, 0);
ObjEffect_SetVertexUV(objeff, 8, 40, 0);
ObjEffect_SetVertexUV(objeff, 9, 0, 0);
while(!Obj_BeDeleted(objeff)) {
ObjEffect_SetVertexXY(objeff, 0, GetCenterX, GetCenterY);
ObjEffect_SetVertexXY(objeff, 1, GetCenterX - 80, GetCenterY - 20);
ObjEffect_SetVertexXY(objeff, 2, GetCenterX, GetCenterY - 30);
ObjEffect_SetVertexXY(objeff, 3, GetCenterX + 80, GetCenterY - 20);
ObjEffect_SetVertexXY(objeff, 4, GetCenterX + 70, GetCenterY);
ObjEffect_SetVertexXY(objeff, 5, GetCenterX + 60, GetCenterY + 30);
ObjEffect_SetVertexXY(objeff, 6, GetCenterX, GetCenterY + 20);
ObjEffect_SetVertexXY(objeff, 7, GetCenterX - 60, GetCenterY + 30);
ObjEffect_SetVertexXY(objeff, 8, GetCenterX -70, GetCenterY);
ObjEffect_SetVertexXY(objeff, 9, GetCenterX - 80, GetCenterY - 20);
yield;
}
}

Which results in:

(http://img91.imageshack.us/img91/5728/exampleh.jpg)

(Text edited in afterwards.)

So, since effect objects can apparently bend an object in weird shapes, you could in theory create a huge amount of vertices on the edge of the image you want to curve and place the curved edges on two circles. Or something like that, hopefully you get the idea. However, I'm not exactly sure on this, since the ball in the above image has only 10 vertices, a curved surface would need a lot more to look decent, and I'm not sure how much computing time would some hundreds of vertices require. You can try it out, though.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 12, 2009, 06:08:18 PM
Clipping the image using tan theta(?) would be better, but Danmakufu seems to hide that function from us.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Hat on October 12, 2009, 06:27:26 PM
*single tear* ... I was hoping that I wouldn't have to set a zillion vertices... Oh, well.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 12, 2009, 07:56:52 PM
Only way to decypher system.png is to create a large sheet perhaps 256x256 or 512x512  with numbered grids which are 32x32. So you can like probably figure out most of them.

The question is, how to make a grid like that :V

Grid made quickly in photoshop, the bomb icon is half a 1c and the enemy marker is 1f en 2f. (non pattern zone)
The player invincible circle seems to be at 1f till 4f (thin zebra pattern) on the X-axis and till bottom of the sheet ( which is missing 16 pixels ) so i.

Cannot figure out the lifebar yet :V seems to be in the non-pattern zone of the sheet as it appears clean.

PS edit: The enemy circle seems to be outside the 512x512 zone. That is interesting.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 13, 2009, 12:22:07 AM
How can you (and me) decypher system.png?

Just save a system.png there would be OK?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 13, 2009, 05:19:06 AM
One more question.

I have a lot of stuff working in my scripts, the spellcards work, everything is coming out nicely.


I even made my own effect for when the boss blows up.  Problem is, though, that it won't load @Finalize.

It's an arrange of effect objects that I cooked up.  But I don't know how to get the X,Y coordinates from the boss when it blows up, and pass it on to a separate enemy script/file, which spawns just where the boss blows up (GetX, GetY).

The main boss is called in the stage script repeatedly. Each time it's defeated, a new one comes up after the blow-up, and resurrection effect.  (I had to do this so the health bar rises in sync with the "resurrection".)

I don't know if doing it through child enemy scripts were the best way to do it, but it worked out nicely so far.


So, can anyone help me with my problem?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 13, 2009, 05:27:52 AM
Code: [Select]
@Finalize{
SetCommonData("EnemyX",GetX);
SetCommonData("EnemyY",GetY);
...

Next script:
Code: [Select]
@Initialize{
SetX(GetCommonData("EnemyX");
SetY(GetCommonData("EnemyY");
...

Use Common Data whenever you have to pass variables between scripts.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 13, 2009, 05:33:41 AM
How can you (and me) decypher system.png?

Just save a system.png there would be OK?

Any sheet you place in danmakufu\img and which is named System.png will automatically replace the system sprites ingame. Once we know which image is located where on the sheet, we can make templates.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 13, 2009, 05:34:21 AM
Haha wow it's so obvious... I've spent hours working my way around for it, and still couldn't get it, while you cook up a solution for it in less than a minute.
Is there anything you don't know?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 13, 2009, 06:21:59 AM
Quote
Is there anything you don't know?
How the fuck CtC works.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Chronojet ⚙ Dragon on October 13, 2009, 03:56:31 PM
How the fuck CtC works.
Mmmmmm, I hacked my copy to let me play Phantasm stage. I also hacked it so that it extends my player's lives by 1 every time Reimu (PH) moves. (insert colon + capital V here)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Mugen Hut on October 13, 2009, 08:47:16 PM
How can I know what are the coordinates of multiple sprites on a spritesheet for the SetGraphicRect part?  What program can help to find the numbers?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 13, 2009, 08:52:12 PM
MSPaint. Scroll around with your mouse, the coordinates are displayed on the bottom right of the program. PROTIP: it's usually 2^x (2, 4, 8, 16, 32, 64, 128, 256, 512).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on October 13, 2009, 11:03:00 PM
Photoshop is more accurate since you can actually see the pixels if you have the background set to transparent
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on October 13, 2009, 11:11:27 PM
Most CtC boss sprites are 128x128. For others, just divide the total image size by the number of columns/rows of sprites. It's usually around 64x64 or 64x80 for official Touhou sprites. (I don't really care about the JP sprite theft drama, we just simply don't have enough English spriters/composers to have original stuff for every fan game/fan creation)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 14, 2009, 12:16:12 AM
Can the obj variable used in obj=Obj_Create(SHOT); be used for AddShot?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on October 14, 2009, 12:26:49 AM
Nope, it doesn't quite work like that.

obj=Obj_Create() stores the ID of the object to obj so that it can be referenced later, but it's not the same as the CreateShot IDs.

Just use the regular CreateShot functions, with Obj_GetX(obj), Obj_GetY(obj), and Obj_GetAngle(obj) instead of the usual variables.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 14, 2009, 01:11:31 AM
I have a question.

How can I have it set up so I can fire 70 bullets (or any other number higher than 60) over a period of 60 frames?

Actually, scratch that.  How can I fire "X" amount of bullets over a period of "F" frames?

Normally, the loop{ fire so,so bullets; loop(delay this many frames before repeating loop){yield;}}  does it enough for me, but it won't cut it this time. And it limits me to firing 60 bullets, or 30, or 20 bullets per second, and so on.


Note: I do not want it to be fired all at the same time, but all of it over a period of a controlled time (or frames).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 14, 2009, 01:18:57 AM
I have a question.

How can I have it set up so I can fire 70 bullets (or any other number higher than 60) over a period of 60 frames?

Actually, scratch that.  How can I fire "X" amount of bullets over a period of "F" frames?

Normally, the loop{ fire so,so bullets; loop(delay this many frames before repeating loop){yield;}}  does it enough for me, but it won't cut it this time. And it limits me to firing 60 bullets, or 30, or 20 bullets per second, and so on.


Note: I do not want it to be fired all at the same time, but all of it over a period of a controlled time (or frames).
imma take a shot at this one,

Try putting multiple loops, with an accent in delay.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 14, 2009, 01:21:36 AM
I've tried that.
I've tried that, and failed miserabely.
I don't know how it works.  Can you give an example by code?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 14, 2009, 01:48:24 AM
I've tried that.
I've tried that, and failed miserabely.
I don't know how it works.  Can you give an example by code?
uhh....im not quite sure how the accent works but i think something like this should work:
Code: [Select]
#TouhouDanmakufu
#Title[..]
#Text[..]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main{


@Initialize{
SetLife(1000);
SetMovePosition01(GetCenterX,GetCenterY,5);

mainTask;
}

@MainLoop{

yield;

}

@DrawLoop{

}

@BackGround{

}

@Finalize{

}


task mainTask{
yield;
fire;
}

task fire{
loop{
loop(60){
ascent(i in 1..60){
CreateShot01(GetEnemyX, GetEnemyY, 3, rand(0,360), RED02, 0*i);}}
loop(10){
ascent(i in 1..10){
CreateShot01(GetEnemyX, GetEnemyY, 3, rand(0,360), RED02, 0*i);}}

wait(10);
yield;
}
}

function wait(w){
loop(w){yield;}
}

}

i think...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Azure Lazuline on October 14, 2009, 02:20:56 AM
The way I would do it is to set up 3 variables, "shots" (total number to fire), "time" (total time to go through them), and "total" (I'll explain it later).

The best way to do this would be in a task, and loop this whole thing "time" times with a yield at the end of the loop. Shots divided by time gets you the amount to fire each frame, which you can store in another variable if you want. Take this number and add it to total each frame. Then while(total>=1){fire shot, total--;}.

This sounds perfect in my head, but I can't quite put it into words. If you need further explanation, I could throw together a simple script.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 14, 2009, 02:23:53 AM
This sounds perfect in my head, but I can't quite put it into words. If you need further explanation, I could throw together a simple script.

Yeah, can you do that?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 14, 2009, 02:30:25 AM
Im sorry Fujiwara, i tried

IDEA!!!!

it wont be in a task tho, lets say that you want to fire 70 bullets in 1 sec, or 60 frames:

if(GetTimer<User Defined && GetTimer>one second away from first){
    Bullet Code}
then
if(GetTimer<Same as Above && frame%10==0 && GetTimer>Same as Above){
    Bullet Code}

this will fire 60 bullets over the first code,
then 10 over the second code,
thus 70 bullets over 1 sec!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Azure Lazuline on October 14, 2009, 02:47:37 AM
Here you go, easily customizable. Right now I just have it shoot out 20 RED05 bullets in random directions over 13 frames (I picked a strange number just to verify it will work with anything) every 200, and you can easily change the code in both MainLoop and the while loop in the task to do whatever you want. It will work with any two numbers, whether shots is greater than time or the other way around.

Code: [Select]
#TouhouDanmakufu
#Title [Shot test thingy]
#Text [firing x shots over y period of time]
#ScriptVersion [2]
#Player[FREE]

script_enemy_main {

let frame = 0;

    @Initialize {
        SetX(GetCenterX);
        SetY(GetClipMinY + 120);
        SetLife(1500);
        SetTimer(50);
        SetScore(1000000);


        LoadGraphic("script\img\ExRumia.png");

    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 24);
        SetCollisionB(GetX, GetY, 24);

yield;

frame++;
if(frame==200){
FireShots(20,13); //20 shots in 13 frames
frame=0;
}

}


    @DrawLoop {


        SetTexture("script\img\ExRumia.png");
        SetGraphicRect(0, 0, 63, 63);
SetGraphicAngle(0,0,0);
SetGraphicScale(1,1);
SetAlpha(255);
        DrawGraphic(GetX, GetY);

    }


    @Finalize {
        DeleteGraphic("script\img\ExRumia.png");
    }





task FireShots(shots, time){

let total=0;

loop(time){
yield;
total=total+(shots/time);
while(total>=1){
CreateShot01(GetX,GetY,2,rand(0,360),RED05,0);
total=total-1;
}
}

}



}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 14, 2009, 02:50:50 AM
Here you go, easily customizable. Right now I just have it shoot out 20 RED05 bullets in random directions over 13 frames (I picked a strange number just to verify it will work with anything) every 200, and you can easily change the code in both MainLoop and the while loop in the task to do whatever you want. It will work with any two numbers, whether shots is greater than time or the other way around.

Code: [Select]
#TouhouDanmakufu
#Title [Shot test thingy]
#Text [firing x shots over y period of time]
#ScriptVersion [2]
#Player[FREE]

script_enemy_main {

let frame = 0;

    @Initialize {
        SetX(GetCenterX);
        SetY(GetClipMinY + 120);
        SetLife(1500);
        SetTimer(50);
        SetScore(1000000);


        LoadGraphic("script\img\ExRumia.png");

    }

    @MainLoop {
        SetCollisionA(GetX, GetY, 24);
        SetCollisionB(GetX, GetY, 24);

yield;

frame++;
if(frame==200){
FireShots(20,13); //20 shots in 13 frames
frame=0;
}

}


    @DrawLoop {


        SetTexture("script\img\ExRumia.png");
        SetGraphicRect(0, 0, 63, 63);
SetGraphicAngle(0,0,0);
SetGraphicScale(1,1);
SetAlpha(255);
        DrawGraphic(GetX, GetY);

    }


    @Finalize {
        DeleteGraphic("script\img\ExRumia.png");
    }





task FireShots(shots, time){

let total=0;

loop(time){
yield;
total=total+(shots/time);
while(total>=1){
CreateShot01(GetX,GetY,2,rand(0,360),RED05,0);
total=total-1;
}
}

}



}

wow........fancy
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Fujiwara no Mokou on October 14, 2009, 03:07:08 AM
That's good.  Thanks a lot.

I use a lot of manipulation in my scripts, and usually NEVER use mainloop for my tasks.  I just load everything at initialize (even object effects. That yield at the beginning of the task keeps it from crashing, if you've never tried it).

This way, I can control everything. The time, task, when it happens, if it happens, make it happen only when a certai standard is met, and only after a previous task has finished, or even have it manipulate itself, based on what the player does, in which each thing lead to a different event based on how the player moves.  Like the firing rate increasing in contrast to the boss's life.

Anyway, I need a very flexible but simple way to make this about, and that kind of script is exactly what I need.  So thanks. 
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Azure Lazuline on October 14, 2009, 03:55:23 AM
No problem. I actually used something very similar for a script I did a few days ago, so it was fresh in my mind. In my case, it was spawning x bullets along the length of a laser in y frames. I just used the same formula for timing but modified the positioning of it, so this was only five minutes of work.
I'm new here, so I might as well make a good image of myself, you know?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 14, 2009, 05:00:58 AM
I'm new here, so I might as well make a good image of myself, you know?

Good image? Tch. Overrated.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Rena-Ryuuguu on October 14, 2009, 02:52:32 PM
Well, I have a question, How can I make enemies?
Like the Tenshi Mini stage and every touhou stage ._.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 14, 2009, 04:08:30 PM
Regular enemies follow the exact same script specifications as spellcards, except they don't use plural files. You load them as "CreateEnemyFromScript" in your stage file.

In the spellcard script you'll just have all the information about what the enemy does while it's onscreen, then have it fly off and auto-delete itself eventually.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 14, 2009, 04:59:48 PM
Proof nobody reads the tutorials :(
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 15, 2009, 01:17:18 AM
ok right forum:
How do you replace the Background image in the danmakufu menus?
and the annoying Default Marisa and Reimu white colors?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 15, 2009, 01:26:04 AM
I have tried to do something new that I have not tried before: creating an enemy script inside of a boss script.

However, I have encountered a major flaw. When either the main boss or the sub-bosses' are attacked to the point where their health bars are depleted, or even when time runs out, Danmakufu crashes. I look through my script, but I see nothing wrong.

Code: [Select]
#TouhouDanmakufu
#Title[Clones]
#Text[Test script]
#Player[FREE]
#BGM[none]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\img\ExRumia.png";

let count = 0;

@Initialize {
SetLife(2000);
SetTimer(60);
SetScore(10000000);

SetEnemyMarker(true);

   CreateEnemyFromScript("Rumia2",GetClipMinX-50,GetClipMinY+180,0,0,0);
   CreateEnemyFromScript("Rumia3",GetClipMaxX+50,GetClipMinY+180,0,0,0);

SetMovePosition01(GetCenterX, GetClipMinY + 120, 5);
CutIn(YOUMU, "Test Sign"\""Text"\", "", 0, 0, 0, 0);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 64, 64);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 60) {

count=0
}
count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}







script_enemy Rumia2
{
let ImgBoss2 = "script\img\ExRumia.png";
let count2 = 0;
 
@Initialize
{
  SetLife(2000);
  SetDamageRateEx(0,0,100,25);


  LoadGraphic(ImgBoss2);
  SetTexture(ImgBoss2);
  SetGraphicRect(0, 0, 64, 64);
 
  }

@MainLoop
{
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

 if(count2 == 90){
  SetMovePosition03(GetCenterX + 50, GetClipMinY + 150, 20, 5);
  }

count2++;

}



@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss2);
}
}







script_enemy Rumia3
{
let ImgBoss3 = "script\img\ExRumia.png";
let count3 = 0;
 
@Initialize
{
  SetLife(2000);
  SetDamageRateEx(0,0,100,25);


  LoadGraphic(ImgBoss3);
  SetTexture(ImgBoss3);
  SetGraphicRect(0, 0, 64, 64);
 
  }

@MainLoop
{
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

 if(count3 == 90){
  SetMovePosition03(GetCenterX - 50, GetClipMinY + 150, 20, 5);
  }

count3++;

}



@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss3);
}
}

What could be the possible issue here? Do I need to somehow state that the sub-bosses are erased from the script at the end of the spellcard? If so, how would I do that?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 15, 2009, 02:49:59 AM
Could have something to due with deleting the same image twice, but I'm still pouring over it.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 15, 2009, 03:14:31 AM
Could have something to due with deleting the same image twice, but I'm still pouring over it.

Actually, that appears to have been the case. I just tested saving the same image as three different file names, and that actually worked than just sharing one image between each of the enemies. O.o

Thank you for that idea. That helped me solve the problem.


Then I have two more questions out of curiosity.

1. Is it possible to keep multiple bosses in a single script when they are killed (i.e. Prismriver Sisters)?

2. What kind of things would I put under the "user-defined argument" in certain pieces of scripting (like 'CreateEnemyFromScript')?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 15, 2009, 03:22:31 AM
1. Yes

2. Anything you want to pass on to the other script. Mainly used if you want to spawn more than one of the same enemy, but only change one thing in it. Like an angle value. Just use "GetArgument" in the child script to get the value you declared for the argument parameter of CreateEnemyFromScript, or whatever.

CreateEnemyFromScript("lololol", GetX, GetY, 0, 0, 2);

...Then in the child script "lololol":

let v = GetArgument;

So v will assume a value of 2 for that script.


@Demonbman:
ok right forum:
How do you replace the Background image in the danmakufu menus?
and the annoying Default Marisa and Reimu white colors?

1. You can't. People make custom menus inside scripts using ObjEffects, that might be what you're thinking of.
2. They're different scripts (if I had to guess, I don't actually have the new textured Reimu and Marisa. Correct me if I'm wrong).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 15, 2009, 03:25:58 AM
Ah, I see. That makes sense.


Then, I am sorry, but I have two more questions (this happens every single time I make a post on these topics).


1. Is it possible to keep multiple bosses in a single script when they are killed (i.e. Prismriver Sisters)?

2. How would I be able to change the angle of an enemy automatically whenever they move, to the direction they are moving? This does not seem to happen when I select ShotDirectionType(SEQUENCE) [unless this is used in some other way?].

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 15, 2009, 03:29:55 AM
1. Yes, use CommonData to pass along their last known position in the previous script to your next script and spawn familiars in @Initialize on the positions you store. Since the transition happens in one frame, you will never see them disappear.

2. SetAngle(GetAngle); ? I'm not sure what you're asking.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 15, 2009, 03:39:06 AM
1. Yes, use CommonData to pass along their last known position in the previous script to your next script and spawn familiars in @Initialize on the positions you store. Since the transition happens in one frame, you will never see them disappear.

2. SetAngle(GetAngle); ? I'm not sure what you're asking.

1. Okay.

2. SetShotDirectionType(SEQUENCE) makes 0 degrees as the angle the enemy is pointed towards, correct? If this is the case, then when the boss moves, wouldn't their angle of facing change as well? This does not appear to happen normally.

E.X.
Code: [Select]
#TouhouDanmakufu
#Title[Moving Test]
#Text[Test script]
#Player[FREE]
#BGM[none]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\img\ExRumia.png";

let count = 0;
let a = 0;
let speed = 1;

@Initialize {
SetLife(4000);
SetTimer(60);
SetScore(10000000);

SetEnemyMarker(true);

SetMovePosition01(GetCenterX, GetClipMinY + 60, 5);
CutIn(YOUMU, "Test Sign"\""Text"\", "", 0, 0, 0, 0);

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);
SetGraphicRect(0, 0, 64, 64);
}

@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(count == 120) {
SetMovePositionHermite(GetX, GetY, 2000, 135, 2000, 225, 240);
}

if(count == 480) {
SetMovePositionHermite(GetX, GetY, 2000, 45, 2000, 315, 240);
}

if(count >= 120 && count <= 360 || count >= 480 && count <= 720){
loop(1){
SetShotDirectionType(SEQUENCE);
CreateShot01(GetX, GetY, 1, 0, RED12, 30);
CreateShot01(GetX, GetY, 1, 0, RED31, 30);

a += 0;
}
a += 27;
}

if(count == 240 || count == 600){
loop(10){
CreateShot01(GetX, GetY, speed, GetAngleToPlayer, RED01, 30);
CreateShot01(GetX, GetY, speed, GetAngleToPlayer + 20, RED01, 30);
CreateShot01(GetX, GetY, speed, GetAngleToPlayer - 20, RED01, 30);
CreateShot01(GetX, GetY, speed, GetAngleToPlayer + 40, RED01, 30);
CreateShot01(GetX, GetY, speed, GetAngleToPlayer - 40, RED01, 30);
CreateShot01(GetX, GetY, speed, GetAngleToPlayer + 60, RED01, 30);
CreateShot01(GetX, GetY, speed, GetAngleToPlayer - 60, RED01, 30);

speed += 0.5;
}
speed = 1;
}

if(count == 720){
count = 0;
}


count++;
}

@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss);
}
}


I would expect, when the boss moves in a certain direction, they would be facing that angle. In this script, for example, no matter which direction the boss moves, their angle is always 0.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 15, 2009, 04:21:25 AM
What is the difference between GetX and GetX()?

is there a way to once a angle equals a certain...angle that it can switch?
im not sure if you can put an if statement in another if statement.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 15, 2009, 05:13:21 AM
What is the difference between GetX and GetX()?

is there a way to once a angle equals a certain...angle that it can switch?
im not sure if you can put an if statement in another if statement.

Surely, you can do so...

Code: [Select]
if(condition1){
   if(condition2){
    ...
   }
}
but then I would prefer this:
Code: [Select]
if(condition1 && condition2){ //the two happens at same time
   ...
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 15, 2009, 05:39:45 AM
Surely, you can do so...

Code: [Select]
if(condition1){
   if(condition2){
    ...
   }
}
but then I would prefer this:
Code: [Select]
if(condition1 && condition2){ //the two happens at same time
   ...
}

not quite what i ment, like:
 if(angle=>300){
    angle=30;

but then have it repeat its self
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on October 15, 2009, 10:31:51 AM
While() statements will loop until the condition is met. For example:

Code: [Select]
while(x >= 360){x -= 360;}
while(x < 0){x += 360;}

This code always makes x (probably an angle of some sort) between 0 and 360. Just be careful that there is no chance of it looping forever unless it's in a task and you're yielding.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on October 15, 2009, 11:03:18 AM
is there a way to input the value of pi in danmakufu? or should it just be 22/7, cause it's not the exact value of pi...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 15, 2009, 12:20:50 PM
define it yourself:

let pi=3.1415926535; (any longer would be wasting the resource, because the error is negligible)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: KomeijiKoishi on October 15, 2009, 01:00:32 PM
Code: [Select]
#TouhouDanmakufu
#Title[maxwell - "D-A-N-M-A-K-U"]
#Text[Maxwell gets out his notepad and summons danmaku by simply writing it.]
#ScriptVersion[1]

script_enemy_main {

    let D = "script\D.png";
    let A = "script\A.png";
    let N = "script\N.png";
    let M = "script\M.png";
    let K = "script\K.png";
    let U = "script\U.png";

    let count1=0;

    let life = 1600;

    let crap = 200;

    let time = 140;

    let l = 0;

    let reqmaxX = GetClipMaxX;
    let reqminX = GetClipMinY;
    let reqmaxY = GetClipMaxY;
    let reqminY = GetClipMinY;

    let kee = 0;

    @Initialize {
        SetLife(1600);
        SetDamageRate(10, 0);
        SetScore(210000);
        SetTimer(130);
        SetInvincibility( 200 );
        LoadGraphic(ImgBoss);
        LoadGraphic(D);
        LoadGraphic(A);
        LoadGraphic(N);
        LoadGraphic(M);
        LoadGraphic(K);
        LoadGraphic(U);
        CutIn(KOUMA, "Maxwell "\""D-A-N-M-A-K-U"\", "", 0, 0, 0, 0);
        LoadUserShotData("\script\extrabosses_mcxd\images\supershot.txt");

        SetMovePosition02(GetCenterX, GetClipMinY + 120, 120);
        SetGraphicRect(0, 0, 64, 64);
    }

    @MainLoop {
    if (!OnBomb) {
    SetCollisionA(GetX, GetY, 32);
    SetCollisionB(GetX, GetY, 16);
    }

    if (count1 == 150){
    kill;
    controller;
    }

    count1++;
    time = GetTimer;
    life = GetEnemyLife;
    yield;
    }

    @DrawLoop {
    if (!OnBomb) {
        SetGraphicAngle(0, 0, 0);
        SetGraphicRect(0, 0, 44, 50);
        SetGraphicScale(1, 1);
        }
    }

    @Finalize {
        DeleteGraphic(ImgBoss);
    }


    task controller(){
        loop{
        if (l == 0){
        if (life < 650){
        crap = 170;
        l++;
        }
        }
        if (l == 1){
        if (life < 500){
        crap = 140;
        l++;
        }
        }
        if (l == 2){
        if (life < 350){
        crap = 110;
        l++;
        }
        }
        if (time < 20){
        if (l != 20){
        l = 20;
        crap = 70;
        }
        }
        yield;
        }
    }

    task kill(){
        let x;
        let y;
        let a;
        loop{
        x = rand(GetClipMinX + 100, GetClipMaxX - 100);
        y = rand(GetClipMinY + 80, GetClipMinY + 160);
        ascent(a in 0..20){
        Slowbie((GetClipMaxX-GetClipMinX)*2/14, GetY, 3.5, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*2/14)+a*18, 240, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*2/14, GetY, 3, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*2/14)+9+a*18, 240, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*2/14, GetY, 2.5, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*2/14)+a*18, 240, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*2/14, GetY, 2, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*2/14)+9+a*18, 240, 50, 0);
        SetTexture(D);
        SetGraphicRect( 0, 0, 44, 50 );
        DrawGraphic(((GetClipMaxX-GetClipMinX)*2/14), GetClipMinX + 95);
        }
        if (GetLife<1400){
        ascent(a in 0..100){
        Slowbie((GetClipMaxX-GetClipMinX)*4/14, GetY, rand(1, 3), rand(0, 360), 46, 50, 0);
        SetTexture(A);
        DrawGraphic(((GetClipMaxX-GetClipMinX)*4/14), GetClipMinX + 95);
        SetGraphicRect( 0, 0, 44, 50 );
        }
}
        if (GetLife<1200){
        ascent(a in 0..85){
        Slowbie((GetClipMaxX-GetClipMinX)*6/14, GetY, 2.5, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*6/14)+180-a*2, 52, a, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*6/14, GetY, 2.5, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*6/14)+180+a*2, 52, a, 0);
        SetTexture(N);
        SetGraphicRect( 0, 0, 44, 50 );
        DrawGraphic(((GetClipMaxX-GetClipMinX)*6/14), GetClipMinX + 95);
        }
}
        if (GetLife<1000){
        ascent(a in 6..21){
        Slowbie((GetClipMaxX-GetClipMinX)*8/14, GetY, a/3, GetAngleToPlayer-30, 81, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*8/14, GetY, a/3, GetAngleToPlayer, 81, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*8/14, GetY, a/3, GetAngleToPlayer+30, 81, 50, 0);
        SetTexture(M);
        SetGraphicRect( 0, 0, 44, 50 );
        DrawGraphic(((GetClipMaxX-GetClipMinX)*8/14), GetClipMinX + 95);
        }
}
        if (GetLife<800){
        ascent(a in 0..20){
        Slowbie((GetClipMaxX-GetClipMinX)*10/14, GetY, 2, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*14/14)+a*18, 130, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*10/14, GetY, 2.1, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*14/14)-1+a*18, 130, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*10/14, GetY, 2.2, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*14/14)-2+a*18, 130, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*10/14, GetY, 2.3, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*14/14)-3+a*18, 130, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*10/14, GetY, 2.4, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*14/14)-4+a*18, 130, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*10/14, GetY, 2.5, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*14/14)-5+a*18, 130, 50, 0);
        Slowbie((GetClipMaxX-GetClipMinX)*10/14, GetY, 2.6, atan2(GetPlayerY - GetY, GetPlayerX - (GetClipMaxX-GetClipMinX)*14/14)-6+a*18, 130, 50, 0);
        SetTexture(A);
        SetGraphicRect( 0, 0, 44, 50 );
        DrawGraphic(((GetClipMaxX-GetClipMinX)*10/14), GetClipMinX + 95);
        }
}
        if (GetLife<600){
        ascent(a in 0..20){
        Home((GetClipMaxX-GetClipMinX)*12/14, GetY, 2, GetAngleToPlayer+a*18, 111, 50+a*4, a);
        SetTexture(K);
        SetGraphicRect( 0, 0, 44, 50 );
        DrawGraphic(((GetClipMaxX-GetClipMinX)*12/14), GetClipMinX + 95);
        }
}
        if (GetLife<400){
        ascent(a in 0..30){
        Slowbie((GetClipMaxX-GetClipMinX)*14/14, GetY, 2.5, GetAngleToPlayer+a*12, 59, 50, 4);
        Slowbie((GetClipMaxX-GetClipMinX)*14/14, GetY, 2.5, GetAngleToPlayer+a*12, 59, 50, -4);
        SetTexture(U);
        SetGraphicRect( 0, 0, 44, 50 );
        DrawGraphic(((GetClipMaxX-GetClipMinX)*14/14), GetClipMinX + 95);
        }

}
        _Wait(200);
        }
        }
       

    task Slowbie(x, y, v, angle, graphic, delay, let turn){
        let obj = Obj_Create(OBJ_SHOT);
        let bounce = 0;
        let i = 0;
        Obj_SetX(obj, x);
        Obj_SetY(obj, y);
        Obj_SetSpeed(obj, v);
        Obj_SetAngle(obj, angle);
        ObjShot_SetGraphic(obj, graphic);
        ObjShot_SetDelay(obj, delay);
        Obj_SetAutoDelete(obj, false);
        ObjShot_SetBombResist(obj, true);
          while (!Obj_BeDeleted(obj)){

          if (bounce == 0){
          if ((Obj_GetX(obj) > 420) || (Obj_GetX(obj) < 30)){
              Obj_SetAngle(obj, Obj_GetAngle(obj));
          bounce++;
          }
     if (Obj_GetY(obj) < 15){
          Obj_SetAngle(obj, Obj_GetAngle(obj));
          bounce++;
          }
          }

          if ((i > 10+delay) && (i < 70+delay)){
          Obj_SetAngle(obj, Obj_GetAngle(obj)+turn);
          }


          if ((i > 140+delay)){
          Obj_SetAutoDelete(obj, true);
          }

          i++;
          yield;
          }
     }


    task Home(x, y, v, angle, graphic, delay, let turn){
        let obj = Obj_Create(OBJ_SHOT);
        let bounce = 0;
        let i = 0;
        Obj_SetX(obj, x);
        Obj_SetY(obj, y);
        Obj_SetSpeed(obj, v);
        Obj_SetAngle(obj, angle);
        ObjShot_SetGraphic(obj, graphic);
        ObjShot_SetDelay(obj, delay);
        Obj_SetAutoDelete(obj, false);
        ObjShot_SetBombResist(obj, true);
          while (!Obj_BeDeleted(obj)){

          if (bounce == 0){
          if ((Obj_GetX(obj) > 420) || (Obj_GetX(obj) < 30)){
              Obj_SetAngle(obj, Obj_GetAngle(obj));
          bounce++;
          }
     if (Obj_GetY(obj) < 15){
          Obj_SetAngle(obj, Obj_GetAngle(obj));
          bounce++;
          }
          }


          if ((i == 40+delay)){
          Obj_SetAngle(obj, atan2(GetPlayerY - Obj_GetY(obj), GetPlayerX - Obj_GetX(obj)))
          }


          if ((i > 140)){
          Obj_SetAutoDelete(obj, true);
          }

          i++;
          yield;
          }
     }


    task YamaReflect(num, spe, turn, graph, delay){
         let offset=0;
         loop{
           ascent(i in 0..num){
               CreateShot01(GetX, GetY, spe, (360)/num*i+offset, graph, 10);
           }
         offset+=turn;
         loop(delay){yield;}
         PlaySE("script\extrabosses_mcxd\sound\Shot6.wav");
         }
    }
    task Permashot(x, y, v, angle, graphic, delay){
        let obj = Obj_Create(OBJ_SHOT);
        Obj_SetX(obj, x);
        Obj_SetY(obj, y);
        Obj_SetSpeed(obj, v);
        Obj_SetAngle(obj, angle);
        ObjShot_SetGraphic(obj, graphic);
        ObjShot_SetDelay(obj, delay);
   Obj_SetAutoDelete(obj, false);
        ObjShot_SetBombResist(obj, true);
          while (!Obj_BeDeleted(obj)){
          yield;
          }
     }

function _Wait( let frame ){
   loop( frame ){ yield; }
}

}
How can I draw all the letters on their destinated spots? Now they don't appear at all, but before I deleted certain parts of the code they all appeared on the D.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: 764asd on October 15, 2009, 02:46:04 PM
I Have a question to ask here. Whenever I Run some scripts ( and my own script made by following the tutorial provided by Helepolis) with Danmakufu, this error appears, as stated by Touhou Danmakufu Wiki:

"<script>内で「{...}」が対応していません"

Inside script is ' Script_enemy_main". Some of the scripts I Get could not run because of that. My friend tried and said that the same script he is using works, but mine does not. Any ideas on this...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 15, 2009, 03:10:10 PM
I Have a question to ask here. Whenever I Run some scripts ( and my own script made by following the tutorial provided by Helepolis) with Danmakufu, this error appears, as stated by Touhou Danmakufu Wiki:

"<script>内で「{...}」が対応していません"

Jesus Christ.
It means your braces are not in alignment. You're missing some {}.

@VideoGameCrack:

Didn't think you could put DrawGraphic outside of @DrawLoop and @BackGround. Try putting it all in the @DrawLoop, but provide conditional statements:

Code: [Select]
@DrawLoop{
   if(var==true){
      SetTexture(D);
      SetGraphicRect(blah, blah, blah, blah);
      DrawGraphic(x, y);
   }
   if(var2==true){
      SetTexture(A);
      SetGraphicRect(blah, blah, blah, blah);
      DrawGraphic(x, y);
   }
//etc.
}

And just set global variables to equal true whenever you want a graphic to appear.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: KomeijiKoishi on October 15, 2009, 03:56:00 PM


Thanks. Do you wanna have a LuNautic version of the script?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Lawence Codye on October 15, 2009, 05:38:45 PM
Thanks again Naut...& now...
okay...now I have two more questions...
1. this is my @DrawLoop for my player script...
Code: [Select]
@DrawLoop{
      SetTexture(img_reimu);
      if(GetKeyState(VK_LEFT)==KEY_PUSH || GetKeyState(VK_LEFT)==KEY_HOLD){
         SetGraphicRect(326, 85, 359, 131);
      }else if(GetKeyState(VK_RIGHT)==KEY_PUSH || GetKeyState(VK_RIGHT)==KEY_HOLD){
         SetGraphicRect(327, 153, 360, 199);
      }else{
         SetGraphicRect(326, 16, 360, 62);
      }
      DrawGraphic(GetPlayerX(), GetPlayerY());
   }
why I'm showing this is cause I need to find out how to animate my sprite...like some others have before me?
If you(whoever) need to see more of my code...say so & it's done...& also
2. Is there a way to have a player's options to do what they do in the image below when focused only...?

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 15, 2009, 06:36:07 PM
Thanks. Do you wanna have a LuNautic version of the script?

This should be the only question never asked in this thread. Of course, love.



@UltimaRepman:
1. Create a global variable:
let count = 0;
Increment it at the beginning of your @DrawLoop:
Code: [Select]
@DrawLoop{
   count++;
   //...
}
And make conditional statements using the incrementing variable to determine which image you will display for which button state:
Code: [Select]
@DrawLoop{
      count++;
      SetTexture(img_reimu);
      if(GetKeyState(VK_LEFT)==KEY_PUSH || GetKeyState(VK_LEFT)==KEY_HOLD){
         if(count%15>=0 && count%15<5){
             SetGraphicRect(326, 85, 359, 131);
         }
         if(count%15>=5 && count%15<10){
             SetGraphicRect(243, 85, 276, 131);
         }
         if(count%15>=10 && count%15<15){
             SetGraphicRect(278, 85, 311, 131);
         }
      }else if(GetKeyState(VK_RIGHT)==KEY_PUSH || GetKeyState(VK_RIGHT)==KEY_HOLD){
         if(count%15>=0 && count%15<5){
             SetGraphicRect(0, 85, 100, 131);
         }
         if(count%15>=5 && count%15<10){
             SetGraphicRect(200, 85, 300, 131);
         }
         if(count%15>=10 && count%15<15){
             SetGraphicRect(100, 85, 200, 131);
         }
      }else{
         if(count%15>=0 && count%15<5){
             SetGraphicRect(326, 0, 359, 45);
         }
         if(count%15>=5 && count%15<10){
             SetGraphicRect(243, 45, 276, 90);
         }
         if(count%15>=10 && count%15<15){
             SetGraphicRect(278, 90, 311, 135);
         }
      }
      DrawGraphic(GetPlayerX(), GetPlayerY());
   }
You can just copy/paste this code if you want, it works (provided you declare count), you'll need to replace all the GraphicRect's though.

2. If I'm seeing the image correctly... The options have disappeared? Can't remember ReimuC from MoF... If you're using ObjEffects:

ObjEffect_SetVertexColor(obj, [0-3], 0, 255, 255, 255); //repeat for all four vertices.

Notice the third parameter -- the alpha value. 0 alpha makes it transparent (disappear). You probably know where I'm going with this: If you're using the @DrawLoop, use SetAlpha(0);, though I wouldn't recommend using the @DrawLoop to draw options. I doubt you are anyway.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 16, 2009, 12:22:31 AM
ok right forum:
How do you replace the Background image in the danmakufu menus?
and the annoying Default Marisa and Reimu white colors?
You can add script sheets into /player.
Try looking for Reimu's and Marisa's sheets in CtC :)

Quote from: Naut
2. If I'm seeing the image correctly... The options have disappeared? Can't remember ReimuC from MoF... If you're using ObjEffects:
No... In fact they just hide behind (in front of???) our shrine maiden when one focuses.


Btw, you can actually add a Title.png to \img for the title image, but still the result is bad :(
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabble on October 17, 2009, 12:29:27 AM
Now that I have a weekend to devote to danmakufu - I have a question

What would I make a menu system with, and what difficulty would it be to make it?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Nuclear Cheese on October 17, 2009, 01:15:45 AM
Now that I have a weekend to devote to danmakufu - I have a question

What would I make a menu system with, and what difficulty would it be to make it?

The way I do menus is with a stage script, which draws menu options and tracks what's selected.  It's a bit of a pain in the ass, but it gets the job done decently.

You can see examples in my recent scripts here (http://www.shrinemaiden.org/forum/index.php?topic=216.0) - specifically, 「Bullet Curtain」 and Never Twice the Same Danmaku.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabble on October 17, 2009, 01:38:11 AM
The way I do menus is with a stage script, which draws menu options and tracks what's selected.  It's a bit of a pain in the ass, but it gets the job done decently.

You can see examples in my recent scripts here (http://www.shrinemaiden.org/forum/index.php?topic=216.0) - specifically, 「Bullet Curtain」 and Never Twice the Same Danmaku.
Just cover it up with images and it'd look like a menu?

Thanks. But oh my god that script scares me.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 17, 2009, 03:26:45 AM
Hm. I tried messing with backgrounds for the past couple of nights, and I hit a strange obstacle, so I thought I would make a question of it.

Why is it that even if you specify the boss image and the background image to @DrawLoop and @Background respectively, the background SetGraphicRect will apply to the boss image as well?

This does not happen normally if you have a set graphic for the boss in @DrawLoop, but it is a completely different story if you have a function of movement (in which their graphic changes while they move/are idle, like in CtC). The problem here is that, if I want this function on my boss, at certain points where the SetGraphicRect for the boss may not be defined properly (which seems to somehow be the case especially when they are idle, when I define a SetGraphicRect for GetSpeedX == 0 as their idle image. However, this seems to be random, with one boss image, it works fine when I define this, but with the other, it goes awry any way), it goes to the one for the background instead and puts in several images of the boss at once instead of the single desired image. This completely throws me off, since they are both defined in separate loops.

I know I am either very complex or just extremely confusing overall with this explanation, but if I wanted to provide examples, it would involve several different images you would most likely not have, and I am not uploading files anytime soon.

What should I do to fix the problem, keep my boss image rects constant while also having my background? Any tips, please?

If there is something I can make clearer in my explanation, I would like to know.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Azure Lazuline on October 17, 2009, 03:35:17 AM
All drawing functions stay as they are until re-defined, even in different loops. Call everything directly before the boss's drawing routine - you probably have SetGraphicRect after DrawGraphic.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 17, 2009, 03:50:40 AM
Either I am doing it incorrectly, or I am misunderstanding what you are meaning. Would you be able to give me an example?

Here is an example of what I am doing in my drawloop:

Code: [Select]
@DrawLoop{
SetTexture(yuyuback);
SetRenderState(ALPHA);
SetAlpha(fadein);
SetGraphicRect(0, 0, 256, 256);
SetGraphicScale(2.25,2.25);
DrawGraphic(GetCenterX, GetCenterY + bgscroll);

if(count%1 == 0){
if(fadein < 253){
fadein += 2;
}
}



SetTexture(yuyuback2);
SetRenderState(ALPHA);
SetAlpha(255);
SetGraphicRect(0, 0, 256, 256);
SetGraphicScale(2.25,2.25);
DrawGraphic(GetCenterX, GetCenterY);

bgscroll += 2;
if(bgscroll > 510){
bgscroll = 0;
}



SetTexture(ImgBoss);
SetRenderState(ALPHA);
SetAlpha(255);
SetGraphicScale(1,1);
SetGraphicAngle(0,0,0);
setGraphicMove;
DrawGraphic(GetX, GetY);
}

Imgboss is self-explanatory, yuyuback is Yuyuko's background. fadein and bgscroll are trivial matters right now.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 17, 2009, 03:59:21 AM
Every function that has "Set" in it's name1 needs only be called once for it to continue running.
I bold so other people get this message as well, since it is important.
1The only exception to this is rule the function SetFog (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Stage_Script_Functions#SetFog).


So since you "set" the graphic rectangular region to be (0, 0, 256, 256), all images that use that function to determine the graphic rect will use those coordinates until specified otherwise, continuing on to other frames if need be. You do not declare a new graphic rect for the boss, so Danmakufu will use the last one you set, which in this case is your background's.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabble on October 17, 2009, 04:00:46 AM
Whenever I start up this spellcard, nothing happens and then it ends, acting like I won.

Probably a newbie mistake but oh well  :V

Code: [Select]
#TouhouDanmakufu
#Title[IkuSpell1]
#Text[Water Sign "Electrically Charged Current"]
#Player[FREE]
#ScriptVersion[0.01]
script_enemy_main {

let ImgBoss = "\script\MyStuff\MyImg\Game\IkuBoss.png";//Boss Sprite Sheet
let cut = "\img\CutIn_PlayerChar01.png";//Cut In

LoadGraphic(ImgBoss)//Boss Loading

//include functions here
#include_function "script\MyStuff\MyFunctions\MCircle.txt";
#include_function "lib\SHOT_REPLACE\shot_replace.dnh";

//include variables here
let angle = 0;

@Initialize {
SetLife(1900);
SetTime(99);
shotinit;
CutIn(KOUMA, "Dragon Fish"\ ""Dragon Temple of Swimming Bullets"\", cut, 0, 0, 251, 284);
SetMovePosition02(GetCenterX, GetCenterY-100, 120);
Main();
}
@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);
yield;
}
@DrawLoop {
Circle;

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);

SetAlpha(255);
SetGraphicScale(1,1);
SetGraphicAngle(0, 0, 0);

SetGraphicRect(0,0,57,72);

if (GetSpeedX()==0){SetGraphicRect(0,0,57,72);;}

else if(GetSpeedX()>0){SetGraphicRect(0,72,48,136);}

else if(GetSpeedX()<0){SetGraphicRect(0,136,48,199);}

DrawGraphic(GetX, GetY);

let BossName="Iku Nagae";
DrawText(BossName, 36, 39, 12, 225);
}
@Finalize {
DeleteGraphic(ImgBoss);
PlaySE("script\MyStuff\MySE\nonfinish.wav");
}
Task Main(){
yield;

loop(240);

loop{
Shot();
loop(360)
SetMovePositionRandom01(60,rand(0,0),3,GetCenterX-100,60,GetCenterX+100,130);
}
}
Task Shot(){
loop(120){
PlaySE("script\Mystuff\MySE\shot1.wav");
CreateShotA(1,GetX-50*cos(angle),GetY-50*sin(angle),10);
SetShotDataA(1,0,4,angle+rand(-3,3),2,-0.04,0,BLUE01);
SetShotDataA(1,80,0,angle,0,0.05,5,BLUE01);
CreateShotA(2,GetX-50*cos(angle-180),GetY-50*sin(angle-180),10);
SetShotDataA(2,0,3,angle-180+rand(-3,3),2,-0.04,0,BLUE01);
SetShotDataA(2,80,0,angle-180,0,0.05,3,YELLOW01);
  FireShot(1);
FireShot(2);

angle += 4;
loop(0.1)
}
}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 17, 2009, 04:05:14 AM
Bottom of your script... "loop(0.1)"? Doesn't have opening braces associated with it (you can actually pass decimals in a loop function, that's not the problem). If that doesn't fix it, I'd need those #include_functions to get any farther with the script.

EDIT: Shit shit shit. Few more things. Your #ScriptVersion is 0.01.... Should be 2 (this is what's causing the script to just end). Next you'll get an error on "LoadGraphic", just put the semi-colon after it. Also, put the LoadGraphic in @Initialize. Also also, not an error, but in your @DrawLoop you let BossName = "Iku Nagae"; then immediately use BossName for your DrawText... Why not just have:
Code: [Select]
DrawText("Iku Nagae", 36, 39, 12, 225);

Means the same thing. Just sort of a needless declaration, I guess.
And one last thing, in your task Shot you loop the sound effect along with the bullets. This is completely needless and will cause a fps spike. Take the PlaySE out of the loop and put it either after or before you fire the bullets. You only ever need to play a shot sound once in a frame, any more and it's wasting resources.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 17, 2009, 04:14:48 AM
Every function that has "Set" in it's name1 needs only be called once for it to continue running.
I bold so other people get this message as well, since it is important.
1The only exception to this is rule the function SetFog (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Stage_Script_Functions#SetFog).


So since you "set" the graphic rectangular region to be (0, 0, 256, 256), all images that use that function to determine the graphic rect will use those coordinates until specified otherwise, continuing on to other frames if need be. You do not declare a new graphic rect for the boss, so Danmakufu will use the last one you set, which in this case is your background's.

Okay. But that seems rather strange. If that is the case, then both the boss image and the background would appear 256 by 256 pixels. This does not make much sense to me, if I wanted my boss image to appear naturally. How would I resolve this, then?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 17, 2009, 04:20:13 AM
Find the coordinates of your boss image and declare it before drawing the image. It's not as strange as you think, the "Set" part of a function is very useful with other things, like object shots for example.

The reason why you still have to do this even if you want the whole image to appear is because you can keep repeating the image over and over again by selecting a graphic rect larger than the actual image. Think of it as "tiling your background". When you set your desktop background as tiled, then the image keeps repeating itself. That's what happens when you declare out of bounds coordinates.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabble on October 17, 2009, 04:23:07 AM
Bottom of your script... "loop(0.1)"? Doesn't have opening braces associated with it (you can actually pass decimals in a loop function, that's not the problem). If that doesn't fix it, I'd need those #include_functions to get any farther with the script.

EDIT: Shit shit shit. Few more things. Your #ScriptVersion is 0.01.... Should be 2 (this is what's causing the script to just end). Next you'll get an error on "LoadGraphic", just put the semi-colon after it. Also, put the LoadGraphic in @Initialize. Also also, not an error, but in your @DrawLoop you let BossName = "Iku Nagae"; then immediately use BossName for your DrawText... Why not just have:
Code: [Select]
DrawText("Iku Nagae", 36, 39, 12, 225);

Means the same thing. Just sort of a needless declaration, I guess.
And one last thing, in your task Shot you loop the sound effect along with the bullets. This is completely needless and will cause a fps spike. Take the PlaySE out of the loop and put it either after or before you fire the bullets. You only ever need to play a shot sound once in a frame, any more and it's wasting resources.

It still has the same problem after fixing it.

Code: [Select]
#TouhouDanmakufu
#Title[IkuSpell1]
#Text[Water Sign "Electrically Charged Current"]
#Player[FREE]
#ScriptVersion[2]
script_enemy_main {

let ImgBoss = "\script\MyStuff\MyImg\Game\IkuBoss.png";
let cut = "\img\CutIn_PlayerChar01.png";

LoadGraphic(ImgBoss);

//include functions here
#include_function "script\MyStuff\MyFunctions\MCircle.txt";
#include_function "lib\SHOT_REPLACE\shot_replace.dnh";

//include variables here
let angle = 0;

@Initialize {
SetLife(1900);
SetTime(99);
shotinit;
CutIn(KOUMA, "Dragon Fish"\ ""Dragon Temple of Swimming Bullets"\", cut, 0, 0, 251, 284);
SetMovePosition02(GetCenterX, GetCenterY-100, 120);
Main();
}
@MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);
yield;
}
@DrawLoop {
Circle;

LoadGraphic(ImgBoss);
SetTexture(ImgBoss);

SetAlpha(255);
SetGraphicScale(1,1);
SetGraphicAngle(0, 0, 0);

SetGraphicRect(0,0,57,72);

if (GetSpeedX()==0){SetGraphicRect(0,0,57,72);;}

else if(GetSpeedX()>0){SetGraphicRect(0,72,48,136);}

else if(GetSpeedX()<0){SetGraphicRect(0,136,48,199);}

DrawGraphic(GetX, GetY);

DrawText(IkuNagae, 36, 39, 12, 225);
}
@Finalize {
DeleteGraphic(ImgBoss);
PlaySE("script\MyStuff\MySE\nonfinish.wav");
}
Task Main(){
yield;

loop(240){yield};

loop{
Shot();
loop(360){yield};
SetMovePositionRandom01(60,rand(0,0),3,GetCenterX-100,60,GetCenterX+100,130);
}
}
Task Shot(){
PlaySE("script\Mystuff\MySE\shot1.wav");
loop(120){

CreateShotA(1,GetX-50*cos(angle),GetY-50*sin(angle),10);
SetShotDataA(1,0,4,angle+rand(-3,3),2,-0.04,0,BLUE01);
SetShotDataA(1,80,0,angle,0,0.05,5,BLUE01);
CreateShotA(2,GetX-50*cos(angle-180),GetY-50*sin(angle-180),10);
SetShotDataA(2,0,3,angle-180+rand(-3,3),2,-0.04,0,BLUE01);
SetShotDataA(2,80,0,angle-180,0,0.05,3,YELLOW01);
  FireShot(1);
FireShot(2);

angle += 4;
loop(1){yield}
}
}
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 17, 2009, 04:29:54 AM
SetTimer(99);, I'm running out of things to look for now!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 17, 2009, 04:31:05 AM
Find the coordinates of your boss image and declare it before drawing the image. It's not as strange as you think, the "Set" part of a function is very useful with other things, like object shots for example.

The reason why you still have to do this even if you want the whole image to appear is because you can keep repeating the image over and over again by selecting a graphic rect larger than the actual image. Think of it as "tiling your background". When you set your desktop background as tiled, then the image keeps repeating itself. That's what happens when you declare out of bounds coordinates.

I believe I am very confused by the syntax itself.

What do you mean by coordinates? How would I select these specific coordinates for the boss image?

Can I ask you to provide an example? (I apologize, I am not one who is quick to learn things without very specific details and directions. Visual aid is handy for me, despite how much I want to be able to learn how to fix the problem on my own, this is a situation I find difficult without assistance. I am also an amateur at coding.)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabble on October 17, 2009, 04:36:10 AM
SetTimer(99);, I'm running out of things to look for now!
Still not it.

:((((
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 17, 2009, 04:43:15 AM
@Frazer:
You've not read Nuclear Cheese's Drawing Tutorial (http://touhou.wikia.com/wiki/Touhou_Danmakufu:_Nuclear_Cheese%27s_Drawing_Tutorial)? I'm sure he does this topic justice better than I'm about to.

SetGraphicRect determines the rectangular region of the graphic (or texture, SetTexture) you want to be displayed. It's parameters are:
SetGraphicRect(the left bound region of the rectangle, the top boundry, the right boundry and the bottom boundry).

So for an image that looks like this:

(http://i641.photobucket.com/albums/uu134/Nautth/example.jpg)

The GraphicRect would be:
SetGraphicRect(35, 28, 134, 131);


@Shikieiki Ya- Yama- CHEN:
Still looking through it... Give me a minute.
Semi-colon after your loop(1){yield} statement at the bottom of the script, put Iku Nagae in quotation marks in your DrawText function, delete the second semi-colon after your second declaration of SetGraphicRect, de-capitalize the word task for all of your tasks, rename your Main() task to something else (I don't feel comfortable with it named such, probably not a problem though), you can put the PlaySE back inside that loop in the bottom since you're yield;-ing. The only thing here that may actually fix your problem is the "Task" thing, but even that I doubt. This is just stuff you will run in to later anyways, so you might as well fix it. If none of this works, hopefully somebody else can answer this problem for you, I gotta go to bed. Sorry.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 17, 2009, 04:54:35 AM
I just took a look through the tutorial (did not think about it before, I might have skimmed through it once before, though).

I know what SetGraphicRect's function is. That is not what I am trying to figure out, though.

In any case, I might have found a possible solution for my problem. I am sorry to have been confusing. Thank you very much.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 17, 2009, 05:00:21 AM
Ah, I must have misunderstood your question, my apologies.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabble on October 17, 2009, 01:47:33 PM
@Shikieiki Ya- Yama- CHEN:
Still looking through it... Give me a minute.
Semi-colon after your loop(1){yield} statement at the bottom of the script, put Iku Nagae in quotation marks in your DrawText function, delete the second semi-colon after your second declaration of SetGraphicRect, de-capitalize the word task for all of your tasks, rename your Main() task to something else (I don't feel comfortable with it named such, probably not a problem though), you can put the PlaySE back inside that loop in the bottom since you're yield;-ing. The only thing here that may actually fix your problem is the "Task" thing, but even that I doubt. This is just stuff you will run in to later anyways, so you might as well fix it. If none of this works, hopefully somebody else can answer this problem for you, I gotta go to bed. Sorry.

Oh thank you. It works!

First Spellcard: Done
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 17, 2009, 07:59:36 PM
Okay, I have yet another irritating dilemma.

I am trying to create a regular enemy script (inside of a spellcard). To my dismay, the first enemy script I tried worked, but this one has an enigmatic error.


This is the one I am trying to work on that is failing:
Code: [Select]
script_enemy redfairy
{
let rf = "script\Remilia spell cards\img\enemy.png";
let count2 = 0;


#include_script "script\Remilia spell cards\Movement for red fairy.txt";
 
@Initialize
{
  SetLife(2000);
  SetDamageRateEx(0,0,50,50);

  LoadGraphic(rf);
  SetTexture(rf);
  SetGraphicRect(0, 0, 64, 80);
  }

@MainLoop
{
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

 if(count2 == 250){
  SetMovePosition02(GetClipMaxX + 50, GetClipMinY + rand_int(20, 200), 30);
  }

count2++;

setgraphicmoverf;
}



@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(rf);
}
}


This is the first enemy script I had ever tried using (it worked pefectly in the spellcard I used it in):
Code: [Select]
script_enemy Remilia2
{
let ImgBoss2 = "script\Remilia spell cards\img\Remilia Boss 2.png";
let count2 = 0;


#include_script "script\Remilia spell cards\Movement for Remilia 2.txt";
 
@Initialize
{
  SetLife(2000);
  SetDamageRateEx(0,0,50,50);

  LoadGraphic(ImgBoss2);
  SetTexture(ImgBoss2);
  SetGraphicRect(0, 0, 64, 80);
  }

@MainLoop
{
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

 if(count2 == 250){
  SetMovePosition02(GetClipMaxX + 50, GetClipMinY + rand_int(20, 200), 30);
  }

 if(count2 == 290){
  SetMovePosition02(GetClipMaxX + 50, GetClipMinY + rand_int(20, 200), 1);
  }

 if(count2 == 300){
  SetMovePosition03(GetCenterX + 50, GetClipMinY + 150, 20, 5);
  }
 
 
 if(count2 == 480){
  SetMovePosition02(GetClipMinX + 50, GetClipMinY + 50, 30);
  }

 if(count2 == 540){
  SetMovePosition02(GetClipMaxX - 50, GetClipMaxY - 50, 60);
  }

 if(count2 == 600){
  SetMovePosition02(GetClipMinX + 50, GetClipMaxY - 50, 60);
  }

 if(count2 == 840){
  SetMovePosition02(GetClipMaxX - 50, GetClipMinY + 50, 60);
  }

 if(count2 == 900){
  SetMovePosition02(GetClipMinX + 50, GetClipMinY + 50, 60);
  }

 if(count2 == 1050){
  count2 = 450;
  }

loop(7){
 shoot(count2, 540, 600, rand_int(45, -135), RED12);
 shoot(count2, 600, 660, rand_int(0, 180), RED12);
 shoot(count2, 840, 900, rand_int(-45, 135), RED12);
 shoot(count2, 900, 960, rand_int(180, 360), RED12);
 }

count2++;

setGraphicMove2;
}



@DrawLoop {
DrawGraphic(GetX, GetY);
}

@Finalize {
DeleteGraphic(ImgBoss2);
}


task shoot(c, n, n2, a, g)
{
if(c >= n && c <= n2){
CreateShot01(GetX, GetY, 2, a, g, 5);
}
}


}


The error I get with the first script is the one that you would normally get when you do not have enough closing brackets in your script [script(redfairy){...}]. This makes no sense whatsoever because there is the sufficient amount of both open and closed brackets in the script, if you look it over carefully. So why would I be getting this error?

And when I DO put one more closing bracket at the end of the script, I get this error:

(http://fc04.deviantart.com/fs51/i/2009/290/2/e/scaaaaaa_by_Ilynine.png)

What does this mean?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on October 17, 2009, 08:06:24 PM
What does setgraphicmoverf; do?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 17, 2009, 08:12:51 PM
I put in setgraphicmoverf as the graphic change for the red fairy's movement (included in a different script, as you can see in the script).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on October 17, 2009, 08:19:58 PM
You should check the included function for bracket errors as well.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Frazer on October 17, 2009, 08:28:21 PM
Ah, I did not think about that before.

Okay, I added the necessary bracket to the function script file and fixed the problem.

Thank you.


I have another question concerning enemies, then: The last time I asked about enemies, the problem I had was Danmakufu crashing due to deleting the same enemy graphic twice. Is it possible to use the same graphic file for two different enemies/the same enemy while being able to summon the same enemy more than once/both enemies and being able to prevent Danmakufu from crashing when they are killed? (Think of stages: multiples of the same enemy in different variations appear, but they are most likely to use the same image file, yet even after you kill them, you can continue the game.)

EDIT: Is the "DeleteGraphic" function necessary to an enemy file? (I ask because after deleting that line in an enemy file and an enemy is killed, Danmakufu continues and the enemy disappears.)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: CK Crash on October 17, 2009, 08:52:29 PM
If the enemy is a familiar for a boss, you may as well delete it's graphic in the boss's @Finalize instead. You don't always need to delete the graphics immediately, just as soon as you're sure it won't be used again.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Kylesky on October 18, 2009, 08:09:22 AM
I have a problem... I only started trying 3D recently, so I don't know much yet... (I already looked at Nuclear Cheese's drawing tutorial)

ok now... why is this only showing a black screen?
but when I take out the fog, it shows everything normally, so I'm thinking something's wrong with how I made the fog...

Code: [Select]
@BackGround
   {
      WriteZBuffer(true);
      UseZBuffer(true);

      SetViewTo(-distance2, 10, -distance2/3.5-50-(distance2/12.5));
      SetViewFrom(600, 10, 30);

      SetFog(400, 600, 0, 0, 0);

SetTexture(imagefileb);
SetGraphicRect(0, 0, 50000, 50000);
SetGraphicScale(2, 2);
SetGraphicAngle(90, 70, 0);
DrawGraphic3D(0, -200, 0);

SetTexture(imagefilec);
SetGraphicRect(0, 0, 257, 50000);
SetGraphicScale(1.5, 1.5);
SetGraphicAngle(0, 160, 90);
DrawGraphic3D(-200, 0, 100);

SetTexture(imagefilec);
SetGraphicRect(0, 0, 257, 50000);
SetGraphicScale(1.5, 1.5);
SetGraphicAngle(0, 340, 90);
DrawGraphic3D(-200, 0, -400);

      SetAlpha(255);
      SetTexture(imagefile);
      SetGraphicRect(0, 0, 173, 303);
      SetGraphicScale(0.5, 0.5);
ascent(i in 1..37)
{
      SetGraphicAngle(rotation, rotation+i*10, 180);
      DrawGraphic3D(-distance2-100-(50*cos(rotation2)), -30, -distance2/3.5-(100*sin(rotation2))-(distance2/12.5)-75);
}
   }
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 18, 2009, 06:41:20 PM
Extremely large polygons break under fog, usually by tinting the whole polygon with the fog (in your case, pure black), so it won't work with your 50000x50000 textures. Around 3000 seems to be where it starts acting up.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 18, 2009, 07:07:12 PM
Extremely large polygons break under fog, usually by tinting the whole polygon with the fog (in your case, pure black), so it won't work with your 50000x50000 textures. Around 3000 seems to be where it starts acting up.

Confirming this as I had the same problem. I had large bits of 3D stage like 2048+. When fog kicks in, it all looks bad and clipping like crazy between the fog and stage parts. I stay myself below 1024 for complex areas and 2048 straight boxed areas shouldn't be a problem.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Cabble on October 18, 2009, 11:32:39 PM
Here I am with another problem. It gives me an error whenever I play the stage.

Enemy1.txt
Code: [Select]
script_enemy_main{
let angle = 0;
@Initialize{
SetLife(100);
}
@MainLoop{
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);
loop(60){
CreateShot01(GetX, GetY, 2, angle, BLUE01, 0);
angle += 360/60;
}
}
@DrawLoop(
}
@Finalize{
}
}

Stage1.txt
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~"Enemy1.txt", GetCenterX, GetCenterY, 0, 0, 0);
  CreateEnemyFromFile(GetCurrentScriptDirectory~"Enemy1.txt", GetCenterX, GetCenterY, 0, 0, 0);
  WaitForZeroEnemy;
  Wait(60);
  Clear;
 }

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

  }
  @Finalize{

  }
}

Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 19, 2009, 12:29:05 AM
DrawLoop in Enemy1.txt has a parentheses instead of a brace.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 19, 2009, 02:02:31 AM
I cant seem to get the right angle to get the bullets to move  in a uniform circle around the point of origin. What is the number i need to make to make bullets move around the Point of Origin?
i need help finding teh numbers for:
Code: [Select]
CreateShotA(1, GetX, GetY+30, 0);
SetShotDataA(1, 0, 0, 0, 0, 0, 0, BLUE01);
SetShotDataA(1, 30, 2, 90, 3.14, 0, 0, BLUE01);
FireShot(1);

CreateShotA(2, GetX, GetY+60, 0);
SetShotDataA(2, 0, 0, 0, 0, 0, 0, RED01);
SetShotDataA(2, 30, 2, 90, 3.14, 0, 0, RED01);
FireShot(2);

CreateShotA(3, GetX, GetY+90, 0);
SetShotDataA(3, 0, 0, 0, 0, 0, 0, YELLOW01);
SetShotDataA(3, 30, 2, 90, 3.14, 0, 0, YELLOW01);
FireShot(3);

CreateShotA(4, GetX, GetY+120, 0);
SetShotDataA(4, 0, 0, 0, 0, 0, 0, GREEN01);
SetShotDataA(4, 30, 2, 90, 3.14, 0, 0, GREEN01);}
FireShot(4);

I've tried a lot of numbers, any ideas?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Suikama on October 19, 2009, 02:40:33 AM
Read the tutorials. There's a section on sin and cos, which you'll need for any sort of circular danmaku.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 19, 2009, 02:50:39 AM
I bet he is referring to uniform circular motion with change in angle...

For that you may try to consider this:

Let the velocity (constant) of the bullet be 'v', angular velocity be 'a' and the radius of circle be 'r'.

Time for it to move 1 cycle: 2*3.14*r/v
Time for the bullet to turn 360 degree: 360/a

So the two are equal, and you can get useful formulae for this kind of motion.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Janitor Morgan on October 19, 2009, 03:00:01 AM
Hello, Danmakufu newb here. After going through some of the basic tutorials (and working out a somewhat hilarious laser glitch) in a test script, I thought I would slowly expand my horizons by recreating some of the Stage 1 and Stage 2 spellcards. My first victim project: Cirno's Diamond Blizzard (Normal).

However, I'm not quite sure where to go from here. I've got it set up to where all of the bullets spawn from the boss sprite, but obviously it doesn't work that way in Embodiment of Scarlet Devil. Do I need to read up on familiars or object shots that might spawn the other bullets, or is there something else I'm missing?

Source code here, with BGM and spellcard backdrop commented out.
Code: [Select]
#TouhouDanmakufu
#Title[Snow Sign "Diamond Blizzard"]
#Text[My first attempt at recreating a card.]
#BackGround[IceMountain]
//#BGM[.\bgm\th06_05.wav]
#Player[REIMU, MARISA, player\Rumia\Rumia.txt]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\img\ExRumia.png";
//let imgSpellBackdrop=GetCurrentScriptDirectory~"img\icewall.png";
let frame = -120;

    @Initialize {
SetScore(50000);
SetLife(240);
SetDamageRate(10,10);
SetTimer(60);
SetInvincibility(30);

SetGraphicRect(1, 1, 64, 64);
LoadGraphic(ImgBoss);
//LoadGraphic(imgSpellBackdrop);

SetMovePosition02(GetCenterX, GetClipMinY + 120, 120);
CutIn(KOUMA, "Snow Sign "\""Diamond Blizzard"\", 0, 0, 0, 0, 0);
    }

    @MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(frame == 10) {
loop(5) {
CreateShot01(GetX, GetY, rand(1, 2.5), rand(0, 359), AQUA23, 20);
    }
frame = 0;
}
frame++;
    }

    @Finalize {
DeleteGraphic(ImgBoss);
//DeleteGraphic(imgSpellBackdrop);
    }

    @DrawLoop {
SetAlpha(255);
SetTexture(ImgBoss);
SetGraphicRect(1,1,64,64);
DrawGraphic(GetX(),GetY());
    }

//    @BackGround {
// SetAlpha(150);
// SetTexture(imgSpellBackdrop);
// SetGraphicRect(0,0,384,448);
// DrawGraphic(GetCenterX,GetCenterY);
//    }
}
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 19, 2009, 03:05:13 AM
I bet he is referring to uniform circular motion with change in angle...

For that you may try to consider this:

Let the velocity (constant) of the bullet be 'v', angular velocity be 'a' and the radius of circle be 'r'.

Time for it to move 1 cycle: 2*3.14*r/v
Time for the bullet to turn 360 degree: 360/a

So the two are equal, and you can get useful formulae for this kind of motion.

I think i understand what you are saying to an Extent... I tried what i think you said and tried this:

   
Code: [Select]
CreateShotA(1, GetX, GetY+30, 0);
SetShotDataA(1, 0, 0, 0, 0, 0, 0, BLUE01);
SetShotDataA(1, 30, 2, 90, 2*3.14*360/2, 0, 0, BLUE01);
FireShot(1);

but it failed
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 19, 2009, 03:12:31 AM
The problem is your initial angle and you did the maths wrongly:

The initial angle should be the angle of the tangent to the circle.

and,
since 2*3.14*r/v=360/a,

a=360*v/(2*3.14*r)

Code: [Select]
CreateShotA(1, GetX, GetY+30, 0);
SetShotDataA(1, 0, 0, 0, 0, 0, 0, BLUE01);
SetShotDataA(1, 30, 2, 180, 360*2/(2*3.14*30), 0, 0, BLUE01);
FireShot(1);
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Demonbman on October 19, 2009, 03:32:39 AM
The problem is your initial angle and you did the maths wrongly:

The initial angle should be the angle of the tangent to the circle.

and,
since 2*3.14*r/v=360/a,

a=360*v/(2*3.14*r)

Code: [Select]
CreateShotA(1, GetX, GetY+30, 0);
SetShotDataA(1, 0, 0, 0, 0, 0, 0, BLUE01);
SetShotDataA(1, 30, 2, 180, 360*2/(2*3.14*30), 0, 0, BLUE01);
FireShot(1);

thanks henry! even tho im in Geometry i still couldnt figure that out...thanks again!!!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Henry on October 19, 2009, 03:48:05 AM
You're welcomed to attend Cirno's Perfect Maths Classroom
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Sakura665 on October 19, 2009, 10:22:41 AM
Ok i got a lot of questions, but for now imma start with the one's that's been bothering me for a while.

I've been trying to make bullets appear around the spot you were at at the time they spawned and they spin in relation to that same spot, the final objective is to make them spin inwards towards the spot and leave trails of bullets on the way (like on Orin's card: Malicious Spirit "Spleen Eater", except here the bullets stay and never move), but i cant even make them keep spinning over that same spot, let alone make them spin inwards.

First i tried by making them detect the angle to the player (-90 or +90) and rotate, it's good... until the player moves.

Second i stored the angle towards the player in the task that spawned the bullets in another array, so for every bullet i get the angle stored, and do (-90 or +90) the bullets rotate but seem to spin outwards which is the total opposite of what i wanted.

Third i stored the player's coordinates at the time, on 2 different arrays (one for X and one for Y) and just used atan2 everytime they were moving, but i got the same result as on the second try.

Fourth i returned to the angle and removed the (+90 or -90) to check if the bullets were really aiming at the player position, and i found out they were indeed aiming at the player position, so i was running out of options.

Fifth i changed the angle modifier to (+10 or -10) and now noticed the bullets spinned inwards but  leave like a small hole in the center of idk what radious (maybe 10) and spin around it then spin outward... this is what i wanted... except i need them to converge in the very center not spin around it.

Since i ran out of options, i decided to go with this result and add some extra stuff to the spellcard and made the fairies spawn bullets instead, plus some extra stuff to make it harder, the ocassional bullets going around you were forcing you to stop for a second unless you were able enough to squeeze through their gaps, but i still want to know how to make the things to converge on the spot.

Here's the current code:
Code: [Select]
#TouhouDanmakufu
#Title[Orin Spell 1]
#Text[Orin's First SpellCard]
#BGM[.\system\OrinTheme.mp3]
#PlayLevel[Extra]
#player[FREE]
#ScriptVersion[2]
script_enemy_main{
let CSD = GetCurrentScriptDirectory;
let FairyZ = CSD ~ "FairyZ01.txt";
let imgBoss = CSD ~ "system\Orin.png";
let SpellCircle = CSD ~"system\SpellCircle.png";
let cut = CSD ~ "system\orincut.png";
let bg = CSD ~ "system\OrinBGa.png";
let bg2 = CSD ~ "system\OrinBGb.png";

let shotSE = CSD ~ "system\shotSE.wav";
let chargeSE = CSD ~ "system\charging.wav";
let TO1 = CSD ~ "system\se_timeout.wav";
let TO2 = CSD ~ "system\se_timeout2.wav";

let frame = 0;
let frame2 = 0;
let frame3 = 0;
let frame4 = 0;
let angle = 0;
let angle2 = 360/6;
let angleTilt = 0;
let Circle = 0;
let PlayerAngle = [];
let DrawAngle = 0;
let radious = 0;
let bullets = [];
let spiral = [];
let spawned = false;
@Initialize{
SetLife(1500);
SetTimer(25);
SetScore(1000000);
SetDamageRate(70,70);
SetInvincibility(120);
// Expert;

LoadGraphic(imgBoss);
LoadGraphic(cut);
LoadGraphic(bg);
LoadGraphic(bg2);
LoadGraphic(SpellCircle);
LoadSE(shotSE);
LoadSE(chargeSE);
LoadSE(TO1);
LoadSE(TO2);

SetMovePosition02(100,GetCenterY-100,120);
CutIn(YOUMU,"Wheel of Hell ~ Zombie Fairies",cut,0,0,402,512);
}
@MainLoop{
SetCollisionA(GetX,GetY,30);
SetCollisionB(GetX,GetY,18);
frame++;
frame2++;
frame3++;
DrawAngle++;
if(frame==180){
SummonCircle(GetPlayerX,GetPlayerY);
frame=60;
}
if(frame2==120){
SetMovePosition02(GetPlayerX,GetCenterY-100,120);
if(spawned==false){
loop(10){
CreateEnemyFromFile(FairyZ,GetX,GetY,3,angle2,0);
angle2+=360/10;
}
spawned=true;
}
frame2=0;
}
if(frame3==120){
loop(2){
CreateShot01(GetX,GetY,5+rand(-3,3),0+angleTilt+rand(-3,3),GREEN01,2);
CreateShot01(GetX,GetY,5+rand(-3,3),180+angleTilt+rand(-3,3),GREEN01,2);
}
angleTilt++;
frame3=118;
}
let i = 0;
while(i<length(bullets)){
if(Obj_BeDeleted(bullets[i])){
bullets = erase(bullets,i);
PlayerAngle = erase(PlayerAngle,i);
i--;
}else{
let obj = bullets[i];
Obj_SetSpeed(obj,5);
Obj_SetAngle(obj,PlayerAngle[i]-10);

}
i++;
yield;
}
yield;
if(GetTimer>4&&GetTimer<=10&&frame%60==0){
PlaySE(TO1);
// wait(60);
}
if(GetTimer<=4&&frame%60==0){
PlaySE(TO2);
// wait(60);
}
}
task SummonCircle(x,y){
loop(8){

let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj,x+100*cos(angle),y+100*sin(angle));
PlayerAngle = PlayerAngle ~ [atan2(y-Obj_GetY(obj),x-Obj_GetX(obj))];
Obj_SetSpeed(obj,0);
Obj_SetAngle(obj,0);
ObjShot_SetDelay(obj,5);
ObjShot_SetGraphic(obj, RED04);
ObjShot_SetBombResist(obj, true);

bullets = bullets ~ [obj];

angle+=360/8;
}
yield;
}
task ShootSpiral{

}
@DrawLoop{
frame4++;
if(frame4<=60){
Circle+=1/60;
}
if(frame4>60 && frame4<=120){
Circle-=1/60;
}
if(frame4>120){
frame4=0;
}
DrawText("Rin Kaenbyou", 36, 39, 12, 225);
SetTexture(imgBoss);
SetColor(255,255,255);
SetRenderState(ALPHA);
SetAlpha(255);
SetGraphicRect(0,0,62,64);
SetGraphicScale(1,1);
SetGraphicAngle(0,0,0);
DrawGraphic(GetX,GetY);

SetTexture(SpellCircle);
SetColor(255,255,255);
SetRenderState(ALPHA);
SetAlpha(60);
SetGraphicRect(0,0,126,125);
SetGraphicScale(Circle+1,Circle+1);
SetGraphicAngle(0,0,DrawAngle*2);
DrawGraphic(GetX,GetY);
}
@BackGround{
SetTexture(bg);
SetRenderState(ALPHA);
SetAlpha(90);
SetGraphicRect(0,0,512,512);
SetGraphicAngle(0,0,DrawAngle);
SetGraphicScale(1,1);
DrawGraphic(GetCenterX,GetCenterY);

SetTexture(bg2);
SetRenderState(ALPHA);
SetAlpha(160);
SetGraphicRect(-DrawAngle,-DrawAngle,512-DrawAngle,512-DrawAngle);
SetGraphicAngle(0,0,0);
SetGraphicScale(1,1);
DrawGraphic(GetCenterX,GetCenterY);

}
@Finalize{
DeleteGraphic(imgBoss);
DeleteGraphic(cut);
DeleteSE(shotSE);
DeleteSE(chargeSE);
DeleteSE(TO1);
DeleteSE(TO2);
SetCommonData("Vanish",true);
DeleteAllEnemyWithoutBoss;
loop(8){
CreateItem(ITEM_SCORE,GetX+rand(-50,50),GetY+rand(-50,50));
}
function wait(w){
loop(w){yield;}
}
}
As for the second question, I wanna know how to add my own bullets to the game, i wanted to recreate Murasa's Anchor, although i get an error everytime, or no sprite at all for it, here are the codes:

Bullet Code:
Code: [Select]
#UserShotData    // Required

ShotImage = GetCurrentScriptDirectory~"system\anchor.png"    // Image of Bullets

// Definition of bullet
ShotData {
    id               = 120                  // Bullet ID
    rect             = (0, 0, 32, 32)     // Region in the ShotImage
    render           = ALPHA              // Render type
    delay_color      = (255, 128, 255)    // Color of light on delay
    angular_velocity = rand(-5, 5)        // Ang. vel. of graphic rotation
}

And the Script where the bullet is supposed to appear (i commented out all the things i did to try to make it appear, and returned the bullet graphic to BLUE03, i left what i was using earlier in a comment too)
Code: [Select]
#TouhouDanmakufu
#Title[Satori Spellcard 2]
#Text[Satori's Second SpellCard]
#BGM[.\system\SatoriTheme.mp3]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main{

let CSD = GetCurrentScriptDirectory;
let imgBoss= CSD ~ "system\satori.PNG";
let cut= CSD ~ "system\satoricut.png";
let bg = CSD ~ "system\SatoriBGa.png";
let bg2 = CSD ~ "system\SatoriBGb.png";

// let ANCHOR = CSD~"Anchor.txt";
// let ANCHOR = LoadUserShotData(CSD~"Anchor".txt);

let shotSE = CSD ~ "system\shotSE.wav";
let chargeSE = CSD ~ "system\charging.wav";
let anchorSE = CSD ~ "system\se_boon00.wav";
let TO1 = CSD ~"system\se_timeout.wav";
let TO2 = CSD ~"system\se_timeout2.wav";

let frame = 0;
let frame2 = 0;
let frame3 = 0;
let angle = 0;

@Initialize{
SetLife(500);
SetTimer(60);
SetScore(110000);
SetDamageRate(10,0);
SetInvincibility(120);
// Expert;

LoadGraphic(imgBoss);
LoadGraphic(cut);
LoadGraphic(bg);
LoadGraphic(bg2);
LoadSE(shotSE);
LoadSE(chargeSE);
LoadSE(anchorSE);
// LoadUserShotData(ANCHOR);
LoadSE(TO1);
LoadSE(TO2);

SetMovePosition02(GetCenterX, GetCenterY - 100, 120); //Move the boss to the top center of the screen.
CutIn(YOUMU,"Recolection ~ Death Anchor",cut,0,0,256,512);
Concentration01(120);
PlaySE(chargeSE);
}
@MainLoop{

if(OnBomb==false){
SetCollisionA(GetX,GetY,32);
SetCollisionB(GetX,GetY,21);
}
frame ++;
frame2 ++;
if(GetTimer>4&&GetTimer<=10&&frame3%60==0){
PlaySE(TO1);
}
if(GetTimer<=4&&frame3%60==0){
PlaySE(TO2);
}
if(frame==120){
CreateShotA(1,GetX,GetY,10);
// SetShotDataA(1,0,1,GetAngleToPlayer,0,0.4,12,ANCHOR);
SetShotDataA(1,0,1,GetAngleToPlayer,0,0.4,12,BLUE03);
ascent(i in 1..60){
CreateShotA(2,0,0,0);
SetShotDataA(2,0,0,GetAngleToPlayer-90,0,0,0,AQUA01);
SetShotDataA(2,30,0,GetAngleToPlayer-90,0,0.3,8,AQUA01);
AddShot(i*2,1,2,0);
CreateShotA(2,0,0,0);
SetShotDataA(2,0,0,GetAngleToPlayer-90,0,0.0,0,AQUA01);
SetShotDataA(2,33,0,GetAngleToPlayer-90,0,0.2,8,AQUA01);
AddShot(i*2,1,2,0);
CreateShotA(2,0,0,0);
SetShotDataA(2,0,0,GetAngleToPlayer-90,0,0.0,0,AQUA01);
SetShotDataA(2,35,0,GetAngleToPlayer-90,0,0.1,8,AQUA01);
AddShot(i*2,1,2,0);
CreateShotA(2,0,0,0);
SetShotDataA(2,0,0,GetAngleToPlayer+90,0,0,0,AQUA01);
SetShotDataA(2,30,0,GetAngleToPlayer+90,0,0.3,8,AQUA01);
AddShot(i*2,1,2,0);
CreateShotA(2,0,0,0);
SetShotDataA(2,0,0,GetAngleToPlayer+90,0,0,0,AQUA01);
SetShotDataA(2,33,0,GetAngleToPlayer+90,0,0.2,8,AQUA01);
AddShot(i*2,1,2,0);
CreateShotA(2,0,0,0);
SetShotDataA(2,0,0,GetAngleToPlayer+90,0,0,0,AQUA01);
SetShotDataA(2,35,0,GetAngleToPlayer+90,0,0.1,8,AQUA01);
AddShot(i*2,1,2,0);
}
FireShot(1);
frame = 60;
PlayAnchor;
}
if(frame2==120){
loop(60){
CreateShot01(GetX,GetY,1,GetAngleToPlayer+angle,PURPLE31,5);
angle+=360/60;
}
PlaySE(shotSE);
angle=0;
frame2=60;
}
yield;


}

@DrawLoop{
SetColor(255,255,255);
SetRenderState(ALPHA);

if(OnBomb==false){
SetAlpha(255);
}else{
SetAlpha(150);
}

SetTexture(imgBoss);
SetGraphicRect(0,0,47,64);
SetGraphicScale(1,1);
SetGraphicAngle(0,0,0);
DrawGraphic(GetX,GetY);
}
@BackGround{
frame3++;
SetTexture(bg);
SetRenderState(ALPHA);
SetAlpha(90);
SetGraphicRect(-frame3,0,512-frame3,512);
SetGraphicScale(1,1);
SetGraphicAngle(0,0,0);
DrawGraphic(GetCenterX, GetCenterY);

SetTexture(bg2);
SetRenderState(ALPHA);
SetAlpha(150);
SetGraphicRect(0,0,256,256);
SetGraphicAngle(0,0,frame3);
DrawGraphic(GetCenterX,GetCenterY);
}

@Finalize
{
DeleteGraphic(imgBoss);
DeleteGraphic(cut);
DeleteGraphic(bg);
DeleteSE(shotSE);
DeleteSE(chargeSE);
DeleteSE(anchorSE);
DeleteSE(TO1);
DeleteSE(TO2);
// DeleteUserShotData(ANCHOR);
loop(20){
CreateItem(ITEM_SCORE,GetX+rand(-50,50),GetY+rand(-50,50));
}
CreateItem(ITEM_1UP,GetX,GetY);
}
task PlayAnchor{
PlaySE(anchorSE);
wait(20);
PlaySE(anchorSE);
yield;
}


function wait(w){
loop(w){yield};
}
}

And for the last question, how can i make bullets glow? hope you guys can help me out
Title: Re: Danmakufu Q&A/Problem Thread
Post by: stillsatellite on October 19, 2009, 11:35:36 AM
Umm... I'm having a problem with a script.


(http://i36.tinypic.com/25qtzsj.jpg)



Well, I don't really know what the problem is...
I'm loading a separate script (using #include_function) and well, I'm loading the variables there.
I'm sure I did it correctly, but if I missed anything, well... could anyone help me?
Here is the separate script...
Code: [Select]
let 1a = GetCurrentScriptDirectory~"images\stagedata\Back001.png";
let 1b = GetCurrentScriptDirectory~"images\stagedata\Back002.png";
let 1c = GetCurrentScriptDirectory~"images\stagedata\Back003.png";
etc...
task LoadImages{
yield;
LoadGraphic(1a);LoadGraphic(1b);LoadGraphic(1c);LoadGraphic(1d);LoadGraphic(1e);LoadGraphic(1f);LoadGraphic(1g);
etc...
}
task DeleteImages{
yield;
DeleteGraphic(1a);DeleteGraphic(1b);DeleteGraphic(1c);DeleteGraphic(1d);DeleteGraphic(1e);DeleteGraphic(1f);DeleteGraphic(1g);
etc...
}

task AnimateBackground(let delay){
yield;

function wait(let frame){
loop(frame){yield;}}
            SetTexture(1a);SetGraphicRect(0,0,384,448);SetAlpha(255);SetRenderState(ALPHA);SetGraphicAngle(0, 0, 0);SetGraphicScale(1,1);DrawGraphic(GetCenterX,GetCenterY);wait(delay);
            SetTexture(1b);SetGraphicRect(0,0,384,448);SetAlpha(255);SetRenderState(ALPHA);SetGraphicAngle(0, 0, 0);SetGraphicScale(1,1);DrawGraphic(GetCenterX,GetCenterY);wait(delay);
etc...
}

And the main script.

Code: [Select]
#TouhouDanmakufu[Stage]
#Title[TEST]
#Text[TEST]
#Player[MARISA]
#ScriptVersion[2]

script_stage_main
{
#include_function".\stageframes.txt";
   @Initialize
   {
yield;
LoadImages;
   }

   @BackGround
{
yield;
AnimateBackground(0);
   }
   
   @Finalize
   {
      DeleteImages;
   }
}


I'm loading the variables like this:
Code: [Select]
let 1a = *;
until...
let 1z = *;
and then...
Code: [Select]
let 2a = *;
until...
let 2x = *;

Yeah it's a long stupid process :\
Maybe that's the problem? :V
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Thaws on October 19, 2009, 12:03:39 PM
I've no idea what the problem is, the error message says something about "Identifier is needed" or something.

but I just want to ask about the use of yield;s in your scripts...
Why are you including it at the beginning of every task? There is no need for pausing your task for 1 frame before you load the graphics. Yield; is not a must in every task you make, you know.

Also, the script is lacking a @MainLoop. I don't know if it's neccesary, maybe it's causing an error. :x
But putting a single yield; in the @MainLoop would be sufficient, you don't need to put a yield; everywhere.

Also, why are you declaring function wait inside task AnimatedBackground? (Can you actually declare functions inside tasks? :x) You should declare it outside of the task and you can still refer to it inside the task.

One more thing, you are starting up a new AnimatedBackground every frame, resulting in one task overlapping draw graphics on another. So the structure won't work.

Sorry that I can't help you with the main problem...
Title: Re: Danmakufu Q&A/Problem Thread
Post by: stillsatellite on October 19, 2009, 01:28:15 PM
Oh wow...
The variables' labels were the actual problems.
I just replaced the numbers in the variables with something else, and I did what you advised me.
It works perfectly now. Thanks!
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 19, 2009, 04:32:23 PM
Yeah, you can't start a variable name with a number.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Sakura665 on October 19, 2009, 05:37:14 PM
Well now one has answered any of my questions yet, but i just got a new one, how do people make it so that it shows Spell Card Attack on the background at the start of a spellcard like on Touhou 10+?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Zengar Zombolt on October 19, 2009, 05:48:24 PM
Well now one has answered any of my questions yet, but i just got a new one, how do people make it so that it shows Spell Card Attack on the background at the start of a spellcard like on Touhou 10+?
Here be it. (http://www.shrinemaiden.org/forum/index.php?topic=2146.0)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Drake on October 19, 2009, 05:49:09 PM
oh the magic of literacy
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Sakura665 on October 19, 2009, 06:22:38 PM
Here be it. (http://www.shrinemaiden.org/forum/index.php?topic=2146.0)
Thanks =D now if someone could answer my other questions ><
Title: Re: Danmakufu Q&A/Problem Thread
Post by: PT8Sceptile on October 19, 2009, 08:23:30 PM
Thanks =D now if someone could answer my other questions ><

Well...

For the inwards spinning circle, the easiest way would be to make a task that saves the current location of the player, and then keep setting the position of the bullet again and again with a shrinking radius and a changing angle. It's completely doable with arrays, too, but a bit trickier, so I'll give an example using a task:

Code: [Select]
task CirclingBullet(x, y, rad, ang, avel, rshrink){
      //x and y are the location of the center, rad the distance from center,
      //ang the initial angle, avel the rate of angle change and rsrink the
      //amount by which the radius shrinks per frame.
      //Add additional variables as necessary

     let obj = Obj_Create(OBJ_SHOT);
     Obj_SetPosition(obj,x+rad*cos(angle),y+rad*sin(angle));
     Obj_SetSpeed(obj,0);
     Obj_SetAngle(obj,0);
     ObjShot_SetDelay(obj,5);
     ObjShot_SetGraphic(obj, RED04);
     ObjShot_SetBombResist(obj, true);

     while(!Obj_BeDeleted(obj) {
          rad -= rshrink;
          ang += avel;
          Obj_SetPosition(obj,x+rad*cos(angle),y+rad*sin(angle));
          //Possibly add some code here to delete the bullet once
          //rad hits 0 if you don't want it to spiral outwards afterwards.
          //Also add bullet creation code here.
          yield;
     }
     
}

And create it in your mainloop using:

Code: [Select]
ascent(i in 0..8) {
    CirclingBullet(GetPlayerX, GetPlayerY, 100, i*360/8, 1, 0.5);
}

And as long as there's a yield; in your main loop, that should be enough.

Also, this is doable with arrays by saving the x and y coordinates in seperate arrays and resetting the position in the main loop accordingly. It just takes a bit more work.

For the anchor problem, I see you're calling the bullet through ANCHOR, which is a String variable. The bullet however has to be called by ID. This should probably make things clearer:

Danmakufu references bullets using numbers. Things such as RED01 and YELLOW03 are just convenient names that reference numbers. If you want to make ANCHOR represent the anchor bullet, you must set "let ANCHOR = 120;", since in the shot creation file, you set the id of the shot to 120. Or you can just put 120 in the bullet part of the script.

However, if I'm right about how bullet defining scripts work (someone please correct me if I'm wrong), loading user shot data replaces all bullets in danmakufu at the moment, so if you load your anchor bullet, bullets like BLUE03 and AQUA01 don't work anymore. So you either have to create the whole bullet sheet from scratch, or edit the anchor to some existing bullet definition file (like for example the CtC shot replace script). Adding a single bullet type while preserving all older ones is, under my current knowledge, impossible through any conventional means.

I'm not exactly sure about this, but seemingly glowy bullets have "render = ALPHA" in the shot definition script replaced with "render = ADD" (again, someone please correct me if I'm wrong). You could create your own in the same file as the anchor for example, or you can use a pre-existing bullet sheet with them (for example the CtC shot replace script has [COLOR]50, [COLOR]51 and [COLOR]57 that glow).
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Sakura665 on October 19, 2009, 08:49:58 PM
Quote from: PT8Sceptile link=topic=296
Well...

For the inwards spinning circle, the easiest way would be to make a task that saves the current location of the player, and then keep setting the position of the bullet again and again with a shrinking radius and a changing angle. It's completely doable with arrays, too, but a bit trickier, so I'll give an example using a task:

I added the task, but then i noticed there was spawning only 1 bullet (Although it probably was spawning all of them in the same position), so i studied your code and noticed you were using the variable angle, which i already had defined earlier for something else, and since that variable isnt moving at all, then the bullets would spawn all at the same angle, so i changed angle with ang (as in the values it receives from when i call this task) and it worked.

Now on to test the bullet part...
EDIT1:
Code: [Select]
script_enemy_main{

let CSD = GetCurrentScriptDirectory;
let imgBoss= CSD ~ "system\satori.PNG";
let cut= CSD ~ "system\satoricut.png";
let bg = CSD ~ "system\SatoriBGa.png";
let bg2 = CSD ~ "system\SatoriBGb.png";

let ANCHOR = CSD~"Anchor.txt";
// let ANCHOR = LoadUserShotData(CSD~"Anchor".txt);

let shotSE = CSD ~ "system\shotSE.wav";
let chargeSE = CSD ~ "system\charging.wav";
let anchorSE = CSD ~ "system\se_boon00.wav";
let TO1 = CSD ~"system\se_timeout.wav";
let TO2 = CSD ~"system\se_timeout2.wav";

let frame = 0;
let frame2 = 0;
let frame3 = 0;
let angle = 0;

@Initialize{
SetLife(500);
SetTimer(60);
SetScore(110000);
SetDamageRate(10,0);
SetInvincibility(120);
// Expert;

LoadGraphic(imgBoss);
LoadGraphic(cut);
LoadGraphic(bg);
LoadGraphic(bg2);
LoadSE(shotSE);
LoadSE(chargeSE);
LoadSE(anchorSE);
LoadUserShotData(ANCHOR);

<same code>
        CreateShotA(1,GetX,GetY,10);
SetShotDataA(1,0,1,GetAngleToPlayer,0,0.4,12,120);
// SetShotDataA(1,0,1,GetAngleToPlayer,0,0.4,12,BLUE03);
ascent(i in 1..60){
<same code>
Ok i edited this now i get this problem:
(http://i238.photobucket.com/albums/ff164/Sakura301/AnchorError.jpg)
And if i click on Ok, it loads all other bullets normally but wont load the anchor, and just is like there wasnt any bullet there

EDIT3:  Nevermind i managed to fix the ghostly glow, the delay was too high, that's why,
here's how it ended up (http://www.youtube.com/watch?v=9W7D4cubpEU)

EDIT6: Ok i managed to do it, not as pretty as the original but is something
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Azure Lazuline on October 20, 2009, 06:01:20 AM
Is there any way to make an object bullet not give any graze points, or any workaround to get this effect?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 20, 2009, 08:24:50 AM
Quote
Is there any way to make an object bullet not give any graze points, or any workaround to get this effect?

There is no way to prevent the graze from registering. To undo it, have the bullet continually check it's distance from the player, and do a AddGraze(-1) when it detects it is in graze range. Note that you will need to somehow find out the exact range at which graze is counted, and make sure it only checks for this once per bullet.

It's a pain in the ass, yeah.

Also just a heads up, when this hits 1000 posts and I'm not around, someone start a new thread since I'm gonna lock this one. (Actually, I think it might happen automatically. I have no idea. How exciting!)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: PT8Sceptile on October 20, 2009, 08:44:37 AM
I added the task, but then i noticed there was spawning only 1 bullet (Although it probably was spawning all of them in the same position), so i studied your code and noticed you were using the variable angle, which i already had defined earlier for something else, and since that variable isnt moving at all, then the bullets would spawn all at the same angle, so i changed angle with ang (as in the values it receives from when i call this task) and it worked.

And yet again, whenever I forget to check the code I write, a typo manages to sneak in. Yes, the angle was supposed to be replaced by ang, but I forgot to do that when hastily writing that down.

Okay, for the anchor part, I think I figured the problem out. For some mysterious reason, if you reference GetCurrentScriptDirectory in the ShotImage definition, that error seemingly gets thrown. Try replacing this:
Code: [Select]
ShotImage = GetCurrentScriptDirectory~"system\anchor.png"with:
Code: [Select]
ShotImage = ".\system\anchor.png"It should mean the exact same thing but not throw errors this time. If that doesn't work, then I'm as confused as you are.

Also, you probably have to edit the rect value of the bullet definition script. Your script indicates the anchor is contained in the upper left square of the image and is 32 pixels wide and tall. That's a pretty small anchor for Murasa, if you ask me. The rect variable should be changed to surround the anchor the same way as you're surrounding the boss's sprite in the main script's DrawLoop using SetGraphicRect. Also, if you don't want the anchor to rotate, change angular_velocity in the bullet definition file to 0.

And...

Is there any way to make an object bullet not give any graze points, or any workaround to get this effect?

You could remove collision detection with the player using Obj_SetCollisionToPlayer(objectname, false); (it stops the bullet from killing the player and giving the player any graze) and manually check the collision with player (as long as the bullet is alive, run the following every frame: if player is within a certain radius from the location of the bullet and GetTimeOfPlayerInvincibility == 0, call ShootDownPlayer). Or at least that's the best idea I can think of.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Naut on October 20, 2009, 03:49:35 PM
Is there any way to make an object bullet not give any graze points, or any workaround to get this effect?
You could remove collision detection with the player using Obj_SetCollisionToPlayer(objectname, false); (it stops the bullet from killing the player and giving the player any graze) and manually check the collision with player (as long as the bullet is alive, run the following every frame: if player is within a certain radius from the location of the bullet and GetTimeOfPlayerInvincibility == 0, call ShootDownPlayer). Or at least that's the best idea I can think of.

This is correct, but how do you plan to get whether or not the player is within a certain radius? Got a function for this? I would just use:

if(GetPlayerX <= Obj_GetX(obj) + (right bound graphic rect of the bullet / 2) && GetPlayerX >= Obj_GetX(obj) - (left bound graphic rect of the bullet / 2) && GetPlayerY <= Obj_GetY(obj) + (lower bound graphic rect of bullet / 2) && GetPlayerY >= Obj_GetY(obj) - (upper bound graphic rect of the bullet /2) && GetTimeOfPlayerInvincibility==0){
   ShootDownPlayer;
}

Square hitbox, I know, but I don't know how to detect collision within a radius outside of ObjSpell's.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Janitor Morgan on October 20, 2009, 05:25:53 PM
After posting my question about recreating Cirno's Diamond Blizzard and what else I'd need to know to make it a success, I started messing around with what I already know, and I think I've got something pretty close.

Code: [Select]
#TouhouDanmakufu
#Title[Snow Sign "Diamond Blizzard"]
#Text[My first attempt at recreating a card.]
#BackGround[IceMountain]
//#BGM[.\bgm\th06_05.wav]
#Player[REIMU, MARISA, player\Rumia\Rumia.txt]
#ScriptVersion[2]

script_enemy_main {
let ImgBoss = "script\img\ExRumia.png";
//let imgSpellBackdrop=GetCurrentScriptDirectory~"img\icewall.png";
let frame = -120;
let movecount = -120;

    @Initialize {
SetScore(50000);
SetLife(240);
SetDamageRate(10,10);
SetTimer(60);
SetInvincibility(30);

SetGraphicRect(1, 1, 64, 64);
LoadGraphic(ImgBoss);
//LoadGraphic(imgSpellBackdrop);

SetMovePosition02(GetCenterX, GetClipMinY + 120, 120);
CutIn(KOUMA, "Snow Sign "\""Diamond Blizzard"\", 0, 0, 0, 0, 0);
    }

    @MainLoop {
SetCollisionA(GetX, GetY, 32);
SetCollisionB(GetX, GetY, 16);

if(frame == 10) {
let leftright = rand(-100, 100);
let updown = rand(-50, 50);
loop(10) {
CreateShot01(GetX+leftright, GetY+updown, rand(0.5, 4), rand(0, 359), AQUA23, 20);
    }
frame = 0;
}
if(movecount == 120) {
SetMovePositionRandom01(50,20,5,GetClipMinX()+100,30,GetClipMaxX()-100,100);
movecount = 0;
}
frame++;
movecount++;
    }

    @Finalize {
DeleteGraphic(ImgBoss);
//DeleteGraphic(imgSpellBackdrop);
    }

    @DrawLoop {
SetAlpha(255);
SetTexture(ImgBoss);
SetGraphicRect(1,1,64,64);
DrawGraphic(GetX(),GetY());
    }

//    @BackGround {
// SetAlpha(150);
// SetTexture(imgSpellBackdrop);
// SetGraphicRect(0,0,384,448);
// DrawGraphic(GetCenterX,GetCenterY);
    }
}

Now my question is, how can I clean this up so that it looks like the one from Embodiment of Scarlet Devil? Obviously, I need to figure out how to make a Cirno boss sprite so that it's not Rumia firing things, but what else could I change to make it a better match?
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Sakura665 on October 20, 2009, 05:30:47 PM

Okay, for the anchor part, I think I figured the problem out. For some mysterious reason, if you reference GetCurrentScriptDirectory in the ShotImage definition, that error seemingly gets thrown. Try replacing this:
Code: [Select]
ShotImage = GetCurrentScriptDirectory~"system\anchor.png"with:
Code: [Select]
ShotImage = ".\system\anchor.png"It should mean the exact same thing but not throw errors this time. If that doesn't work, then I'm as confused as you are.

Also, you probably have to edit the rect value of the bullet definition script. Your script indicates the anchor is contained in the upper left square of the image and is 32 pixels wide and tall. That's a pretty small anchor for Murasa, if you ask me. The rect variable should be changed to surround the anchor the same way as you're surrounding the boss's sprite in the main script's DrawLoop using SetGraphicRect. Also, if you don't want the anchor to rotate, change angular_velocity in the bullet definition file to 0.

Well i downloaded yesterday before i went to sleep the shot_replace thingy, now i just need to know how to use it, as in, 1 - the readme file says which codes for which bullets, but then im not that good at recognizing some of them with their image to say "ah, this bullet is with this variable", some pic -> code would be nice. 2 - if i use that, can i add the anchor to that file and use it?, as for the size thingy, i just cut it from the rip from UFO sprites, considering is kinda small yeah i would need to increase it's size on MS_Paint (unless it allows me to scale it to a bigger size). 3 - if i were to use the shot_replace thingy wouldnt that mean that only people with the shot_replace would be able to use the script?, and if so, how can i edit it so that i can just include it in my script.

Edit: Also, i think this is pretty close to the original Shooting Star from Th11(SA), but is there anyway to make it look better?:
Code: [Select]
#TouhouDanmakufu
#Title[Satori Spellcard 6]
#Text[Satori's 6th Spellcard]
#BGM[.\system\SatoriTheme.mp3]
#Player[FREE]
#ScriptVersion[2]

script_enemy_main {
#include_function ".\cutin.txt"

let CSD = GetCurrentScriptDirectory;
let imgBoss= CSD ~ "system\satori.PNG";
let BossRight = CSD ~ "system\SatoriRight.PNG";
let BossLeft = CSD ~ "system\SatoriLeft.png";
let cut= CSD ~ "system\satoricut.png";
let bg = CSD ~ "system\SatoriBGa.png";
let bg2 = CSD ~ "system\SatoriBGb.png";
let bgN1 = CSD ~ "system\Nuclear.png";
let bgN2 = CSD ~ "system\CAUTION.PNG";

let shotSE = CSD ~ "system\shotSE.wav";
let chargeSE = CSD ~ "system\charging.wav";
let TO1 = CSD ~"system\se_timeout.wav";
let TO2 = CSD ~"system\se_timeout2.wav";
let ALERT = CSD ~"system\se_alert.wav";

let frame = 0;
let frame2 = 0;
let frame3 = 0;
let angle = 0;
let angleTilt = 0;
let speed=1;
let angle1 =0;
let angle2 =0;

@Initialize{
SetLife(1000);
SetDamageRate(30,0);
SetTimer(75);
SetScore(1200000);
SetMovePosition02(GetCenterX-150,GetCenterY-100,120);
SetInvincibility(180);
SetEnemyMarker(true);

LoadGraphic(imgBoss);
LoadGraphic(BossRight);
LoadGraphic(BossLeft);
LoadGraphic(cut);
LoadGraphic(bg);
LoadGraphic(bg2);
LoadGraphic(bgN1);
LoadGraphic(bgN2);
LoadSE(shotSE);
LoadSE(chargeSE);
LoadSE(ALERT);
LoadSE(TO1);
LoadSE(TO2);
CutIn(YOUMU,"Recolection ~ Shooting Star",cut,0,0,0,0);
cutin("NAZRIN",cut,0,0,256,512)

}

@MainLoop{
frame++;
frame2++;
frame3++;
if(!OnBomb){
SetCollisionA(GetX,GetY,32);
SetCollisionB(GetX,GetY,21);
}
if(GetTimer>4&&GetTimer<=10&&frame3%60==0){
PlaySE(TO1);
}
if(GetTimer<=4&&frame3%60==0){
PlaySE(TO2);
}
if(frame3==10){
loop(4){
PlaySE(ALERT);
wait(4);
}
}

if(frame==120){
ShootingStar(20,5,RED03,15);
}
if(frame2==180){
angleTilt=rand(-5,5);
angle1=atan2(GetSpeedY,GetSpeedX)+90;
angle2=atan2(GetSpeedY,GetSpeedX)-90;
loop(20){
CreateShot01(GetX+50*cos(angle1),GetY+50*sin(angle1),speed/3,angle1+angleTilt,YELLOW02,0);
CreateShot01(GetX-50*cos(angle2),GetY-50*sin(angle2),speed/3,angle2+angleTilt,YELLOW02,0);
// CreateShot01(GetX+50,GetY+50,speed,92,bullet,0);
// CreateShot01(GetX+50,GetY+50,-(speed),92,bullet,0);
speed++;
}
speed=1;
frame2=166;
}

yield;
}
@DrawLoop{
SetColor(255,255,255);
SetRenderState(ALPHA);
if(OnBomb){
SetAlpha(150);
}else{
SetAlpha(255);
}
if(GetSpeedX==0){
SetTexture(imgBoss);
SetGraphicRect(0,0,47,64);
}
if(GetSpeedX>0){
SetTexture(BossRight);
SetGraphicRect(0,0,54,63);
}
if(GetSpeedX<0){
SetTexture(BossLeft);
SetGraphicRect(0,0,54,63);
}
SetGraphicScale(1,1);
SetGraphicAngle(0,0,0);
DrawGraphic(GetX,GetY);

}
@BackGround{
frame3++;
SetTexture(bg);
SetRenderState(ALPHA);
SetAlpha(90);
SetGraphicRect(-frame3,0,512-frame3,512);
SetGraphicScale(1,1);
SetGraphicAngle(0,0,0);
DrawGraphic(GetCenterX, GetCenterY);

SetTexture(bg2);
SetRenderState(ALPHA);
SetAlpha(150);
SetGraphicRect(0,0,256,256);
SetGraphicAngle(0,0,frame3);
DrawGraphic(GetCenterX,GetCenterY);

SetTexture(bgN1);
SetRenderState(ALPHA);
SetAlpha(155);
SetGraphicRect(frame3/2,0,GetClipMaxX+(frame3/2),131);
SetGraphicAngle(0,0,0);
DrawGraphic(GetCenterX,GetCenterY);

SetTexture(bgN2);
SetRenderState(ALPHA);
SetAlpha(155);
SetGraphicRect(-frame3/2,0,GetClipMaxX-(frame3/2),230);
SetGraphicAngle(0,0,0);
DrawGraphic(GetCenterX,GetCenterY);

}
    @Finalize {
DeleteGraphic(imgBoss);
DeleteGraphic(BossRight);
DeleteGraphic(BossLeft);
DeleteGraphic(cut);
DeleteGraphic(bg);
DeleteGraphic(bg2);
DeleteGraphic(bgN1);
DeleteGraphic(bgN2);
DeleteSE(shotSE);
DeleteSE(chargeSE);
DeleteSE(TO1);
DeleteSE(TO2);
    }
task ShootingStar(frames,speed,bulletB,numC){;
Concentration01(frames);
wait(frames);
SetMovePositionHermite(GetClipMaxX+120,GetY,150,90,-150,90,180);
wait(180);
SetMovePosition02(GetX,GetCenterY,60);
wait(60);
SetMovePosition02(GetClipMinX-120,GetCenterY-100,120);
wait(120);
SetMovePosition02(GetX,GetCenterY,30);
wait(30);
SetMovePosition02(GetClipMaxX+120,GetCenterY-120,120);
wait(120);
SetMovePosition02(GetX,GetCenterY,30);
wait(30);
SetMovePosition02(GetCenterX,GetCenterY-100,60);
wait(60);
ascent(i in 0..10){
loop(numC){
CreateShot01(GetX,GetY,speed,angle+GetAngleToPlayer,bulletB,0);
angle+=360/numC;
frame2=166;
}
wait(10);
}
Concentration01(frames);
wait(frames);
SetMovePositionHermite(GetClipMinX-120,GetY,150,90,-150,90,180);
wait(180);
SetMovePosition02(GetX,GetCenterY,60);
wait(60);
SetMovePosition02(GetClipMaxX+120,GetCenterY-100,120);
wait(120);
SetMovePosition02(GetX,GetCenterY,30);
wait(30);
SetMovePosition02(GetClipMinX-120,GetCenterY-120,120);
wait(120);
SetMovePosition02(GetX,GetCenterY,30);
wait(30);
SetMovePosition02(GetCenterX,GetCenterY-100,60);
wait(60);
ascent(i in 0..10){
loop(numC){
CreateShot01(GetX,GetY,speed,angle+GetAngleToPlayer,bulletB,0);
angle+=360/numC;
frame2=166;
}
wait(10);
}
ShootingStar(frames,speed,bulletB,numC);
yield;

}
task ShootIt(count,bullet,num){
let speed=1;
let angle1 =0;
let angle2 =0;
loop{
angle1=atan2(GetSpeedY,GetSpeedX)+90;
angle2=atan2(GetSpeedY,GetSpeedX)-90;
loop(num){
CreateShot01(GetX+50*cos(angle1),GetY+50*sin(angle1),speed,angle1,bullet,0);
CreateShot01(GetX-50*cos(angle2),GetY-50*sin(angle2),speed,angle2,bullet,0);
// CreateShot01(GetX+50,GetY+50,speed,92,bullet,0);
// CreateShot01(GetX+50,GetY+50,-(speed),92,bullet,0);
speed++;
}


speed=1;
wait(count);
}
yield;
}
function wait(w){
loop(w){yield;}
}
}
Dont mind the unused task, mostly because the task never worked for me and i had to use it in the mainloop, idk why with the mainloop it worked if it's basically the same thing, as an addition, why do i have to make a task recall itself so it can loop?

Edit 2: Is it possible to make the boss split in 2 and control both movements from 1 script? or do i have to make the other one as a familiar and control it in it's section

Edit 3: If i want to make a Point system do i have to add the task on every script, or only the stage script

Edit 4: If i want to change the BGM in mid of a fight, (a.k.a like Mystia on IN with dialogue included) i should delete the previous BGM before i Play the new one right?, assuming im using the song from the 1st dialogue, to delete it from memory in let's say 6 spellcards later, would it delete it even if the spellcard didnt load it on initialize? im kinda confused about that

Edit 5: Ehh it would be nice if someone could tell me the exact script for reflecting bullets for the X vertices and for the Y vertices (for each) so i can have an overall use of it whenever i need to make reflecting stuff.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: PT8Sceptile on October 21, 2009, 09:25:09 AM
Well i downloaded yesterday before i went to sleep the shot_replace thingy, now i just need to know how to use it, as in, 1 - the readme file says which codes for which bullets, but then im not that good at recognizing some of them with their image to say "ah, this bullet is with this variable", some pic -> code would be nice. 2 - if i use that, can i add the anchor to that file and use it?, as for the size thingy, i just cut it from the rip from UFO sprites, considering is kinda small yeah i would need to increase it's size on MS_Paint (unless it allows me to scale it to a bigger size). 3 - if i were to use the shot_replace thingy wouldnt that mean that only people with the shot_replace would be able to use the script?, and if so, how can i edit it so that i can just include it in my script.

1 - Trial and error is one way. Another is opening shot_All.dnh and shot_replace.dnh in Notepad/whatever code editor you use and opening shot_all.png in MSPaint/whatever graphics editor you use. Now, whenever you move your mouse in Paint, in the lower left corner there should be two numbers that represent the coordinates of the mouse in the picture. Find the numerical ID of the bullet referenced from shot_replace.dnh, locate the bullet with that ID in shot_All.dnh and look at the rect of that bullet. The first two coordinates define the upper-left corner of the bullet in the shot_all.png file you opened with MSPaint, so you can just go locate the corner and see which bullet is down-right from that point. Do note, though, that if the render type of the bullet is not ALPHA, it will look different in Danmakufu than in MSPaint.

However, as I initially said, trial and error is probably the best way. Try out different bullet types and you'll see what they look like.

2 - Technically, it's possible (I'm not knowledged enough of the copyright and general policy issues regarding that, so you should probably ask someone else. I'm just assuming editing the file is O.K. as long as you're not trying to claim the whole file is your work). Just insert the anchor into shot_all.png through whichever graphics editing program you're using (editing it in MSPaint is probably stupid, though, since unless it's been changed lately that program can't handle transparencies, but there are myriads of free graphics editors on the internet that do support transparency so finding one shouldn't be an issue) and change one of the shotdata blocks in shot_All.dnh into the required information for the anchor (adding one won't probably work since Danmakufu has a upper limit on the amount of bullets in shotdata files, but you can just remove one you most probably aren't using). Of course, that brings me into...

3 - If you are, in fact, going to modify the file, you probably have to distribute it alongside your code, too. You can do this by for example coyping the SHOT_REPLACE -folder to your script folder (I recommend doing this before editing the files, so that you still have the original) and just replace the include function command specified in the readme with:

Code: [Select]
#include_function ".\SHOT_REPLACE\shot_replace.dnh"
Then just call shotinit; in the initialization part of the code and it should work. Do note, though, that if you're not modifying the script, you're probably okay with only referencing that the shot replace script is required in whatever topic you're posting your cards in, since most of the people here on the forums have downloaded it.

Edit 3: If i want to make a Point system do i have to add the task on every script, or only the stage script

Edit 4: If i want to change the BGM in mid of a fight, (a.k.a like Mystia on IN with dialogue included) i should delete the previous BGM before i Play the new one right?, assuming im using the song from the 1st dialogue, to delete it from memory in let's say 6 spellcards later, would it delete it even if the spellcard didnt load it on initialize? im kinda confused about that

Edit 5: Ehh it would be nice if someone could tell me the exact script for reflecting bullets for the X vertices and for the Y vertices (for each) so i can have an overall use of it whenever i need to make reflecting stuff.

E3 - Depends entirely on the point system and it's complexity. Generally, if you use enough Common Data variables, you'll do well enough with just adding the processing system to the stage and adding any custom point items you've made on scripts that drop them (perhaps by importing a function from a general script).

E4 - Haven't had to do anything like this before, so I can't really comment on that.

E5 - There are multiple ways of doing this. The one I use (not necessarily the most simple and efficient one) is: Whenever the object hits a wall (X coordinate less than the left bound or greater than the right bound, or the same for Y), split the speed/angle combination into components (speedx = speed*cos(angle), speedy = speed*sin(angle)), and if the component is going out of the field (x < left bound and speedx < 0, or x > right bound and speedx > 0), multiply the corresponding speed by -1 (speedx = speedx*(-1)), and recalculate the angle (angle = atan2(speedy, speedx)). Here's an example code I've used in some spellcards:

Code: [Select]
task SpinShot(xpos, ypos, speed, angle, avel, aacc, minavel, bounces, graph) {
let obj = Obj_Create(OBJ_SHOT);
Obj_SetPosition(obj, xpos, ypos);
Obj_SetSpeed(obj, speed);
Obj_SetAngle(obj, angle);
ObjShot_SetGraphic(obj, graph);
ObjShot_SetDelay(obj, 0);
ObjShot_SetBombResist(obj, false);
Obj_SetAutoDelete(obj, true);

while (!Obj_BeDeleted(obj)) {
angle += avel;
avel += aacc;
if ((avel < minavel && aacc < 0) || (avel > minavel && aacc > 0)) {
avel = minavel;
}

let velx = speed*cos(angle);
let vely = speed*sin(angle);

if (Obj_GetX(obj) < 5 && velx < 0 && bounces > 0) {
velx *= -1;
bounces--;
}
if (Obj_GetX(obj) > 443 && velx > 0 && bounces > 0) {
velx *= -1;
bounces--;
}
if (Obj_GetY(obj) < 5 && vely < 0 && bounces > 0) {
vely *= -1;
bounces--;
}
if (Obj_GetY(obj) > 475 && vely > 0 && bounces > 0) {
vely *= -1;
bounces--;
}

angle = atan2(vely, velx);

Obj_SetAngle(obj, angle);
yield;
}
}

That's a task for a bouncing bullet with variable set location, speed, angle, angular velocity (avel), angular acceleration (aacc), maximum/minimum angular velocity (minavel), amount of bounces the bullet does and the graphic of the bullet. It bounces off of all 4 walls, so that should be enough for example code.

However, there's also a second, possibly slightly easier, faster and overall more efficient method than mine, that I unfortunately haven't had the will to learn for, due to it requiring a bit more memorization that this one in my opinion. If someone here could post the general formula that works only with angles, you'll probably want to use that instead.
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Sakura665 on October 21, 2009, 09:36:01 AM
Yeah that could work i basically want to make bullets that bounce off all walls except the bottom one

EDIT: but having the angles and all that stuff for every wall is nice to have so i can just copy it everytime i need bouncing

EDIT 2:
Quote
2 - Technically, it's possible (I'm not knowledged enough of the copyright and general policy issues regarding that, so you should probably ask someone else. I'm just assuming editing the file is O.K. as long as you're not trying to claim the whole file is your work). Just insert the anchor into shot_all.png through whichever graphics editing program you're using (editing it in MSPaint is probably stupid, though, since unless it's been changed lately that program can't handle transparencies, but there are myriads of free graphics editors on the internet that do support transparency so finding one shouldn't be an issue) and change one of the shotdata blocks in shot_All.dnh into the required information for the anchor (adding one won't probably work since Danmakufu has a upper limit on the amount of bullets in shotdata files, but you can just remove one you most probably aren't using). Of course, that brings me into...

Actually i just wanted to use it to be able to add the anchor without having to make another shot file, not to claim anything about it, since if i have this file i can just add a new id and assing the anchor to it, so this would help
Title: Re: Danmakufu Q&A/Problem Thread
Post by: PT8Sceptile on October 21, 2009, 09:59:59 AM
Just remove this and it won't bounce off the bottom one:

Code: [Select]
if (Obj_GetY(obj) > 475 && vely > 0 && bounces > 0) {
            vely *= -1;
            bounces--;
         }
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Helepolis on October 21, 2009, 10:17:04 AM
Make the anchor a familiar. I told DgBarca the same thing when he started immitating Murasa. An anchor as a shot is a bad idea :V It looks so fake and hard to control. If you turn it into a familiar you can give it all kind of functions and effects (also code wise it is more overview)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Sakura665 on October 21, 2009, 04:19:48 PM
Yeah it looks like a nice idea to me, although now i hope i dont end up with the same problem trying to imitate Utsuho's 2nd non-spell. (As seen in the code i provided earlier... might end up providing a video too)
Title: Re: Danmakufu Q&A/Problem Thread
Post by: Stuffman on October 21, 2009, 04:44:06 PM
New thread! (http://www.shrinemaiden.org/forum/index.php?topic=3218.0)

If you have active questions please repost them there.