While Loop Crash in C# game - c#

I am creating a Kinect Text Adventure game for a project. I know the code isn't that great, but the project features more on effects of the game than the game itself, so it doesn't have to be complicated. This section of code is used to progress through the game using certain skeletal positions. The problem I am having is that I am trying to use a while loop so that depending on the current value of f, it will go to that specific room. The only problem is when I use a while loop, it always crashes before it's even started. I'm not sure what the problem is
private void ProcessGesture(Joint head, Joint handleft, Joint handright)
{
while (f!=0)
{
if (handright.Position.Y > head.Position.Y && handleft.Position.Y > head.Position.Y && f == 1)
{
txtBox1.Text = "You find yourself at the foot of a large mountain, with a gaping cave at the front. \nYou have come here to find the Lost Sword of Gaia and you have heard that it lies \nhere in the Cave of Borlak the Red. You can move east";
f = 2;
this.btnangle.Visibility = Visibility.Hidden;
this.slider1.Visibility = Visibility.Hidden;
this.Degree.Visibility = Visibility.Hidden;
this.helpbtn.Visibility = Visibility.Hidden;
}
if (handright.Position.X > 0.3 && f == 2)
{
txtBox1.Text = "You walk up to the entrance of the cave and spot and \nlittle goblin wearing a suit of armour and holding a spear. \n'I'm so bored' he says. 'What I need is a good high five'\nYou can go west";
f = 3;
this.sadGoblin.Visibility = Visibility.Visible;
}
if ((f == 3 && handright.Position.Y > head.Position.Y) || (f == 3 && handleft.Position.Y > head.Position.Y))
{
Uri uri1 = new Uri("/SkeletalTracking;component/Resources/hgoblin.jpg", UriKind.Relative);
ImageSource source1 = new BitmapImage(uri1);
this.sadGoblin.Source = source1;
txtBox1.Text = "'Ah, thank you kind stranger, for that I shall let you in'.\n The goblin steps to the side ";
f = 4;
}
if (f == 4 && handright.Position.Y > head.Position.Y && handleft.Position.Y > head.Position.Y)
{
this.sadGoblin.Visibility = Visibility.Hidden;
txtBox1.Text = "You are now in the main hall of the mountain. You can hear chanting and singing from the north.\nYou see a statue in the middle of the room and two doors to the left and right of it";
f = 5;
}
if (f == 5 && handleft.Position.X < -0.3)
{
txtBox1.Text = "This is Borlak's treasure room. In here are all of the things he has colleted over the years\nSome bought and some not so bought.\nYour eyes are drawn to a necklace in a glass case in the center of the room.\nThere is also a picture of Borlak holding a giant chunk of ham\nYou can go east";
f = 6;
}
if (f == 6 && handright.Position.X > 0.3)
{
f = 5;
}
//else if (f == 5 && handright.Position.X > 0.3)
// {
// txtBox1.Text = "";
// }
}
}

Instead of using a while loop use a switch statement:
int caseSwitch = 1;
switch (caseSwitch)
{
case 1:
Console.WriteLine("Case 1");
break;
case 2:
Console.WriteLine("Case 2");
break;
default:
Console.WriteLine("Default case");
break;
}

Where do you exit the loop? Looks like you're stuck in an infinite loop. Games usually a check like this every update. I don't think you should stay in this loop all in one frame of game play. You should check what f is and decide what to do each frame.
Edit: also, please post what error you get. It would be easier to tell what happens.
In my opinion, take away the while loop, and just let it check 'f' every frame.

The default value of f is 0. If f is not being set ( >=1 ) before this method is called then it would not enter the while loop.
Since all the code isn't shown, and there is no error shown, could "crash" mean immediate exit?

Related

MessageBox.Show being displayed too fast

I'm trying to create my own version of "Fleet battle", but I'm stuck at 99.9%. And here is why. After a ship was destroyed, its color should change to red and then a MessageBox "You won" or "You lost" should come. So now, if the AI destroys my last ship, everything is going fine, all the ships are becoming red one by one and then comes this "You lost" message. But in the opposite case - if I win, the AI ships are becoming red, but the last cell of the last ship becomes red after I click "OK" at the MessageBox "You won". I'm using the same algorithm in both cases and wondering what I'm doing wrong with it. Here is the AI part:
// AI hits a ship
if ((arrayOccupiedCellsBattlefield1[rowIndex, columnIndex] == "1") || (arrayOccupiedCellsBattlefield1[rowIndex, columnIndex] == "2") ||
(arrayOccupiedCellsBattlefield1[rowIndex, columnIndex] == "3") || (arrayOccupiedCellsBattlefield1[rowIndex, columnIndex] == "4"))
{
AIHuntingAShip = true;
dataGridView1.Rows[rowIndex].Cells[columnIndex].Value = " X";
arrayShipsHitbyAIMap[rowIndex, columnIndex] = " X"; // AI marks the burning enemy ships
dataGridView1.Rows[rowIndex].Cells[columnIndex].Style.BackColor = Color.Red;
arrayAITakenShots[transformCoordinatesToCellNumber(rowIndex, columnIndex)] = transformCoordinatesToCellNumber(rowIndex, columnIndex);
storeRowIndex = rowIndex;
storeColumnIndex = columnIndex;
arrayShipsHitbyAIXY[detectedShipLength] = transformCoordinatesToCellNumber(rowIndex, columnIndex);
detectedShipLength++;
if (detectedShipLength == int.Parse(arrayOccupiedCellsBattlefield1[rowIndex, columnIndex])) // AI destroys a ship (the array stores the length of the ship in each of the ship's cells)
{
for (int i = 0; i < detectedShipLength; i++) // placing " o"s around the destroyed ship
{
restrictArea(int.Parse(tranformCellNumberToCoordinates(arrayShipsHitbyAIXY[i])[0].ToString()),
int.Parse(tranformCellNumberToCoordinates(arrayShipsHitbyAIXY[i])[1].ToString()),
dataGridView1,
arrayShipsHitbyAIMap,
arrayAITakenShots);
}
detectedShipLength = 0;
AIHuntingAShip = false;
playerShips--;
textBox6.Text = playerShips.ToString();
if (playerShips == 0)
{
MessageBox.Show("You lost!", "Try it again!", MessageBoxButtons.OK);
dataGridView2.Enabled = false;
}
}
and here is my part:
// player hits a ship
if ((arrayOccupiedCellsBattlefield2[e.RowIndex, e.ColumnIndex] != null) && (arrayOccupiedCellsBattlefield2[e.RowIndex, e.ColumnIndex] != " ."))
{
dataGridView2.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = " X";
arrayShipsHitbyPlayerMap[e.RowIndex, e.ColumnIndex] = " X";
dataGridView2.Rows[e.RowIndex].Cells[e.ColumnIndex].Style.BackColor = Color.Red;
arrayPlayerTakenShots[transformCoordinatesToCellNumber(e.RowIndex, e.ColumnIndex)] = transformCoordinatesToCellNumber(e.RowIndex, e.ColumnIndex);
int shipIdent = int.Parse(arrayOccupiedCellsBattlefield2[e.RowIndex, e.ColumnIndex][0].ToString()); // ship ID
int playersShipLength = int.Parse(arrayOccupiedCellsBattlefield2[e.RowIndex, e.ColumnIndex][1].ToString()); // ship length
arrayForPlayersShipsXY[shipIdent] += e.RowIndex.ToString() + e.ColumnIndex.ToString() + ";"; // save the coordinates of this particular ship
arrayForPlayerCounters[shipIdent]++; // increase this particular cell counter basing on the "shipIdent"
if (arrayForPlayerCounters[shipIdent] == playersShipLength) // ship destroyed, so mark the area with " o"
{
for (int i = 0; i < playersShipLength; i++)
{
string xy = extractXYForPlayersShip(arrayForPlayersShipsXY[shipIdent])[i].ToString();
int x = int.Parse(xy.ToString()[0].ToString());
int y = int.Parse(xy.ToString()[1].ToString());
restrictArea(x, y, dataGridView2, arrayShipsHitbyPlayerMap, arrayPlayerTakenShots);
}
AIShips--;
textBox7.Text = AIShips.ToString();
}
if (AIShips == 0)
{
dataGridView2.Enabled = false;
MessageBox.Show("You won!", "Congrats!", MessageBoxButtons.OK);
}
}
Does anybody have an idea? Thank you for your help.
The algorithms might seem the same, but they are not. There is a lot of repeated code, and it is hard to make sure they both do the "same thing". Try and break out parts of this code into smaller methods so you can reuse them.
Without seeing everything, I think this is the issue:
AI:
if (...) //Ship is destroyed
{
// ...
if (ships == 0)
{
MessageBox.Show(...);
}
}
Player
if (...) //ship is destroyed
{
// ...
}
if (ships == 0)
{
MessageBox.Show(...);
}
MessageBox.Show is called inside vs. outside the "ship destroyed" if block.
This question is not exactly the best for StackOverflow because the code is fairly messy and not simplified. Check out this link for how to ask good questions. But keep at it!
As you said both algorithms are equal but windows refresh your form after you hit the 'OK' button.
So I suggest refresh it yourself before displaying msgbox.
if (AIShips == 0)
{
dataGridView2.Refresh(); // <-------- +
dataGridView2.Enabled = false;
MessageBox.Show("You won!", "Congrats!", MessageBoxButtons.OK);
}
Your code is a bit messy I'm not sure about the grid view name, If your problem is about the first one, try this: dataGridView1.Refresh();

Reading the keys form a keyboard C#

I have a console app in C# that does a animation with a word, in a loop. Its basically showing the word going from left to righ.
My idea is that if the user press upArrow the animation would start to go up , if he press left the word would satrt to go left... and so on
My question is, how can i have a loop running and also have the program listen for the keyboard key that will be pressed at any given moment?
I wrote a good and considerable code for you although you need to complete it yourself. It just follows the order of the Left Arrow key. You need to add some extra code for following the other orders. Also you have to care about indexoutofrangeexception. As you can see I have written some extra code to handle the left side of console. I hope you enjoy it.
static void Main(string[] args)
{
const string txt = "STACKOVERFLOW";
var x = 1;
var startPos = 0;
var col = 0;
while (true)
{
do
{
while (!Console.KeyAvailable && (startPos <= 100 || startPos >= 0))
{
startPos = col + x;
if (startPos < 0)
{
startPos = 0;
x = 1;
}
Console.SetCursorPosition(startPos, 0);
Console.WriteLine(txt);
col = startPos;
Thread.Sleep(500);
Console.Clear();
}
} while (Console.ReadKey(true).Key != ConsoleKey.LeftArrow);
x = -1;
}
}
I don't know if you have found a solution for your program yet, but here is a good tutorial you might find useful.
Basic C# Game Programming Moving Object on the form

Moving trough Array by using ReadKey()

In the beginning i will tell that I'm new with C# and Programming. Trying to learn as much as i can alone.
My first learning project is simple. Moving trough array 10x10 by using "W, S, A, D". It is "game" which is letting user to move his character trough array. The problem is that i want "my character" to move as long as his position will be out of range. So i think i'm trying to make infitive loop which is printing position and lets moving forward. If i'm using for example do{}while(true), position is changing all the time after pressing one key. I'm looking for suggestion how should i construct loop for this kind of "movement".
I'm attaching my code which is responsible for moving character.
int axisx = 0;
int axisy = 0;
var movement = Console.ReadKey();
int[,] level = new int[10, 10];
if (movement.Key.ToString() == "W"){axisy = axisy+1;}
else if (movement.Key.ToString() == "S"){axisy = axisy-1;}
else if (movement.Key.ToString() == "D"){axisx = axisx+1;}
else if (movement.Key.ToString() == "A"){axisx = axisx-1;}
Console.WriteLine("{2} is on position:{0},{1}", axisx, axisy, Player1.getBuilderName());
if (movement.Key == ConsoleKey.Escape)
{
Console.WriteLine("You pressed Escape, Goodbye");
}
You can use a while(true) loop:
int axisx = 0;
int axisy = 0;
while (true)
{
var movement = Console.ReadKey();
if (movement.KeyChar == 'W' || movement.KeyChar == 'w')
{
axisy += 1;
}
else if (movement.KeyChar == 'S' || movement.KeyChar == 's')
{
axisy -= 1;
}
else if (movement.KeyChar == 'D' || movement.KeyChar == 'd')
{
axisx += 1;
}
else if (movement.KeyChar == 'A' || movement.KeyChar == 'a')
{
axisx -= 1;
}
Console.WriteLine("{2} is on position:{0},{1}", axisx, axisy, Player1.getBuilderName());
if (movement.Key == ConsoleKey.Escape)
{
Console.WriteLine("You pressed Escape, Goodbye");
break;
}
}
The break; in the ConsoleKey.Escape block will get you out of the loop.
You can also use movement.KeyChar instead of movement.Key.ToString(), strings are immutable in .NET, so every time you do a ToString() you are creating a new string.

Weird input bug on c#

Errm...Let's see...The bug my project is having is...Weird.
I'm making a Monster Training game,and when it enters on the battle mode,there is a bug that may happen,once you press the key to the left or the right of the controls,before you enter on the battle.
The bug is simple,for example,if you press A(Aka left button),when it lets you choose the action you will take,the game keeps recognizing as if the A button is still pressed,even if it isn't.
This is the code that is causing the bug:
public static int ChooseAction()
{
int choosen = 0;
Battle.CanAct = true;
Battle.ChoosenAction = -1;
while (Battle.ChoosenAction == -1)
{
if (Battle.KeyDelay == 0)
{
if (Procedures.ButtonPressed(Procedures.KeyCodes.KeyRight))
{
Battle.KeyDelay = 64;
int a = Battle.SelectedAction;
a++;
if (a >= BattleActions.Length)
{
a -= BattleActions.Length;
}
Battle.SelectedAction = a;
}
else if (Procedures.ButtonPressed(Procedures.KeyCodes.KeyLeft))
{
Battle.KeyDelay = 64;
int a = Battle.SelectedAction;
a--;
if (a < 0)
{
a += BattleActions.Length;
}
Battle.SelectedAction = a;
}
else if (Procedures.ButtonPressed(Procedures.KeyCodes.Action))
{
Battle.ChoosenAction = Battle.SelectedAction;
}
}
if (KeyDelay != 0 && !Procedures.ButtonPressed(Procedures.KeyCodes.KeyRight) && !Procedures.ButtonPressed(Procedures.KeyCodes.KeyLeft))
{
KeyDelay = 0;
}
if (Battle.KeyDelay > 0)
{
Battle.KeyDelay--;
}
}
choosen = Battle.ChoosenAction;
Battle.CanAct = false;
return choosen;
}
I don't know if this will help,but that script runs on a thread,since it's maden based on the modification of the official script,that were in c# console.
Also,the ButtonPress procedure,returns if the button is pressed,but it ever creates a new boolean everytime it is called.
Any clue of what may be causing the bug?
The Procedures.ButtonPress(KeyCodes) script.
public static bool ButtonPressed(KeyCodes buttonKey)
{
bool pressed = false;
switch (buttonKey)
{
case KeyCodes.MenuKey:
if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.M) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.Start))
pressed = true;
break;
case KeyCodes.RunKey:
if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.LeftShift) || Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.RightShift) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.B))
pressed = true;
break;
case KeyCodes.KeyUp:
if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.W) || Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Up) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.DPadUp))
pressed = true;
break;
case KeyCodes.KeyDown:
if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.S) || Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Down) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.DPadDown))
pressed = true;
break;
case KeyCodes.KeyLeft:
if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.A) || Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Left) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.DPadLeft))
pressed = true;
break;
case KeyCodes.KeyRight:
if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.D) || Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Right) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.DPadRight))
pressed = true;
break;
case KeyCodes.Action:
if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Enter) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.A))
pressed = true;
break;
case KeyCodes.Return:
if (Keyboard.GetState().IsKeyDown(Microsoft.Xna.Framework.Input.Keys.Escape) || GamePad.GetState(PlayerIndex.One).IsButtonDown(Microsoft.Xna.Framework.Input.Buttons.B))
pressed = true;
break;
}
return pressed;
}
After downloading XNA and setting up everything (yes I'm bored at work), I tried the code on a simple menu and it works flawlessly.
The problem is that for some reason XNA's input is not threadable. It doesn't work at all for me when I create another thread with the input. I tried various keys and none of them get a pressed state but the letter "R" which once it's pressed, it stays that way.
I also tried with the R to save the original keyboard state and once the state changes use the original to compare if R was pressed and it worked. However, you will know just ONCE that R was pressed and you won't know if it's being pressed again.
After doing all that I googled and I found recommendations to ALWAYS check your input on your main thread on the update method (as I did at first)
Hope this helps =)

Space Invaders health/array issues

I've been doing some exercises to learn C#. I've been doing XNA and making a space invaders clone.
So far, everything is dandy, but I have come across some walls when coding.
The issues and the supporting code are as follows:
My top of row of invaders have 2 health points, take 2 hits to destroy and yield more points. However, when one is hit, and destroyed, the rest of the top of row are reduced to 1 HP, and take 1 hit to destroy - which is not my desired result.
The offending code I suspect is:
if (playerBullet != null && Type1Invaders != null)
{
Rectangle rectMissile = new Rectangle((int)playerBullet.getX(), playerBullet.getY(), playerBulletIMG.Width, playerBulletIMG.Height);
for (int count = 0; count < 11; count++)
{
Rectangle rectInvader = new Rectangle(Type1Invaders[count].getX(), Type1Invaders[count].getY(), invader1.Width, invader1.Height);
if (Type1Invaders[count].getVis() && rectMissile.Intersects(rectInvader))
{
Type1Invaders[count].setHP(Type1Invaders[count].getHP() - 1);
shootTimer = 0;
if (Type1Invaders[count].getHP() == 0)
{
explosionInstance.Play();
playerBullet = null;
Type1Invaders[count].setVis(false);
score = score + Type1Invaders[count].getPointValue();
}
}
}
}
My second error resides in how I'm detecting the leftmost and rightmost invaders in a row. When an entire row has been destroyed, I get a nullreferenceerror. (Those are a nightmare..)
Anyway, this is the offending code
The method of finding the left and right most invaders
var LeftMost5 = Type5Invaders.Where(i => i.getVis()).FirstOrDefault();
var RightMost5 = Type5Invaders.Where(i => i.getVis()).LastOrDefault();
And the if statement is throwing the null error
if (RightMost5.getX() >= RightGameEdge)
{
Type5.setDir(-1);
for (int count = 0; count < 11; count++)
{
invaderMoveInstance5.Play();
Type5Invaders[count].MoveY(8);
}
}
It only happens with the rightmost, but I can assume it will happen to the left too - I'm assuming I can apply the same logic to fix this error to the left side too.
I can supply more information and snippets if this is not sufficient.
Thanks in advance for the assistance!
For the first issue. I suppose that when a bullet kills an invader, you can say that that bullet won't kill another invader. Therefore, you can add a break; to stop looping. Like this:
if (Type1Invaders[count].getVis() && rectMissile.Intersects(rectInvader))
{
Type1Invaders[count].setHP(Type1Invaders[count].getHP() - 1);
shootTimer = 0;
if (Type1Invaders[count].getHP() == 0)
{
explosionInstance.Play();
playerBullet = null;
Type1Invaders[count].setVis(false);
score = score + Type1Invaders[count].getPointValue();
}
break;
}
For the second error, the FirstOrDefault method returns null in case your collection is empty (after you have killed all type 5 invaders). You simply need to check if it is null or not, like this:
var LeftMost5 = Type5Invaders.Where(i => i.getVis()).FirstOrDefault();
var RightMost5 = Type5Invaders.Where(i => i.getVis()).LastOrDefault();
if(RightMost5 != null)
{
// this means we have a non-null invader
if (RightMost5.getX() >= RightGameEdge)
{
Type5.setDir(-1);
for (int count = 0; count < 11; count++)
{
invaderMoveInstance5.Play();
Type5Invaders[count].MoveY(8);
}
}
}
else
{
//this means that the invader does not exist anymore, so we do nothing
}

Categories