I am actually making a game, the issue is that when a card moves (I'm using Timer), it makes me freeze the entire form, sometimes it manages to load, sometimes it freezes the entire game. (+ prevents from clicking a label and clicking a MessageBox)
Issue : (.png)
Here
Code : (timers)
public void moveCardsAdv6_2_Tick(object sender, EventArgs e)
{
if (Partie)
{
Distrib = true;
int y6_2 = 48;
int x6_2 = 13;
pictureBoxd6_2.Top += y6_2;
pictureBoxd6_2.Left += x6_2;
#region Adversaire 6
if (pictureBoxd6_2.Top >= 560 && pictureBoxd6_2.Left >= 110)
{
dist6_1 = true;
SecondDistr = true;
moveCardsAdv6_2.Stop();
pictureBoxd6_2.Location = pictureBoxDeck.Location;
GenCartesAdv();
dist6_1 = false;
SecondDistr = false;
moveCardsAdv7_2.Enabled = true;
moveCardsAdv7_2.Start();
}
#endregion
}
}
Card gen code
#region Adversaire 6
int CarteAleaA6 = CarteAleatoire();
Cartes carteA6 = jeu[CarteAleaA6];
CartesUtilisees.Add(CarteAleaA6);
int CarteAleaA6_2 = CarteAleatoire();
while (CartesUtilisees.Contains(CarteAleaA6_2))
{
CarteAleaA6_2 = CarteAleatoire();
}
CarteAleaA6_2 = 1 * CarteAleaA6_2;
ListeCartes.Add(carteA6);
if (Distrib && dist6_1)
{
if (SecondDistr == false)
{
pictureBoxAdv6_1.ImageLocation = carteA6.Image;
}
else
{
Cartes carteA6_2 = jeu[CarteAleaA6_2];
CartesUtilisees.Add(CarteAleaA6_2);
ListeCartes.Add(carteA6_2);
pictureBoxAdv6_2.ImageLocation = carteA6_2.Image;
}
}
#endregion
As the others suggested, maybe try moving them into asnyc functions and await them.
public async void moveCardsAdv6_2_Tick(object sender, EventArgs e)
{
await moveCardsAdv6_2_TickAsync();
}
private async Task moveCardsAdv6_2_TickAsync()
{
if (Partie)
{
Distrib = true;
int y6_2 = 48;
int x6_2 = 13;
pictureBoxd6_2.Top += y6_2;
pictureBoxd6_2.Left += x6_2;
#region Adversaire 6
if (pictureBoxd6_2.Top >= 560 && pictureBoxd6_2.Left >= 110)
{
dist6_1 = true;
SecondDistr = true;
moveCardsAdv6_2.Stop();
pictureBoxd6_2.Location = pictureBoxDeck.Location;
GenCartesAdv();
dist6_1 = false;
SecondDistr = false;
moveCardsAdv7_2.Enabled = true;
moveCardsAdv7_2.Start();
}
#endregion
}
}
Related
I have a list of images(Helper.theaterImagesInfo) that i am reading through a foreach loop and continuing infinite loop using while until a form closed. images display well with the code below
Application.DoEvents();
await Task.Delay(img.durationInMilliseconds);//img.durationInMilliseconds
this.PictureBox1.Image = img.ImageHere;
Now i want to implement fade effect to those images displaying. Each image is displayed after 5 seconds.
Function to apply fade:
private int intCount = 0;
private List<Bitmap> lstFade = new List<Bitmap>();
private void ApplyFade(Bitmap imgTarget, Bitmap imgSource)
{
int intX = 0;
int intY = 0;
int intAmount = 10;
Rectangle rctDest = new Rectangle(intX, intY,
imgTarget.Width, imgTarget.Height);
using (var tmpBitMap = new Bitmap(imgSource))
using (var gTemp = Graphics.FromImage(tmpBitMap))
for (int i = 0; i <= intAmount; i++)
{
gTemp.DrawImage(imgSource, intX, intY);
ColorMatrix cmColors = new ColorMatrix();
cmColors.Matrix33 = System.Convert.ToSingle(i /
(double)intAmount);
ImageAttributes iaAttributes = new ImageAttributes();
iaAttributes.SetColorMatrix(cmColors);
gTemp.DrawImage(imgTarget, rctDest, intX, intY,
imgTarget.Width, imgTarget.Height, GraphicsUnit.Pixel,
iaAttributes);
lstFade.Add((Bitmap)tmpBitMap.Clone());
}
}
Timer:
private void timer1_Tick(object sender, EventArgs e)
{
intCount += 2;
if (intCount > 10)
{
timer1.Stop();
}
else
{
PictureBox1.Image = lstFade[intCount];
}
}
and here reading list and applying fade to images
public int x=1;
private async void TheaterForm_Shown(object sender, EventArgs e)
{
if (this.PictureBox1.Image == null) SetDefaultImage();
if (Helper.theaterImagesInfo != null && Helper.theaterImagesInfo.Count >
0)
{
while (x == 1)
{
foreach (var img in Helper.theaterImagesInfo.ToList())
{
if (img.IsAnimated)
{
try
{
Application.DoEvents();
var imgS = new Bitmap(this.PictureBox1.Image);
await Task.Delay(img.durationInMilliseconds);
var imgT = new Bitmap(img.ImageHere);
ApplyFade(imgT, imgS);
intCount = 0;
timer1.Interval = 200;
timer1.Start();
}
catch { }
}
else
{
try
{
Application.DoEvents();
await Task.Delay(img.durationInMilliseconds);
var imgS = new Bitmap(this.PictureBox1.Image);
var imgT = new Bitmap(img.ImageHere);
ApplyFade(imgT, imgS);
intCount = 0;
timer1.Interval = 200;
timer1.Start();
}
catch { }
}
if (this.x == 0)
{
break; // exit the for loop early
}
}
}
SetDefaultImage();
}
}
Problem
Fade is applied between starting two images and then keep on the same fading process with those two images. Seems like ApplyFade function doesn't apply again the imgSource and imgTarget once passed through the parameter
I'm trying to code a Simon Says game and I ran into a problem. I cannot figure out how to make my Randomizer timer (that randomizes which boxes are lit up) to run by waves. I want it to run once, then when it's referred to again - run twice and so on.
This is RandomPlace():
private PictureBox RandomPlace()
{
PictureBox p = new PictureBox();
Random rnd = new Random();
switch (rnd.Next(1, 5))
{
case 1:
p = TopRight;
break;
case 2:
p = TopLeft;
break;
case 3:
p = BottomRight;
break;
case 4:
p = BottomLeft;
break;
}
return p;
} //Gets a random PictureBox
This is RandomImage():
private void RandomImage()
{
TopLeft.Enabled = false;
TopRight.Enabled = false;
BottomLeft.Enabled = false;
BottomRight.Enabled = false;
PictureBox a = RandomPlace();
if (a == TopLeft)
{
TopLeft.Image = Resources.TopLeftLit;
label1.Text = "TopLeft";
Thread.Sleep(500);
TopLeft.Image = Resources.TopLeft;
label2.Text = "TopLeftAFTERSLEEP";
Thread.Sleep(500);
pattern[patternRightNow] = 1;
patternRightNow++;
}
if (a == TopRight)
{
TopRight.Image = Resources.TopRightLit;
label1.Text = "TopRight";
Thread.Sleep(500);
TopRight.Image = Resources.TopRight;
label2.Text = "TopRightAFTERSLEEP"; //FIGURE OUT HOW TO RESET PICTURE
Thread.Sleep(500);
pattern[patternRightNow] = 2;
patternRightNow++;
}
if (a == BottomLeft)
{
this.BottomLeft.Image = Resources.BottomLeftLit;
label1.Text = "BottomLeft";
Thread.Sleep(500);
this.BottomLeft.Image = Resources.BottomLeft;
label2.Text = "BottomLeftAFTERSLEEP";
Thread.Sleep(500);
pattern[patternRightNow] = 3;
patternRightNow++;
}
if (a == BottomRight)
{
this.BottomRight.Image = Resources.BottomRightLit;
label1.Text = "BottomRight";
Thread.Sleep(500);
this.BottomRight.Image = Resources.BottomRight;
label2.Text = "BottomRightAFTERSLEEP";
Thread.Sleep(500);
pattern[patternRightNow] = 4;
patternRightNow++;
}
} //Lits up the random PictureBoxes and sets them back to normal
This is Randomizer_Tick():
rivate void Randomizer_Tick(object sender, EventArgs e)
{
RandomImage();
patternRightNow = 0;
tickCount++;
Randomizer.Stop();
ClickCheck();
} //Use RandomImage() to lit up random PictureBoxes on 5 waves, wave 1 - 1 PictureBox, wave 2 - 2 PictureBoxes and so on.
This is ClickCheck():
private void ClickCheck()
{
TopLeft.Enabled = true;
TopRight.Enabled = true;
BottomLeft.Enabled = true;
BottomRight.Enabled = true;
if (tickCount == clickCount)
{
CheckIfWin();
Randomizer.Start();
}
} //Enables the PictureBoxes to be pressed, after the user input reaches the current wave's amount of PictureBoxes lit up, disable PictureBoxes again and start the randomizer
Instead of using timers, I advise you to look at Tasks. It's much easier to create such statemachines.
Fill a list with colors and play it. Wait until the user pressed enough buttons and check the results.
For example: (haven't tested it, it's just for example/pseudo code)
It might contain some typo's.
private List<int> _sequence = new List<int>();
private List<int> _userInput = new List<int>();
private Random _rnd = new Random(DataTime.UtcNow.Milliseconds);
private bool _running = true;
private bool _inputEnabled = false;
private TaskCompletionSource<object> _userInputReady;
public async void ButtonStart_Click(object sender, EventArgs e)
{
if(_running)
return;
while(_running)
{
// add a color/button
_sequence.Add(_rnd.Next(4));
// play the sequence
for(int color in _sequence)
{
// light-up your image, whatever
Console.WriteLine(color);
// wait here...
await Task.Delay(300);
// turn-off your image, whatever
}
// clear userinput
_userInput.Clear();
_userInputReady = new TaskCompletionSource<object>();
_inputEnabled = true;
// wait for user input.
await _userInputReady.Task;
// compare the user input to the sequence.
for(int i=0;i<_sequence.Count;i++)
{
if(_sequence[i] != _userInput[i])
{
_running = false;
break;
}
}
}
Console.WriteLine("Not correct");
}
// one handler for all buttons. Use the .Tag property to store 0, 1, 2, 3
public void ButtonClick(object sender, EventArgs e)
{
if(!_inputEnabled)
return;
var button = (Button)sender;
// add user input to the queue
_userInput.Add((int)button.Tag);
if(_userInput.Count >= _sequence.Count)
_userInputReady.SetResult(null);
}
This is my code so far,im trying to make a c# connect four game but i cant seem to get the win checker to work! I'd like for my game to be able to check for four in a row, horizontally, vertically and diagonally and show a message telling you the winner. I have checked and everything else works as it should.
namespace ConnectFour
{
public partial class Form1 : Form
{
Button[] gameButtons = new Button[42]; //array of buttons for markers(red and blue)
bool blue = true; //blue is set to true if the next marker is to be a blue
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Text = "Connect 4";
this.BackColor = Color.BlanchedAlmond;
this.Width = 500;
this.Height = 500;
for (int i = 0; i < gameButtons.Length; i++)
{
int index = i;
this.gameButtons[i] = new Button();
int x = 50 + (i % 7) * 50;
int y = 50 + (i / 7) * 50;
this.gameButtons[i].Location = new System.Drawing.Point(x, y);
this.gameButtons[i].Name = "btn" + (index + 1);
this.gameButtons[i].Size = new System.Drawing.Size(50, 50);
this.gameButtons[i].TabIndex = i;
//this.gameButtons[i].Text = Convert.ToString(index);
this.gameButtons[i].UseVisualStyleBackColor = true;
this.gameButtons[i].Visible = true;
gameButtons[i].Click += (sender1, ex) => this.buttonHasBeenPressed(sender1, index);
this.Controls.Add(gameButtons[i]);
}
}
private void buttonHasBeenPressed(object sender, int i)
{
if (((Button)sender).BackColor == Color.BlanchedAlmond)
{
if (blue == true)
{
((Button)sender).BackColor = Color.Red;
}
else
{
((Button)sender).BackColor = Color.Blue;
}
blue = !blue;
}
}
private void fourInARow(int a, int b, int c,int d)
{
if (gameButtons[a].BackColor == gameButtons[b].BackColor && gameButtons[a].BackColor == gameButtons[c].BackColor && gameButtons[a].BackColor==gameButtons[d].BackColor)
{
if (gameButtons[a].BackColor == Color.Blue)
{
MessageBox.Show("the winner is player 1");
}
else
{
MessageBox.Show("the winner is player 2");
}
}
}
}
Why do you use Index?
int index = I;
will stay at "0" - because its an initializer and only called once in for-loop.
But it makes no sense for me at all to have an index var.
I'm currently working with the Raspberry PI 3 with Windows 10 IoT and I'm trying to make the game 'Simon Says' in Visual Studio 2015.
Everything is plugged in as followed:
Fritzing image
I got the LEDs working but I can't really figure out how to detect when a button is being pressed.
Parts of the source code:
Variables
private const int BTNRED = 5;
private const int BTNBLUE = 6;
private const int BTNYELLOW = 13;
private const int BTNGREEN = 19;
private GpioPin _btnRed;
private GpioPin _btnBlue;
private GpioPin _btnYellow;
private GpioPin _btnGreen;
private Random rnd;
private static GpioController _gpioController;
Method to recognize when a button is being pressed.
public static IList<Step> PressedButtons
{
get
{
List<Step> returnVal = new List<Step>();
if (GetMap._btnBlue.Read() == GpioPinValue.High)
{ returnVal.Add(Step.Blue); }
if (GetMap._btnGreen.Read() == GpioPinValue.High)
{ returnVal.Add(Step.Green); }
if (GetMap._btnRed.Read() == GpioPinValue.High)
{ returnVal.Add(Step.Red); }
if (GetMap._btnYellow.Read() == GpioPinValue.High)
{ returnVal.Add(Step.Yellow); }
return returnVal;
}
}
/// <summary>
/// Checks if any of the 4 buttons is pressed.
/// </summary>
/// <returns>Returns false if no button is pressed.</returns>
public static bool isButtonPressed
{
get
{
if (GetMap._btnBlue.Read() == GpioPinValue.Low)
{ return true; }
if (GetMap._btnGreen.Read() == GpioPinValue.Low)
{ return true; }
if (GetMap._btnRed.Read() == GpioPinValue.Low)
{ return true; }
if (GetMap._btnYellow.Read() == GpioPinValue.Low)
{ return true; ; }
return false;
}
}
Assigning the right pins on the GPIO to the corresponding variables
private GPIOMap()
{
rnd = new Random();
_gpioController = GpioController.GetDefault();
if (_gpioController == null) { return; }
_ledRed = _gpioController.OpenPin(LEDRED);
_ledRed.SetDriveMode(GpioPinDriveMode.Output);
_ledYellow = _gpioController.OpenPin(LEDYELLOW);
_ledYellow.SetDriveMode(GpioPinDriveMode.Output);
_ledGreen = _gpioController.OpenPin(LEDGREEN);
_ledGreen.SetDriveMode(GpioPinDriveMode.Output);
_ledBlue = _gpioController.OpenPin(LEDBLUE);
_ledBlue.SetDriveMode(GpioPinDriveMode.Output);
_btnBlue = _gpioController.OpenPin(BTNBLUE);
_btnGreen = _gpioController.OpenPin(BTNGREEN);
_btnRed = _gpioController.OpenPin(BTNRED);
_btnYellow = _gpioController.OpenPin(BTNYELLOW);
}
private static GPIOMap GPIOMapInstance;
public static GPIOMap GetMap
{
get
{
if (GPIOMapInstance == null || _gpioController == null)
{ GPIOMapInstance = new GPIOMap(); }
return GPIOMapInstance;
}
}
Run game, where as you can see it should bring me to state 2 whenever a button is being pressed. However this isn't quite the case as the idle animation keeps on going on.
private void RunGame()
{
while (_isRunning)
{
switch (_state)
{
//Idle state
case (0x01):
//If any button is pressed, start the game.
if (GPIOMap.isButtonPressed)
{
_state = 0x02;
Task.Delay(500).Wait();
GPIOMap.PlayStartAnimation();
Task.Delay(1000).Wait();
break;
}
//If nothing happens, continue playing the idle animation.
GPIOMap.PlayIdleAnimationOnce();
break;
//Playback state
case (0x02):
//Play all the currently existing steps.
for (int i = 0; i <= _gameInstance.TotalSteps; i++)
{ GPIOMap.BlinkLight(_gameInstance.GetNextStep(), 500); }
//Generate and play a new step.
GPIOMap.BlinkLight(_gameInstance.GetNextStep(), 500);
//Switch to the input state.
_state = 0x03;
//Set the start time for the input.
_answerPending = DateTime.UtcNow;
break;
//Input state
case (0x03):
if(_gameInstance.CurrentStep > MAXSTEPS)
{
//Win Game
ResetGame();
break;
}
//If the player waits too long before answering, lose the game.
if ((DateTime.UtcNow - _answerPending) > _timeout)
{
GPIOMap.ConfirmWrongAnswer();
ResetGame();
break;
}
//If there are no more steps to re-trace, go back to playback state.
if (_gameInstance.CurrentStep > _gameInstance.TotalSteps)
{ _gameInstance.ResetSteps(); _state = 0x02; break; }
//If no buttons are pressed, keep polling.
if (!GPIOMap.isButtonPressed) { break; }
IList<Step> pressedButtons = GPIOMap.PressedButtons;
//If anything but one button is pressed, lose the game.
if (pressedButtons.Count != 1)
{
GPIOMap.ConfirmWrongAnswer();
ResetGame();
break;
}
if (_gameInstance.VerifyStep(pressedButtons[0]))
{
GPIOMap.BlinkLight(pressedButtons[0], 500);
}
else//Wrong step, end game
{
GPIOMap.ConfirmWrongAnswer();
ResetGame();
break;
}
break;
}
}
}
How can I get my source code to recognize when a button is being pressed so I can go to the next state which involves getting user input on the buttons.
You can use GPIO ValueChanged to catch the button pressed event like this:
_btnBlue = _gpioController.OpenPin(BTNBLUE);
_btnBlue.ValueChanged += btnValueChanged;
public void btnValueChanged(GpioPin pin, GpioPinValueChangedEventArgs e)
{
if (_btnBlue.Read() == GpioPinValue.Low)
{
isBlueButtonPressed = true;
}
}
I am developing a game in C# .But it has some infinite loop that prevents form from being loaded. I have tried many solutions available on internet, But that doesn't seems to work.
My problem is :"How to load the form before execution of while loop."?
My Program.cs Source
namespace SumSwamp
{
static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var window = new Form1();
window.Show();
}
}
}
Form1.cs :
namespace SumSwamp
{
public partial class Form1 : Form
{
public static int DieLargeNum = 0;
public static int DieSmallNum = 0;
public static int DieOperator = 0;
public static int DieTotal = 0;
public static int TotalSpaces = 42;
public static int CompSum = 0;
public static int PlayerSum = 0;
public static Boolean PlayersRoll = true;
public static Boolean WaitForRoll = true;
public static int Turn = 0;
public Form1()
{
InitializeComponent();
this.Load += new EventHandler(this.Form1_Load);
while(Turn == 0) //INFINITE LOOP
{
if (WaitForRoll==false)
{
DieTotal=DieLargeNum;
Random rnd1 = new Random();
DieLargeNum = rnd1.Next(1, 7);
if (DieTotal>DieLargeNum)
{
Turn = 1;
labelStatus.Text = "Player 1's Turn";
WaitForRoll=true;
}
else
{
Turn = 2;
labelStatus.Text = "Player 2's Turn";
WaitForRoll = false;
}
}
}
while ((CompSum < TotalSpaces) & (PlayerSum < TotalSpaces))//INFINITE LOOP
{
while (Turn == 1)
{
if (WaitForRoll == false)
{
if (DieOperator == 1)
{
DieTotal = DieLargeNum + DieSmallNum;
}
else
{
if (DieLargeNum > DieSmallNum)
{
DieTotal = DieLargeNum - DieSmallNum;
}
else
{
DieTotal = DieSmallNum - DieLargeNum;
}
}
PlayerSum = PlayerSum + DieTotal;
Turn = 2;
PlayersRoll = false;
labelStatus.Text = "Player 2's Turn";
}
}
while (Turn == 2)
{
Random rnd1 = new Random();
DieLargeNum = rnd1.Next(1, 7);
Random rnd2 = new Random();
DieSmallNum = rnd2.Next(1, 7);
Random rnd3 = new Random();
DieOperator = rnd3.Next(1, 3);
labelDieLargeNum.Text = DieLargeNum.ToString();
labelDieSmallNum.Text = DieSmallNum.ToString();
if (DieOperator == 1)
{
labelDieOperator.Text = "+";
}
else
{
labelDieOperator.Text = "-";
}
if (DieOperator == 1)
{
DieTotal = DieLargeNum + DieSmallNum;
}
else
{
if (DieLargeNum > DieSmallNum)
{
DieTotal = DieLargeNum - DieSmallNum;
}
else
{
DieTotal = DieSmallNum - DieLargeNum;
}
}
CompSum = CompSum + DieTotal;
Turn = 1;
PlayersRoll = true;
labelStatus.Text = "Player 1's Turn";
}
}
if (CompSum>=TotalSpaces)
{
labelResult.Text = "CPU Player has won!";
}
else
{
labelResult.Text = "You win!";
}
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void buttonRoll_Click(object sender, EventArgs e)
{
if (PlayersRoll == true)
{
Random rnd1 = new Random();
DieLargeNum = rnd1.Next(1, 7);
Random rnd2 = new Random();
DieSmallNum = rnd2.Next(1, 7);
Random rnd3 = new Random();
DieOperator = rnd3.Next(1, 3);
WaitForRoll = false;
labelDieLargeNum.Text = DieLargeNum.ToString();
labelDieSmallNum.Text = DieSmallNum.ToString();
if(DieOperator == 1)
{
labelDieOperator.Text = "+";
}
else
{
labelDieOperator.Text = "-";
}
}
}
}
}
If you put your infinite loop in the Form.Enter() event, the form will be loaded first and then run your loop. But the UI will be unresponsive if you're really in an infinite loop.
Usually UI games are driven by user interaction with controls. So, instead of an infinite loop where you have "WaitForRoll", you just have a button that says "Roll", and when they click it you run your code for that particular event (of rolling the dice).
If you do have to run a loop while the user isn't interacting with controls, it should be done in a separate thread, like a BackgroundWorker or Task.