Game Development Community

SetLayer causes image to disapear?

by Martin Askestad · in Torque Game Builder · 08/02/2005 (1:20 pm) · 14 replies

When I add the $player.setLayer(1); line to my script. The sprite disapears. Do I have to do something to tell T2D wich layers I want to use or something??

Added my code just for reference
$player = new fxStaticSprite2d() { scenegraph = t2dscenegraph; };
	$player.setPosition("0 0");
	$player.setSize("2 2");
	$player.setImageMap(playerSpehere);
	$player.setLayer(1);

#1
08/02/2005 (1:57 pm)
Are you sure you don't have a script error? For example, should that read: $player.setImageMap(playerSphere); ?

I use layers with no problems and you don't need to do anything special.
#2
08/02/2005 (2:26 pm)
This can be caused by having some sort of image map on another layer overlapping player. The way layers work is semi wierd in my opinion. If I am on layer 20, then anything in 21 and loweris below me. ( I personally think it should be opposite ). Are you sure you dont have a sprite in which you dont define the layer? If you dont define a layer it works by drawn. The last thing drawn is the first thing ontop.
#3
08/02/2005 (2:49 pm)
Sigh!
Would seem like I set the layers in reverse. I had my neat scrolling background set to Layer 0... wich caused it to be drawn above the sphere.
#4
08/02/2005 (2:52 pm)
So layer 0 is always the "front" layer? Definetly seems backwards to me.
#5
08/02/2005 (4:42 pm)
It's just like arrays, index 0 is always the top. And thus layer 0 is always the top.

In programming, you should get used to having 0 being the start.

If you dont program this way currently, I strongly suggest re-evaluating your patterns and practices...
#6
08/02/2005 (9:28 pm)
Quote:In programming, you should get used to having 0 being the start.

It's not the question of a 0-base or 1-base index. It's the question of which layer is at the top of the stack and which is at the bottom. Arrays are, conceptually, horizontal, so there is no natural idea that index 0 of an array is on top of index 1. Indeed, the natural inclincation for such things is a less-than check. If my layer is less than yours, then I am below you. Less means below, so it makes sense. Having smaller layer indices mean closer to the top is just wierd.

It's probably not going to be changed, of course, as doing so would be pretty backwards-incompatible. However, it is an idiosincrocy.
#7
08/03/2005 (7:04 am)
Got to agree with Smaug on this.

Layers imply one above the other. Think about layers of clothes on an Eskimo. The first layer you put on will be below the second layer you put on etc. etc.

This is something that can be solved by simply educating artists and users into thinking of the layers as going into the screen instead of out of it. Once you know which way the layers go, you are unlikely to make the same mistake twice.
#8
08/03/2005 (7:41 am)
I would tend to disagree as it depends very much on your mental picture.

If I had a stack of paper in front of me and someone asked me to get the 9th sheet I wouldnt start counting from the bottom of the pile - they would think I was strange :)
#9
08/03/2005 (8:06 am)
Why not just setup:

$backgroundLayer=31
$scrollyCloudsLayer=30
$playerLayer=20
$enemyLayer=15

Then you just need:

$player.setLayer($playerLayer)

Then you can mess about with your layers without having to recode lots of things everytime.

Leaving a bit of a gap between the layers allows you insert new items without having to change your existing layers.
#10
08/03/2005 (8:17 am)
I would disagree, at least for me and how I imagine it. When I think the layer numbers I do come to an array... and though an array may be horizontal the way I imagine it (though obviously inaccurate in certain ways, this is just how the numbers are imagined by me)...

array[0] = sprites
array[1] = sprites sprites
array[2] = sprites sprites sprites


and I think of it in reverse order of being rended, where 0 will always be last to be thrown on screen (hence in front)... or the inverse of such I think of it as order from front to back... since

array[
0, 1, 2]
to me it make sense that I should imagine those like the layers on the screen from a side view.

in my opinion 0 should always be the closest layer to the screen, it makes it much easier to ensure somethings on the screen, instead of having to get a count of the current layers and setting it to the end, which then becomes void if you were to add more layers)... 0 will always be the layer in front... but I can understand people getting mixed up as well
#11
08/03/2005 (11:45 am)
Quote:in my opinion 0 should always be the closest layer to the screen, it makes it much easier to ensure somethings on the screen, instead of having to get a count of the current layers and setting it to the end, which then becomes void if you were to add more layers)... 0 will always be the layer in front...

But the opposite is true as well. Setting something to layer 0 doesn't guarentee that it is visible, as it can be occluded by other things in layer 0 (given draw order). Whereas if you know that you are only using up to layer 25, putting objects into layer 26 will guarentee until you start using layer 27.

Technically, I'm not even sure that having layers be hard-indexed at all is a good idea. It would probably be a better system to make it so that layers are named (possibly with integers, but with user-defined names whatever those names may be), and that you can create and insert them anywhere. That is, you can create a new layer that exists above or below a given one in the stack. Then, you just use the name whenever you are referring to a particular layer. Layer lookup is pretty rare; it only happens when you switch the layer that a sprite is in, so it wouldn't be a performance issue.

Note that this remapping could easily be done as a layer (no pun intended) on the already existing layer system, so there's no need to have the internal system do the virtuallization.
#12
08/03/2005 (1:38 pm)
One incongruity is that the existing TGE functionality for Canvas.pushDialog takes an optional second parameter of layer (GUI layers; completely separate from T2D's implementation of layers) and is zero-is-bottom oriented. Would be nice if they were both the same, whichever that 'same' may be.
#13
08/04/2005 (3:05 am)
A quick, dirty and pretty effective way to reverse this order if it's a problem is to simply render the objects in the reverse order. To do this you can change the following line in "void fxSceneGraph2D::renderView()":-
for ( S32 layer = t2dSceneGraph::maxLayersSupported-1; layer >= 0 ; layer-- )
... to ...
for ( S32 layer = 0; layer < t2dSceneGraph::maxLayersSupported; layer++ )

This shouldn't break anything but you need to be careful with a few things, namely the picking routines that return things from the front->back would now be passing you things in the same order but would effectively be back->front. Also, the rarely used "fxSceneGraph2D::setLayerDrawOrder()/setSceneDrawOrder()" work fine but do things 'backwards'.

More importantly, the default for the scenegraph is to place objects that are created within the same layer (as Smaug quite rightly pointed-out), in-front of older objects. If you still want this to be the case, you can easily change the default from scripts using the documented "fxSceneGraph2D::initialise()" function or datablock initialisation. This would look like this:-
new fxSceneGraph2D(myScene);
myScene.initialise( 20, 256, true, false );

This is off the top of my head so I may have missed something but this should work if someone wants to give it a try.

I think Smaug has a good view on this subject in that virtualising the layers could be (and should be) done using names such as $effectsLayer, $hudLayer, $pickupsLayer or potentially a more sophisticated setup.

- Melv.
#14
08/04/2005 (8:24 am)
@Smaug: good point about not always being in front, though when you set it to Layer 0 it will be thrown to the front that first time... and if you reserve layer 0 for only things that need to be in the closest layer it can work quite well...

I agree with the names, though its very easy to simply make a global (like Melv points out) for it presently... here is my setup for my RTS in a day and it was a very quick setup, simplifies things nicely


$collision::circleGroup = 1;
	$collision::squareGroup = 1;

	$collision::circleLayer = 1;
	$collision::squareLayer = 1;

	$collision::baseLayer = 5;
	$collision::baseGroup = 5;

	$collision::goldLayer = 6;
	$collision::goldGroup = 6;

	$collision::farmLayer = 7;
	$collision::farmGroup = 7;	

	$collision::goldMineLayer = 8;
	$collision::goldMineGroup = 8;	

	$collision::sets::mapGroupMask = BIT($collision::circleGroup) | BIT($collision::squareGroup);
	$collision::sets::mapLayerMask = BIT($collision::circleLayer) | BIT($collision::squareLayer);

	$collision::sets::circleGroupMask = BIT($collision::squareGroup) | BIT($collision::goldGroup) | BIT($collision::farmGroup) | BIT($collision::baseGroup) | BIT($collision::goldMineLayer);
	$collision::sets::circleLayerMask = BIT($collision::squareLayer) | BIT($collision::goldLayer) | BIT($collision::farmLayer) | BIT($collision::baseLayer) | BIT($collision::goldMineGroup);


	$collision::sets::squareGroupMask = BIT($collision::circleGroup) | BIT($collision::goldGroup) | BIT($collision::farmGroup) | BIT($collision::baseGroup) | BIT($collision::goldMineLayer);
	$collision::sets::squareLayerMask = BIT($collision::circleLayer) | BIT($collision::goldLayer) | BIT($collision::farmLayer) | BIT($collision::baseLayer) | BIT($collision::goldMineGroup);