I am trying to make a slider puzzle game and I keep getting the error "NullReferenceException was unhandled" when I call myBoard.paint(e.Graphics) in my form1. Please help me!!!
Here is my code for Form1 (Let me know if I need to post some of my other classes code):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
namespace SliderPuzzle
{
public partial class Form1 : Form
{
private int tileSize;
private int rowsCols;
private SlidePuzzle myBoard;
private Stopwatch timer;
private int moveCount;
public Form1()
{
InitializeComponent();
pictureBox1.TabIndex = 3;
pictureBox1.Size = new Size(100, 50);
pictureBox1.Location = new Point(16, 71);
pictureBox1.BackColor = Color.PaleGreen;
pictureBox1.BorderStyle = BorderStyle.Fixed3D;
pictureBox1.TabStop = false;
tileSize = imageList1.ImageSize.Width;
rowsCols = 3;
pictureBox1.Width = rowsCols * tileSize;
pictureBox1.Height = rowsCols * tileSize;
}
public void initGame()
{
myBoard = new SlidePuzzle(rowsCols, tileSize, imageList1);
timer = new Stopwatch();
moveCount = 0;
timer.Start();
}
private void Form1_Load(object sender, EventArgs e)
{
initGame();
}
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
this.myBoard.paint(e.Graphics);
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (myBoard.move(e.Y / tileSize, e.X / tileSize))
++moveCount;
Refresh();
if (!myBoard.winner())
return;
timer.Stop();
if (MessageBox.Show(string.Format("You won!!\nIt took you {0} moves and {1:F2} seconds.\nPlay again?", (object)moveCount, (object)timer.Elapsed.TotalSeconds), "Game Over", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.No)
{
Close();
}
else
{
initGame();
Refresh();
}
}
}
}
Update #1: Okay, so I moved myBoard = new SlidePuzzle(rowsCols, tileSize, imageList1); to my constructor, but now none of the images are showing up on it. Here is what It looks like vs what it is supposed to look like:
Edit #2: Okay, I moved it back to where it was before and put
if (this.myBoard != null)
this.myBoard.paint(e.Graphics);
instead, and it works a little better and looks better as well. But the images not showing up is still a problem.
Edit #3: Here is the SliderPuzzle.Paint Code:
public void paint(Graphics g)
{
for (int r = 0; r < this.myGrid.getNumRows(); ++r)
{
for (int c = 0; c < this.myGrid.getNumCols(); ++c)
this.myGrid.get(new Location(r, c)).paint(g);
}
}
Edit #4: Here is the code for the SliderPuzzle Class:
using System;
using System.Drawing;
using System.Windows.Forms;
namespace SliderPuzzle
{
internal class SlidePuzzle
{
private static Random rand = new Random();
private int myTileSize;
private BoundedGrid myGrid;
private ImageList myImages;
private Location myBlankLoc;
static SlidePuzzle()
{
}
public SlidePuzzle(int rowsCols, int tileSize, ImageList images)
{
this.myTileSize = tileSize;
this.myGrid = new BoundedGrid(rowsCols, rowsCols);
this.myImages = images;
this.myBlankLoc = new Location(rowsCols - 1, rowsCols - 1);
this.initBoard();
}
private void initBoard()
{
int index1 = 0;
for (int r = 0; r < this.myGrid.getNumRows(); ++r)
{
for (int c = 0; c < this.myGrid.getNumCols(); ++c)
{
this.myGrid.put(new Location(r, c), new Tile(index1, this.myTileSize, new Location(r, c), this.myImages.Images[index1]));
++index1;
}
}
for (int index2 = 0; index2 < 1000; ++index2)
{
Location adjacentLocation = this.myBlankLoc.getAdjacentLocation(SlidePuzzle.rand.Next(4) * 90);
if (this.myGrid.isValid(adjacentLocation))
{
this.swap(this.myBlankLoc, adjacentLocation);
this.myBlankLoc = adjacentLocation;
}
}
}
public bool move(int row, int col)
{
Location loc1 = new Location(row, col);
if (Math.Abs(this.myBlankLoc.getRow() - row) + Math.Abs(this.myBlankLoc.getCol() - col) != 1)
return false;
this.swap(loc1, this.myBlankLoc);
this.myBlankLoc = loc1;
return true;
}
public bool winner()
{
int num = 0;
for (int r = 0; r < this.myGrid.getNumRows(); ++r)
{
for (int c = 0; c < this.myGrid.getNumCols(); ++c)
{
if (this.myGrid.get(new Location(r, c)).getValue() != num)
return false;
++num;
}
}
return true;
}
private void swap(Location loc1, Location loc2)
{
Tile tile1 = this.myGrid.put(loc2, this.myGrid.get(loc1));
Tile tile2 = this.myGrid.put(loc1, tile1);
tile1.setLocation(loc1);
tile2.setLocation(loc2);
}
public void paint(Graphics g)
{
for (int r = 0; r < this.myGrid.getNumRows(); ++r)
{
for (int c = 0; c < this.myGrid.getNumCols(); ++c)
this.myGrid.get(new Location(r, c)).paint(g);
}
}
}
}
Update #5: Here is the Tile Class:
using System.Drawing;
namespace SliderPuzzle
{
internal class Tile
{
private int myValue;
private int mySize;
private Location myLoc;
private Image myImage;
public Tile(int value, int tileSize, Location loc, Image img)
{
this.myValue = value;
this.mySize = tileSize;
this.myLoc = loc;
this.myImage = img;
}
public int getValue()
{
return this.myValue;
}
public void setLocation(Location newLoc)
{
this.myLoc = newLoc;
}
public void paint(Graphics g)
{
g.DrawImage(this.myImage, this.myLoc.getCol() * this.mySize, this.myLoc.getRow() * this.mySize);
}
}
}
Edit #6: Here is the Location Class:
namespace SliderPuzzle
{
internal class Location
{
public const int LEFT = -90;
public const int RIGHT = 90;
public const int HALF_LEFT = -45;
public const int HALF_RIGHT = 45;
public const int FULL_CIRCLE = 360;
public const int HALF_CIRCLE = 180;
public const int AHEAD = 0;
public const int NORTH = 0;
public const int NORTHEAST = 45;
public const int EAST = 90;
public const int SOUTHEAST = 135;
public const int SOUTH = 180;
public const int SOUTHWEST = 225;
public const int WEST = 270;
public const int NORTHWEST = 315;
private int row;
private int col;
public Location(int r, int c)
{
this.row = r;
this.col = c;
}
public int getRow()
{
return this.row;
}
public int getCol()
{
return this.col;
}
public Location getAdjacentLocation(int direction)
{
int num1 = (direction + 22) % 360;
if (num1 < 0)
num1 += 360;
int num2 = num1 / 45 * 45;
int num3 = 0;
int num4 = 0;
if (num2 == 90)
num3 = 1;
else if (num2 == 135)
{
num3 = 1;
num4 = 1;
}
else if (num2 == 180)
num4 = 1;
else if (num2 == 225)
{
num3 = -1;
num4 = 1;
}
else if (num2 == 270)
num3 = -1;
else if (num2 == 315)
{
num3 = -1;
num4 = -1;
}
else if (num2 == 0)
num4 = -1;
else if (num2 == 45)
{
num3 = 1;
num4 = -1;
}
return new Location(this.getRow() + num4, this.getCol() + num3);
}
public bool equals(Location other)
{
if (this.getRow() == other.getRow())
return this.getCol() == other.getCol();
else
return false;
}
public int hashCode()
{
return this.getRow() * 3737 + this.getCol();
}
public int compareTo(Location otherLoc)
{
if (this.getRow() < otherLoc.getRow())
return -1;
if (this.getRow() > otherLoc.getRow())
return 1;
if (this.getCol() < otherLoc.getCol())
return -1;
return this.getCol() > otherLoc.getCol() ? 1 : 0;
}
public string toString()
{
return "(" + (object)this.getRow() + ", " + (string)(object)this.getCol() + ")";
}
}
}
Edit #7: Here is the last class, the BoundedGrid Class:
using System;
using System.Collections.Generic;
namespace SliderPuzzle
{
internal class BoundedGrid
{
private Tile[,] occupantArray;
public BoundedGrid(int rows, int cols)
{
this.occupantArray = new Tile[rows, cols];
}
public int getNumRows()
{
return this.occupantArray.GetLength(0);
}
public int getNumCols()
{
return this.occupantArray.GetLength(1);
}
public bool isValid(Location loc)
{
if (0 <= loc.getRow() && loc.getRow() < this.getNumRows() && 0 <= loc.getCol())
return loc.getCol() < this.getNumCols();
else
return false;
}
public List<Location> getOccupiedLocations()
{
List<Location> list = new List<Location>();
for (int r = 0; r < this.getNumRows(); ++r)
{
for (int c = 0; c < this.getNumCols(); ++c)
{
Location loc = new Location(r, c);
if (this.get(loc) != null)
list.Add(loc);
}
}
return list;
}
public Tile get(Location loc)
{
if (!this.isValid(loc))
throw new Exception("Location " + (object)loc + " is not valid");
else
return this.occupantArray[loc.getRow(), loc.getCol()];
}
public Tile put(Location loc, Tile obj)
{
if (!this.isValid(loc))
throw new Exception("Location " + (object)loc + " is not valid");
if (obj == null)
throw new NullReferenceException("obj == null");
Tile tile = this.get(loc);
this.occupantArray[loc.getRow(), loc.getCol()] = obj;
return tile;
}
public Tile remove(Location loc)
{
if (!this.isValid(loc))
throw new Exception("Location " + (object)loc + " is not valid");
Tile tile = this.get(loc);
this.occupantArray[loc.getRow(), loc.getCol()] = (Tile)null;
return tile;
}
}
}
Edit #8: When I click on the picturebox, the program crashes and it says the the timer.Stop(); in form1 gives me a NullReferenceException!!!
Edit #9: Okay, THAT worked... I have found that the images still do not show up, but I think that they are never being placed on the grid. When I click on the grid ( still has no images) It says that I have won. This should only display after I move the tiles into the correct order. Any idea what is going on?
Edit #10: My program finally works now! It turns out I had something missplaced in the constructor of form1, now everything works! The images show up and everything! How cool is that!!!
THANK YOU EVERYONE FOR YOU CONTRIBUTIONS, I WILL NOW GET A GREAT GRADE ON MY SCHOOL PROJECT!
This is one of those problems that will give you headaches. Trying to nail down the exact sequence of events is fine, when you can guarantee that the events are never going to be invoked out of sequence. Unfortunately the Paint event is one that gets fired at all sorts of odd times, any may be fired even before the Load event.
The only real answer is to never rely on events being fired in a particular sequence. Always check that your myBoard object is valid before trying to paint it:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if (this.myBoard != null)
this.myBoard.paint(e.Graphics);
}
And yes, as others have noted, it is better to create all of your objects as soon as possible - in the constructor for instance, which is what a constructor is for after all. Even then, you can still get events being fired by actions in the constructor that will ruin your whole day. Your even handlers should be set as late as possible in the constructor code to account for this.
Rule(s) of thumb:
if you're creating custom objects that will be used in event handlers, always try to create and initialize them prior to calling InitializeComponent in the constructor.
Wire up your event handlers as late as possible, especially for things like Paint - it won't be useful before your constructor is done, so do it last in the constructor.
Your actual Form1_Load event never gets called (the one where you are initializing your board).
Add this code at the end of the Form1 constructor this.Load +=Form1_Load;
Your pictureBox1.Paint event is raised before your Form1.Load event. Move
myBoard = new SlidePuzzle(rowsCols, tileSize, imageList1);
to your constructor and you should be fine.
Related
I am so confessed right now I don't even know how to properly form this question.
I have some code (as shown below) that is run on a different thread with the variable i not being referenced anywhere else that could interfere with it here. I just don't understand what is happening to cause this error, I put some watchers down with visual studio code and the values all seem to be fine and in range but almost randomly out of nowhere I will get this error.
Is it possible that this is caused by another section of code despite to my best knowledge being completely isolated from it? I even went as far to rename all other uses of i to different letters and I still get this problem.
Is it just something with for loops?
Am I somehow modifying i without even know it?
I just don't even know what to ask.
Here is the full code
`
using SFML.Graphics;
using SFML.Window;
using System.Diagnostics;
using System.Numerics;
namespace RenderEngine
{
public class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
PhysicsEngine re = new PhysicsEngine();
for (int i = 0; i < 100; i++)
{
Debug.WriteLine(i);
}
}
}
public class PhysicsEngine
{
Solver solver = new Solver();
public void RenderEngine2()
{
ContextSettings settings = new ContextSettings();
settings.AntialiasingLevel = 8;
RenderWindow window = new RenderWindow(new VideoMode(2000, 1000), "Poop", Styles.Default, settings);
SFML.Graphics.Color color = new SFML.Graphics.Color(0, 0, 0, 0);
window.SetVerticalSyncEnabled(true);
CircleShape shape = new CircleShape(5);
shape.FillColor = new SFML.Graphics.Color(0, 0, 255, 255);
window.Closed += handelclose;
int drawcount = 0;
while (window.IsOpen)
{
window.Clear(color);
window.DispatchEvents();
try
{
foreach (Partical partical in solver.Particals)
{
shape.Position = new SFML.System.Vector2f((partical.position.X), (partical.position.Y));
window.Draw(shape);
drawcount++;
}
drawcount = 0;
}
catch
{
Debug.WriteLine("notready yet");
}
window.Display();
}
void handelclose(object sender, EventArgs e)
{
window.Close();
Environment.Exit(Environment.ExitCode);
}
}
List<Partical> todraw = new List<Partical>();
void EngineLoop()
{
while (true)
{
foreach (Partical partical in solver.Particals)
{
int x = (int)Math.Round(partical.position.X/10);
int y = (int)Math.Round(partical.position.Y/10);
List<int> ts = solver.Grid[x, y];
if (ts != null)
{
for (int brokenint = 0; brokenint < ts.Count; brokenint++)
{
Debug.WriteLine(partical.ID);
Debug.WriteLine(ts[brokenint]);
if (partical.ID != ts[brokenint])
{
Vector2 pos = new Vector2(partical.ID, ts[brokenint]);
if (solver.Collision.Count > 0)
{
if (!solver.Collision.Contains(pos))
solver.Collision.Add(pos);
}
else
{
solver.Collision.Add(pos);
}
}
}
}
}
}
}
private int particalcount = 10;
bool canstart = false;
public PhysicsEngine()
{
Parallel.Invoke(() =>
{
while (!canstart) { Thread.Sleep(100); }
Debug.WriteLine("third thread");
RenderEngine2();
},
() =>
{
while (!canstart) { Thread.Sleep(100); }
Debug.WriteLine("engine started");
EngineLoop();
},
() =>
{
Debug.WriteLine("first thread");
PhysicsLoop(this);
}
);
}
void PhysicsLoop(PhysicsEngine PhyEng)
{
int frames = 0;
long second = 0;
PhysicsStart(PhyEng);
Thread.Sleep(1000);
Stopwatch sw = Stopwatch.StartNew();
solver.startupdate();
while (true)
{
sw.Start();
todraw = solver.Particals;
solver.update();
frames++;
if (second != (Stopwatch.GetTimestamp() / Stopwatch.Frequency))
{
second = (Stopwatch.GetTimestamp() / Stopwatch.Frequency);
Debug.WriteLine(frames);
frames = 0;
}
sw.Stop();
sw.Reset();
if (sw.ElapsedMilliseconds < 15)
Thread.Sleep(15 - (int)sw.ElapsedMilliseconds);
}
}
void PhysicsStart(PhysicsEngine phyeng)
{
for (int i = 0; i < 210; i++)
{
for (int j = 0; j < 110; j++)
{
solver.Grid[i,j] = new List<int>();
}
}
Random rand = new Random();
for (int i = 0; i < particalcount; i++)
{
Partical partical = new Partical();
partical.position = new Vector2(rand.Next(0, 2000), rand.Next(0, 1000));
partical.oldposition = partical.position;
partical.ID = i;
int x1 = (int)Math.Round((partical.position.X + 5) / 10);
int y1 = (int)Math.Round((partical.position.Y + 5) / 10);
int x2 = (int)Math.Round((partical.position.X - 5) / 10);
int y2 = (int)Math.Round((partical.position.Y - 5) / 10);
solver.Grid[x1, y1].Add(partical.ID);
solver.Grid[x2, y1].Add(partical.ID);
solver.Grid[x1, y2].Add(partical.ID);
solver.Grid[x2, y2].Add(partical.ID);
solver.Particals.Add(partical);
}
canstart = true;
}
}
public class Partical
{
public Vector2 position = new Vector2(0, 0);
public Vector2 oldposition = new Vector2(0, 0);
public Vector2 acceleration = new Vector2(0, 0);
Vector2 zero = new Vector2(0, 0);
public int ID = new int();
public void updatePosition(float sub)
{
Vector2 velocity = position - oldposition;
oldposition = position;
position = position + (velocity * 0.9f) + acceleration * sub;
acceleration = zero;
}
public void accelerate(Vector2 accel)
{
acceleration = acceleration + accel;
}
}
public class Solver
{
public List<Partical> Particals = new List<Partical>();
public List<Vector2> Collision = new List<Vector2>();
public List<int>[,] Grid = new List<int>[2100,1100];
public void update()
{
int subcount = 8;
float sub = 1f / (float)subcount;
for (int i = 0; i < subcount; i++)
{
applyGravity(sub);
updatePositions(sub);
for (int j = 0; j < Collision.Count; j++)
{
solvecolisions((int)Collision[j].X, (int)Collision[j].Y);
}
Collision.Clear();
}
}
public void startupdate()
{
applyGravity(0.5f);
updatePositions(0.5f);
applyGravity(0.5f);
updatePositions(0.5f);
}
void updatePositions(float sub)
{
foreach (Partical partical in Particals)
{
partical.updatePosition(sub);
int x1 = (int)Math.Round((partical.oldposition.X + 5) / 10);
int y1 = (int)Math.Round((partical.oldposition.Y + 5) / 10);
int x2 = (int)Math.Round((partical.oldposition.X - 5) / 10);
int y2 = (int)Math.Round((partical.oldposition.Y - 5) / 10);
Grid[x1,y1].Remove(partical.ID);
Grid[x2,y1].Remove(partical.ID);
Grid[x1,y2].Remove(partical.ID);
Grid[x2,y2].Remove(partical.ID);
x1 = (int)Math.Round((partical.position.X + 5) / 10);
y1 = (int)Math.Round((partical.position.Y + 5) / 10);
x2 = (int)Math.Round((partical.position.X - 5) / 10);
y2 = (int)Math.Round((partical.position.Y - 5) / 10);
Grid[x1,y1].Add(partical.ID);
Grid[x2,y1].Add(partical.ID);
Grid[x1,y2].Add(partical.ID);
Grid[x2,y2].Add(partical.ID);
}
}
void applyGravity(float sub)
{
float gravitystrangth = -0.1f;
foreach (Partical partical in Particals)
{
float a = partical.position.Y;
float b = partical.position.X;
b -= 1000;
a -= 500;
double angle = Math.Atan2(a, b);
float newA = gravitystrangth * (float)(Math.Sin(angle));
float newB = gravitystrangth * (float)(Math.Sin((Math.PI / 180) * 90 - angle));
Vector2 gravity = new Vector2(newB, newA);
partical.accelerate(gravity);
}
}
void solvecolisions(int id1, int id2)
{
Partical part = Particals[id1];
Partical part2 = Particals[id2];
if (part != part2)
{
Vector2 colisionaxis = part.position - part2.position;
float dist = colisionaxis.Length();
if (dist < 10)
{
Vector2 n = colisionaxis / dist;
float delta = 10 - dist;
part.position += 0.5f * delta * n;
part2.position -= 0.5f * delta * n;
}
}
}
public List<Partical> GetParticals()
{
return Particals;
}
}
}
`
You ts list depends on solver.Grid[x,y]. I am sure that some of your code that is not visible on the screen makes some changes of solver.Grid, probably deletes some times, or replaces them. This is what causing the error.
This question already has answers here:
CS0120: An object reference is required for the nonstatic field, method, or property 'foo'
(9 answers)
Closed 6 years ago.
i have a private method is ball.cs class in witch i want to modify a bool type from margins.cs class, but i get the Error An object reference is required for the non-static field, method, or property 'PingPong.Margins.win'.
Can someone help me with this?
this is the ball class code :
namespace PingPong
{
public class Ball
{
private PictureBox ball;
Random rand= new Random();
Player leftSidePlayer, rightSidePlayer;
int xSpeed, ySpeed;
public Ball(PictureBox aBall, Player leftSidePlayer, Player rightSidePlayer)
{
this.ball = aBall;
this.leftSidePlayer = leftSidePlayer;
this.rightSidePlayer = rightSidePlayer;
xSpeed = 1;
ySpeed = 2;
resetBall();
}
internal void processmove()
{
var bottom = Margins.bottomOfWorld - ball.Height;
DoMove();
if(ball.Location.Y >= bottom || ball.Location.Y <= Margins.topOfWorld)
{
ySpeed *= -1;
}
if (ball.Location.X <= Margins.leftOfWorld)
{
Score(leftSidePlayer);
}
else if (ball.Location.X >= Margins.rightOfWorld - ball.Width)
{
Score(rightSidePlayer);
}
if ((leftSidePlayer.paddle.Bounds.IntersectsWith(ball.Bounds)) || (rightSidePlayer.paddle.Bounds.IntersectsWith(ball.Bounds)))
{
xSpeed *= -1;
if ((ySpeed <= 6 && ySpeed >=-6) && (xSpeed <= 5 && xSpeed >=-5) )
{
if(ySpeed < 0)
{
ySpeed -= 1;
}else
{
ySpeed += 1;
}
if (xSpeed < 0)
{
xSpeed -= 1;
}
else
{
xSpeed += 1;
}
}
}
}
private int DoMove()
{
var bottom = Margins.bottomOfWorld - ball.Height;
ball.Location = new Point(ball.Location.X + xSpeed, Math.Max(Margins.topOfWorld, Math.Min(bottom, ball.Location.Y + ySpeed)));
return bottom;
}
private void Score(Player winningPlayer)
{
winningPlayer.scoreNumber++;
if(winningPlayer.scoreNumber == 7)
{
if(winningPlayer == leftSidePlayer )
{
Margins.win = true;
}else if(winningPlayer == rightSidePlayer)
{
Margins.win = false;
}
}
resetBall();
}
private void resetBall()
{
ball.Location = new Point((Margins.leftOfWorld + Margins.rightOfWorld) / 2, (Margins.bottomOfWorld + Margins.topOfWorld) / 2);
do
{
xSpeed = rand.Next(-3, 3);
ySpeed = rand.Next(-3, 3);
} while(Math.Abs(xSpeed) + Math.Abs(ySpeed) <= 3);
}
}
}
and this is the margins class code :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace PingPong
{
public class Margins
{ //Marimea ferestrei 1000; 600
public const int topOfWorld = 0, bottomOfWorld = 560, leftOfWorld =0, rightOfWorld = 1000;
public bool? win = null;
}
}
the error i get is in private void score when i use the margins.win = true
and margins.win = false .
You have a class with some static (or constant) variables now. Next to that, there is the instance variable win. That means you have to create an instance of Margins in order to get or set it.
If you really need a static class since there can always be just one Margins instance, make the class and its variables static:
public static class Margins
{ //Marimea ferestrei 1000; 600
public const int topOfWorld = 0, bottomOfWorld = 560, leftOfWorld =0, rightOfWorld = 1000;
public static bool? win = null;
}
If not, make a proper instance of Margins:
private Margins margins = new Margins();
this.margins.win = true;
I have something like chessboard, 21x21 checks, each of one have 10x10pixels. I have no idea how do I paint one of the check when user click mouse on it.
Probably i have to use arrays but i dont know how can I assign 10x10 pixels to one element of other array. Can i assign array wiht 100 elements to one elemnet of other array?
This is my code:
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;
namespace gotowa_mapa
{
public partial class Form1 : Form
{
Bitmap mapa;
private int szer_pb = 200;
private int wys_pb = 200;
private int ilosc_kratek_x = 41;
private int ilosc_kratek_y = 41;
// private void wpisanie_tablic()
//{
// int[,] tablica_kratki = new int[ilosc_kratek_x, ilosc_kratek_y];
// int[,] tablica_piksele = new int[szer_pb, wys_pb];
//for(int i=0;i<ilosc_kratek_x; i++)
// {
// for(int j=0; j<ilosc_kratek_y; j++)
//{
// tablica_kratki[ilosc_kratek_x, ilosc_kratek_y] = tablica_piksele[2,2];
//}
//}
//}
private void siatka1()
{
mapa = new Bitmap(szer_pb, wys_pb);
int factor_x = (int)(szer_pb / ilosc_kratek_x);
int factor_y = (int)(wys_pb / ilosc_kratek_y);
for (int i = 0; i < szer_pb; i++)
{
if (i > (factor_x * ilosc_kratek_x))
break;
for (int j = 0; j < wys_pb; j++)
{
if (j > (factor_y * ilosc_kratek_y))
break;
if (i % (factor_x) == 0 || j % (factor_y) == 0)
{
mapa.SetPixel(i, j, Color.Black);
mapa.SetPixel(j, i, Color.Black);
}
else
{
mapa.SetPixel(i, j, Color.White);
mapa.SetPixel(j, i, Color.White);
}
}
}
}
// private void rysowanie_scian(int x, int y)
// {
// }
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
siatka1();
pictureBox1.Image = mapa;
}
private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
{
int x, y;
x = e.X;
y = e.Y;
MessageBox.Show(x + " " + y);
}
}
}
I've made an example for you, although there is probably better ways of doing this, using some simple math you can achieve this.
A neat trick is overriding the onPaint method of a panel, making a new Bitmap with the same size as the panel, drawing this image over the panel during the onPaint method, making changes directly to the image, then invalidating the panel so it draws the image. (You can then save the image with Bitmap.Save)
Keep in mind, if a game of some sort is what you are aiming for, GDI is not ideal, look into managed DirectX or similar.
//declare variables
public const int offset = 50;
public const int boardX = 10;
public const int boardY = 10;
public const int checkSize = 40;
int[] checks;
//set initial values for the checks array
if(checks == null)
{
checks = new int[boardX * boardY];
}
//start iterating through the array of checks
for (int i = 0; i < checks.Length; i++)
{
//if the check is empty (assuming you will use integers as identifiers for the pieces on the board)
if (checks[i] < 1)
{
//check if the check in array is odd number & paint odd numbers black on alternating rows
if (i % 2 != 0)
{
//check if row is odd
if (Math.Ceiling((double)(i + 1) / boardX) % 2 != 0)
{
drawCheck(Brushes.Black, e.Graphics, i);
}
else
{
drawCheck(Brushes.White, e.Graphics, i)
}
}
else
{
//check if row is odd
if (Math.Ceiling((double)(i+1) / boardX) % 2 != 0;
{
drawCheck(Brushes.White, e.Graphics, i);
}
else
{
drawCheck(Brushes.Black, e.Graphics, i)
}
}
}
else if (checks[i] == 1)
{
//the check is a "clicked check" - draw it red
drawCheck(Brushes.Red, e.Graphics, i);
}
}
//The Methods
private void YOURDRAWINGSURFACE_MouseClick(object sender, MouseEventArgs e)
{
if(e.X < (boardX * checkSize) + offset && e.Y < (boardY * checkSize) + offset && e.X > offset && e.Y > offset )
{
//you have clicked somewhere on the board. if that square isn't red, make it so, else turn it back to a normal square
if (checks[checkClicked(e.X, e.Y)] != 1)
{
checks[checkClicked(e.X, e.Y)] = 1;
}
else
{
checks[checkClicked(e.X, e.Y)] = 0;
}
}
//this is only relevant for GDI drawing code. It will invalidate the form to redraw the surface (needs to be called whenever you make a change)
this.Invalidate();
}
public int checkClicked(int mouseX, int mouseY)
{
//this method returns the int of the particular check that was clicked in the array.
return ((int)Math.Ceiling((double)(mouseX - offset) / checkSize) + (int)((Math.Ceiling((double)(mouseY - offset) / checkSize)) * boardX) - (1 + boardX));
}
public void drawCheck(Brush brush, Graphics graphics, int checkNumber)
{
//this method draws the check given the parameters.
graphics.FillRectangle(brush, ((checkNumber % boardX) * checkSize) + offset, (int)(Math.Ceiling((double)(checkNumber-(boardX-1)) / boardX) * checkSize) + offset, checkSize, checkSize);
}
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);
}
}
will someone help me in this moving of my token, which is found in the diceroll() method,
if the user clicks the dice roll button, the token will round the board. the problem is the token is going outside the board
i already set a the first value of x as 15 and y as 12
(if you want to see the whole game file: http://www.mediafire.com/?1rz1689di15o8sq)
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace GAME
{
public partial class GameInterface : Form
{
int curx, cury, tempx, tempy;
private int x, y;
public int Seconds;
public int minutes = 5;
Int32 dice;
public GameInterface()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
token.Location = new Point(15, 12);
x = 15;
y = 12;
button1.Enabled = false;
}
private void Quit_Click(object sender, EventArgs e)
{
quitting quit = new quitting();
quit.ShowDialog();
}
private void Dice_Click(object sender, EventArgs e)
{
diceroll();
timer1.Enabled = true;
}
public void coorx(int x)
{
curx = x;
}
public void coory(int y)
{
cury = y;
}
public int getx()
{
return curx;
}
public int gety()
{
return cury;
}
public void diceroll()
{
System.Random diceroll = new Random();
dice = diceroll.Next(6) + 1;
DiceBox.Text = Convert.ToString(dice);
if (x >= 15 && y <= 102)
{
x = getx();
tempx = x + (105 * dice);
token.Location = new Point(tempx, y);
coorx(tempx);
}
if (x >= 608 && y <= 12)
{
y = gety();
int tempy = y + (95 * dice);
token.Location = new Point(x, tempy);
coory(tempy);
}
if (x >= 707 && y <= 552)
{
x = getx();
tempx = x - (105 * dice);
token.Location = new Point(tempx, y);
coorx(tempx);
}
if (x >= 113 && y <= 642)
{
y = gety();
int tempy = y - (95 * dice);
token.Location = new Point(x, tempy);
coory(tempy);
}
}
private void timer1_Tick(object sender, EventArgs e)
{
if ((minutes == 0) && (Seconds == 0))
{
timer1.Enabled = false;
MessageBox.Show("Game Over!");
label3.Text = "05";
label5.Text = "00";
}
else
{
if (Seconds < 1)
{
Seconds = 60;
timer1.Interval = 1000;
if (minutes != 0)
minutes -= 1;
}
else
{
Seconds -= 1;
label3.Text = minutes.ToString();
label5.Text = Seconds.ToString();
}
}
}
private void GameInterface_Load(object sender, EventArgs e)
{
}
}
}
It looks like it could fall into several of the if conditions at the same time.
say x=150, y=12 and dice=6
It would fall into this if statement:
if (x >= 15 && y <= 102) and this one: if (x >= 113 && y <= 642)
since the X and Y values don't get updated, only curx and cury, that might explain the weird token movement.