|
-
May 1st, 2009, 11:33 AM
#1
Thread Starter
Hyperactive Member
[RESOLVED] Choppy Movement in GDI
I have 22 30x30 shapes(players) moving around a simulated football field. This is the culmination of 2 years of basement hobby work and it looks pretty good except for some choppy movement. With 11 shapes moving around it really looks good, but doubling the load causes the flicker to be noticeable.
I have double-buffered the control that does the drawing and that helped immensely, but I'm looking for another way to improve the invalidation speed.
For each tick of the timer I basically calculate the positions of the "players" before and after they move and then invalidate the those rects, then I call Update() to force the drawing. This process repeats until the play is over.
Besides double-buffereing is there any tricks to try?
Last edited by neef; May 1st, 2009 at 11:01 PM.
Intermediate Level Programmer Extraordinaire 
-
May 1st, 2009, 11:47 AM
#2
Re: Choppy Movement in GDI
If you use doublebuffering there should be no flicker. Are you sure you mean flicker? Moving 30 shapes around a screen should have very little load on the CPU, so I suspect there may be something in how you are doing the drawing.
Also, are you sure you mean Update and not Invalidate? Invalidate is what you would use, passing in your invalidation region (i.e. all those rectangles) as a parameter.
How fast are you updating the screen?
"Ok, my response to that is pending a Google search" - Bucky Katt.
"There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
"Before you can 'think outside the box' you need to understand where the box is."
-
May 1st, 2009, 12:17 PM
#3
Thread Starter
Hyperactive Member
Re: Choppy Movement in GDI
I invalidate one rect at a time (x22 players on the field, x2 for before and after positions for each player) for every tick of the clock and then call update between ticks.
Should I group all those rects into a collection and just call invalidate once per tick? Maybe there's an overload of invalidate that does this that I've never used before. (I'd look online but I'm at work at my day job).
I felt the way I'm doing it is so basic it's wasting CPU effort.
As far as update speed I believe I'm going for 1/20 a second, but once again I'm at work and can't remember for certain.
Thanks for the help.
Intermediate Level Programmer Extraordinaire 
-
May 1st, 2009, 01:20 PM
#4
Re: Choppy Movement in GDI
You only need a single Invalidate. In your 'tick' event, you'd perform all calculations on every object, then, once complete, call the invalidate event.
Usually, I start off by performing a full invalidate (i.e. redraw the whole canvas). If performance starts to suffer then I'd start looking at proper invalidate regions.
Here's a little 'balls' program I have as a quick graphical test:
Code:
Public Class Form1
Private Class Ball
Public Direction As Point
Public Bounds As Rectangle
End Class
Private WithEvents CalculationTimer As Windows.Forms.Timer
Private Const BallCount As Integer = 100
Private Balls As List(Of Ball)
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
' Prevent flickering
Me.DoubleBuffered = True
'
' create a list of balls
Dim rnd As New Random
Balls = New List(Of Ball)
For i As Integer = 0 To BallCount - 1
Dim w As Integer = 10 + rnd.Next(0, 31)
Dim h As Integer = w
Dim x As Integer = rnd.Next(0, Me.ClientSize.Width)
Dim y As Integer = rnd.Next(0, Me.ClientSize.Height)
Dim incX As Integer = rnd.Next(0, 9) - 4
Dim incY As Integer = rnd.Next(0, 9) - 4
Dim b As New Ball
b.Bounds = New Rectangle(x, y, w, h)
b.Direction = New Point(incX, incY)
Balls.Add(b)
Next
' Create the calculation timer
CalculationTimer = New Windows.Forms.Timer
CalculationTimer.Interval = 25
CalculationTimer.Start()
'
End Sub
Private Sub Form1_Paint(ByVal sender As Object, _
ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
' Smooth ball
e.Graphics.SmoothingMode = Drawing2D.SmoothingMode.HighQuality
For Each b As Ball In Balls
' Fill color
e.Graphics.FillEllipse(Brushes.SkyBlue, b.Bounds)
' Border color
e.Graphics.DrawEllipse(Pens.Black, b.Bounds)
Next
End Sub
Private Sub CalculationTimer_Tick(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles CalculationTimer.Tick
'
For Each b As Ball In Balls
' Move the ball
b.Bounds.Offset(b.Direction)
' Check Left
If b.Bounds.X < 0 Then
b.Bounds.X = 0
b.Direction.X = Math.Abs(b.Direction.X)
End If
' Check Top
If b.Bounds.Y < 0 Then
b.Bounds.Y = 0
b.Direction.Y = Math.Abs(b.Direction.Y)
End If
' Check Right
If b.Bounds.Right >= ClientSize.Width Then
b.Bounds.X = ClientSize.Width - b.Bounds.Width
b.Direction.X = -Math.Abs(b.Direction.X)
End If
' Check Bottom
If b.Bounds.Bottom >= ClientSize.Height Then
b.Bounds.Y = ClientSize.Height - b.Bounds.Height
b.Direction.Y = -Math.Abs(b.Direction.Y)
End If
Next
'
' Redraw
Me.Invalidate()
End Sub
End Class
The timer tick event fires off a full invalidate after recalculating the positions for 100 balls. I'm sure your calculations are a bit more complex. I'm also (trying) to update every 25mS.
Last edited by SJWhiteley; May 1st, 2009 at 01:23 PM.
"Ok, my response to that is pending a Google search" - Bucky Katt.
"There are two types of people in the world: Those who can extrapolate from incomplete data sets." - Unk.
"Before you can 'think outside the box' you need to understand where the box is."
-
May 1st, 2009, 03:39 PM
#5
Re: Choppy Movement in GDI
I'd seriously start looking at managed DirectX or XNA though if I were you neef. They're not very hard at all to pick up and their performance is HUGE compared to GDI+
-
May 1st, 2009, 04:46 PM
#6
Thread Starter
Hyperactive Member
Re: Choppy Movement in GDI
Thanks for the code SJ - I knew I was missing something the way I was doing it. One thing I do differently is I calculate all the movement points before I start moving anything; I store it in List(of ) collections and then just cycle through it. My fear was all the complex physics equations would slow things down, so why not do it all before the players move?
Jenner: I was wondering if someone would recommend DirectX. I'll have to look into this.
I'll implement the new code soon and report back here how it goes in a day or too. Thank you both very much.
Intermediate Level Programmer Extraordinaire 
-
May 1st, 2009, 11:00 PM
#7
Thread Starter
Hyperactive Member
Re: Choppy Movement in GDI
Wow! Using one invalidate is much better. I would think you'd try to limit the amount of screen that needed to be redrawn by specifying specific areas, but apparantly the overhead of doing that is much higher than just redrawing the entire thing.
Maybe this is the double-buffering working? I don't know.
Anyway, I'm all set now with that simple alteration. Thanks very much.
Intermediate Level Programmer Extraordinaire 
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|