VB.NET

Moderators: seancampbell
Number of threads: 4022
Number of posts: 10035

This Forum Only
Post New Thread
Single Post View       Linear View       Threaded View      f

Report
Sprites and MakeTransparent() Questions Posted by Gavin42 on 15 Apr 2010 at 7:52 PM
Hi there :)

I'm new to VB.net, using Visual Studio Express 2008 and having a great time.

I'm working on a little game demo, and had some questions about sprites that the MSDN library was not helpful for.

Here is a sample of my code that I used to draw a transparent 32x32 character onto a base tile in a picture box:

' declarations
Public bm_char As New Bitmap("C:\char.bmp") 'the character tile 32x32 with red background)
Public bm_floorunderchar As New Bitmap("C:\base.bmp") 'a 32x32 floor tile
Public grchartransparent As Graphics = Graphics.FromImage(bm_floorunderchar)

' the subroutine that draws the sprite
Private Sub DrawChar()
' sets the transparent color to red (255, 0, 0)
bm_floorunderchar.MakeTransparent(Color.Red)

' not sure what this does
grchartransparent.DrawImage(bm_char, _
(bm_floorunderchar.Width - bm_floorunderchar.Width) \ 2, _
bm_floorunderchar.Height - bm_floorunderchar.Height, 32, 32)

' draws the images to PictureBox1
PictureBox1.Image = bm_char
PictureBox1.Image = bm_floorunderchar
End Sub

Is this the best way to go about it? It seems like an awful lot of code, especially considering I'd like to draw a few hundred of them every 20th of a second or so.

I'd like to be able to declare my bitmaps at the beginning of the program and then fill them with data later.

This is the code I was thinking might help me do that:

' declarations
Public bm_char As New Bitmap(32, 32)

' drawing subroutine
bm_char = System.Drawing.Image.FromFile("C:\test\shared\char.bmp")

I think that later, to reuse it, I could just load a new file and continue to run my other subroutines without any changes.

The other thing I was wondering was how to layer transparent images.

Example: Floor -> Character -> trees overhead -> bird flying over tree

In this example I'd still like to see all of the images below the bird.

Any ideas about how to do that with the MakeTransparent() method and what I already have?

Thanks in advance,

Gavin
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 15 Apr 2010 at 11:17 PM
I went ahead and coded a FPS meter to see how the program is running on my machine. All things considered 17 FPS is not so bad for a demo.

So, I'd still like to figure out how to overlay multiple transparencies in the project. Other than that I just need to make the whole thing a bit more scalable before I start mapping and generating other in-game data.

Does anyone out there know the methodology for doing multiple levels of transparency, even if it means me starting from scratch on my 2D graphics, I'll be willing to give it a go :)
Report
Re: Sprites and MakeTransparent() Questions Posted by seancampbell on 16 Apr 2010 at 6:05 AM
What do you mean by "Multiple levels of transparency"?

Check this out:
http://cotw.11.forumer.com/viewtopic.php?t=113
(on page 2 I have a screen shot after I made the game a playable demo

It's a game I've been working on in VB.Net using VS VB.Net 2008 Express Edition. I use PNG's, BMP's, and GIF's to store Transparency in my saved image. The VB.Net Bitmap object recognizes that transparency.

In the game, Most of my Class Objects inherit from a base class:
    Public Class COTW_Element
        Public X As Integer
        Public Y As Integer
        Public Col As Integer
        Public Row As Integer
        Public Solid As Boolean = False
        Public isConsumed As Boolean = False

        Public Event Hit(ByRef Sender As Object, ByRef e As EventArgs)

        Public Sub New()

        End Sub

        Public Sub New(ByVal _X As Integer, ByVal _Y As Integer, ByVal _R As Integer, ByVal _C As Integer)

        End Sub

        Public Function isInTile(ByRef R As Integer, ByRef C As Integer) As Boolean
            Return (R = Row And C = Col)
        End Function
    End Class

and then have a "DrawOntoGraphics" routine like this:
    Public Class COTW_Player
        Inherits COTW_Element

        Dim imageLoaded As Boolean
        Dim poisoned As Boolean
        Dim poisonLevel As Integer
        Dim img As Bitmap
        Dim Container As COTW_Container

        Public Sub New(ByVal ImagePath As String)
            Me.X = 0
            Me.Y = 0
            Me.Col = 0
            Me.Row = 0

            Try
                Me.img = New Bitmap(Application.StartupPath.Trim("\") & "\" & ImagePath)
                Me.imageLoaded = True
            Catch ex As Exception
            End Try

            Container = New COTW_Container
        End Sub

        Public Sub New()
            Me.X = 0
            Me.Y = 0
            Me.Col = 0
            Me.Row = 0

            Container = New COTW_Container
        End Sub

        Public Sub addItem(ByVal NewItem As COTW_Item)
            Container.addItem(NewItem)
        End Sub

        Public Function rmvItem(ByVal Index As Integer) As Object
            Dim Item As Object = Container.rmvItem(Index)
            Return Item
        End Function

        Public Sub gotHit() Handles MyBase.Hit

        End Sub

        Public Sub drawOntoGraphics(ByRef G As Graphics)
            G.DrawImage(img, New Point(X, Y))
        End Sub

        Public Sub Move(ByRef _Row As Integer, ByRef _Col As Integer, ByRef _X As Integer, ByRef _Y As Integer)
            Col = _Col
            Row = _Row
            X = _X
            Y = _Y
        End Sub
    End Class


Inside of my Engine object, I have a "PaintDisplay" object which gets the Level image (which is dynamically generated by analyzing each tile and painting them into a master image) and then draws on the Player object. The player object has transparency which work's just fine:

        Private Sub PaintDisplay()
            If Not IsNothing(Level) Then
                Dim BMP As Bitmap = Level.getImage()
                Dim G As Graphics = Graphics.FromImage(BMP)
                Player.drawOntoGraphics(G)
                pcbDisplay.Image = BMP
            End If
        End Sub


I should note that ClsPlayer.drawOntoGraphics takes the Graphics object as ByRef (so I don't have to return a value, the Graphics object that was passed is directly manipulated inside of the DrawOntoGraphics routine, instead of a New Value being created (if you used ByVal).
pcbDisplay is a picturebox, so when I want to update the display, I just insert the new BMP, and some background Windows process triggers it to RePaint that display.


That said, if you are serious about game development, VB.Net is probably not the language you want to use. C#.Net has a package from Microsoft called "XNA Framework" which is specifically designed to develop games (I moved on from this project to working in XNA, and will be converting the whole project to XNA after I finish the game I am working on now).

Using XNA requires you to own a license of Visual Studio, as I don't think there is a version that works with C#.Net Express Edition (which is cheap if you are a student in college or highschool). XNA is also C# only, I don't know if they plan to allow support for VB.


Anyway, back to your question. Sounded more like you were interested in drawing layers, which have transparency... So here is how I would approach it:

'At the beginning of the game, at Load time of the level or game itself
'load the Layers into Layer objects as follows:
'These Layer Images should contain transparency saved directly into them

Dim Layers() As Bitmap
Dim Player As Bitmap
Dim Tiles(,) as Bitmap
Dim HUD as Bitmap


Public Sub DrawDisplay()
'All of these arrays and bitmaps should be initialized by this point
Dim DisplayBMP As Bitmap = New Bitmap(_Columns * _TileWidth, Rows * _TileHeight)
'Creates the graphics object that lets you draw into a Bitmap object
Dim G as Graphics = Graphics.FromImage(DisplayBMP)

'Clear the BMP with white first
G.Clear(Color.White)

'Draw the objects in the farthest background first, thats your Layers
Dim i as integer = 0
For i = 0 to Layers.Count - 1
  G.DrawImage(Layers(i), New Point(0, 0)) 'assumes the layer stays still
Next i

'Draw the tiles
Dim r as integer
Dim c as integer
for r = 0 to _TileRows - 1
  For c = 0 to _TileCols - 1
   G.DrawImage(Tiles(c, r), New Point(c * _TileWidth, r * _TileHeight))
  Next c
Next r

'Draw the player
  G.DrawImage(Player, New Point(PlayerX, PlayerY))

'Draw the Heads up Display - which is the front most object
  G.DrawImage(HUD, New Point(0, 0))

'Finally, we need to assign that BMP to something
PictureBox1.Image = BMP 'should automatically repaint when this Sub ends
End Sub


Thats a very simple example of how to draw images that have transparency onto a Bitmap and assigns that to a picture box image.

Hope this helps, may be too complex of an answer tho, so DO ask away,
Sean C
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 16 Apr 2010 at 4:01 PM
Knowing that VB.net handles transparency natively using png and gif is probably going to make things a lot easier. Thanks for that :)

As far as the code goes, I am going to be AFK for a few more hours, so I won't have a chance to really descipher it until then, but it looks good.

Regarding the "multiple levels of transparency", what I mean is that I want to be able to see "down" (through the z-order) all of the tiles with transparency. So, if I want to display a grass tile with a character standing on top of it, and a bird flying overhead, and clouds passing by, I would still be able to see some of the grass through it all.

I know that sounds rather basic, but using the VB drawing routines I wasn't able to figure it out (in VB 6 it was even difficult to BitBlt multiple layers.

The other reason I posted the code was because these graphics routines were requiring me to store the equivalent of 4 bitmaps in memory, and I thought that there might be a less memory intensive way to do that.

In the long term I will want to probably use XNA, but as a proof of concept I just want to get this project "finished" before I start on that.

Thanks for your help so far. I'll try to respond again later once I get back to my PC.

-Gavin


Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 16 Apr 2010 at 5:02 PM
There is a lot more to the program than what I posted. I just pulled out the parts that were related to my question and put them into the message :)

It looks like my game is almost to the same point as yours aside from the graphics that you seem to already have. I've been photoshopping up horrible graphics as well as 'stealing' game images, and hoping to get an artist friend to start making some game images for me later.

I'd like to get the demo to a playable state at around 20 fps, minimum. If I can't do that in VB.net I'll switch out and learn a new language. I already have a bit of Java under my belt, and don't have much trouble picking up other languages.

I'm about to give gif and png files a chance, and see how well that works, and how it changes my framerate.

Will report back, hopefully soon :)

-G
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 16 Apr 2010 at 6:28 PM
I just made a sample program using a pair of png files with transparency. While they both show the background of the form perfectly, when they intersect only the one on top (by z-order) shows.

Example
P and O are images, and P has a higher z-order. - is the background.
In this frame they stand alone and neither intersects with the other, they both show the window's background image.

PPPP------OOOO-
P--PP----OO--OO
P--PP----OO--OO
PPPP-----OO--OO
P--------OO--OO
P--------OO--OO
P---------OOOO-

What I Want when O and P intersect:

PPPPOOOO-
P--PP--OO
P--PP--OO
PPPPO--OO
P--OO--OO
P--OO--OO
P---OOOO-

What I get:

PPPP-OOO-
P--PP--OO
P--PP--OO
PPPP---OO
P------OO
P------OO
P----OOO-


I'd like to be able to see both of them through each others "holes" as well as seeing the background where they both have "holes". I can get one or the other, but I need both.

I think I might have to go back to BitBlt for graphics since my last demo had a lot more graphically intensive stuff going on, did this type of transparency (with a lot of work) and ran around 110 FPS.

The only thing that would stop me from switching to BitBlt is if it doesn't work anymore, or there is a way around this problem.

-G
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 16 Apr 2010 at 6:33 PM
Sorry, duplicate post. Formatting fail :(
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 16 Apr 2010 at 6:44 PM
Another way to show the same thing


Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 18 Apr 2010 at 12:22 AM
Sean,

While I do understand in theory how you are going your graphics functions, I can't say I understand them well enough to implement them in code.

I realize at least a few of my errors with my previous attempts, but aside from using BitBlt (old school) I'm not sure how to get around these problems without a drastic redesign.

I'll keep fiddling with things, and let you know if I get one to work.

Thanks for your help :)
Report
Re: Sprites and MakeTransparent() Questions Posted by seancampbell on 19 Apr 2010 at 5:46 AM
I wasn't having that issue when I did my drawing,

Would you mind pasting some of your Draw code so we can dig into why it is replacing pixels with Transparent pixels instead of ignoring them?

Sorry it took me so long to answer, I usually don't hop on over the weekends,

I'd like to understand what is going on for future solutions and help you along your way
Sean Campbell
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 19 Apr 2010 at 6:13 AM
I just made some major alterations to my code so that I am manipulating my class objects rather than a couple of bitmaps. However, now I have another minor problem I have to deal with before I'm ready to try to fix the main issue.

The new problem is that my transparency is too good, it shows all the way through the form ;)

Anyway, when I get back home I'll translate some code and show you what I have.

Thanks,

-G
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 19 Apr 2010 at 7:21 AM
Here's a bit of working transparency code. Any chance we can get this to support multiple transparent images?

Public Class Form1
    Public bm_char As New Bitmap("C:\charg.png") 'the character tile with red background)
    Public bm_back As New Bitmap("C:\backn.png") 'a background tile
    Public gr As Graphics = Graphics.FromImage(bm_back)
    Private Sub DrawChar()
        ' sets the transparent color to red (255, 0, 0)
        bm_char.MakeTransparent(color.Red)

        gr.DrawImage(bm_char, 0, 0, 32, 32)

        ' draws the images to PictureBox
        pbxSrc.Image = bm_char
        pbxSrc.Image = bm_back
    End Sub
    Private Sub btnDraw_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDraw.Click
        DrawChar()
    End Sub
End Class


The form needs a picturebox named pbxSrc, and a button named btnDraw.

Here are the images I used:


Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 19 Apr 2010 at 7:49 AM
This code seems to produce the desired effect, however, I can't seem to get the old foreground to clear.

Public Class Form1
    Public bm_char As New Bitmap("C:\charg.png") 'the character tile
    Public bm_back As New Bitmap("C:\backn.png") 'a background tile
    Public gr As Graphics = Graphics.FromImage(bm_back)

Private Sub DrawChar(ByVal gr As Graphics, ByVal background As Bitmap, ByVal foreground As Bitmap, ByVal transcolor As System.Drawing.Color, ByVal offsetx As Integer, ByVal offsety As Integer)
        foreground.MakeTransparent(transcolor)

        gr.DrawImage(foreground, offsetx, offsety, 32 + offsetx, 32 + offsety)

        pbxSrc.Image = foreground
        pbxSrc.Image = background
End Sub

Private Sub btnDraw_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDraw.Click
        For x = 1 To 8
            DrawChar(gr, bm_back, bm_char, Color.Red, x, x)
            'Threading.Thread.Sleep(250)
            'If x < 8 Then pbxSrc.Image = Nothing
        Next
End Sub
End Class

Report
Re: Sprites and MakeTransparent() Questions Posted by seancampbell on 19 Apr 2010 at 11:23 AM
Why are you setting the .Image to something, and then immediately setting it to soemthing else?

        pbxSrc.Image = foreground
        pbxSrc.Image = background

should be
        pbxSrc.Image = background

Because the first line there is pointless because it is overwritten with the second line.

-----------------
I am not entirely sure how your application is built, or if your just testing code now to understand it before you go back and start to build the game.... I see several things wrong with your code, here is some comments I put into what you sent to explain what I see wrong:

Public Class Form1
    Public bm_char As New Bitmap("C:\charg.png") 'the character tile
    Public bm_back As New Bitmap("C:\backn.png") 'a background tile
    Public gr As Graphics = Graphics.FromImage(bm_back)

    Private Sub DrawChar(ByVal gr As Graphics, ByVal background As Bitmap, ByVal foreground As Bitmap, ByVal transcolor As System.Drawing.Color, ByVal offsetx As Integer, ByVal offsety As Integer)
        foreground.MakeTransparent(transcolor)

        'The parameters you are sending here are (ImgToDraw, X, Y, Width, Height)
        'so your adding you X location to the Width of 32 to get a Width/Height that
        'are most likely wrong, and wrong by a lot
        gr.DrawImage(foreground, offsetx, offsety, 32 + offsetx, 32 + offsety)

        'Your setting the background image to Foreground here, which would display the contents of Bm_char
        '  because thats what was sent to the DrawChar Function
        pbxSrc.Image = foreground
        'However you overwrite the last line with the contents of background - Which would only ever have 1 char drawn on it
        pbxSrc.Image = background
    End Sub

    Private Sub btnDraw_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDraw.Click
        For x = 1 To 8
            'Each time this function is called, it will overwrite the work of the last time it was called
            'Any changes you made are not saved in bm_back or bm_char because you are sending GR as ByVal, and you are
            'sending Baackground and Foreground as ByVal... no changes made in that routine have effect on the values
            'outside that function then...
            DrawChar(gr, bm_back, bm_char, Color.Red, x, x)
            'Threading.Thread.Sleep(250)
            'If x < 8 Then pbxSrc.Image = Nothing
        Next
    End Sub
End Class



Here is some code that should work, but you'll need to test first because I didn't. (to get that commenting scheme for the Sub, above any subroutine or function, type ''' and hit enter, it will auto-generate and you can fill in the comments)
Public Class Form1

    Public bm_char As New Bitmap("C:\charg.png") 'the character tile
    Public bm_back As New Bitmap("C:\backn.png") 'a background tile
    Public gr As Graphics = Graphics.FromImage(bm_back)

    ''' <summary>
    ''' This function will draw an image onto a Graphics object at the setting
    ''' the transparency to the desired color, and using the X and Y coordinates
    ''' passed by the user
    ''' </summary>
    ''' <param name="GR">Graphics Object passed By Reference</param>
    ''' <param name="IMG">Image we will draw to the Graphics Object</param>
    ''' <param name="transcolor">Color of the MakeTrasparent</param>
    ''' <param name="X">X coordinate to draw the image to</param>
    ''' <param name="Y">Y coordinate to draw the image to</param>
    Private Sub DrawImageToGraphicsObject(ByRef GR As Graphics, ByVal IMG As Bitmap, ByVal transcolor As System.Drawing.Color, ByVal X As Integer, ByVal Y As Integer)
        IMG.MakeTransparent(transcolor)

        GR.DrawImage(IMG, X, Y) 'Draws IMG onto the Image that GR is set to at point (X,Y)
    End Sub

    Private Sub DrawDisplay()
        'First, I need to know how big the drawn display will be
        'I will use this to assign to a new Bitmap image
        Dim LevelWidth As Integer = bm_back.Width
        Dim LevelHeight As Integer = bm_back.Height

        'Next we create a new Bitmap object that we are going to be drawing all
        'of the objects onto, and at the end assigning this bitmap to a pictureBox.
        'I'm using LevelWidth and LevelHeight which could be integers declared globally and assigned anywhere
        'but for this example are declared and assigned inside the Private Sub DrawDisplay()
        Dim BMP As New Bitmap(LevelWidth, LevelHeight)
        'Graphics Object we use to Draw stuff to the display
        Dim GR As Graphics = Graphics.FromImage(BMP)

        '###########################
        'Now we are going to draw all items we want displayed onto the GR object
        'in the order of BACKMOST to FOREMOST

        'Therefore, the background is draw first:
        GR.DrawImage(bm_back, 0, 0) 'Draws the Background at point(0,0)

        'Now draw the characters onto the picture
        For x = 1 To 8
            'Now we are going to send the GR object to a function BYREF,
            'look up the difference between ByRef and ByVal, and look at the parameter
            'definitions in the DrawImageToGraphicsObject routine I made
            DrawImageToGraphicsObject(GR, bm_char, Color.Red, x, x)
        Next

        'Now we're done drawing onto BMP, lets assign that back to the picturebox
        pbxSrc.Image = BMP
    End Sub

    Private Sub btnDraw_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDraw.Click
        DrawDisplay()
    End Sub
End Class



It occured to me when I was commenting your function that you were trying to trouble shoot the issue by watching it draw one item at a time (by pausing the routine with Threading.Thread.Sleep(250)). Not sure if that helped you, but you should probably learn how to watch your code execute 1 line at a time (and how to put breaklines into your code so it stops at the desired spot for you to view the values of whats going on). This will greatly improve your troubleshooting experience (in my opinion, programming is 25% coding, and 75% troubleshooting).

Hope this helps,
Sean Campbell
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 19 Apr 2010 at 11:42 AM
Thanks Sean,

The sleep command was just supposed to make it so that I could see when the image changed. I thought that setting the image would have caused it to update, but I see now that it doesn't happen in that way.

Public Class Form1

    Public bm_char As New Bitmap("C:\charg.png") 'the character tile
    Public bm_back As New Bitmap("C:\backn.png") 'a background tile
    Public gr As Graphics = Graphics.FromImage(bm_back)
    Public X As Integer = 0

    ''' <summary>
    ''' This function will draw an image onto a Graphics object at the setting
    ''' the transparency to the desired color, and using the X and Y coordinates
    ''' passed by the user
    ''' </summary>
    ''' <param name="GR">Graphics Object passed By Reference</param>
    ''' <param name="IMG">Image we will draw to the Graphics Object</param>
    ''' <param name="transcolor">Color of the MakeTrasparent</param>
    ''' <param name="X">X coordinate to draw the image to</param>
    ''' <param name="Y">Y coordinate to draw the image to</param>

    Private Sub DrawImageToGraphicsObject(ByRef GR As Graphics, ByVal IMG As Bitmap, ByVal transcolor As System.Drawing.Color, ByVal X As Integer, ByVal Y As Integer)
        IMG.MakeTransparent(transcolor)
        GR.DrawImage(IMG, X, Y) 'Draws IMG onto the Image that GR is set to at point (X,Y)
    End Sub

    Private Sub DrawDisplay(ByVal offsetx As Integer, ByVal offsety As Integer)
        'First, I need to know how big the drawn display will be
        'I will use this to assign to a new Bitmap image
        Dim LevelWidth As Integer = bm_back.Width
        Dim LevelHeight As Integer = bm_back.Height

        'Next we create a new Bitmap object that we are going to be drawing all
        'of the objects onto, and at the end assigning this bitmap to a pictureBox.
        'I'm using LevelWidth and LevelHeight which could be integers declared globally and assigned anywhere
        'but for this example are declared and assigned inside the Private Sub DrawDisplay()
        Dim BMP As New Bitmap(LevelWidth, LevelHeight)
        'Graphics Object we use to Draw stuff to the display
        Dim GR As Graphics = Graphics.FromImage(BMP)

        '###########################
        'Now we are going to draw all items we want displayed onto the GR object
        'in the order of BACKMOST to FOREMOST

        'Therefore, the background is draw first:
        GR.DrawImage(bm_back, 0, 0) 'Draws the Background at point(0,0)

        'Now draw the characters onto the picture
        'Now we are going to send the GR object to a function BYREF,
        'look up the difference between ByRef and ByVal, and look at the parameter
        'definitions in the DrawImageToGraphicsObject routine I made
        DrawImageToGraphicsObject(GR, bm_char, Color.Red, offsetx, offsety)

        'Now we're done drawing onto BMP, lets assign that back to the picturebox
        pbxSrc.Image = BMP
    End Sub

    Private Sub ClearDisplay()
        pbxSrc.Image = Nothing
    End Sub

    Private Sub btnDraw_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDraw.Click
        ClearDisplay()
        DrawDisplay(X Mod 3, X Mod 3)
        X += 1
    End Sub

End Class


Now it's just a matter of loading a second image and trying to place it on top of the first without overwriting them.

Once that is done I can implement it into my original program and send you a copy of the result.

Thanks to much for your help so far, I feel like I understand the process a lot better already.

-Gavin
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 19 Apr 2010 at 11:56 AM
I just realized that the bit of code I changed showed just how little I understood about the execution of the program.

A closer look later, I have the finished code that displays the sprites in the correct order.

Public Class Form1

    Public bm_char As New Bitmap("C:\charg.png") 'the character tile
    Public bm_over As New Bitmap("C:\overh.png") 'a fence in front
    Public bm_back As New Bitmap("C:\backn.png") 'a background tile
    Public gr As Graphics = Graphics.FromImage(bm_back)

    ''' <summary>
    ''' This function will draw an image onto a Graphics object at the setting
    ''' the transparency to the desired color, and using the X and Y coordinates
    ''' passed by the user
    ''' </summary>
    ''' <param name="GR">Graphics Object passed By Reference</param>
    ''' <param name="IMG">Image we will draw to the Graphics Object</param>
    ''' <param name="transcolor">Color of the MakeTrasparent</param>
    ''' <param name="X">X coordinate to draw the image to</param>
    ''' <param name="Y">Y coordinate to draw the image to</param>

    Private Sub DrawImageToGraphicsObject(ByRef GR As Graphics, ByVal IMG As Bitmap, ByVal transcolor As System.Drawing.Color, ByVal X As Integer, ByVal Y As Integer)
        IMG.MakeTransparent(transcolor)
        GR.DrawImage(IMG, X, Y) 'Draws IMG onto the Image that GR is set to at point (X,Y)
    End Sub

    Private Sub DrawDisplay()
        'First, I need to know how big the drawn display will be
        'I will use this to assign to a new Bitmap image
        Dim LevelWidth As Integer = bm_back.Width
        Dim LevelHeight As Integer = bm_back.Height

        'Next we create a new Bitmap object that we are going to be drawing all
        'of the objects onto, and at the end assigning this bitmap to a pictureBox.
        'I'm using LevelWidth and LevelHeight which could be integers declared globally and assigned anywhere
        'but for this example are declared and assigned inside the Private Sub DrawDisplay()
        Dim BMP As New Bitmap(LevelWidth, LevelHeight)
        'Graphics Object we use to Draw stuff to the display
        Dim GR As Graphics = Graphics.FromImage(BMP)

        '###########################
        'Now we are going to draw all items we want displayed onto the GR object
        'in the order of BACKMOST to FOREMOST

        'Therefore, the background is draw first:
        GR.DrawImage(bm_back, 0, 0) 'Draws the Background at point(0,0)

        'Now draw the characters onto the picture
        'Now we are going to send the GR object to a function BYREF,
        'look up the difference between ByRef and ByVal, and look at the parameter
        'definitions in the DrawImageToGraphicsObject routine I made
        DrawImageToGraphicsObject(GR, bm_char, Color.Red, 0, 0)
        'and this draws a fence in front of the character icon
        DrawImageToGraphicsObject(GR, bm_over, Color.Red, 0, 0)

        'Now we're done drawing onto BMP, lets assign that back to the picturebox
        pbxSrc.Image = BMP
    End Sub

    Private Sub ClearDisplay()
        pbxSrc.Image = Nothing
    End Sub

    Private Sub btnDraw_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDraw.Click
        ClearDisplay()
        DrawDisplay()
    End Sub

End Class

Report
Re: Sprites and MakeTransparent() Questions Posted by seancampbell on 20 Apr 2010 at 9:59 AM
Very nice! Looks like you figured it out.

So, in summary,

1. You create an Image object (in our code its a Bitmap called BMP)
2. You draw all of the images you want onto that Image object in the order in which you want them, starting with the backmost img and ending with the foremost img.
3. Lastly, You assign that Image object to PictureBox.Image

------------------

Did that solve your original question?
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 21 Apr 2010 at 5:28 AM
Yeah. I have the "multiple levels of transparency" I wanted, and now understand why that question was so hard for most people to answer, the functionality was built in, I was just messing up the code pretty badly ;)

The problems I'm having now are related to z-ordering the sprites (character, NPCs, and foreground tiles).

I'm deciding which I'd prefer: to have a z-order attribute for each of my map objects, or to have the code generate the z-order on the fly based on the height of the object I'm drawing.

This is the Map object I'm using (read from a text file).

Public Class Map
    Public Name As String
    Public Tileset As Integer
    Public TileSize As Integer = 32
    Public NumTiles As Integer 'how many tiles to keep in memory
    Public FromMap As Integer 'where did the user come from
    Public ToMap As Integer ' where is the user headed
    Public CanExitFromStart As Integer
    Public Size As Integer ' width and height of map in "tilewidth"s
    Public BorderStyle As Integer '0 = clear, 1 = barriers,
    Public StartPointX As Integer ' x-coord of entry point
    Public StartPointY As Integer ' y-coord of entry point
    Public bmpTile(99) As Bitmap '100 foreground tiles
    Public bmpFloor As Bitmap ' base/floor tile
    ' visible mapset
    Public visible(99, 99) As Integer ' actual maximum Map.Size = 90 (0-4 and 95-99 are buffers)
    ' barriers mapset
    Public barriers(99, 99) As Integer ' actual maximum Map.Size = 90 (0-4 and 95-99 are buffers)
    Public OffsetX As Integer = 0 ' offset for drawing the map during character movement
    Public OffsetY As Integer = 0 ' offset for drawing the map during character movement


I'd like to do something like:

Public Class Map
    Public Name As String
    ...
    Public bmpTile(99) As Bitmap
                .height as Integer 'number of tiles high (normally 1)
                .width as Integer  'number of tiles wide (normally 1)
    ...


The reason I'm worried about this is that my map files' data looks like this:

01,01,01,01 'barrier data
01,00,99,01 '00 = walkable, 02 = start point
01,02,00,01 '99 = exit point
01,01,01,01 '01 = blocked

01,01,01,01 'visible map data
01,00,11,01 '01 = bush (32,32)
01,00,18,01 '11 = warp (32,32)
01,01,19,01 '18 = tree top (32,32), 19 = tree bottom (32,32)


If I can implement the above changes to my object I might be able to make the visible map look like this instead:

01,01,01,01 'visible map data
01,00,11,01 '01 = bush (32,32)
01,00,00,01 '11 = warp (32,32)
01,01,19,01 '19 = tree (64,32)


This could potentially fix my z-order problems, as the program will draw the entire object when it gets down to the last line of the map, thus always drawing it in the right place.

What do you think? Is there an easier way to implement this?

The reason I want to take an object-oriented approach to solving this is that after I finish with the mapping I'll be moving on to the battle system where I don't expect any of my objects to conform to the confines of a "regularly" shaped tile.

-G
Report
Re: Sprites and MakeTransparent() Questions Posted by seancampbell on 21 Apr 2010 at 12:52 PM
I'm not entirely sure what you are asking. Are you saying that you want to create a ZOrder property which will tell the program what order to draw the sprites in? and have that based on the Height of the objects in the game?

The only problem I see you running into with that is losing a lot of processing power doing the analysis each time it draws to check the Zorder of objects. I would suggest having an Entity layer that holds anything that is going to be outside of the Tile constraints and showup overtop of the player (like a tree only clocks 1 or 4 squares, but the leaves extend out for many squares). This entity layer would get drawn last in the order of drawing stuff.

Clarify your request for me in a new post, and we'll take it from there!
Report
Re: Sprites and MakeTransparent() Questions Posted by Gavin42 on 22 Apr 2010 at 11:11 AM
Here are the layers it looks like I'll need:

Floor (drawn first, everything covers it)
Barrier Layer (tells us where the character can and cannot go)
Standard 32x32 foreground objects
Irregular objects (houses, player, NPCs)
Overhead layer (alpha layer of clouds)

The reason I want a separate barrier layer is so I can add secret tunnels through solid looking objects.
42884
Right now, however, my code is handling simple 32x32 tiles improperly :( so I need to tackle that.

I can send you my code if you'd like, but this forum wouldn't brthe best place for that kind of sharing ;)

-G
Report
Re: Sprites and MakeTransparent() Questions Posted by seancampbell on 23 Apr 2010 at 7:11 AM
There are nearly limitless possible solutions to tackle what you are trying to do. The approach I would take may not be similar to the one you would.

I wouldn't mind helping you solve specific problems, but it's really up to you to do the rest.

That said, if you're still having problems with some specific code, start a new thread and write out a description of your problem and provide som sample code and I'll gladly help you
1 2  Next



 

Recent Jobs

Official Programmer's Heaven Blogs
Web Hosting | Browser and Social Games | Gadgets

Popular resources on Programmersheaven.com
Assembly | Basic | C | C# | C++ | Delphi | Flash | Java | JavaScript | Pascal | Perl | PHP | Python | Ruby | Visual Basic
© Copyright 2011 Programmersheaven.com - All rights reserved.
Reproduction in whole or in part, in any form or medium without express written permission is prohibited.
Violators of this policy may be subject to legal action. Please read our Terms Of Use and Privacy Statement for more information.
Operated by CommunityHeaven, a BootstrapLabs company.