I have started to learn some Microsoft.DirectX 3D basic techniques, and bumped to this problem that is too dificult for me. I have created 3D Scene, Camera, Light's etc, with some simple 3D objects drawn. What I want to do now is simple 3D rotation of that objects around all three axes. For that I want to use Arrow and ASWD keyboard keys as in manner in computer games are used. For that I have used OnKeyDown and OnKeyUp event handlers :
#region - Event handler -
protected override void OnKeyDown(KeyEventArgs e)
{
base.OnKeyDown(e);
#region - speed -
if(e.KeyValue == (char)Keys.Add || e.KeyValue == (char)Keys.Oemplus)
step_p = true;
if(e.KeyValue == (char)Keys.Subtract || e.KeyValue == (char)Keys.OemMinus)
step_m = true;
if(step_p)
step++;
if(step_m)
step--;
if(step==0)
step = 1;
#endregion
#region - rotation -
if(e.KeyCode == Keys.Left)
{
left = true;
}
if(e.KeyCode == Keys.Right)
{
right = true;
}
if(e.KeyCode == Keys.Up)
{
up = true;
}
if(e.KeyCode == Keys.Down)
{
down = true;
}
if(e.KeyCode == Keys.A)
{
a = true;
}
if(e.KeyCode == Keys.D)
{
d = true;
}
if(left)
angleZ_D+=step;
if(right)
angleZ_D-=step;
if(up)
angleX_D-=step;
if(down)
angleX_D+=step;
if(a)
angleY_D+=step;
if(d)
angleY_D-=step;
//
//
//
if(angleX_D == 360)
angleX_D = 0;
if(angleY_D >= 360)
angleY_D = 0;
if(angleZ_D >= 360)
angleZ_D = 0;
angleX_R = angleX_D * rad;
angleY_R = angleY_D * rad;
angleZ_R = angleZ_D * rad;
//
//
//
#endregion
#region - zoom -
if(e.KeyValue == (char)Keys.W)
{
w = true;
}
if(e.KeyValue == (char)Keys.S)
{
s = true;
}
if(w)
{
zoom+=0.1f * step;
if(zoom>10.0f) zoom=10.0f;
}
if(s)
{
zoom-=0.1f * step;
if(zoom<1.0f) zoom=1.0f;
}
#endregion
Draw();
}
protected override void OnKeyUp(KeyEventArgs e)
{
base.OnKeyUp(e);
#region - speed -
if(e.KeyValue == (char)Keys.Add || e.KeyValue == (char)Keys.Oemplus)
step_p = false;
if(e.KeyValue == (char)Keys.Subtract || e.KeyValue == (char)Keys.OemMinus)
step_m = false;
#endregion
#region - rotation -
if(e.KeyCode == Keys.Left)
{
left = false;
}
if(e.KeyCode == Keys.Right)
{
right = false;
}
if(e.KeyCode == Keys.Up)
{
up = false;
}
if(e.KeyCode == Keys.Down)
{
down = false;
}
if(e.KeyCode == Keys.A)
{
a = false;
}
if(e.KeyCode == Keys.D)
{
d = false;
}
#endregion
#region - zoom -
if(e.KeyValue == (char)Keys.W)
{
w = false;
}
if(e.KeyValue == (char)Keys.S)
{
s = false;
}
#endregion
Draw();
}
This is the problem :
When I press key A and while holding it down I press key W, program works perfectly but when I release key W the event handler do not recognize that key A is still pressed.
Is there solution for such problem in C# 4.0 and .Net framework 2.0
All the best,
Željko Perić
According to
Quote:
You are depending on the keyboard repeating a key when held down.
That stops working as soon as you press another key.
You instead need to use a Timer and in the Tick event handler
check which way you want to move. Now key-repeat no longer matters.
Set the timer's Interval property to 15 or 31 to get good consistency. – Hans Passant
this is problem solution :
using System;
using System.Windows.Forms;
namespace WASD_keyboard_game_control
{
public partial class MainForm : Form
{
//
// Global variables declaration
//
//
// Timer
//
// Implements a timer that
// raises event at user defined interval
//
Timer Clock;
//
// Set Timer tick Interval in miliseconds
//
// By changing value of Interval,
// we control how often the timer tick event handler is raised
// and eventually the call frequency of Main_Function()
//
const int Interval = 15;
//
// Variables for counting the number
// of times that program has confirmed
// the key down state of AWSD keys
//
int W = 0;
int A = 0;
int S = 0;
int D = 0;
//
// Variables ( flags ) for memorizing
// the key down state of AWSD keys
//
// true - key is down ( pressed )
//
// false - key is up ( released )
//
//
bool w = false;
bool a = false;
bool s = false;
bool d = false;
//
//
//
public MainForm()
{
//
// The InitializeComponent() call is required
// for Windows Forms designer support.
//
InitializeComponent();
//
// Call Initialize_Timer() function
//
Initialize_Timer();
}
void Initialize_Timer()
{
// Create new timer
Clock = new Timer();
// Set timer tick interval in miliseconds
//
// By changing value of interval,
// we control how often the timer tick event handler is raised
// and eventually the call frequency of Main_Function()
//
Clock.Interval = Interval;
//
// Add timer tick event handler
//
// This event handler is raised
// every time timer make tick
//
// The smaler value for timer interval,
// more often the event handler is raised
//
Clock.Tick += new System.EventHandler(this.ClockTick);
//
// Start timer
//
Clock.Start();
}
void ClockTick(object sender, EventArgs e)
{
//
// Timer tick event handler
//
//
// Call Main_Function()
//
Main_Function();
//
//
//
}
protected override void OnKeyDown(KeyEventArgs e)
{
//
// This event handler is raised every time
// some key on the keyboard is first pressed
//
base.OnKeyDown(e);
//
// Set corresponding key down flag state to true
//
if(e.KeyCode == Keys.W)
w = true;
if(e.KeyCode == Keys.A)
a = true;
if(e.KeyCode == Keys.S)
s = true;
if(e.KeyCode == Keys.D)
d = true;
}
protected override void OnKeyUp(KeyEventArgs e)
{
//
// This event handler is raised every time
// some key on the keyboard is released
//
base.OnKeyUp(e);
//
// Set corresponding key down flag state to false
//
if(e.KeyCode == Keys.W)
w = false;
if(e.KeyCode == Keys.A)
a = false;
if(e.KeyCode == Keys.S)
s = false;
if(e.KeyCode == Keys.D)
d = false;
}
void Main_Function()
{
//
// Main function
//
//
// This function is called every time the
// timer tick event handler is raised
//
//
// This function determines wich key is pressed
// upon key down flag value and updates correspondig counter value
//
// Counter value shows how many times program has confirmed the
// key down state and not how many times user has pressed the key
//
//
// Increase counter value if key is down
//
if(a)
A++;
if(s)
S++;
if(w)
W++;
if(d)
D++;
//
// Show values of counters
//
Label_A.Text = "A = " + A.ToString();
Label_S.Text = "S = " + S.ToString();
Label_W.Text = "W = " + W.ToString();
Label_D.Text = "D = " + D.ToString();
}
}
}
Related
I've some code written in C# that allows the user to scan a barcode, and the label.Text changes to the input of the barcode. I used a label instead of textbox to prevent the user from fat-fingering a wrong barcode -basically disabling any keyboard input.
Everything works nice, except when the barcode being scanned has alphabetic characters in it. If the barcode starts with an alphabetic character and ends with an alphabetic character, then the barcode doesn't scan at all.
If the barcode starts with an alphabetic character, but ends with numeric characters, the program picks up only the trailing numeric characters.
Here's the code:
char cforKeyDown = '\0';
int _lastKeystroke = DateTime.Now.Millisecond;
List<char> _barcode = new List<char>();
bool UseKeyboard = false;
private void Form1_Load(object sender, EventArgs e)
{
this.ActiveControl = label1;
this.KeyDown += new KeyEventHandler(Form1_KeyDown);
this.KeyUp += new KeyEventHandler(Form1_KeyUp);
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
// if keyboard input is allowed to read
if (UseKeyboard && e.KeyData != Keys.Enter)
{
MessageBox.Show(e.KeyData.ToString());
}
/* check if keydown and keyup is not different
* and keydown event is not fired again before the keyup event fired for the same key
* and keydown is not null
* Barcode never fired keydown event more than 1 time before the same key fired keyup event
* Barcode generally finishes all events (like keydown > keypress > keyup) of single key at a time, if two different keys are pressed then it is with keyboard
*/
if (cforKeyDown != (char) e.KeyCode || cforKeyDown == '\0')
{
cforKeyDown = '\0';
_barcode.Clear();
return;
}
// getting the time difference between 2 keys
int elapsed = (DateTime.Now.Millisecond - _lastKeystroke);
/*
* Barcode scanner usually takes less than 17 milliseconds to read, increase this if neccessary of your barcode scanner is slower
* also assuming human can not type faster than 17 milliseconds
*/
// Bumped it up to 35[ms]
if (elapsed > 50)
_barcode.Clear();
// Do not push in array if Enter/Return is pressed, since it is not any Character that need to be read
if (e.KeyCode != Keys.Return)
{
//_barcode.Add((char) e.KeyData);
_barcode.Add((char) e.KeyData);
}
// Barcode scanner hits Enter/Return after reading barcode
if (e.KeyCode == Keys.Return && _barcode.Count > 0)
{
string BarCodeData = new String(_barcode.ToArray());
if (!UseKeyboard)
{
//MessageBox.Show(String.Format("{0}", BarCodeData));
label1.Text = String.Format("{0}", BarCodeData);
}
//_barcode.Clear();
}
// update the last key stroke time
_lastKeystroke = DateTime.Now.Millisecond;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//Debug.WriteLine("CS_Single_Label_Printer_KeyDown : " + (char)e.KeyCode);
cforKeyDown = (char) e.KeyCode;
}
I've narrowed down the problem to the fact that the alphabetic parts of the alpha-numeric barcodes being scanned are uppercase. I generated a test barcode using lower-case letters, and everything worked as it should, but this still doesn't fix the problem as I have to scan thousands of already printed barcodes that have uppercase characters encoded into the barcode data matrix.
Is there a way to switch the above code in order to account for the 'character | Shift' KeyData?
The answer is that KeyCode returns the KEY pressed. It does not respect the case of the key. Use Shift to get the case. Below is a working example based on your supplied code. The magic is in the local function ToCharacter. You'll need to play with the if statements at the top to include numbers too if that's your desire.
From1.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace DesktopApp2
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
char cforKeyDown = '\0';
int _lastKeystroke = DateTime.Now.Millisecond;
List<char> _barcode = new List<char>();
bool UseKeyboard = false;
private void Form1_Load(object sender, EventArgs e)
{
this.ActiveControl = InputBox;
this.InputBox.KeyDown += new KeyEventHandler(Form1_KeyDown);
this.InputBox.KeyUp += new KeyEventHandler(Form1_KeyUp);
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
char NotALetter = '-';
DebugBox.Items.Clear();
DebugBox.Items.Add($"KeyEventArgs->KeyCode = {e.KeyCode.ToString()}");
DebugBox.Items.Add($"KeyEventArgs->KeyData = {e.KeyData.ToString()}");
DebugBox.Items.Add($"KeyEventArgs->KeyValue = {e.KeyValue.ToString()}");
DebugBox.Items.Add($"KeyEventArgs->e.Shift = {e.Shift.ToString()}");
DebugBox.Items.Add($"ToCharacter = {ToCharacter(e) ?? NotALetter}");
char? ToCharacter(KeyEventArgs kea)
{
int DtoNumPadOffset = (int)(Keys.NumPad0 - Keys.D0);
if (kea.KeyCode < Keys.D0) return null; // Keys.D0 through Kyes.D9 are the Keys on the top row of the keyboard. D9 is right next to A in the enum type.
if (kea.KeyCode > Keys.NumPad9) return null;
if (kea.KeyCode > Keys.Z && kea.KeyCode < Keys.NumPad0) return null; //knocks out keys between Z and NumPad0
if (kea.Shift && kea.KeyCode < Keys.A) return null; // rejects special characters when numbers across the top are used with the <shift> key.
if (kea.KeyCode < Keys.A) return (char)kea.KeyCode;
if (kea.KeyCode > Keys.Z) return (char)((int)kea.KeyCode - DtoNumPadOffset);
return kea.Shift
? (char)kea.KeyCode
: char.ToLower((char)kea.KeyCode);
}
// if keyboard input is allowed to read
if (UseKeyboard && e.KeyData != Keys.Enter)
{
MessageBox.Show(e.KeyData.ToString());
}
/* check if keydown and keyup is not different
* and keydown event is not fired again before the keyup event fired for the same key
* and keydown is not null
* Barcode never fired keydown event more than 1 time before the same key fired keyup event
* Barcode generally finishes all events (like keydown > keypress > keyup) of single key at a time, if two different keys are pressed then it is with keyboard
*/
//if (cforKeyDown != (char)e.KeyCode || cforKeyDown == '\0')
//{
// cforKeyDown = '\0';
// _barcode.Clear();
// return;
//}
// getting the time difference between 2 keys
int elapsed = (DateTime.Now.Millisecond - _lastKeystroke);
/*
* Barcode scanner usually takes less than 17 milliseconds to read, increase this if neccessary of your barcode scanner is slower
* also assuming human can not type faster than 17 milliseconds
*/
// Bumped it up to 35[ms]
//if (elapsed > 2000)
if (e.KeyCode == Keys.Return)
{
InputBox.Text = String.Empty;
_barcode.Clear();
}
// Do not push in array if Enter/Return is pressed, since it is not any Character that need to be read
if (e.KeyCode != Keys.Return)
{
char? TestForCharacter = ToCharacter(e);
if (TestForCharacter != null)
{
//_barcode.Add((char) e.KeyData);
_barcode.Add((char)TestForCharacter);
}
}
OutputBox.Text = string.Concat(_barcode);
// Barcode scanner hits Enter/Return after reading barcode
if (e.KeyCode == Keys.Return && _barcode.Count > 0)
{
string BarCodeData = new String(_barcode.ToArray());
if (!UseKeyboard)
{
//MessageBox.Show(String.Format("{0}", BarCodeData));
OutputBox.Text = String.Format("{0}", BarCodeData);
}
//_barcode.Clear();
}
// update the last key stroke time
_lastKeystroke = DateTime.Now.Millisecond;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//Debug.WriteLine("CS_Single_Label_Printer_KeyDown : " + (char)e.KeyCode);
cforKeyDown = (char)e.KeyCode;
}
}
}
Form1.Designer.cs
namespace DesktopApp2
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.OutputBox = new System.Windows.Forms.TextBox();
this.InputBox = new System.Windows.Forms.TextBox();
this.DebugBox = new System.Windows.Forms.ListBox();
this.SuspendLayout();
//
// OutputBox
//
this.OutputBox.Location = new System.Drawing.Point(52, 93);
this.OutputBox.Name = "OutputBox";
this.OutputBox.ReadOnly = true;
this.OutputBox.Size = new System.Drawing.Size(650, 22);
this.OutputBox.TabIndex = 1;
//
// InputBox
//
this.InputBox.Location = new System.Drawing.Point(52, 45);
this.InputBox.Name = "InputBox";
this.InputBox.Size = new System.Drawing.Size(650, 22);
this.InputBox.TabIndex = 2;
//
// DebugBox
//
this.DebugBox.FormattingEnabled = true;
this.DebugBox.ItemHeight = 16;
this.DebugBox.Location = new System.Drawing.Point(52, 131);
this.DebugBox.Name = "DebugBox";
this.DebugBox.Size = new System.Drawing.Size(650, 308);
this.DebugBox.TabIndex = 3;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(716, 450);
this.Controls.Add(this.DebugBox);
this.Controls.Add(this.InputBox);
this.Controls.Add(this.OutputBox);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.TextBox OutputBox;
private System.Windows.Forms.TextBox InputBox;
private System.Windows.Forms.ListBox DebugBox;
}
}
Tidy helper class for dealing with KeyEventArgs
The Is* functions group the keycodes into ranges and detect (if appropriate) the shift states. To* functions produce the char that best represents the KeyCode in the event. ToAlphaNumericAsciiCharacter simply pairs up detectors with producers.
public static class KeyEventArgs_Functions
{
public static bool Between(this Keys source, Keys lhv, Keys rhv)
{
return source >= lhv && source <= rhv;
}
public static bool IsLetterKeyBoardChar(this KeyEventArgs source)
{
return source.KeyCode.Between(Keys.A, Keys.Z);
}
public static bool IsNumberKeyBoardChar(this KeyEventArgs source)
{
return !source.Shift && source.KeyCode.Between(Keys.D0, Keys.D9);
}
public static bool IsNumber10KeyPadChar(this KeyEventArgs source)
{
return source.KeyCode.Between(Keys.NumPad0, Keys.NumPad9);
}
public static char ToLetterKeyBoardChar(this KeyEventArgs source) // Only returns a valid value if IsLetterKeyBoardChar returns true.
{
return source.Shift ? (char)source.KeyCode: char.ToLower((char)source.KeyCode);
}
public static char ToNumberKeyBoardChar(this KeyEventArgs source) // Only returns a valid value if IsNumberKeyBoardChar returns true.
{
return (char)source.KeyCode;
}
public static char ToNumber10KeyPadChar(this KeyEventArgs source) // Only returns a valid value if IsNumber10KeyPadChar returns true.
{
const int DtoNumPadOffset = (int)(Keys.NumPad0 - Keys.D0);
return (char)((int)source.KeyCode - DtoNumPadOffset);
}
public static char? ToAlphaNumericAsciiCharacter(this KeyEventArgs source)
{
if (source.IsLetterKeyBoardChar()) return source.ToLetterKeyBoardChar();
if (source.IsNumberKeyBoardChar()) return source.ToNumberKeyBoardChar();
if (source.IsNumber10KeyPadChar()) return source.ToNumber10KeyPadChar();
return null;
}
}
I need to be able to press a key down and no matter how long it is held down for it only does the action once. I have tried using bools to keep track of the state but haven't had any luck.
bool downPressed = false;
int a = 0;
if (Keyboard.GetState().IsKeyDown(Keys.Down))
{
downPressed = true;
if (downPressed == true)
{
while(a == 0)
{
y += 100;
a++;
}
}
}
This is my latest attempt. The aim is for when the down key is pressed it moves the object by 100px but only once every time it is pressed.
You should add an EventHandler to your KeyDown Event of the Application/Form and just do the
y += 100;
in there.
public void OnKeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
y += 100;
}
If it's strange its going to happen to me.
I'm writing a C# Windows Form application (VS 2010) comprised of multiple textboxes as well as multiple labels for them all. Except for Textbox names the actions are all the same (copied and pasted then the proper TextBox name substituted. They all include a TextChange event and a KeyDown event. The KeyDown event is to catch the Return key and process the data.
The bazaar part is that the first section (region Operating Frequency) works fine. All others never enter the KeyDown event. I've looked through and compared properties for all TextBoxes and I see no difference. I've tried moving the sections around to see if it is the order in the code. Nothing changes. Operating Frequency always works. Nothing else does. I've tried just about everything I can think of. I've even tried going from KeyDown to KeyUp with no difference;
Does anyone have any ideas?
Here is the code. I've only included the first 2 textboxes as the rest are essentially the same.
// Constants
public static readonly double rad = Math.PI / 180, DEG = 180 / Math.PI; // PI to RAD
public const double solM = 299792458; // Speed of light in meters/sec
public const double solMm = solM / 1000; // Speed of light in mega meters/sec
public const double solFt = 983571056.43; // Speed of light in feet/sec
public const double ft2mtr = 0.3048; // Convert Feet to Meters
// Parameters
public static double D = 60; // Loop diameter
public static double C = D*Math.PI; // Loop Circumfrence
public static double conductorD = 0.375; // Conductor diameter
public static double RL = 0; // Added loss resistance
public static double xmitP = 25; // RF xmitter power
public static double freq = 14.1; // Frequence
public MagLoopAntenna()
{
InitializeComponent();
// Start off with some default parameter values
tbFreq.Text = "14.1"; // Target Frequency
tbLoopDia.Text = "60"; // Antenna Loop Diameter
tbUnitsLoopDia.Text = "in";
tbConductorDia.Text = "0.5"; // Conductor Diameter
tbUnitsConductorDia.Text = "in"; // Conductor Diameter Units
tbAddedLossR.Text = "0"; // Added Loss in ohms
tbRfPower.Text = "25"; // RF Power in Watts
}
private bool nonNumberEntered = false; // Command Key Flag
#region Operating Frequency
private void tbFreq_TextChanged(object sender, EventArgs e)
{
int test;
test = 0; // place for breakpoint
}
private void tbFreq_KeyDown(object sender, KeyEventArgs e)
{
// Initialize the flag to false.
nonNumberEntered = false;
// Determine whether the keystroke is a number from the top of the keyboard.
if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
{
// Determine whether the keystroke is a number from the keypad.
if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
{
// Determine whether the keystroke is a backspace.
if (e.KeyCode != Keys.Back)
{
// A non-numerical keystroke was pressed.
// Set the flag to true and evaluate in KeyPress event.
nonNumberEntered = true;
}
if (e.KeyCode == Keys.Enter || e.KeyCode == Keys.Tab)
{
// Note: may want calculate everything at this point.
// We got here now move on to the next textbox
freq = Convert.ToDouble(tbFreq.Text);
tbLoopDia.Focus();
}
}
}
}
#endregion
#region Loop Diameter
private void tbLoopDia_TextChanged(object sender, EventArgs e)
{
int test;
test = 0; // Just a place to put a breakpoint
}
private void tbLoopDia_KeyDown(object sender, KeyEventArgs e)
{
// Initialize the flag to false.
nonNumberEntered = false;
// Determine whether the keystroke is a number from the top of the keyboard.
if (e.KeyCode < Keys.D0 || e.KeyCode > Keys.D9)
{
// Determine whether the keystroke is a number from the keypad.
if (e.KeyCode < Keys.NumPad0 || e.KeyCode > Keys.NumPad9)
{
// Determine whether the keystroke is a backspace.
if (e.KeyCode != Keys.Back)
{
// A non-numerical keystroke was pressed.
// Set the flag to true and evaluate in KeyPress event.
nonNumberEntered = true;
}
if (e.KeyCode == Keys.Enter)
{
int gothere;
gothere = 1; // Just for a breakpoint
// Note: may want calculate everything at this point.
// We got here now move on to the next textbox
//tbConductorDia.Focus(); // will implement this once its' working
}
}
}
}
I am trying to create kind of a spaceship game, where you control an image (of a spaceship obviously) with the arrow keys, to move UP/DOWN/R/L.
For this I use a CoreWindow.KeyDown event.
It actually works fine, but the motion is not smooth enough.
Every time I press one of the arrow keys, the image then:
1. Moves one step to that direction
2. FREEZES, for like half a second (even less)
3. Then continue on moving with no trouble.
(A "step", is an 'int' variable the holds a number of pixels, say, 20).
Of course, that is no way to run a game. I want the ship to move smoothly immediately when i press one of the arrow keys with no "Half a second" delay.
This is my code:
public sealed partial class MainPage : Page
{
double playerYAxisPosition;
double playerXAxisPosition;
int steps = 20;
bool upMovement;
bool downMovement;
bool rightMovement;
bool leftMovement;
public MainPage()
{
this.InitializeComponent();
Window.Current.CoreWindow.KeyDown += CoreWindow_KeyDown;
Window.Current.CoreWindow.KeyUp += CoreWindow_KeyUp;
}
// Recognizes the KeyDown press and sets the relevant booleans to "true"
private void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args) {
playerYPosition = (double) playerShip.GetValue(Canvas.TopProperty);
playerXPosition = (double) playerShip.GetValue(Canvas.LeftProperty);
if (args.VirtualKey == Windows.System.VirtualKey.Up) {
upMovement = true;
}
else if (args.VirtualKey == Windows.System.VirtualKey.Down) {
downMovement = true;
}
else if (args.VirtualKey == Windows.System.VirtualKey.Left) {
leftMovement = true;
}
else if (args.VirtualKey == Windows.System.VirtualKey.Right) {
rightMovement = true;
}
movePlayer();
}
// recognizes the KeyUp event and sets the relevant booleans to "false"
private void CoreWindow_KeyUp(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args) {
if (args.VirtualKey == Windows.System.VirtualKey.Up) {
upMovement = false;
}
else if (args.VirtualKey == Windows.System.VirtualKey.Down) {
downMovement = false;
}
else if (args.VirtualKey == Windows.System.VirtualKey.Left) {
leftMovement = false;
}
else if (args.VirtualKey == Windows.System.VirtualKey.Right) {
rightMovement = false;
}
}
// Calls the movement Methods of the relevant direction
private void movePlayer() {
if (upMovement) {
moveUp();
}
if (downMovement) {
moveDown();
}
if (rightMovement) {
moveRight();
}
if (leftMovement) {
moveLeft();
}
}
private void moveUp() {
playerShip.SetValue(Canvas.TopProperty, playerYPosition - stepsToMove);
}
private void moveDown() {
playerShip.SetValue(Canvas.TopProperty, playerYPosition + stepsToMove);
}
private void moveRight() {
playerShip.SetValue(Canvas.LeftProperty, playerXPosition + stepsToMove);
}
private void moveLeft() {
playerShip.SetValue(Canvas.LeftProperty, playerXPosition - stepsToMove);
}
By the way, the reason I created some dedicated booleans that will be set to 'true' or 'false' on every KeyDown event, and not used the KeyDown event directly, is because that separation allows the element (the ship image) to move diagonally as well, while using the "args.VirtualKey == Windows.System.VirtualKey.SomeArrowKey" directly does not allow it from some reason.
Thank's for your help.
If you want create a game, you should move playerShip in your game loop. You can use DispatcherTimer or register CompositionTarget.Rendering event to create a game loop.
Windows.UI.Xaml.Media.CompositionTarget.Rendering += CompositionTarget_Rendering;
Change CoreWindow_KeyDown event handler as follows:
private void CoreWindow_KeyDown(Windows.UI.Core.CoreWindow sender, Windows.UI.Core.KeyEventArgs args)
{
if (args.VirtualKey == Windows.System.VirtualKey.Up)
{
upMovement = true;
}
else if (args.VirtualKey == Windows.System.VirtualKey.Down)
{
downMovement = true;
}
else if (args.VirtualKey == Windows.System.VirtualKey.Left)
{
leftMovement = true;
}
else if (args.VirtualKey == Windows.System.VirtualKey.Right)
{
rightMovement = true;
}
}
Next, move your ship in CompositionTarget.Rendering event handler.
private void CompositionTarget_Rendering(object sender, object e)
{
playerYPosition = (double)playerShip.GetValue(Canvas.TopProperty);
playerXPosition = (double)playerShip.GetValue(Canvas.LeftProperty);
movePlayer();
}
I'm creating ping pong game. I managed to move both lines (picture box) at same time if keys for movement are pressed down. Problem is that if control for one player is pressed down and then other player JUST clicks (1 time) it breaks movement of other player,so that he needs to press key again. I tried to fix it with keypress and Keyboard.IsKeyDownbut no luck.
Here is my code:
public void Form1_KeyDown(object sender, KeyEventArgs e)
{
Keys up1 = (Keys)Enum.Parse(typeof(Keys), form1.p5_text_kontrole_gor1.Text , true);
Keys down1 = (Keys)Enum.Parse(typeof(Keys), form1.p5_text_kontrole_dol1.Text , true);
Keys up2 = (Keys)Enum.Parse(typeof(Keys), form1.p5_text_kontrole_gor2.Text, true);
Keys down2 = (Keys)Enum.Parse(typeof(Keys), form1.p5_text_kontrole_dol2.Text, true);
if (e.KeyCode == Keys.Escape)
Application.Exit();
if(e.KeyCode == up1)
{
goup1 = true;
}
if (e.KeyCode == down1)
{
godown1 = true;
}
if (e.KeyCode == up2)
{
goup2 = true;
}
if (e.KeyCode == down2)
{
godown2 = true;
}
igra1();
}
private void Form1_KeyUp(object sender, KeyEventArgs e)
{
Keys up1 = (Keys)Enum.Parse(typeof(Keys), form1.p5_text_kontrole_gor1.Text, true);
Keys down1 = (Keys)Enum.Parse(typeof(Keys), form1.p5_text_kontrole_dol1.Text, true);
Keys up2 = (Keys)Enum.Parse(typeof(Keys), form1.p5_text_kontrole_gor2.Text, true);
Keys down2 = (Keys)Enum.Parse(typeof(Keys), form1.p5_text_kontrole_dol2.Text, true);
if (e.KeyCode == up1)
{
goup1 = false;
}
if (e.KeyCode == down1)
{
godown1 = false;
}
if (e.KeyCode == up2)
{
goup2 = false;
}
if (e.KeyCode == down2)
{
godown2 = false;
}
igra1();
}
public void igra1()
{
if (goup1)
{
if (form1.p6_ploscek1.Top > form1.panel6_pongIgra.Top)
form1.p6_ploscek1.Top -= 15;
}
if (goup2)
{
if (form1.p6_ploscek2.Top > form1.panel6_pongIgra.Top)
form1.p6_ploscek2.Top -= 15;
}
if (godown1)
{
if (form1.p6_ploscek1.Bottom < form1.panel6_pongIgra.Bottom)
form1.p6_ploscek1.Top += 15;
}
if (godown2)
{
if (form1.p6_ploscek2.Bottom < form1.panel6_pongIgra.Bottom)
form1.p6_ploscek2.Top += 15;
}
}
I believe you're relying on the fact that keys get repeated by Windows while you hold them down to make your game pieces move. The first key being held down will stop repeating because the new key being held down is repeating instead.
To fix this move the pieces in the Tick() event of a Timer control. In the KeyDown/KeyUp events simply change the state of a variable that represents whether the associated piece should be moving (and what direction it should go). The Timer code will look at the state variables and act accordingly...