I am having problems with flickering when drawing squares to a picture box. Heres my main form code:
Code:
Public Class FrmGame
Public ArrayBlocks(15, 30) As Block
Public BlockSize As New Size(15, 15)
Private Sub FrmGame_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'Reduce Flicker'
SetStyle(ControlStyles.DoubleBuffer, True)
SetStyle(ControlStyles.AllPaintingInWmPaint, True)
End Sub
Private Sub FrmGame_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
'Draw Game Board To Picture Box'
Dim GameBoard As New GameBoard
GameBoard.Draw(ImgMain.Handle)
'Draw First Line Of Blocks To Picture Box'
Dim X As Integer
Dim Color1 As Color = Color.Blue
Dim Color2 As Color = Color.LightBlue
Dim InitialLoc As New Point(0, 0)
For X = 0 To 14
ArrayBlocks(X, 0) = New Block(BlockSize, InitialLoc, Color1, Color2)
ArrayBlocks(X, 0).Draw(ImgMain.Handle)
'Update Initial Location'
InitialLoc.X += 15
'Change Block Colors'
If Color1 = Color.Blue And Color2 = Color.LightBlue Then
Color1 = Color.Red
Color2 = Color.Yellow
Else
Color1 = Color.Blue
Color2 = Color.LightBlue
End If
Next X
Me.Invalidate()
End Sub
End Class
The Rectangle which is my game board is drawn as per normal no flickering, however when the 15 blocks/squares are drawn they are all flickering for some reason. I may be doing something wrong as until now i've been creating basic games with picture boxes. If anyone has any advice i would appreciate it greatly.
I have also attached a picture of the outcome of what i'm drawing.
I have just noticed with this, if I use the code in a button it draws once and doesn't flicker. However if i do it in the Form_Load even it doesn't draw anything at all.
Honestly, it may be time to set aside GDI+ draw methods and step up to either Managed DirectX or XNA Game Studio. Personally, I know XNA can easily make the game you're trying to make in probably about two pages of code.
Could you also advise the limits of using gdi+ as this is the first game i have started making using gdi and straight away i have ran into this problem.
You're looking at the limits. GDI+ is a 100% software-based system that is designed to paint controls on static forms. It's not hardware accelerated at all and isn't optimized for even the simplest animations. There's no guarantee on the speed of the refresh. Refresh is typically whenever Windows decides that it would be best to refresh it. Even forced refreshes can take their own sweet time of several milliseconds to happen. On top of it all, there is typically a lot of overdraw.
GDI+ is good for some games though. Games that don't involve a lot of animation that is. Card games, turn-based strategy games, etc. Arcade games? Not at all.
Download XNA Game Studio 3.0. Just Google it and you will find it. A good site to learn how to use it is here. If you want a game to pull apart and see how it works, download my Tetris game in my signature. If you follow the tutorials on that above site, it'll show you how to make a working Bust-a-Move/Puzzle Bobble style game. If you've come this far with understanding GDI+, this won't be hard at all for you to pick up.
If you have any questions, post them here.
Getting started, the first move you should do is convert your Form object into an XNA Game object. The Game object contains special routines that handle drawing the screen and since XNA directly talks with DirectX, it's extremely fast.
The reason your image is flickering is because you have put Me.Invalidate in the Paint event handler. Invalidate is a way of saying "please fire the Paint event as soon as possible". It's a small wonder your program doesn't lock up altogether .
I have started making my game after running through some XNA tutorials but have run into a problem.
Firstly Here is my class for creating blocks:
Code:
Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Graphics
Public Class Block
'Define Block Objects'
Public BlockSB As SpriteBatch = New SpriteBatch(Device)
Public BlockTex As Texture2D = Nothing
Public BlockRect As Rectangle = Nothing
Public BlockTexCreationParams As TextureCreationParameters = TextureCreationParameters.Default
'Define Block Variables'
Public CanShoot As Boolean = True
Public BlockSize As New Size(25, 25)
Public BlockColor As String
Public BlockPosition As Point
Public Sub CreateBlock()
BlockTex = Texture2D.FromFile(Device, "../../Resources/" & BlockColor & "Block.png", BlockTexCreationParams)
BlockRect.Height = BlockSize.Height
BlockRect.Width = BlockSize.Width
BlockRect.X = BlockPosition.X
BlockRect.Y = BlockPosition.Y
End Sub
Public Sub New(ByVal InitialColor As String, ByVal InitialPosition As Point)
BlockColor = InitialColor
BlockPosition = InitialPosition
End Sub
End Class
Next this is my code which i am using to set up new blocks in a 2dimensional array:
Code:
Private Sub SetUpInitialBlocks()
Dim Color As String = "Black"
'First Row'
For i As Integer = 0 To 9
Blocks(i, 0) = New Block(Color, StartLoc)
Blocks(i, 0).CreateBlock()
If Color = "Black" Then
Color = "Red"
Else
Color = "Black"
End If
Next
End Sub
Then this is my code for rendering graphics:
Code:
Private Sub Render()
If Device Is Nothing Then Return
'Clear The Back Buffer To Black'
Device.Clear(ClearOptions.Target, Microsoft.Xna.Framework.Graphics.Color.Black, 1.0F, 0)
'Draw All Non Block Textures'
NonBlockSB.Begin(SpriteBlendMode.AlphaBlend)
NonBlockSB.Draw(FrameTex, FrameRect, Color.White)
NonBlockSB.Draw(GameBoardTex, GameBoardRect, Color.White)
NonBlockSB.End()
'Draw Starting Blocks'
For X As Integer = 0 To 9
For Y As Integer = 0 To 14
Blocks(X, Y).BlockSB.Begin(SpriteBlendMode.AlphaBlend)
Blocks(X, Y).BlockSB.Draw(Blocks(X, Y).BlockTex, Blocks(X, Y).BlockRect, Color.White)
Blocks(X, Y).BlockSB.End()
Next Y
Next X
Device.Present()
End Sub
When it gets to rendering the blocks in the render sub i am getting the following error message referring to the block i am trying to draw:
Object reference not set to an instance of an object.
Im not sure why its throwing this message as i have the SetUpInitialBlocks Sub which is used to create the new blocks.
I may be doing something completely wrong here as i have only just started with the XNA as advised above so if anyone has any suggestions i would appreciate it greatly.
Oh, simple. You're only defining the first row of blocks in SetUpInitialBlocks(). Blocks(0,0) through Blocks(0,9).
But when your Render routine runs, it'll hit Blocks(0,1), which doesn't have a Block object defined for it because it's still set to Nothing and thus will give your Object reference error.
Add in the code:
Code:
If Blocks(X, Y) IsNot Nothing Then
Right after the "For Y" line in your Render routine. That will skip any undefined elements in your 2-dimensional array.
Likewise, since your Blocks objects define their own locational coordinates, you really may not need to run the whole board array in the Render object. If you made a generic List (Of Block), and only stored defined blocks in that list, you would only need to cycle through that list using something like:
Code:
For Each b As Block in MyBlockList
b.BlockSB.Begin(SpriteBlendMode.AlphaBlend)
b.BlockSB.Draw(Blocks(X, Y).BlockTex, Blocks(X, Y).BlockRect, Color.White)
b.BlockSB.End()
Next
The only thing that you may be doing wrong that I can see of in your methodology is you're creating a separate SpriteBatch with each block object. Typically, in a game, you only make one SpriteBatch and process it in the Render loop.
Not to say this won't work, it may work beautifully. Just never seen it done like this before. I see no reason why it wouldn't work.