Is there a faster way to render alot of pictures using the Graphics object?

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
Hello everyone,<br/>
<br/>
Im making a copy of Terraria (2D-adventure game) in VB as a personal project.<br/>
While I can play Terraria in fullscreen on high quality, with a high framerate. I only get 5 frames per second in my game.<br/>
<br/>
Im using 16px by 16px images for the tiles. My screen has a resolution of 16:9 (1600x900).<br/>
The world is 160x160 tiles this obviously is way bigger then my screen in pixels so I am using some custom code to set up the reder x, y, width and height.<br/>
Using this I can get the frames per second up by setting the render width, height to only 20 frames.
<br/>
But when playing u need to render more tiles. <br/>
So I have set the render width and height to my screen resolution wich is around 100x60<br/>
<br/>
Im using offscreen rendering in a bitmap to stop the flickering. <br/>
I will post my a part of my rendering code below. But my question now is: Is there a better way to render it with only VB? Because Terraria is made in C# & XNA.<br/>
Question2: If I would render with a DirectX wrapper for .Net or XNA would I get more frames per second?<br/>
<br/>
Now here is the code for rendering:<br/>

<pre class="prettyprint lang-vb The main loop running in a seperated thread
While (Running)
Application.DoEvents()

Tick()
Render()

Thread.Sleep(reducedCpuUsage) this is 0 or 1
End While[/code]
<br/>
Now lets go into the Render()<br/>

<pre class="prettyprint lang-vb Public Sub Render()
Screen is a bitmap with the same size as the render width, height
Rendering it offscreen
Dim g As Graphics = Graphics.FromImage(screen)

The smoothingMode is set to high speed
g.SmoothingMode = frmMain.SmoothingMode

Telling the world it should render it using our graphics object
wrld.Render(g)

Setting the graphics object to the form
g = Me.CreateGraphics()
Setting the smoothingmode to high speed
g.SmoothingMode = frmMain.SmoothingMode

Drawing the screen bitmap (used for offscreen rendering) to the screen
g.DrawImage(screen, 0, 0)

Disposing the graphics object (:
g.Dispose()
End Sub[/code]
<br/>
Lets go into wrld.Render(g as graphics) (:<br/>

<pre class="prettyprint lang-vb Public Sub Render(g As Graphics)
Drawing a blue screen as background
g.DrawImage(Tile.Background,
0, 0,
CInt(Camera.Vision.Width * Tile.TileSize),
CInt(Camera.Vision.Height * Tile.TileSize)
)

Getting the camera object wich holds the render X, Y, Width, Height
c.X = render x
c.Y = render y
c.Vision.Width = render width
c.Vision.Height = render Height
Dim c As Camera = frmMain.Current.p.Cam

WorldWidth = amount of tiles in the width
WorldHeight = amount of tiles in the height
For x As Int32 = c.X - 1 To Camera.Vision.Width + c.X
For y As Int32 = c.Y - 1 To Camera.Vision.Height + c.Y

Make sure we are not rendering outside the world bounds
If (x > -1 And x < WorldWidth And y > -1 And y < WorldHeight) Then

The tile render method
level(x, y).Render(g)
End If

Next
Next
End Sub[/code]
Lets go into the level(x, y).Render(g)
<pre class="prettyprint lang-vb Public Sub Render(g As Graphics)

Getting the camera object
Dim c As Camera = frmMain.Current.p.Cam

Drawing the image to the offscreen bitmap
g.DrawImage(bufferedImage, New Point((Me.X - c.X) * Tile.TileSize, (Me.Y - c.Y) * Tile.TileSize))
End Sub

The Init() method is to get create the bufferedImage
Note this only gets called when the image needs to change or when the object
get created.
Public Sub Init()
Locking the tileset object (static/shared)
Im creating threads for code that has to do alot of loops etc so I wont lose more frames.
And sometimes they both want to acces this at the same time
Monitor.Enter(Tile.DirtTileSet)
Try
The GetGraphics func is just for getting the graphics of the bufferedImage
Dim g As Graphics = GetGraphics()
Making the rectangles to cut an image
Dim destRect As New Rectangle(0, 0, Tile.TileSize, Tile.TileSize)
Dim srcRect As New Rectangle(Info.Id(0) * (Tile.TileSize + Tile.TileSetSpacing), Info.Id(1) * (Tile.TileSize + Tile.TileSetSpacing), Tile.TileSize, Tile.TileSize)

Drawing the image to the bufferendImage bitmap
g.DrawImage(Tile.DirtTileSet, destRect, srcRect, GraphicsUnit.Pixel)

Disposing our graphics
g.Dispose()
Finally
releasing the tileset
Monitor.Exit(Tile.DirtTileSet)
End Try
End Sub[/code]
<br/>
Note my computer has a Dual Core 2.1 Ghz CPU (this might be the reason why I have such low frames per second)<br/>
<br/>
Thank you for helping me or giving me suggestions! (: <hr class="sig Hope This Helps! <br/>
<br/>
If this post answers your question, please click <b>"Mark As Answer"</b>.<br/>
If this post is helpful please click <b>"Mark as Helpful"</b>.<br/>
Else you got to wait until a MVP or MCC replies they are the <b>"PROs"
</b><br/>

View the full article
 
Back
Top