I'll try to explain my scenario as best i can;
At each application tick I query the current state of the keyboard and mouse and wrap them in individual classes and data structures. For the keyboard it's an array of my Keys enum (one item for each of the keys that are currently pressed) and for the mouse it's a class containing coordinate delta's and bools for each buttons pressed.
I also have a rudimentary state machine managed via a state manager class which maintains the stack and marshalls the states.
All I want to know is, how best to pass the input (snapshots) to the individual states my app can be in at any one time?
I would like to process as much of the input as possible away from the individual states, so as to reduce repeating logic within the states.
Or would it be better to keep the input snapshots as pure as possible and pass them to the states so they can keep they're input-specific-logic hidden?
Note
This structure is similiar to how I imagine a game would work, and although this application is not a game it does need to be processed as quickly as possible.
Why are you querying the state of the keyboard and mouse with each tick? A much better and traditional solution would be to capture events fired from the keyboard and mouse. That way you only need to update the state when you HAVE to.
If you simply query your keyboard and mouse every tick, I can guarantee you'll run into problems. When you query every tick, you'll find that you miss inputs that occur quickly (within the time domain of a single tick). Imagine a situation where the user presses and releases a key/button between two ticks (it will happen more than you think) - you'll completely miss the input.
Particularly in C#, which is completely geared for input events like this, you should be using events.
In XNA, they do this by making the keyboard class static.
KeyboardState state = Keyboard.GetState();
you can then access the current key state with the above line of code.
You should fire events and capture the arguments. That would be the easiest, and most efficient way to handle this.
class YourClass
{
//data members ...
public void OnKeyboardPress(object sender, EventArgs args)
{
//handle your logic capturing the state here
}
}
//elsewhere
someControl.KeyPress += new KeyPressDelegate(yourClassInstance.OnKeyboardPress);
Related
So, I as trying to create an "Open world exploration" game in C# WinForms, And while coding the mining, (which works just fine), I encountered a problem with saving the number of broken blocks to the inventory (a label). Basically, for every block player breaks, it gets added to the inventory as inventoryWrite.Text = $"Grass: {grassHolder}, Rock: {rockHolder}";.
Now, the thing is, sometimes, even though I use the ++ operator, it adds up to 4 to the inventory. I'm citing the code below.
private void Remove(object sender, EventArgs e, PictureBox itm)
{
if (itm.BorderStyle == BorderStyle.FixedSingle)
{
if (itm.Tag.Equals("grass") && items.Contains(itm))
{
grassHolder++;
itm.Tag = "";
}
if (itm.Tag.Equals("rock") && items.Contains(itm))
{
rockHolder++;
itm.Tag = "";
}
if (itm.Tag.Equals("dio") && items.Contains(itm))
{
dioHolder++;
itm.Tag = "";
}
this.Controls.Remove(itm);
items.Remove(itm);
}
}
I update the inventory in a public loop, don't worry about that (interval is 1ms). But I don't think that's the problem, since I tried putting it in the Remove() function, and nothing seemed to change.
I've even double locked the if statement, but nothing! It still adds more than 1. Can anybody tell me how to solve this? Thank you a lot.
EDIT:
As a reply to Ronald's comment, the if statement is called ONLY when the block is selected. ONLY once when the method is called.
There are too many points to cover in a comment and so I've had to enter an answer.
In itself the ++ operator is not the issue and will always behave as it should, but as someone reviewing a small piece of code the following points crop up.
grassHolder, rockHolder, dioHolder appear to have
accessibility beyond this function and so could be altered
elsewhere.
Function void Remove(object sender, EventArgs e, PictureBox itm) appears to be an event handler and yet there is no locking mechanism to ensure that the externally accessible parameters are not changed or used elsewhere whilst the function code is executed. Specifically items which is appears to be a collection of sorts and is used both in logic to determine whether parameters in (1) are incremented, but also has its contents changed within the function.
From comments made it would appear that this logic is run in
response to user interaction, maybe by use of a mouse button or key
event. Is this base event de-bounced to ensure that multiple
triggers aren't handled?
Your statement "saving the number of broken blocks to the inventory (a label)." Implies that you are storing game data within the UI. This should be avoided as it ties game data directly to the UI implementation and therefore makes it difficult to alter the game, but also ties any handling of game data directly to the UI thread.
Recommended actions:
Ensure that the parameters in question are not accessed and altered
elsewhere causing the issue seen.
Utilize a lock(x) statement to ensure that items is not changed
whilst this function is being executed. More information here
De-bounce the mouse button or key click that triggers this function
to ensure that multiple events aren't triggered. This is performed
by placing a minimum time between event triggers. A minimum time
period of say 150ms would be a good starting point. This would equate to a reasonably quick, conscious user action, but be slower than multiple events triggered by partial/poor switch contact. Incidentally this is especially true on touch screen interfaces.
Consider controlling access to global parameters through use of
access functions. For example
int IncrementRockHolder(){ rockHolder++;} Although implementation may appear onerous, they can greatly help with debugging as call stack information is then available showing what code is calling the function and thus making the change.
Implement a game engine class to control access to game data and implement game logic. This
would allow you to unit test game functionality whilst also freeing
it from UI implementation and restrictions.
There is the whole super simple C# console app here:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
int left = 0;
Console.SetCursorPosition(++left, 0);
while (true)
{
ConsoleKeyInfo stisknutaKlavesa = Console.ReadKey(true);
if (stisknutaKlavesa.Key == ConsoleKey.RightArrow)
{
Console.SetCursorPosition(++left, 0);
Console.Write("#");
}
}
}
}
}
Description: When I press RIGHT KEY (and hold it!!) it quickly writes one hash, then there is a pause, and then it fluently keeps writting another hashes further.
How can I get rid of that pause? I have been dealing with identical problem in one of my winform app, but for simplicity I posted it in this console application here.
I have found some answers about this topic but all of them were about javascript (jquery) and i did not understand how to apply it on this my c# project.
And i do not want to resolve it in asynchronous way either. Is there such a solution, please?
This comes from the way that the windows console (and most other text-based inputs in Windows and other environments) behaves. If you put your cursor on any text input (like your browser's address bar, for instance), and press and hold an arrow key, you will see it move once, pause, and then start moving repeatedly with a much shorter pause.
In effect, your console's ReadKey registers keypresses based on some predefined behaviors of the operating system.
If you want to be able to detect and respond to someone holding a key down, you'll need to use a medium that gives you more low-level access to events like keydown and keyup. Something like Windows Forms, WPF, Unity... pretty much anything that's not Console.
Furthermore, if you want to respond to those key-down and key-up events using timing that's different from how the system treats those events, you'll have to create your own timing mechanism, and only use those events to help you know when things have changed. Examples of this can be found here and here.
If you're trying to make something akin to a video game, you might consider looking into libraries that are specifically designed for these use cases, like Unity3D.
Is there a way to immediately react to any change in the states of mouse, keyboard and gamepad(s) in a C# application?
I believe XNA is just like any other C# app, so it might not be any different, but just in case, I want to improve my XNA game input by immediately firing up corresponding events.
Default XNA doesn't have an event handler (at least I've never seen it being mentioned). Nuclex.Input doesn't detect some keys (like Alt, F10 or Pause, which is unacceptable).
Normally you store the state of the input on the previous frame, and then test whether then input has changed between frames. For example, your Update method might look like:
KeyboardState ks = Keyboard.GetState();
if(ks.IsKeyDown(Keys.Space) && lastKeyboardState.IsKeyUp(Keys.Space))
{
DoAThing();
}
lastKeyboardState = ks;
(Wrote that code entirely from memory, so it might not be quite right. But it should illustrate the concept.)
This will give you key events with no more than 1 / yourFPS delay. At 60FPS this is about 16ms. This is usually acceptable for gameplay purposes. If you especially want an event - you could simply fire one where I have put DoAThing, above.
For typing text you generally want the character events from Windows (which a library like Nuclex.Input can give you). This isn't so much so you get better latency, but so you can get keyboard events in an ordered and reliable way (for example: this way you never get two key coming down on a single frame resulting in an ambiguous order).
More importantly, it's so you can get the events after Windows has had a chance to apply input processing. For example, this gives you difference between typing an a and an A. Or someone entering a character with alt+numpad, or applying a diacritic. The downside is that you miss out on various non-text keys like, as you mention, Alt, F10, Pause, etc.
Finally, a quick read over Nuclex.Input reveals that it at least should provide the keys that you want - specifically IKeyboard.KeyPress and .KeyRelease. If it's not working, it could be a bug in Nuclex. Or something on your system is interfering with window messages.
One possible work-around might be to accept the latency on these missing keys by polling for them as well. The code to use polling as a seamless fall-back is probably fairly simple.
I'm having a little trouble concisely describing what it is that I'm trying to do, which is hurting my ability to search for an answer. I'll try to be specific with my problem, if anyone could give a suggestion or point me in the direction of what to study, I'd greatly appreciate it.Tr
I'm trying to program a GUI version of the cardgame Dominion, where playing different cards will yield different results and choices. Many of these cards have similar starting choices (e.g. select a card from your hand and trash it/look at enemy hand), but different ending choices (e.g. upgrade that trashed card/give trashed card to another player). upon playing a card, the program looks for the unique numeric card code and begins executing code specific to that card.
Here's where I'm hung up:
I'd like to have more general methods that listen for user input INSIDE the unique card-code, but I keep getting errors. Ideally, I'd be able to do something like
for(int i = 0; i < totalPlayers; i++)
{
showEnemyHand(i);
}
or
for(int i = 0; i < totalPlayers; i++)
{
thiefEffect(i);
}
within a 'buttonclicked' event (the "play card" button, specifically.) The showEnemyHand(int) and thiefEffect(int) method would wait for user input, store responses, and then return right back to the for loop that it was called from, but its not as easy as I'd originally hoped.
I'm suffering most from not even knowing what it is that I should be searching for. I've been reading up on event handling and delegates, and I'm not sure that's what I need. Can anyone point me in the direction of what I need to learn, or maybe give me the topic of what I'm trying to solve so I can search for it a little easier? (of course, helping me solve it would be appreciated too =D)
Thanks a bunch!
Jake
Your solution would be fine for a command line based game, in a language with continuations/coroutines, or maybe in a multi-threaded application where showEnemyHand etc would block on user input. For a GUI-based game, an event driven architecture is really what would work best for you, so in principle I'd suggest learning more about it.
But if you really want to do that using a loop, I'd suggest then reading about threading and blocking calls. Once you understand the concepts, you should be able to:
Create a separate thread to host your loop;
Create a lock that will block execution until the user inputs something (see the example in the linked question);
Use that lock in your loop and on the callback for user input:
In the beginning of your loop, you wait on your lock;
When the user inputs something (which you'll detect using an event handler - see the docs for the particular GUI framework you're using) you save which action was chosen and frees the lock;
Your loop will automatically continue, reading the saved action and performing an iteration, until it reachs the same point again and waits for another user input.
Whether this method is easier or harder than coding your rules using the event driven logic, it's debatable. The same can be said about coroutines (though being less experienced with that, I can not opinate). The pointers I gave should help you get started though.
Scenario: a game with a board, and several tiles on it. Classes: Board, Tile, Player and of course, Game.
Whenever the player presses a tile, his score gets incremented by 1. Board is instantiated inside of Game, and an array of Tile is instantiated inside of Board. My first option to increment that score easily was to make a public static class with a public static field (Score). Of course, it's rather amateurish. And seemed to break the overall flow of the app.
After some thought, I changed everything to use Events; Tile raises an event when clicked; Board handles that event, and raises another event to the main Game class. Player is instantiated inside of Game; when Game handles the event received from Board, it does a PlayerOne(instance of Player).Score += 1;
Should I just go on ahead and use this flow? Do you have any other architecture/design ideas that would work better? Why would your ideas work better?
I didn't use custom made events intensively before and I feel that the whole event raising another even idea might be a bit wrong. From afar though, it looks like a good flow. And it certainly does the job correctly.
What you described looks like (is) the observer design pattern. The game should 'listen' to events from the board, the board should listen to events from the tiles etc.
You should have provided some code.
Should I just go on ahead and use this flow?
Depends on what the events look like.
Do you have any other architecture/design ideas that would work better?
Publish/Subscribe is an alternative. But the .NET events works fine here.
I didn't use custom made events intensively before and I feel that the whole event raising another even idea might be a bit wrong.
It's fine to keep encapsulation. I would do something like:
class Tile
{
public event EventHandler Clicked = delegate{};
}
class Board
{
private void OnTileClick(object source, EventArgs e)
{
var tile = (Tile)source;
//doSome
var args = new CustomEventArgs();
CustomEvent(this, args);
}
public event EventHandler<CustomEventArgs> SomeEvent = delegate{};
}
public class SomeCustomEventArgs : EventArgs
{
}
The only other possiblity that springs to mind is passing / setting in delegates from higher classes that act as callbacks - so the lower classes can check for a valid delegate and call it without any knowledge of who owns it. If you make it a list of possible delegates, it allow for multiple subscribers all benefitting from that callback.
Having said that, I find your event architecture pretty elegant.
Another way to look at it is that the Board depends on Player to function correctly. How many players are there at any one time and do players get added to and from the board during game time?
If not, you might be able to pass the player(s) to the board on creation and then the board could increment the player score. This works as long as there is no other logic that happens at the Game level which could influence the scoring.
The architecture you seem to have implemented works well for this scenario.
using the observer architecture allows the dependencies you have created through the object relationships to be easily managed.
The observer architecture here will allow you you add or remove players, tiles, boards very easily. If there was a requirement for a 'Game' to now manage multiple boards, then simply adding the object in and subscribing to its exposed events allows you to manage that elegantly. This is because a tile does not need to know that a player exists. The same way a player does not need to know that a game exists - they just do their jobs independently.
Other patterns may create unwanted dependencies, leading to the extra code that would be required to pass the information back up the chain (from tile, to player, to game) - that could very easily result in issues further down the line of your project implementation.