simple GDI problem

melbmartin
03-12-2006, 11:08 PM
well, I hope that it is a simple problem.

Basically, here is my code in the paint section

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint
'draw background
Dim X, Y As Integer
For X = 0 To 22
For Y = 0 To 22
If Level1.Passable(X, Y) = False Then
e.Graphics.DrawImage(New Bitmap("tiles\mountain.jpg"), X * Level1.Tile.Width, _
Y * Level1.Tile.Height, Level1.Tile.Width, Level1.Tile.Height)
Else
e.Graphics.DrawImage(New Bitmap("tiles\thingrass.jpg"), X * Level1.Tile.Width, _
Y * Level1.Tile.Height, Level1.Tile.Width, Level1.Tile.Height)
End If
Next
Next


'draw character
e.Graphics.DrawImage(New Bitmap("tiles\person.jpg"), Dude.Pos.X, Dude.Pos.Y, Level1.Tile.Width, _
Level1.Tile.Height)
End Sub

basically, when first run, i want the background to be drawn and the character. but then the characters position (dude.pos.x and dude.pos.y) changes when keys are pressed. after the keys are pressed i have me.invalidate()

what is obviously happening is whenever a key is pressed (the character moves), both the background AND the character are reloaded when I only want the character to reload because the background never changes.

hopefully only a simple change is needed. neway, thnx in advance

i thought i might add that this is based on the tile based collision detection tutorial here:

http://www.vbprogramming.8k.com/tutorials/TileBasedCollision.htm

but i enhanced it by having graphics for grass and mountains instead of just diff coloured rectangles and i also added in walls around the outside and random mountains in the middle etc

JNewt
03-13-2006, 11:58 AM
There are a few things that should change. The big one that stands out is the fact that you are loading each tile's bitmap every time you paint! A better way would be to declare bitmap objects like bmpMountain and bmpPerson in the Declarations section of your code and then load the images in the form's Load event. That way you wouldn't have to create a new bitmap and load it from file for each tile.
If the only thing which will change is the player character position, you might think about declaring a big bitmap and drawing the entire map once at load time. Then, in your Paint event, simply draw the big map image, then the player character image.

jo0ls
03-13-2006, 04:19 PM
also,

There is an overload of invalidate, invalidate(rec) that will ask paint to just redraw the bit in the rectangle. The rectangle will need to encompass the area of the current position of the character, and the last position of the character - the previous area needs the background painted over the sprite to erase it, the new area will have the new location. You can put as much as you like in the paint event, if it is not in the rectangle then it isn't drawn.
So , when you first place your character, save his position into two variables, say currentPosition and lastPosition. Before invalidating, work out the rectangle to invalidate. As the character may have moved left, right, up, down, or whatever you need to find the leftmost point of the two positions, and the topmost point of the two positions and so (topmost, leftmost) is the start of the rectangle to invalidate. We also need the width and height. Width is the difference in left positions plus the width of the bitmap, similar for height:


' we have been keeping track of his location with lastPosition, and currentPosition.
If lastPosition.X < currentPositiom.x Then
leftmost = lastPosition
Else
leftmost = currentPosition
End If
' similar for Y positions to get topmost...
width = Math.Abs(lastPosition.x - currentPosition.x) + dudesBitmap.width
' similar to find the height.
' then you can say
Dim rec as Rectangle = New Rectangle(leftmost, topmost, width, height)
Me.Invalidate(rec)


If you are going to have many characters, and are invalidating for each one, then at some point it will be better to draw everything to a bitmap, and draw that to the screen as JNewt said. If there is a fixed background, and only a few moving chars then invalidating is better.

melbmartin
03-13-2006, 05:23 PM
I've done what you suggested....I think JNewt. Is this what you were suggesting? I've had good results. my dude now jumps around from tile to tile with adequate speed. I am yet to put in a timer to make him move around slowly etc but that stuff will come with adding in diff frames of movement etc but that aint important atm.

Dim bmpImage(,) As Bitmap
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
setstyle(ControlStyles.DoubleBuffer, True) 'fixes the flicker
setstyle(ControlStyles.AllPaintingInWmPaint, True) 'fixes the lag, set this to false for a good transition effect
Level1.SetUpTiles()
'stuff from here down is what i changed
ReDim bmpImage(Level1.intColumns, Level1.intRows)
For X = 0 To Level1.intColumns
For Y = 0 To Level1.intRows
bmpImage(X, Y) = New Bitmap(Level1.strTiles(X, Y))
Next
Next
End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

For X = 0 To Level1.intColumns
For Y = 0 To Level1.intRows
e.Graphics.DrawImage(bmpImage(X, Y), X * Level1.Tile.Width, _
Y * Level1.Tile.Height, Level1.Tile.Width, Level1.Tile.Height)
Next
Next
e.Graphics.DrawImage(New Bitmap("tiles\character.jpg"), Dude.Pos.X, Dude.Pos.Y, Level1.Tile.Width, _
Level1.Tile.Height)
End Sub

strTiles is a 2 dimensional array of the file paths for the background. it only has 3 possible values corrisponding to 3 possible images (1 for thin grass, 2 for thick grass, 3 for mountain)

is that pretty much what you suggested or is there an even better way?

after I get this bit down pat im going to work on jo0ls's suggestion which looks like a good one when I get lots of characters on screen.

JNewt
03-14-2006, 11:06 AM
No, that's not really what I had in mind. You have an array of bitmaps to represent your map; this is quite memory expensive. My suggestion is to create one large bitmap (as large as your game's "screen") and render the map (like you were doing originally) to it in the Load event. So something like this: Dim bmpMap as Bitmap
Dim gfxMap as Graphics

Dim bmpCharacter ' this will hold our player character image

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
setstyle(ControlStyles.DoubleBuffer, True) 'fixes the flicker
setstyle(ControlStyles.AllPaintingInWmPaint, True) 'fixes the lag, set this to false for a good transition effect
Level1.SetUpTiles()

bmpMap=New Bitmap(Level1.intColumns*Level1.Tile.Width, Level1.intRows*Level1.Tile.Height)
gfxMap=Graphics.FromImage(bmpMap)
bmpCharacter=New Bitmap("tiles\character.jpg") ' we'll just load it once

' render the entire map
For X = 0 To Level1.intColumns
For Y = 0 To Level1.intRows
gfxMap.DrawImage(New Bitmap(Level1.strTiles(X, Y)), X*Level1.Tile.Width, Y*Level1.Tile.Height)
Next
Next
End Sub

Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles MyBase.Paint

e.Graphics.DrawImage(bmpMap, 0,0)
e.Graphics.DrawImage(bmpCharacter, Dude.Pos.X, Dude.Pos.Y, Level1.Tile.Width, _
Level1.Tile.Height)
End Sub

Private Sub CleanUp
gfxMap.Dispose
bmpMap.Dispose
bmpCharacter.Dispose
End Sub


You'll note that last Sub, CleanUp, call this sub whenever your program is starting to exit (like the form Closing event); it'll release the resources held by our bitmaps and graphics objects.

EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum