Trying to make tiles from a bitmap

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Im working on code from this tutorial at VB-Helper.com, Howto_net_picture_tiles. I modified it to use my jpgs and it worked fine. Then I tried to use Form1 and the Piece Class in another project and it gave me an error at List(Of
Piece) - Type"List" is not defined.
Im copy and pasting the code from Form1 and the Piece Class below, but it would probably be easier to download the app at VB-Helper and step through it.

<pre class="prettyprint lang-vb Public Class Form1
The current full picture.
Private FullPicture As Bitmap = Nothing

The boards background.
Private Background As Bitmap = Nothing

The board.
Private Board As Bitmap = Nothing

The pieces.
Private Pieces As List(Of Piece) = Nothing

The target size. (Initially easy.)
Private TargetSize As Integer = 200

The number and size of the rows and columns.
Private NumRows, NumCols, RowHgt, ColWid As Integer

The piece the user is moving.
Private MovingPiece As Piece = Nothing
Private MovingPoint As Point

True when the game is over.
Private GameOver As Boolean = True

Exit.
Private Sub mnuFileExit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuFileExit.Click
Me.Close()
End Sub

Open an image file.
Private Sub mnuFileOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuFileOpen.Click
If (ofdPicture.ShowDialog() = DialogResult.OK) Then
LoadPicture(ofdPicture.FileName)
End If
End Sub

Load this file.
Private Sub LoadPicture(ByVal filename As String)
Try
Load the picture.
Using bm As New Bitmap(ofdPicture.FileName)
FullPicture = New Bitmap(bm.Width, bm.Height)
Using gr As Graphics = Graphics.FromImage(FullPicture)
gr.DrawImage(bm, 0, 0, bm.Width, bm.Height)
End Using
End Using

Make the Board and background bitmaps.
Background = New Bitmap(FullPicture.Width, FullPicture.Height)
Board = New Bitmap(FullPicture.Width, FullPicture.Height)
picPuzzle.Size = FullPicture.Size
picPuzzle.Image = Board
Me.ClientSize = New Size( _
picPuzzle.Right + picPuzzle.Left, _
picPuzzle.Bottom + picPuzzle.Left)

Start a new game.
StartGame()

Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End Sub

Select the level.
Private Sub mnuOptionsLevel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuOptionsEasy.Click, mnuOptionsMedium.Click, mnuOptionsHard.Click
Check and uncheck the items.
Dim mnu As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
mnuOptionsEasy.Checked = (mnu Is mnuOptionsEasy)
mnuOptionsMedium.Checked = (mnu Is mnuOptionsMedium)
mnuOptionsHard.Checked = (mnu Is mnuOptionsHard)

Get the target size.
TargetSize = Integer.Parse(mnu.Tag.ToString())

Start a new game.
StartGame()
End Sub

Start a new game.
Private Sub StartGame()
If (FullPicture Is Nothing) Then Return
GameOver = False

Figure out how big the pieces should be.
NumRows = FullPicture.Height TargetSize
RowHgt = FullPicture.Height NumRows
NumCols = FullPicture.Width TargetSize
ColWid = FullPicture.Width NumCols

Make the pieces.
Dim rand As New Random()
Pieces = New List(Of Piece)()
For row As Integer = 0 To NumRows - 1
Dim hgt As Integer = RowHgt
If (row = NumRows - 1) Then hgt = FullPicture.Height - row * RowHgt
For col As Integer = 0 To NumCols - 1
Dim wid As Integer = ColWid
If (col = NumCols - 1) Then wid = FullPicture.Width - col * ColWid
Dim rect As New Rectangle(col * ColWid, row * RowHgt, wid, hgt)
Dim new_piece As New Piece(FullPicture, rect)

Randomize the initial location.
new_piece.CurrentLocation = New Rectangle( _
rand.Next(0, FullPicture.Width - wid), _
rand.Next(0, FullPicture.Height - hgt), _
wid, hgt)

Add to the Pieces collection.
Pieces.Add(new_piece)
Next col
Next row

Make the background.
MakeBackground()

Draw the board.
DrawBoard()
End Sub

Make the whole background image without MovingPiece.
Private Sub MakeBackground()
Using gr As Graphics = Graphics.FromImage(Background)
MakeBackgroundOnGraphics(gr)
End Using
End Sub

Make the background image without MovingPiece
confined to the rectangle rect.
Private Sub MakeBackground(ByVal rect As Rectangle)
Using gr As Graphics = Graphics.FromImage(Background)
gr.SetClip(rect)
MakeBackgroundOnGraphics(gr)
End Using
End Sub

Make the background image without MovingPiece.
Private Sub MakeBackgroundOnGraphics(ByVal gr As Graphics)
Clear.
gr.Clear(picPuzzle.BackColor)

Draw a grid on the background.
Using thick_pen As New Pen(Color.DarkGray, 4)
For y As Integer = 0 To FullPicture.Height Step RowHgt
gr.DrawLine(thick_pen, 0, y, FullPicture.Width, y)
Next y
gr.DrawLine(thick_pen, 0, FullPicture.Height, FullPicture.Width, FullPicture.Height)

For x As Integer = 0 To FullPicture.Width Step ColWid
gr.DrawLine(thick_pen, x, 0, x, FullPicture.Height)
Next x
gr.DrawLine(thick_pen, FullPicture.Width, 0, FullPicture.Width, FullPicture.Height)
End Using

Draw the pieces.
Using white_pen As New Pen(Color.White, 3)
Using black_pen As New Pen(Color.Black, 3)
For Each a_piece As Piece In Pieces
Dont draw the piece we are moving.
If (a_piece IsNot MovingPiece) Then
gr.DrawImage(FullPicture, _
a_piece.CurrentLocation, _
a_piece.HomeLocation, _
GraphicsUnit.Pixel)
If (Not GameOver) Then
If (a_piece.IsHome()) Then
Draw locked pieces with a white border.
gr.DrawRectangle(white_pen, a_piece.CurrentLocation)
Else
Draw locked pieces with a black border.
gr.DrawRectangle(black_pen, a_piece.CurrentLocation)
End If
End If
End If
Next a_piece
End Using
End Using

picPuzzle.Visible = True
picPuzzle.Refresh()
End Sub

Fix the background image without MovingPiece.
Private Sub RemoveMovingPieceFromBackground()
If (MovingPiece Is Nothing) Then Return

Using gr As Graphics = Graphics.FromImage(Background)
Restrict the drawing to MovingPieces area.
gr.SetClip(MovingPiece.CurrentLocation)

Draw the grid at that position.
Using bg_brush As New SolidBrush(picPuzzle.BackColor)
gr.FillRectangle(bg_brush, MovingPiece.CurrentLocation)
End Using

Draw a grid on that area.
Using thick_pen As New Pen(Color.DarkGray, 4)
For y As Integer = 0 To FullPicture.Height Step RowHgt
If (y >= MovingPiece.CurrentLocation.Top AndAlso _
y <= MovingPiece.CurrentLocation.Bottom) _
Then
gr.DrawLine(thick_pen, _
MovingPiece.CurrentLocation.Left, y, _
MovingPiece.CurrentLocation.Right, y)
End If
Next y

For x As Integer = 0 To FullPicture.Width Step ColWid
If (x >= MovingPiece.CurrentLocation.Left AndAlso _
x <= MovingPiece.CurrentLocation.Right) _
Then
gr.DrawLine(thick_pen, _
x, MovingPiece.CurrentLocation.Top, _
x, MovingPiece.CurrentLocation.Bottom)
End If
Next x
End Using

Draw the pieces.
Using white_pen As New Pen(Color.White, 3)
Using black_pen As New Pen(Color.Black, 3)
For Each a_piece As Piece In Pieces
Dont draw the piece we are moving.
If (a_piece IsNot MovingPiece) Then
If (a_piece.CurrentLocation.IntersectsWith(MovingPiece.CurrentLocation)) Then
gr.DrawImage(FullPicture, _
a_piece.CurrentLocation, _
a_piece.HomeLocation, _
GraphicsUnit.Pixel)
If (Not GameOver) Then
If (a_piece.IsHome()) Then
Draw locked pieces with a white border.
gr.DrawRectangle(white_pen, a_piece.CurrentLocation)
Else
Draw locked pieces with a black border.
gr.DrawRectangle(black_pen, a_piece.CurrentLocation)
End If
End If
End If
End If
Next a_piece
End Using
End Using
End Using

picPuzzle.Visible = True
picPuzzle.Refresh()
End Sub

Draw the board.
Private Sub DrawBoard()
Using gr As Graphics = Graphics.FromImage(Board)
Restore the background.
gr.DrawImage(Background, 0, 0, Background.Width, Background.Height)

Draw MovingPiece.
If (MovingPiece IsNot Nothing) Then
gr.DrawImage(FullPicture, _
MovingPiece.CurrentLocation, _
MovingPiece.HomeLocation, _
GraphicsUnit.Pixel)

Using blue_pen As New Pen(Color.Blue, 4)
gr.DrawRectangle(blue_pen, MovingPiece.CurrentLocation)
End Using
End If
End Using

picPuzzle.Visible = True
picPuzzle.Refresh()
End Sub

Start moving a piece.
Private Sub picPuzzle_MouseDown(ByVal sender As Object, ByVal e As MouseEventArgs) Handles picPuzzle.MouseDown
See which piece contains this point.
Skip fixed pieces.
Keep the last one because its on the top.
MovingPiece = Nothing
For Each a_piece As Piece In Pieces
If (Not a_piece.IsHome() AndAlso a_piece.Contains(e.Location)) Then
MovingPiece = a_piece
End If
Next a_piece
If (MovingPiece Is Nothing) Then Return

Save this location.
MovingPoint = e.Location

Move it to the top of the stack.
Pieces.Remove(MovingPiece)
Pieces.Add(MovingPiece)

Redraw the area under MovingPiece.
Dim rect As Rectangle = MovingPiece.CurrentLocation
rect.Inflate(4, 4)
MakeBackground(rect)
DrawBoard()
End Sub

Move the selected piece.
Private Sub picPuzzle_MouseMove(ByVal sender As Object, ByVal e As MouseEventArgs) Handles picPuzzle.MouseMove
If (MovingPiece Is Nothing) Then Return

Move the piece.
Dim dx As Integer = e.X - MovingPoint.X
Dim dy As Integer = e.Y - MovingPoint.Y
MovingPiece.CurrentLocation.X += dx
MovingPiece.CurrentLocation.Y += dy

Save the new mouse location.
MovingPoint = e.Location

Redraw.
DrawBoard()
End Sub

Stop moving the piece and see if it is where it belongs.
Private Sub picPuzzle_MouseUp(ByVal sender As Object, ByVal e As MouseEventArgs) Handles picPuzzle.MouseUp
If (MovingPiece Is Nothing) Then Return

See if the piece is in its home position.
If (MovingPiece.SnapToHome()) Then
Move the piece to the bottom.
Pieces.Remove(MovingPiece)
Pieces.Reverse()
Pieces.Add(MovingPiece)
Pieces.Reverse()

See if the game is over.
GameOver = True
For Each a_piece As Piece In Pieces
If (Not a_piece.IsHome()) Then
GameOver = False
Exit For
End If
Next a_piece
End If

Get MovingPieces location.
Dim rect As Rectangle = MovingPiece.CurrentLocation
rect.Inflate(4, 4)

Stop moving the piece.
MovingPiece = Nothing

Redraw the area that was under MovingPiece.
If (GameOver) Then
MakeBackground()
Else
MakeBackground(rect)
End If

DrawBoard()
End Sub

Public Sub New()

This call is required by the Windows Form Designer.
InitializeComponent()

Add any initialization after the InitializeComponent() call.

End Sub
End Class


>>>>>>>>THIS IS THE PIECE CLASS<<<<<<<<<<<<<

Public Class Piece
Public Picture As Bitmap
Public HomeLocation, CurrentLocation As Rectangle

Public Sub New(ByVal new_picture As Bitmap, ByVal home_location As Rectangle)
Picture = new_picture
HomeLocation = home_location
End Sub

Return true if the piece is in its home position.
Public Function IsHome() As Boolean
Return HomeLocation.Equals(CurrentLocation)
End Function

Return true if this position is within
the pieces current location.
Public Function Contains(ByVal pt As Point) As Boolean
Return CurrentLocation.Contains(pt)
End Function

If the piece is close to its home position, move it there.
Public Function SnapToHome() As Boolean
If ((Math.Abs(CurrentLocation.X - HomeLocation.X) < 20) AndAlso _
(Math.Abs(CurrentLocation.Y - HomeLocation.Y) < 20)) _
Then
CurrentLocation = HomeLocation
Return True
End If

Return False
End Function
End Class
[/code]
<br/>



View the full article
 
Back
Top