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

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1140 on: April 11, 2018, 04:55:29 PM »
Magikrow, I am suspecting that you're very new to Danmakufu in general and you're already attempting to use someone else's code without actually understanding what you're doing. Dialogues and circular lifebars are intermediate to expert level scripting effects. Unless they are really dummy-proof prepared and offered, you're not going to get it right.

That dialogue code paste is never going to work because it is incomplete. It is an example, not a ready to use script. The initial dialogue you got is a playable script from Python's. The author probably integrated the dialogue functionality it into its own work. He/she already understands how to work it out.


Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1141 on: April 12, 2018, 12:42:26 AM »
Magikrow, I am suspecting that you're very new to Danmakufu in general and you're already attempting to use someone else's code without actually understanding what you're doing. Dialogues and circular lifebars are intermediate to expert level scripting effects. Unless they are really dummy-proof prepared and offered, you're not going to get it right.

That dialogue code paste is never going to work because it is incomplete. It is an example, not a ready to use script. The initial dialogue you got is a playable script from Python's. The author probably integrated the dialogue functionality it into its own work. He/she already understands how to work it out.
Yes I am very new, however I did get the circular lifebar to work. Dialogue really seems to be the only thing I've had a big struggle with working with danmakufu. Is there somewhere I can learn more about it?

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1142 on: April 12, 2018, 06:06:56 AM »
Everybody can get eventually something to work by lots of trying, that still doesn't though makes you understand what is exactly going on. Well, that is eventually up to you whether you're fine with that or not.

Dialogues are a combination of 2D Sprites, drawing/manipulating these and utilizing Tasks/Function. These topics are covered in Sparen's Danmakufu ph3 tutorials (also listed in the information thread). My suggestion would be to go through these topics to get a better understanding of what you're doing and when something fails to work, you understand what is/might be causing it.

Of course you're always free to ask for help here. But when you do, you need to provide us information such as the error message. And if something freezes, then we need to see your script files. You can post these in Pastebin.
« Last Edit: April 12, 2018, 06:09:01 AM by Helepolis »

Drake

  • *
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1143 on: April 15, 2018, 05:35:25 AM »
So, I know Danmakufu is kinda bad about arrays. What I'm not sure of is the relative speed of common data and object dictionaries. My guess is it's at least somewhat slower than just using a variable, but I'm unsure how it compares to arrays.
Warning, incoming wall

You're essentially asking if using a hash table to mimic an array is better than using an array for array-like operations. Maybe if there were something actually problematic with the array implementation, but there isn't any huge problem like that. Arrays aren't slow. They're O(1) access as expected. There are still some lingering misconceptions about this because back in 0.12m arrays were not O(1) access.

Meanwhile, hash tables are often internally implemented using arrays to begin with. There would have to be some additional factors in play for a straightforward array implementation to be worse than a hash table mimicking an array. Moreover, this ignores any extra work that has to be done to shape the input. ObjVals and CommonData both map from strings only, so at the very minimum you have to convert the numbers to strings which is at least O(k) in the number of digits k.

CommonData in particular would be a bad idea for namespace reasons alone. This is equivalent to using global variables everywhere and is incredibly bad practice. Additionally, if you use CommonData to work with large pseudo-arrays and try to use the debug window you may be met with screaming lag.


I think it can be assumed that DNH doesn't use dynamically-sized arrays due to having no mechanism to grow/shrink freely. Instead you just concatenate arrays, which (probably) means when you do a concatenation you're allocating memory for the new array then copying them over. If you have any code that grows an array element-by-element this will be very inefficient. However, because you can't instantiate arrays of a given size (which might have to do with them being of variable type and structure until assigned) all you can do is use a better algorithm, like the following (which is O(log n) rather than O(n) in time and wastes O(n) space instead of O(n2)):

Code: [Select]
function array(size, value){
let a = [value];

while(length(a) < size * 2){
a = a ~ a;
}

return a[0..size];
}

Also, because you can use this method to instantiate arrays of a certain size, but cannot do so with a hash table, creating a hash table mimicking an array of a fixed size will be significantly slower even ignoring the overhead explained above.

What hash tables do have over arrays in this sense is their variable size, but hash tables still have to resize internally when filled up a certain amount, and you can just as well do this with arrays in order to create dynamic arrays, but I'm not going to get into that.

Anyways, the majority of latency people tend to find with arrays in DNH is from them trying to create and manipulate arrays as though they are dynamic when they are not. If you ignore the fact that you can't simply instantiate an array with a given size they are just fine.



Now for some problems with your tests. First is that you have no proper control tests. You don't factor in what could be overhead and what is inherent to the method used. Not only does this mean you can't tell what is/isn't overhead, but also you can't properly measure and compare each method.

You use FPS to measure. While I've done this previously, this is a bad measure because it stays at 60 until it slows down and is not necessarily linear decreasing past that. It's not a very reliable way to compare, especially for reasons I'll give later.

You use only arrays of length 10. Although theoretically, if you assume all of the test method accesses are O(1) but with different constant factors, the size of the structures shouldn't be important. However, not only should you not assume this to begin with, but as explained above, the pseudo-array hash table access will take O(k) time for the digit length k. So with a pseudo-array of length 20000, accessing element 10000 will take slightly longer than element 0 because of the string conversion.

You use ObjVal on the empty string. I'm not sure why you did this but I really hope you don't use that in any other code. Strings are not objects that you can use these functions on. While it might appear that it's working successfully, what is happening is that putting a string in place of the object ID ends up falling back to the value 0 instead. So you are actually manipulating the object values of object ID 0. Check this example:

Code: [Select]
let a = "a";
Obj_SetValue(a, "key", "a:val");
let b = "b";
Obj_SetValue(b, "key", "b:val");
Obj_GetValueD(a, "key", "a:null"); // => "b:val"
Obj_GetValueD(b, "key", "b:null"); // => "b:val"
Obj_GetValueD(0, "key", "0:null"); // => "b:val"

Lastly you're doing a hell of a lot of branching unnecessarily by using Arr_Set/Get for every single iteration. This is going to inflate times and the differences between each method will become muddy, especially considering you don't have controls that would expose the overhead. This is further compounded by all the extra stuff you're doing for each iteration: access the variables arr and i, create a variable v and set it, access all three of those again, add 1, (do a set op), access i and size, add 1, do a modulo operation, and set i again. This is a lot of overhead that you're introducing for each iteration that will likely dominate runtime.



So basically this got me invested enough, when I've done these tests similar to this in the past, that I went back and refined them even more.

Here is the code: https://gist.github.com/drakeirving/a99d768beca4c69d7c44050620777b2f

Here are some results:

https://drive.google.com/file/d/1QmxcjFVENOtCjK8cxksA-N1K0WTjZvVr/view



Notes:

As I comment in the code, for a given number of iterations, putting in more iterations per frame asymptotically speeds up the process. So what you were doing, where you have a certain number of iterations per frame, each frame you wait to update the screen increases runtime. With the same number of iterations, as you perform more iterations per frame while decreasing the number of frames to run, it gets faster and faster. So, the optimal way to test is to not yield whatsoever and only update the screen when the run is done.

DNH gives you the GetStageTime function to work in milliseconds. You can easily just time using this and it's much more accurate than checking FPS values; plus it is cumulative so it represents the whole test while tracking FPS has to be sampled at certain points in time. Doing it this way also allows you to test without needing to update the screen.

AddScore() has less overhead than incrementing a variable, so I use this. It's the operation with the least overhead I bothered testing that demonstrably does something.

Using CommonData has more overhead than AreaCommonData because of the extra string concatenation, but as shown by the controls, the actual access is the same. Meanwhile, ObjVals are inherently faster, but still far slower than array access even when ignoring the overhead.



tl;dr use arrays when you want to use arrays. Use efficient methods if you need to make arrays of a certain size rather than just concatenating each element.

And use ObjVals over CommonData when you need to use dictionaries unless you actually need to use the global properties of CommonData.
« Last Edit: April 16, 2018, 02:01:26 AM by Drake »

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

R. P. Genocraft

  • Craftsman of absolute unpredictability
  • Boundary of productive and lazy
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1144 on: April 18, 2018, 06:19:11 PM »
How do you get info of a bullet ID such as delay color from within the script?

ExPorygon

  • Veteran Danmakufu Scripter
  • Currently working on a full Touhou fangame!
    • Ephemeral Entertainment
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1145 on: April 18, 2018, 07:37:49 PM »
How do you get info of a bullet ID such as delay color from within the script?
You can use the GetShotDataInfoA1 function. It needs the shot graphic id that you want to look up, and the type of information you're looking for. In your case that would be INFO_DELAY_COLOR.

So something like this:
let RGB_array = GetShotDataInfoA1(1,INFO_DELAY_COLOR);
Just replace 1 with whatever shotsheet graphic id you want the info for.

Drake

  • *
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1146 on: April 19, 2018, 12:25:03 AM »
Note there are three arguments e.g. GetShotDataInfoA1(id, TARGET_ENEMY, INFO_DELAY_COLOR) where you distinguish between player and enemy shot graphics.
You can also get the shot graphic ID with ObjShot_GetImageID(obj).

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

Andi

  • World's Gayest Danmaku
  • PlaySE("./se/Nyaa.wav");
    • 2hu blog
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1147 on: April 20, 2018, 01:56:32 AM »
There are still some lingering misconceptions about this because back in 0.12m arrays were not O(1) access.
So THAT's why I was thinking they were slow. I must have heard that somewhere and not realized it was outdated.
Now for some problems with your tests.
Yeah... Well, they weren't really intended to be exhaustive, just trying to get a general idea, but you're right, it was pretty slapdash.
(The empty string thing was just to see what would happen, and since it didn't break anything I forgot to change it back.)
AddScore() has less overhead than incrementing a variable, so I use this. It's the operation with the least overhead I bothered testing that demonstrably does something.
Huh. How does that work? I would have thought it would still just be incrementing a variable.



So the distortion effect in SampleE02, is there a way to do that with a shader instead of breaking the image up into a spritelist? ...Preferably with working example because I'm still just beginning to fumble my way through figuring out HLSL.
Literally everything in this script will crash and burn.
1CC tracker

Fujiwara no Mokou

  • Hourai Incarnate
  • Oh, so this trial of guts is for ME?
    • Profile
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1148 on: April 20, 2018, 04:12:33 AM »
Huh. How does that work? I would have thought it would still just be incrementing a variable.

If it weren't being done in a virtual machine, you'd be right. But that's not the case here. Danmakufu uses an abstract data type to store script data. This data type must first be deduced in runtime by the virtual machine and operations such as addition must be done in that script environment as well. To do this, it must allocate a new abstract datatype and assign your to it in the stack, before performing a callback function that does the addition operation. Then the 'adding' variable must be freed from the VM stack each time you do something as simple as that. Oh, and since you're doing this in a VM, there is an array of instructions and a pointer that is iterated to perform all of this each step of the way.
The addScore() function uses a different scheme, however. Since it's a native function, the operation is likely done in pure C/C++ with a true integer at some point, and the number of (assembly-language) instructions to actually increment it is far fewer.

TLDR; C++ is faster than Danmakufu.

Drake

  • *
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1149 on: April 21, 2018, 08:28:47 AM »
So the distortion effect in SampleE02, is there a way to do that with a shader instead of breaking the image up into a spritelist? ...Preferably with working example because I'm still just beginning to fumble my way through figuring out HLSL.
What part of it? If it's just the distortion, then SamplePS03 already does mostly that. The darkness thing also wouldn't be too difficult, it would just require modifying the pixel colors to be the regular color minus a function of distance from the center, which SamplePS03 already uses.

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

Andi

  • World's Gayest Danmaku
  • PlaySE("./se/Nyaa.wav");
    • 2hu blog
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1150 on: April 21, 2018, 07:04:33 PM »
If it's just the distortion, then SamplePS03 already does mostly that.
Whoops, I remembered there was something to do that in the samples and stopped checking when I found one in E02. Never mind!


Every so often when I go to start a script, it just hangs with the log saying nothing but
Code: [Select]
2018/04/21 18:37:37.842 読み込み完了待機(ScriptManager):(something like "waiting to finish reading") every few seconds.
Why does this happen and is there anything I can do about it? Is it some inherent issue with Danmakufu, an issue with the default package, something I'm doing?
« Last Edit: April 21, 2018, 10:44:23 PM by Andi »
Literally everything in this script will crash and burn.
1CC tracker

JDude :3

  • tururu
  • boy with code
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1151 on: April 22, 2018, 01:16:13 PM »
How can I make multiphased nos and spells? Like Reimu in CtC
I know I've already asked this but I didnt understand it, and also lost he post... :blush:
"dnh is hard" - said no one
"dnh is bullshit" - everyone making a creative pattern

CrestedPeak9

  • Fangame Advocate
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1152 on: April 22, 2018, 03:23:42 PM »
How can I make multiphased nos and spells? Like Reimu in CtC
I know I've already asked this but I didnt understand it, and also lost he post... :blush:

There are three steps to multiphased attacks.
1) Check boss health remaining. You can do this with ObjEnemy_GetInfo(objBoss, INFO_LIFE).
2) (If necessary) cancel previous phases by checking if health is below a certain threshold. Do something like if(health>threshold){Shoot;}
3) Fire added phases by checking if health is below a certain threshold. Do something like if(health<threshold){Shoot;}

You can also do this with spell timers to create timeout phases/multiphased timeout spells, by doing ObjEnemyBossScene_GetInfo(objScene, INFO_TIMER).

People might get angry at me, but I like to set health/time as a global variable and set it per frame in MainLoop.
Lunatic 1cc: EoSD, PCB, IN, MoF, TD, DDC, LoLK, HSiFS, WBaWC

Andi

  • World's Gayest Danmaku
  • PlaySE("./se/Nyaa.wav");
    • 2hu blog
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1153 on: April 22, 2018, 07:10:02 PM »
I'm trying to clear up some of the clutter/bugs in my environment regarding magic circles, spellcard bonuses, etc. In the process of doing so, I've discovered that I apparently don't actually know how to use GetScriptResult properly. I tried looking through the code for examples, but I couldn't actually find anywhere it was being used.
Here's the function I'm working on to serve as a one-stop shop for all my notifying needs:
Code: [Select]
function Notify(type,event,args){
let id = GetScriptID(type);
if(id==ID_INVALID || type==SCRIPT_ALL || ((type==SCRIPT_PACKAGE)!=(GetOwnScriptID==GetScriptID(SCRIPT_PACKAGE))) ) {
NotifyEventAll(event,args);
}
else{
NotifyEvent(id,event,args);
return GetScriptResult(id);
}
}
Currently, it does not work. Specifically, it doesn't return anything, and I get a "trying to use a variable that has not been set" when I try to use the result.
The same thing happens when I try doing it without the function:
Code: [Select]
NotifyEvent(GetOwnScriptID,EV_REQUEST_IS_DURABLE_SPELL,[]);
let foo = GetScriptResult(GetOwnScriptID);
WriteLog(foo); //errors
Yielding between notifying the event and getting the result didn't help. I also tried notifying a different script (I added a case to my system script to test) with the same result.

So, I guess my question is "how the heck do I actually get something back from GetScriptResult?"
Literally everything in this script will crash and burn.
1CC tracker

Spacechurro

  • FiteMe;
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1154 on: April 22, 2018, 09:16:43 PM »
Hey guys, it's been a long while since I've been here, you probably don't even remember me but, I've gotten back into the roll of danmaku making and was having trouble with rolling a text that tells the player what the name of the spell is being cast. The Image works fine, but the text doesn't even appear. DanmakufuPH3

Code: [Select]
task SpellCast(Text){

let slideX = GetScreenWidth;
let slideY = 0;
let slidetxtX = 0;
let slidetxtY = GetScreenHeight/2;
let SpAnFr = 0;
let Alpha = 0;
let ZAngle = 0;
let obj = ObjPrim_Create(OBJ_SPRITE_2D);
let txtobj = ObjText_Create();
//==========================================
ObjText_SetFontBorderType(txtobj,BORDER_FULL);
ObjText_SetFontSize(txtobj,10);
Obj_SetRenderPriority(txtobj,1);
ObjRender_SetX(txtobj,slidetxtX);
ObjRender_SetY(txtobj,slidetxtY);
ObjText_SetFontColorTop(txtobj,0,255,0);
ObjText_SetFontColorBottom(txtobj,0,255,0);
ObjText_SetFontBorderColor(txtobj,1,100,1);
ObjText_SetHorizontalAlignment(txtobj,ALIGNMENT_CENTER);
ObjText_SetSyntacticAnalysis(txtobj,true);
ObjText_SetAutoTransCenter(txtobj,true);
ObjText_SetFontBorderWidth(txtobj,2);
ObjText_SetText(txtobj,Text);
//============================================
ObjPrim_SetTexture(obj,imgSpell1);
ObjSprite2D_SetSourceRect(obj,0,0,1000,1000);
ObjSprite2D_SetDestCenter(obj);
ObjRender_SetBlendType(obj,BLEND_ALPHA);
ObjRender_SetAlpha(obj,Alpha);
ObjSprite2D_SetDestRect(obj, -500, -500, 500, 500);
ObjRender_SetScaleXYZ(obj,0.5,0.5,0);
ObjRender_SetAngleXYZ(obj,0,0,ZAngle);
Obj_SetRenderPriority(obj,0.95);
ObjRender_SetX(obj,slideX);
ObjRender_SetY(obj,slideY);

while(!Obj_IsDeleted(txtobj)){

ObjRender_SetX(obj,slideX);
ObjRender_SetY(obj,slideY);
ObjRender_SetX(txtobj,slidetxtX);
ObjRender_SetY(txtobj,slidetxtY);
ObjRender_SetAlpha(obj,Alpha);
ObjRender_SetAngleXYZ(obj,0,0,ZAngle);

if(SpAnFr<30){
slideX-=10;
slideY+=8;
slidetxtX+=(GetScreenWidth/2)/30;
Alpha+=255/30;
ZAngle-=(360/30);
}
if(SpAnFr>30&&SpAnFr<120){
slidetxtX+=0.1;
ZAngle-=0.2;
slideX-=0.1;
slideY+=0.1;
}
if(SpAnFr>120){
slidetxtX+=((GetScreenWidth/2)/30)-30;
slidetxtY-=((GetScreenHeight/2)/30)-30;
slideX-=10;
slideY+=8;
Alpha-=255/30;
ZAngle-=(360/30);
}
if(SpAnFr>300){
Obj_Delete(obj);
}
if(ObjEnemy_GetInfo(bossObj, INFO_LIFE) <= 0){Obj_Delete(txtobj);}
SpAnFr++;
yield;
}

}


The plan is that I can reuse it and plant whatever text I what appearing there. It's been a while since I've programmed so i'm probably missing some obvious stuff.
task FiteMe{
    loop{
          let m = atan2(MyFistY-YourFaceY,MyFistX-YourFaceX);
          Punch01(GetMyX,GetMyY,100,m,REDFIST01,0);
          wait(1);  }     }

Andi

  • World's Gayest Danmaku
  • PlaySE("./se/Nyaa.wav");
    • 2hu blog
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1155 on: April 22, 2018, 10:48:48 PM »
The Image works fine, but the text doesn't even appear.
In order to use a horizontal alignment other than ALIGNMENT_LEFT, you need to use ObjText_SetMaxWidth first. Otherwise it doesn't know where the right boundary is, so how can it center it between the left and right boundaries?

Also, I would recommend putting that in a library instead of duplicating the code like it sounds like you're planning. Just put it in a file somewhere and put #include "./Library/Cutin.txt" (or whatever the path is) in any file you want to be able to use it.

Or better yet, instead of including it directly make one file that includes it, and include that file.
Index.txt:
Code: [Select]
#include "./Library/Cutin.txt"
#include "./Library/Resources.txt" //et
#include "./Library/Functions.txt" // cetera
Other_Script.dnh:
Code: [Select]
#include "./Index.txt"This way you can change what you're #including all in one place and you don't have to clutter up your scripts with a dozen #includes each.
« Last Edit: April 22, 2018, 10:58:56 PM by Andi »
Literally everything in this script will crash and burn.
1CC tracker

Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1156 on: April 22, 2018, 11:45:57 PM »
Hi people!
I want to make or understand a lot of things present in danmakufu, like:
  • How to do a circular boss life
  • And how to make life and spell piece
  • How to scale up the "out" of a item
Can some of you help me with that stuff?
(Already found the answer for the boss life)
« Last Edit: April 23, 2018, 01:05:22 AM by Zinochan »

Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1157 on: April 23, 2018, 02:21:53 AM »
Hello!
I have just a simple question. How would you make danmaku with a zig-zaggy pattern?
Thanks!

Andi

  • World's Gayest Danmaku
  • PlaySE("./se/Nyaa.wav");
    • 2hu blog
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1158 on: April 23, 2018, 03:08:42 AM »
2. how to make life and spell piece
So there are a few different parts to that:
  • Making the actual item that will add a life/spell piece. Probably the easiest part, it sounds like you've got that covered already based on your (3).
  • Making life/spell pieces actually function (add a life/spell after collecting enough). This is also relatively easy. There are a few approaches; I just add a fraction of a life/bomb (and multiply/round/divide by the number of pieces per life/spell to avoid floating point errors) and check if the integer part increased to decide which sound effect to play. Others use common data instead of the actual life/spell count.
  • Display life/spell pieces nicely. This is probably the hardest part if you haven't already set up your system script to display lives/bombs as sprites instead of numbers. If you have, it's a matter of displaying a different sprite for the fractional part. Here's the code I use to do it; your Default_System.png won't have the images I'm using so you'll need to mess with that.
3. How to scale up the "out" of a item
I think you'd have to scale it up in the actual image.



I have just a simple question. How would you make danmaku with a zig-zaggy pattern?
Depends what you mean by "zig-zaggy". If you mean zig-zaggy like, say, Nue's snakes, you could do something like:
Code: [Select]
let dir = 1;
while(!Obj_IsDeleted(shot)){
ObjMove_SetAngularVelocity(shot,0.1*dir);
//or ObjMove_SetAngle(shot,a0+45*dir);
wait(30); dir*=-1;
}



Drake/Sparen/Helepolis/etc, I posted a few questions earlier - they've kind of been swallowed up by these other questions, so I figured I should say something or you probably wouldn't see them.

Actually, I've got another one as well. When you set the render scale of a shot, that doesn't change its hitbox, right? How do you change its hitbox when you scale it?
« Last Edit: April 23, 2018, 03:12:42 AM by Andi »
Literally everything in this script will crash and burn.
1CC tracker

Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1159 on: April 23, 2018, 03:46:49 AM »
@Andi Thank you! I'll keep that code in note but I meant danmaku that changes directions (like from left to right) continuously.  An example would be something like this:
https://i.ytimg.com/vi/oJZPZ6gETbQ/maxresdefault.jpg

Spacechurro

  • FiteMe;
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1160 on: April 23, 2018, 04:57:18 AM »
@Andi Thank you! I'll keep that code in note but I meant danmaku that changes directions (like from left to right) continuously.  An example would be something like this:
https://i.ytimg.com/vi/oJZPZ6gETbQ/maxresdefault.jpg

If you want a way to move your object it's good to look at stuff like graphs in math. If you want something to "float" I usually add something with a cos or sin along with frame for example:
Code: [Select]
task example{
    let Frame=0;
    let y=12;
    loop(){
        Set_ObjY(obj,y);
        y+=sin(Frame);
        Frame++;
        wait(1);
    }
}
This doesn't reflect any existing functions in danmakufu and is just an example of using sin or cos to move an object up and down or left to right smoothly and repetitively.
But it really helps to figure loops out by doing calculations on graphs.
But also, that's for smooth movement.

If you want quit jaggered movements, you can just use x+=1;
and then when enough frames passes you can change it to x-=1 in another if statement.
Example:
Code: [Select]
task shoot{
    let Frame=0;
    let a=12;
    while(!Obj_IsDeleted(obj)){
        Set_Angle(obj,a);
        if(Frame<60){a+=1;}   //adding angle addition for current bullet
        if(Frame>60&&Frame<120){a-=1;}   //switching angle addition for current bullet
        if(Frame>120){Frame=0;}  //Resetting frame count
        Frame++;
        yield;
    }
}

Sparen's got a lot of very helpful tuts on here:
http://sparen.github.io/ph3tutorials/ph3tutorials.html

almost a whole directory and is still being updated.

I hope I helped!
« Last Edit: April 23, 2018, 05:04:07 AM by Spacechurro »
task FiteMe{
    loop{
          let m = atan2(MyFistY-YourFaceY,MyFistX-YourFaceX);
          Punch01(GetMyX,GetMyY,100,m,REDFIST01,0);
          wait(1);  }     }

Drake

  • *
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1161 on: April 23, 2018, 10:14:58 AM »
@Andi Thank you! I'll keep that code in note but I meant danmaku that changes directions (like from left to right) continuously.  An example would be something like this:
https://i.ytimg.com/vi/oJZPZ6gETbQ/maxresdefault.jpg
That pattern from Shuusou Gyoku doesn't have bullets that change direction, it's the firing angle that changes direction, and the bullets themselves just go straight but decelerate. If you can fire bullets with the angle increasing, you can do the same while decreasing it instead, and alternate between them for the intended effect. Here's an implementation of this, but note I took a shortcut for increasing/decreasing the angle.

Code: [Select]
let num_waves = 4;
let num_lines = 11;
let min = 0;
let max = 30;
let inc = 3;
let shots_per_wave = (max-min) / inc;
let z = min;
loop(num_waves){
  loop(shots_per_wave){
    ascent(i in 0..num_lines){
      CreateShotA2(192, 200, 4, (i*360/num_lines) + z, -0.1, 1.5, SHOT_RING_RED, 0);
    }
    z += inc;
    if(z <= min || z >= max){ inc *= -1; }
    loop(6){yield;}
  }
}

(Really this showcases cleaner pattern design than trying to do something fancier with complex bullet movement, since the unfolding of the danmaku and how the player will experience it is what is important, but that's an aside)
« Last Edit: April 23, 2018, 10:20:48 AM by Drake »

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

Drake

  • *
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1162 on: April 23, 2018, 10:20:12 AM »
Actually, I've got another one as well. When you set the render scale of a shot, that doesn't change its hitbox, right? How do you change its hitbox when you scale it?
Would have to do it manually. You can use ObjShot_GetImageID to get the shot graphic ID, GetShotDataInfoA1 to get the collision, and ObjShot_SetIntersectionCircleA1 (or A2 if necessary) to set the hitbox each frame. If you wanted to you could neatly package that all up into its own function like ObjShot_SetScale but I'm too lazy to do it right now.


GetScriptResult
The first trap is that you expect GetScriptResult to obtain the value that you've set with SetScriptResult as though it were returning from a function. If you're unaware of how the event scheduler works, when you trigger an event, it doesn't just run the script's event loop at that moment. (Note, the following is my interpretation) Instead, notifying an event adds the relevant information to a large queue of all events. On a given frame, a global event scheduler (I'm assuming it's global) takes the whole queue of events being triggered and messages the event data to the relevant scripts, and on that frame, that script's @Event routine will be run once for every new event put in that script's event queue. (That or there's another mechanism for scripts to add events to all other scripts' event queues somehow. Or, all events are done together outside of the individual script flow, but I doubt that.)

Because this is how event scheduling works, obviously if you use NotifyEvent somewhere, there is nothing to come back from GetScriptResult, as no events have actually been handled yet. Meanwhile, you could also question how you would get any useful information set with SetScriptResult; wouldn't two SetScriptResult calls overwrite each other? The answer is yes, if you do SetScriptResult(10); SetScriptResult(20);  then GetScriptResult(id) will return 20. That being said, as far as events go it doesn't even matter, because using SetScriptResult in @Event will not affect the value of GetScriptResult outside of @Event! I don't really know why, because script results do persist over time, but that's how it is. In other words, the second trap is expecting that SetScriptResult does anything useful for user events at all.

Note that the predefined events that make use of SetScriptResult to set values like life and the timer are only triggered at the beginning of the script load (not run) so clearly they have some special processing.

What you can do though, is use GetScriptResult(A) from a script B, even if A was closed. So more like the name suggests, it can be used as a "return value" for whole scripts. This is useful for game structure, and is already used for things like pause scenes and end scenes.
« Last Edit: April 23, 2018, 12:43:40 PM by Drake »

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

Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1163 on: April 23, 2018, 05:54:42 PM »
So there are a few different parts to that:
  • Making the actual item that will add a life/spell piece. Probably the easiest part, it sounds like you've got that covered already based on your (3).
  • Making life/spell pieces actually function (add a life/spell after collecting enough). This is also relatively easy. There are a few approaches; I just add a fraction of a life/bomb (and multiply/round/divide by the number of pieces per life/spell to avoid floating point errors) and check if the integer part increased to decide which sound effect to play. Others use common data instead of the actual life/spell count.
  • Display life/spell pieces nicely. This is probably the hardest part if you haven't already set up your system script to display lives/bombs as sprites instead of numbers. If you have, it's a matter of displaying a different sprite for the fractional part. Here's the code I use to do it; your Default_System.png won't have the images I'm using so you'll need to mess with that.
I think you'd have to scale it up in the actual image.
Thanks Andi! You've helped me a lot with this post.
The code that you've posted took me some to figure out what to do to make that the life/spell appears correctly, but when I discovered what was going on I was like  :o .
« Last Edit: April 23, 2018, 05:56:39 PM by Zinochan »

Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1164 on: April 23, 2018, 11:53:21 PM »
Also, when I collect a life item, it doesn't add a life.
Here is the code:
Code: [Select]
case(EV_GET_ITEM){
if(GetEventArgument(0)==ITEM_LIFE_B_P){//life piece
SetPlayerLife(GetPlayerLife+1);
}
}
« Last Edit: April 23, 2018, 11:57:04 PM by Zinochan »

Drake

  • *
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1165 on: April 26, 2018, 12:42:42 AM »
I don't really get much information from that snippet, especially when items have several places with relevant code. How have you defined the item type? Are you using an item script or just CreateItemU1?
You should test things in order:
1) Does the item appear
2) Does EV_GET_ITEM trigger
3) What is the item ID and what is ITEM_LIFE_B_P

I imagine the problem is at step 2?

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

Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1166 on: April 26, 2018, 01:25:40 AM »
I don't really get much information from that snippet, especially when items have several places with relevant code. How have you defined the item type? Are you using an item script or just CreateItemU1?
You should test things in order:
1) Does the item appear
2) Does EV_GET_ITEM trigger
3) What is the item ID and what is ITEM_LIFE_B_P

I imagine the problem is at step 2?
I'm using CreateItemU1 in a task (to make that the item spawns like the newer games and does a y-angle spin).
I've made the item script just like a shot sheet, with a item data script, item constant script and a  item task script, and that code snippet is in the player script (the only part that has item and EV_GET_ITEM involved)(2).
ITEM_LIFE_B_P is a life piece item that should add a common data to add a life piece, but to test purposes, I've made it to give a life(3).
I can spawn the item and it adds the score when I collect it (1)

Drake

  • *
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1167 on: April 26, 2018, 02:22:48 AM »
See https://www.shrinemaiden.org/forum/index.php/topic,16584.msg1108259.html#msg1108259
Also https://www.shrinemaiden.org/forum/index.php/topic,19249.msg1373257.html#msg1373257

This is why I asked if you were using an item script, and why I figured tests would fail at EV_GET_ITEM. What you have isn't an actual item script, it's an include with a bunch of tasks. In order to have user-defined items work properly you need to write an item script for them, rather than try to define the item behaviour in a player script.

If you really needed some player-specific behaviour on top of the regular item behaviour you could trigger extra events from the item script and handle that event in the player script, or manipulate ObjVals on the player object, or otherwise make fake items. But that doesn't seem to be the case here.
« Last Edit: April 26, 2018, 02:42:31 AM by Drake »

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

Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1168 on: April 26, 2018, 04:47:29 PM »
See https://www.shrinemaiden.org/forum/index.php/topic,16584.msg1108259.html#msg1108259
Also https://www.shrinemaiden.org/forum/index.php/topic,19249.msg1373257.html#msg1373257

This is why I asked if you were using an item script, and why I figured tests would fail at EV_GET_ITEM. What you have isn't an actual item script, it's an include with a bunch of tasks. In order to have user-defined items work properly you need to write an item script for them, rather than try to define the item behaviour in a player script.

If you really needed some player-specific behaviour on top of the regular item behaviour you could trigger extra events from the item script and handle that event in the player script, or manipulate ObjVals on the player object, or otherwise make fake items. But that doesn't seem to be the case here.
I've read your tutorials, and merged both the Item Task and Item Const in a single script, and made some code to apply my tasks and item collection with events, as seen here, but my item graphics are not appearing (but the "out" is).


Andi

  • World's Gayest Danmaku
  • PlaySE("./se/Nyaa.wav");
    • 2hu blog
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #1169 on: April 26, 2018, 06:04:24 PM »
if you use NotifyEvent somewhere, there is nothing to come back from GetScriptResult, as no events have actually been handled yet.
...
wouldn't two SetScriptResult calls overwrite each other?
I guessed at these issues, but yielding didn't seem to help so I put the first off (but still kept using yields when testing) and figured I'd deal with the second when I managed to get anything back at all.
That being said, as far as events go it doesn't even matter, because using SetScriptResult in @Event will not affect the value of GetScriptResult outside of @Event! I don't really know why, because script results do persist over time, but that's how it is. In other words, the second trap is expecting that SetScriptResult does anything useful for user events at all.
Oh. ...I do so love Danmakufu.

Alright, then. New way:
Code: [Select]
function Notify(type,event,args){
let id = GetScriptID(type);
let hash = GetNextHash(); //nothing fancy atm, just increments and returns an int
args = args ~ [ hash ];
if(id==ID_INVALID || type==SCRIPT_ALL || ((type==SCRIPT_PACKAGE)!=(GetOwnScriptID==GetScriptID(SCRIPT_PACKAGE))) ) {
NotifyEventAll(event,args);
}
else{
NotifyEvent(id,event,args);
}
return hash;
}
function SetEventResult(hash,result){
SetCommonData("EventResult"~itoa(hash), result);
yield; yield;
DeleteCommonData("EventResult"~itoa(hash));
}
function GetEventResult(hash){
let result = GetCommonData("EventResult"~itoa(hash), NULL);
DeleteCommonData("EventResult"~itoa(hash));
return result;
}

task SomeTask{
let evhash = Notify(SCRIPT_ITEM, EV_SPAWN_ITEM, [ I_EXTEND, ex,ey, ex,ey-30 ];
yield;
let item = GetEventResult(evhash);
ObjRender_SetAngleZ(item,180);
}
That seems to work.

Oh, random question. How the heck do I put a backslash in a char? '\' escapes the close ', '\\' throws an exception for being too long to go in a char, and let temp="\\"; temp[0] throws an exception as well.
« Last Edit: April 26, 2018, 08:33:12 PM by Andi »
Literally everything in this script will crash and burn.
1CC tracker