Results 1 to 15 of 15

Thread: Graphics Help

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Apr 2012
    Posts
    20

    Graphics Help

    Hello folks.

    Relatively new VB hobbyist programmer here. I've been playing around with an application to make a "Space Invaders" type game --- I actually cut and pasted the code from a post I found on these forums. But the graphics are updating sloooowwwww... The spaceship goes left and right but the background doesn't redraw until you stop moving because the system is chugging along. I was trying to Google some sites for optimizing VB graphics or just plain VB code in general. I found some stuff on VB code --- not a lot but a little. I could find hardly anything on optimizing graphics though. Does anyone have any good tips for how to get graphics to draw faster? I think I'm using either GDI or GDI+ (like I said --- new programmer =)).

    I know I'm trying to run before I learn to walk on VB by jumping into a game so soon but I'm having fun doing this. Really I just looking for A) some tips on optimizing or B) good links I can educate myself further. Any help is appreciated!!!

  2. #2
    eXtreme Programmer .paul.'s Avatar
    Join Date
    May 2007
    Location
    Chelmsford UK
    Posts
    26,413

    Re: Graphics Help

    it might be possible to optimize your code, but we won't know unless you post it...

  3. #3
    Addicted Member
    Join Date
    Nov 2011
    Posts
    223

    Re: Graphics Help

    There used to be templates available on the Microsoft pages one of which was an introduction to games programming and it was called SpaceBlitz Starter Kit.

    I could not find the template on line but found a copy on my HD from a couple of years ago. I don't know how it functions but there is a "Documentation" folder that talks about sprites, keyboard control etc.

    It may be outdated now and thats why I could not locate it online , I don't know, but it may contain something useful for you.
    Attached Files Attached Files

  4. #4
    Lively Member
    Join Date
    May 2010
    Posts
    103

    Re: Graphics Help

    Although I can't see you code, maybe you need to do some double buffering.

    http://www.bobpowell.net/doublebuffer.htm

    On a Form_Load event try this:

    Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    Me.SetStyle(ControlStyles.UserPaint, True)
    Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    Me.UpdateStyles()

    See if that changes anything.

  5. #5

    Thread Starter
    Junior Member
    Join Date
    Apr 2012
    Posts
    20

    Re: Graphics Help

    Thank you for the replies --- I will try the double buffering MotoX646 --- thanks for the tip. And I'll check out SpaceBlitz also --- thanks Mc_VB.

    For Paul's query --- I will post the code a bit later. I am on a work computer now and the file I'm working with is on my laptop back in the room. Basically though, I copied a post in here the said "Need help with my Space Invaders game". I used that code as a starting point. Where I went to with it is pretty much unrecognizable from where I started though (other than maybe the section that takes keyboard input). Last night I got everything working properly ---- ship fires laser, alien gets hit, points update, if alien hits ship - ship disappears and game over pops up. So that was cool --- but the graphics performance still sucks.

    Anyways, I'm getting long winded. I'll try the tip and post my code later (probably tomorrow). Thanks for the help guys!

  6. #6
    PowerPoster boops boops's Avatar
    Join Date
    Nov 2008
    Location
    Holland/France
    Posts
    3,201

    Re: Graphics Help

    Hi Powerstack,

    When you are drawing moving or changing images you need to do it on a double buffered control surface. If you are drawing on a Form (and you are using VB2005+) just set the form's DoubleBuffered property to True (in the Designer or in Code). The SetStyles statements are no longer needed. But double buffering the form doesn't double buffer the form's child controls. If you are drawing on a PictureBox, there is no need to do anything because it's double buffered anyway. Panels can also be made double buffered by inheriting. Ignore the Bob Powell link: apparently he didn't realize the Framework already provided double buffering when he wrote that (2003).

    Still, your description sounds more like a problem with Invalidating/Refreshing. For efficiency invalidate only the dirty rectangles (previous and new positions). Don't use Refresh or Update when dragging because it will just slow things down.

    BB

  7. #7

    Thread Starter
    Junior Member
    Join Date
    Apr 2012
    Posts
    20

    Re: Graphics Help

    Ok, I got the code last night and copied it to my flash drive. It is short and sweet. The code I copied from these forums was much longer but I deleted much of it that I thought was unnecessary and I tinkered with other things until I got the program working right.

    So, here's where I'm at: Double buffering has greatly improved performance, thanks MOTOX646 and boops boops! I still have some graphics issues that are weird --- when the alien comes down the screen, roughly the top 10% of his head is "doubled" --- looks weird. It is the same with your ship when you move it left or right. If you move left then the right 10% of the ship is doubled while you're moving. If you move right then the left 10% of your ship is doubled.

    Ok, one other thing that I just thought of last night that is probably at the heart of all this stuff. When I first installed VB Express 2010 on my laptop, I kept crashing on startup and I would get an error message that "video driver crashed and has recovered". I went online and found that this was a conflict between my Radeon video drivers and Microsoft WPF. So I disabled WPF and the error stopped ---- but I don't remember how I disabled it!!! There's nothing in the VB options... and online it says to check the registry --- the tree leads to a directory called Avalon.graphics --- which I checked my registry and that key isn't even in there. Hrmmmmm, not sure where to go now. Ok, but if you guys want to tell me if you see anything with the code while you're at it, here it is:

    Public Class Board
    'All images created in Microsoft Paint and then imported to PictureBox controls
    'Objects in this program: Board(Space-themed background), Ship(player's ship), Laser(small "beam" graphic), Alien(descends towards player),
    'GameOver(label in center of screen), Score(Label in upperright of background)

    'Possible reason for problems... think I remember having to switch off WPF on VB Express because it was conflicting with Radeon driver? Can't
    'find area to switch it back on and check though --- probably wounldn't matter if I can't use with Radeon anyways - at least on my laptop

    'Problems --- Graphics updating sucks!!! Double buffering has helped but user holding down input key kills all action until user lets up
    'Scoring is not updating properly: When laser hits alien, it is supposed to assign score of 1,000, then get rid of the alien. Instead it
    'counts up to 5 times on the same issue and awards a score of 5,000. Not a huge deal - just don't understand why not working properly

    Dim plScore As Integer = 0

    Private Sub Board_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    tmrMain.Start() 'This is the main clock for the game
    Laser.Visible = False
    GameOver.Visible = False
    Score.Text = "0000000" 'Display Expression of players Score
    Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
    Me.SetStyle(ControlStyles.UserPaint, True)
    Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
    Me.UpdateStyles()

    End Sub

    Private Sub Board_KeyPress(ByVal eventsender As Object, ByVal eventArgs As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
    Dim Input As Short = Asc(eventArgs.KeyChar)
    'In game controls
    Select Case Input
    Case Asc("a")
    Me.Ship.Left = Me.Ship.Left - 10
    Case Asc("d")
    Me.Ship.Left = Me.Ship.Left + 10
    Case Asc("x")
    End
    Case Asc(" ")
    Laser.Visible = True
    Laser.Location = New System.Drawing.Point((Ship.Location.X + 40), Ship.Location.Y - 20)
    End Select
    End Sub

    'This section moves the enemies down, moves you laser Laser up the screen and destroys the alien if you shoot it
    Private Sub tmrMain_tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles tmrMain.Tick
    Me.Alien.Top = Me.Alien.Top + 5
    If Laser.Visible = True Then Laser.Top -= 10
    If Laser.Bounds.IntersectsWith(Alien.Bounds) Then Alien.Visible = False : plScore += 1000 : Score.Text = CStr(plScore)
    If Alien.Bounds.IntersectsWith(Ship.Bounds) And Alien.Visible = True Then Ship.Enabled = False : Ship.Visible = False : GameOver.Visible = True
    End Sub

    End Class

  8. #8
    PowerPoster dunfiddlin's Avatar
    Join Date
    Jun 2012
    Posts
    8,245

    Re: Graphics Help

    user holding down input key kills all action until user lets up
    I suspect this is because you're using the Form_KeyPress event which is notoriously unreliable as a receiver. I suggest that you add all the controls on the form eg.

    vb.net Code:
    1. Private Sub Board_KeyPress(ByVal eventsender As Object, ByVal eventArgs As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress, Control1.KeyPress, Control.Keypress

    This will make sure that any keypress is handled irrespective of where the focus is. (Incidentally, is there any particular reason for departing from the default sender and e variables in the sub definition?)

    'Scoring is not updating properly: When laser hits alien, it is supposed to assign score of 1,000, then get rid of the alien. Instead it
    'counts up to 5 times on the same issue and awards a score of 5,000. Not a huge deal - just don't understand why not working properly
    This one's easy! You don't get rid of the alien you merely make it invisible. Just because you can't see it doesn't mean it's not there and as you're using its bounds rather than any visible property for collision detection it is very much still there.

  9. #9

    Thread Starter
    Junior Member
    Join Date
    Apr 2012
    Posts
    20

    Re: Graphics Help

    Thanks for your response Dunfiddlin.

    To answer your question on whether there was any reason to depart from the default sender and e variables --- I'm afraid I don't know enough about Visual Basic to answer that question =( I cut-and-pasted the code from someone else that posted on the forums and then chopped out the unnecessary bits and switch some code positions around. The event coding is a left over from my cut-and-paste job ---- I really don't know enough about event coding ---- as a matter a fact, I know next to nothing about it other than it pops up when I double-click an object on a form =)

    So your 1st suggestion about adding all the form objects is a bit lost on me --- I might be able to play around with it and figure out what you mean but I can already visualize myself getting frustrated. Still, I'm going to try your suggestion(s) and see if I can figure them out ---- I'm usually clever enough to get myself in trouble at least...

    I have been learning from several different books and probably jumping around too much. But I am having much more fun trying to make a game than I am writing a business application to figure out compound interest... that's for sure!

    So thanks again Dunfiddlin and thanks again to everyone who has responded ---- these forums are great! It's nice to be able to get some advice on what I'm trying to do.

  10. #10

    Thread Starter
    Junior Member
    Join Date
    Apr 2012
    Posts
    20

    The latest

    Ok, let me try this again --- I had posted everything including the new code but then my internet crashed --- <grumble>

    I'm not going to post the code again (mainly because I didn't copy it on to my flash drive and I'm on my work computer). But here's what I've tried so far. Per Dunfiddlin's suggestion, I started focusing on how I was taking user input. I added all the objects in the program to the event handler --- no change. Then I surfed to MSDN to see what they had to say on single key input. They still used the keypress method but their sender (and whatever the 2nd variable after the comma is called) was closer to what Dunfiddlin wondered why I departed from. So I used that... and I axed the 'select case' in favor of if statements using the ASCII code for each character. I figured I was really onto something --- then I compiled and the exact same behavior.... lol, doh!!!!

    Ok... so.... here's what I'm thinking. Tell me if it sounds like I'm on to something. When you move the ship left or right and hold the key down --- the alien stops moving. Haven't checked the laser (should have done that.... will when I head back to the room for the night). But so what I'm wondering is ---- while VB is running the keypress method ---- or any other method I guess ---- can this cause the timertick event to stop or pause? I would think they'd be asynchronous but something's going on....

    The only other thing was I ran across a program called EZInvaders online and they said some users of their programs tried to put an image in the background form and it causes what sounded like the same behavior as I'm having in my program.

    Any thoughts on this??

    I'll keep trying to reserach solutions as well but you guys are just so damn convenient!!! haha, seriously --- I would have never figured out the double buffering thing... and more ideas are always welcome. Tinkering is more fun when you have an idea what to tinker with.... =)

  11. #11
    PowerPoster dunfiddlin's Avatar
    Join Date
    Jun 2012
    Posts
    8,245

    Re: Graphics Help

    while VB is running the keypress method ---- or any other method I guess ---- can this cause the timertick event to stop or pause?
    It most certainly can. If you have loops or recurring events such as keypress when the key is held down it makes sense to add....

    Application.DoEvents()

    ... at strategic points. This ensures that events happen when they're supposed to happen and, perhaps more crucially, that the form is updated.
    As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"

    Reviews: "dunfiddlin likes his DataTables" - jmcilhinney

    Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!

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

    Re: Graphics Help

    Quote Originally Posted by dunfiddlin View Post
    It most certainly can. If you have loops or recurring events such as keypress when the key is held down it makes sense to add....

    Application.DoEvents()

    ... at strategic points. This ensures that events happen when they're supposed to happen and, perhaps more crucially, that the form is updated.
    No, don't do this, it is not necessary. If you need to do something that requires this then you will be hiding a flaw in the program - redesign your program.
    "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."

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

    Re: Graphics Help

    Here's my take of a 'space invaders' in a quick 15 minute hack-up of code:
    Code:
    Public Class Form1
    
        Private WithEvents DisplayTimer As Windows.Forms.Timer
        Private Rand As New Random
        Private monster As Alien
        Private ship As Citizen
        Private laser As Gun
        Private score As Integer
    
        Private Class Alien
            Public Property Visible As Boolean
            Public Property X As Integer
            Public Property Y As Integer
            Public Property Width As Integer
            Public Property Height As Integer
            Public Property Speed As Integer
        End Class
    
        Private Class Citizen
    
            Public Sub New()
                Width = 20
                Height = 10
            End Sub
    
            Public Property X As Integer
            Public Property Y As Integer
            Public Property Width As Integer
            Public Property Height As Integer
        End Class
    
        Private Class Gun
    
            Public Sub New()
                Width = 3
                Height = 8
            End Sub
    
            Public Property visible As Boolean
            Public Property X As Integer
            Public Property Y As Integer
            Public Property Width As Integer
            Public Property Height As Integer
        End Class
    
    
        Public Sub New()
            ' This call is required by the designer.
            InitializeComponent()
            ' Add any initialization after the InitializeComponent() call.
            Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
            Me.SetStyle(ControlStyles.UserPaint, True)
            Me.SetStyle(ControlStyles.AllPaintingInWmPaint, True)
            Me.UpdateStyles()
        End Sub
    
        Private Sub Board_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
            DisplayTimer = New Windows.Forms.Timer
            monster = New Alien
            ship = New Citizen
            laser = New Gun
            ship.X = Me.ClientSize.Width \ 2
            ship.Y = Me.ClientSize.Height - 20
            DisplayTimer.Interval = 30
            DisplayTimer.Enabled = True
        End Sub
    
        Protected Overrides Sub OnKeyDown(e As System.Windows.Forms.KeyEventArgs)
            MyBase.OnKeyDown(e)
            If e.KeyCode = Keys.A Then
                ship.X -= 10
            ElseIf e.KeyCode = Keys.D Then
                ship.X += 10
            ElseIf e.KeyCode = Keys.Space Then
                If laser.visible = False Then
                    laser.X = ship.X + ship.Width \ 2 - laser.Width \ 2
                    laser.Y = ship.Y - laser.Height
                    laser.visible = True
                End If
            End If
        End Sub
    
        Protected Overrides Sub OnResize(e As System.EventArgs)
            MyBase.OnResize(e)
            Me.ship.Y = Me.ClientSize.Height - 20
        End Sub
    
        Private Sub DisplayTimer_Tick(sender As Object, e As System.EventArgs) Handles DisplayTimer.Tick
            If monster.Visible Then
                monster.X += monster.Speed
                If monster.X > Me.ClientSize.Width Then monster.Visible = False
            Else
                monster.Visible = True
                monster.Width = Rand.Next(20, 40)
                monster.Y = Rand.Next(0, 100)
                monster.Height = Rand.Next(10, 20)
                monster.Speed = Rand.Next(1, 10)
                monster.X = -monster.Width
            End If
            '
            If laser.visible Then
                Dim oldY As Integer = laser.Y
                laser.Y -= 10
                If laser.Y + laser.Height < 0 Then laser.visible = False
                ' Check for collision
                Dim r As New Rectangle(laser.X, laser.Y, laser.Width, laser.Y - oldY + laser.Height)
                If r.IntersectsWith(New Rectangle(monster.X, monster.Y, monster.Width, monster.Height)) Then
                    ' HIT
                    monster.Visible = False
                    laser.visible = False
                    score += 1
                End If
            End If
            ' perform a redraw
            Me.Invalidate()
        End Sub
    
        Protected Overrides Sub OnPaint(e As System.Windows.Forms.PaintEventArgs)
            MyBase.OnPaint(e)
            ' draw the monster
            If monster.Visible Then e.Graphics.FillRectangle(Brushes.Red, monster.X, monster.Y, monster.Width, monster.height)
            ' draw the ship
            e.Graphics.FillEllipse(Brushes.DarkBlue, ship.X, ship.Y, ship.Width, ship.Height)
            ' draw the laser
            If laser.visible Then e.Graphics.FillRectangle(Brushes.Green, laser.X, laser.Y, laser.Width, laser.Height)
            ' draw the score
            e.Graphics.DrawString(score.ToString, Me.Font, Brushes.Black, 0, 0)
        End Sub
    
    
    End Class
    "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."

  14. #14
    PowerPoster dunfiddlin's Avatar
    Join Date
    Jun 2012
    Posts
    8,245

    Re: Graphics Help

    Yes, well, sometimes maybe it's not such a bad idea to cover up the 'flaws' in your program! Your code, ironically, starts with an unhandled exception (well several actually) and, more pertinently, when edited to make it work, can't fire and move at the same time (oh, and on one occasion I swear the 'bullet' passed straight through the middle of an 'alien' and had no effect on it whatsoever but that could just be my eyes). Right now, I'm not recommending it as a learning experience if that's ok.
    As the 6-dimensional mathematics professor said to the brain surgeon, "It ain't Rocket Science!"

    Reviews: "dunfiddlin likes his DataTables" - jmcilhinney

    Please be aware that whilst I will read private messages (one day!) I am unlikely to reply to anything that does not contain offers of cash, fame or marriage!

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

    Re: Graphics Help

    Quote Originally Posted by dunfiddlin View Post
    Yes, well, sometimes maybe it's not such a bad idea to cover up the 'flaws' in your program! Your code, ironically, starts with an unhandled exception (well several actually) and, more pertinently, when edited to make it work, can't fire and move at the same time (oh, and on one occasion I swear the 'bullet' passed straight through the middle of an 'alien' and had no effect on it whatsoever but that could just be my eyes). Right now, I'm not recommending it as a learning experience if that's ok.
    Regardless, telling people to do the wrong thing to hide their mistakes, I'll take your 'recommendation' with the due consideration it deserves.

    The 'example' isn't about how to create a working invaders game, but how to correctly program graphics. The keyboard event(s) are functioning as designed: no amount of do-events or any shenanigans will correct that problem. Since graphics are the basic issue, the keypress issue can be corrected at a later point (it requires an Win32 API call, if I recall, but there may be a .NET equivalent).

    To reiterate, the above code is for demonstration, not production code. But if you feel you can do better, go ahead and do so. I'm open to learning better ways of doing things in .NET.
    "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."

Tags for this Thread

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