Topic: ※ Danmakufu Q&A/Problem thread 3 ※  (Read 80706 times)

0 Members and 1 Guest are viewing this topic.

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
  • Staff
  • LOOK AT ME
※ Danmakufu Q&A/Problem thread 3 ※
« on: January 30, 2016, 12:51:16 pm »
Welcome to the Question and Answer (or any problem/help me) thread for Danmakufu

Important notice (26-04-2016): This thread will function as the general Danmakufu Q&A from this point on
As we all know, 0.12m is heavily outdated. It has become ancient :V So far, we've been keeping two threads to help people with their questions or problems. However, Ph3 is no longer considered scary or difficult as we got a skilled community with various people to help out. It is time to move on and leave 0.12m alone.

If you have 0.12m questions (because of old scripts and such), feel free to ask them in here.





« Last Edit: April 26, 2016, 06:36:32 pm by Helepolis »
  • Helepolis' Siege Workshop

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
  • Staff
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1 on: January 30, 2016, 02:23:21 pm »
Last ongoing question by Zhan_Fox  which had started here. Below a guote from the last post.

Oh, Sorry my English is not clear…
I want to connect two objects (like for example GetObjectDistance(obj1,obj2) ), but both objects are in different loop making rings. With SetCommonData (as you said before) I have no imagination how could I do that.
  • Helepolis' Siege Workshop

Drake

  • *
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #2 on: January 31, 2016, 07:52:25 am »
I was waiting for an elaboration because I'm pretty sure my last post needed a concrete example.

Code: [Select]
let listA = [];
let listB = [];

// note that this is specifically a function, which creates and sets up a single object we want
function ObjectA(y){
    // create and initialize the object
    let objA = CreateShotA1(20, y, 1, 25, DS_BALL_S_RED, 20);
    // task *within* a function, which keeps running even when the function returns
    task DoStuffA(){
        // running loop
        while(!Obj_IsDeleted(objA)){ 
            // in this example, A bullets change color when they collide with B bullets
            let collision = false;
            ascent(i in 0..length(listB)){
                if(GetObjectDistance(objA, listB[i]) < 20){
                    ObjShot_SetGraphic(objA, DS_BALL_S_BLUE);
                    collision = true;
                    break;
                }
            }
            if(!collision){
                ObjShot_SetGraphic(objA, DS_BALL_S_RED);
            }
            yield;
        }
    }
    // run the above task
    DoStuffA();
    // return the object ID you just created to store it in a variable with higher scope
    return objA;
}

// similar to above
function ObjectB(y){
    let objB = CreateShotA1(364, y, 1, 155, DS_BALL_S_RED, 20);
    task DoStuffB(){
        while(!Obj_IsDeleted(objB)){
        let collision = false;
            ascent(i in 0..length(listA)){
                if(GetObjectDistance(objB, listA[i]) < 20){
                    ObjShot_SetGraphic(objB, DS_BALL_S_BLUE);
                    collision = true;
                    break;
                }
            }
            if(!collision){
                ObjShot_SetGraphic(objB, DS_BALL_S_RED);
            }
            yield;
        }
    }
    DoStuffB();
    return objB;
}

ascent(i in 0..10){
    listA = listA ~ [ ObjectA(20+i*20) ]; // creates ten of the ObjectA bullets
    listB = listB ~ [ ObjectB(20+i*20) ]; // creates ten of the ObjectB bullets
    loop(10){yield;}
}

There are better ways to code this particular example, but hopefully this illustrates my previous post. Note that both A objects and B objects are created in different function scopes and have different behaviour, but still reference each other. The functions that create the objects return their IDs, so you can store the object IDs using variables declared in higher scopes (so they're more accessible). The tasks within each function still run independently of each other, even though the function surrounding it returns.
« Last Edit: February 06, 2016, 12:03:50 am by Drake »

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by あかがし -

Jean Fox

  • Nickname: Fox
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #3 on: January 31, 2016, 08:56:14 am »
I was waiting for an elaboration because I'm pretty sure my last post needed a concrete example.

Code: [Select]
let listA = [];
let listB = [];

function ObjectA(y){
    let objA = CreateShotA1(20, y, 1, 25, DS_BALL_S_RED, 20);
    task DoStuffA(){
        while(!Obj_IsDeleted(objA)){
            let collision = false;
            ascent(i in 0..length(listB)){
                if(GetObjectDistance(objA, listB[i]) < 20){
                    ObjShot_SetGraphic(objA, DS_BALL_S_BLUE);
                    collision = true;
                    break;
                }
            }
            if(!collision){
                ObjShot_SetGraphic(objA, DS_BALL_S_RED);
            }
            yield;
        }
    }
    DoStuffA();
    return objA;
}

function ObjectB(y){
    let objB = CreateShotA1(364, y, 1, 155, DS_BALL_S_RED, 20);
    task DoStuffB(){
        while(!Obj_IsDeleted(objB)){
        let collision = false;
            ascent(i in 0..length(listA)){
                if(GetObjectDistance(objB, listA[i]) < 20){
                    ObjShot_SetGraphic(objB, DS_BALL_S_BLUE);
                    collision = true;
                    break;
                }
            }
            if(!collision){
                ObjShot_SetGraphic(objB, DS_BALL_S_RED);
            }
            yield;
        }
    }
    DoStuffB();
    return objB;
}

ascent(i in 0..10){
    listA = listA ~ [ ObjectA(20+i*20) ]; // creates ten of the ObjectA bullets
    listB = listB ~ [ ObjectB(20+i*20) ]; // creates ten of the ObjectB bullets
    loop(10){yield;}
}

There are better ways to code this particular example, but hopefully this illustrates my previous post. Note that both A objects and B objects are created in different function scopes and have different behaviour, but still reference each other. The functions that create the objects return their IDs, so you can store the object IDs using variables declared in higher scopes (so they're more accessible). The tasks within each function still run independently of each other, even though the function surrounding it returns.

WOW! IT'S WORKING!
I never would have guessed to do like that.
Thank you! My superhero!

Lollipop

  • stay woke
  • literally and figuratively dying
  • Nickname: TouhouGamer3141592
  • Gender: guess
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #4 on: February 05, 2016, 10:57:35 pm »
2 questions.

1. How to do a magic circle (the circles that spin around the boss)
2. How to spawn familiars
Touhou 1CCS:
Hard: LLS, EoSD(NB), PCB(NB), IN, MoF, TD, DDC(NB), LoLK
Lunatic: EoSD, PCB, DDC, LoLK
Extra: LLS, EoSD, PCB(Extra&Phantasm), IN, MoF, SA, DDC, LoLK
Current Focus: 1cc SA Hard, or an Extra

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #5 on: February 06, 2016, 05:49:58 am »
2 questions.

1. How to do a magic circle (the circles that spin around the boss)
2. How to spawn familiars

1. Depends on what you want. The built-in system uses a primitive object with a large number of vertices. You can also use a 2D sprite (or multiple 2D sprites) instead of a primitive.
2. Depends on what you mean by 'familiar'. If they have life bars, implement them as Obj_Enemy. If they do not have life bars, you can use 2D sprites and control their movement and positioning using trigonometry.

iVAwalys

  • Nickname: Awalys
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #6 on: February 06, 2016, 10:18:28 am »
Since someone asked me to explain how I made the following code work, and since the old thread has reached its limit, I couldn't edit it, so I'm posting it here:

Basically, this line of code was supposed to spawn a circle of bullets out of a bigger bullet if it reaches the sides of the screen:
Code: [Select]
task BulletCommandExplosions(shot){
let rx = ObjMove_GetX(shot);
let ry = ObjMove_GetY(shot);
let angleR = rand(0, 360);
while(rx > 0 && rx < GetStgFrameWidth){yield;}
if(rx <= 0){
loop(12){
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 10);
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 10);
ObjShot_SetDeleteFrame(shot, 0);
angleR += 360/12;}
}
if(rx >= GetStgFrameWidth){
loop(12){
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 10);
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 10);
ObjShot_SetDeleteFrame(shot, 0);
angleR += 360/12;}
}
}
However, the bullets exploded instantly after being spawned. So, why didn't it work? It was a mistake to put while(rx > 0 && rx < GetStgFrameWidth){yield;} so far in the task. I just needed to put it one line after the task is declared, and it started to work!
And, after a few tweaks and fixes to prevent 0,0 spawning, I finally got my explosions.
Code: [Select]
task BulletCommandExplosionsSide(shot){
while(ObjMove_GetX(shot) > 20 && ObjMove_GetX(shot) < GetStgFrameWidth-20){yield;}
        // Replace Width with Height and GetX with GetY if you want it to explode if it touches the upper and lower screen instead of the sides.
let rx = ObjMove_GetX(shot);
let ry = ObjMove_GetY(shot);
let angleR = rand(0,360);
if(rx <= 20&&!Obj_IsDeleted(shot)){
        // Replace rx with ry if you want it to explode if it touches the upper and the lower screen instead of the sides.
loop(14){
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 5);
ObjShot_SetDeleteFrame(shot, 5);
angleR += 360/14;}
}
if(rx >= GetStgFrameWidth-20&&!Obj_IsDeleted(shot)){
        // Replace Width with Height if you want it to explode if it touches the upper and the lower screen instead of the sides.
loop(14){
CreateShotA2(rx, ry, 4, angleR, -0.1, 1, rand(30,32), 5);
ObjShot_SetDeleteFrame(shot, 5);
angleR += 360/14;}
}
}
And just wanted to point out, the "3" in the thread title is in Arabic, while the "II" in the old was in Greek. Just a meaningless observation.
also, yes, i did edit my post that many times because why not do everything wrong
« Last Edit: February 06, 2016, 10:30:19 am by iVAwalys »
Lunatic 1CCs: PCB, IN, PoFV, HSiFS
Extra: All except PC-98.

Oh hey look I can do DNH scrips.

Lollipop

  • stay woke
  • literally and figuratively dying
  • Nickname: TouhouGamer3141592
  • Gender: guess
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #7 on: February 06, 2016, 07:00:49 pm »
How do you make bullets fire not in a ring, but in a square?
Touhou 1CCS:
Hard: LLS, EoSD(NB), PCB(NB), IN, MoF, TD, DDC(NB), LoLK
Lunatic: EoSD, PCB, DDC, LoLK
Extra: LLS, EoSD, PCB(Extra&Phantasm), IN, MoF, SA, DDC, LoLK
Current Focus: 1cc SA Hard, or an Extra

Uruwi

  • Nightmare of Torrential Precipitation
  • 478 million goober
  • Nickname: blue_bear_94
  • Gender: Meme
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #8 on: February 06, 2016, 07:40:33 pm »
How do you make bullets fire not in a ring, but in a square?

Here.

Create four line segments for a square.
foo = foldl $ flip ($)
Highest difficulty 1CCed for each game, by shot type in the original order. (-: never 1CCed on any difficulty, or never used; E: easy, N: normal, H: hard, L / U: lunatic / unreal.)
EoSD [NNNE] PCB [EE--N-] IN [NEEE + Ex Border] PoFV [Mystia N, Mystia E no charge] MoF [EN--H- + Ex Marisa B] SA [N-----] UFO [----EN] TD [NENE] DDC [EE-EHE + Ex Marisa B & Sakuya A] LoLK [PD --N- Legacy ---N] EE [N- + Ex Yabusame] EMS [N-- + Ex Yabusame] RMI [NHN + Ex YaoSuku]
Avelantis (demo) Easy YuukiB 426,077,200

Drake

  • *
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #9 on: February 07, 2016, 06:17:56 am »
Um, that Wolfram link doesn't exactly give anything useful over here (misinterpreted query?), and even if it gave some equations it isn't necessarily obvious how you would implement it to do what you want, and that's still assuming they could follow the math required.



Where you start is that you want to get a line segment that describes one side. For a square this could be a line between points (1,0) and (0,1), but I'm continuing with general regular polygons. We're going to draw an n-sided polygon inside of the unit circle (radius is 1). Since going all the way around the circle is 360 degrees, splitting that into n sides means each corner is at a multiple of 360/n degrees. Since these corner points are supposed to lie on the unit circle, the first corner's coordinates are (cos(360/n), sin(360/n)), so the first side will be a line segment from (1,0) to (cos(360/n), sin(360/n)) (see here, which is one side of a triangle, n=3). Note that if n=4 for a square, (cos(360/n), sin(360/n)) = (cos(90), sin(90)) = (0,1).

Now you can convert this line to polar coordinates (which I didn't work through myself), and this ends up with r = cos(180/n) / cos(angle - (180/n)). However, this is only what we want for the single side, with angles from 0 to 360/n (see here). If you keep increasing the angle past that, the value for the radius r you get just keeps increasing, which is useless (see here). But the first side's angles work, so you can make sure you get the same radii for the other sides as the first side by throwing in a modulo (so the radius for angle=360/n+1 is the same as for angle=1, etc).
The equation is then r = cos(180/n) / cos((angle % (360/n)) - (180/n)). You can see this working here. Change the n=4 at the end to other values for different polygons.

Soooo, what this gives you is a base unit. You can think of the radius r values as the required speed for a bullet moving at a given angle, so that the overall shape moves at a speed of 1. If you want to rotate the shape, just change the angle in the equation to (angle - offset) instead.
« Last Edit: February 07, 2016, 06:32:01 am by Drake »

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by あかがし -

Lollipop

  • stay woke
  • literally and figuratively dying
  • Nickname: TouhouGamer3141592
  • Gender: guess
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #10 on: February 07, 2016, 05:04:14 pm »
Thanks!

But how would you shoot it? Can I have a code example from an actual script?

(Wow, I need to brush up on my advanced math skills)
« Last Edit: February 07, 2016, 05:07:05 pm by Lollipop »
Touhou 1CCS:
Hard: LLS, EoSD(NB), PCB(NB), IN, MoF, TD, DDC(NB), LoLK
Lunatic: EoSD, PCB, DDC, LoLK
Extra: LLS, EoSD, PCB(Extra&Phantasm), IN, MoF, SA, DDC, LoLK
Current Focus: 1cc SA Hard, or an Extra

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #11 on: February 07, 2016, 05:15:39 pm »
Thanks!

But how would you shoot it? Can I have a code example from an actual script?

(Wow, I need to brush up on my advanced math skills)

This depends on how you want to spawn the bullets. If you want to spawn the actual shape, then do as Drake said, calculating the x and y coordinates to spawn the bullet at. If you want to fire a shape from the boss (rather than spawning the shape around the boss), then that's going to require a slightly different type of math.

Drake

  • *
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #12 on: February 08, 2016, 02:48:46 am »
No, either way is fine, and I was actually specifically looking at shooting the shape outwards. Because this is already done in polar coordinates, it uses an angle (which you're already going to loop through just as though you were shooting a circle), and a "radius", which is given by the above equation. Like I wrote in the last post, you can interpret this radius as a speed and just plug it in, multiplying it for a faster shape. Basically "increase the radius of the shape by speed each frame".

Code: [Select]
function CreateShotShapeOA1(obj, sides, gap, speed, angle_off, graphic, delay){
let x = ObjMove_GetX(obj);
let y = ObjMove_GetY(obj);
let t = 0;
while(t < 360){
let r = cos(180/sides) / cos(((t - angle_off) % (360/sides)) - (180/sides));
CreateShotA1(x, y, r * speed, t, graphic, delay);
t += gap;
}
}

Meanwhile spawning the shape at a location and size is also a matter of multiplying ("give the shape a certain radius size") and converting back to x,y coordinates, so

Code: [Select]
CreateShotA1(x + size*r*cos(t), y + size*r*sin(t), s, a, g, d);
« Last Edit: February 08, 2016, 02:51:55 am by Drake »

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by あかがし -

Lollipop

  • stay woke
  • literally and figuratively dying
  • Nickname: TouhouGamer3141592
  • Gender: guess
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #13 on: February 08, 2016, 05:28:42 pm »
No, either way is fine, and I was actually specifically looking at shooting the shape outwards. Because this is already done in polar coordinates, it uses an angle (which you're already going to loop through just as though you were shooting a circle), and a "radius", which is given by the above equation. Like I wrote in the last post, you can interpret this radius as a speed and just plug it in, multiplying it for a faster shape. Basically "increase the radius of the shape by speed each frame".

Code: [Select]
function CreateShotShapeOA1(obj, sides, gap, speed, angle_off, graphic, delay){
let x = ObjMove_GetX(obj);
let y = ObjMove_GetY(obj);
let t = 0;
while(t < 360){
let r = cos(180/sides) / cos(((t - angle_off) % (360/sides)) - (180/sides));
CreateShotA1(x, y, r * speed, t, graphic, delay);
t += gap;
}
}

Meanwhile spawning the shape at a location and size is also a matter of multiplying ("give the shape a certain radius size") and converting back to x,y coordinates, so

Code: [Select]
CreateShotA1(x + size*r*cos(t), y + size*r*sin(t), s, a, g, d);

Thanks alot  :)
Touhou 1CCS:
Hard: LLS, EoSD(NB), PCB(NB), IN, MoF, TD, DDC(NB), LoLK
Lunatic: EoSD, PCB, DDC, LoLK
Extra: LLS, EoSD, PCB(Extra&Phantasm), IN, MoF, SA, DDC, LoLK
Current Focus: 1cc SA Hard, or an Extra

Lollipop

  • stay woke
  • literally and figuratively dying
  • Nickname: TouhouGamer3141592
  • Gender: guess
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #14 on: February 09, 2016, 04:05:46 am »
Is it possible to set a spawn point for the player i.e when you start the script, you start at the top of the screen or something like that.
Touhou 1CCS:
Hard: LLS, EoSD(NB), PCB(NB), IN, MoF, TD, DDC(NB), LoLK
Lunatic: EoSD, PCB, DDC, LoLK
Extra: LLS, EoSD, PCB(Extra&Phantasm), IN, MoF, SA, DDC, LoLK
Current Focus: 1cc SA Hard, or an Extra

Drake

  • *
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #15 on: February 09, 2016, 04:40:14 am »
GetPlayerObjectID() gets the player object ID, so you can use ObjMove_SetPosition() to move them at the start of the stage script.

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by あかがし -

Sphe

  • ¿ǝɹǝɥ ƃuıop ɐɾıǝS sı ʇɐɥM
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #16 on: February 09, 2016, 04:53:57 pm »
How can I modify an object  with a laser (ex. if a bullet is close to a laser, the bullet is destroyed)?
Spam :3
http://www.bulletforge.org/u/sphe

Normal 1CCs : PCB, IN, PoFV, MoF, UFO, TD, DDC.
Extra Clears: IN.

Badz

  • Nickname: -Badz
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #17 on: February 13, 2016, 06:34:06 pm »
How can I modify an object  with a laser (ex. if a bullet is close to a laser, the bullet is destroyed)?

IsIntersected_Obj_Obj might be the solution to your problem. You could use it in a loop to check if a bullet is intersecting with the laser, and do something (in this case, destroy the bullet) if that's the case.

Sphe

  • ¿ǝɹǝɥ ƃuıop ɐɾıǝS sı ʇɐɥM
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #18 on: February 14, 2016, 09:19:46 am »
Thanks :D And homing bullets? How do they work?
Spam :3
http://www.bulletforge.org/u/sphe

Normal 1CCs : PCB, IN, PoFV, MoF, UFO, TD, DDC.
Extra Clears: IN.

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
  • Staff
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #19 on: February 14, 2016, 09:32:33 am »
Thanks :D And homing bullets? How do they work?
Please define though for which purpose you want to use them. Do the bullets home accurately (like Reimu's homing amulets) or only upon firing (so the player can graze them). The latter is achieved by calculating the angle between the object bullet and player using: GetAngleToPlayer(obj); or if you're happy with manual labour using: atan2(y1-y2,x1-x2);  when setting the angle of the object bullet. Where x/y positions of the object + player is filled in.

Example:
Code: [Select]
let dir = GetAngleToPlayer(obj);
ObjMove_SetAngle(obj,dir);

or

let dir = atan2(GetPlayerY-ObjMove_GetY(obj),GetPlayerX-ObjMove_GetX(obj));
ObjMove_SetAngle(obj,dir);


Edit: Thanks Drake for reminding me GetAngleToPlayer(obj). Keep forgetting about that one.

« Last Edit: February 14, 2016, 10:11:12 am by Helepolis »
  • Helepolis' Siege Workshop

Sphe

  • ¿ǝɹǝɥ ƃuıop ɐɾıǝS sı ʇɐɥM
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #20 on: February 14, 2016, 10:52:39 am »
I want the homing bullets like Reimu´s ones, but less accurate.
Spam :3
http://www.bulletforge.org/u/sphe

Normal 1CCs : PCB, IN, PoFV, MoF, UFO, TD, DDC.
Extra Clears: IN.

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
  • Staff
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #21 on: February 14, 2016, 07:19:24 pm »
I am afraid my knowledge lacks on that part :ohdear: and hopefully someone else can come help out .




A question to the people who've been building full fledged games with menu system and everything: Did you manage to successfully implement a continue system?

As far as my research, testing and analysing other full fan games such as well known MPP, RSS and BSM, I have to conclude it is impossible to build a continue system using the functions ph3 offers. Things like GetStageSceneState cannot be called from a Stage Script and GetPlayerState cannot be called outside a Stage Script.

Even thinking of certain detours results in a dead-end. At least, that is my personal conclusion.

So I am curious if anybody successfully managed to achieve this and what did you use to avoid the StageSceneState or PlayerState from going to DED. (As you can't alter playerstate with any function)
  • Helepolis' Siege Workshop

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #22 on: February 14, 2016, 10:54:34 pm »

My continue system is an absolute mess, but I got it to work. It depends on NotifyEvents and CommonData.

In @Event, I use
Code: [Select]
    case(EV_PLAYER_SHOOTDOWN){//To disable continue system, block comment this case.
  if(GetPlayerLife<0){
      SetPlayerLife(0.123); //from Arby26
      ContinueSystem;
  }
    }
By setting the player life to be above 0, you prevent the script from ending. My Continue System task handles communication with the package - if the player has continues left and it's not a replay, the package is notified to Pause the Stage. From here, the player decides in the package which course they would like to take, and the stage is notified from the package via NotifyEvent.

Lollipop

  • stay woke
  • literally and figuratively dying
  • Nickname: TouhouGamer3141592
  • Gender: guess
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #23 on: February 14, 2016, 11:59:09 pm »
I want the homing bullets like Reimu´s ones, but less accurate.

I assume something like this would work:

Code: [Select]
loop{
      let dir = atan2(GetPlayerY-ObjMove_GetY(obj),GetPlayerX-ObjMove_GetX(obj));
      ObjMove_SetAngle(obj,dir);
      yield;
}

If you wanted it to be less accurate, there are two ways to go about this. (i think)

1. Have the angle change less frequently

Code: [Select]
loop{
      let dir = atan2(GetPlayerY-ObjMove_GetY(obj),GetPlayerX-ObjMove_GetX(obj));
      ObjMove_SetAngle(obj,dir);
      loop(n){yield;} // where n is a variable
}

2. Have the angle be slightly off

Code: [Select]
loop{
      let dir = atan2(GetPlayerY-ObjMove_GetY(obj),GetPlayerX-ObjMove_GetX(obj));
      ObjMove_SetAngle(obj,dir+rand(-1,1));
      yield;
}

Or you could do both.

I hope this helps.
Touhou 1CCS:
Hard: LLS, EoSD(NB), PCB(NB), IN, MoF, TD, DDC(NB), LoLK
Lunatic: EoSD, PCB, DDC, LoLK
Extra: LLS, EoSD, PCB(Extra&Phantasm), IN, MoF, SA, DDC, LoLK
Current Focus: 1cc SA Hard, or an Extra

Drake

  • *
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #24 on: February 15, 2016, 04:58:44 am »
Rather than changing less frequently, many (most?) dynamic "soft" homing implementations will change a set amount towards the direction of e.g. the player.

Code: [Select]
task homing_test{
let obj = CreateShotA1(192, 150, 4, 90, 77, 20);
let speed = 4;
let a = 90;
let a_spd = 5; // rate of angle change
while(!Obj_IsDeleted(obj)){
let angle_to = GetAngleToPlayer(obj);

// choose to increase or decrease angle depending on which is closer
let da = [a_spd, -a_spd][((a - angle_to) % 360) < 180];

// if the angles are close enough, just snap instead
if( (|a - angle_to|) < a_spd){
a = angle_to;
}else{
a = (a + da) % 360;
}

ObjMove_SetAngle(obj, a);

// optionally scale speed so it slows down to adjust angle
let scale = (|(a - angle_to) % 360 - 180|) / 180; // ranges [0,1]; is 1 when angles are equal
ObjMove_SetSpeed(obj, speed * scale^2); // squaring also optional, increases slowdown
yield;
}
}

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander
- original art by あかがし -

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
  • Staff
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #25 on: February 15, 2016, 06:24:48 am »
By setting the player life to be above 0, you prevent the script from ending. My Continue System task handles communication with the package - if the player has continues left and it's not a replay, the package is notified to Pause the Stage. From here, the player decides in the package which course they would like to take, and the stage is notified from the package via NotifyEvent.
Oh I see. That is quite a clever workaround. Because 0 lives in Touhou actually means it is your last life right? So preventing it from going to -1? Events are strong it seems, guess I have to call in its help again.

Any side effects of keeping never triggering the PlayerState or StageSceneState to PLAYER_DOWN? Like replays breaking. Desyncing, etc.

« Last Edit: February 15, 2016, 06:26:43 am by Helepolis »
  • Helepolis' Siege Workshop

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #26 on: February 15, 2016, 03:00:07 pm »
Oh I see. That is quite a clever workaround. Because 0 lives in Touhou actually means it is your last life right? So preventing it from going to -1? Events are strong it seems, guess I have to call in its help again.

Any side effects of keeping never triggering the PlayerState or StageSceneState to PLAYER_DOWN? Like replays breaking. Desyncing, etc.

I am unsure, but ExPorygon has a replay-safe continue system (which he uses for Ephemeral Unnatural Balance). So if you're interested in a system that definitely works with replays, you should consider PMing him. Personally, my system handles replays in a very haphazard way.

Rule of thumb is that if something is done in the actual play through that is not done exactly the same way in the replay, things will break. If PlayerState is never triggered in either the original play through nor the replay, it should be consistent.

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
  • Staff
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #27 on: February 15, 2016, 04:17:26 pm »
Will see if he shows up here. Though from what you explained and what I know:

A replay file is "cut/edited" based on the FinalizeStageScene function and the PauseStageScene. Technically a PauseStageScene is called when the user manually pauses it. Thus the replay knows how to handle the moment until PauseStageScene is set back to false

Currently my game calls the "ending scene" in two conditions:
- STAGE_RESULT_PLAYER_DOWN = FinalizeStageScene -> launches a Ending scene.
- Escape button pressed = PauseStageScene -> launches a Pause scene.

The stage closing happens in the Stage script with GetPlayerState.

So basically the STAGE_RESULT_PLAYER_DOWN should be never checked. The GetPlayerState should never be used to check and changed into sort of manual event / commondata I guess. Inside the package script, when the event/commondata is triggered, a forced PauseStageScene needs to be called inside the ending scene. As long as you don't spawn / set / modify anything during the pause, your replays should be in my opinion safe. Actually, PauseStageScene will pretty much make sure of this.

Seems I need to adjust my ending scene and inject a part of the pause scene into it.
« Last Edit: February 15, 2016, 04:19:44 pm by Helepolis »
  • Helepolis' Siege Workshop

iVAwalys

  • Nickname: Awalys
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #28 on: February 17, 2016, 08:04:42 pm »
What are the easiest Touhou bosses to replicate, or base on, in Danmakufu?
Lunatic 1CCs: PCB, IN, PoFV, HSiFS
Extra: All except PC-98.

Oh hey look I can do DNH scrips.

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #29 on: February 18, 2016, 05:47:08 am »
What are the easiest Touhou bosses to replicate, or base on, in Danmakufu?

Depends on what you mean by 'base on' or 'replicate', as well as the general availability of graphical assets. This question is extremely broad, but characters with simpler danmaku (Stage 1-2 bosses) without custom graphics (IE not Nazrin) tend to be less of a logistical hassle. It is for this reason that Rumia used to be one of the most commonly used bosses in early scripts.
 

SMF 2.0.15 | SMF © 2017, Simple Machines
Theme based on ModernDark64 design by BlocWeb
Page created in 0.094 seconds with 22 queries.