Author Topic: Hellwind — A (eventually) Danmakufu-compatible Bullet Hell Engine for Browsers  (Read 11562 times)

rfw

Hellwind is aiming to be a 100% compatible implementation of Danmakufu in the browser. Yes, that's right — it means you'll eventually be able to run Danmakufu scripts right inside your browser, without having to copy and paste them into weird directories, and maybe even just play them online!



Demos
SampleA01 (source)
SampleA02 (source)
SampleA03 (source)
SampleA04 (source)

It's not super-exciting or anything right now, but SampleA04 is cool.

Roadmap
Here's the roadmap of upcoming features, in order of importance. Green indicates completed.
  • Basic rendering
    Hooray, it does stuff!
  • Resource loading
    Loading of images, child scripts, and music.
  • Task scheduling
    Hellwind doesn't support task scheduling because it's a pain to implement and will need a whole bunch of runtime support (requires supplementary support from Google Traceur).
  • DNH Script to JavaScript compiler
    Optimally, I don't want to have to make you write JavaScript that's more or less mechanically translatable from the equivalent DNH script, so a compiler would be cool.
  • Player support
    I feel like that's kind of important.
  • Runtime library completeness (sans-3D)
    Full compatibility with all Danmakufu built-in functions (except 3D because that's hard).
  • JavaScript FFI
    Extensions to use JavaScript inside existing scripts.
  • Audio
    Pew-pew!
  • ZIP loading
    Eventually I want to be able to just let you load a Danmakufu ZIP archive into the engine and have it automagically run in the browser.
  • 3D
    3D is hard.
  • Tests
    Tests are hard.

Contributing
Unfortunately I do have a day job, so progress might be slow. However, the project is open source and all the code is available on GitHub. Feel free to send me a PM if you're interested in contributing.
« Last Edit: May 02, 2014, 11:45:10 PM by rfw »

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
    • AFCDTech
A few questions:

-Are you going for 0.12m or ph3? (This is very important)
-How do you plan to address habits involving shot replace sheets and absolute pathing?
-How do you plan to deal with external images that replace defaults?

There are obviously more, but I don't want to overload and/or accidentally demotivate you.

ShadowNCS

  • Prinny Overlord
  • Highly Responsive to Jinxes
This project sounds interesting, to say the least. ^^

How exactly are you trying to achieve a "100% compatible implementation of Danmakufu"?
Are you going to rebuilding the Danmakufu engine in HTML5, but read the player scripts as they are and interpret them in a way your implementation can read them?
Or are you going to interpret the original engine already. Or something completely different.
(From the looks of it, you are trying to do my first guess. But I'm interested and want to know this exactly, so that's why I'm asking this probably stupid question.  :V )
Also, if I am correct with my first guess, what are you going to do with features that are being added in danmakufu in the future? It is still being worked on, as far as I know (I'm not a danmakufu scripter, so I don't know much of that.) You will need to keep implementing new features for a while, then. ^^;

By the way, if by tests you are talking about unit tests, do them right away, please!
Heck, it probably would be a good idea to do a test first development, even. But don't do them after everything is done. ^^;
Trust me, I know what I'm talking about. Because I ignored my own advice. xD;
I've programmed a danmaku engine myself. When I started, it was only supposed to be "a little test project", so "obviously" I didn't need any tests. Well, now that my "little test project" is actually a running engine, the joke's on me, since there are exactly zero tests. So whenever I need to rewrite some code (for example, I added a scaling feature for the projectiles recently), I have to pray that everything works later on. The end result of the scaling implementation was that I almost published a game where 50% of the scaled projectiles had misplaced hitboxes.
Don't make the same mistake and do some tests when you are actually programming your project. I know, tests are annoying, but you'll kick yourself in the butt later on if you need to rewrite something. ^^;

Anyway, enough with the nagging about tests, I wish you good luck with your project! I hope you won't run into any unexpected problems later on. ^^

PhantomSong

  • The Ghost Living through Everyday Life.
  • Eh, it doesn't matter.
Hmm quick question, have you informed MKM about this? It may be a good idea to. Considering it's their engine you're making this compatible to.

In case you don't know how to contact him, contact him via email chemcandym@yahoo.co.jp
« Last Edit: April 24, 2014, 10:48:23 PM by PhantomSong »

rfw

A few questions:

-Are you going for 0.12m or ph3? (This is very important)
-How do you plan to address habits involving shot replace sheets and absolute pathing?
-How do you plan to deal with external images that replace defaults?

There are obviously more, but I don't want to overload and/or accidentally demotivate you.

I'm going for ph3 compatibility since it seems to be the hot new thing. I know there are a lot of scripts in 0.12m but since ph3 seems to be strictly more powerful I could just implement some kind of compatibility shim later. (FWIW I have no idea how to write Danmakufu scripts, it just looks super interesting and I'm just implementing things and seeing how they work out.)

As for paths, I'm intending to implement a kind of virtual filesystem with regards to resource loading – you specify a bunch of files to load at a set of given paths, and the engine will accordingly refer to them at that path, e.g. how loadBundle works.

This project sounds interesting, to say the least. ^^

How exactly are you trying to achieve a "100% compatible implementation of Danmakufu"?
Are you going to rebuilding the Danmakufu engine in HTML5, but read the player scripts as they are and interpret them in a way your implementation can read them?
Or are you going to interpret the original engine already. Or something completely different.
(From the looks of it, you are trying to do my first guess. But I'm interested and want to know this exactly, so that's why I'm asking this probably stupid question.  :V )
Also, if I am correct with my first guess, what are you going to do with features that are being added in danmakufu in the future? It is still being worked on, as far as I know (I'm not a danmakufu scripter, so I don't know much of that.) You will need to keep implementing new features for a while, then. ^^;

By the way, if by tests you are talking about unit tests, do them right away, please!
Heck, it probably would be a good idea to do a test first development, even. But don't do them after everything is done. ^^;
Trust me, I know what I'm talking about. Because I ignored my own advice. xD;
I've programmed a danmaku engine myself. When I started, it was only supposed to be "a little test project", so "obviously" I didn't need any tests. Well, now that my "little test project" is actually a running engine, the joke's on me, since there are exactly zero tests. So whenever I need to rewrite some code (for example, I added a scaling feature for the projectiles recently), I have to pray that everything works later on. The end result of the scaling implementation was that I almost published a game where 50% of the scaled projectiles had misplaced hitboxes.
Don't make the same mistake and do some tests when you are actually programming your project. I know, tests are annoying, but you'll kick yourself in the butt later on if you need to rewrite something. ^^;

Anyway, enough with the nagging about tests, I wish you good luck with your project! I hope you won't run into any unexpected problems later on. ^^


I'm doing a clean-room implementation of the original engine, mirroring the functions exactly in JavaScript. Hopefully, then I can just compile DNH scripts to JavaScript with a 1:1 mapping so there's no overhead of having to run them through an interpreter and also the browser's JIT will kick in and optimize functions automagically.

As for unit tests, yes they're a good idea but no I'm just lazy :ohdear: (patches welcome!)

Hmm quick question, have you informed MKM about this? It may be a good idea to. Considering it's their engine you're making this compatible to.

In case you don't know how to contact him, contact him via email chemcandym@yahoo.co.jp

Not yet, but I'll do it later when I've made more progress.
« Last Edit: April 25, 2014, 12:33:05 AM by rfw »

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
    • AFCDTech
OK. How do you plan to implement some more complicated things such as the following:

-Render Objects vs. Move Objects
-Graphic render priority
-blends such as ADD_ARGB and INVERT_DESTRGB
-Curved lasers

Also, how do you plan to implement CommonData (including saving to files/cookies), font installation (which is critical post-ph3[.1 pre1] since default fonts changed), Virtual Keys (which may differ depending on device used), Render targets (which are used by some of the more graphically skilled scripters), and the package system, as well as the plethora of system and script functions commonly used in larger projects?

I'm just bringing this up now because technically, anything more complicated than a Single will involve system and script functions, and since Render vs. Move needs to be duplicated exactly to prevent breaking of important code blocks such as animations and visual effects that can have a detrimental effect if not done correctly.

(Also, replays. But I assume you know how random seeds work in Javascript; Replay Comments may be an issue though)

PhantomSong

  • The Ghost Living through Everyday Life.
  • Eh, it doesn't matter.
Not yet, but I'll do it later when I've made more progress.
You should probably ask him now, in case he doesn't want you to do so...

rfw

OK. How do you plan to implement some more complicated things such as the following:

-Render Objects vs. Move Objects
-Graphic render priority
-blends such as ADD_ARGB and INVERT_DESTRGB
-Curved lasers

Also, how do you plan to implement CommonData (including saving to files/cookies), font installation (which is critical post-ph3[.1 pre1] since default fonts changed), Virtual Keys (which may differ depending on device used), Render targets (which are used by some of the more graphically skilled scripters), and the package system, as well as the plethora of system and script functions commonly used in larger projects?

I'm just bringing this up now because technically, anything more complicated than a Single will involve system and script functions, and since Render vs. Move needs to be duplicated exactly to prevent breaking of important code blocks such as animations and visual effects that can have a detrimental effect if not done correctly.

(Also, replays. But I assume you know how random seeds work in Javascript; Replay Comments may be an issue though)

- I'm not familiar with Render vs. Move; could you explain?

- Graphic render priority is something I've avoided implementing for now due to its performance implications, but the idea is to allocate 100 (or so) arrays ahead of time for each render priority, then insert/remove objects from those arrays as needed. Images are sorted with GL's depth buffer.

- <canvas> has built-in support for most common blending modes with globalCompositeOperation, so that shouldn't be an issue. I am not familiar with INVERT_DESTRGB (or have any idea what it implies), though. Shaders for compositing can be written.

- I'm not entirely sure about the semantics of curved lasers yet, I'll get back to you on that.

- CommonData will probably just use localStorage.

- I assume I can just handle virtual keys in the normal input handling mechanism.

- Web fonts can handle loading OTF/TTF files. Font installation won't be necessary.

- Render targets are interesting. With a 2D implementation of the engine (what I'm currently doing), they can be simulated with additional <canvas>es. However, if I ever support 3D... GL has framebuffer support for rendering to textures.

It might be worth switching to WebGL to utilize shaders (to support non-standard blend modes), more efficient render targets, and z-buffer depth sorting. I've currently avoided WebGL because it's a total pain to use but I might fiddle around with it a bit because it'll be better in the long run.

So I've switched everything over to use WebGL and it runs about 100x better but now you need a compatible graphics card (I don't know what graphics cards are supported). It's also a massive memory hog because I did a lot of premature optimization and I'm a bad person.

You've also raised a good question about replays. I doubt I will ever support loading replays from Danmakufu format because it will probably be horrendously finicky to reimplement whatever RNG Danmakufu uses, and also horrendously slow. I'm not familiar with replay comments ? elaborate?

You should probably ask him now, in case he doesn't want you to do so...

Is English OK? Not the biggest deal, but it would be more convenient for me.
« Last Edit: April 25, 2014, 05:08:32 PM by rfw »

PhantomSong

  • The Ghost Living through Everyday Life.
  • Eh, it doesn't matter.
Hehe, luckily for you, mkm does know a little English, so, just be sure to use simple words if you do.

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
    • AFCDTech
- I'm not familiar with Render vs. Move; could you explain?

You can change the location of an object's graphic without changing the actual object's location, and there are other even more complicated things that derive from this.[/quote]

You've also raised a good question about replays. I doubt I will ever support loading replays from Danmakufu format because it will probably be horrendously finicky to reimplement whatever RNG Danmakufu uses, and also horrendously slow. I'm not familiar with replay comments ? elaborate?
If you never implement replays, running them correctly will never be a problem. This is a complicated topic that is the standard way of saving CommonData data to a replay.

Also, about multithreading. Danmakufu uses coroutines that execute in the order they are initially called in. Make sure you mimic the same or things will break in scripts, such as when one object's position is determined by another's.

Some new things:
-How do you plan to deal with Obj_SetValue and NotifyEvent, as well as the @Event loop and SetAutoDeleteObject? These are some of the more complicated things with Danmakufu.
-I assume you have a system for script IDs
-Will this engine require constant internet connection?

Note on render priorities: If render priority is 80 or above, the origin shifts to the top left of the playing field from the top left of the game screen in which the player can move.

Also, will you be able to make it run at 60 FPS constantly? And how do you plan to deal with Danmakufu's auto compilation of boss scenes and the shot constant system?

(I know I'm overloading you, but it's best that you're aware of the system issues before you get too far and can't fix them as easily)

Sage Ω (Ultima)

  • CEO at Team Eternal Desire
  • ??? X
This is a nice idea and all but to be honest I don't see the effort being worth it. Especially how danmakufu is designed to run. I just don't see a web browser running it just like it would be in windows. Why not make you're own engine in a web browser and leave danmakufu to mkm. That way you can come up with your own standards, features, and generally you'll have a better understanding of how things work rather than trying to remake an engine in a web browser which that in itself sounds like it would be really limited because its not like you have the source code laying around.


rfw

You can change the location of an object's graphic without changing the actual object's location, and there are other even more complicated things that derive from this.

That doesn't sound too complex, if object rendering is decoupled from object movement.

If you never implement replays, running them correctly will never be a problem. This is a complicated topic that is the standard way of saving CommonData data to a replay.

I'll look at that further down the line.

Also, about multithreading. Danmakufu uses coroutines that execute in the order they are initially called in. Make sure you mimic the same or things will break in scripts, such as when one object's position is determined by another's.

Danmakufu's yield is really weird and yield seems to do two different things:

 - Inside a coroutine, on yield, the coroutine is paused and then the next coroutine runs (coroutine yield)?

 - Outside a coroutine, yield starts running all coroutines (scheduler resume)?

Some new things:
-How do you plan to deal with Obj_SetValue and NotifyEvent, as well as the @Event loop and SetAutoDeleteObject? These are some of the more complicated things with Danmakufu.

Obj_SetValue: sets the associated key/value in the object's metadata table. NotifyEvent: runs the associated @Event function (I already do this to some extent with EV_REQUEST_LIFE). SetAutoDeleteObject: maintain a list of used objects, then destroy them at script completion.

-I assume you have a system for script IDs

Yeah, it's just a monotonically increasing number.

-Will this engine require constant internet connection?

No, it's all client-side.

Note on render priorities: If render priority is 80 or above, the origin shifts to the top left of the playing field from the top left of the game screen in which the player can move.

wat ok

Also, will you be able to make it run at 60 FPS constantly?

A lot of what I've done currently trades off memory for speed. All of the "expensive" operations are constant time (creating a bullet, destroying a bullet, altering the velocity of a bullet) and avoid allocations, so I've tried to avoid as little variance in runtime as possible. If it's smooth at 100 bullets, it'll probably be smooth at 1000 bullets, and the major overhead is the number of vertices the graphics card can process at once.

And how do you plan to deal with Danmakufu's auto compilation of boss scenes and the shot constant system?

Implementation details that won't be particularly complicated.

(I know I'm overloading you, but it's best that you're aware of the system issues before you get too far and can't fix them as easily)

Sure, I don't mind. It's better to find flaws early on rather than realize them later.

This is a nice idea and all but to be honest I don't see the effort being worth it. Especially how danmakufu is designed to run. I just don't see a web browser running it just like it would be in windows. Why not make you're own engine in a web browser and leave danmakufu to mkm. That way you can come up with your own standards, features, and generally you'll have a better understanding of how things work rather than trying to remake an engine in a web browser which that in itself sounds like it would be really limited because its not like you have the source code laying around.

This is mostly for interest's sake. I don't get what you mean by "Especially how danmakufu is designed to run" ? seeing as your browser can run Unreal Engine 3 today, I don't believe there's really any kind of limitation with regards to having a Danmakufu engine in the browser.

Sage Ω (Ultima)

  • CEO at Team Eternal Desire
  • ??? X
This is mostly for interest's sake. I don't get what you mean by "Especially how danmakufu is designed to run" ? seeing as your browser can run Unreal Engine 3 today, I don't believe there's really any kind of limitation with regards to having a Danmakufu engine in the browser.

Well, when I say limitations I mean, how well will this web version stack up to the original? Should I assume that I can freely play my scripts by just inserting them into the web version without having to worry about re working the scripts? Can the performance atleast hold up to the original? ect...

I don't remember mkm giving out the source code to danmakufu so I assume you're building this based on personal knowledge and what you've learned about danmakufu itself.

On the other hand, if this isn't all that of a serious project then I guess it wouldn't hurt to try; I am definitely interested in seeing how far you get so keep it up if things are going well.

rfw

Well, when I say limitations I mean, how well will this web version stack up to the original? Should I assume that I can freely play my scripts by just inserting them into the web version without having to worry about re working the scripts? Can the performance atleast hold up to the original? ect...

Yes, the end goal is to be able to run Danmakufu scripts without you having to modify them. Currently, in terms of raw rendering speed, it outperforms Danmakufu but has its own set of limitations (which in theory you'll never encounter). When cooperative tasks are implemented, I'm dubious about whether performance will still be up to scratch.

I don't remember mkm giving out the source code to danmakufu so I assume you're building this based on personal knowledge and what you've learned about danmakufu itself.

Yeah ? unfortunately I don't know exactly how Danmakufu behaves, which is leading to some, uh, interesting misunderstandings about how things work.

rfw



Just an update about performance -- Hellwind scores a steady 55-60 fps on mobile devices (well, my mobile device) with a load of around 1000 bullets per frame.

Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
    • AFCDTech
Note on Sample A4: You seem to have an issue with the right bound shot auto delete. Also, it'd be nice if you took simple scripts from people here and used those to test various features, so that you will be aware of issues before they become problematic. Also, you may want to set the default STG_Frame, lifebar, etc soon.

rfw

Note on Sample A4: You seem to have an issue with the right bound shot auto delete. Also, it'd be nice if you took simple scripts from people here and used those to test various features, so that you will be aware of issues before they become problematic. Also, you may want to set the default STG_Frame, lifebar, etc soon.

The right bound culling is correct, since the right bound is where all the life/score/etc. will be displayed.

Currently I'm still experimenting with the scripts that come built in with Danmakufu. I've managed to port a (mostly) correct version of ExRumia's spell 01, using tasks here, and to some extent ExRumia's normal phase here.


Sparen

  • Danmakufu Artist
  • Git ready, git set, PUUSH!
    • AFCDTech
Regarding the right bound shot auto delete, simply draw the STG_Frame a layer above so that you can maintain a standard (-32,-32,32,32) AutoDeleteFrame or something similar, because you can see the bullets deleting and that is graphically tasteless.

It might help to give you some more complex scripts to try out, with perhaps 2D backgrounds and animated sprites.

Note: I would like to see your implementation of the following:

loop(n){}

loop()

ascent(i in n..m){}

descent(i in n..m){}

I don't know if Javascript comes with these built-in (many languages lack a basic loop, and Danmakufu's for loops, the ascent and descent, function differently than in other languages, especially that descent), and I don't know where you store that code pre and post implementation. I checked on Github, but I don't know where exactly it is.

rfw

Regarding the right bound shot auto delete, simply draw the STG_Frame a layer above so that you can maintain a standard (-32,-32,32,32) AutoDeleteFrame or something similar, because you can see the bullets deleting and that is graphically tasteless.

It might help to give you some more complex scripts to try out, with perhaps 2D backgrounds and animated sprites.

Note: I would like to see your implementation of the following:

loop(n){}

loop()

ascent(i in n..m){}

descent(i in n..m){}

I don't know if Javascript comes with these built-in (many languages lack a basic loop, and Danmakufu's for loops, the ascent and descent, function differently than in other languages, especially that descent), and I don't know where you store that code pre and post implementation. I checked on Github, but I don't know where exactly it is.

loop (n) { ... }

Code: [Select]
for (var _ = 0; _ < n; ++_) { ... }

loop { ... }

Code: [Select]
for (;;) { ... }

ascent (i in n..m) { ... }

Code: [Select]
for (var i = n; i < m; ++i) { ... }

descent (i in n..m) { ... }

Code: [Select]
for (var i = n; i > m; --i) { ... }

I haven't implemented STG_Frame drawing purely out of laziness (and it's low priority right now). If you have any more complex scripts, I'd be happy to try them out! I'm also not sure what you're looking at on GitHub, but the code is full of nasty speed hacks so it's not exactly the epitome of understandability, sorry!
« Last Edit: May 02, 2014, 11:47:38 PM by rfw »

I, for one, am excited for this, keep up the good work!