Hi, I am writing a boardgame. I need to load the chess pieces into a chessboard. I am using picturebox for each chesspiece. The code look like this:
private PictureBox[,] pieceBox;
public Form_Chess()
{
InitializeComponent();
initPieces();
}
private void initPieces()
{
pieceBox = new PictureBox[8, 8];
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
{
pieceBox[i, j] = new PictureBox();
pieceBox[i, j].BringToFront();
pieceBox[i, j].Location = new System.Drawing.Point(7 + i * 71, 4 + j * 66);
pieceBox[i, j].Name = "Piece";
pieceBox[i, j].Size = new Size(60, 60);
pieceBox[i, j].TabStop = false;
pieceBox[i, j].TabIndex = i;
if (j <= 3)
pieceBox[i, j].BackgroundImage = BreakThrough.Properties.Resources.BLACK;
else
if (j >= 4)
pieceBox[i, j].BackgroundImage = BreakThrough.Properties.Resources.RED;
this.panel_Chessboard.Controls.AddRange(new System.Windows.Forms.Control[] { this.pieceBox[i, j] });
}
}
Basically, you can see that all picture boxes are created and loaded to a panel and this is one the screenshot http://img17.imageshack.us/img17/8813/loadingg.jpg when all pieces are initializing... However, I see that it is slow loading, piece by piece. As you can see from the screenshot. If there is any form (web browser) overlap it, the whole form will reload again, the same case if I minimize the form and maximize the form. Is there any better solution for loading the pieces without loading one by one. What I want is that: when I click on exe file, all pieces are there without loading effects. And prevent to repaint the whole form when not needed. Thanks in advance. your help is much appreciated! | | nguyenxh Thursday, April 09, 2009 11:51 AM | Calculate the area you moved to and repaint the area with the appropriate image.
Please remember to click “Mark as Answer�on the post that helps you, and to click “Unmark as Answer�if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread. - Marked As Answer bynguyenxh Monday, April 13, 2009 10:45 AM
-
| | Ling Wang Monday, April 13, 2009 7:53 AM | You haven't eliminated the PictureBoxes. Some sample code: public partial class Form1 : Form { public Form1() { InitializeComponent(); this.ClientSize = new Size(8 * cSquare, 8 * cSquare); } const int cSquare = 60; Bitmap bmpRed = new Bitmap(Properties.Resources.Red, cSquare, cSquare); Bitmap bmpBlack = new Bitmap(Properties.Resources.Black, cSquare, cSquare); protected override void OnPaint(PaintEventArgs e) { for (int x = 0; x < 8; ++x) { for (int y = 0; y < 8; ++y) { bool red = ((x % 2) == 0) ^ ((y % 2) == 0); Rectangle rc = new Rectangle(x * cSquare, y * cSquare, cSquare, cSquare); e.Graphics.DrawImage(red ? bmpRed : bmpBlack, rc); // Draw the piece, if any //... } } } protected override void OnMouseDown(MouseEventArgs e) { // Check which field is clicked int x = e.X / cSquare; int y = e.Y / cSquare; // Do something with x, y //... } }
Hans Passant.- Marked As Answer byLing WangMSFT, ModeratorMonday, April 13, 2009 7:54 AM
-
| | nobugz Thursday, April 09, 2009 5:43 PM | I used this code as my base class. It is a test versioni of what I am doing. It"flashes" between 2 images at a rate of 1/2 second.
public abstract class GameElement : Panel
{
protected Size small;
protected Size medium;
protected Size large;
protected Timer flashTimer;
protected Image image0;
protected Image image1;
protected int flashFrame;
protected Size elementSize;
public Size ElementSize
{
get
{
return elementSize;
}
set
{
elementSize = value;
}
}
protected Point modelLocation;
public Point ModelLocation
{
get
{
return modelLocation;
}
set
{
modelLocation = value;
}
}
protected Boolean running;
public Boolean Running
{
get
{
return running;
}
set
{
running = value;
}
}
public GameElement()
{
InitializeComponent_this();
small = new Size(12, 12);
medium = new Size(18, 18);
large = new Size(24, 24);
flashFrame = 0;
}
public GameElement(Size size)
: this()
{
Initialize_Size(size);
}
public GameElement(GameBoardStyle gameBoardStyle)
: this()
{
switch (gameBoardStyle)
{
case GameBoardStyle.Small:
Initialize_Size(new Size(12, 12));
break;
case GameBoardStyle.Medium:
Initialize_Size(new Size(18, 18));
break;
case GameBoardStyle.Large:
Initialize_Size(new Size(24, 24));
break;
default:
break;
}
}
private void Initialize_Size(Size size)
{
if (size == small)
{
this.Size = small;
this.image0 = Properties.Resources.Block;
this.image1 = Properties.Resources.Block;
this.elementSize = small;
}
if (size == medium)
{
this.Size = medium;
this.image0 = Properties.Resources.Block_18x18;
this.image1 = Properties.Resources.Block_18x18;
this.elementSize = medium;
}
if (size == large)
{
this.Size = large;
this.image0 = Properties.Resources.Block_24x24;
this.image1 = Properties.Resources.Block_24x24;
this.elementSize = large;
}
return;
}
protected virtual void InitializeComponent_this()
{
this.BackColor = Color.Aquamarine;
this.BackgroundImage = Properties.Resources.Blank;
this.Size = new Size(12, 12);
this.Running = false;
this.flashTimer = new Timer();
this.flashTimer.Interval = 500;
this.flashTimer.Enabled = true;
this.flashTimer.Tick += new EventHandler(flashTimer_Tick);
return;
}
protected virtual void flashTimer_Tick(object sender, EventArgs e)
{
switch (flashFrame)
{
case 0:
this.BackgroundImage = this.image1;
this.flashFrame = 1;
break;
case 1:
this.BackgroundImage = this.image0;
this.flashFrame = 0;
break;
}
}
}
The images get loaded into the BackgroundImage property. This control is a little bit dynamic. I initialize to one of 3 sizes.
small =
new Size(12, 12); medium = new Size(18, 18); large = new Size(24, 24);
Pass one of those sizes into the constructor. I create a grid of these things. I guess that you could use the same image for each frame of the flash to test it out with just a single image. Iadd these panel controls inside of complex custompanel sized to fit a largesquare grid of these controls. The grid is never completely filled with panels, assome of themneed room to move around. The amount of the little guys can vary between 150 and 300, which is user selectable. The bigger panels make for a harder game. Less room to run!
Mark the best replies as answers. "Fooling computers since 1971." - Edited byRudedog2 Thursday, April 09, 2009 10:51 PMedit
- Marked As Answer byLing WangMSFT, ModeratorMonday, April 13, 2009 7:54 AM
-
| | Rudedog2 Thursday, April 09, 2009 10:37 PM | Controls are expensive objects. With 64 pictureboxes, you are using more windows than a Microsoft Office program like Outlook. Fix it by using only one. Use the Paint event to draw the board. Implement the MouseDown event to do hit testing. Hans Passant. | | nobugz Thursday, April 09, 2009 1:56 PM | Hi nobugz, Thanks for your reply, Could you please give more details? (or sample code). I already tried this:
private void initPieces()
{
pieceBox = new PictureBox[8, 8];
for (int i = 0; i < 8; i++)
for (int j = 0; j < 8; j++)
{
pieceBox[i, j] = new PictureBox();
pieceBox[i, j].BackColor = Color.Transparent;
pieceBox[i, j].Location = new System.Drawing.Point(7 + i * 71, 4 + j * 66);
pieceBox[i, j].Name = "Piece";
pieceBox[i, j].Size = new Size(60, 60);
pieceBox[i, j].TabStop = false;
pieceBox[i, j].TabIndex = i;
if (j <= 3)
{
pieceBox[i, j].Paint += new PaintEventHandler(Form_Chess_Paint_Black);
//pieceBox[i, j].BackgroundImage = BreakThrough.Properties.Resources.BLACK;
}
else
if (j >= 4)
{
pieceBox[i, j].Paint += new PaintEventHandler(Form_Chess_Paint_Red);
//pieceBox[i, j].BackgroundImage = BreakThrough.Properties.Resources.RED;
}
this.panel_Chessboard.Controls.AddRange(new System.Windows.Forms.Control[] { this.pieceBox[i, j] });
}
}
private void Form_Chess_Load(object sender, EventArgs e)
{
}
private void Form_Chess_Paint_Black(object sender, System.Windows.Forms.PaintEventArgs e)
{
// Create a local version of the graphics object for the PictureBox.
Graphics g = e.Graphics;
g.DrawImage(global::BreakThrough.Properties.Resources.BLACK, new Point(0, 0));
}
private void Form_Chess_Paint_Red(object sender, System.Windows.Forms.PaintEventArgs e)
{
// Create a local version of the graphics object for the PictureBox.
Graphics g = e.Graphics;
g.DrawImage(global::BreakThrough.Properties.Resources.RED, new Point(0, 0));
}
private void Form_Chess_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
// Create a local version of the graphics object for the PictureBox.
Graphics g = e.Graphics;
g.DrawImage(global::BreakThrough.Properties.Resources.CHESSBOARD, new Point(0, 0));
}
But it is the same result... :( Thanks in advance. | | nguyenxh Thursday, April 09, 2009 3:11 PM | You haven't eliminated the PictureBoxes. Some sample code: public partial class Form1 : Form { public Form1() { InitializeComponent(); this.ClientSize = new Size(8 * cSquare, 8 * cSquare); } const int cSquare = 60; Bitmap bmpRed = new Bitmap(Properties.Resources.Red, cSquare, cSquare); Bitmap bmpBlack = new Bitmap(Properties.Resources.Black, cSquare, cSquare); protected override void OnPaint(PaintEventArgs e) { for (int x = 0; x < 8; ++x) { for (int y = 0; y < 8; ++y) { bool red = ((x % 2) == 0) ^ ((y % 2) == 0); Rectangle rc = new Rectangle(x * cSquare, y * cSquare, cSquare, cSquare); e.Graphics.DrawImage(red ? bmpRed : bmpBlack, rc); // Draw the piece, if any //... } } } protected override void OnMouseDown(MouseEventArgs e) { // Check which field is clicked int x = e.X / cSquare; int y = e.Y / cSquare; // Do something with x, y //... } }
Hans Passant.- Marked As Answer byLing WangMSFT, ModeratorMonday, April 13, 2009 7:54 AM
-
| | nobugz Thursday, April 09, 2009 5:43 PM | I wrote a game application for some kids to test out that uses panels instead of pictureboxes. Still setting the background image as the OP. My panels vary in size; 12x12, 18x18, 24x24 pixels depending upon gameboard size.
The smallest panels fill a grid that is over 40 by 40 panels, that's more than 1600. I don't see any of the problems the OP is reporting. My panels move around like graphical sprites, which is what they are. About a dozen of them use timers to sequence through images to provide asimple animation.
Curious. I see these types of posts all of the time regarding other types of controls. Never with Panels. Mark the best replies as answers. "Fooling computers since 1971." | | Rudedog2 Thursday, April 09, 2009 7:45 PM | Hi nobugz,
Yes, it works with better performance to loading the pieces.
But now, I am getting another problem. The piece needs to move. How could I remove the image which was drawn by e.Graphics.DrawImage?
I could erase this with a white filled rectangle but my background is an image like a chess board.
Could you please help me again?
Thanks in advance.
With kind regards, | | nguyenxh Thursday, April 09, 2009 8:57 PM | Hi Rudedog2,
I also tried to use panels instead of pictureboxes. But It is still the same like using pictureboxes, it looks like each piece is loaded one by one.
Could you please post your code where you load the images on the panels?
Thanks in advance. | | nguyenxh Thursday, April 09, 2009 8:58 PM | I used this code as my base class. It is a test versioni of what I am doing. It"flashes" between 2 images at a rate of 1/2 second.
public abstract class GameElement : Panel
{
protected Size small;
protected Size medium;
protected Size large;
protected Timer flashTimer;
protected Image image0;
protected Image image1;
protected int flashFrame;
protected Size elementSize;
public Size ElementSize
{
get
{
return elementSize;
}
set
{
elementSize = value;
}
}
protected Point modelLocation;
public Point ModelLocation
{
get
{
return modelLocation;
}
set
{
modelLocation = value;
}
}
protected Boolean running;
public Boolean Running
{
get
{
return running;
}
set
{
running = value;
}
}
public GameElement()
{
InitializeComponent_this();
small = new Size(12, 12);
medium = new Size(18, 18);
large = new Size(24, 24);
flashFrame = 0;
}
public GameElement(Size size)
: this()
{
Initialize_Size(size);
}
public GameElement(GameBoardStyle gameBoardStyle)
: this()
{
switch (gameBoardStyle)
{
case GameBoardStyle.Small:
Initialize_Size(new Size(12, 12));
break;
case GameBoardStyle.Medium:
Initialize_Size(new Size(18, 18));
break;
case GameBoardStyle.Large:
Initialize_Size(new Size(24, 24));
break;
default:
break;
}
}
private void Initialize_Size(Size size)
{
if (size == small)
{
this.Size = small;
this.image0 = Properties.Resources.Block;
this.image1 = Properties.Resources.Block;
this.elementSize = small;
}
if (size == medium)
{
this.Size = medium;
this.image0 = Properties.Resources.Block_18x18;
this.image1 = Properties.Resources.Block_18x18;
this.elementSize = medium;
}
if (size == large)
{
this.Size = large;
this.image0 = Properties.Resources.Block_24x24;
this.image1 = Properties.Resources.Block_24x24;
this.elementSize = large;
}
return;
}
protected virtual void InitializeComponent_this()
{
this.BackColor = Color.Aquamarine;
this.BackgroundImage = Properties.Resources.Blank;
this.Size = new Size(12, 12);
this.Running = false;
this.flashTimer = new Timer();
this.flashTimer.Interval = 500;
this.flashTimer.Enabled = true;
this.flashTimer.Tick += new EventHandler(flashTimer_Tick);
return;
}
protected virtual void flashTimer_Tick(object sender, EventArgs e)
{
switch (flashFrame)
{
case 0:
this.BackgroundImage = this.image1;
this.flashFrame = 1;
break;
case 1:
this.BackgroundImage = this.image0;
this.flashFrame = 0;
break;
}
}
}
The images get loaded into the BackgroundImage property. This control is a little bit dynamic. I initialize to one of 3 sizes.
small =
new Size(12, 12); medium = new Size(18, 18); large = new Size(24, 24);
Pass one of those sizes into the constructor. I create a grid of these things. I guess that you could use the same image for each frame of the flash to test it out with just a single image. Iadd these panel controls inside of complex custompanel sized to fit a largesquare grid of these controls. The grid is never completely filled with panels, assome of themneed room to move around. The amount of the little guys can vary between 150 and 300, which is user selectable. The bigger panels make for a harder game. Less room to run!
Mark the best replies as answers. "Fooling computers since 1971." - Edited byRudedog2 Thursday, April 09, 2009 10:51 PMedit
- Marked As Answer byLing WangMSFT, ModeratorMonday, April 13, 2009 7:54 AM
-
| | Rudedog2 Thursday, April 09, 2009 10:37 PM | nobugz is the King of custom controls. John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com | | JohnGrove Thursday, April 09, 2009 10:43 PM |
public class GameElementBlock : GameElement
{
public GameElementBlock()
: this(new Size(18, 18))
{
}
public GameElementBlock(Size size)
: base()
{
this.Initialize_Size(size);
}
public GameElementBlock(GameBoardStyle gameBoardStyle)
: base()
{
switch (gameBoardStyle)
{
case GameBoardStyle.Small:
Initialize_Size(new Size(12, 12));
break;
case GameBoardStyle.Medium:
Initialize_Size(new Size(18, 18));
break;
case GameBoardStyle.Large:
Initialize_Size(new Size(24, 24));
break;
default:
break;
}
}
void Initialize_Size(Size size)
{
if (size == small)
{
this.Size = small;
this.image0 = Properties.Resources.Block;
this.image1 = Properties.Resources.Block;
this.elementSize = small;
}
if (size == medium)
{
this.Size = medium;
this.image0 = Properties.Resources.Block_18x18;
this.image1 = Properties.Resources.Block_18x18;
this.elementSize = medium;
}
if (size == large)
{
this.Size = large;
this.image0 = Properties.Resources.Block_24x24;
this.image1 = Properties.Resources.Block_24x24;
this.elementSize = large;
}
}
protected override void flashTimer_Tick(object sender, EventArgs e)
{
base.flashTimer_Tick(sender, e);
}
protected override void InitializeComponent_this()
{
base.InitializeComponent_this();
}
}
Here's one of the test classes to implement the abstract control. Note that it loads images from project resources. These images are pretty small as far as pixels go. Roughly the size of your average icon.
Mark the best replies as answers. "Fooling computers since 1971." | | Rudedog2 Thursday, April 09, 2009 10:49 PM | nobugz is the King of custom controls.
John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com
"NoBugs, that guy's wise!", said the ewokafter Threepio sat upright and first spoke their language. Star Wars VI: Return of the Jedi It's a blooper that they edited never out of the film. Ewoks speaking english, not ewokese.
Mark the best replies as answers. "Fooling computers since 1971." | | Rudedog2 Thursday, April 09, 2009 11:50 PM | Rudy, A fellow movie quoter.
John Grove - TFD Group, Senior Software Engineer, EI Division, http://www.tfdg.com | | JohnGrove Friday, April 10, 2009 3:25 AM | Calculate the area you moved to and repaint the area with the appropriate image.
Please remember to click “Mark as Answer�on the post that helps you, and to click “Unmark as Answer�if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread. - Marked As Answer bynguyenxh Monday, April 13, 2009 10:45 AM
-
| | Ling Wang Monday, April 13, 2009 7:53 AM | Thanks all of you for the supports,
Great help... | | nguyenxh Monday, April 13, 2009 10:46 AM |
|