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.
Related
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;
}
}
});
}
Hi I successfully made a program that moves a picture box by pressing keys, but the movement of the picture box isn't smooth and there is lag when you first start moving the picture box.
Here is my code
namespace Imagebox_test1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.KeyPreview = true;
this.KeyDown += Form1_KeyDown;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
int x = pictureBox1.Location.X;
int y = pictureBox1.Location.Y;
bool player_left;
bool player_right;
player_left = false;
player_right = false;
int move_speed;
move_speed = 10;
switch (e.KeyCode)
{
case Keys.A:
player_right = false;
player_left = true;
break;
case Keys.D:
player_right = true;
break;
}
if (player_left == true) x -= move_speed;
if (player_right == true) x += move_speed;
pictureBox1.Location = new Point(x, y);
}
}
}
How can I get rid of this lag and make the movement smoother?
Help much appreciated.
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();
For a school project I need to make a small game where multiple Ellipses move.
The last one that gets made with my method to make multiple at the same time moves with the timer I make.
How do you make one timer for all the Ellipses.
class EnemyTeam
{
private Ellipse enemy;
private Canvas canvas;
private double xChange = 50, yChange = 50;
public DispatcherTimer enemyTimer;
private char direction = '0';
private Thickness enemyThickness;
public EnemyTeam(Canvas canvas, double startPosition, SolidColorBrush playerBrush)
{
this.canvas = canvas;
DrawTeam(canvas, 40, playerBrush);
enemyTimer.Interval = TimeSpan.FromMilliseconds(100);
enemyTimer.Start();
}
private void DrawBall(SolidColorBrush brush, Canvas canvas,double x,double y)
{
enemy = new Ellipse();
enemy.Stroke = brush;
enemy.Fill = brush;
enemy.Height = 30;
enemy.Width = 30;
enemy.Margin = new Thickness(x,y, 0, 0);
enemyTimer = new DispatcherTimer();
enemyThickness = enemy.Margin;
canvas.Children.Add(enemy);
enemyTimer.Tick += enemyTimer_Tick;
}
void enemyTimer_Tick(object sender, EventArgs e)
{
if (enemyThickness.Left >= canvas.Width - 100)
{
GoDown();
direction = '1';
}
if (enemyThickness.Left <= 0 + 20)
{
GoDown();
direction = '0';
}
MoveTeam(enemy);
}
private void MoveTeam(Ellipse enemy)
{
enemyThickness = enemy.Margin;
if (direction == '1')
{
enemyThickness.Left -= xChange;
}
if (direction == '0')
{
enemyThickness.Left += xChange;
}
enemy.Margin = enemyThickness;
}
private void GoDown()
{
enemyThickness.Top += yChange;
enemy.Margin = enemyThickness;
}
}
Instead of initializing and assigning event handler in DrawBall method, do that in constructor of EnemyTeam class. This is will give you on timer per EnemyTeam object.
Declare enemyTimer as a static field:
class EnemyTeam
{
private static enemyTimer = new DispatcherTimer();
...
The keyword static will make the field shared for the class.
You're making multiple timers and throwing them away. See this line:
enemyTimer = new DispatcherTimer();
Every time you call that, you're making a new timer and throwing away the previous copy that enemyTimer held a reference to. Because enemyTimer.Start() is called after DrawTeam, it's called only on the last-created timer. None of the other timers get started.
But even if the other timers got started, you'd still only see one Ellipse move, because in enemyTimer_Tick you only ever make changes to enemy, which is a class member variable that points to the last Ellipse created.
I would suggest that you only use one timer, that you save all the Ellipses you create in a list for later use, and that in enemyTimer_Tick you update all of those Ellipses by iterating through the list.
EDIT: Here is a copy of your code, reworked a bit to show you what I mean. I don't really understand what you're trying to do with MoveTeam and the enemyThickness variable, so I didn't mess with that stuff. That is to say, this isn't a complete working solution, just an example of the changes I'm suggesting.
using System.Collections.Generic;
class EnemyTeam
{
private List<Ellipse> enemies = new List<Ellipse>();
private Canvas canvas;
private double xChange = 50, yChange = 50;
public DispatcherTimer enemyTimer;
private char direction = '0';
private Thickness enemyThickness;
public EnemyTeam(Canvas canvas, double startPosition, SolidColorBrush playerBrush)
{
this.canvas = canvas;
DrawTeam(canvas, 40, playerBrush);
enemyTimer = new DispatcherTimer();
enemyTimer.Interval = TimeSpan.FromMilliseconds(100);
enemyTimer.Tick += enemyTimer_Tick;
enemyTimer.Start();
}
private void DrawBall(SolidColorBrush brush, Canvas canvas,double x,double y)
{
enemy = new Ellipse();
enemy.Stroke = brush;
enemy.Fill = brush;
enemy.Height = 30;
enemy.Width = 30;
enemy.Margin = new Thickness(x,y, 0, 0);
enemyThickness = enemy.Margin; // what is this supposed to do?
canvas.Children.Add(enemy);
enemies.Add(enemy);
}
void enemyTimer_Tick(object sender, EventArgs e)
{
foreach (Ellipse enemy in enemies)
{
if (enemyThickness.Left >= canvas.Width - 100)
{
GoDown();
direction = '1';
}
if (enemyThickness.Left <= 0 + 20)
{
GoDown();
direction = '0';
}
MoveTeam(enemy);
}
}
private void MoveTeam(Ellipse enemy)
{
enemyThickness = enemy.Margin;
if (direction == '1')
{
enemyThickness.Left -= xChange;
}
if (direction == '0')
{
enemyThickness.Left += xChange;
}
enemy.Margin = enemyThickness;
}
private void GoDown()
{
enemyThickness.Top += yChange;
enemy.Margin = enemyThickness;
}
}
Basically, i have an endless number of blocks (each built from class "Enemy") being create, stored into a list, and sent animated across the screen. It does this forever. I want to delete the first block after 100 blocks have been created so as not to use too much processing power. Any ideas?
THIS IS THE CODE FOR THE WHOLE CLASS FOR WHICH THE OBJECTS I WANT TO DELETE:
namespace MovementTestV1
{
class Enemy
{
protected Dispatcher dispatcher;
protected Canvas Background;
protected Label Display;
Int32 waitTime;
double EnemyWidth = 53;
Image EnemyImage;
String FilePathImage;
BitmapImage bitPic;
protected double x, y;
System.Windows.Forms.Timer tmr;
double incrementSize = 5.0;
private int i = 0;
public Enemy(Canvas Background, Dispatcher dispatcher, Dictionary<String, String> keys,Label Display, Int32 waitTime = 100)
{
this.Background = Background;
this.dispatcher = dispatcher;
this.waitTime = 70;
//this.keys = keys;
this.Display = Display;
EnemyImage = new Image();
EnemyImage.Width = EnemyWidth;
FilePathImage = #"RedSqare.png";
bitPic = LoadBitmap(FilePathImage, EnemyWidth);
//tmr = new System.Windows.Forms.Timer();
//tmr.Interval = this.waitTime;
//tmr.Tick += new EventHandler(Position);
//tmr.Start();
}
protected BitmapImage LoadBitmap(String assetsRelativePath, double decodeWidth)
{
BitmapImage theBitmap = new BitmapImage();
theBitmap.BeginInit();
String basePath = System.IO.Path.Combine(Environment.CurrentDirectory, #"assets\");
String path = System.IO.Path.Combine(basePath, assetsRelativePath);
theBitmap.UriSource = new Uri(path, UriKind.Absolute);
theBitmap.DecodePixelWidth = (int)decodeWidth;
theBitmap.EndInit();
return theBitmap;
}
public void Place(double x, double y)
{
EnemyImage.Source = bitPic;
this.x = x;
this.y = y;
Background.Children.Add(EnemyImage);
EnemyImage.SetValue(Canvas.LeftProperty, x);
EnemyImage.SetValue(Canvas.TopProperty, y);
tmr = new System.Windows.Forms.Timer();
tmr.Interval = 10;
tmr.Tick += new EventHandler(Position);
tmr.Start();
}
public void Position(object sender, System.EventArgs e)
{
i++;
if (i < 9000)
{
x -= incrementSize *.3;
}
UpdatePosition();
}
void UpdatePosition()
{
EnemyImage.SetValue(Canvas.LeftProperty, x);
EnemyImage.SetValue(Canvas.TopProperty, y);
}
public double X
{
get
{
return x;
}
set
{
x = value;
}
}
public double Y
{
get
{
return y;
}
set
{
y = value;
}
}
public void Shutdown()
{
tmr.Stop();
}
}
}
public void spawn(object sender, System.EventArgs e)
{
Int32 place = random.Next(1, 4);
Enemy enemy;
i += 2;
if (i % 46 == 0)
{
Int32 Ycoord = random.Next(0, 700);
switch (place)
{
case 1:
enemy = new Enemy(Background, dispatcher, keys, Display, 10);
enemy.Place(1080, Ycoord);
break;
case 2:
enemy = new Enemy(Background, dispatcher, keys, Display, 10);
enemy.Place(1080, Ycoord);
break;
default:
enemy = new Enemy(Background, dispatcher, keys, Display, 10);
enemy.Place(1080, Ycoord);
break;
}
enemies.Add(enemy);
}
if (enemies.Count > 5)
{
//THIS PART DOESNT WORK!!!!!
enemies.RemoveAt(0);
//enemies[1] = 0;
////enemies[2] = null;
//enemies[2].Shutdown();
////enemies[3] = null;
//enemies[3].Shutdown();
////enemies[4] = null;
//enemies[4].Shutdown();
}
}
Hard to say without any code to work off of... However, you could just check to see if your list has over 100 blocks, then setting your first blocks to null. C# has a garbage collector that will clean up the mess.
Edit: or use the Remove method stated above.
for ( int i = 0; i < enemies.size(); ++i )
{
if ( enemies.Count > 5 )
{
enemies.Remove(i);
}
}