So I will start with a game.
I’ve been doing so many demos with Visual WebGui and application for so long and I think it’s time to do some fun and games. I will write a more specific post later on Visual WebGui what we do (For this post I want to believe you all ready know what it is).
I really have to get this out of my system and also I don't think you can’t call a platform a platform if no one develops a game on it. So here is the first ever (as far as I know) Visual WebGui based Game.
My very own Picture Scramble. If you don't know what is a picture scramble game the idea is very very simple and old. What you basically have a picture that was cut to a specific number of cubes and one of those cubes preferably the bottom right one is removed. Next you need to scramble the pictures and sort them back to the original picture by moving a picture to the open space that was created by removing the bottom right cube. For this example I’ve used “Chips” my cat as a model you can see the picture before I sorted it and after. Don’t let the picture fool you, he is the devil spawn.
So I create a new VWG application template and Enabled Visual WebGui integration to allow access to Visual Studio’s integrated options of VWG to my project.
Next I’ve added a new VWG User Control SlicedPictureBox.cs. This control will hold a slice of the source image.
Make our SlicedPictureBox inherit from PictureBox and add a few members.
public class SlicedPictureBox : PictureBox
{
#region Members
//The current image slice part
private Point mobjSlicePart = new Point(0, 0);
//The location of the current slice
private Point mobjPicLocation = new Point(0, 0);
//The size of the grid that cuts the image
private Size mobjGridSize = new Size(1, 1);
//The size of source image
private Size mobjSourceSize = new Size(1, 1);
//A resource handle to the image
private ResourceHandle mobjSource = null;
#endregion Members
Next we will add properties for these members.
public Point SlicePart
{
get { return mobjSlicePart; }
set { mobjSlicePart = value; }
}
public Point PicLocation
{
get { return mobjPicLocation; }
set { mobjPicLocation = value; }
}
public Size GridSize
{
get { return mobjGridSize; }
set
{
this.Update();
mobjGridSize = value;
}
}
The last property we need to add is for the ResourceHandle Source. Resource handles are actually pointers to the actual resource. When a control requires a resource such as an Image it should declare a ResourceHandle typed property that will link to an external located resource that will be retrieved through HTTP.
public ResourceHandle Source
{
get { return mobjSource; }
set
{
mobjSource = value;
if (mobjSource != null)
{
Bitmap bm = new Bitmap(mobjSource.ToStream());
// Calculate the Crop size
int intCropWidth = bm.Size.Width / mobjGridSize.Width;
int intCropHeight = bm.Size.Height / mobjGridSize.Height;
//Set the size of the control according to Crop size
this.Size = new Size(intCropWidth, intCropHeight);
}
}
}
Every control in VWG implements IGatewayComponent that provides a way for a component to handle requests. We will override the ProcessGatewayRequest function and set the behavior of our resources handle. What we will do is create a cropped image from the master resource according to the grid size.
protected override Gizmox.WebGUI.Common.Interfaces.IGatewayHandler ProcessGatewayRequest(HttpContext objHttpContext, string strAction)
{
if (mobjSource != null)
{
Bitmap bm = new Bitmap(mobjSource.ToStream());
int intCropWidth = bm.Size.Width / mobjGridSize.Width;
int intCropHeight = bm.Size.Height / mobjGridSize.Height;
Bitmap cropped = new Bitmap(intCropWidth, intCropHeight);
Graphics g = Graphics.FromImage(cropped);
g.DrawImage(bm, new Rectangle(0, 0, cropped.Width, cropped.Height), intCropWidth * mobjSlicePart.X, intCropHeight * mobjSlicePart.Y, cropped.Width, cropped.Height, GraphicsUnit.Pixel);
g.Dispose();
cropped.Save(objHttpContext.Response.OutputStream, ImageFormat.Jpeg);
}
return null;
}
In the control constructor we will set the Image ResourceHandle property that was inherited from the PictureBox class to a new GatewayResourceHandle.
public SlicedPictureBox()
{
this.Image = new GatewayResourceHandle(new GatewayReference(this, "picture"));
}
Now that we have our slice picture box control let’s start creating the application itself.
Open form1 in design mode and add a panel docked to bottom and place two textboxes and a button on it. One text box will hold the number of rows and one will hold the number of columns.
Next we will add a few members.
// Amount of rows
int mintRows;
//Amount of Columns
int mintColumns;
//The currently opened space to move an image to
Point mobjOpendPoint;
//A collection of Points that represent the images location in the grid
List<Point> mobjPointList;
//A collection of images.
List<SlicedPictureBox> mobjSlicedPictureBoxList;
//A collection of shuffled images.
List<SlicedPictureBox> mobjShuffledSlicedPictureBoxList;
The first method that we will create will be FillPointList.
/// <summary>
/// Fill the point collection with the necessary points
/// according to the row and columns that where set by the user.
/// </summary>
private void FillPointList()
{
mobjPointList = new List<Point>();
mobjOpendPoint = new Point(mintRows-1, mintColumns-1);
for (int x = 0; x < mintRows; x++)
{
for (int y = 0; y < mintColumns; y++)
{
if (!((x == y) && (y == mintColumns-1)))
{
mobjPointList.Add(new Point(x, y));
}
}
}
}
The second method is SlicePictures.
/// <summary>
/// Creates a collection of SlicedPictureBox. Each SlicedPictureBox gets a
/// point that represent the part that it needs to crop with the ProcessGatewayRequest
/// function.
/// </summary>
private void SlicePictures()
{
mobjSlicedPictureBoxList = new List<SlicedPictureBox>();
foreach (Point objPoint in mobjPointList)
{
SlicedPictureBox objSlicedPictureBox = new SlicedPictureBox();
objSlicedPictureBox.GridSize = new Size(mintRows, mintColumns);
objSlicedPictureBox.Source = new ImageResourceHandle("Image1.jpg");
objSlicedPictureBox.SlicePart = objPoint;
objSlicedPictureBox.BorderStyle = BorderStyle.FixedSingle;
objSlicedPictureBox.Click += new EventHandler(objSlicedPictureBox_Click);
mobjSlicedPictureBoxList.Add(objSlicedPictureBox);
}
}
Open form1 in design mode and add another panel docked to fill. Rename it to MainPanel. This panel will hold the scrambled puzzle.
Go back to the code section of form1 and add a new method DrowPicturees.
/// <summary>
/// clears the main panel from all the pictures and draws a new set of pictures.
/// </summary>
private void DrowPicturees()
{
this.MainPanel.Controls.Clear();
foreach (SlicedPictureBox objSlicedPictureBox in mobjShuffledSlicedPictureBoxList)
{
objSlicedPictureBox.Left = objSlicedPictureBox.Width * objSlicedPictureBox.PicLocation.X;
objSlicedPictureBox.Top = objSlicedPictureBox.Height * objSlicedPictureBox.PicLocation.Y;
this.MainPanel.Controls.Add(objSlicedPictureBox);
}
}
Last method we need to add is Shuffle.
/// <summary>
///Fills the mobjShuffledSlicedPictureBoxList with images from
///mobjSlicedPictureBoxList but scrambles the order of the images
/// </summary>
private void Shuffle()
{
mobjShuffledSlicedPictureBoxList = new List<SlicedPictureBox>();
Random randNum = new Random();
int objNumberofSlice = mintColumns * mintRows-1;
for (int i = 0; i < objNumberofSlice; i++)
{
int intNext = randNum.Next(0, objNumberofSlice - i);
SlicedPictureBox objSlicedPictureBox = mobjSlicedPictureBoxList[intNext];
mobjSlicedPictureBoxList.Remove(objSlicedPictureBox);
Point objPoint = mobjPointList[i];
objSlicedPictureBox.PicLocation = objPoint;
mobjShuffledSlicedPictureBoxList.Add(objSlicedPictureBox);
}
}
Now let’s add an event to click of the button. On that click event we will read the rows and columns size and create the scramble puzzle.
private void button1_Click(object sender, EventArgs e)
{
mintRows = int.Parse(objRows.Text);
mintColumns = int.Parse(objColumns.Text);
FillPointList();
SlicePictures();
Shuffle();
DrowPicturees();
}
All we need to do now is run the application and play. Enter the amount of rows and columns you want and press the shuffle button.
If you want to download this code you can use this link.
I hope you enjoyed this post. I know I have.
Print | posted on Sunday, January 04, 2009 11:04 AM