Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a fighting game input buffer. #100

Closed
ca3games opened this issue Sep 24, 2019 · 84 comments
Closed

Add a fighting game input buffer. #100

ca3games opened this issue Sep 24, 2019 · 84 comments

Comments

@ca3games
Copy link

Describe the project you are working on:
A 2D remake of a NES fighting game.

Describe how this feature / enhancement will help your project:
It would make my life easier, implementing an input buffer for my game.

Show a mock up screenshots/video or a flow diagram explaining how your proposal will work:
A 2D fighting game input buffer.

Describe implementation detail for your proposal (in code), if possible:
Basically a circular list that reads the inputs and output a signal if a certain movement is input.

If this enhancement will not be used often, can it be worked around with a few lines of script?:
Sure, but making a good input buffer is not a trivial solution, my code while it works, is buggy and I think having a basic Input buffer supported by the engine would be good for action games, maybe devs who want a cheat code, fighting games, metroidvanias, action rpgs, etc.

Is there a reason why this should be core and not an add-on in the asset library?:
Is not such a trivial solution, specialy for guys who may be more on the art side than programming side, like me.

@LikeLakers2
Copy link

LikeLakers2 commented Sep 25, 2019

Keeping in mind that I've never tried to implement a input buffer before myself, and therefore wouldn't know if it entails anything else: Perhaps the engine could keep track of the last time each action in the input map was activated/deactivated, using something like OS.get_ticks_msec? Then you could call something like Input.is_action_recently_pressed("some_action_name", time_in_seconds) (returns true if the action has been pressed within that time) or Input.get_action_last_press("some_action_name") (returns a float representing the amount of time since the action was last pressed). I wonder if something like this could be an acceptable solution?

@Calinou
Copy link
Member

Calinou commented Sep 25, 2019

Since a majority of games won't need this, this can likely be provided as an asset on the Asset Library 🙂

@golddotasksquestions
Copy link

golddotasksquestions commented Sep 25, 2019

@Calinou How can you dismiss this proposal right away with the assessment that the "majority of games" (whatever this means), won't need this feature before anyone making games had the time to express their need here?

Input buffers would be useful for a variety of already existing genres (OP named a few: cheat code, fighting games, metroidvanias, action rpgs.) but would also allow to easily test and come up with new game mechanics and concepts, would be fantastic as one line solution for rhythm games and quicktime events as well for debugging.

@Zylann
Copy link

Zylann commented Sep 25, 2019

@golddotasksquestions because "proposal for it to be core" means that feature would have to be ALWAYS present in the engine, and because of this, maintained FOREVER by core devs, while only a handful of projects will actually use it. I say "handful" and "will" because it looks like that feature wasn't requested for years. It would have been if it was an actual common need rather than "a cool thing to have". Also that feature is easy to figure out and implement as an addon to help people less proficient at coding, so... that's why an addon makes sense.
It doesn't mean it shouldnt be available in Godot, it means it should be available as an option.

@ca3games
Copy link
Author

Since a majority of games won't need this, this can likely be provided as an asset on the Asset Library slightly_smiling_face

I already mentioned a few cases where this may become handy, like a konami cheat code, fighting games, DMC clones, rythm games, smash clones, metroidvanias, action rpgs.
Even FPS could use an input command for things like dash or cover.
It's a very handy feature to add.
Even GTA had some kind of cheat code.

@golddotasksquestions because "proposal for it to be core" means that feature would have to be ALWAYS present in the engine, and because of this, maintained FOREVER by core devs, while only a handful of projects will actually use it. I say "handful" and "will" because it looks like that feature wasn't requested for years. It would have been if it was an actual common need rather than "a cool thing to have". Also that feature is easy to figure out and implement as an addon to help people less proficient at coding, so... that's why an addon makes sense.
It doesn't mean it shouldnt be available in Godot, it means it should be available as an option.

I don't think is that horrible complex feature to add, is mostly a circular buffer that receives input from the input class and can output an user made custom signal.
Maybe as an aditional function of a class could be implemented, I kind of did it once for a game of mine in godot as a script, but I'm not the best coder, so it was kind of clumsy.

@girng
Copy link

girng commented Sep 25, 2019

This can be done with timers and a dictionary/array to store the commands I believe?
If done as an Addon, would be neat. With a nice API, etc.

@golddotasksquestions
Copy link

golddotasksquestions commented Sep 25, 2019

I say "handful" and "will" because it looks like that feature wasn't requested for years.

What's the purpose of having a "proposal" repo if only proposals that have been made before the existence of this proposal repo are even considered for a discussion and everything else is immediately shut down as with the argument "noone has asked for this so far", "bloat", or casted to the asset libary (a jungle you only ever find something unless someone directly points you there)

If your goal is to stop people from making proposals to improve the engine, not the asset library, why have a proposal repo in the first place?

@Zylann
Copy link

Zylann commented Sep 25, 2019

@golddotasksquestions proposals can be made with arguments which many other people can relate or have related in the past (and eventually will when seeing your post, as we answered it). It's part of what makes them solid (but not mandatory indeed). Also this is just one part of my explanation, you have to read it as a whole. I'm just trying to explain why @Calinou 's suggestion makes sense, not stopping people from proposing features.

@golddotasksquestions
Copy link

golddotasksquestions commented Sep 25, 2019

It would have been if it was an actual common need rather than "a cool thing to have".

If you want to find out if there is common need to have it in core, you cannot dismiss it just a few hours after it has been posted. We all know Godot Github is frequented more often by contributors then is is by general users.

@willnationsdev
Copy link
Contributor

willnationsdev commented Sep 25, 2019

@golddotasksquestions

What's the purpose of having a "proposal" repo if only proposals that have been made before the existence of this proposal repo are even considered for a discussion

I think this is a bit of an over-exaggeration. They are just saying that there have been no previous Issues requesting the feature, so suggesting that something which can be implemented as a separate asset should instead go into the main repository is overkill.

everything else is immediately shut down as with the argument "noone has asked for this so far", "bloat"

And with good reason. Those are exactly the kinds of things that shouldn't go into the main engine repository.

I think the difference of opinion here is in what should be considered "bloat". While you are seeing, "this would be useful for a variety of games," the devs are seeing something that can easily be implemented with a script-based solution. The whole idea of having the proposals repo is to better filter OUT things that match that scenario (Edit: unless it is provably desired heavily by the community - more on that later).

casted to the asset libary (a jungle you only ever find something unless someone directly points you there)

This implies that we need to 1) improve the Asset Library's discoverability and/or 2) add support for other online asset vendors (#12). The solution is not to start porting things that we can easily host and develop separately all into the main engine repository.

If you want to find out if there is common need to have it in core, you cannot dismiss it just a few hours after it has been posted. We all know Godot Github is frequented more often by contributors then is is by general users.

The fact that engine change proposals are more heavily seen by contributors more so than general Godot users is a natural side effect of hosting the GIPs on GitHub. That won't be changing anytime soon (probably), so if people want more public feedback on their idea, that's what sharing the proposal on social media is for. I would invite OP to do that.

What is more practical would be implementing this as a separate plugin first (since that can be done easily enough) and then, if enough people are interested in and using that plugin, then it's a safe bet that people would appreciate having it merged into the engine. It's the same kind of thing that I'm going to have to do for #13.

Make a proof of concept. Prove the people want it. Get a preliminary implementation up and running. When it's clear that it would be useful as an integrated thing, then submit a PR. Converting script code to engine code isn't all that hard, so no biggie.

@golddotasksquestions
Copy link

golddotasksquestions commented Sep 25, 2019

Prove the people want it.

I won't rally for a race of "who clicks that thumbs button first before the proposal is dismissed". If people want this feature in core, eventually more people will thumb it up. If not, then it simply won't happen. The only thing sure is that you won't get a meaningful result within a few hours of submitting a proposal because you don't have regular users eyeballing the proposal list every day. Immediately dismissing it counters the fundamental idea of a repo called "proposals". If we also had an official "ideas" repo, then this discussion could be moved there, but we don't.

When it's clear that it would be useful as an integrated thing, then submit a PR. Converting script code to engine code isn't all that hard, so no biggie.

You know very well that I'm not capable of doing that (yet). OP is in the same boat.

@willnationsdev
Copy link
Contributor

I won't rally for a race of "who clicks that thumbs button first before the proposal is dismissed". If people want this feature in core, eventually more people will thumb it up. If not, then it simply won't happen. The only thing sure is that you won't get a meaningful result within a few hours of submitting a proposal because you don't have regular users eyeballing the proposal list every day.

And having a many proposals in exactly this style is something they want to avoid here (which you also acknowledge with the "ideas" suggestion). Too many "maybe someday people will want this" Issues sitting around clutters the space reprehensibly, so yeah, they shut them down if they aren't clearly defined, imminently useful things with a demonstrable use case.

If we also had an official "ideas" repo, then this discussion could be moved there, but we don't.

I agree that we need a place for things like this. My suggestion in #47 for things that involve clearly useful assets/addons/plugins/modules/templates/projects would cover this case. Rather than re-iterating the same old arguments here as we do there though, we should simply refer to this case in that Issue and move along; simply close this as a "should be a separate addon" is good for now. It can be re-opened and migrated later on. Maybe @Xrayez can convert it into a tracker that starts cataloging all of the Proposal Issues to which it could reasonably apply.

Regardless of whether an open Issue exists somewhere for it, the status in practical terms for "when should this be merged into the engine" doesn't change. If someone builds it separately and it becomes popular, i.e. people star / download the addon a lot, then that will be evidence we can point to when suggesting that it be integrated into the engine in a formal Proposal. Until then, there is no proof of its public viability that warrants full-time maintenance by the core team, ergo, the Proposal should be closed.

You know very well that I'm not capable of doing that (yet). OP is in the same boat.

I was just saying that, once a formal implementation is done (which anyone who can write script code can do), migrating the code is quite easy. Any developer would be able to assist with that. I wasn't implying that you guys would have to necessarily.

Anyway, the godot-extended-libraries/godot-ideas repo is still hanging around. @ca3games is free to transfer the Issue there if they want. There's nothing stopping us from using it and promoting the Issues on social media. Once Juan/Remi make a decision on #47, then we can see if those issues get moved to a different place in the godotengine organization or if they stay where they are. Either way, this is not the place to argue the case.

@clayjohn
Copy link
Member

This is not a case of "if the idea is popular enough it will be merged". The reason this proposal will not be accepted is because there is no benefit to having this in core rather than providing it as a downloadable script.

The last question in the template is:

Is there a reason why this should be core and not an add-on in the asset library?:

Saying that it is too complicated for artists is not a reason to include it in core. That is just asking the core developers to code your game for you. Simple, reusable scripts like this belong on the asset library and/or in the community based godot-extended-libraries (as willnationsdev, kindly pointed to).

Community interest is only a valid metric for proposals that meet the base criteria set out in the template.

@Xrayez
Copy link
Contributor

Xrayez commented Sep 25, 2019

This kinda illustrates my previous thoughts, there's a difference between a use case and a general-purpose proposal. One person is unlikely to provide many use cases (different game genres for instance), so he has to document it at least. Seeing this proposal being opened, I created another similar one #104 which I felt like is really related to this (otherwise I wouldn't create it in the first place tbh).

My point is that if enough use cases pile up for a particular problem, it can prove to be useful to be part of the core, not necessarily what the use case describe but to satisfy all those use cases to simplify implementing them via script/plugin/module etc.

@willnationsdev
Copy link
Contributor

willnationsdev commented Sep 25, 2019

@Xrayez

Well, #104 does things "correctly" where you have a valid use case, i.e. the separate system you describe when explaining the context, but the actual suggested change is scripting API updates and a new method in the Input class, i.e. things that can only be done with source code changes.

This proposal, on the other hand, has all of its necessary changes bundled into the "separate system". No part of it actually requires changes to the engine. Without any necessary engine changes, it has no purpose in being a "Proposal to Improve Godot"/"Godot Improvement Proposal." It fits better in godot-ideas.

@LikeLakers2
Copy link

LikeLakers2 commented Sep 25, 2019

@willnationsdev Reading that is really confusing me as to what is allowed in this repo. If a proposal has to require changes to existing systems, then what's the point of ever suggesting new features or systems now? Don't new features or systems, by their very nature, bundle most/all of their changes into the separate system?

Or am I somehow misunderstanding this?

@willnationsdev
Copy link
Contributor

willnationsdev commented Sep 25, 2019

@LikeLakers2

Let's say I want to write some kind of script to do something. This is my "task".

If I can fully implement the task's features with script code, but I want the engine to come with my task pre-implemented and available, then I should NOT create a Proposal for adding that task's solution to the engine. It should go in a different repository that can be maintained independently and downloaded as a separate asset in the Asset Library.

If it is impossible to write the code purely with scripts, i.e. if you need to make engine/editor changes to write that script code the way you want to, then you can submit a proposal to make the necessary engine/editor changes while stating your task as the "use case"/problem you are attempting to solve.

So, for example, this Issue proposes that we introduce an input buffer into the engine. However, the code for this can be fully written in script code. It does not require any engine or editor changes to function. Having it in the engine would simply be a matter of convenience. New features as a matter of convenience, however, when they can be easily done with scripts instead of engine changes, are things the core devs want isolated to separate repositories and so should not clutter the proposal repository.

#104's OP is attempting to do things with scripts, with a similar purpose, but they specifically state that it cannot operate efficiently because the engine's API does not support the operation they want to perform. Their proposal is to add the necessary operations to the API. It IS NOT a proposal to add their scripted functionality to the engine. They have a problem that cannot be resolved through scripts. They are suggesting that we fix the things to resolve that obstacle (which empowers the script code to do more than it could before, i.e. enables users to handle their own problems more effectively).

This results in less of a maintenance burden on the core team and improves the usability and power of Godot's scripting API for solving future problems.

Edit:

But then what's the point of ever suggesting new features now, if it has to require changes to other systems?

It's not that it requires changes to other systems. It's that you must have a problem that you could not already do yourself and then with the changes, you are then able to solve your problem. If you can already solve the problem on your own, then it belongs in an addon/plugin/module, not the engine repository.

@willnationsdev
Copy link
Contributor

Another good example is #103. I have a change to the engine/editor that I would like to make (an Instantiation Palette toolbar). However, I know that it may or may not be desired as an integrated part of the engine. It can be entirely written via script code already, so what I should do is write a plugin that adds the features to the editor.

However, as I'm thinking about how I might implement it, I realize that it has all these different performance limitations that will inhibit its responsiveness as the project's size grows. To avoid this, I came up with a list of engine/editor changes that would be required to improve its performance.

I didn't submit a proposal to add the toolbar to the editor (because even if Godot could really use it, it belongs in a separate plugin). I submitted a proposal to change things impossible for scripts that would enable my plugin to behave efficiently.

I've heard mixed things about whether "a highly successful, generic plugin that assists with game development on a large scale" can be considered for editor integration though. @clayjohn earlier said no. I've heard Remi say yes in the past. So on that point, I'm not 100% sure what the word is today.

@LikeLakers2
Copy link

LikeLakers2 commented Sep 26, 2019

I'm still confused, possibly even more so than before I read your comments.

If I can fully implement the task's features with script code, but I want the engine to come with my task pre-implemented and available, then I should NOT create a Proposal for adding that task's solution to the engine. It should go in a different repository that can be maintained independently and downloaded as a separate asset in the Asset Library.

If it is impossible to write the code purely with scripts, i.e. if you need to make engine/editor changes to write that script code the way you want to, then you can submit a proposal to make the necessary engine/editor changes while stating your task as the "use case"/problem you are attempting to solve.

[...]

It's not that it requires changes to other systems. It's that you must have a problem that you could not already do yourself and then with the changes, you are then able to solve your problem. If you can already solve the problem on your own, then it belongs in an addon/plugin/module, not the engine repository.

I don't understand the sense in this line of logic. Many (if not all) of the nodes (or perhaps even the SceneTree concept itself) already within the engine could be ripped out and put into GDScript with next to no penalty (besides a performance hit). Given the line of logic I'm seeing, that means they don't belong in the engine, as they could be made into assets, therefore they should.

For example, I want to draw text to the screen. You could tell me to use the Label control. Or I can use CanvasItem.draw_text. Let's make a theoretical from this, and let's say the Label control doesn't already exist. I make a suggestion for such a Label node on this repo. From what I'm reading here, I would expect "You can draw text already using CanvasItem.draw_text" or "This would be better suited as an asset on the asset library" as the response I'd get, as everything about the Label control can already be replicated in GDScript code without changes to the engine. Yet, because the Label node already exists in the core and is much easier to use than CanvasItem.draw_text, it is widely used and is how we recommend people draw text to the screen. I don't understand how this line of logic holds up.

The same could be said about the Sprite node, being replicable with CanvasItem.draw_texture. Or the MultiplayerAPI, using the PacketPeer class. We can implement a JSON parser ourselves in GDScript, with little more than a few String functions to back it up. Even the InputMap concept could be replicated using scripts. The only reason we still need them in the engine is because they're already widely used nodes... but they're widely used because they're in the engine... this feels like a big, convoluted Catch-22 to me. (not sure if there's any better term to describe this)

I've heard mixed things about whether "a highly successful, generic plugin that assists with game development on a large scale" can be considered for editor integration though. @clayjohn earlier said no. I've heard Remi say yes in the past. So on that point, I'm not 100% sure what the word is today.

This is one of the other issues I have with the whole "make it an asset" argument that I keep seeing on this repo: If I make an asset for something suggested here/elsewhere, I don't know if it'll be allowed in the engine later down the line (regardless of the asset being useful to people), specifically because it's already a publicly-available asset (despite that having been the original suggestion because it wasn't thought to be useful to the engine).

So I'd be very interested in hearing a concrete answer on this.

@willnationsdev
Copy link
Contributor

@LikeLakers2 it does sound like a Catch-22 (that's the right term). I think it is supposed to be somehow about balancing usability against the technical debt of core devs maintaining it. My guess is something along the lines of, "we like the current state of the core engine. Keep it where it is unless absolutely necessary." There are even plans to strip out things like InterpolatedCamera and VehicleBody, afaik, so that they will exist as assets (probably GDNative).

I too would love to hear more about how far down that particular rabbit hole goes.

@girng
Copy link

girng commented Sep 26, 2019

@ca3games If you don't mind and since you have the code already, you can submit it to https://github.com/godot-extended-libraries/godot-next I think. Would be a very nice addition. Or, it could just be released as an addon perhaps.

@willnationsdev
Copy link
Contributor

No, yeah, that sounds like a good addition. If @ca3games submits a PR, I'll review it to see if I'd like any changes made before merging.

@KoBeWi
Copy link
Member

KoBeWi commented Sep 26, 2019

@LikeLakers2 The reason there's Label and Sprite node in the engine is that they provide much more functionality than simply using draw_string or draw_texture. The label.cpp code has over 700 lines of code and it's not something you can replicate easily. Also lots of Control nodes are used internally by the editor, so they need to be in core anyways. Also², I used Sprite in literally every of my (2D) projects, whereas what's proposed here I needed, like, twice and it took me just few lines to implement it.

So most of things in the core are integral parts of the engine or something used so extremely often that it makes it obvious that they should be there. There are some nodes that could qualify as add-on material, and they might be eventually moved there if the plan for official plugin library is realized (godotengine/godot#19486).

@ca3games
Copy link
Author

@ca3games If you don't mind and since you have the code already, you can submit it to https://github.com/godot-extended-libraries/godot-next I think. Would be a very nice addition. Or, it could just be released as an addon perhaps.

No, yeah, that sounds like a good addition. If @ca3games submits a PR, I'll review it to see if I'd like any changes made before merging.

I have made a basic demo with my own implementation, but needs maybe a refactoring or better design.
https://github.com/ca3games/Godot-fighter-demo
Here's my implementation of said issue.

If anyone is willing to take a look at this issue, here's an example of an input buffer on the XNA old educational demoes.
https://github.com/SimonDarksideJ/XNAGameStudio/wiki/Input-Sequence

So far my code has similar ideas, but is lacking a timer to clean the input after there's not input, and they also seem to use another trick, which is to merge inputs if they're too close.

@LikeLakers2
Copy link

LikeLakers2 commented Sep 27, 2019

@KoBeWi

The reason there's Label and Sprite node in the engine is that they provide much more functionality than simply using draw_string or draw_texture. The label.cpp code has over 700 lines of code and it's not something you can replicate easily.

I think you misunderstood the point. I understand it's not something you can replicate easily, and I understand those two nodes do much more than CanvasItem.draw_string and CanvasItem.draw_texture (Label does a good bit of math with the position, for example). The problem is that you can replicate them as assets for the Asset Library, even if it takes a lot of work. From the line of logic I was seeing from Will, the fact that they could be made as assets means that they should be made as assets, rather than be included in the engine.

We can both agree that removing the Sprite node, or Label node, or any of the Control nodes would be a bad idea, considering their widespread usage. But the problem I was seeing is that this line of logic never takes that into account, that it's a bad idea. It never considers whether it's a good idea or a bad idea for something to be made as an asset, compared to being in the engine. And if the logic can't hold up against the nodes already in the engine, then there's no reason we should be using it to determine which proposals get approved, since basically anything can be made with Godot's asset system... and since basically anything can be made as an asset, next to nothing will ever get approved under this line of logic.

(edit: removed the second part of this comment; I felt it might come off as rude, which wasn't my intention, and I couldn't really find a better way to word it)

@Zylann
Copy link

Zylann commented Sep 27, 2019

I think what makes more sense in what @willnationsdev says, is not really that they "can" be replicated at all (this argument alone doesnt hold), but more that they require a lot of work for a frequent use. Some things really can't be replicated (like access to an OpenGL feature) but you can't say that of all features. But the way to measure these things is relative: less proficient coders find it hard, other coders find it easy. It's an ever-going battle, finding the right balance can't content everyone :p

@golddotasksquestions
Copy link

golddotasksquestions commented Sep 27, 2019

is not really that they "can" be replicated at all (this argument alone doesnt hold), but more that they require a lot of work for a frequent use.

This argument is also very hard to follow since the core code is filled to the brim with methods that are just shorthand for a few lines of code or less: Take myarray.pop_back(), myarray.push_back(), myarray.front(), myvector.angle(), myvector.length() just to name a few.
Correct me if I'm wrong, myvector.length() is the same as sqrt(pow(abs(myvector.y),2) + pow(abs(myvector.x),2)), is it not?
Even worse, myarray.front() is to my understanding even exactly the same as myarray[0], no?

Don't get me wrong, I love choice and I love readable code. I like to have and use those examples.

But in the light of the above, how can a request to add an actually valuable method to the Input class (like: Array set_input_buffer ( int buffer_length, bool include_time_between_inputs=false, bool include_mousemotion=false ) , Array get_input_buffer ( ) )
be considered immediate bloat to the core without even giving folks adequate time to express their need. Was myvector.length() not included to the core for exactly the same reasons OP has requested an input buffer? To make life easier, to get projects done faster and more readable and Godot more accessible for people who are less proficient in the technicalities of coding.

This sucks.

@willnationsdev
Copy link
Contributor

cc-ing @reduz and @akien-mga so that they are aware that more #10 -like discussion is happening in this Issue too. Slightly different arguments being put forth though, by @LikeLakers2.

@SuperTrailMix
Copy link

One thing that should be brought up is the importance and widespread usage of input buffers in video games. Input buffers exist in a majority of all video games that exist; they reduce the frustration of inputting repetitive actions and allow for combination actions that don't necessitate frame perfect inputs. Given time I could produce a list of every video game that isn't a fighting game that has an input buffer, and the list would be so massive that it would eclipse the total text of the entire rest of this thread. Not having an input buffer of some kind nearly guarantees a game that isn't enjoyable to control, unless that game is immensely simplistic.

I bring this up to this topic because at the current moment, people are arguing that this wouldn't be used enough to necessitate its existence. I don't think that's a fair statement, as most people who wouldn't implement an input buffer into their game are making that decision because of a lack of understanding of how important having one is.

@girng
Copy link

girng commented Oct 1, 2019

One thing that should be brought up is the importance and widespread usage of input buffers in video games. Input buffers exist in a majority of all video games that exist; they reduce the frustration of inputting repetitive actions and allow for combination actions that don't necessitate frame perfect inputs. Given time I could produce a list of every video game that isn't a fighting game that has an input buffer, and the list would be so massive that it would eclipse the total text of the entire rest of this thread. Not having an input buffer of some kind nearly guarantees a game that isn't enjoyable to control, unless that game is immensely simplistic.

I bring this up to this topic because at the current moment, people are arguing that this wouldn't be used enough to necessitate its existence. I don't think that's a fair statement, as most people who wouldn't implement an input buffer into their game are making that decision because of a lack of understanding of how important having one is.

It's already possible to do in Godot.. I don't know what you mean by "to necessitate its existence"

I think it's whether this is added to the core, or used as an addon. I think the lead devs will lean towards the latter

@LikeLakers2
Copy link

LikeLakers2 commented Oct 4, 2019

@golddotasksquestions Thanks for the feedback. I really appreciate it.

However, I want to make a reply to your suggestion to use the { timestamp: [[input, duration]] } syntax. While I understand that you find this syntax elegant (and perhaps understandable to you), I find it hard to understand (even after you've already explained it to me), and I worry that this may extend to other users trying to understand the syntax.

To explain why I think this, I want to explain to you how the engine normally uses arrays and dictionaries.

An array will normally be used to denote several values that are not necessarily related to each other, but are usually of the same type of information. For example, take a shopping list. A shopping list, shown as an array, could be ["Bread", "Eggs", "Milk"]. The different items are all grocery items, but are not necessarily similar in other ways.

A dictionary, on the other hand, is normally used to denote several key->value pairs that are related to each other, but that are usually not of the same type of information. Going back to our shopping list example, each item on our shopping list could have additional information attached to it. So for something like bread, we might have {"item": "Bread", "aisle": 12, "shelf": "top"} to represent that we want an item Bread, and that it is located on the top shelf of aisle 12. This new information is linked to the item "Bread", as it is related to the bread by means of being its store location, but this new info does not contain the same type of information as the other pieces of info attached to "Bread".

Your syntax, while certainly describing the data in a meaningful way, unfortunately does not follow these rules. As it does not follow the same rules that the engine normally uses, I worry that this inconsistency will confuse many users who try to use this API, even if we do try to explain it to them in the docs. And even if it doesn't confuse people, I would still take issue with it not being consistent with the rest of the engine.

(P.S. I'm going to pre-emptively apologize, as I get the feeling that this explanation may not make you feel too happy, but I'm not sure why I'm getting that feeling. So, sorry. But I hope you understand why I made this explanation.)


I also have a reply to another bit of your comment:

get_action_press_times(action)
I would not call it "action" though, because it might not always be an action, but maybe just an input.

Indeed, it will not always be an action. That said, the only real reason I'm using "action" here is because I don't really know of a better term to use. So meh. :/

@golddotasksquestions
Copy link

golddotasksquestions commented Oct 4, 2019

@LikeLakers2 No need to apologize, I really appreciate your input.
I'm not really much experienced with the use of dictionaries, they may not be the most ideal data structure. The reason I chose a dictionary as wrapper in my examples was because they would result in a more human readable structure compared to an arrays in array in array. However I think I also read arrays are more performant compared to dictionaries, so maybe that alone would be reason enough to use an array as wrapper.
Using only arrays instead of dictionaries would make little difference to my proposal though:
(this example data is the same as in the visualization above)

dictionaries and arrays:

if Input_Buffer.has( {	124: [[KEY_3, 50], [KEY_9, 710, NO_INPUT]],
			483: [[ARROW_DOWN, 50], [ARROW_RIGHT, 50], [KEY_ENTER, 50]],
			775: [[ARROW_UP, 50]],
			861: [[KEY_9, 100]],
			1180: [[ARROW_UP, 100]] } ):
	do stuff

would just be

if Input_Buffer.has([	[124, [[KEY_3, 50], [KEY_9, 710, NO_INPUT]]],
			[483, [[ARROW_DOWN, 50], [ARROW_RIGHT, 50], [KEY_ENTER, 50]]],
			[775, [[ARROW_UP, 50]]],
			[861, [[KEY_9, 100]]],
			[1180, [[ARROW_UP, 100]]] ]):
	do stuff

In words:

if Input_Buffer.has([[timestamp, [[input or action, duration, optional flag NO_INPUT]]]]):
	do stuff

All of the above would all be a timestamp-priority format. An input-priority format would work as well, same data as before:

In words:

if Input_Buffer.has({input or action: [[timestamp, duration, optional flag NO_INPUT]]}):
	do stuff

Input-priority format, dictionaries and arrays:

if Input_Buffer.has({	KEY_3: [[124, 50]],
			ARROW_DOWN: [[483, 50]],
			ARROW_RIGHT: [[483, 50]],
			ARROW_UP: [[775, 50], [1180, 100]],
			KEY_9: [[124, 710, NO_INPUT], [861, 100]],
			KEY_ENTER: [[483, 50]] }):
	do stuff

Input-priority format, only arrays:

if Input_Buffer.has([	[KEY_3, [[124, 50]]],
			[ARROW_DOWN, [[483, 50]]],
			[ARROW_RIGHT, [[483, 50]]],
			[ARROW_UP, [[775, 50], [1180, 100]]],
			[KEY_9, [[124, 710, NO_INPUT], [861, 100]]],
			[KEY_ENTER, [[483, 50]]] ]):
	do stuff

@LikeLakers2
Copy link

LikeLakers2 commented Oct 4, 2019

@golddotasksquestions All three pieces of data (the timestamp, the input, and the duration) are as equally necessary as each other to describe a recorded input, and they are all related to each other in a way. Therefore, I think it would be best to format the data as dictionaries, like so:

[
    {"timestamp": 124, "input": KEY_3, "duration": 50},
    {"timestamp": 483, "input": ARROW_DOWN, "duration": 50},
    {"timestamp": 483, "input": ARROW_RIGHT, "duration": 50},
    {"timestamp": 775, "input": ARROW_UP, "duration": 50},
    {"timestamp": 1180, "input": ARROW_UP, "duration": 100},
    {"timestamp": 124, "input": KEY_9, "duration": 710, "no_input": true},
    {"timestamp": 483, "input": KEY_ENTER, "duration": 50}
]

Indeed, this means repeating data where you could possibly make it a bit more compact, but it is also far more readable (it describes itself). It also fits with the style of how the engine already does things... and from experience, I would guess that this sort of format is a lot easier to code, as now we're not spending extra code compacting things where we honestly didn't need to.

The only other option we have is making a class out of that style of dictionary, with properties timestamp, input, duration, and no_input. However, I'm not sure if that would be acceptable in the Godot code, as they typically refrain from such small data classes... or so the docs have shown me. Regardless, using a class would have the same effect as a dictionary in this instance.

Also...

However I think I also read arrays are more performant compared to dictionaries

Perhaps, but if it is more performant, it's so imperceptible at such small sizes that I don't honestly think it would matter to anybody. Someone may be able to correct me on this, but I don't believe dictionaries really get slow unless you're doing operations on dictionaries with thousands upon thousands of key->value pairs.

@golddotasksquestions
Copy link

golddotasksquestions commented Oct 4, 2019

@LikeLakers2 As long as the aforementioned UX would be there, I personally don't care so much about the which specific data structure and format to use. I also would be more than fine with what you are proposing here in your last comment (as I am sure other people know more about what is ideal than me).

@SuperTrailMix
Copy link

SuperTrailMix commented Oct 10, 2019

Now, to not derail this topic even more, I'm really confused by @AmericanTrailMix 's comment. It sounds almost like input buffers are the most important thing ever and every game needs this. Unless I'm misunderstanding something, I needed this functionality literally twice - one was fighting game (surprising) and the other was a rogue-like with combos. Out of over 15 bigger and smaller projects. You don't need this in platformers, RTS games, FPS games, jRPG games, racing games and probably other genres. And I doubt these games are "immensely simplistic". But it might be possible I don't understand what we are talking about here. I'd really like to see that huge list of games using input buffers, along with their use cases ;)

Platformers, racing games, and "other genres" absolutely have input buffers. Input buffers aren't about inputting quarter circles, or having button combos, or cheat codes, or anything like that. Input buffers are about game feel, and making sure that the controls feel responsive and solid.
One example of a dramatically noticeable input buffer is the games in the Soulsborne series. In fact, the input buffer is so long in games like Dark Souls 3 that often times it can kill you by making you roll 2 seconds after you pressed the button.
It's hard to come up with specific examples for games and be able to prove it, however. Obviously, I can't dig into the code of most games, and most input buffers are so small it's hard to know if they're even there. But an input buffer for, say, a platformer like Celeste, is mandatory as otherwise jumping as soon as you hit the ground would be a frame perfect input every time.
https://www.caseportman.com/single-post/2018/08/16/Input-Buffering-2D-Platforming
This page talks about it pretty well, in my opinion.

When I say "input buffers are important", I mean it. It's absolutely necessary for any game that has actions that take time, or have endlag, or what have you, to have an input buffer. Be it as short as 3 frames or long as 60, they're there so that you're not struggling to get inputs out because you didn't realize you were still on the final frame of an uninterruptible animation. Not to mean any offense, but if you're not including a jump buffer for a platformer you've made, it's probably not going to feel very good to play, especially if it proves to be a challenging and intense one like the aforementioned Celeste.

@Calinou
Copy link
Member

Calinou commented Oct 11, 2019

@AmericanTrailMix The use case you linked can be achieved with a Timer node, or even by making the jump action allow continuous jumping (i.e. "pogo sticking", which you find in many popular games today).

@LikeLakers2
Copy link

LikeLakers2 commented Oct 11, 2019

@Calinou Apologies, but I'm not sure either of those ideas would really be good ideas. Please let me know if I'm missing something.

The use case you linked can be achieved with a Timer node

It could be achieved that way, but I'm not sure what benefit it would gain from doing so.

First off, now we're tasked with managing lots of timer nodes. This means having to instantiate each one, and make sure we can keep track of which one is for which action... starting and stopping them, and so on. In some cases, it can be a mess to figure out; and in any case, I don't think this sort of timer management should be something that we make the developer implement when we could implement it in a simple manner for them.

Second, a lot of the Timer node's features are probably not going to be useful to the average need of an input buffer. While these features can be disabled, and probably wouldn't incur any noticable performance penalty even when we're using hundreds of timers with those features disabled, I don't see the need to allow for those optional features when we probably won't ever use them.

by making the jump action allow continuous jumping (i.e. "pogo sticking", which you find in many popular games today).

This solution actually wouldn't replace a input buffer. Indeed, to allow continuous jumping, the player would have to be pressing the button as they hit the ground. The thing is, the problem the article describes is when the player does press the button right before landing, but has already released it once the character hits the ground -- which can often cause the "I PRESSED JUMP!" reaction that is shown at the top of the article.

So to be able to detect this situation, we would need to implement some sort of buffer that checks if the player has pressed the button within a certain timeframe before the current point -- this is exactly what the article suggests as a solution.

@Calinou
Copy link
Member

Calinou commented Oct 11, 2019

@LikeLakers2 "Pogo sticking" is the opposite of what you described; it means you can jump as many times as you'd like by holding down the jump key just once 😉

It's a matter of taste, but it tends to be more accessible as it doesn't require players to press keys repeatedly.

@LikeLakers2
Copy link

LikeLakers2 commented Oct 11, 2019

@Calinou Oh, I understood that "pogo sticking" is that. But you said:

The use case you linked can be achieved [...] by making the jump action allow continuous jumping

My understanding of this comment is that you are saying "pogo sticking" would be a suitable alternative to implementing some sort of input buffer. This is simply not true.

To explain: From my understanding, the problem proposed in that article is that it can be frustrating when a player presses a button down for a split second, but they were just a frame or two too early with releasing the button -- and thus the game refuses to recognize the input as it was not being pressed at the correct time (when the player is on the ground), causing the all-too-well-known "I pressed jump!" response. The solution is to have some sort of mechanism for detecting a situation like that, and being able to respond to it appropriately. An input buffer would be this sort of system, but a "pogo jumping" system would not.

Whereas input buffers are meant to help where a button was released just a little too early, "pogo sticking" is the idea that holding down the button would cause the action to happen again and again, until the button is released. But as the problem in the article is about when the button is released too early, "pogo sticking" would not be a viable option, as the player would not be pressing/holding the button when they hit the ground.

It's a matter of taste, but it tends to be more accessible as it doesn't require players to press keys repeatedly.

Don't get me wrong though, both can totally be used together (and when implemented in a thoughtful manner, it could potentially make the experience even better for players of all button-pressing preferences). But my comment was not about which is better, but about which would even be a viable solution in the context of the article's proposed problem.

@girng
Copy link

girng commented Oct 11, 2019

This is random, but what does Unity do for "game input buffers"? Do they have a system like @golddotasksquestions s/s above?

@vnen
Copy link
Member

vnen commented Oct 12, 2019

This is random, but what does Unity do for "game input buffers"? Do they have a system like @golddotasksquestions s/s above?

@girng it's not random, it's a valid question. In fact, I asked before if other engines has something like it: #100 (comment) but I didn't see any answer in the discussion.

@girng
Copy link

girng commented Oct 12, 2019

Oh wow @vnen, lol. I totally forgot about that.
I did some searching online. I found this qa post, which apparently this doesn't exist in Unity either. I also stumbled upon this, this, this, and this. Seems like it can be done in C#. I guess the same could be said for Godot (done with gdscript or gdnative)

@golddotasksquestions
Copy link

golddotasksquestions commented Oct 12, 2019

from the Unity Q&A:

I'd disagree, I don't think built-in support is needed for this sort of thing, we have to leave something for developers to do still

How about if developers could focus on making games?

Here is a guy showcasing his Unity Input buffer implementation: https://www.youtube.com/watch?v=3ZDHhr50fIY. Note the necessity of setting inputs to "used" as well as the cancellation of inputs. The Dark Souls "roll" is a good example for what happens if you have no input cancellation.
Here is a MIT licensed Input buffer for unreal4 https://github.com/Isatin/UE4InputBuffer
I hear xna has something built in, not sure how useful that is.

@LikeLakers2
Copy link

LikeLakers2 commented Oct 12, 2019

@golddotasksquestions I had some thinks about how to implement your proposal. I think I'm back to supporting my own proposal over yours, at least for the purpose of input buffers. Here's why:

I realized that your proposal came off much more as an input recorder, one with a limit past which any stored inputs are deleted, than as a input buffer. While that's not a bad thing, I don't know if something of that caliber is needed for every usage of an input buffer. I don't imagine we'd need more than the last press/release times for most usages, and if we do need more than that, then your input recorder would be a decent solution (and would double as a replay-maker) -- but I don't see it replacing something simple-to-use like my solution except where my solution already doesn't work.

This isn't to say your input recorder idea couldn't be implemented and used as an input buffer -- but I think it would be better implemented as its own thing rather than as the singular solution to input buffers.

I hope this doesn't seem too rude to you. And I hope you understand my reasoning. Please let me know if I'm missing something.


Speaking of which, I would like to throw a full description of my original proposal into the pile.

My original proposal, described in detail

First off, within the Action struct, we would include two new variables: last_press_time and last_release_time. These two would get updated with the rest of the action's state, perhaps with the value of OS.get_ticks_usec, with last_press_time only updating when the button was just pressed, and last_release_time only updating when the button was just released.

For the user to find out if they were pressed within a certain timeframe ago, we would include a new parameter to is_action_just_pressed and is_action_just_released. This parameter would be something like a float that represents how long ago we want to allow the last press/release to be, for it to still count as "just pressed" or "just released". It would probably default to null or some negative number, so that the old functionality of the functions is still available.

We could also introduce get_action_last_press_time() and get_action_last_release_time() which would get the two new variables, for any advanced usages.

@LikeLakers2
Copy link

LikeLakers2 commented Oct 13, 2019

Also, I posted the rambling below earlier today, but quickly deleted it because I thought afterwards that I had misinterpreted the situation. However, I want to repost it, because I feel again that it is relevant.

Please don't feel like any of you have to respond to this, though. This is simply my thoughts laid out, and I admit it's not perfect, and honestly I feel weird bringing it back up, but I feel like I should repost it as it expresses how I feel right now.

Rambling under this fold

Just going to ramble a little here. This is at nobody in particular, but it does regard the issue at hand.

I have to wonder why we're so concerned with the amount of current games use it, or if other engines implement it, and so on. I mean, yes I get that we don't want to implement a feature that we don't see being used very often. But with how simple this could be, it makes me wonder why we can't just implement it anyways. If it ends up unused, we can revert the addition. If it ends up being used, great.

But not helping matters with this is how input buffers, when implemented in certain manners, are designed to be effectively invisible, imperceptible to the average human (and maybe even to those looking for if a input buffer is there). If we don't see it, how do we know it's there? On the flip side, how do we know it's not there either? We'd be better off asking lots of developers of existing games whether they use input buffers or not, and if they consider them important.

This isn't to say that being concerned with its usage count is somehow a bad thing, or that it would be fruitless. But to show how often it's already used would either require a lot of emails (which come with its own implications) or a lot of hard work and maybe even reverse-engineering of games... which would be hard, to a point where I would argue we should just implement it and watch the numbers, before making a decision on whether to keep the proposal.


But now I'm faced with another issue. If I were to propose such a thing, the obvious response would be to make it an addon, and watch those numbers.

But I'm worried that we won't really get any accurate numbers from such a solution. Specifically, I don't think the numbers we'd get would support anything except how many people used the addon. That's a number we want, but it doesn't show us how many people chose to code their own solution, or how many looked on Google instead of the asset library, or how many just gave up immediately and chose to use a different mechanic.

And without those other numbers, I feel concerned that people will say "well it won't be used that much anyways, no point in putting it in the engine". That sort of conclusion could be true, but without the other numbers to support it, it's no better than a premature conclusion.


And so the questions remain: Will it be worth it to add this to the engine? Or will it not be worth it? How do we know either way? Especially important: How do we know without several other factors getting in the way?

It seems like this issue will go nowhere, unless we can prove one way or the other -- which is next to impossible to do without adding it to the engine.

...At least, that's how I see it.

@golddotasksquestions
Copy link

golddotasksquestions commented Oct 13, 2019

Haha, not rude at all, but I am also afraid I can't quite follow your reasoning, tbh. Your proposal is so minimal, I would not even dare call this an input buffer. I feel like if it would only cover the last input, it would also be useless for 90% of all input buffer usecases.

My proposal above though is easily scalable. It's a one liner use to compare. From a user perspective, it's at least equally simple to use as yours, while it offers much more flexibility and an incredible wide range of usecases. If you haven't already, check out this guys approach: https://youtu.be/3ZDHhr50fIY?t=100. He also describes how he uses it to check for last input for jumps like @AmericanTrailMix described earlier (including prioritization, cancellation, used). It's pretty much identical to mine, he just has it visualized differently.

Many features in Godot exist, but they feel halfheartedly implemented and are in consequence lot less useful than their title suggests. I would really hate if "Input Buffer" would make the next addition in this sad group of enthusiastic disappointments.

As for your ramblings, I would not worry too much. Input Buffers are really important in gamedesign. They will come to Godot sooner or later. Think how much easier it would be to get your statemachine to sort out states correctly if you had a proper input buffer. The usecase list is just too long: Any action game, quicktime events games, Rhythm games, brawler and fighting games, reaction based games, typing games, cheat-codes ... anything that has to work with simultaneous inputs ...

@clayjohn
Copy link
Member

It's worth repeating. The threshold to implementing a new feature is not how many different games could use it. It's whether or not something is impossible to do without this feature. Then you need to show that that something is very important for a lot of games. As it stands there is no benefit to having a built in input buffer over having one in an asset in the asset library.

Additionally, as your discussion has shown, there is a wide range of opinion on what a proper input buffer should look like, forcing one form on all users makes little sense. Especially since the only benefit of having it built-in is ease of access.

On top of all that, we would be the only engine that ships a built-in input buffer, so the expectation that we cover all valid use cases for all types of games will be very high. Accordingly, it will take a lot of development effort to craft an input buffer that satisfies everyone's needs. It is much better to let everyone create their own that is tailored to their own game's needs.

@golddotasksquestions
Copy link

golddotasksquestions commented Oct 13, 2019

The threshold to implementing a new feature is not how many different games could use it. It's whether or not something is impossible to do without this feature. Then you need to show that that something is very important for a lot of games. As it stands there is no benefit to having a built in input buffer over having one in an asset in the asset library.

This is BS and you know it.
This list is filled with added features that just require a few lines of code to work around.
Can you point me to where this feature has been requested by the community before it was made?

"Impossible" ... you know as much as I do that engines (as all tools of creation) are not about making something possible or not.
It's not impossible to create a 3D game with similar graphics to Godot in machine code. Godot's tools just make it a hole lot more faster and more convenient. Tools make things more feasible to do.
This engine is filled to the brim with features that are feasible even for me to do with a few lines of code, and even more that I will probably never use in any of my projects.

This input buffer feature on the other hand has been requested by the community. It is not something anyone can just write in a few lines of code. If it would exist it would make a lot more games a lot more feasible to create in Godot, even for people who do not have years of programming experience already. It would lower the barrier of entry, yet provide everything to make complex game features.

If you brush this off while at the same time don't apply the same rigor you show here on all other implementations of the aforementioned list, it makes your arguments seem immensely arbitrary. Especially in light of the time and effort we spend here to illustrate the use, need and purpose of an input buffer feature.

@vnen
Copy link
Member

vnen commented Oct 13, 2019

Honestly, this discussion is becoming increasingly pointless. It's less about the input buffer and more about the proposal system itself.

Also, you can't compare features introduced before the proposal system was in place. Those "few lines of code" features might have not made the grade if this system were up at that point. In fact, it's one point that the proposals are trying to avoid (i.e. bloating the engine with small rarely used functions). The line is arbitrary, and the point here is that we are trying to define it objectively. But obviously not everyone agrees on the criteria (and many might not even know what they are).


About the input buffer itself, I'd very much like to see an implementation, in particular one provided in the assetlib. Then we can see the uses that people make of it to understand it's flaws when applied to a general public.

Because this is about use cases first. But in the thread barely any concrete example is presented. The OP is only about fighting game combos (and the title reflects that). And that can be done with a small helper class entirely in scripting, which is the kind of thing that we want to be provided by the assetlib.

So being provided as an addon is not a bad thing. Developers can still just care about making their game instead of infrastructure, because they can easily download the addon using the engine interface itself and then start using. We don't want people to implement their own solutions everytime, but improve a common, community-provided, useful asset that does not need to be in the base engine itself. Asking all of that to be in-engine is like asking for the npm registry be included in the node.js binary. We don't want that. We want a healthy ecosystem of addons that can extend the engine and used by the projects when needed.

We won't improve the ecosystem by jamming every feature into the engine just because the assetlib usability is not great. We improve it by understanding the flaws of the assetlib and fixing them so content (like an input buffer class) can easily be reached by anyone who needs it.

@golddotasksquestions
Copy link

Because this is about use cases first. But in the thread barely any concrete example is presented.

Really?!? I'm taking myself out from this discussion now, because that's just makes my blood boil. What a waste of time.

@Zireael07
Copy link

Uh, use cases have been presented in this thread over and over again?

@vnen
Copy link
Member

vnen commented Oct 13, 2019

Because this is about use cases first. But in the thread barely any concrete example is presented.

Really?!? I'm taking myself out from this discussion now, because that's just makes my blood boil. What a waste of time.

Definitely a waste of time. 90% of what I said on this thread was utterly ignored, with people nitpicking on a particular point and ignoring the rest. Barely taking time to understand what I tried to say and simply rejecting without understanding.

BTW, (even though this will be ignored anyway, or have a word nitpicked, don't know why I bother) saying "fighting game" isn't a use case. There are myriads of ways to make fighting games. Some don't need an input buffer. If you need to do a combo system, describe how your combo system works. The platformer jump article was a really good example of specific use case. The proposal template answers should come from that, then we can see if it's needed often, can't be worked around easily, etc. (and make sure the proposed design cover all cases).

@KoBeWi
Copy link
Member

KoBeWi commented Oct 13, 2019

Sooo, I kind of understood the importance of input buffer in platformers now and realized I sort of use one too. If it was built in the engine, I'd probably use it for my project. But that would save me literally few lines of code, so not sure if writing a complex system for this purpose is worth it.

@girng
Copy link

girng commented Oct 13, 2019

Really?!? I'm taking myself out from this discussion now, because that's just makes my blood boil. What a waste of time.

I've been in your shoes and understand how you feel. The sole fact vnen is replying is a good thing. I've been back and forth with some core developers, but honestly, in the end do they have their heart in the right place regarding the engine. I've came to this conclusion after many years. This is not abnormal, happens in the crystal-lang repo and other communities :). I would say just continue to stay positive, sometimes the vision doesn't align with core developers, that's normal, not a negative. I view open source suggestions like dating / job interviewing, sometimes it just doesn't work out, and that's okay.

@LikeLakers2
Copy link

LikeLakers2 commented Oct 13, 2019

@vnen

Definitely a waste of time. 90% of what I said on this thread was utterly ignored, with people nitpicking on a particular point and ignoring the rest. Barely taking time to understand what I tried to say and simply rejecting without understanding.

Hey look, something we can agree upon! I felt like 90% of what I said was ignored too. I could go in-depth if you want me to, I'm not afraid to be blunt about it if you ask me to.

But I'd like to point out something. Just because I don't respond doesn't mean I'm somehow ignoring it. Most of my responses to you (and to everyone else) were trying to hit on the key points -- the idea being that the rest of the argument falls apart without them. (How does a building stay standing when it has no solid foundation to stand on?) I also do that to avoid giving you twelve pages worth of the same arguments over every little comment made.

If that is still somehow ignoring the rest of your comments, then I don't know what to say. Do you want me to make a comment on everything you say, no matter how minor it is to your point as a whole, if I'm going to reply to you at all? Because there's clearly a divide between how I read comments and how you read comments. Clearly, I'm not understanding what's key to your point like you are.

Tell me, what do I do to fix this?


That said, I'm going to remove myself from this discussion too. Far too many times I feel like my points have been utterly ignored, and I've had to repeat them over and over. But it seems that was not enough like I originally thought, and my comments have been continually ignored anyways.

This issue has worn on my mind for far too long, where sometimes I spend entire hours typing what I thought was a decent reply, only to be ignored.

Goodbye.

@akien-mga
Copy link
Member

Haven't read but this seems way too heated, so locking. I might reopen after assessing it, or a constructive discussion can be restarted in another thread without the flaming.

@godotengine godotengine locked as too heated and limited conversation to collaborators Oct 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.