RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
Go Back  Xtreme Visual Basic Talk > > > RPG Dynamic Bitmap Class


Reply
 
Thread Tools Display Modes
  #1  
Old 07-09-2013, 08:40 AM
ephestion ephestion is offline
Newcomer
 
Join Date: Aug 2006
Posts: 10
Default RPG Dynamic Bitmap Class


I have some basic knowledge of BitBlt methods but I am trying to learn some of VB.Net approaches to Graphics manipulations.

I don't want to BitBlt or use XNA or DirectX API calls etc.

I found a nice class module called DynamicBitmap here:
http://www.vbforums.com/showthread.p...nd-pathfinding

The module is very good and works flawlessly so far. It even has some pathfinding and other things in it. The part I need for the moment is a simple yet effective way to move around a map.

I have tried various methods but seem to always leave artifacts in the screen of the player image as a trail or in other experiements the map underneath the player's image is rubbed out. I have also run into a problem where the picture box loses it's image/bitmap when some action is performed.

So is there a very simple lean project/solution that demonstrates how to move around a map in VB.Net. The class I am using is DynamicBitmap, and would prefer an example using that class module. It has alphablending for fog of war, which works well, transparent management and is really very good for my purposes. But for the life of me I just cant get a character to move around the map.

Please take a look at the linked class module or visit a tutorial site here to understand:
http://www.visual-basic-tutorials.com/PicRendering3.php

I want to use this module but have no idea how to get it to work for moving a character around the map and doing graphical manipulations.

If I get over this hurdle I will be able to focus on more important things. Any help is appreciated.
Reply With Quote
  #2  
Old 07-12-2013, 06:16 AM
ephestion ephestion is offline
Newcomer
 
Join Date: Aug 2006
Posts: 10
Default

Sorted it out partially.

With this class module I am able to store and restore the grid background. I do this just before applying the sprite changes. Because I am drawing to the form and then updating a picture box, I seem to be getting a buffering without need to apply masks.

Code:
Case Keys.Down
                'DownKey = True
                gPlayerWalking = True
                piX = (aGrid.TileColumn(gPlayerLoc) * gTileWidth) - gTileWidth
                piY = (aGrid.TileRow(gPlayerLoc) * gTileHeight) - gTileHeight + 1
                gPlayerDest = gPlayerLoc + 30
                gPlayerLoc = gPlayerLoc + 30
                'Restore the Grid as it was initially saved
                aGrid.ImageRestore()
                'Update the sprite, Fog and redraw screen
                DrawSprite(2)
                DrawFOG()
                DrawScreen()
                'Set the picture box to use the image in buffer.
                picMap.Image = aGrid.Bitmap
Because I am using a Grid class all the drawing and stuff is based on a Tile count left to right. eg 0,0 px position is actually a rectangle at point 0,0 but called Tile number 1. The Grid I use is 30 tiles wide and 30 tiles high, so the Global variable gPlayerLoc needs to add 30 (30 tiles from current position) to drop to the next row of tiles.

This is all good and working. But now I want to animate the sprite. I want to press key down for example, then the sprite does goes through some walking frames and also moves 1 pixel at a time to the required destination. I know with BiBlt API it is easily done, but what I want to explore VB.Net managed code without getting into full blown DirectX or XNA programming.

How can I animate an object in VB.Net using its Graphics managed code? But at the same time make use of my Grid system. I want the Sprite to move to the next Grid in animated fashion but when they arrive to destination to update the Grid. Best example I can think of is like the way the Civilization games work. You press a key, the sprite animates and moves to the required location and stops. I don't want to stack calls when the key is pressed either ie some kind of lock while moving. Otherwise if a player keeps the button pressed and the move hasn't finished, they may likely make another move based on some Windows que.

If this forum is dead, can someone please tell me since it was about a week since my last post and I had no reply.

Thanks.

This is the sample code that plugs into a normal Windows Forms Application Form.
Quote:
Code:
Public Class Form1



    Dim aTileSheet As New DynamicBitmap
    Dim aGrid As New DynamicBitmap
    Dim aSprite As New DynamicBitmap
    Dim aBlackSquare As New DynamicBitmap
    Dim gPlayerLoc As Integer
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        gPlayerLoc = 1
        aGrid.CreateBitmap(960, 960)
        aSprite.CreateBitmap(19, 32)
        aSprite.LoadBitmap("C:\temp\tilesets\sprite.png", 19, 32)
        aTileSheet.LoadBitmap("C:\temp\tilesets\test5.bmp", 32, 32)
        aSprite.MakeTransparent()
        aBlackSquare.CreateBitmap(32, 32)
        aBlackSquare.Clear(Color.Black)
        aBlackSquare.AlphaBlend()


        aGrid.CreateBitmap(960, 960)
        aGrid.CreateGrid(32, 32, 30, 30)
        For i As Integer = 1 To aGrid.TileCount
            aGrid.DrawOnSurface(aTileSheet.Bitmap, aTileSheet.Rectangle(1), aGrid.Rectangle(i))
        Next

        If aGrid.Exists Then MessageBox.Show(aGrid.TileCount)
        aGrid.ImageStore()

    End Sub



    Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        Dim intX As Integer
        Dim intY As Integer
        aGrid.ImageRestore()
        intX = aGrid.TileColumn(gPlayerLoc)
        intY = aGrid.TileRow(gPlayerLoc)
        gPlayerLoc = gPlayerLoc + 30
        aGrid.FillTile(aGrid.Tile(e.X, e.Y), Color.Red, True)
        PictureBox1.Image = aGrid.Bitmap
        DrawSprite()
        DrawScreen()




    End Sub





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

        DrawScreen()

    End Sub



    Public Sub DrawScreen()

        Dim G As Graphics = Me.CreateGraphics
        G.DrawImage(aGrid.Bitmap, New Point(0, 0))

    End Sub


    Sub DrawSprite()
        aGrid.DrawOnSurface(aSprite.Bitmap, aSprite.Rectangle(5), aGrid.Rectangle(gPlayerLoc), False, True)
    End Sub
End Class
Reply With Quote
  #3  
Old 07-12-2013, 05:17 PM
passel's Avatar
passelRPG Dynamic Bitmap Class passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,018
Default

The grid class isn't setup to move sprites by pixel.
Instead of using the aGrid.DrawOnSurface to draw the sprite, you should probably just draw it on the form after you drawn the aGrid.bitmap.
If you do it that way you don't have to worry about saving and restoring aGrid.bitmap using the built in functions because you won't be drawing on it.
You would have to calculate the pixel offsets and animation frame, of course, but you would remove the DrawSprite call from the MouseDown event, and the DrawScreen would look like this
Code:
    Public Sub DrawScreen()

        Dim G As Graphics = Me.CreateGraphics
        G.DrawImage(aGrid.Bitmap, New Point(0, 0))
        G.DrawImage(aSprite.Bitmap,Sprite.X, Sprite.Y)  'draw at the pixel location you determine
    End Sub
Actually doing "Dim G as Graphics = Me.CreateGraphics" as you are here is a bad thing to do. I know that was the example the author gave, but it is not good.

You should just invalidate the form when you want to redraw the screen and use the Graphics object provided in the Paint event.
Code:
    Private Sub Form1_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
        Dim intX As Integer
        Dim intY As Integer
        aGrid.ImageRestore()
        intX = aGrid.TileColumn(gPlayerLoc)
        intY = aGrid.TileRow(gPlayerLoc)
        gPlayerLoc = gPlayerLoc + 30
        aGrid.FillTile(aGrid.Tile(e.X, e.Y), Color.Red, True)
        PictureBox1.Image = aGrid.Bitmap
        Me.Invalidate()    'have the form redraw itself
    End Sub

    Private Sub Form1_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
        DrawScreen(e.Graphics)   'pass the provided Graphics object to the draw routine
    End Sub

    Public Sub DrawScreen(G as Graphics)
        G.DrawImage(aGrid.Bitmap, New Point(0, 0))
        G.DrawImage(aSprite.Bitmap,Sprite.X, Sprite.Y)  'draw at the pixel location you determine
    End Sub
You probably don't need the picturebox either. Just set the "DoubleBuffered" property to "True" for the Form in the IDE.

Possibly the attachment in this post might be of interest, but it is neither a tile based example nor dealing with animation so is not directly relevant.
This post has some simple two phase animation, but still no tile map.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.

Last edited by passel; 07-12-2013 at 05:34 PM.
Reply With Quote
  #4  
Old 07-14-2013, 11:25 PM
ephestion ephestion is offline
Newcomer
 
Join Date: Aug 2006
Posts: 10
Default

Thanks for your help.

I placed all updates to the Graphics object in DrawScreen(G) procedure and passed all the picturebox paint events to the DrawScreen(G). I updated my code to invalidate the picturebox instead of the form. Me.picMap.invalidate()

It actually works much faster than declaring a separate graphics object every time to draw the screen. I also kept the Me.Invalidate by using some conditionals to control whether I want the form redrawn or just the picture box.

I also took your advice to handle pixel by pixel movement to the required position and added a a short loop with a wait command.

Code:
Select Case iDirection
                Case 1 'up
                    DrawFOG()
                    Do While iY > iMoveToY
                        nSpriteX = iX
                        nSpriteY = iY
                        For X = pFrame To pFrame + 2
                            nCurrentSprite = X
                            Me.picMap.Invalidate()
                            Wait(60)
                        Next X
                        iY = iY - CType(dY / 9, Integer)
                    Loop
                    'Me.picMap.Invalidate()
                Case 2 'down
                    DrawFOG()
                    Do While iY < iMoveToY
                        nSpriteX = iX
                        nSpriteY = iY
                        For X = pFrame To pFrame + 2
                            nCurrentSprite = X
                            Me.picMap.Invalidate()
                            Wait(60)
                        Next X
                        iY = iY + CType(dY / 9, Integer)
                    Loop
                    'Me.picMap.Invalidate()
                Case 3 'left
                    DrawFOG()
                    Do While iX > iMoveToX
                        nSpriteX = iX
                        nSpriteY = iY
                        For X = pFrame To pFrame + 2
                            nCurrentSprite = X
                            Me.picMap.Invalidate()
                            Wait(60)
                        Next X
                        iX = iX - CType(dX / 9, Integer)
                    Loop
                    'Me.picMap.Invalidate()
                Case 4 'right
                    DrawFOG()
                    Do While iX < iMoveToX
                        nSpriteX = iX
                        nSpriteY = iY
                        For X = pFrame To pFrame + 2
                            nCurrentSprite = X
                            Me.picMap.Invalidate()
                            Wait(60)
                        Next X
                        iX = iX + CType(dX / 9, Integer)
                    Loop
                    'Me.picMap.Invalidate()
                Case Else
                    'MapRegion(nGridCurrent).DrawOnSurface(aSprite.Bitmap, aSprite.Rectangle(pFrame), MapRegion(nGridCurrent).Rectangle(gPlayerLoc), False, False)
            End Select
The sleep event is defined as a Sub called Wait

Code:
Public Sub Wait(ByVal interval As Integer)
        Dim stopW As New Stopwatch
        stopW.Start()
        Do While stopW.ElapsedMilliseconds < interval
            ' Allows your UI to remain responsive
            Application.DoEvents()
        Loop
        stopW.Stop()
    End Sub
Only problem I have at the moment is that when the Key-up event fires it sets a variable gPlayerWalking to True if the movement is valid. It sets some variable like moveTo in Pixels. The moveFrom is set in KeyDown event.

It draws the sprite and animates fine but if I press the key again while it is making the move from one tile area to another it fires the Sprite Drawing again. In the Wait Sub I have to set Application.DoEvents() otherwise nothing is visually displayed until the sprite moves to it's destination. Is there a way to check state or force one procedure to end before accepting key strokes? It seems I have a problem with the asynchronous nature of .Net.

Basically I want a toggle to accept keystrokes only after all required procedures have finished.
Reply With Quote
  #5  
Old 07-15-2013, 01:57 PM
passel's Avatar
passelRPG Dynamic Bitmap Class passel is offline
Sinecure Expert

Super Moderator
* Guru *
 
Join Date: Jun 2003
Location: Upstate New York, usa
Posts: 8,018
Default

It would be best to have an overall "game loop" triggered by some periodic timer that would look at "state" variable to determine what it should be doing each time through the loop, rather then multiple inline loops with delays that can be re-entered, but if you don't want to take the time to restructure that now, you can prevent processing the keys when your're busy in a loop by setting a "busy" flag so that you don't process additional keys.
Code:
Static Busy as Boolean

If Not Busy Then    'If I'm not currently processing a key
  Busy = True       
  Select Case iDirection
                Case 1 'up
                    DrawFOG()
                    Do While iY > iMoveToY
                        nSpriteX = iX
                        nSpriteY = iY
                        For X = pFrame To pFrame + 2
                            nCurrentSprite = X
                            Me.picMap.Invalidate()
                            Wait(60)
                        Next X
                        iY = iY - CType(dY / 9, Integer)
                    Loop
                    'Me.picMap.Invalidate()
                Case 2 'down
                    DrawFOG()
                    Do While iY < iMoveToY
                        nSpriteX = iX
                        nSpriteY = iY
                        For X = pFrame To pFrame + 2
                            nCurrentSprite = X
                            Me.picMap.Invalidate()
                            Wait(60)
                        Next X
                        iY = iY + CType(dY / 9, Integer)
                    Loop
                    'Me.picMap.Invalidate()
                Case 3 'left
                    DrawFOG()
                    Do While iX > iMoveToX
                        nSpriteX = iX
                        nSpriteY = iY
                        For X = pFrame To pFrame + 2
                            nCurrentSprite = X
                            Me.picMap.Invalidate()
                            Wait(60)
                        Next X
                        iX = iX - CType(dX / 9, Integer)
                    Loop
                    'Me.picMap.Invalidate()
                Case 4 'right
                    DrawFOG()
                    Do While iX < iMoveToX
                        nSpriteX = iX
                        nSpriteY = iY
                        For X = pFrame To pFrame + 2
                            nCurrentSprite = X
                            Me.picMap.Invalidate()
                            Wait(60)
                        Next X
                        iX = iX + CType(dX / 9, Integer)
                    Loop
                    'Me.picMap.Invalidate()
                Case Else
                    'MapRegion(nGridCurrent).DrawOnSurface(aSprite.Bitmap, aSprite.Rectangle(pFrame), MapRegion(nGridCurrent).Rectangle(gPlayerLoc), False, False)
            End Select
  Busy = False  'I'm done processing the key
End If
Now, if a key is pressed while the first hasn't reached the end of the If..EndIf block, the code will skip over the block and not process the key.
__________________
There Is An Island Of Opportunity In The Middle of Every Difficulty.
Miss That, Though, And You're Pretty Much Doomed.
Reply With Quote
  #6  
Old 07-15-2013, 06:34 PM
ephestion ephestion is offline
Newcomer
 
Join Date: Aug 2006
Posts: 10
Default

Thanks. You confirmed that it should work.

I had placed a similar code since posting and it was still bugged. When a user kept pressing the arrow keys repeatedly and fast. So I added this:

Code:
If Not Busy And iDirection > 0 Then

When my movement is finished it would set Direction to 0. But for some weird *** reason despite adding the busy argument to key up and down event:

Code:
If Not Busy Then
            Select Case e.KeyCode
                Case Keys.Up
Which should have blocked all keystrokes while busy the stupid thing would fire the Busy Event again.

Thanks it was frustrating because I wasn't sure if you could lock the keys without an API lock. But this seems good enough and is working.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
 
RPG Dynamic Bitmap Class
RPG Dynamic Bitmap Class
 
-->