12 ms·
Firedancer: Language for 2D shmups bullet-hell patterns
- dang 2y agoLooks like these are related: BulletML is a markup language that describes the barrage of bullets in shooting games. - https://news.ycombinator.com/item?id=410898 https://news.ycombinator.com/item?id=410898 - Dec 2008 (2 comments) https://hn.algolia.com/?dateRange=all&page=0&prefix=false&query=%22bulletml%22&sort=byDate&type=comment https://hn.algolia.com/?dateRange=all&page=0&prefix=false&qu...
- freeone3000 2y agoSixteen years ago! I saw “applet” and thought it was retro, then someone tried it in firefox 3 and I had to check the year.
- noufalibrahim 2y agoYes. I was exposed to this when I came across kenta cho's games. I even tried to use it a little iirc for a shooter i was playing with but couldn't get very far and abandoned it.
- bitbasher 2y agoBulletML was developed by ABA Games (aka kenta cho, creator of the classic rrootage, which is now open source). It was rrootage that sent me down a rabbit hole and eventually stumbled onto fal-works and firedancer after someone suggested their works had the same aesthetic appeal. The libbulletml c++ library is still somewhat used in some niche vertical shmup games (mostly Japanese indie games). You can read a little about bulletml and the history of it all in the libbulletml readme file. [0] https://en.wikipedia.org/wiki/ABA_Games https://en.wikipedia.org/wiki/ABA_Games [1] https://github.com/abagames/rrootage https://github.com/abagames/rrootage [2] https://shinh.skr.jp/libbulletml/README.en.txt https://shinh.skr.jp/libbulletml/README.en.txt [3] https://www.fal-works.com/solid-aether https://www.fal-works.com/solid-aether
- chii 2y agoThis is pretty cool! It's even haxe based!
- miffe 2y agoSeems to be vsync-based. Would make the laundry pattern very hard at 360Hz :)
- eru 2y agoWhat's the laundry pattern?
- mock-possum 2y agoChoose it from the ‘example’ select box and see for yourself ;)
- eru 2y agoOK, thanks! I found it. But why would vsync make that hard? You mean if it's 1:1 on the vsync?
- Karliss 2y agoI guess the idea is was that Firedancer is designed with fixed update rate in mind. And the demo makes an assumption that it will run at 60 FPS = 60 updates per second, probably becoming very fast and hard on 360 Hz screens. But that's just nitpicking on details in library demo. It would be bad to have such mistake in a real game or game engine demo, but it's not that surprising for example code to skip details for the sake of simplicity. The main purpose of example is demonstrating the library as cleanly as possible without distracting reader by containing more boiler plate code for third party game engine than the thing it's attempting to demonstrate. I don't see a reason why you couldn't update FireDancer VM at whatever fixed rate you want (faster or slower than typical FPS) just like many games and game engines with fixed tick rate for physics or game logic handle it.
- unconed 2y agoIf the shots weren't timed to a regular fixed clock, then there would be visual jitter in the pattern. Even if you correctly spawn shots in between two ticks, each bullet would only first appear some random distance along its trajectory. If an enemy spawns e.g. a circle of bullets, you would see it rapidly expanding/contracting. I suspect a variable frame rate bullet hell game would be harder to play, but I'm not a fan of the genre.
- redrobein 2y agoCan you add a little player box and make this playable with touhou style controls. For testing purposes ofcourse. Ah. I thought the script was being compiled inbrowser. These are prerendered.
- ginko 2y agoYeah, kind of disappointing. I was hoping I could play around with this a bit in the browser.
- Karliss 2y agoLooking at the demo source code it seems like it is running everything in browser and is not prerendered. It just lacks a parser. So the AST nodes in all examples are created through function calls https://github.com/fal-works/firedancer/blob/4a15e80fe55893bf9b2097ee112a71ea6306815a/demo/src/BulletPatterns.hx#L900 https://github.com/fal-works/firedancer/blob/4a15e80fe55893b... .
- qwery 2y agoBulletML[0] (circa Java applet, AD) is a markup language to describe shmup bullet behaviours. The Firedancer README says the project is "Inspired by BulletML". Cool to see it living on, in a way. But where is the toothpaste laser? What even is a toothpaste laser? I hear you cry, well... Today in Search Engines: Software for No-one, I try (somewhat naively) to search for "toothpaste laser" in hope of finding an accurate analysis/explanation/implementation of the famous weapon/s from the Raiden series. It won't surprise you to learn that this got me a grid of photos of toothpaste tubes and mechanically-induced fluorescent grins. It might surprise you to learn that prepending 'raiden' to my query barely helped. If only there was a search engine that allowed the user to decide what to search for. Long story short, Raiden (series) is about as popular as the intersection of Raiden (Kharacter) and referring to electrical arcs as "lasers"[1]. Both of these topics are totally eclipsed by the Bend-Tech Dragon A400: The Essential CNC Tube Production Machine[2]. [0] http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html http://www.asahi-net.or.jp/~cs8k-cyu/bulletml/index_e.html [1] not that any of the toothpaste lasers are lasers [2] it is essential, after all (https://www.youtube.com/watch?v=xMb9XZjK6m0 https://www.youtube.com/watch?v=xMb9XZjK6m0)
- anonymoushn 2y agoMaybe you mean this sort of thing (first image result for "raiden purple laser") https://gamedev.stackexchange.com/questions/29424/what-are-the-maths-behind-raiden-2-purple-laser https://gamedev.stackexchange.com/questions/29424/what-are-t...
- qwery 2y agoThat's referring to the same "toothpaste laser", yes. The discussion never arrived at a satisfactory algorithm -- I tend to agree with the gist of the incremental "steering" ideas, though.
- renewiltord 2y agoAbsolutely bonkers https://youtu.be/0SEcyot2qgA?si=m_J17m2q6PMzuDhv&t=107 https://youtu.be/0SEcyot2qgA?si=m_J17m2q6PMzuDhv&t=107
- GuB-42 2y agoI see BulletML being mentioned but there is a third one: CannonML. https://web.archive.org/web/20120626041044/http://www.libspark.org/wiki/keim/cannonML_e https://web.archive.org/web/20120626041044/http://www.libspa... Haxe port: https://github.com/gunnbr/CML https://github.com/gunnbr/CML As you may have guessed by the archive.org link, it doesn't have much support. Compared to BulletML and Firedancer, it has a very terse and rich syntax that kind of makes me think of Perl.
- qwery 2y agoI wasn't sure exactly what you meant by "terse and rich syntax" but I wasn't expecting the example on the CML github which is referred to as quite cryptic: > bs,4,,10bm5,360f10{i30vw90br5,360,2,2f4{i30v~ko}w10ay0.05} That is certainly terse! [aside: I'm not usually one to pedant over what qualifies as a "markup language", but I have to say this is not it. I'm happy to report that the author didn't think so either, because the 'ML' stands for "macro language".]
- philipov 2y agoYeah, that's not Perl; that's Q!
- CyberDildonics 2y agoThis is unfortunately a classic example of mixing data with execution. Data is easy to understand and manipulate. Execution is much harder because you don't know what it produces without executing it. Inventing a language is the third step and even worse, because you not only have execution instead of data, but you wipe out the entire ecosystem of tools, libraries, fragments and knowledge and start all over again.
- anonymoushn 2y agoDefining the behavior of enemies and bullets in a shmup is programming. I'm not sure how you want it to be done without the programming part. Could you maybe show us?
- CyberDildonics 2y agoDefining the behavior of enemies and bullets in a shmup is programming. Says who? And for what definition of programming? I'm not sure how you want it to be done without the programming part. Maybe you should point out the parts that can't be static data. Even branching, triggers or graphs could be straight data. Which parts needs loops, state and computation?
- YurgenJurgensen 2y agoOkay, let’s see your data-only implementation of “shoot n fast homing projectiles in a burst that takes a total of a third of a second where n is the number of times this attack has been performed in this phase at a location where the player was one third of a second ago.” I guess you could accomplish this with invisible bullets and making bullets targetable, but at that point, you’re just creating state and loops and pretending you’re not.
- CyberDildonics 2y agoTime: 0.3, Burst: true, Count: $phase, Location: $playerXYZ, LocationTime: -0.3
- mariocesar 2y agoIs there a book that teaches these patterns? looks so useful to known when building games
- netdoll 2y agoThe classic book references for programming shmup bullet patterns (in Japanese) are シューティングゲームアルゴリズムマニアックス and シューティングゲーム プログラミング, but in general, a lot of this stuff is folk knowledge and isn't communicated well outside of trial and error until you get something passable. I would suggest looking up web tutorials and game source code and learning from that (also will mention the Development sub forum on shmups.system11.org being quite useful).
- mariocesar 2y agoThank you !
- slmjkdbtl 2y agoThis is cool but I never understand most DSLs, looks like most of them can just be defined as some functions in your host language. The example on the main page just looks like JavaScript and you define the parallel(), radial() functions yourself to return some data, and a run() function to deal with these data / run the game. Writing a compiler and VM for this is a huge overkill imo, if it aims to be productive and not just a programming practice. Am I missing something?
- anonymoushn 2y agoA run() function to deal with the data is an interpreter (the data has stuff like calls to the wait function and subroutines in it) or at least a command-replayer, if the control flow all runs before any gameplay happens. The behavior might also be dynamic such that the command-replayer approach doesn't work. One reason BulletML is useful compared to a general-purpose language is that you could arbitrarily recombine BulletML ASTs to produce valid bullet patterns, which Kenta Cho did for rRootage[0]. I think another reason that people implement VMs for these languages is that the host language lacks coroutines, so it cannot express the wait() function, and they don't want to turn their bullet pattern code inside-out. Even if the host language has coroutines, they may not be serializable, so saving your game in the middle of a level may not be possible if you build on top of coroutines, whereas it is definitely possible if you control the interpreter state of your DSL. [0]: https://www.asahi-net.or.jp/~cs8k-cyu/windows/rr_e.html https://www.asahi-net.or.jp/~cs8k-cyu/windows/rr_e.html
- jayd16 2y agoI find that a lot of DSLs are essentially "I need these N languages features in a serializable and dynamically runnable language." If you're already in a scripting language its not all that interesting but if you're in a compiled language, a small embedded DSL can scratch an itch. Even in JavaScript, you might not want the full power of eval() exposed and instead you want something with less power that can be parsed and sanitized.
- fitsumbelay 2y ago> Writing a compiler and VM for this is a huge overkill imo Personally, that's what attracts the artist side of me to this, like it's the ultimate creative product. There seems to be a lot of blogging and tweeting recently around the subject has also created a bit of an itch.
- philipov 2y agoThe way the scripts are presented in a text box makes it feel like I should be able to edit the text box contents and have the change represented in the image. It's a bit disappointing that I can't play around with it like that.
- mrandish 2y agoI find myself strangely drawn to Japanese bullet-hell shmups despite sucking at playing them. There's something about peak 2D pixel art sprites over parallax scrolling fantasy environments while dodging through insane geometric bullet patterns and spectacular animated explosions that's beautiful and hypnotically compelling. I just wish I wasn't so hopeless at them, only managing to survive seconds at a time by constant credit feeding. While I realize the entire genre is notorious for being brutally difficult and that's in fact the appeal to many serious players, I dream of shmups where: * Difficulty scaled dynamically up a smooth gradient based on real-time player performance * Success didn't require deep level and pattern memorization. My cognitive style is anti N-back and this requisite shmup ability remains forever beyond my reach. I need the shmup equivalent of Fischer Random Chess (aka Chess960) where the necessity of book memorization is removed and the focus is mostly on reactively dodging in the moment. * The engine supports interactive practice modes enabling weaker players to gradually build skills such as: rewind, ghost follow and partial dynamic slowdown (eg only bullets get slower, only when N of bullets > Threshold, growing gradually slower as N increases, returning to normal below N). On the last point, some modern shmups do at least have "practice modes" but they seem like developer afterthoughts, typically very basic bolt-ons instead of being integrated, dynamic and granular. The result often leaves me feeling more frustrated than trained. While it is possible to apply hacks to emulated shmups which can help a bit, these are usually limited to brute force such as pause, global frame rate limiting and infinite lives or invincibility. While MAME and Retroarch do have rewind features, I believe they are hacky since I've never been able to get them to work reliably with shmups. My deep attraction to the genre seems doomed to remain unrequited despite buying and playing so many, watching various training videos and following many guides. I feel like I can't reach the level needed to trigger the fun-obsession loop of a typical bullet-hell shmup because it currently requires a minimum level of a few neuro-competencies I don't possess. Even top players and fans admit (and occasionally revel in) the inaccessibility of the genre, highlighting the need to memorize deep pattern sequences, commit dozens of hours to rote practice and how it helps to be "at least a little on-the-spectrum." This makes me sad because top players, fans and developers are also worried about the long-term decline of the genre from cool niche in the 90s to seriously at-risk in recent years. I suspect there may be others who are, like me, strongly attracted to shmups but too-often barred by a metaphorical "Must Be This 'Neuro-Level' to Ride" sign. Yet other once niche gaming genres have successfully broadened their appeal by deeply integrating 'accessibility' features like racing games have done with: ghost cars, rewind and suggested driving line/speed indicators, and fighting games with granular, smooth-scaling training modes with extensive on-screen instruction.
- davidpfarrell 2y agoAwesome - I have designed similar things in my head dozens of times over the years. Often I end up drifting into thoughts away from these deterministic patterns and into a more adaptive approach based on how the user is performing - At least at the 'closer to the boss' parts of the levels ... Just the same thanks for sharing and I'm enjoying playing around with this !
- YurgenJurgensen 2y agoYou have just described Warning Forever, which was reasonably popular in its niche back in the day.
- imiric 2y agoWhile these patterns are pretty to look at, I don't think bullet-hell shmups are fun to play. The challenge becomes to very carefully dodge bullets that appear in the same pattern over and over again, instead of, you know, actually shooting at the enemy. Yes, dodging is part of shmup gameplay, but I find it much more enjoyable when the bullets don't have a recognizable pattern, and when the goal is not to overwhelm you with the amount of them on the screen. I love the shmup genre, but would rather play traditional ones like Raiden, DemonStar, R-Type, Gradius, Blazing Star, etc., and modern entries like Sky Force, than Ikaruga and the like. But, hey, to each their own. :)
- YurgenJurgensen 2y agoIf you’d ever played danmaku games at a high level, you’d realise that the patterns are not the same over and over. Most well-made games have many elements of positional advantage and economy of movement to shape the bullet patterns in your favour. R-Type, on the other hand, is a pure memorisation game, much more so than Touhou or Donpachi, and definitely features the same patterns every single time.
- imiric 2y agoRight. Memorization of patterns is definitely a staple of most shmups. I suppose I didn't express myself properly. What I meant is that when there is a pattern in the objects you have to avoid, and the number of them becomes overwhelming, it doesn't make the gameplay more enjoyable (IMO). Those micro movements you mention surely require a lot of skill, but to me they're just not fun. Take a game like The Binding of Isaac as another example, whose core mechanic is a shooter. Twin-stick shooters are an evolution of the shmup after all, where the player is in control of their attack direction. What makes TBoI so much fun is the unpredictability of enemy movement and randomness of objects you have to avoid. It does have areas where attacks are overwhelming, but player progression is usually well balanced (though it is possible to become overpowered as well :), so it's never just a dodging game. But I concede that my experience with bullet-hell shooters is limited, due to this initial dislike of their core mechanic. On a slight tangent, this is why I don't see the appeal of the recently popularized "survivors-like" games. Sure, there are swarms of enemies, but they come at predictable patterns, so the main mechanic is just strafing around them. Add to that that they remove your ability to aim or fire, and the gameplay boils down to just using directional keys in a specific order. It's so boring and unengaging. But then again, there are entire genres of clickers and idlers I don't get either, so this is purely a subjective take. :)