DaBooda Turbo v1.4 - Tutorial A
Mousing Around (Mouse Techniques)
Andrew "DaBooda" Stickney
August 08, 2004

Welcome to the first of the v1.4 tutorials, I am going to be covering all the new aspects of the engine as well as some old ones, and a few that have nothing to do with the engine, but have been asked of me to cover.

After running Tutorial - A, you might have thought... well it looks like garbage.  Well of course it isn't anything fancy, I am just trying to keep this as clean cut as possible, and showing you that v1.4 now has advanced mouse support.  I have added several techniques and functions into the engine that make handling the mouse 100% more functional.  Originally the mouse class just told you if it it moved or if a button was pressed, well that was very limited as a fellow contributor pointed out to me, so therefore I went back and realized he was right.  This is the product of this work, and without any further yapping, lets get into this thing.

I want to first point out, that initialization and all that jazz is the same, even the commands are the same, so transitioning from earlier versions is no big thing, so therefore I will cover only the new stuff.  Also if you are new to this Engine, I highly suggest going back and reading tutorials 1 to 8 for they cover the basics, and you will most likely be lost without knowing those... lets get on with this thing.


What Is Up With These Overlay Commands?

You might have been gandering at the code and you veterans might have noticed all the new commands within the overlay initialization routine, well lets cover these.

With Engine.DBOverlay
    .QMSetOverlayView 0, 0, 320, 480

First thing and probably most important.  We all know that the engine has a map view, that sets up a coordinate system for maps and sprites, but what about overlays, well here you go.  This sets up the coordinate system for overlays, and does some other stuff.  Consider this an alignment box, for alot of new commands that align and center overlays will use this view, so this must be set up.  You can set this up to anything you wish, for it is there for formatting overlays.

        .Add
        .SetTextureReference 1, 1
        .QMSetPutRectangle 1, 0, 0, 64, 32
        .QMSetGetRectangle 1, 0, 0, 64, 32
        .QMCenterOverlayX 1

The first four lines will be familiar to the veterans, but that last line well that is something new.  This is one of commands of what I like to call the alignment suite.  For these commands will do a special formatting for you.  Only you need to remember a few things, for one the origin of the overlay needs to be at the upper left corner, the overview has to be set up, and basically just experiment until you fill comfortable with them.  Try them all.  One more thing I have added a few new commands that need really no covering, but they are QM's to quickly set the origin of an overlay, you can use these to set the origin, and they don't move the overlay at all.  Nice huh....well maybe...

    For I = 2 To 10
        .AddFromSource 1
    Next I

This really isn't anything new, but I figure I would point it out.  I knew that I would have ten overlays, with the same properties, one exception being the position.  Well instead of creating 10 seperate objects, I used a loop to add from the first copy, this way I just had to set up one.  Do yourself a favor, save your fingers.... take this from a man who's fingers have become disfigured after typing that help file.

        .QMSpreadVertical 1, 10, 8
        .QMSpreadColorRed 1, 10, 0, 255
End With

Ok, now these two commands are something new also.  The first one is also part of the alignment suite, but it is a little special, for it takes a list of overlays and spreads them from the top of the overview to the bottom.  This is very handy for creating menus.  Be sure to look at the SpreadHorizontal and the CenterHorizontal and CenterVertical commands also.  The second command, thanks to Ander's simply takes a list of overlays and spreads a color from one end to the next.  There is a similar command for every color component, also to make them the same color, just use the same value for start and finish.


Ohhh.... a new render style.... and what the @#$% is scale all about?

The sprite init routine may seem very familiar to you, with the exception of two commands.

    .RenderNewStyle 5

New Style rendering is something I incorporated into v1.4 and what is does is let the engine know to use a DirectX8 sprite for sprites and even overlays if you wish.  Before I was using generic texture strips and during rotation they looked kinda bad, so here you go.  But I will tell you this, New style may look better but it has its limitations.  For one specular is out, for the fact that some idiot at Micro$oft decided the sprites didn't need it.  As for four corner coloring or irregular shaping, forget about that.  Basically I left it up to you to choose which one looks best and you can have either type at any time, for the only time the engine cares about this is right before it draws it.  By default sprites and overlays render in the old style and for more information on the two be sure to check the help file, for it gives a break down of what each can or cannot do.  But I will tell you this, change that line above in the program to RenderOldStyle and see the difference between the two.  Also since the color is for the whole sprite, new style gets its color from the Upper Left corner and how its drawn is actually by the distance between the Upper Left and Lower Right corners.  Do not worry you do not have to change any positioning or origins for the engine compensates for it all.

    .QMSetScale 5, 16

Ok, now this command.  Before you might have found out that the QMExpands would do the trick for making the sprite bigger, but it would permanentaly alter the size.  Well here you go, this actually only changes the size when it is being drawn or checked for any type of collision or hovering.  The size is determined in pixels so the above command actually makes it 32 pixels larger, 16 on each side.  You can add a scale to any corner, width, height, or even both.  Scale is much better for you can regain the size of the sprite, by simply setting it back to its default 0.


Ahh Right, multiple Fonts!

Yes the engine now has the capability to use multiple fonts on the screen at one time.  The limit being 16 of them, but honestly who would use more.  Lets look at the Text Init routine.

'initialize Text
With Engine.DBText
    .CreateFontMultiple 1, "timenewroman", 16
    .QMSetTextView 320, 0, 320, 480
    For I = 1 To 10
        .Add
        .SetFontIndex I, 1
        .SetVisible I, True
        .SetText I, "Text"
        .QMSetPutRectangle I, 0, 0, 37, 23
        .QMCenterTextX I
    Next I
    .QMSpreadVertical 1, 10, 8
End With

The first thing you might have noticed is the Text View, well guess what... yep does the same thing as the over and map view, except only the text follows it.

Now take a look at the new CreateFontMultiple command, this is the only way to create multiple fonts.  The old command is still there but what it does is create a font at index 0 which is the default for all text.  So to use multiple fonts, one must first create it, and then assign it as you can see by the SetFontIndex command.

The only two other things worth looking at are the alignment commands, these act the same as the overlay alignment suite, except they affect the text.  One thing to keep in mind with the text is that aligment occurs from the size of the put rectangle of the text, not the text itself.  Also with text you do not have to worry about origins for the origin is always at the upper left corner... just experiment, trust me it is the only way to learn.


An Easier Way To Deal With KeyInput!

Now you may have just glanced at this piece of code, but it isn't the same as before.

'Initialize KeyBoard
With Engine.DBKeyInput
    .Initialize Main.hWnd
    For I = 1 To 211
        .Add I
    Next I
End With

What I realized is that the DIK_Key commands where really constants, so instead of initializing a few keys to use, I decided to add them all.  Well this makes things easier, for when I do decide to read a key, I just have to use the corrosponding DIK_Key constant... pretty simple eh?


And Finally Some Mouse Routine.

Ok, Ok... I know I named this tutorial as if it was going be nothing but mouse routines, but give me a break I have to cover the new stuff first, but here you go.

'Initialize Mouse
With Engine.DBMouse
    .InitializeMouse Main.hWnd
    .SetUpMouseViewRect 0, 0, 640, 480
    .AttachSpriteToCursor 6
    .SetMouseSpeed 1
End With

Now most of this is new, except the initialization command.  Well lets take a look at the mouse view, I know what your thinking why not just make one view for everything, well I am covering all bases here and versatility is key here.  Well anyways, the mouse view is a little different than other views, for it tells the class where to keep the pointer at.  Basically the mouse will not leave this window at all, each poll command will check it, and it will not leave the boundaries. 

Now lets look at the next command, and this is where it gets interesting.  We all know that when DirectX8 takes over the mouse it says byebye to the cursor.  Well who needs that stupid pointer anyways, not when we can attach a sprite to the mouse.  This does that and during every render loop the mouse gets polled( that is right the mouse, keyboard, and joystick are now automatically polled) it updates the sprite to reflect the mouse position.  You can even still treat the sprite like a sprite.  The hot spot of the cursor is of course going to be the origin of the sprite.  Now you might be wondering, what about map view and how it effects the sprite. Well seeing how the sprite is effected by this, it will still be, so one thing to keep in mind that when using a sprite and the map view has a upper left corner other than 0,0... you should always leave the mouse view at 0,0, do not worry as long as you do this, the engine will compensate for the rest.  Just keep repeating this to your self, always keep the mouse view's upper left corner at 0,0...always keep... see it works.

Well some people might know this, but when your mouse moves it does not move at a constant velocity, that would be dumb, so it moves at a variable rate.  Well this still might not be that fast for you so you can multiply the rate with the last command.

The good news is that once the above is initialized you simply can let it go, for the engine will do the rest with the mouse... isn't that nice of it...

Oh and one last thing, notice that I attached sprite number 6 to the mouse, well go and take a look at the sprite init routine and see how I set that up.  Take note of the ZOrder, I had to set the sprite higher than the rest for the simple fact that the engine renders the text after the sprites, so I did that to get the sprite above the text.


Ok, Lets Do Some Hovering!

Ok, this is the last thing to cover but probably the most important when using the mouse.... hovering... you know like the internet explorer.

    'check mouse hover
    If Engine.DBMath.MouseHoverOverlayA(I) = True Then
        Engine.DBOverlay.QMSetSpecular I, 50, 50, 50
        Engine.DBOverlay.QMSetScale I, 5
    End If

This command does what it says it does, and it does just that, it checks to see if the mouse is over the overlay, and if so it returns true.  In which case I simply razzle dazzle the overlay to reflect this... pretty simple.  You might be wondering what the A stands for well I am getting to this... but first.

    'check mouse hover
    If Engine.DBMath.MouseHoverSpriteA(I) = True Then
        Engine.DBSprite.QMSetSpecular I, 50, 50, 50
        Engine.DBSprite.QMSetScale I, 5
    End If

Ok... looks pretty simple, but guess what I am checking the sprites now, and yes does the same thing, just with sprites... as for the A... well fine here you go...

'do odd sprite
If Engine.DBMath.MouseHoverSpriteB(5) = False Then
    Engine.DBSprite.SetRotationAngle 5, Angle
    Angle = Angle + 1
    If Angle > 359 Then Angle = 0
End If

There is a B now.... I am confused... but do not fret for the A and B just simply stand for two different checks.  Check A is for simple point in rect check, the point is either in or out of a rectangle.  Now B is a little more fancier for it checks to see if a point is in or out of a Polygon.  Overlays have the same checks for them.  Basically it is up to you which to use, but for rotating objects I suggest Type B, but I will warn you use sparngly for it uses API that can be a little processor intensive.  Also notice how I said false for the check instead of true, this is because I wanted it to spin until it hits the mouse... why... who know why...also if you click this while its running it will end the program.  Menu systems shouldn't be any problem for anybody with all these techniques...

One last thing....

    If Engine.DBMath.MouseHoverText(I) = True Then
        Engine.DBText.QMSetColor I, 255, 0, 150, 150
    End If

And yes even text gets a piece of the action.  There is only one type of check for text, this is because text will always be in rectangular form. 

Ok now that you have seen the mouse in work, you may think again, what about all these stupid views, well these checks compensate for each view.  So like I said earlier, always keep the mouse view at 0,0.... this will cause no problems this way.  And again experiment with the views, trust me no matter where you move them the mouse will always find them.  One way to keep track of how the mouse view works, is by realizing it is virtual and really just a setting for the mouse to stay in... this is all.


Ok, this is the end of the first in a series of tutorials covering v1.4, and I hope you are not more confused.  If you are go over the code, most are like me and learn by the code anyways.  Also do not worry there are so many more commands to learn and many more tutorials to read, so stay with it, but make sure you are comfortable before moving on.

I want you to do something next time you run this program, go ahead hit ctl_alt_delete... guess what not a single error and it even gives window's back its precious mouse... I fixed it, since the last version.  Also later we will discover how to do this in windowed mode... until the next tutorial, have a good day.

There is one error that occurs but very infrequently when using the mouse, but I have noticed it only happens if window's is running anything in the background.  Can I fix this, no, for it is a directX8 issue... sorry guys... I tried... but maybe someone has an idea, or maybe it even may be on my end.  I am the only one to recieve it or no ones notified me of this.

Oh, and please experiment, trash, rewrite this code.  This will help you learn trust me.  And if you have further questions feel free to email me at masterbooda@yahoo.com . There hasn't been one question un answered yet, trust me.