im working on a simple game like "space invaders",and i got into a problem.
Im trying to give the user, the possiblity to move as much as he want from Left to Right, and in the same time have the possiblty to shot using the "Space bar".
My problem is: when i pressed more then 1 key, only 1 function run.
here a few stuff i tried:
Storing the keys in a List<Keys> (but i didnt find any good way to excute the functions and everything become messy)
2.normal handling of the key_down event like this:
protected void Form1_keysDown(object obj, KeyEventArgs e)
{
(e.KeyData == Keys.Space)
spaceShip.FireBullets();
if (e.KeyCode == Keys.Left)
spaceShip.MoveLeft();
if (e.KeyCode == Keys.Right)
spaceShip.MoveRight();
}
my qustion is: what is a good way to make this work?
(sorry for my english)
You are relying on the keyboard controller repeating the key when you hold it down. That stops working when you press another key. This requires a different approach.
First you need an enum that indicates the motion state of the spaceship with values like NotMoving, MovingLeft and MovingRight. Add a variable of that type to your class. You'll need both the KeyDown and KeyUp events. When you get a KeyDown for, say, Keys.Left then set the variable to MovingLeft. When you get the KeyUp event for Keys.Left then first check if the state variable is still MovingLeft and, if it is, change it NotMoving.
In your game loop, use the variable value to move the spaceship. Some sample code:
private enum ShipMotionState { NotMoving, MovingLeft, MovingRight };
private ShipMotionState shipMotion = ShipMotionState.NotMoving;
protected override void OnKeyDown(KeyEventArgs e) {
if (e.KeyData == Keys.Left) shipMotion = ShipMotionState.MovingLeft;
if (e.KeyData == Keys.Right) shipMotion = ShipMotionState.MovingRight;
base.OnKeyDown(e);
}
protected override void OnKeyUp(KeyEventArgs e) {
if ((e.KeyData == Keys.Left && shipMotion == ShipMotionState.MovingLeft) ||
(e.KeyData == Keys.Right && shipMotion == ShipMotionState.MovingRight) {
shipMotion = ShipMotionState.NotMoving;
}
base.OnKeyUp(e);
}
private void GameLoop_Tick(object sender, EventArgs e) {
if (shipMotion == ShipMotionState.MovingLeft) spaceShip.MoveLeft();
if (shipMotion == ShipMotionState.MovingRight) spaceShip.MoveRight();
// etc..
}
Related
I'm making a game in C# in Forms in Visual Studio and I'm currently registering key presses from the player with the keyDown event and it works well. When the player is holding down a button it gets pressed once, there is a delay and then the key is registered many times over and over, which is good, but if any other key that I'm checking for gets pressed while the first key is being held, the new key is registered once and then nothing more, just like when typing. I want it so that if key is pressed while another is being held, the first key is registered once, and then the first key, that's being held, keeps outputting.
I'm currently getting:
aaaaaaaaaaaaaaaaaap
but I want:
aaaaaaaaaaaaaaaaaapaaaaaaaaaaaaaa
if that makes sense
Is it possible?
Here is my current method:
private void GUItetris_KeyDown(object sender, KeyEventArgs e)
{
if (!Tetris.gameOver && Tetris.gameBoard != null)
{
if (e.KeyCode == Keys.A) // a
{
Tetris.gameBoard.activePiece.MoveLeft(Tetris.gameBoard.boardColor);
Tetris.gameBoard.UpdatePiece();
}
if (e.KeyCode == Keys.D) //d
{
Tetris.gameBoard.activePiece.MoveRight(Tetris.gameBoard.boardColor);
Tetris.gameBoard.UpdatePiece();
}
if (e.KeyCode == Keys.S) //s
{
Tetris.gameBoard.activePiece.MoveDown(Tetris.gameBoard.boardColor);
Tetris.gameBoard.UpdatePiece();
}
if (e.KeyCode == Keys.P) // p
{
Tetris.gameBoard.activePiece.Rotate(Tetris.gameBoard.boardColor, true);
Tetris.gameBoard.UpdatePiece();
}
if (e.KeyCode == Keys.L) // l
{
Tetris.gameBoard.activePiece.Rotate(Tetris.gameBoard.boardColor, false);
Tetris.gameBoard.UpdatePiece();
}
}
}
sorry again for asking a probable simple question but I have been searching among the internet for this solution but I am unable to. I am in Highschool programming working on a final project. I have everything done except this little part. I have 2 background workers made(One for each player) and I have keydown events turning these background workers on. Here is the code:
if (e.keycode == Keys.D)
{
p1f = true;
bgwPlayerOne.RunWorkerAsync();
}
if (e.keycode == Left)
{
p2f = true;
bgwPlayerTwo.RunWorkerAsync();
}
Okay, so I had to type that out because it is on my other computer which has no internet but that is the code in the keydown event. The variables tells that in the background worker which if statement to do. But, the main issue is that whenever I press D and Left Arrow Key at the same time, The one going before the other click is stopped and the most recent key event is started. I didn't have this issue when I was using timers previously(I was having a lag issue so I switched to multithread). If there are any questions about this please tell me, any help would be appreciated, thanks!
Updated*****
private void frmTankBattle_MapOne_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.D)
{
p1f = true;
bgwPlayerOne.RunWorkerAsync();
}
//System.Threading.Thread.Sleep(1);
if (e.KeyCode == Keys.A)
{
p1b = true;
bgwPlayerOne.RunWorkerAsync();
}
//System.Threading.Thread.Sleep(1);
if (e.KeyCode == Keys.Left)
{
p2f = true;
bgwPlayerTwo.RunWorkerAsync();
}
//System.Threading.Thread.Sleep(1);
if (e.KeyCode == Keys.Right)
{
p2b = true;
bgwPlayerTwo.RunWorkerAsync();
}
if (e.KeyCode == Keys.Space)
{
p1c = true;
tmrPlayerOneCombat.Start();
}
// System.Threading.Thread.Sleep(1);
}
private void frmTankBattle_MapOne_KeyUp(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.D)
{
p1f = false;
p1b = false;
bgwPlayerOne.CancelAsync();
}
if (e.KeyCode == Keys.A)
{
p1f = false;
p1b = false;
bgwPlayerOne.CancelAsync();
}
if (e.KeyCode == Keys.Left)
{
p2f = false;
p2b = false;
bgwPlayerTwo.CancelAsync();
}
if (e.KeyCode == Keys.Right)
{
p2f = false;
p2b = false;
bgwPlayerTwo.CancelAsync();
}
}
There are couple things wrong with your code and I will go thru them one by one.
Firstly KeyDown event will fire multiple times per second as long as any key has been hold down.
This means if RunWorkerAsync(); did not finish before the event fires for the second time you will receive an InvalidOperationException.
If you have previously hold down a key lets say key A, and then you try to hold down D key the new key code will be D instead of A even though two keys are held down at the same time. You can test out this behavior in notepad.
Since you are on WinForm you don't have the access to the Win32 Keyboard wrapper. You will need to do some manual tracking yourself.
You can have a HashSet<Keys> to store the keys currently being held down. You add the new keys in KeyDown event and Removes them in KeyUp event. Then you can iterate thru the list to check which keys are currently down and act accordingly.
I want to make keyboard shorcut key in c# but since i could not find any "Ç" char on keyboard shorcuts list for menu items. So I decided to make it as my own keydown event for parent control. But it didn't work. The problem may be it does not see the char 'Ç' there. So i want change it as Keys.Ç like casual english chars. Is there anyway to do that? Here is my code below:
private void mniOpenW_KeyDown(object sender, KeyEventArgs e)
{
if ((e.Control && e.KeyCode.ToString() == "ç" ) || (e.Control == true && e.KeyCode.ToString() == "Ç"))
{
mniOpenW.PerformClick();
}
}
I want to make it like that:
private void mniOpenW_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.Ç)
{
mniOpenW.PerformClick();
}
}
Is there any way that i can find that button in c#? Because I could not find it myself. Or something make that code working is also good for me.
I did something similar to Hans' comment and it worked for me. Here is my code below:
private void mniOpenW_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyValue == 220)//this is keyvalue of 'Ç' key.
{
mniOpenW.PerformClick();
}
}
I use a MaskedTextBox control to facilitate the entry of dates in my project. I have mtb.BeepOnError set to false. However, it makes a generic beep whenever the 'Enter' key or 'Esc' key is pressed, and this is undesirable for my application.
This seems to be the default behaviour for the MTB, so is there any way to change that?
You can try something like this:
void mtb_KeyDown(object sender, KeyEventArgs e) {
if (e.KeyCode == Keys.Enter | e.KeyCode == Keys.Escape) {
e.SuppressKeyPress = true;
}
}
Software Utilize : C#, VS-2005
Is This Possible to override Shift+Tab Function/Method or detect Shift+Tab Function and Utilize it with Backspace.?
In Shot replace Shift+Tab Function with Backspace. And Then Backspace will Behave like Shift+Tab:
Is this possible in C#?
I suppose you are working on a win-form. Register a key down event:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab && e.Shift)
{
// act like a backspace is pressed
}
else if (e.KeyCode == Keys.Back)
{
SendKeys.Send("+{TAB}"); // simualte a shift-tab press
}
}
To resolve the issue #liggett78 mentioned in the comment, you can set
form.KeyPreview = true;
to handle all the key events of child controls in the KeyDown event of the from.
EDIT: To prevent deleting a character in textbox when pressing BACKSPACE, you can:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.Back)
{
e.SuppressKeyPress = true;
SendKeys.Send("+{TAB}");
}
}
Override ProcessDialogKey or ProcessTabKey on your form.