I need help with a test method to see if the snake is/or isn't moving in the right direction, aka "==/!=".
I also need to check if the snake has food on the console or not.
I've tried to call the "starter class" that I have almost all the code in. But I can't try to predict where it will go correctly and assert from there.
How should I go about doing so? [Only need tips!]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace Snake
{
/// <summary>
/// Start class, everything goes from here.
/// </summary>
public class Starter : InterF
{
public static object Key { get; private set; }
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Green;
bool loopC = true;
while (loopC)
{
string mystring = null; Console.WriteLine("Welcome to Snake.\nPress S+Enter to start or press Q+Enter to exit.");
mystring = Console.ReadLine();
switch (mystring)
{
case "Q":
Environment.Exit(0);
break;
case "S":
Console.WriteLine("Starting game!");
System.Threading.Thread.Sleep(4000);
loopC = false;
break;
default:
Console.WriteLine("Invalid Entry.. Try again.");
break;
}
}
//Call for GameSense if
//they want to play.
GameSense();
}
/// <summary>
/// Game object!
/// </summary>
public static void GameSense()
{
//Game console height/width.
Console.WindowHeight = 30;
Console.WindowWidth = 70;
int screenwidth = Console.WindowWidth;
int screenheight = Console.WindowHeight;
Random randomnummer = new Random();
//Lenght of tail == current score.
int score = 2;
int gameover = 0;
//Gather positions from pixel class.
pixel positions = new pixel();
positions.xpos = screenwidth / 2;
positions.ypos = screenheight / 2;
positions.Black = ConsoleColor.Red;
string movement = "RIGHT";
//Position manegment.
List<int> xpos = new List<int>();
List<int> ypos = new List<int>();
int berryx = randomnummer.Next(0, screenwidth);
int berryy = randomnummer.Next(0, screenheight);
//Time manegment.
DateTime time1 = DateTime.Now;
DateTime time2 = DateTime.Now;
string buttonpressed = "no";
//Draw world from GameWorld.cs.
GameWorld.DrawBorder(screenwidth, screenheight);
while (true)
{
GameWorld.ClearConsole(screenwidth, screenheight);
if (positions.xpos == screenwidth - 1 || positions.xpos == 0 || positions.ypos == screenheight - 1 || positions.ypos == 0)
{
gameover = 1;
}
Console.ForegroundColor = ConsoleColor.Green;
if (berryx == positions.xpos && berryy == positions.ypos)
{
score++;
berryx = randomnummer.Next(1, screenwidth - 2);
berryy = randomnummer.Next(1, screenheight - 2);
}
for (int i = 0; i < xpos.Count(); i++)
{
Console.SetCursorPosition(xpos[i], ypos[i]);
Console.Write("*");
if (xpos[i] == positions.xpos && ypos[i] == positions.ypos)
{
gameover = 1;
}
}
if (gameover == 1)
{
break;
}
Console.SetCursorPosition(positions.xpos, positions.ypos);
Console.ForegroundColor = positions.Black;
Console.Write("*");
//Food color & position.
Console.SetCursorPosition(berryx, berryy);
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write("*");
Console.CursorVisible = false;
time1 = DateTime.Now;
buttonpressed = "no";
while (true)
{
time2 = DateTime.Now;
if (time2.Subtract(time1).TotalMilliseconds > 500) { break; }
if (Console.KeyAvailable)
{
ConsoleKeyInfo info = Console.ReadKey(true);
if (info.Key.Equals(ConsoleKey.UpArrow) && movement != "DOWN" && buttonpressed == "no")
{
movement = "UP";
buttonpressed = "yes";
}
if (info.Key.Equals(ConsoleKey.DownArrow) && movement != "UP" && buttonpressed == "no")
{
movement = "DOWN";
buttonpressed = "yes";
}
if (info.Key.Equals(ConsoleKey.LeftArrow) && movement != "RIGHT" && buttonpressed == "no")
{
movement = "LEFT";
buttonpressed = "yes";
}
if (info.Key.Equals(ConsoleKey.RightArrow) && movement != "LEFT" && buttonpressed == "no")
{
movement = "RIGHT";
buttonpressed = "yes";
}
}
}
xpos.Add(positions.xpos);
ypos.Add(positions.ypos);
switch (movement)
{
case "UP":
positions.ypos--;
break;
case "DOWN":
positions.ypos++;
break;
case "LEFT":
positions.xpos--;
break;
case "RIGHT":
positions.xpos++;
break;
}
if (xpos.Count() > score)
{
xpos.RemoveAt(0);
ypos.RemoveAt(0);
}
}
Console.SetCursorPosition(screenwidth / 5, screenheight / 2);
Console.WriteLine("Game over, Score: " + score);
Console.SetCursorPosition(screenwidth / 5, screenheight / 2 + 1);
System.Threading.Thread.Sleep(1000);
restart();
}
/// <summary>
/// Restarter.
/// </summary>
public static void restart()
{
string Over = null; Console.WriteLine("\nWould you like to start over? Y/N");
bool O = true;
while (O)
{
Over = Console.ReadLine();
switch (Over)
{
case "Y":
Console.WriteLine("\nRestarting!");
System.Threading.Thread.Sleep(2000);
break;
case "N":
Console.WriteLine("\nThank you for playing!");
Environment.Exit(0);
break;
default:
Console.WriteLine("Invalid Entry.. Try again.");
break;
}
}
}
/// <summary>
/// Set/get pixel position.
/// </summary>
class pixel
{
public int xpos { get; set; }
public int ypos { get; set; }
public ConsoleColor Black { get; set; }
}
}
}
using Microsoft.VisualStudio.TestTools.UnitTesting;
using NUnit.Framework;
using Snake;
using System;
using System.Collections.Generic;
using System.Text;
namespace Snake.Tests
{
[TestClass()]
public class StarterTests
{
[TestMethod()]
public void test()
{
}
}
}
The difficulty you're experiencing is caused mostly because one giant function is basically untestable.
So, you need to split your code. What follows is a list of the things you should consider:
instead of a giant static function, you could create a class GameSense with a Run method. In your main you would do new GameSense.Run(). In the constructor of the class you would put the initialization, and the state of the game (AFAICT, the various variables declared on top of GameSense).
you should split the body of GameSense by purpose: ReadInput(), UpdatePosition(movement), DrawBerry, CheckGameOver, etc
You should limit the usage non-testing friendly things to only the body of the Run method or in the ReadInput method. Then your tests should proceed like this:
// classes should have an uppercase initial. please rename "pixel" to "Pixel"!
// this is the setup
var pos = new pixel();
pos.xpos = 10;
pos.ypos = 10;
// this is the operation:
UpdatePosition(pos, "UP");
// check the results
Assert.That(pos.xpos, Is.EqualTo(10));
Assert.That(pos.ypos, Is.EqualTo(9));
If it seems mundane, it's because tests usually are :D
Related
I'm trying to make a little game in the Console App and i want an enemy to move at a constantly while moving the player. The code looks like this right now:
public static int y = 5;
public static string player = "O";
public static int enemyX = 10;
static void Main(string[] args)
{
while (true)
{
Console.SetCursorPosition(enemyX, 10);
Console.Write("X");
enemyX = enemyX - 1;
Console.CursorVisible = false;
Console.SetCursorPosition(5, y);
Console.Write(player);
var move = Console.ReadKey(true);
switch (move.Key)
{
case ConsoleKey.W:
y = y - 1;
break;
case ConsoleKey.S:
y = y + 1;
break;
}
if (y <= 0)
{
y = 1;
}
if (y >= 25)
{
y = 24;
}
Console.Clear();
}
}
From what I understand you want the enemy to move regardless of if the player moves or not and to do that you could use Threads
Example:
bool BreakThread = false; //you need this to break the thread loop
Thread enemyThread = new Thread(()=>
{
while(!BreakThread)
{
//do Enemy Actions
}
});
enemyThread.Start();
//then execute your main game loop
but remember to set the BreakThread value to true when ever you
are closing the game.
Will I just have to store the data somewhere or can the second buttonclick take advantage of the current state of the program that the first buttonclick has generated? The first buttonclick has generated local variables that the second buttonclick needs to access.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
namespace AnimalGame
{
public partial class Game : Form
{
List<Animal> animalList = new List<Animal>();
public Game()
{
InitializeComponent();
}
private void SpawnButton_Click(object sender, EventArgs e)
{
int cricketQuantity = Int32.Parse(CricketQuantityInput.Text);
int frogQuantity = Int32.Parse(FrogQuantityInput.Text);
int birdQuantity = Int32.Parse(BirdQuantityInput.Text);
int mouseQuantity = Int32.Parse(MouseQuantityInput.Text);
int snakeQuantity = Int32.Parse(SnakeQuantityInput.Text);
int hunterQuantity = Int32.Parse(HunterQuantityInput.Text);
for (var i = 0; i < cricketQuantity; i++)
{
animalList.Add(new Cricket());
}
for (var i = 0; i < frogQuantity; i++)
{
animalList.Add(new Frog());
}
for (var i = 0; i < birdQuantity; i++)
{
animalList.Add(new Bird());
}
for (var i = 0; i < mouseQuantity; i++)
{
animalList.Add(new Mouse());
}
for (var i = 0; i < snakeQuantity; i++)
{
animalList.Add(new Snake());
}
for (var i = 0; i < hunterQuantity; i++)
{
animalList.Add(new Hunter());
}
int totalAnimals = animalList.Count();
TotalAnimalsTextBox.Text = Convert.ToString(totalAnimals);
foreach (Animal a in animalList)
{
if (a is Cricket)
{
Panel cricketPanel = new Panel();
cricketPanel.Size = new System.Drawing.Size(9, 9);
cricketPanel.BackColor = Color.DarkGoldenrod;
a.Spawn();
GameGrid.Controls.Add(cricketPanel, a.XCoordinate, a.YCoordinate);
}
else if (a is Frog)
{
Panel frogPanel = new Panel();
frogPanel.Size = new System.Drawing.Size(9, 9);
frogPanel.BackColor = Color.Lime;
a.Spawn();
GameGrid.Controls.Add(frogPanel, a.XCoordinate, a.YCoordinate);
}
else if (a is Bird)
{
Panel birdPanel = new Panel();
birdPanel.Size = new System.Drawing.Size(9, 9);
birdPanel.BackColor = Color.SaddleBrown;
a.Spawn();
GameGrid.Controls.Add(birdPanel, a.XCoordinate, a.YCoordinate);
}
}
}
private void NextMoveButton_Click(object sender, EventArgs e)
{
// this code needs to access the current object locations above and "move" them to another cell in
// the grid
}
}
}
public abstract class Animal
{
private int xCoordinate;
private int yCoordinate;
public abstract void Move();
public void Spawn()
{
Random locationX = new Random(Guid.NewGuid().GetHashCode());
var spawnX = locationX.Next(0, 50);
Random locationY = new Random(Guid.NewGuid().GetHashCode());
var spawnY = locationY.Next(0, 50);
xCoordinate = spawnX;
yCoordinate = spawnY;
}
public int XCoordinate
{
get
{
return xCoordinate;
}
set
{
xCoordinate = value;
}
}
public int YCoordinate
{
get
{
return yCoordinate;
}
set
{
if (yCoordinate > 50)
{
yCoordinate = 50;
}
else if ( yCoordinate < 0)
{
yCoordinate = 0;
}
else
{
yCoordinate = value;
}
}
}
}
class Cricket : Animal
{
public override void Move()
{
Random direction = new Random();
// the Cricket only moves one cell at a time.
// 0 = Up
// 1 = Right
// 2 = Down
// 3 = Left
var selectionDirection = direction.Next(0, 4);
switch (selectionDirection)
{
case 0:
YCoordinate -= 1;
break;
case 1:
XCoordinate += 1;
break;
case 2:
YCoordinate += 1;
break;
case 3:
XCoordinate -= 1;
break;
}
}
}
class Frog : Animal
{
public override void Move()
{
Random direction = new Random();
// the Frog moves 3 cells at a time.
// 0 = Up
// 1 = Right
// 2 = Down
// 3 = Left
var selectionDirection = direction.Next(0, 4);
switch (selectionDirection)
{
case 0:
YCoordinate -= 3;
break;
case 1:
XCoordinate += 3;
break;
case 2:
YCoordinate += 3;
break;
case 3:
XCoordinate -= 3;
break;
}
}
}
class Bird : Animal
{
public override void Move()
{
Random direction = new Random();
// the Bird moves 5 cells at a time.
// 0 = Up
// 1 = Right
// 2 = Down
// 3 = Left
var selectionDirection = direction.Next(0, 4);
switch (selectionDirection)
{
case 0:
YCoordinate -= 4;
break;
case 1:
XCoordinate += 4;
break;
case 2:
YCoordinate += 4;
break;
case 3:
XCoordinate -= 4;
break;
}
}
}
class Mouse : Animal
{
public override void Move()
{
Random direction = new Random();
// the Mouse moves 2 cells at a time.
// 0 = Up
// 1 = Right
// 2 = Down
// 3 = Left
var selectionDirection = direction.Next();
switch (selectionDirection)
{
case 0:
YCoordinate -= 2;
break;
case 1:
XCoordinate += 2;
break;
case 2:
YCoordinate += 2;
break;
case 3:
XCoordinate -= 2;
break;
}
}
}
class Snake : Animal
{
public override void Move()
{
Random direction = new Random();
// the Mouse moves 4 cells at a time.
// 0 = Up
// 1 = Right
// 2 = Down
// 3 = Left
var selectionDirection = direction.Next();
switch (selectionDirection)
{
case 0:
YCoordinate -= 2;
break;
case 1:
XCoordinate += 2;
break;
case 2:
YCoordinate += 2;
break;
case 3:
XCoordinate -= 2;
break;
}
}
}
class Hunter : Animal
{
public override void Move()
{
Random direction = new Random();
// the Hunter moves 2 cells at a time.
// 0 = Up
// 1 = Right
// 2 = Down
// 3 = Left
var selectionDirection = direction.Next();
switch (selectionDirection)
{
case 0:
YCoordinate -= 2;
break;
case 1:
XCoordinate += 2;
break;
case 2:
YCoordinate += 2;
break;
case 3:
XCoordinate -= 2;
break;
}
}
}
You can get all Panels from GameGrid.Controls collection. You can iterate through those controls and do your logic.
If you need to know which Animal belongs you which Panel you can create a dictionary field and map each Animal to a Panel:
public partial class Game : Form
{
List<Animal> animalList = new List<Animal>();
Dictionary<Animal, Panel> animalPanels = new Dictionary<Animal, Panel>();
...
// For each animal.
a.Spawn();
GameGrid.Controls.Add(birdPanel, a.XCoordinate, a.YCoordinate);
animalPanels.Add(a, birdPanel);
...
private void NextMoveButton_Click(object sender, EventArgs e)
{
// Access GameGrid.Controls.
// Or animalPanels.
}
}
I'm trying to make a play again button for my game in a separate windows form, but I'm not really sure how to call the new form. Can someone point me in the right direction?
Here's my Form1 code:
namespace BrickO1
{
public partial class Form1 : Form
{
private const int kNumberOfTries = 3;
public int rounds;
private Ball TheBall = new Ball();
private Paddle ThePaddle = new Paddle();
private Paddle TheOtherPaddle = new Paddle();
private PlayAgain playagain = new PlayAgain();
// private System.Windows.Forms.Timer timer1;
private Score TheScore = null;
private Score TheOtherScore = null;
private Thread oThread = null; //thread is used to run sounds independently
[DllImport("winmm.dll")]
public static extern long PlaySound(String lpszName, long hModule, long dwFlags);
//method PlaySound must be imported from the .dll file winmm
public Form1()
{
InitializeComponent();
ThePaddle.Position.X = 5;
ThePaddle.Position.Y = this.ClientRectangle.Bottom - ThePaddle.Height;
TheOtherPaddle.Position.X = 5;
TheOtherPaddle.Position.Y = 0;
// this.ClientRectangle refers to the current container (the instance of Form1)
TheBall.Position.Y = this.ClientRectangle.Bottom - 200;
TheScore = new Score(ClientRectangle.Right - 30, ClientRectangle.Bottom - 40);
TheOtherScore = new Score(ClientRectangle.Right - 30, ClientRectangle.Bottom - 370);
//positions the score - 0 at this moment
// choose Level
SpeedDialog dlg = new SpeedDialog();
/* makes sure that, if the DialogResult property of the button "OK" is on,
the SpeedDialog form appears and stays on the screen, and timer's Interval
gets an appropriate value */
if (dlg.ShowDialog() == DialogResult.OK)
{
timer1.Interval = dlg.Speed;
rounds = dlg.SelectedLength;
}
}
private string m_strCurrentSoundFile = "BallOut.wav"; //sound file is initialized
public void PlayASound() //method to play a sound; to be called by a thread
{
if (m_strCurrentSoundFile.Length > 0)
{
PlaySound(Application.StartupPath + "\\" + m_strCurrentSoundFile, 0, 0);
/* the above gives full path to the location of the sound file from the startup path
of the executable file: Application.StartupPath */
}
m_strCurrentSoundFile = "";
oThread.Abort(); //aborts the tread playing sound
}
public void PlaySoundInThread(string wavefile) //creates and starts a new thread to play a sound
{
m_strCurrentSoundFile = wavefile;
oThread = new Thread(new ThreadStart(PlayASound)); //calls the method PlayASound
oThread.Start();
}
private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e) //method to draw Form1
{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, 0, 0, this.ClientRectangle.Width, this.ClientRectangle.Height);
TheScore.Draw(g);
TheOtherScore.Draw(g);
ThePaddle.Draw(g);
TheOtherPaddle.Draw(g);
TheBall.Draw(g);
}
private void CheckForCollision()
{
if (TheBall.Position.X < 0) // hit the left side, switch polarity
{
TheBall.XStep *= -1;
TheBall.Position.X += TheBall.XStep;
PlaySoundInThread("WallHit.wav");
}
if (TheBall.Position.Y < 0) // hit the top of the form
{
//Lost the ball for 2nd paddle
TheScore.Increment();
if(TheScore.Count == rounds)
{
MessageBox.Show("Congrats! Player 1 wins!");
playagain.Show();
//Application.Exit();
}
Reset();
PlaySoundInThread("BallOut.wav");
}
if (TheBall.Position.X > this.ClientRectangle.Right - TheBall.Width) // hit the right side, switch polarity
{
TheBall.XStep *= -1;
TheBall.Position.X += TheBall.XStep;
PlaySoundInThread("WallHit.wav");
}
if (TheBall.Position.Y > this.ClientRectangle.Bottom - TheBall.YStep) // lost the ball!
{
TheOtherScore.Increment();
if (TheOtherScore.Count == rounds)
{
MessageBox.Show("Congrats! Player 2 wins!");
playagain.Show();
}
Reset();
PlaySoundInThread("BallOut.wav");
}
int hp = HitsPaddle(TheBall.Position); //check if the ball hit the paddle
if (hp > -1)// checks if the ball is not lost
{
PlaySoundInThread("PaddleHit.wav");
switch (hp) //new direction of the ball depends on which quarter of the paddle is hit
{
case 1:
TheBall.XStep = -7;
TheBall.YStep = -3;
break;
case 2:
TheBall.XStep = -5;
TheBall.YStep = -5;
break;
case 3:
TheBall.XStep = 5;
TheBall.YStep = -5;
break;
default:
TheBall.XStep = 7;
TheBall.YStep = -3;
break;
}
}
int hp2 = HitsPaddle2(TheBall.Position); //check if the ball hit the paddle
if (hp2 > -1)// checks if the ball is not lost
{
PlaySoundInThread("PaddleHit.wav");
switch (hp2) //new direction of the ball depends on which quarter of the paddle is hit
{
case 1:
TheBall.XStep = -7;
TheBall.YStep = 3;
break;
case 2:
TheBall.XStep = -5;
TheBall.YStep = 5;
break;
case 3:
TheBall.XStep = 5;
TheBall.YStep = 5;
break;
default:
TheBall.XStep = 7;
TheBall.YStep = 3;
break;
}
}
}
private int HitsPaddle(Point p)
{
Rectangle PaddleRect = ThePaddle.GetBounds(); //current position of the paddle
if (p.Y >= this.ClientRectangle.Bottom - (PaddleRect.Height + TheBall.Height))//If the ball has hit the paddle according to its y value
{
if ((p.X > PaddleRect.Left) && (p.X < PaddleRect.Right)) //ball hits the paddle (horizontally)!
{
if ((p.X > PaddleRect.Left) && (p.X <= PaddleRect.Left + PaddleRect.Width / 4))
return 1; //hits leftmost quarter of the paddle
else if ((p.X > PaddleRect.Left + PaddleRect.Width / 4) && (p.X <= PaddleRect.Left + PaddleRect.Width / 2))
return 2; //hits the second quarter of the paddle
else if ((p.X > PaddleRect.Left + PaddleRect.Width / 2) && (p.X <= PaddleRect.Right - PaddleRect.Width / 2))
return 3; //hits the third quarter of the paddle
else
return 4; //hits the rightmost quarter of the paddle
}
}
return -1;
}
private int HitsPaddle2(Point q)
{
Rectangle Paddle2Rect = TheOtherPaddle.GetBounds(); //current position of the paddle
if (q.Y <= this.ClientRectangle.Top + Paddle2Rect.Height)
{
if ((q.X > Paddle2Rect.Left) && (q.X < Paddle2Rect.Right)) //ball hits the paddle!
{
if ((q.X > Paddle2Rect.Left) && (q.X <= Paddle2Rect.Left + Paddle2Rect.Width / 4))
return 1; //hits leftmost quarter of the paddle
else if ((q.X > Paddle2Rect.Left + Paddle2Rect.Width / 4) && (q.X <= Paddle2Rect.Left + Paddle2Rect.Width / 2))
return 2; //hits the second quarter of the paddle
else if ((q.X > Paddle2Rect.Left + Paddle2Rect.Width / 2) && (q.X <= Paddle2Rect.Right - Paddle2Rect.Width / 2))
return 3; //hits the third quarter of the paddle
else
return 4; //hits the rightmost quarter of the paddle
}
}
return -1;
}
private void Reset() //resets the ball, stops timer, and redraws the main form
{
TheBall.XStep = 5;
TheBall.YStep = 5;
TheBall.Position.Y = this.ClientRectangle.Bottom - 190;
TheBall.Position.X = 5;
timer1.Stop();
TheBall.UpdateBounds();
Invalidate(TheBall.GetBounds());
}
private void timer1_Tick(object sender, System.EventArgs e) //runs one round of the game, when started
{
TheBall.UpdateBounds(); //gets the ball position
Invalidate(TheBall.GetBounds()); //redraws the ball
TheBall.Move(); //moves the ball
TheBall.UpdateBounds(); //updates position of the ball
Invalidate(TheBall.GetBounds()); //redraws the boll
CheckForCollision(); //checks for collision
Invalidate(TheScore.GetFrame()); //redraws the score
Invalidate(TheOtherScore.GetFrame());
}
private void Form1_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
{
string result = e.KeyData.ToString();
Invalidate(ThePaddle.GetBounds());
switch (result)
{
case "Left":
ThePaddle.MoveLeft();
Invalidate(ThePaddle.GetBounds());
if (timer1.Enabled == false) //starts the game if it does not run yet
timer1.Start();
break;
case "Right":
ThePaddle.MoveRight(ClientRectangle.Right);
Invalidate(ThePaddle.GetBounds());
if (timer1.Enabled == false) //starts the game if it does not run yet
timer1.Start();
break;
case "Z":
TheOtherPaddle.MoveLeft();
Invalidate(TheOtherPaddle.GetBounds());
if (timer1.Enabled == false) //starts the game if it does not run yet
timer1.Start();
break;
case "C":
TheOtherPaddle.MoveRight(ClientRectangle.Right);
Invalidate(TheOtherPaddle.GetBounds());
if (timer1.Enabled == false) //starts the game if it does not run yet
timer1.Start();
break;
default:
break;
}
}
public void init()
{
TheBall.XStep = 5;
TheBall.YStep = 5;
TheBall.Position.Y = this.ClientRectangle.Bottom - 190;
TheBall.Position.X = 5;
TheBall.UpdateBounds();
Invalidate(TheBall.GetBounds());
TheScore.Reset();
TheOtherScore.Reset();
}
private void Form1_Load(object sender, EventArgs e)
{
}
}
}
And my PlayAgain class:
namespace BrickO1
{
public partial class PlayAgain : Form1
{
public PlayAgain()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
init();
}
}
}
If you want to make a new form, then create a new object for that form.
Form1 f1=new Form1();
f1.Show();
This is the code for importing objs into my unity.
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
public class ObjImporter : MonoBehaviour {
public GameObject spawnPoint;
public GameObject emptyPrefabWithMeshRenderer;
public string meshPath;
public GameObject spawnedPrefab;
static float progressPercentageMin;
static float progressPercentageMax;
static float progressPercentage;
public Texture2D barBG;
public Texture2D barLoad;
int noOfLines;
void Start ()
{
progressPercentageMin = 0;
progressPercentageMax = 0;
progressPercentage = 0;
}
void Update ()
{
progressPercentage = Mathf.Lerp (progressPercentageMin, progressPercentageMax, Time.time * progressPercentageMax * 0.01f);
if(Input.GetKeyDown("space")){
Mesh importedMesh = GetComponent<ObjImporter>().ImportFile(meshPath);
noOfLines = TotalLines(meshPath);
spawnedPrefab=Instantiate(emptyPrefabWithMeshRenderer,spawnPoint.transform.position,spawnPoint.transform.rotation) as GameObject;
spawnedPrefab.GetComponent<MeshFilter>().mesh=importedMesh;
spawnedPrefab.GetComponent<Renderer>().material.color = new Color(Random.value, Random.value, Random.value, 1.0f);
}
}
public static void UpdateProgressBar()
{
progressPercentageMax += 10;
}
private struct meshStruct
{
public Vector3[] vertices;
public Vector3[] normals;
public Vector2[] uv;
public Vector2[] uv1;
public Vector2[] uv2;
public int[] triangles;
public int[] faceVerts;
public int[] faceUVs;
public Vector3[] faceData;
public string name;
public string fileName;
}
// Use this for initialization
public Mesh ImportFile (string filePath){
meshStruct newMesh = createMeshStruct(filePath);
populateMeshStruct(ref newMesh);
UpdateProgressBar();
Vector3[] newVerts = new Vector3[newMesh.faceData.Length];
Vector2[] newUVs = new Vector2[newMesh.faceData.Length];
Vector3[] newNormals = new Vector3[newMesh.faceData.Length];
int i = 0;
/* The following foreach loops through the facedata and assigns the appropriate vertex, uv, or normal
* for the appropriate Unity mesh array.
*/
UpdateProgressBar();
foreach (Vector3 v in newMesh.faceData)
{
newVerts[i] = newMesh.vertices[(int)v.x - 1];
if (v.y >= 1)
newUVs[i] = newMesh.uv[(int)v.y - 1];
if (v.z >= 1)
newNormals[i] = newMesh.normals[(int)v.z - 1];
i++;
}
Mesh mesh = new Mesh();
mesh.vertices = newVerts;
mesh.uv = newUVs;
mesh.normals = newNormals;
mesh.triangles = newMesh.triangles;
mesh.RecalculateBounds();
mesh.Optimize ();
UpdateProgressBar();
return mesh;
}
private int TotalLines(string filePath)
{
using (StreamReader r = new StreamReader(filePath))
{
int i = 0;
while (r.ReadLine() != null)
{
i++;
}
return i;
}
}
private static meshStruct createMeshStruct(string filename)
{
int triangles = 0;
int vertices = 0;
int vt = 0;
int vn = 0;
int face = 0;
meshStruct mesh = new meshStruct();
mesh.fileName = filename;
// Read and retrieve all the text in the file.
StreamReader stream = File.OpenText(filename);
string entireText = stream.ReadToEnd();
stream.Close(); // End of stream.
UpdateProgressBar();
// Going through the retrieved text.
using (StringReader reader = new StringReader(entireText))
{
string currentText = reader.ReadLine();
char[] splitIdentifier = { ' ' };
string[] brokenString;
UpdateProgressBar();
while (currentText != null)
{
if (!currentText.StartsWith("f ") && !currentText.StartsWith("v ") && !currentText.StartsWith("vt ")
&& !currentText.StartsWith("vn "))
{
currentText = reader.ReadLine();
if (currentText != null)
{
currentText = currentText.Replace(" ", " ");
}
}
else
{
currentText = currentText.Trim(); // Trim the current line
brokenString = currentText.Split(splitIdentifier, 50); // Split the line into an array, separating the original line by blank spaces
switch (brokenString[0])
{
case "v":
vertices++;
break;
case "vt":
vt++;
break;
case "vn":
vn++;
break;
case "f":
face = face + brokenString.Length - 1;
triangles = triangles + 3 * (brokenString.Length - 2); /*brokenString.Length is 3 or greater since a face must have at least
3 vertices. For each additional vertice, there is an additional
triangle in the mesh (hence this formula).*/
break;
}
currentText = reader.ReadLine();
if (currentText != null)
{
currentText = currentText.Replace(" ", " ");
}
}
}
UpdateProgressBar();
}
mesh.triangles = new int[triangles];
mesh.vertices = new Vector3[vertices];
mesh.uv = new Vector2[vt];
mesh.normals = new Vector3[vn];
mesh.faceData = new Vector3[face];
UpdateProgressBar();
return mesh;
}
private static void populateMeshStruct(ref meshStruct mesh)
{
StreamReader stream = File.OpenText(mesh.fileName);
string entireText = stream.ReadToEnd();
stream.Close();
UpdateProgressBar();
using (StringReader reader = new StringReader(entireText))
{
string currentText = reader.ReadLine();
char[] splitIdentifier = { ' ' };
char[] splitIdentifier2 = { '/' };
string[] brokenString;
string[] brokenBrokenString;
int f = 0;
int f2 = 0;
int v = 0;
int vn = 0;
int vt = 0;
int vt1 = 0;
int vt2 = 0;
UpdateProgressBar();
while (currentText != null)
{
if (!currentText.StartsWith("f ") && !currentText.StartsWith("v ") && !currentText.StartsWith("vt ") &&
!currentText.StartsWith("vn ") && !currentText.StartsWith("g ") && !currentText.StartsWith("usemtl ") &&
!currentText.StartsWith("mtllib ") && !currentText.StartsWith("vt1 ") && !currentText.StartsWith("vt2 ") &&
!currentText.StartsWith("vc ") && !currentText.StartsWith("usemap "))
{
currentText = reader.ReadLine();
if (currentText != null)
{
currentText = currentText.Replace(" ", " ");
}
}
else
{
currentText = currentText.Trim();
brokenString = currentText.Split(splitIdentifier, 50);
switch (brokenString[0])
{
case "g":
break;
case "usemtl":
break;
case "usemap":
break;
case "mtllib":
break;
//
case "v":
mesh.vertices[v] = new Vector3(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]),
System.Convert.ToSingle(brokenString[3]));
v++;
break;
case "vt":
mesh.uv[vt] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
vt++;
break;
case "vt1":
mesh.uv[vt1] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
vt1++;
break;
case "vt2":
mesh.uv[vt2] = new Vector2(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]));
vt2++;
break;
case "vn":
mesh.normals[vn] = new Vector3(System.Convert.ToSingle(brokenString[1]), System.Convert.ToSingle(brokenString[2]),
System.Convert.ToSingle(brokenString[3]));
vn++;
break;
case "vc":
break;
case "f":
int j = 1;
List<int> intArray = new List<int>();
while (j < brokenString.Length && ("" + brokenString[j]).Length > 0)
{
Vector3 temp = new Vector3();
brokenBrokenString = brokenString[j].Split(splitIdentifier2, 3); //Separate the face into individual components (vert, uv, normal)
temp.x = System.Convert.ToInt32(brokenBrokenString[0]);
if (brokenBrokenString.Length > 1) //Some .obj files skip UV and normal
{
if (brokenBrokenString[1] != "") //Some .obj files skip the uv and not the normal
{
temp.y = System.Convert.ToInt32(brokenBrokenString[1]);
}
temp.z = System.Convert.ToInt32(brokenBrokenString[2]);
}
j++;
mesh.faceData[f2] = temp;
intArray.Add(f2);
f2++;
}
j = 1;
while (j + 2 < brokenString.Length) //Create triangles out of the face data. There will generally be more than 1 triangle per face.
{
mesh.triangles[f] = intArray[0];
f++;
mesh.triangles[f] = intArray[j];
f++;
mesh.triangles[f] = intArray[j+1];
f++;
j++;
}
break;
}
currentText = reader.ReadLine();
if (currentText != null)
{
currentText = currentText.Replace(" ", " "); //Some .obj files insert double spaces, this removes them.
}
}
}
}
UpdateProgressBar();
}
void OnGUI()
{
//GUI.Label (new Rect (20, 20, 100, 100), progressPercentage.ToString());
GUI.DrawTexture(new Rect(100, 100, 100, 20), barBG);
GUI.DrawTexture(new Rect(100, 100, progressPercentage, 20), barLoad);
}
}
A progress bar is supposed run smoothly when the model is loaded.
However, Unity hangs due to the loading of the modeland you can't actually see the progress of the bar.
Anyone knows how to delay the drawing of the progress bar so that it will be seen.
The reasons Unity hangs is because Unity is (mostly) run on a single thread, Meaning the ImportFile function in Update will complete fully before the next line of code will be called which will prevent the OnGUI function from being called until the entire Update function is complete.
The only way around this is to use MultiThreading which can be tough in Unity since you can't access any of Unity's data outside of the main thread, so you will only have access to your own data in a separate thread.
https://web.archive.org/web/20140702033426/http://unitygems.com/threads/
Looks like the original website is down but this did a really good job of explaining threading in Unity for me and comes with some example code and use cases
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I'm writing a simple console based game. In the game, I have two functions that should move two things - A paddle and a ball.
But when I use two loops that have Thread.sleep, the game doesn't work. How can I use the two loops with Thread.sleep and get it to run properly?
My code:
class Program
{
static void Ball()
{
}
static void Main(string[] args)
{
int x = 10; int y = 10;
int dx = 1; int dy = 1;
ConsoleKeyInfo Exit = new ConsoleKeyInfo();
do
{
Console.SetCursorPosition(x, y);
Console.WriteLine(" ");
x += dx;
y += dy;
Console.SetCursorPosition(x, y);
Console.Write("*");
Thread.sleep(95);
if (x > 77) dx = -dx;
if (x < 2) dx = -dx;
if (y > 22) dy = -dy;
if (y < 2) dy = -dy;
} while (true);
int a = 2;
int b = 23;
int da = 1;
Console.SetCursorPosition(a, b);
Console.Write(" ");
if (Console.KeyAvailable)
{
ConsoleKeyInfo k = Console.ReadKey(true);
if (k.Key == ConsoleKey.LeftArrow) a = a - da;
else if (k.Key == ConsoleKey.RightArrow) a = a + da;
if (a > 78) a = -da;
if (a < 2) a = -da;
Thread.Sleep(200);
}
Console.SetCursorPosition(a, b);
Console.Write("~~~~~~~~~~");
}
}
When I run the example code you provided, the application will run. That is to say, the ball (*) will move around the screen. Are you expecting the ball to move on the screen, and the paddle to be drawn and move when an arrow is pressed? If so, you should look at how you are looping. The issue I see is that you have a loop that draws the ball and your loop will never ends, and therefore your code will not draw the paddle and/or reflect your arrow key changes. Is your expectation also for the Thread.Sleep to pause the loop and allow you to draw/move the paddle?
UPDATE:
namespace ConsoleGame
{
class Ball {
private static Ball _instance;
private int _a = 10, _b = 10;
private int _dx = 1, _dy = 1;
private int _timer = 0;
private int _milliseconds = 1000;
private Ball() { }
public static Ball Instance {
get {
if(_instance == null) {
_instance = new Ball();
}
return _instance;
}
}
/// <summary>
/// Move the ball on screen
/// </summary>
/// <param name="speed">The refresh/draw speed of the screen</param>
public void Move(int speed) {
if (_timer >= _milliseconds) {
// Set the cursor position to the current location of the ball
Console.SetCursorPosition(_a, _b);
// Clear the ball from the screen
Console.WriteLine(" ");
_a += _dx;
_b += _dy;
// Set a new locatio for the ball
Console.SetCursorPosition(_a, _b);
// Draw the new ball location on screen
Console.Write("*");
if (_a > 77) _dx = -_dx;
if (_a < 2) _dx = -_dx;
if (_b > 22) _dy = -_dy;
if (_b < 2) _dy = -_dy;
} else {
_timer = _timer + speed;
}
}
}
class Paddle {
private int _x = 2, _y = 23, _da = 1;
public int x {
get {
if (_x > (Console.BufferWidth - "~~~~~~~~~~".Length)) x = -_da;
if (_x < 2) x = -_da;
if (_x < 0) x = 2;
return _x;
}
set { _x = value; }
}
private static Paddle _instance;
private Paddle() { }
public static Paddle Instance {
get {
if (_instance == null) {
_instance = new Paddle();
}
return _instance;
}
}
/// <summary>
/// Move the Paddle on screen
/// </summary>
/// <param name="direction">Direction to move the paddle (Left = -1, Right = 1, Do Not Move = 0)</param>
public void Move(int direction) {
Console.SetCursorPosition(x, _y);
Console.Write(" ");
x = x - direction;
Console.SetCursorPosition(x, _y);
Console.Write("~~~~~~~~~~");
}
}
class Program {
private static int PaddleDirection = 0;
static void Main(string[] args) {
Thread ConsoleKeyListener = new Thread(new ThreadStart(ListerKeyBoardEvent));
ConsoleKeyListener.Name = "KeyListener";
ConsoleKeyListener.Start();
//ConsoleKeyListener.IsBackground = true;
int speed = 50;
do {
Console.Clear();
Ball.Instance.Move(speed);
Paddle.Instance.Move(PaddleDirection);
PaddleDirection = 0; // You can remove this line to make the paddle loop left/right on the screen after key press.
Thread.Sleep(speed);
} while (true);
}
private static void ListerKeyBoardEvent() {
do {
ConsoleKeyInfo k = Console.ReadKey(true);
if (k.Key == ConsoleKey.LeftArrow) PaddleDirection = 1;
else if (k.Key == ConsoleKey.RightArrow) PaddleDirection = -1;
else PaddleDirection = 0;
Console.ReadKey(false);
} while (true);
}
}
}