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();
Related
I have two different shapes . A rectangle which moves by using the keys up,down,right,left and a circle that is moving in a fixed position ( Up and down the Y axis) . I'm trying the detect the collision that if I move the rectangle into the circle the collision is to be detected and the game to stop . I have tried this code but it doesn't work:
public bool collision()
{
if (PlayerPositionX == EnemyPosX & PlayerPositionY == EnemyPosY )
{
_movementTimer.Stop();
}
if (collision()==true)
{
_movementTimer.Stop();
}
return collision();
}
this is the full code . Does anyone have any idea how to do it?
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.Timers;
using System.Drawing.Imaging;
using Timer = System.Windows.Forms.Timer;
namespace prot_4
{
public partial class Form1 : Form
{
int PlayerPositionX = 40, PlayerPositionY = 200, width = 40, height = 40; // player
int EnemyWidth = 40, EnemyHeight = 40, EnemyPosX = 100, EnemyPosY = 0, EnemySpeedX = 0, EnemySpeedY = 20; // enemy
int EnemyWidth2 = 40, EnemyHeight2 = 40, EnemyPosX2 = 200, EnemyPosY2 = 400, EnemySpeedX2 = 0, EnemySpeedY2 = 20; // enemy2
int EnemyWidth3 = 40, EnemyHeight3 = 40, EnemyPosX3 = 300, EnemyPosY3 = 0, EnemySpeedX3 = 0, EnemySpeedY3 = 20; // enemy3
int EnemyWidth4 = 40, EnemyHeight4 = 40, EnemyPosX4 = 400, EnemyPosY4 = 400, EnemySpeedX4 = 0, EnemySpeedY4 = 20; // enemy4
int EnemyWidth5 = 40, EnemyHeight5 = 40, EnemyPosX5 = 500, EnemyPosY5 = 0, EnemySpeedX5 = 0, EnemySpeedY5 = 20; // enemy5
int EnemyWidth6 = 40, EnemyHeight6 = 40, EnemyPosX6 = 600, EnemyPosY6 = 400, EnemySpeedX6 = 0, EnemySpeedY6 = 20; // enemy6
private bool moveUp, moveDown, moveLeft, moveRight;
private System.Windows.Forms.Timer _movementTimer = new Timer { Interval = 100 };
public bool collision()
{
if (PlayerPositionX == EnemyPosX & PlayerPositionY == EnemyPosY )
{
_movementTimer.Stop();
}
if (collision()==true)
{
_movementTimer.Stop();
}
return collision();
}
public Form1()
{
InitializeComponent();
_movementTimer.Tick += movementTimer_Tick;
}
private void movementTimer_Tick(object sender , EventArgs e)
{
playerControls();
}
//Form1_KeyDown
private void playerControls() // Player controls
{
if (moveRight)
{
PlayerPositionX += 5;
if (PlayerPositionX >= 800 - width)
{
PlayerPositionX = 800 - width;
}
}
if (moveLeft)
{
PlayerPositionX -= 5;
if (PlayerPositionX <= -43 + width)
{
PlayerPositionX = -43 + width;
}
}
if (moveUp)
{
PlayerPositionY -= 5;
if (PlayerPositionY <= 0)
{
PlayerPositionY = 0;
}
}
if (moveDown)
{
PlayerPositionY += 5;
if (PlayerPositionY >= 410)
{
PlayerPositionY = 410;
}
}
}
public void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
moveUp = true;
break;
case Keys.Down:
moveDown = true;
break;
case Keys.Left:
moveLeft = true;
break;
case Keys.Right:
moveRight = true;
break;
}
playerControls();
_movementTimer.Start();
}
public void Form1_KeyUp(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
moveUp = false;
break;
case Keys.Down:
moveDown = false;
break;
case Keys.Left:
moveLeft = false;
break;
case Keys.Right:
moveRight = false;
break;
}
if (!(moveUp || moveDown || moveLeft || moveRight ))
{
_movementTimer.Stop();
}
}
public void player(object sender, PaintEventArgs e) // drawing the player
{
e.Graphics.SmoothingMode =
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.Clear(this.BackColor);
e.Graphics.FillRectangle((Brushes.Blue), PlayerPositionX, PlayerPositionY, width, height);
e.Graphics.DrawRectangle(Pens.Black,
PlayerPositionX, PlayerPositionY,
width, height);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX, EnemyPosY,
EnemyWidth, EnemyHeight);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX, EnemyPosY,
EnemyWidth, EnemyHeight);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX2, EnemyPosY2,
EnemyWidth2, EnemyHeight2);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX2, EnemyPosY2,
EnemyWidth2, EnemyHeight2);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX3, EnemyPosY3,
EnemyWidth3, EnemyHeight3);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX3, EnemyPosY3,
EnemyWidth3, EnemyHeight3);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX4, EnemyPosY4,
EnemyWidth, EnemyHeight);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX4, EnemyPosY4,
EnemyWidth4, EnemyHeight4);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX5, EnemyPosY5,
EnemyWidth5, EnemyHeight5);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX5, EnemyPosY5,
EnemyWidth5, EnemyHeight5);
e.Graphics.SmoothingMode = //drawing the enemy
System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.FillEllipse(Brushes.Red,
EnemyPosX6, EnemyPosY6,
EnemyWidth6, EnemyHeight6);
e.Graphics.DrawEllipse(Pens.Black,
EnemyPosX6, EnemyPosY6,
EnemyWidth6, EnemyHeight6);
}
private void PlayerMoveTimer(object sender, EventArgs e ) // timer 2
{
Invalidate();
}
private void moveTimer(object sender, EventArgs e) // timer
{
//update coorndinates
EnemyPosX += EnemySpeedX; // how the enemy moves //timer 1
if (EnemyPosX < 0 ||
EnemyPosX + EnemyWidth > this.ClientSize.Width
)
{
EnemySpeedX = -EnemySpeedX;
}
EnemyPosY -= EnemySpeedY;
if (EnemyPosY < 0 ||
EnemyPosY + EnemyHeight > this.ClientSize.Height
)
{
EnemySpeedY = -EnemySpeedY;
}
EnemyPosX2 += EnemySpeedX2; // how the enemy moves //timer 1
if (EnemyPosX2 < 0 ||
EnemyPosX2 + EnemyWidth2 > this.ClientSize.Width
)
{
EnemySpeedX2 = -EnemySpeedX2;
}
EnemyPosY2 += EnemySpeedY2;
if (EnemyPosY2 < 0 ||
EnemyPosY2 + EnemyHeight2 > this.ClientSize.Height
)
{
EnemySpeedY2 = -EnemySpeedY2;
}
EnemyPosX3 += EnemySpeedX3; // how the enemy moves //timer 1
if (EnemyPosX3 < 0 ||
EnemyPosX3 + EnemyWidth3 > this.ClientSize.Width
)
{
EnemySpeedX3 = -EnemySpeedX3;
}
EnemyPosY3 -= EnemySpeedY3;
if (EnemyPosY3 < 0 ||
EnemyPosY3 + EnemyHeight3 > this.ClientSize.Height
)
{
EnemySpeedY3 = -EnemySpeedY3;
}
EnemyPosX4 += EnemySpeedX4; // how the enemy moves //timer 1
if (EnemyPosX4 < 0 ||
EnemyPosX4 + EnemyWidth4 > this.ClientSize.Width
)
{
EnemySpeedX4 = -EnemySpeedX4;
}
EnemyPosY4 += EnemySpeedY4;
if (EnemyPosY4 < 0 ||
EnemyPosY4 + EnemyHeight4 > this.ClientSize.Height
)
{
EnemySpeedY4 = -EnemySpeedY4;
}
EnemyPosX5 += EnemySpeedX5; // how the enemy moves //timer 1
if (EnemyPosX5 < 0 ||
EnemyPosX5 + EnemyWidth5 > this.ClientSize.Width
)
{
EnemySpeedX = -EnemySpeedX;
}
EnemyPosY5 -= EnemySpeedY5;
if (EnemyPosY5 < 0 ||
EnemyPosY5 + EnemyHeight5 > this.ClientSize.Height
)
{
EnemySpeedY5 = -EnemySpeedY5;
}
EnemyPosX6 += EnemySpeedX6; // how the enemy moves //timer 1
if (EnemyPosX6 < 0 ||
EnemyPosX6 + EnemyWidth6 > this.ClientSize.Width
)
{
EnemySpeedX6 = -EnemySpeedX6;
}
EnemyPosY6 += EnemySpeedY6;
if (EnemyPosY6 < 0 ||
EnemyPosY6 + EnemyHeight6 > this.ClientSize.Height
)
{
EnemySpeedY6 = -EnemySpeedY6;
}
//refresh windows
Invalidate();
}
}
}
Sorry, but from a brief look at your code, it doesn't make much sense to me. A recursive collision-function which never returns an actual value. What is the idea behind that ? Does it even compile ?
Having said that, the specific collision detection you are after isn't that complicated. Here is the general way to do it.
If you know from the rectangle the coordinates of the four corners and from the circle the coordinate of the center and the length of the radius. All you have to do is calculate the distance (with the pythagoras formula) from each rectangle-corner to the center of the circle. If one or more of these distances is less than the radius of the circle you have a collision.
UPDATE
after giving this problem some more thought I now see there are some cases when a rectangle and circle collide which are not covered by my method. However I still think my method is a good way to start.
I am learning C #, and I am creating a hypothetical game for me to understand the language. I want several bots to follow the Player who is moving the rectangle, but I can only move the player, but the automatic bots do not move.
I really researched what I could do to move these bots. And I came to the conclusion that I would have to understand Threads, which simply causes the program not to crash.
I leave here the full code of what I am trying.
public partial class Form1 : Form
{
public enum Direction { Up, Down, Left, Right }
private Player player;
private List<Bot> bots;
public Form1()
{
InitializeComponent();
this.Paint += Form1_Paint;
this.KeyPreview = true;
this.KeyDown += Form1_KeyDown;
this.player = new Player(new Size(8, 8));
this.bots = new List<Bot>();
for (int i = 0; i < 30; i++)
{
Bot bot = new Bot(player, new Size(8, 8));
bot.Follow();
this.bots.Add(bot);
}
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
switch (e.KeyCode)
{
case Keys.Up:
player.Move(Direction.Up);
break;
case Keys.Down:
player.Move(Direction.Down);
break;
case Keys.Left:
player.Move(Direction.Left);
break;
case Keys.Right:
player.Move(Direction.Right);
break;
}
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
List<Rectangle> rs = new List<Rectangle>();
rs = this.bots.Select(x => x.Rectangle).ToList();
rs.Add(player.Rectangle);
if (rs.Count > 0)
{
e.Graphics.FillRectangles(new SolidBrush(Color.Red), rs.ToArray());
}
}
}
public class Player
{
private Rectangle rectangle;
public Rectangle Rectangle { get => rectangle; }
public Player(Size size)
{
this.rectangle = new Rectangle() { Size = size };
}
public void Move(Direction direction)
{
switch (direction)
{
case Direction.Up:
this.rectangle.Y -= 3;
break;
case Direction.Down:
this.rectangle.Y += 3;
break;
case Direction.Left:
this.rectangle.X -= 3;
break;
case Direction.Right:
this.rectangle.X += 3;
break;
default:
break;
}
}
}
public class Bot
{
private Rectangle rectangle;
private Player player;
public Rectangle Rectangle { get => rectangle; }
public Bot(Player player, Size size)
{
this.player = player;
this.rectangle = new Rectangle() { Size = size };
}
public void Follow()
{
Task.Run(() =>
{
while (true)
{
Point p = player.Rectangle.Location;
Point bot = rectangle.Location;
for (int i = bot.X; i < p.X; i += 2)
{
Thread.Sleep(100);
bot.X = i;
}
for (int i = bot.X; i > p.X; i -= 2)
{
Thread.Sleep(100);
bot.X = i;
}
for (int i = bot.Y; i < p.Y; i += 2)
{
Thread.Sleep(100);
bot.Y = i;
}
for (int i = bot.Y; i > p.Y; i -= 2)
{
Thread.Sleep(100);
bot.Y = i;
}
}
});
}
}
As you can see, I can only move the player, but the bots don't move what can I do to move the bots?
I think a Timer would work better here and remove the requirement for you to fully understanding threading at this point, as it will handle the details for you. I'm assuming you actually want the bots to "follow" instead of only moving when the Player moves and will fall behind if the player is moving quickly.
So to use a Timer, I would adjust your Bot class as below, to remove your usage of threads and only allow it to take a single step towards the player in the Follow method which will be called every 100ms. Note Rectangle is a struct, so it is not mutable - that is why your bots do not move - if you do the following:
Point bot = Rectangle.Location;
bot.X = 5;
You're probably thinking Rectangle.Location.X is now 5; but it is not. So we create a new rectangle using the new position.
public class Bot
{
private Player player;
public Rectangle Rectangle { get; set; }
public Bot(Player player, Size size)
{
this.player = player;
this.Rectangle = new Rectangle() { Size = size };
}
public void Follow()
{
Point p = player.Rectangle.Location;
Point bot = Rectangle.Location;
for (int i = bot.X + 2; i < p.X;)
{
bot.X = i;
break;
}
for (int i = bot.X - 2; i > p.X;)
{
bot.X = i;
break;
}
for (int i = bot.Y + 2; i < p.Y;)
{
bot.Y = i;
break;
}
for (int i = bot.Y - 2; i > p.Y;)
{
bot.Y = i;
break;
}
Rectangle = new Rectangle(bot, player.Rectangle.Size);
}
}
And add the following code to replace your existing constructor and add another method to handle the Timer tick.
private Timer timer;
public Form1()
{
InitializeComponent();
this.Paint += Form1_Paint;
this.KeyPreview = true;
this.KeyDown += Form1_KeyDown;
// setup a timer which will call Timer_Tick every 100ms
timer = new System.Windows.Forms.Timer();
timer.Interval = 100;
timer.Tick += Timer_Tick;
timer.Start();
this.player = new Player(new Size(8, 8));
this.bots = new List<Bot>();
for (int i = 0; i < 30; i++)
{
Bot bot = new Bot(player, new Size(8, 8));
bot.Follow();
this.bots.Add(bot);
}
}
private void Timer_Tick(object sender, System.EventArgs e)
{
foreach (var bot in bots)
bot.Follow();
this.Invalidate();
}
Point is a value type (a struct). (Read more about this at What's the difference between struct and class in .NET?)
When you did this:
Point bot = Rectangle.Location;
bot.X = i;
...you created a local Point and modified it. This doesn't change the Location of the Rectangle of the Bot. Also, Rectangles are structs too, so you have to modify the original Bot's Rectangle, or assign a new Rectangle to the Bot.
To fix, you could replace:
bot.X = i;
...with...
this.rectangle.X = i;
And make the similar change for .Y (in all your for loop locations)
Spelling it all out:
public void Follow()
{
Task.Run(() =>
{
while (true) {
Point p = player.Rectangle.Location;
Point bot = rectangle.Location;
for (int i = bot.X; i < p.X; i += 2) {
Thread.Sleep(100);
this.rectangle.X = i;
}
for (int i = bot.X; i > p.X; i -= 2) {
Thread.Sleep(100);
this.rectangle.X = i;
}
for (int i = bot.Y; i < p.Y; i += 2) {
Thread.Sleep(100);
this.rectangle.Y = i;
}
for (int i = bot.Y; i > p.Y; i -= 2) {
Thread.Sleep(100);
this.rectangle.Y = i;
}
}
});
}
public class green : MonoBehaviour
{
private AudioSource source;
public AudioClip sound;
static int result = 0;
void Start()
{
StartCoroutine("RoutineCheckInputAfter3Minutes");
Debug.Log("a");
}
IEnumerator RoutineCheckInputAfter3Minutes()
{
System.Random ran = new System.Random();
int timeToWait = ran.Next(1, 50) * 1000;
Thread.Sleep(timeToWait);
source = this.gameObject.AddComponent<AudioSource>();
source.clip = sound;
source.loop = true;
source.Play();
System.Random r = new System.Random();
result = r.Next(1, 4);
Debug.Log("d");
yield return new WaitForSeconds(3f * 60f);
gm.life -= 1;
Debug.Log("z");
}
public void Update()
{
if (result == 1 && gm.checka == true)
{
Debug.Log("e");
StopCoroutine("RoutineCheckInputAfter3Minutes");
gm.life += 1;
source.Stop();
gm.checka = false;
Debug.Log("j");
}
if (result == 2 && gm.checkb == true)
{
Debug.Log("f");
StopCoroutine("RoutineCheckInputAfter3Minutes");
gm.life += 1;
source.Stop();
gm.checkb = false;
Debug.Log("z");
}
else if (result == 3 && gm.checkc == true)
{
StopCoroutine("RoutineCheckInputAfter3Minutes");
Debug.Log("g");
gm.life += 1;
source.Stop();
gm.checkc = false;
Debug.Log(gm.life);
}
}
}
There are two problems
I want to make music stop and life variable decrease -1, if the user doesn't push any buttons for 3 minutes. But if the user pushes the right button, life variable will be increased + 1. but I don't know how to get null input from the user for 3 minutes.
If I use while for this program, this shuts down… until life is below 0, I want to repeat music which is played on irregular time.
Edit: Don't use Thread in Unity
How Unity works
Alternative to Thread
Couroutine Example 1
Coroutine Example 2
* To put it simple, Thread.Sleep hangs to Unity and Unity can't operate for the time, and that's why it looks like running slow.
You can use coroutines for this problem.
void Start()
{
StartCoroutine("RoutineCheckInputAfter3Minutes");
}
IEnumerator RoutineCheckInputAfter3Minutes()
{
yield return new WaitForSeconds(3f*60f);
gm.life -= 1;
}
void RightButtonClicked()
{
gm.life += 1;
StopCoroutine("RoutineCheckInputAfter3Minutes");
StartCoroutine("RoutineCheckInputAfter3Minutes");
}
Or, you can just turn your a function into a coroutine, if the other code sections work.
void Start()
{
StartCoroutine(a());
}
public IEnumerator a()
{
while (gm.life >= 0)
{
System.Random ran = new System.Random();
int timeToWait = ran.Next(1, 50) * 1000;
yield return new WaitForSeconds(timeToWait);
source = this.gameObject.AddComponent<AudioSource>();
source.clip = sound;
source.loop = true;
source.Play();
System.Random r = new System.Random();
result = r.Next(1, 4);
Debug.Log("d");
}
}
This is an example usage of coroutine based on your code More than this is out of scope:
A pastebin link to code
Now I am reading a book C # Programming for the Absolute Beginner
In Chapter 7, Section workouts, which put it.My question is that
The Interval property of a timer is specified in milliseconds, not ticks.
Now, how can I change the value of a variable(dy) based on each tick
Modify the difficulty level of the Lunar Lander game. There are several ways you could
tweak the code. Perhaps you could change gravity by modifying the change in dy during
each tick of the timer. You could also adjust how much dx and dy change during each key
press or how fast time progresses by modifying the timer’s interval. Another easy change
would be to modify the size of the landing pad or the lander.
public partial class theForm : Form
{
private double x, y; //will show new position of lander
private double dx, dy; //diffrence in x and y
private int fuel = 100; //how much fuel is left
private int ships = 3; // number of ships player has
private int score = 0; //the player's current score
private int level = 1;
public theForm()
{
InitializeComponent();
initGame();
}
private void timer1_Tick(object sender, EventArgs e)
{
//account for gravity
dy += 0.5;
//increment score for being alive
score += 100;
//show ordinary (no flames) lander
picLander.Image = myPics.Images[0];
//call helper methods to handle details
moveShip();
checkLanding();
showStats();
}//end timer tick
private void showStats()
{
//display the statistics
lblDx.Text = "dx: " + dx;
lblDy.Text = "dy: " + dy;
lblFuel.Text = "fuel: " + fuel;
lblShips.Text = "ships: " + ships;
lblScore.Text = "score: " + score;
}//end showStats
private void checkLanding()
{
//get rectangle from the objects
Rectangle rLander = picLander.Bounds;
Rectangle rPlatform = picPlatform.Bounds;
//look for an interesection
if (rLander.IntersectsWith(rPlatform))
{
//it's either a crash or a landing
//turn off the timer for a moment
timer1.Enabled = false;
if (Math.Abs(dx) < 3)
{
//horizontal speed ok
if (Math.Abs(dy) < 5)
{
//vertical speed ok
if (Math.Abs(rLander.Bottom - rPlatform.Top) < 3)
{
//landing on top of platform
MessageBox.Show("Good Landing!");
lblLevel.Text=Convert.ToString(level++);
fuel += 30;
score += 1000;
}
else
{
//not on top of platform
MessageBox.Show("You have to land on top.");
killShip();
}//end vertical if
}
else
{
//dy too large
MessageBox.Show("Too much vertical velocity!");
killShip();
} // end vertical if
}
else
{
//dx too large
MessageBox.Show("too much horizontal velocity");
killShip();
}//end horiz if
//reset the lander
initGame();
}//end if
}//end checkLanding
private void initGame()
{
//re-initializes the game
Random roller = new Random();
int platX, platY;
//find random dx,dy values for lander
dx = Convert.ToDouble(roller.Next(5) - 2);
dy = Convert.ToDouble(roller.Next(5) - 2);
//place lander randomly on form
x = Convert.ToDouble(roller.Next(this.ClientSize.Width));
y = Convert.ToDouble(roller.Next(this.ClientSize.Height));
//place platform randomly on form (but make sure it appears)
platX = roller.Next(this.ClientSize.Width - picPlatform.Width);
platY = roller.Next(this.ClientSize.Height - picPlatform.Height);
picPlatform.Location = new Point(platX, platY);
//turn on timer
timer1.Enabled = true;
}//end initGame
private void killShip()
{
//kill off a ship,check for end of game
DialogResult answer;
ships--;
if (ships <= 0)
{
//game is over
answer = MessageBox.Show("Play Again?", "Game Over", MessageBoxButtons.YesNo);
if (answer == DialogResult.Yes)
{
ships = 3;
fuel = 100;
initGame();
}
else
{
Application.Exit();
}//end if
}//end 'no ships' if
}//end killShip
private void theForm_KeyDown(object sender, KeyEventArgs e)
{
fuel--;
//check to see if user is out of gas
if (fuel < 0)
{
timer1.Enabled = false;
MessageBox.Show("Out of Fuel!!!");
fuel += 20;
killShip();
initGame();
}//end if
//look for arrow keys
switch (e.KeyData)
{
case Keys.Up:
picLander.Image = myPics.Images[1];
dy -= 2;
break;
case Keys.Left:
picLander.Image = myPics.Images[2];
dx++;
break;
case Keys.Right:
picLander.Image = myPics.Images[3];
dx--;
break;
default:
//do nothing
break;
}//end switch
if(e.KeyCode==Keys.Up && level==2)
{
dy -= 3;
}else if(e.KeyCode == Keys.Left && level== 2)
{
dx += 2;
}else if(e.KeyCode == Keys.Right && level == 2)
{
dx -= 2;
}
}//end keydown
private void moveShip()
{
//change x and check for boundaries
x += dx;
if (x > this.Width - picLander.Width)
{
x = 0;
}
if (x < 0)
{
x = Convert.ToDouble(this.Width - picLander.Width);
}//end if
//change y and check for boundaries
y += dy;
if (y < 0)
{
y = Convert.ToDouble(this.Height - picLander.Height);
}//end if
if (y > this.Height - picLander.Height)
{
y = 0;
}//end if
//move picLander to new location
picLander.Location = new Point(Convert.ToInt32(x), Convert.ToInt32(y));
}//end MoveShip
private void theForm_Load(object sender, EventArgs e)
{
}
}
You can use the 'Tick' event of the timer.
public Form1()
{
InitializeComponent();
Timer timer = new Timer();
timer.Tick += Timer_Tick;
}
private void Timer_Tick(object sender, EventArgs e)
{
//Your code goes here
}
I created a modified Pacman, but I want to add a firebolt shooting out from the mouth of the Pacman. My code is:
namespace TestingPacman
{
class Firebolt
{
Bitmap firebolt0 = null;
Bitmap firebolt1 = null;
public Point fireboltposition;
int fireboltwidth = 0;
int fireboltheight = 0;
public Firebolt(int x, int y)
{
fireboltposition.X = x;
fireboltposition.Y = y;
if (firebolt0 == null)
firebolt0 = new Bitmap("firebolt0.gif");
if (firebolt1 == null)
firebolt1 = new Bitmap("firebolt1.gif");
int fireboltwidth = firebolt0.Width;
int fireboltheight = firebolt0.Height;
}
public Rectangle GetFrame()
{
Rectangle Labelrec = new Rectangle(fireboltposition.X, fireboltposition.Y, fireboltwidth, fireboltheight);
return Labelrec;
}
public void Draw(Graphics g)
{
Rectangle fireboltdecR = new Rectangle(fireboltposition.X, fireboltposition.Y, fireboltwidth, fireboltheight);
Rectangle fireboltsecR = new Rectangle(0, 0, fireboltwidth, fireboltheight);
g.DrawImage(firebolt0, fireboltdecR, fireboltsecR, GraphicsUnit.Pixel);
}
}
How can I make a firebolt move in the direction the pacman is facing?
I have a form1 that when I press "F" it will fire a firebolt
but it cant seem to produce the firebolt image. Why is that?
namespace TestingPacman
{
public partial class Form1 : Form
{
// int inc = 0;
Eater TheEater = new Eater(100,100);
TimeDisplay time = new TimeDisplay();
int sec = 0;
Score score = new Score();
int countofeaten=0;
Random r = new Random();
private List<Label> redlabels = new List<Label>();
private List<Label> bluelabels = new List<Label>();
Firebolt firebolt;
List<Firebolt> listfirebolt = new List<Firebolt>();
private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
g.FillRectangle(Brushes.White, 0, 0, this.ClientRectangle.Width, ClientRectangle.Height);
TheEater.Draw(g);
foreach(Firebolt f in listfirebolt)
f.Draw(g);
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
timer1.Enabled = true;
string result = e.KeyData.ToString();
Invalidate(TheEater.GetFrame());
switch (result)
{
case "D1":
if (TheEater.eaterwidth >= 9 && TheEater.eaterheight >= 9)
{
TheEater.eaterwidth++;
TheEater.eaterheight++;
}
break;
case "F":
listfirebolt.Add(firebolt = new Firebolt(TheEater.Position.X, TheEater.Position.Y));
Invalidate(firebolt.GetFrame());
break;
case "D2":
if (TheEater.eaterwidth > 10 && TheEater.eaterheight > 10)
{
TheEater.eaterwidth--;
TheEater.eaterheight--;
}
break;
case "D9": TheEater.inc=TheEater.inc+2;
break;
case "D0": TheEater.inc=TheEater.inc-2;
break;
case "Left":
TheEater.MoveLeft(ClientRectangle);
Invalidate(TheEater.GetFrame());
break;
case "Right":
TheEater.MoveRight(ClientRectangle);
Invalidate(TheEater.GetFrame());
break;
case "Up":
TheEater.MoveUp(ClientRectangle);
Invalidate(TheEater.GetFrame());
break;
case "Down":
TheEater.MoveDown(ClientRectangle);
Invalidate(TheEater.GetFrame());
break;
default:
break;
}
RemoveifIntersected();
}
label2.Text = score.Iskore.ToString();
}
private void timer1_Tick(object sender, EventArgs e)
{
label1.Text = time.FormatTime(sec++);
}
}
}
Jeo, what you are missing in your code is the concept of "Time" as far as I can tell your game only reacts when you press keys. What you really need is a mechanism to pass time in your game. This is almost always done in games with repetitive calls to something called "A Game Loop". Here's a quick example of a game loop that might work for you
class Mob
{
float XPos;
float YPos;
float XVel;
float YVel;
}
List<Mob> EveryThingMovable = new List<Mob>();
void GameLoop() //This loop is called 30 times every second... use a timer or whatever, there are far more sophisticated models, but for a first attaempt at a game it's easiest.
{
MoveEverybody(); //make a function that moves everything that can move
//Later you will have to add collision detection to stop pacman from moving through walls
CollideFireballs(); //Check if a fireball hits the bad guys
//More game stuff...
}
void MoveEverybody()
{
foreach(Mob dude in EverythingMovable)
{
ifDoesntHitWall(dude)
{
dude.XPos += dude.XVel;
dude.YPos += dude.YVel;
}
}
}
anyways, read up on the idea of a Game Loop, I think it's the biggest hurtle you haven't passed in order to move ahead.