Stacking issues

Blitz3D Forums/Blitz3D Beginners Area/Stacking issues

PCBGuy(Posted 2004) [#1]
First I want to thank Soja, Perturbatio and Wolron for their help. It got me pretty far down the road. Now I have a nagging issue with image "counter" stacking. I have counters moving all over the board and sometimes they stack up in one "32x32pixelsquare" 5 deep. As I mouse click each counter I cannot figure out how to control the stacking order so I can choose which counter to pick. here is the following brief example of a larger problem:

Any takers out there. I have been struggling with this one for days and now I've had it!


Sunteam Software(Posted 2004) [#2]
You could add a field that holds the height. When a counter is added to a square you do a check to count how many others are already on it and then add 1 and store it as the height. Then when you click on a square the first one to be picked will be the one with the highest height (LIFO = last in first out).

Hope that helps.


Perturbatio(Posted 2004) [#3]
you could have a 3 dimensional array (x,y,z) for the board and simply add the counter into the first available slot in the z-dimension and when you move a counter, it will be the one in the highest index of the z dimension.


PCBGuy(Posted 2004) [#4]
Sunteam, I like your idea. You said "do a check to count how many others are already on it and then add 1 and store it as the heights"
The thing is I am using a type: counter and a type: square.
Infact was already on your track but could not pass the final heights in type:sq to all the type:counters in that square.
Using the example below can you give me a code example of what you mean?



Note:
As you can see I use "act" variables for the "inst" instances to process (2) types, one type within the other. It has to be this way for the game!
I loop through the whole thing four times to put four counters into the sq.
Also I need to close the actives to process the other data!


Sunteam Software(Posted 2004) [#5]
Errrm ok, that code doesn't make much sense to me as I can't see how that works. For example you have a While without a condition, this immediately throws an error at me?!

Also you have height fields in both. So my questions at the moment would be:

1. how does the mouse interaction work? (is it click->drag->drop or click->click to drop?)

2. why are you using the mouse x/y coords with an 'equal to' check of the counter position? Are all the counters 1x1 in dimension?

A couple of other things to note, you don't have any 'End Type' statements, this throws errors up! Also you don't have a 'Next' for your embedded 'For' statement?!

Having said all this, let's see if I can show you an example of the method I was describing. I would work on the basis of using functions to handle these as Types can be accessed anywhere in the program and it makes for neater programming :)

I'll presume that counters are placed on the squares to a maximum height of 4 counters on a square, and that the last counter placed on the square is always the first selected when the mouse if clicked on it.

Also as your not moving the squares around (I presume only the counters move), I will remove the square type as it is not required, i.e. it is represented but not necessary to track.

Type counter
	Field sqx	;x square location
	Field sqy	;y square location
	Field cheight	; height on square
End Type

; FUNCTION: MoveCounter
;
; Pass the FROM square x and y and the TO square x and y
;
; Returns true if successful or false if the square is full (4 counters)
;
Function MoveCounter(fromsqx,fromsqy,tosqx,tosqy)
	;cf1-cf4 temp var holds pointers to any found counters on the from square
	Local cf1.counter,cf2.counter,cf3.counter,cf4.counter
	;ct1-ct4 temp var holds pointers to any found counters on the to square
	Local ct1.counter,ct2.counter,ct3.counter,ct4.counter
	;ctm is the pointer to the counter that is moving
	Local ctm.counter
	;c.counter is a temp var used for the loops only
	Local c.counter
	
	;loop through counters to find those on the from square and work out the counter that is moving
	For c.counter=Each counter
		;if the current counter in the loop is on our from square...
		If c\sqx=fromsqx And c\sqy=fromsqy Then
			;determine the height and place it in the relevant cf? var
			Select c\cheight
				Case 1
					cf1=c
				Case 2
					cf2=c
				Case 3
					cf3=c
				Case 4
					cf4=c
			End Select
		EndIf
	Next
	
	;work out the topmost counter on the from square and place a pointer in ctm.counter
	If cf4<>Null Then
		ctm=cf4
	ElseIf cf3<>Null Then
		ctm=cf3
	ElseIf cf2<>Null Then
		ctm=cf2
	ElseIf cf1<>Null Then
		ctm=cf1
	EndIf
	
	;loop through counters to find those on the to square
	For c.counter=Each counter
		;if the current counter in the loop is on our to square...
		If c\sqx=tosqx And c\sqy=tosqy Then
			;determine the height and place it in the relevant ct? var
			Select c\cheight
				Case 1
					ct1=c
				Case 2
					ct2=c
				Case 3
					ct3=c
				Case 4
					ct4=c
			End Select
		EndIf
	Next
	
	;work out the topmost counter on the to square and update the counter that is moving to be the topmost
	;NB: if there are already 4 counters on the square then the counter to move can't be moved!
	If ct1=Null Then
		ctm\sqx=tosqx
		ctm\sqy=tosqy
		ctm\cheight=1
	ElseIf ct2=Null Then
		ctm\sqx=tosqx
		ctm\sqy=tosqy
		ctm\cheight=2
	ElseIf ct3=Null Then
		ctm\sqx=tosqx
		ctm\sqy=tosqy
		ctm\cheight=3
	ElseIf ct4=Null Then
		ctm\sqx=tosqx
		ctm\sqy=tosqy
		ctm\cheight=4
	Else
		;already 4 on square so return false
		Return False
	EndIf
	
	;if we get to here then the counter was successfully moved so we return true
	Return True
	
End Function


*phew that took a while :)

I haven't tested it as I obviously don't have anything to test it with but I think the logic should work ok :)

Let me know if you have any questions or can better explain how your game is intending to use this code/data.


PCBGuy(Posted 2004) [#6]
Thanks so much for the hard worked reply. I will look it over carefully, then get back to you. By the way the code I showed you was a chopped shortcut hack job of the real code (That actually works quite well) so alot of stuff was left out. Again thanks for all the effort!!!!


Sunteam Software(Posted 2004) [#7]
No problem, I did kinda guess the code was incomplete, the problem is that it was sooo incomplete it was very difficult to understand how it was being implemented. A little more next time please :)


PCBGuy(Posted 2004) [#8]
Ok I ran into the same problem. I cant pass data back from cf# to ctm as in your example (If cf4<>Null Then ctm=cf4 etc..) The ctm (actBG in my case) is null. I know you want me to close the loop after ( Select c\cheight Case 1 cf1=c etc...) but my shortened code sample below shows that it can't be done without hosing the program. Note: program works fully as it is now but without stack ordering!

I translated your code to mine and found what i was trying to do in the instance of the type, you where doing with multible variables of the type, KOOL! Now if I can only get it to work. I hope you can help me on this, thanks for everything so far!!!!!


Sunteam Software(Posted 2004) [#9]
Right, this is not making a lot of sense to me. Why:

I don't understand why your now holding source and destination x,y's in the type, it's not necessary??!

..and you certainly don't need activex,y in there?? do you?

Please bear in mind that every instance of a type takes up the same space which is defined by the fields, so if you have 10 fields and you have 100 types in the list, each of those 100 types will have those 10 fields, whether you use em or not. The reason I used vars is because they were not needed in the type, in fact they were only needed once per iteration of the checking loop they were used in, so using vars makes all the sense!

stackorder = height??

You whole mousehit loop isn't making much sense to me, actbg will always be null because even if you get to a situation where you can set actbg=instbg, because it is in a loop, on the next iteration it will set actbg to null again?? why? The ONLY time it won't be null is if the last bg in the type list happens to match your criteria for setting actbg=instbg.

I am trying to understand but it's always difficult reading someone else's code, so it's not a dig just one of those learny curve things :D


PCBGuy(Posted 2004) [#10]
Please read the comments in my code.
ActBG will not always be Null because as a "variable of a type" if you dont declare the var Null its still holds the instance you have in it. If when processing a condition and var finds the match in one of the instances then var takes on that instance not the last instance in the type.
The use of the different XY's is for the conditions in my functions like my Final Undo, Draws, Moves etc and for checking the process altogether with Writeout files. The write out files will show me with the different xys how my functions handles or didnt handle the activeXY data.
The Mouse loop is as I said in the notes. It passes through once to pick up the counter then passes through again to put it down. The first pass has its conditions and the second pass has its.
This program is a variation on Soja "template" which was an advanced version of Perturbatio's counter controller program. I am extremely pleased with its heartyness so far.
I do not want to rewrite this program so any solution that does I wont consider. I dont have the time or desire to rewrite this from scratch, atleast not now.
I did find one thing. While trying to do everything at once, I forgot the basic tracking of "from" squares. I also found its resolution of the problem by using a modified version of my Final Undo because it performs flawlessly. It performs after ActBG is turned off and that was my problem in the first place, that I could not control the instances after I turned of the actBG.
I hope that clarified the issue. I may also be able to solve the stacking issue with the instbg\Stackorder. I have to track a Defender stack and an Agressor stack and all in the same square so thereby being in the same instance, I don't want to track it in the Counters Type at least not yet, It again will mean major rework. and redoing all my .data streams. For now I am still resolving the "from" square issue I won't get to the stack issue for a while.
When I finish my "from" square solution I may have the answer and if not I will look into your "multiple var of a type" solution. If you can still make any sense of this then I will appreciate any other input otherwise,
Thanks for all your help.


Sunteam Software(Posted 2004) [#11]
I think my brain is now dribbling... nope didn't understand much of that so all I can do is wish you luck with it all :)