RealBasic: Canvas Tutorial Lesson 5

I had the question from some people how to handle different type of objects.
In this tutorial we’re going to change our last tutorial so we can handle multiple types and can recognize them when we click.

Next to our comic covers, we’ll also add some CDs and DVDs.

As every type element will have its own shadow and glow, we’ll remove the comic mask and glow properties from ABCanvas and where we use them in the functions:

'ComicGlow as picture ' remove property
'ComicMask as picture ' remove property

Sub Init(tmpBackGround as picture, tmpComicMask as picture, tmpComicGlow as picture)
  me.Background = NewPicture(width,height, 32)
  me.Background.Graphics.DrawPicture tmpBackGround,0,0, width, height, 0,0, tmpBackGround.Width, tmpBackGround.Height
  pBuffer = NewPicture(width, height, 32)
  gBuffer = pBuffer.Graphics
  'ComicMask = NewPicture(tmpComicMask.Width, tmpComicMask.Height, 32) ' remove
  'ComicMask.Graphics.DrawPicture tmpComicMask,0,0 ' remove

  'ComicGlow = NewPicture(tmpComicGlow.Width, tmpComicGlow.Height, 32) ' remove
  'ComicGlow.Graphics.DrawPicture tmpComicGlow,0,0 ' remove
End Sub

Sub CleanUp()
  dim a as integer
  for a = 0 to UBound(MyElements)
  Redim MyElements(-1)
  Background = nil
  gBuffer = nil
  pBuffer = nil
  'ComicMask = nil ' remove
  'ComicGlow = nil ' remove
End Sub

In the function ElementHit we also need to change

if ComicMask.Graphics.Pixel(Abs(x - tmpElem.x + halfw), Abs(y - tmpElem.y + halfh)) = &c000000 then


if tmpElem.MyMask.Graphics.Pixel(Abs(x - tmpElem.x + halfw), Abs(y - tmpElem.y + halfh)) = &c000000 then

Let’s rebuild this in the ABElement class. We’ll need properties to handle our type and our own mask and glow. We also add InnerX and InnerY. These are the coordinates of the picture within the Element. This way, we’ll be able to position our CD cover not on x=0, y=0 but at a different place. This is handy for our CD so that it appears the cover is in a plastic cd case:

Type as integer
MyGlow as Picture
MyMask as picture
InnerX as integer 
InnerY as integer

In the Init() function we make some changes so we’ll use our type, our own mask and glow. We can also add our inner X and Y position:

Sub Init(tmpID as integer, tmpType as integer, tmpX as integer, tmpY as integer, tmpInnerX as integer, tmpInnerY as integer, tmpImage as picture, tmpMask as picture, tmpGlow as picture, tmpVisible as boolean)
  me.ID = tmpID
  me.x = tmpX
  me.y = tmpY
  me.Visible = tmpVisible
  me.w = tmpImage.Width
  me.h = tmpImage.Height
  me.Type = tmpType
  me.MyGlow = tmpGlow ' new
  me.MyMask = tmpMask ' new
  me.InnerX = tmpInnerX ' new
  me.innerY = tmpInnerY ' new
  Image = NewPicture(w,h, 32)
  image.Graphics.DrawPicture tmpImage,0,0
  if MyMask <> nil then ' changed
    me.w = MyMask.Width ' changed
    me.h = MyMask.Height 'changed
  end if
  pBuffer = NewPicture(w,h, 32)
  gBuffer = pBuffer.Graphics
End Sub

In de DrawMe function we’ll also need to make the changes. As here we’ll using InnerX and InnerY to position our cover, we’ll need to add an extra black layer so we use the glow also on the parts without a picture:

Sub DrawMe()
  if Image <> nil then
    pBuffer = NewPicture(w,h, 32)
    gBuffer = pBuffer.Graphics
    if MyMask <> nil then ' changed
      gBuffer.ForeColor = &c000000
      gBuffer.FillRect 0,0, w,h
      pBuffer.Mask.Graphics.DrawPicture MyMask,0,0 ' changed
    end if
    if MyGlow <> nil then ' changed
      dim tmpBuildPic as Picture
      dim tmpGW as Integer = MyGlow.Width ' changed
      dim tmpGH as integer = MyGlow.Height ' changed
      tmpBuildPic = newpicture(tmpGW,tmpGH,32)
      tmpBuildPic.mask.Graphics.DrawPicture MyGlow,0,0 ' changed
      ' draw a black layer so everything that is not covered by our image is also using the glow mask
      tmpBuildPic.Graphics.ForeColor = &c000000 ' new
      tmpBuildPic.Graphics.FillRect 0,0, w,h ' new
      tmpBuildPic.Graphics.DrawPicture Image,InnerX,InnerY ' changed
      gbuffer.ForeColor = &cFFFFFF
      gbuffer.FillRect 0,0, tmpGW, tmpGH
      gbuffer.DrawPicture tmpBuildPic,0,0     
    end if
  end if  
End Sub

Don’t forget to cleanup the glow and mask when the object is destroyed:

Sub CleanUp()
  gBuffer = nil
  pBuffer = nil
  Image = nil
  MyABCanvas = nil
  MyGlow = nil ' new
  MyMask = nil ' new 
End Sub

And now in the main form we can load our comics, CDs and DVDs in the new LoadMe() and LoadType() functions. This way we clean up our code a little bit and we can add or remove covers just by copying pictures into the right maps. Notice in each init() function we now give a type, load our Masks and Glows and give an InnerX and InnerY value.

Note: some people pointed out the LoadType() function does not work in RB version 2011+. It seems from 2011 on, the items list starts from 1 instead of 0. So change the line

for a = 0 to all.Count - 1


for a = 1 to all.Count

Here are the functions:

Sub LoadMe()
  Dim f as FolderItem
  f = GetFolderItem("Background.png")
  ' some Comics
  LoadType 1, GetFolderItem("").AbsolutePath + "COMIC\", 0,0
  ' some CDs
  LoadType 2, GetFolderItem("").AbsolutePath + "CD\", 17,4
  ' Some DVDs
  LoadType 3, GetFolderItem("").AbsolutePath + "DVD\", 0,2
End Sub

Sub LoadType(tmpType as integer, Folder as String, InnerX as integer, InnerY as integer)
  Dim f as FolderItem
  Dim all as FolderItem
  Dim tmpElem as ABElement
  Dim tmpPic as Picture
  Dim tmpPicMask as Picture
  Dim tmpPicGlow as Picture
  Dim a as integer
  Dim counter as integer
  ' preload the mask and glow
  f= GetFolderItem(Folder + "Mask.png")
  tmpPicMask = f.OpenAsPicture
  f= GetFolderItem(Folder + "Glow.png")
  tmpPicGlow = f.OpenAsPicture
  all = GetFolderItem(Folder)
  if all <> nil then
    ' for RB version 2011+ change this line to
    ' for a = 1 to all.Count
    for a = 0 to all.Count - 1
      f = all.item(a)
      select case f.Name
      case "Mask.png", "Glow.png", "."
        ' ignore these
      case else
        ' a cover, so load it
        tmpPic = f.OpenAsPicture
        tmpElem = new ABElement(ABCanvas1)
        tmpElem.Init(Counter,tmpType, rnd * (me.Width - tmpPic.width) + tmpPic.Width / 2, rnd * (me.Height - tmpPic.Height) + tmpPic.Height / 2,InnerX,InnerY, tmpPic, tmpPicMask, tmpPicGlow, true)
        Counter = counter + 1
      end select
  end if
End Sub

So a couple of new things like InnerX and InnerY alows us to make even more special objects.
I’m rather glad we’ll changed it to multiple objects as it will give us the chance to do something fun in our next tutorial: animation!

The source can be download from:

See ya!

Click here to Donation if you like my work


About Alwaysbusy

My name is Alain Bailleul and I'm the Senior Software Architect/Engineer at One-Two. I like to experiment with new technologies, Computer Vision and A.I. My projects are programmed in B4X , Xojo, C#, java, HTML, CSS and JavaScript. View all posts by Alwaysbusy

3 responses to “RealBasic: Canvas Tutorial Lesson 5

  • Jordan

    For cross platform, you should probably change

    LoadType 1, GetFolderItem(“”).AbsolutePath + “COMIC\”, 0,0


    LoadType 1, GetFolderItem(“”).child(“COMIC”).AbsolutePath, 0,0

  • Alwaysbusy

    @Jordan: I’m a Windows programmer, and it shows 🙂

    You are absolutely right but these are the things I sometimes forget.

  • Charles Fasano

    I have a few questions:

    1. How do you know what InnerY and X to give a particular object?
    2. Does the value given to “Type” have any special meaning or can I use any Integer?
    3. What does ABVector do as it is not in this tutorial but is in the sample project download?
    4. What code do I need to change or remove to eliminate the “Mask” and “Glow” as I don’t need them?

    I am making my own Trading Card Game computer game and these Canvas Tutorials are really helping me.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: