-
Apr 5th, 2013, 08:42 PM
#1
Drawing an image using XNA in VB.Net
A few prerequisites:
- Visual Basic.Net 2010 or higher
- Microsoft XNA 4.0 or higher
Following my prior tutorial, go ahead and add the correct XNA references and Import:
- Microsoft.Xna.Framework
- Microsoft.Xna.Framework.Graphics
The first thing that we will do is declare three(3) variables:
Code:
Private grafix As Graphics.GraphicsDevice = Nothing
Private s_Batch As SpriteBatch
Private sprite As Texture2D
The next step in our process is to start a boolean function. Now in this function, we will try to set up the graphics device. If for whatever reason we fail, in the form_load event an error will be thrown.
Code:
Private Function initialize(ByRef surface As PictureBox) As Boolean
Try
Dim pparam As New PresentationParameters
pparam.DeviceWindowHandle = surface.Handle
pparam.IsFullScreen = False
Dim grafixAdapt As GraphicsAdapter = GraphicsAdapter.DefaultAdapter
grafix = New GraphicsDevice(grafixAdapt, GraphicsProfile.HiDef, pparam)
initialize = True
Catch ex As Exception
initialize = False
End Try
End Function
I explained what that function does in the prior tutorial. The next step is to create a function that will return a texture2d.
Code:
Public Shared Function BitmapToTexture2D(GraphicsDevice As GraphicsDevice, image As System.Drawing.Bitmap) As Texture2D
Dim bufferSize As Integer = image.Height * image.Width * 4
Dim memoryStream As New System.IO.MemoryStream(bufferSize)
image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png)
memoryStream.Seek(0, SeekOrigin.Begin)
Dim texture As Texture2D = Texture2D.FromStream(GraphicsDevice, memoryStream, image.Width, image.Height, False)
memoryStream.Close()
Return texture
End Function
This is important because XNA isn't intended to render bitmaps, it's intended to render texture2d's. Now the main method going on in that function is the Texture2d.FromStream. Now if you aren't paying attention to the prerequisites and using a former version of XNA I believe the method used is the Texture2d.FromFile, the parameters are a bit different, but the concepts the same.
The next step is to actually convert the bitmap to a texture2d:
Code:
Private Sub Load_Content()
If IsNothing(grafix) = False Then
s_Batch = New SpriteBatch(grafix)
sprite = BitmapToTexture2D(grafix, My.Resources.my_image)
Else
Throw New ArgumentNullException("Grafix")
Exit Sub
End If
End Sub
Finally we will use a backgroundworker to continually display our sprite:
Code:
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Do Until True = False
grafix.Clear(Color.CornflowerBlue)
With s_Batch
.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend)
.Draw(sprite, New Rectangle(0, 0, My.Resources.my_image.Width, My.Resources.my_image.Height), Color.CornflowerBlue)
.End()
End With
grafix.Present()
Loop
End Sub
This is where all the action happens. The spritebatch.begin starts the whole process. The spritebatch.draw actually does the rendering. Finally the spritebatch.end brings the state of our device back to the state it was in before we called .Begin. You can think of spritebatch.end as FileStream.Close. The last thing we do is call graphicsdevice.Present, this actually shows the sprite. All in all in the end, it should look like this:
Code:
Option Strict On
Option Explicit On
Imports System.IO
Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Graphics
Public Class Form1
Private grafix As Graphics.GraphicsDevice = Nothing
Private s_Batch As SpriteBatch
Private sprite As Texture2D
Private Function initialize(ByRef surface As PictureBox) As Boolean
Try
Dim pparam As New PresentationParameters
pparam.DeviceWindowHandle = surface.Handle
pparam.IsFullScreen = False
Dim grafixAdapt As GraphicsAdapter = GraphicsAdapter.DefaultAdapter
grafix = New GraphicsDevice(grafixAdapt, GraphicsProfile.HiDef, pparam)
initialize = True
Catch ex As Exception
initialize = False
End Try
End Function
Public Shared Function BitmapToTexture2D(GraphicsDevice As GraphicsDevice, image As System.Drawing.Bitmap) As Texture2D
Dim bufferSize As Integer = image.Height * image.Width * 4
' Create new memory stream and save image to stream so
' we don't have to save and read file
Dim memoryStream As New System.IO.MemoryStream(bufferSize)
image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png)
' Creates a texture from IO.Stream - our memory stream
memoryStream.Seek(0, SeekOrigin.Begin)
Dim texture As Texture2D = Texture2D.FromStream(GraphicsDevice, memoryStream, image.Width, image.Height, False)
memoryStream.Close()
Return texture
End Function
Private Sub Load_Content()
If IsNothing(grafix) = False Then
s_Batch = New SpriteBatch(grafix)
sprite = BitmapToTexture2D(grafix, My.Resources.my_image)
Else
Throw New ArgumentNullException("Grafix")
Exit Sub
End If
End Sub
Private Sub BackgroundWorker1_DoWork(sender As System.Object, e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork
Do Until True = False
grafix.Clear(Color.CornflowerBlue)
With s_Batch
.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend)
.Draw(sprite, New Rectangle(0, 0, My.Resources.my_image.Width, My.Resources.my_image.Height), Color.CornflowerBlue)
.End()
End With
grafix.Present()
Loop
End Sub
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim bool As Boolean = initialize(PictureBox1)
If bool = True Then
Call Load_Content()
BackgroundWorker1.RunWorkerAsync()
Else
MessageBox.Show("There was a problem initializing XNA.")
Me.Close()
End If
End Sub
End Class
Edit - I would like to mention that the busy loop used in this example is not very relevant. Instead, you should use a game loop like the one I made here: http://www.vbforums.com/showthread.p...aged-Game-Loop
Last edited by dday9; Oct 17th, 2016 at 08:25 AM.
-
Apr 10th, 2013, 03:04 PM
#2
Re: Drawing an image using XNA in VB.Net
So this will draw a bitmap to the form using XNA, right? I'm wondering what the point of the backgroundworker is? I wouldn't think you'd have to be redrawing continually unless something else is drawing over your image continually, which may be the case. To draw controls with XNA I had to suppress the paint event for the control as I didn't want GDI to be painting the control when I was painting it.
My usual boring signature: Nothing
 
-
Apr 10th, 2013, 03:23 PM
#3
Re: Drawing an image using XNA in VB.Net
What this does is it draw's a converted texture2d from a bitmap onto a picturebox using the 'game' loop. The reason I keep it in the backgroundworker is because of the 'game' flow concept. See in regular winform's the app assumes that everything stays the same until something is invoked, where as in game app's it assumes that everything is constantly changing. There was an article I read.... <waiting for google> .... When WinForms met the game loop that really helped me out that I think people should read when deciding when to use a 'game' loop and when to just draw in 'WinForm' fashion. So because I'm assuming that most people will visit this thread for game programming in xna I decided to keep it in a continuous loop, or the 'game' loop.
-
Apr 11th, 2013, 09:59 AM
#4
Re: Drawing an image using XNA in VB.Net
Ah, a game running in a window as opposed to a typical WinForms program that spends most of its time doing nothing.
My usual boring signature: Nothing
 
-
Apr 11th, 2013, 10:16 AM
#5
Re: Drawing an image using XNA in VB.Net
 Originally Posted by Shaggy Hiker
Ah, a game running in a window as opposed to a typical WinForms program that spends most of its time doing nothing.
Yep, that was the flow design idea behind these series of tutorials. Something I'd like to mention to those with aspirations of XBox programming is:
A)You cannot port a vb.net xna game to XBox
B)Even if you could, you wouldn't beable to use the BitmapToTexture2D because XBox wouldn't let you.
Microsoft hasn't mentioned anything about allowing VB.Net/XNA games to be ported over to Xbox and to be honest I don't think they'll ever consider it. Reason being is because I'm assuming it would cost thousands of dollars to get Xbox to compile vb.net code.
Last edited by dday9; Apr 11th, 2013 at 10:21 AM.
-
Apr 19th, 2013, 05:31 PM
#6
Re: Drawing an image using XNA in VB.Net
That's kind of ironic, when you think about it. The point behind .NET, originally, was that various people would create JIT compilers for different platforms and you'd be able to take your IL and run it on different platforms. It was the idea behind JAVA, too. Therefore, it's a bit funny that MS decided not to create a JIT compiler for the only platform they totally own.
My usual boring signature: Nothing
 
-
Oct 16th, 2016, 07:23 AM
#7
Member
Re: Drawing an image using XNA in VB.Net
 Originally Posted by dday9
What this does is it draw's a converted texture2d from a bitmap onto a picturebox using the 'game' loop. The reason I keep it in the backgroundworker is because of the 'game' flow concept. See in regular winform's the app assumes that everything stays the same until something is invoked, where as in game app's it assumes that everything is constantly changing. There was an article I read.... <waiting for google> .... When WinForms met the game loop that really helped me out that I think people should read when deciding when to use a 'game' loop and when to just draw in 'WinForm' fashion. So because I'm assuming that most people will visit this thread for game programming in xna I decided to keep it in a continuous loop, or the 'game' loop.
I know this thread is old but...
The GameLoop should not be ran in an infinite. This is very inefficient and eats CPU. It is better to use a type of Timer instead. There are several timers you can use that are available online if you do not want to use any of the built in ones. I personally made my own Timer which is accurate to the microsecond due to there not being an efficient one built in and couldn't find an efficient one elsewhere either.
PS: You could also have done it this way instead (looks cleaner imo):
While true
...
...
End While
-
Oct 16th, 2016, 08:31 PM
#8
Re: Drawing an image using XNA in VB.Net
Oh yeah, trust me I don't use the infinite loop process as shown in this example any longer. I have a game loop contribution somewhere here on VBForums, but I don't know the exact link to point to off hand.
As far as a timer, I would not recommend using the System.Windows.Forms.Timer class for many reasons.
- It is not accurate with lower level intervals like 16.6(60 FPS)
- Resource heavy
- Not consistent among platforms
-
Oct 16th, 2016, 09:59 PM
#9
Member
Re: Drawing an image using XNA in VB.Net
Good to know that isn't being used anymore, and that game loop contribution should be linked imo because the information here is dated and not optimal. I don't mean The forms timer or the thread timer and of of the timers in particular but I meant a form of timer as to imply their efficiency over using an infinite while loop. Although A multimedia timer is pretty accurate down to the millisecond (the others are not real-time, the others while allowing you to set millisecond intervals they only make best efforts to do so). I would be interested in that link with the game loop so I can see what is done there and possible contribute my MicroTimer if no one has presented a good solution yet which is accurate to the micro second and is efficient for anything that doesn't loop faster than 1ms (thus 16.67 is completely doable).
As for Consistency, among platforms what do you mean by that? On linux for example the timers actually tick at the specified intervals. Or do you mean hardware wise as in a machine doesn't have a high performance counter.
-
Oct 17th, 2016, 08:29 AM
#10
Re: Drawing an image using XNA in VB.Net
Good to know that isn't being used anymore, and that game loop contribution should be linked imo because the information here is dated and not optimal.
I've editted the post to include game loop example.
As for Consistency, among platforms what do you mean by that? On linux for example the timers actually tick at the specified intervals. Or do you mean hardware wise as in a machine doesn't have a high performance counter.
I meant hardware wise.
-
Oct 17th, 2016, 09:25 AM
#11
Re: Drawing an image using XNA in VB.Net
I think it is both hardware and software. Right now I can put my hands on three computers whose Timer values and Threading.Sleep values have different periods.
The Threading.Sleep in particular is a disappointment since I would like to have a short sleep (1 to 3 ms) in a background thread, but on two machines I have access to, if you do a Threading.Sleep for anything less than 15 ms, you are going to get up to 16 ms because the Threading.Sleep clock is using the 64hz clock, so will "wake up" on one of the 15.625 ms ticks of the clock, not before.
And even on the same machine, like my business laptop, if I test the period, sometimes it will be the 15.625 period, but other times be a 2 ms period, so obviously some software uses the API to set the clock tick frequency used by windows to drive some of these timers.
And while sometimes it seems like the Threading.Sleep and some timers are tied to the same clock, obviously in other cases they are not (Threading.Sleep can have a much shorter period than the timer).
There are fairly good timing sources, but not so much timer sources.
There is no consistency in Windows for the majority of the timer sources made available to the user.
Last edited by passel; Oct 17th, 2016 at 09:29 AM.
-
Oct 18th, 2016, 09:56 PM
#12
Member
Re: Drawing an image using XNA in VB.Net
Here is my MicroTimer solution I made:
http://pastebin.com/NnvJQCmK
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
|