5 ms·
I suppose now the engine evaluates all of the Locations that any pattern could ask for every frame (or more often?) so it can store a buffer of past values, all
by anonymoushn 2y ago
I suppose now the engine evaluates all of the Locations that any pattern could ask for every frame (or more often?) so it can store a buffer of past values, all so we could avoid writing aim() and then wait().
Then we write a new class or add new members to our class every time we want to do anything even slightly different. For example we'll have two members for doing a fixed angular and temporal step between bullets, then another for controlling the number of volleys of a fixed number of simultaneous bullets with fixed angular and temporal steps between them, then a couple more for controlling linear increases and decreases in the volley count, then when implementing Border of Wave and Particle we may as well add quadratic terms to all of the above (although we will only need one of them). Later we'll realize that our linear step-up-and-down knob doesn't actually differentiate between these sorts of things:
e
.
. .
. . .
. .
.
e
.
. .
. . .
. .
.
e
.
. .
. . .
. .
.
so we'll turn it into two knobs or add some hack that lets us start adding angular increments after a delay in the middle of a single non-programming data-command.
To allow some enemies to aim some single bullets to the left or the right of the player, we'll just add an arithmetic expression evaluator to our location member too :)
- CyberDildonics 2y agoI suppose now the engine evaluates all of the Locations that any pattern could ask for every frame Is that what the custom language is doing? Why would that be necessary? Someone asked the question and I answered. Even if you wanted to write new stuff, why not just use lua?
- anonymoushn 2y ago> Is that what the custom language is doing? Why would that be necessary? Sorry, I guess instead I should ask "How does your engine fire at locations that are evaluated in the past?" One way is to keep a queue. Honestly this whole business of targeting locations in the past is not a dealbreaker to me. I don't know of games that need it. It's sufficient to implement this sort of delay by spawning some non-damaging thing under the player and having it spawn bullets later, or aiming at some time and then firing later. > Even if you wanted to write new stuff, why not just use lua? I listed some reasons here: https://news.ycombinator.com/item?id=41257693 https://news.ycombinator.com/item?id=41257693
- CyberDildonics 2y agoSorry, I guess instead I should ask "How does your engine fire at locations that are evaluated in the past?" One way is to keep a queue. Again, how does the language do it? If you query past values you can then know to keep track of past values. Also there is no reason to use coroutines to make game bullets. You can just let a function keep track of state if it needs to and call it every frame. At the core of all this is classic examples of over complicating things. As soon as someone declares they are making a brand new language with VM and coroutines to decide how bullets emit in a simple shooter, anyone else involved should be stepping in and putting a stop to it.
- anonymoushn 2y ago> Again, how does the language do it? If you query past values you can then know to keep track of past values. I don't think that asking for something causes you to have recorded it in the past! In the various languages you would aim and then wait. Here it is in Firedancer: aim() wait(18) and in BulletML: <action label="main"> <fire> <direction type="aim">0</direction> <bullet> <speed>1</speed> <action> <vanish/> </action> </bullet> </fire> <wait>18</wait> <fire> <direction type="sequence">0</direction> <bullet> <speed>2</speed> </bullet> </fire> </action> This is a bit of a hack. We fire a bullet that immediately disappears to set our firing direction for the direction type="sequence" that we will use 18 frames later. > Also there is no reason to use coroutines to make game bullets. You can just let a function keep track of state if it needs to and call it every frame. Quite uniformly, developers of bullet hell games do not want to separate their code into basic blocks delimited by any part that might involve time passing in the game, and they don't want to give up on subroutines existing. Turning all of your code inside-out and giving up on subroutines existing obviously makes the work extremely tedious and makes it hard to iterate or to know what's going on in some file you haven't touched in a week. I don't necessarily advocate for making a new language and VM, but if you review the tools people actually use for this stuff, nobody does what you say everyone should be doing. For a third example, here's a danmakufu tutorial in which we learn that we should make Marisa's laser not freeze the game by adding a yield to a loop: https://sparen.github.io/ph3tutorials/ph3u1l5.html https://sparen.github.io/ph3tutorials/ph3u1l5.html I have done this stuff in lua, but in any real game I would probably want the game state to be serializable.