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

0 Members and 1 Guest are viewing this topic.

HumanReploidJP

  • The Scripter with Something of Common Sense
  • "Start the life of an idol! Let's get STAR~ted!"
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1800 on: July 30, 2019, 01:05:58 am »
I have something I didn't know:

You know the one where (2 or 10) bullets are orbiting around the boss or an another bullet, which I saw in most dnh scripts.
Can you explain how  in a way, and give an example code (must be a shot function ObjMove_AddPatternB2).

Let me know.  :)
MiraikeiBudoukan (Futuristic Vineyard) Game Concepts (WIP)
(Non-Touhou, yet bullet-hell-Inspirable (Like JynX). Don't get serious.)
  • HumanReploidJP's Youtube Channel

Lapis Lazuli

  • Neophyte
  • Nickname: ruri
  • Gender: Trans girl
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1801 on: July 30, 2019, 06:41:31 pm »
So, I don't exactly have the spoons to explain how you would do that with ObjMove_AddPatternB2 ALL IN ONE MESSAGE, though I will say that it would likely be much easier to do this by just manually setting the X and Y positions of the bullets. But IDK. We're going to set this up by making a simple pattern where, every 5 seconds, ten bullets are summoned around the boss, will orbit around said boss, and then fire out radially- or at least, how I would do it using ObjMove_AddPatternB2.

Quick warning that this will require not only knowledge of trigonometry, as you would expect, but ALSO calculus. Fortunately, the calculus part isn't THAT difficult to understand, hopefully, so even if you haven't taken a calculus class don't worry too much about it.

The first thing you'd want to do is set some kind of distance variable, for example 100. You're also gonna want to set some starting angle, and maybe make an array of ten (X, Y) points, all around the boss, using some ascent loops and trigonometry. I trust that this is something you're able to do on your own.

Now, one of the first things you'll want to do is make sure to... in a way, rig the bullets such that, no matter what, they are always the same distance from the boss. For the sake of our example, we're gonna have a loop set to run every 300 frames, and each frame it will update the position of all of the bullets. You'll do this with another ascent loop, by getting the angle from each player to the boss. You're gonna want to hold onto this array of angles, it will be helpful later. But then, with this angle, you'll set the position of each of the ten bullets to be equal to (dist * cos(angle) + ObjMove_GetX(objBoss), dist * sin(angle) + ObjMove_GetY(objBoss). Then, you might set it such that this only happens when a certain boolean is true, but you might be able to get around that. I hope you're understanding so far?

Now... for this next part, you're gonna need a bit of calculus. Remember that array of angles from the previous paragraph? Yeah, you need to hold onto them because at each timestep, you're going to want to use ObjMove_AddPatternB2 on each of these bullets, setting the X speed to be equal to dist * sin(angle), and the y speed to be dist * cos(angle). You might be thinking that I've mixed up the sines and cosines here, but in fact, I haven't. We're not using trigonometry to set POSITION, we're using it to set VELOCITY, which means we have to set the X and Y speeds to be equal to the DERIVATIVE of the X and Y positions, which is the X and Y velocities. And, in short...

d/dx(sin(x)) = cos(x), and

d/dx(cos(x)) = sin(x).

This will make it so that the X and Y positions of every bullet will follow a circle. (note: technically, the only reason we need to rig the distance of the bullets is because of the fact that we're doing this on a computer and not in real life, so every differential equation can only be so accurate since they're going in timesteps. It's complicated, but think of it as the bullets being a bit drunk and sorta stepping off the straight line path, so we need to keep them oriented.)

Fortunately, though, this should be aboooout all you'd need to do. I'm gonna post an example of actual code for this in the next post, so give me a moment. In the meantime, feel free to correct or verify anything here if you notice something wrong! ^u^

Lapis Lazuli

  • Neophyte
  • Nickname: ruri
  • Gender: Trans girl
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1802 on: July 31, 2019, 12:37:21 am »
Okay, so I found a way to make this work that doesn't use ObjMove_AddPatternB2. Lemme copy and paste it down here.

Code: [Select]
task fire(angle, dir)
{
if(ObjEnemy_GetInfo(objBoss, INFO_LIFE) <= 0){return;}

let dist = 100;
let bulNum = 10;
let time = 240;

let bx = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let by = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let bul = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
let ang = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
ascent(i in 0..bulNum)
{
ang[i] = angle + dir * i * 360/bulNum;
bx[i] = dist * cos(ang[i]) + ObjMove_GetX(objBoss);
by[i] = dist * sin(ang[i]) + ObjMove_GetY(objBoss);
bul[i] = CreateShotA1(bx[i], by[i], 2, ang[i], DS_BALL_M_BLUE, 20);
}

loop(time)
{
ascent(i in 0..bulNum)
{
ang[i] = ang[i] + 2 * PHI;
ObjMove_SetPosition(bul[i], dist * cos(ang[i]) + ObjMove_GetX(objBoss), dist * sin(ang[i]) + ObjMove_GetY(objBoss));
ObjMove_SetAngle(bul[i], ang[i]);
}

yield;
}
}

Again, since you said it needed to use ObjMove_AddPatternB2, I can still create a solution that uses it, but I personally think this seems a lot more elegant, and is sort of just how i naturally ended up making the spell. Plus, ObjMove_AddPatternB2 versions of the pattern have the caveat that they need to stay still unless you add the X and Y speed components to the rotating bullets as a vector, which is... I don't even want to get into that. This just seems like a lot less work, but if it's not acceptable for your purposes, let me know.

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1803 on: July 31, 2019, 02:20:53 pm »
If you really just want objects to move relative to another object, you can just keep track of that other object.

e.g. rotate about the boss.

Given n objects rotating:

Code: [Select]
ascent(i in 0..n) {
    CreateRotatingObj(objBoss, i, n, r);
}

task CreateRotatingObj(parent, ID, numinring, radius) {
    let offset = ID * 360/numinring;
    let obj = CreateShotA1(ObjMove_GetX(parent) + radius*cos(offset), ObjMove_GetY(parent) + radius*sin(offset), 0, 0, 0, 0);
    let objcount = 0;
    while(!Obj_IsDeleted(parent)) {
        ObjMove_SetX(obj, ObjMove_GetX(parent) + radius*cos(offset + objcount);
        ObjMove_SetY(obj, ObjMove_GetY(parent) + radius*sin(offset + objcount);
        objcount += 1;
        yield;
    }
    Obj_Delete(obj);
}
« Last Edit: July 31, 2019, 02:22:33 pm by Sparen »
  • AFCDTech

Lapis Lazuli

  • Neophyte
  • Nickname: ruri
  • Gender: Trans girl
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1804 on: August 11, 2019, 02:32:20 am »
Hey, can someone help me?
I've got a bunch of single scripts for a Momiji boss fight, but I'm having trouble stitching them together into a plural script. All eight of the singles work perfectly as intended, but when I run them all as a plural, the game just crashes on me, without even giving so much grace as an error message. Can someone help me find out what's going on?

Here's the code:

Code: [Select]
#TouhouDanmakufu[Plural]
#ScriptVersion[3]
#Title["Momiji Fight"]
#Text["for kiiro"]
@Event
{

}
@Initialize
{
    TPlural;
}
@MainLoop
{
    yield;
}

task TPlural
{
    let dir = GetCurrentScriptDirectory();
    let obj = ObjEnemyBossScene_Create();
    ObjEnemyBossScene_Add(obj, 0, dir ~ "momiji 1.txt");
    ObjEnemyBossScene_Add(obj, 0, dir ~ "momiji spell 1.txt");
    ObjEnemyBossScene_Add(obj, 1, dir ~ "momiji 2.txt");
    ObjEnemyBossScene_Add(obj, 1, dir ~ "momiji spell 2.txt");
    ObjEnemyBossScene_Add(obj, 2, dir ~ "momiji 3.txt");
    ObjEnemyBossScene_Add(obj, 2, dir ~ "momiji spell 3.txt");
    ObjEnemyBossScene_Add(obj, 3, dir ~ "momiji spell 4.txt");
    ObjEnemyBossScene_Add(obj, 4, dir ~ "momiji spell 5.txt");
    ObjEnemyBossScene_LoadInThread(obj);
    ObjEnemyBossScene_Regist(obj);
    while(!Obj_IsDeleted(obj)){
        yield;
    }
    CloseScript(GetOwnScriptID());
}
 

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