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

0 Members and 1 Guest are viewing this topic.

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
  • Staff
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #510 on: March 16, 2017, 06:34:10 pm »
@Helepolis

I tried to do sound system as u said, but it was way too complicated for me. Could u tell me please how it works more detailed. And how can I put these variables into a AreaCommonData???

Edit: Nevermind, i solved the problem :/
Sorry for being unable to respond on time. Lately been quite busy that I even neglected my own game development.

Curious though, what was the final problem and how did you solve it?
  • Helepolis' Siege Workshop

Zhan_fox

  • Kitsune~~~
  • A numerologistů
  • Nickname: Fox
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #511 on: March 17, 2017, 06:24:05 am »
Oh, I see. I understand. Thank you for responding!

Curious though, what was the final problem and how did you solve it?

The problem was in restarting the music after I leave the pause. Music started always from beginning. My mistake was:
Code: [Select]
ObjSound_SetRestartEnable( GetAreaCommonData("sound", "song", 0) ,false) Which is of course wrong, because this common data not a music object itself. The solution was to call this function as I did it with play/stop music object.
Normal: All
Hard: EoSD, IN, MoF, TD
Extra: Flandre, Ran, Mokou, Suwako, Koishi, Nue, Mamizou, Raiko, Hecatia, Otohime (Marine Benefit)
Phantasm: Yukari

ExPorygon

  • Veteran Danmakufu Scripter
  • Currently working on a full Touhou fangame!
  • Nickname: Ozzy
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #512 on: March 20, 2017, 05:12:55 pm »
Just to preface this post, I'd like to note that Danmakufu has been my only programming experience. I've had no formal education or experience in any general programming language.

I've been looking for something that I can eventually move to after I'm done with Danmakufu and to this end I've recently been dabbling in a Lua framework called LOVE2D, which has had me learning coding in Lua. It's been stated in the past that Danmakufu's tasks are basically the same as coroutines and it's my dabbling in lua that made me understand exactly why that is correct.

Danmakufu's tasks are not truly running in parallel. This is why the @MainLoop must be yielded in order for tasks to properly run (it's essentially resuming the task coroutine from where it was paused, or yielded, if I'm correct). I understand this now and have started to construct a similar method of programming in lua using coroutines to the tasks that I'm used to using in Danmakufu.

What I don't understand is how Danmakufu runs multiple scripts at the same time. I don't even really get what the scripts even ARE, as each one of them appears to be its own separate thread since they each have their own @MainLoop and tasks. It's been stated before that Danmakufu cannot do multithreading so these scripts can't actually be their own processing threads, unless I'm misunderstanding something.

So, my question is:

How does Danmakufu handle scripts if multiple can be run at the same time?

I'm interested in learning so that I can hopefully construct a programming environment that is similar to Danmakufu, which is what I'm used to. I'm still learning so please correct me if anything I said in this post is incorrect.

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
  • Staff
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #513 on: March 20, 2017, 08:53:07 pm »
When it comes to threading, I can tell you my own experience from being a JAVa programmer. Threading in Java is never parallel. The word multi-threading implies parallel execution, but it is not. For the Java programming language, the Java Virtual Machine (Also called JVM) handles the order of execution for any multi-threaded program made in Java.

Example, heavily assume that I launch a java program which creates 3 threads and each thread has a loop which inside simply echoes "Hello I am thread N".

Next, I start the threads in order 1, 2 and 3. Here comes the fun part: The order of these echoes are unsure. I didn't write "never" because that is a false statement. When it comes to threading, all you can claim is that the Threads are started, running and doing their jobs.
"Hello I am thread 1"
"Hello I am thread 2"
"Hello I am thread 1"
"Hello I am thread 3"
"Hello I am thread 3"
"Hello I am thread 1"
"Hello I am thread 3"


The above could be an outcome. Some thread might be even reported four times in a row or perhaps never for a long time. You simply don't know. There is absolutely no guarantee that the threads are echoed in order. So is there a way to control order in Java? Yes, there is. But that requires in-depth knowledge of the Java language. Are other languages similar when it comes to threading. I assume they are, but can't confirm from experience.

So why the example, you might ask. Danmakufu is (guessing) similar. The MainLoop of a script is always initiated by the engine. It can be assumed that the MainLoop in your script isn't actual the Main Loop. No, the Danmakufu engine probably has its own actual MainLoop hard coded which you cannot influence or control. Therefore the script @MainLoop is definitely a thread on its own. Which seems to have highest ultimate priority when not yielded, regardless of any task added in your script. Something that isn't true in Java. Threads in Java can be given a priority, but again there is no guarantee whether it gets a chance to run.

We already know that if you yield; the @MainLoop in your script, the Danmakufu Engine's Main Thread checks whether there are other tasks that can be performed. But it will never stop executing the @MainLoop. The @MainLoop of your script always runs, until it hits that yield. Only then the Engine will allow other threads to "grab their chance" and execute. All of this happens so fast that we humans thing there is parallel process going on. But there isn't.

Experiment
I heavily assume that if you would immediately call 3 bullets tasks with 3 different colours at the same time, the order of the bullet would be different each time the MainLoop hits that yield. So for example:
Code: [Select]
task fireRed() { }
task fireBlue() { }
task fireGreen() { }
The last bullet fired would overlap the previous two (because of Drawing Order). And my bet is that each time the overlapping bullet is a different colour.


Edit:
Asked a C# programmer RL friend about multi-threading. He says that in C# it is the same case as Java when it comes to the order of threads running. Except C# threading is probably influenced directly by the OS / CPU's orchestration. Fun fact, the JVM is actually also influenced by the OS/CPU.

Edit2
Tested the experiment of firing three bullets. It seems that there order of execution for tasks is as displayed in the script. Which, is if I think about it, quite logical. Calling the bullets is either done by a "task" or the @MainLoop. And there is one guarantee when it comes to putting things in loops (threads). The stuff is executed from top to bottom inside it. So my experiment failed because the script itself is probably a single thread. I have no idea how to run three scripts simultaneously.

Edit3:
Wow,  I forgot to answer your question after building up this much of a wall of text. I can only guess the following:

The Danmakufu Engine launches a new thread for every new script started. When you have a Stage Script and a Spell Card script, they are both independent instances, but the Engine's main thread is aware. Each script also launches its own routine called the @MainLoop, which has highest priority unless yielded within the script.

Scripts themselves don't conflict over each other's @MainLoop, that is for sure. But the execution of which script's MainLoop is most likely controlled by the Engine's main thread.

« Last Edit: March 20, 2017, 09:37:20 pm by Helepolis »
  • Helepolis' Siege Workshop

ExPorygon

  • Veteran Danmakufu Scripter
  • Currently working on a full Touhou fangame!
  • Nickname: Ozzy
  • Gender: Male
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #514 on: March 21, 2017, 04:09:09 am »
Thanks Helepolis, that was a very insightful read and makes a lot of sense. I think you're definitely right about multithreading not having perfectly simultaneous processes.

I have no idea how to run three scripts simultaneously.
You can actually use LoadScript and StartScript to start any number of scripts. I actually do this to start special scripts for effect rendering and sound management in my game. They listen for Event signals from other scripts to perform visual effects like concentrations and explosions and play sound effects without worrying about being interrupted by the ending of a single script.

Edit3:
Wow,  I forgot to answer your question after building up this much of a wall of text. I can only guess the following:

The Danmakufu Engine launches a new thread for every new script started. When you have a Stage Script and a Spell Card script, they are both independent instances, but the Engine's main thread is aware. Each script also launches its own routine called the @MainLoop, which has highest priority unless yielded within the script.

Scripts themselves don't conflict over each other's @MainLoop, that is for sure. But the execution of which script's MainLoop is most likely controlled by the Engine's main thread.
My guess was that each new script was actually a task of sorts running from the hidden 'true' MainLoop. The hidden MainLoop would yield to the new script's MainLoop which would then in turn yield to any running tasks in that script. This begs the question of whether I can have coroutines start other coroutines which is something I had not considered.

Are we sure that scripts are definitely separate processing threads and not like tasks? I had imagined that if that were the case, then each script would be able to take advantage of a different core of a multi-core CPU, but my understanding on that is very limited and I'm probably wrong about it. I was under the impression that because Danmakufu only ever uses one CPU core it isn't truely utilizing multithreading, at least in that sense. I'm probably babbling about nonsense that I don't fully understand. Someone please clarify, if that is the case.

Drake

  • ねぇ、君
  • *
  • 一緒に寝ないかい?
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #515 on: March 21, 2017, 05:49:47 am »
Within a script, there are the predefined routines like @Initialize, @MainLoop, etc. These are predefined because they have special behaviour relating to that running script that is hardcoded as part of the engine. The actual execution flow of a "script" will start by doing some internal initialization stuff, interpreting and running @Initialize and @Loading, then when done will run @MainLoop once per frame, and also once per frame internally checking if conditions to run @Finalize are met. A global event scheduler (I'm assuming it's global) likely also takes the whole stack of events being triggered and messages the event data to the relevant scripts, and on that frame, that script's @Event will be run once for every new event put in that script's event stack. (That or there's another mechanism for scripts to add events to all other scripts' event stacks somehow. Or, all events are done together outside of the individual script flow, but I doubt that.)

If the programmer starts a task in @Initialize, which is likely, that starts a coroutine. Once it yields or ends, the context switches back to where the task was called; in @Initialize, which again is part of the main execution flow of the "script". If the task started more tasks the same applies and it just builds a tree of new coroutines and eventually winds back to the initial context. The "tree"-ness of calling tasks from tasks only really matters when they're first called; once a task yields, that coroutine is just set up in a queue for the next frame. Once @Initialize is over, and I assume it's starting on the next frame, @MainLoop runs. @MainLoop will have some stuff in it, and importantly it (should) yield, which lets the context yield back to the first task queued in the task scheduler. Once that task yields (or ends) again, context switches to the next in the queue, and so on until it reaches the end of the queued tasks for that frame, and finally context comes back to @MainLoop, which maybe runs some more stuff and then ends.

If you're clever, you might notice that if you don't put a yield in your @MainLoop, you get a few interesting pieces of information: 1) @MainLoop does not halt, and will keep running once per frame; and 2) only the coroutines relevant to the script are never yielded back to. Because of this it can be concluded that task/coroutine scheduling is divided on the script-level and is not a global scheduler. Tasks "belong" to a script.

Now, I've been writing "script" in quotations here because as far as I can tell, scripts are structures that have similar organization to coroutines, but are one step up the chain, and ultimately do many more things. I'm fairly sure that Danmakufu doesn't particularly do any multithreading with this, and that scripts are simply run in order similarly to how coroutines are scheduled per task, but done in a more global fashion. Danmakufu does run more than one thread for running in general though.

A Colorful Calculating Creative and Cuddly Crafty Callipygous Clever Commander

Helepolis

  • Charisma!
  • *
  • O-ojousama!?
  • Staff
  • LOOK AT ME
Re: ※ Danmakufu Q&A/Problem thread 3 ※
« Reply #516 on: March 21, 2017, 08:07:08 pm »
All I can suspect from the LogWindow is that the Danmakufu Engine is scheduling its own coroutines/threads. (See attachment). The extra tasks/threads appeared when I was transitioning between Dnh's own Main Menu and Package Menu.

Looking at the ETaskManager at the top, is this perhaps the global "Manager" which handles all the coroutines for the engine?
  • Helepolis' Siege Workshop
 

SMF 2.0.13 | SMF © 2016, Simple Machines
Theme based on ModernDark64 design by BlocWeb
Page created in 0.079 seconds with 15 queries.