|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Optimizing Repeated PictureBox.Paintsdecided to create a graphical Proof of Concept just to confirm that graphics would be... well, simple. Predictably, they've proven otherwise. This is my PictureBoxMap_Paint() Sub, which a tiles a PictureBox with 19* 17 40*40-pixel images, two rows and two columns of which are painted beyond the current bounds of the picturebox to facilitate scrolling. The If/Else statements handle the bounds of the map... At the moment they simply 'roll over' and display the graphics on the other side. Dim A, B As Integer For A = -9 To 9 For B = -8 To 8 Dim X, Y As Integer If A + CurrentCoords.East < 0 Then X = Cell.GetUpperBound(0) + (A + CurrentCoords.East) + 1 ElseIf A + CurrentCoords.East > Cell.GetUpperBound(0) Then X = (A + CurrentCoords.East) - Cell.GetUpperBound(0) - 1 Else X = A + CurrentCoords.East End If If B + CurrentCoords.North < 0 Then Y = Cell.GetUpperBound(1) + (B + CurrentCoords.North) + ElseIf B + CurrentCoords.North > Cell.GetUpperBound(1) Then Y = (B + CurrentCoords.North) - Cell.GetUpperBound(1) - 1 Else Y = B + CurrentCoords.North End If e.Graphics.DrawImage(CellImages(Cell(X, Y, CurrentCoords.Up).Image), ((A + 9) * 40) - 40 + XOffSet, (520 - ((B + 6) * 40) + YOffSet)) Next Next The XOffSet and YOffSet are used to produce the scrolling effect, as seen in this code from my Form_KeyDown procedure. If e.KeyCode = System.Windows.Forms.Keys.Left Then For XOffSet = 0 To 40 Step 4 PictureBox_Map.Refresh() Next XOffSet = 0 If CurrentCoords.East > 0 Then CurrentCoords.East = CurrentCoords.East - 1 Else CurrentCoords.East = Cell.GetUpperBound(0) End If PictureBox_Map.Refresh() End If Unfortunately, this produces a very slow scroll on my Pentium III 933MHZ; I've had to add the equivalent of frame-skipping using 'Step 4' just to make it comparable to the speed in, say, Final Fantasy. My theory for the reason behind this slowness was the reassembly of the map with each PictureBox_Map.Refresh(), and I therefore searched for a way to offset a preassembled graphic, reassembling only when necessary. Unfortunately, I could not then force PictureBox_Map to display this preassembled graphic in such a way that it could be offset as necessary to produce scrolling. An IRC acquaintance who otherwise has been very helpful suggested that calling PictureBox_Map.Refresh might be producing some unintended overhead, and that calling the PictureBox_Paint() routine directly from KeyDown might be better. Unfortunately, I could not call it in such a way that my entry for the PaintEventArgs argument would not completely break the PictureBox_Paint routine. Does anybody have any suggests as to where, exactly, most of my overhead is coming from and how I might reduce or eliminate it? Are repliers have my sincere gratitude. The Confessor wrote:
> I'm trying to develop a graphically-simple, gameplay-complex RPG, and I I won't go into details, because I think your performance problems can> decided to create a graphical Proof of Concept just to confirm that > graphics would be... well, simple. [snip] be best addressed by conceptual changes rather than particular code changes. The way to handle a picturebox that displays a complex graphics is not to build the graphics in the Paint event, but rather to maintain a Bitmap, which holds the actual image, and in the Paint event just DrawImage the bitmap onto the Graphics provided. When the image is required to change, draw the changes onto the Bitmap, then Invalidate the picturebox to force it to paint. Here is a short example: ' VS2003/2005 ' create a new Windows Forms app ' drop a picturebox and two buttons on a form ' add this at the top of the code file Imports System.Drawing 'add this in the form, before the End Class line Private myImage As Bitmap Private myImageGraphics As Graphics 'probably more correct to create the Graphics 'whenever we want to draw 'but this is quicker Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.Load myImage = New Bitmap(PictureBox1.Width, PictureBox1.Height, Imaging.PixelFormat.Format32bppArgb) myImageGraphics = Graphics.FromImage(myImage) myImageGraphics.Clear(Color.White) End Sub Private Sub PictureBox1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint 'all we do in here is draw myImage e.Graphics.DrawImage(myImage, e.ClipRectangle, e.ClipRectangle, GraphicsUnit.Pixel) End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 'create a complex image Dim x As Integer, y As Integer Dim b As Brush, c As Color Dim r As New Random For x = 0 To myImage.Width Step 10 For y = 0 To myImage.Height Step 8 c = Color.FromArgb(r.Next(0, 255), r.Next(0, 255), r.Next(0, 255)) b = New SolidBrush(c) Try myImageGraphics.FillRectangle(b, x, y, 10, 8) Finally b.Dispose() End Try Next Next 'and force painting PictureBox1.Invalidate() End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click 'make some change to the image Dim oldImage As Bitmap = myImage myImage = New Bitmap(PictureBox1.Width, PictureBox1.Height, Imaging.PixelFormat.Format32bppArgb) myImageGraphics = Graphics.FromImage(myImage) myImageGraphics.ResetTransform() myImageGraphics.TranslateTransform(-myImage.Width \ 2, -myImage.Height \ 2, Drawing2D.MatrixOrder.Append) myImageGraphics.RotateTransform(10, Drawing2D.MatrixOrder.Append) myImageGraphics.TranslateTransform(myImage.Width \ 2, myImage.Height \ 2, Drawing2D.MatrixOrder.Append) myImageGraphics.DrawImage(oldImage, 0, 0) PictureBox1.Invalidate() End Sub Your situation is going to involve creating the main image with an extra strip of cells, as currently, and some error-prone transformation stuff working out exactly which portion of the image to draw in the Paint event, so have fun with that :) The key point is that we only do the 'hard' work (that nested loop that creates the image) when we have to, ie when we scrol to a region we haven't seen before. While examining a portion of the image we *have* created, all we do is just DrawImage. -- Larry Lard Replies to group please
VB.Net 2005 Treeview example required
WebBrowser Databound Radiobuttons Handles keyword. FileStream is adding extra characters padding text field with blank in MS Access vs OLEDB Jet 4.0 Getting icon from form in dynamically loaded DLL Browsers Threading make computer slow Block Step Into Debugging for a function |
|||||||||||||||||||||||