Game Development Community

Am I missing something painfully obvious? (Mouse functions)

by Daniel Ravipinto · in Torque Game Builder · 08/17/2006 (2:11 pm) · 7 replies

Hello!

I've been playing around with TGB for a bit, trying out what is (to my mind) a very simple exercise -- can I place down a map (sprite) and then have the user click various territories in it and respond somehow (simple, basic interface stuff for a strategy game, right?).

I've read through the examples (the strategy one in particular) and thought I understood what was going on...but apparently not.

There seems to be two layers of information: the 'physical' image of the map, and the 'logical' concept of territories and the like.

So I created a simple territory class, in a seperate file called territory.cs and I've called that file from my game.cs by adding:

exec("./territory.cs");

territory.cs contains the following:

function Territory::onLevelLoaded(%this, %scenegraph)
{
%this.setUseMouseEvents(true);
}

function Territory::onMouseDown(%this, %modifier, %worldPos, %mouseClicks)
{
echo ("click!");
echo (%this.name);
}

Next, I create a Scene Object (from under the 'Other' menu) and place it over the territory.

[A side question: is it possible to create scene objects in a shape other than rectangular? I'd like to better-fit the territories, as rectangular spaces would cause overlap and confusion on which territory the user is clicking...]

[Another side question: Is there a better way of representing the logical layout of the board other than using Scene Objects?]

I click "Edit" and then "Scripting", give the Scene Object a name (the name of the territory), as well as the proper class ("Territory") and I click "use Mouse Events".

To make sure my class code pulls over, I quit and restart TGB (after saving the level).

I run the test. This is what happens:

The console says it's executing my territory.cs, as well as the t2d file of the first level.

I click on the map. ANYWHERE on the map (either inside the Object or outside) and I get:

click!
[blank space]

Clearly, the event is going off, but it's being set off by an unnamed object that is NOT the territory. I purposefully named every object in the object tree (the scenegraph, the staticsprite of the map, the scene object, and the default tile map).

So:

(1) Why isn't the callback only called by the Territory (the onMouseDown if specifically for the Territory class)?
(2) What *is* causing the callback? What is the unnamed object?

In other words, what the heck am I missing here? :)

Thanks in advance to anyone who can help me!

--d

About the author

Recent Threads


#1
08/17/2006 (3:26 pm)
When you say blank do you mean that it enters a blank line in the command window?
Are you getting any other errors on start up?

I haven't read through your logic completely and will do so after I eat. Just curious as to what is appearing in your console
#2
08/17/2006 (4:00 pm)
Ok I'm back

Since your only testing , you should be using the scene window as the place for your function. I don't think the other call is neccesary.
by default the scene windows name is sceneWindow2D

So, if I remember correctly if you typed


function sceneWindow2D::onMouseDown(%this, %modifier, %worldPos, %mouseClicks)
{
echo ("click!");

}
and saved it in your game.cs file, it should work properly.

Remember that %this refers to the object that is calling the function and I don't think name is a valid name for the scene object but I may be wrong

Check this link out. It may be more helpful then my rusty coding.
tdn.garagegames.com/wiki/TGB/MiniTutorials/ObjectMouseEvents

Edit: fixed some stuff and added the tuturial link
#3
08/17/2006 (6:31 pm)
It can't be the scene window, otherwise you would be getting sceneWindow2D for the name. Are you sure you set the name field in the scripting rollout in TGB for the territory object correctly? If not it won't have a name and that would explain the blank space. If you try echo(%this) in your onLevelLoaded and onMouseDown you should see:

Click!
[ID]

Cross-check those ID's with the list of ID's at the top (from the onLevelLoaded calls) to make sure you're getting your territory objects.

If that doesn't reveal your problem, try putting %this.dump() or %this.dumpClassHierarchy() in your onMouseDown callback to see exactly what it is that's getting the mouse click.

Hope this helps.
#4
08/18/2006 (2:54 am)
First -- thanks to Charlie and Thomas for your help. :) I think I've figured out what's going on. It's a combination of a couple of things.

First, following the tutorial Charlie linked to, I updated my code to the following for territories:

function Territory::onLevelLoaded(%this, %scenegraph)
{
// make sure the scene window is set to send mouse events to objects
if(!sceneWindow2D.getUseObjectMouseEvents())
{
sceneWindow2D.setUseObjectMouseEvents(true);
}

// set this object to accept mouse events
%this.setUseMouseEvents(true);

echo ("loaded");
echo (%this);
}

I think this is made a huge difference (the if statement forcing sceneWindow2D to Use Object Mouse Events).

Second, I think Thomas is correct in that %this.name (or even %this.Name) resolves to NOTHING, basically. You can't access an object's name this way.

When I changed my code to

echo ("click!");
echo (%this);

I started getting IDs, as he indicated I would.

Which begs the question of how one gains access to the Name of an Object normally?

I created a variable in the Territory class called territoryname and my code now looks like this:

function Territory::onMouseDown(%this, %modifier, %worldPosition, %clicks)
{
echo ("click!");
echo (%this.territoryname);
}

This seems to work.

So short of having a repeated variable (Name and TerritoryName are really the same thing), I think I have it doing what I want. :)

I was a little worried about overlap/odd shapes on the map, but in all honesty, it seems to be working pretty well. I'm sure there are areas (a penninsula here and there) that won't respond when you click, but for now the rectangular SceneObjects (rotated a bit when necessary) seem to be close enough.

Just to check: are invisible SceneObjects the best way to overlay logical functionality over a map? Or is there some other possibility I'm missing?

Thanks again!

-- d
#5
08/18/2006 (8:08 am)
Daniel:
You can use %this.getName() to get the name of the object, similiar to .getWidth(), .getID(), etc.
#6
08/18/2006 (8:19 am)
Nick:

Perfect! Thanks for that. :)

I guess the only thing left is: how can I best shape a SceneObject to fit non-rectangular spaces on an image (territories on my map)? I'm using SceneObjects and rotating them to try and get a best fit, but there's still some overlap and the like.

Short of that, I've got everything working. Thanks everyone!

[EDIT:]

Actually, fiddling around, I found that editing the SceneObject's collision polygon gets me pretty darn close to fitting only the shape of the territories (although the shapes have to be convex and a few of my territories are concave, I can still get darn close...).

I guess that's about it! If anyone else has any advice, I'd be glad to hear it. Thanks again to everyone who helped me out with this!

-- d
#7
08/18/2006 (9:00 pm)
No problem. Good luck with your project!

Be sure to post your progress in the "Show Off" thread when youre ready to share. I would love to see what you've got going (you got me curious).