Results 1 to 7 of 7

Thread: [RESOLVED] Choppy Movement in GDI

  1. #1

    Thread Starter
    Hyperactive Member neef's Avatar
    Join Date
    Dec 2001
    Location
    Boston
    Posts
    311

    [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

  2. #2
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    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."

  3. #3

    Thread Starter
    Hyperactive Member neef's Avatar
    Join Date
    Dec 2001
    Location
    Boston
    Posts
    311

    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

  4. #4
    PowerPoster SJWhiteley's Avatar
    Join Date
    Feb 2009
    Location
    South of the Mason-Dixon Line
    Posts
    2,256

    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."

  5. #5
    PowerPoster Jenner's Avatar
    Join Date
    Jan 2008
    Location
    Mentor, OH
    Posts
    3,712

    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+
    My CodeBank Submissions: TETRIS using VB.NET2010 and XNA4.0, Strong Encryption Class, Hardware ID Information Class, Generic .NET Data Provider Class, Lambda Function Example, Lat/Long to UTM Conversion Class, Audio Class using BASS.DLL

    Remember to RATE the people who helped you and mark your forum RESOLVED when you're done!

    "Two things are infinite: the universe and human stupidity; and I'm not sure about the universe. "
    - Albert Einstein

  6. #6

    Thread Starter
    Hyperactive Member neef's Avatar
    Join Date
    Dec 2001
    Location
    Boston
    Posts
    311

    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

  7. #7

    Thread Starter
    Hyperactive Member neef's Avatar
    Join Date
    Dec 2001
    Location
    Boston
    Posts
    311

    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
  •  



Click Here to Expand Forum to Full Width