array maps

Blitz3D Forums/Blitz3D Beginners Area/array maps

mindstorms(Posted 2006) [#1]
I have a two dimensional array, and there are players, cpu people, and everything else moving about a 2d map. The players/ cpu/ everything else can be at any of the "cells" in the array. What is the best way, if something is moving, to mark new cells as occupied and unmark the old cells?


H&K(Posted 2006) [#2]
oldcell = 0
newcell = 1 ( Ok make this CPU or Player, that you have defined in an enum)


Ross C(Posted 2006) [#3]
You could build a type list. Each time something moves, post it's old co-ords into it, with a flag stating either insert or remove occupied status.

The program will search through this type list afterwards and make the nesessary changes.


Type postbox
   field x,y
   field flag ; 0 for remove occupied status. 1 for mark as occupied.
End Type



p.postbox = new postbox
p\x = arrayx
p\y = arrayy
p\flag = 0


Something like that?

Then, when it comes to process it:

For p.postbox = each postbox
   if p\flag = 0 then
      array(p\x,p\y) = <mark as empty>
   elseif p\flag = 1 then
      array(p\x,p\y) = <mark as occupied>
   end if
   delete p.postbox
Next



mindstorms(Posted 2006) [#4]
Ross, that's a good idea. I am still not sure as to the implementation of it, though. Your saying, when something moves, I should create a "postbox" that will then get rid of the occupiedness? Would it be simpler to include that into the type that makes up the players/cpu?


Ross C(Posted 2006) [#5]
Well, it might be. Depends on how often they change squares and how many enemies/players etc are on the go. It might be more efficent to do it my way, if less things move. But if nearly everything is changing squares, then yeah, your probably right :o)


mindstorms(Posted 2006) [#6]
I'm just saying that it looks like I have to have two fields in the player/cpu's type to store the old coordinates, and then when the coordinates of the player/cpu move to be in the next array cell I have to then do what you were saying. I have lots of players/cpus - otherwise it wouldn't be a fun game :)


H&K(Posted 2006) [#7]
You dont realy, if the player and the cpu are of the same type, then you could just use the array field to hold a pointer to that instance, as opposed to true or false, as we've been saying.
Or, if they are different types, hold a negative of the pointer if its a player, and a positive if its a cpu. (Unless Blitz3d doesnt have pointers.... but I think it does.)


mindstorms(Posted 2006) [#8]
What's a pointer? Is it the handle to the instance of the entity (such as player\entity = 5674321...)


Andy(Posted 2006) [#9]
>I have a two dimensional array, and there are players, cpu
>people, and everything else moving about a 2d map.
>The >players/ cpu/ everything else can be at any of
>the "cells" in the array. What is the best way, if
>something is moving, to mark new cells as occupied and
>unmark the old cells?

Why not just use an image buffer?


Andy


H&K(Posted 2006) [#10]
Andy, If you think about it all image buffers are arrays, but with a different command set, so its not actualy easyer to use an image buffer.
Mind, Yes a handle to the type is the same as a pointer to it. (But I ment a "Handle" to the player type, not a handle to the player model).


In war games there is no winning move if you are one of the pieces, not if you are the player. Why is there no sympathy for the pawns in chess?


mindstorms(Posted 2006) [#11]
The array is not visable...it is there to make sure players/units don't move in the same places...How would you get the handle to the type itself? I am creating about 50 cpu types that are just local. Whenever I want to access them I do a for each loop. Is this not the way I should be doing it?


mindstorms(Posted 2006) [#12]
Here is some code (that is not working)...I am wondering why?
(the code does not "see" other units)
Function find_open_build_spot(start_x,start_z)
Local h = 0
	Repeat
		If h > build_patternSize Then Return 0
		If (start_x < mapWidth*tilesize) And (start_x > 0) And (start_z < mapHeight*tilesize) And (start_z > 0) Then
			If walkability(Floor(start_x/tilesize),Floor(start_z/tilesize)) = walkable Then
				If unit_walkability(Floor(start_x/tilesize),Floor(start_z/tilesize)) = 0 Then 
					Return h-1
				End If
			EndIf
		EndIf
		start_x = start_x + build_pattern(h,1)	;build pattern h is the pointer to the next coords to try
		start_z = start_z + build_pattern(h,2)  ;relative to (x,y)...basically a spiral
		h = h + 1
	Forever
End Function



and in the main loop

for unit.unit = each unit
For i = -5 To 5
	For h = -5 To 5
		tempx = unit\xLoc/tilesize
		tempz = unit\zLoc/tilesize
		If i+tempx > 0 And i+tempx < mapWidth And h+tempz > 0 And h+tempz < mapHeight Then 
			If unit_walkability(i+tempx,h+tempz) = unit\entity Then 
				unit_walkability(i+tempx,h+tempz) = 0
			EndIf
		EndIf
	Next
Next
unit_walkability(unit\xLoc/tilesize,unit\zLoc/tilesize) = unit\entity
next


It is important to note that the build_pattern(x,y) point to the next cell coordinates


Ross C(Posted 2006) [#13]
Ok, so. Your moving players and CPU players. You store there location in a 2D grid. I assume you do this, so two players don't occupy the same grid square?

If so, then, each time a player goes to a new grid square, mark the old grid square unoccupied from the moment the player leaves, and at the same time, mark the new grid square occupied. Can't you do this from when you check each type object?


mindstorms(Posted 2006) [#14]
Shouldn't the above code do that? I am just updating the grid each loop instead of each move? (I changed the top, adding the for each loop...in the code that is in the updateunit function.)


Ross C(Posted 2006) [#15]
Ah, sorry, i didn't realise you had altered your code :) I'm afraid it's a bit beyond me right now to see if this would work...


mindstorms(Posted 2006) [#16]
It doesn't work...The units are not seen, but the other obstacles are. I was wondering why?


Andy(Posted 2006) [#17]
>Andy, If you think about it all image buffers are arrays,

Exactly!

>but with a different command set, so its not actualy
>easyer to use an image buffer.

Actually it is, but unless you need to scroll a tilemap, then you don't need it.


Andy


H&K(Posted 2006) [#18]
There is no "actually it is", he only wants to turn an element/pixel on and off. ( But yes I do agree with you, there are times when a pixel map is better than an array, for example, its a lot easyer to save and copy an image map)


mindstorms(Posted 2006) [#19]
Wait, are you guys saying that I should be using an image with (say white and black) pixels representing the "field of play" instead of an array? I don't think this solves the problem...


H&K(Posted 2006) [#20]
no, its just another way to do it.


mindstorms(Posted 2006) [#21]
I just am wondering why the array does not seem to match when I set the values as to when I retrieve the values.


Andy(Posted 2006) [#22]
>There is no "actually it is"

Actually there is:)

I was responding to this:
>so its not actualy
>easyer to use an image buffer.

If you need to scroll tiles, then using an image buffer is actually easier to use. Copyrect is your friend!


Andy


Buggy(Posted 2006) [#23]
How would an image map work? Wouldn't those pixels need to use an array or types as previously mentioned?


Nicstt(Posted 2006) [#24]
perhaps depends on complexity or number of images in the image

hold the image in program as normal, say:

gfxLevel = loadimage ("F:\Documents and Settings\Administrator.NSTT1\My Documents\Blitz Progs\test.bmp")

then when you want a speficic image

rough example:

for a = 0 to 9 step 2
copyrect gfxLevel, a * 256, 0, 256, 256, imagebuffer(gfxLevel), backbuffer()
next

or
need = 5

copyrect gfxLevel, need * 256, 0, 256, 256, imagebuffer(gfxLevel), backbuffer()

Edit: hmmm no matter i misread question


H&K(Posted 2006) [#25]
@ Andy, in a situation when all you want to do is hold TRUE or False, An image map is NOT actually easyer than an array.

I am not saying you are wrong, (cos you are not), I often use Image maps for, (at the least), saving the "array" to disk. (after all a height map is just an array). But Minds question started with "I have a two dimensional array", so turning round and saying you can use an image map, (when he cannot use an array properly) was not actually helpful. ;)

@ Mindstorm. An Image is made up of losts of values stored next to each other, pixel (0,0) pixel (0,1) etc This as you can see if the same as an array Pix(0,0), pix (0,0). When You want a two dimentional array (or sometimes 3), you can see that a imagemap is the same thing. Often if you want 3 Two dimentional arrays, and you know that the max value in each cell will be less than 255, you can still use 1 image (x,y,red) (x,y,Green) (X,y,Blue).
In the situation you described your problem seems to be that you are miscalculating which cell to look at, and that the problem is not that you are not using an image.


Andy(Posted 2006) [#26]
>@ Andy, in a situation when all you want to do is hold
>TRUE or False, An image map is NOT actually easyer than an
>array.

I agree.

>But Minds question started with "I have a two dimensional
>array", so turning round and saying you can use an image
>map, (when he cannot use an array properly) was not
>actually helpful. ;)

According to the first post, he has a basic game up and running and according to later posts he understands enough to deal with types. Perhaps you are underestimating mindstorm.

However, mastering the basics of BASIC is nessesary before moving on, and Arrays are certainly basic stuff in BASIC.


Andy


mindstorms(Posted 2006) [#27]
Well, I thought I had them mastered, and have been using them for several months now, but I just can't seem to find the problem with this particular code...Would the above code mess up if the actual position of the player/cpu was not the exact coordinates of where the array thinks it is? I was running some tests, and the player is always at 101.5,101.5 instead of 99,99. I think this is a rounding error, because I call the floor(unit\xLox/tilesize) to determine the latter. Would the rounding error cause the problem?


Sir Gak(Posted 2006) [#28]
Numbers with decimal places are floating. Do you want whole numbers? If so, use integers.

Second, your code shows several variable names inside your Function (i.e. build_patternSize, mapWidth, mapHeight, etc). Are these variables global? If not, then they are zero-value inside the Function.


mindstorms(Posted 2006) [#29]
The mapWidth, mapHeight, build_patternsize, tilesize are all constants declared in another include file. The reason I am trying to convert from floating point to integer is so that my array will work....The position is floating point while the array has to be integer...I think the converting process somewhere is wrong...Does this sound right?


H&K(Posted 2006) [#30]
Ok, strange question Does the position data HAVE to be floats.
The Main Reason I ask, is that I, (And I assume Ross), had been giving what help we could on the assumption that the objects (player/cpu etc) on the map could either be in a square, or not be in a square. If the value of position is a float (ie not concurrent with the map), then the units/objects can be in upto 4 map squares at once (and more if they are bigger than a square)

For example if you look at say starcraft, although it looks like the units can be (say) 2 and a half map squares from the bottom, they are in fact 5 (say) Unitmap squares from the bottom. I would advise, that if at all posible dont use floats for positon. So if the most float you have is a quarter, then multiply the map by 4. So 1.25 becomes 5.
I realise that once you start to use 3d, then all this goes out of the window. (I still try and stick to whole numbers, and move things from whole number node to whole number node), But honestly, the more of your variables you can make ints, the better


mindstorms(Posted 2006) [#31]
They are slightly smaller than the square's size...sorry for not telling... The way they move is by A* pathfinding (I have heavily modified some code from the code archives over the course of several months). The way I want the units to be declared on the grid is on the square that they are most in (ie their center). This I thought would be possible by taking their position and converting to the array coordinates, but I think I am wrong ( the unit_walkability map does not represent the playing field fully, but is more of a representation to get an idea of where units are located and what squares to avoid.)


H&K(Posted 2006) [#32]
I would rewrite it so that the path finding nodes are all on whole numbers of the map. I would also try to rewite it so that every game cycle the units are also on a whole number of the map.

Basicaly you want

tempx = unit\xLoc/tilesize
to always be a whole number.

So. Where Have you Declared tempX. Because from what you just said Tempx will be a float, and just maybe you havent declared it so?
Local Tempx# = unit\xLoc/TileSize


mindstorms(Posted 2006) [#33]
I declare it as a float right above that code (don't know why i didn't include it...) I changed the code to this, hoping to make it simpler and to isolate the problem:

Function MoveUnit(unit.unit)
	unit_walkability(Floor(unit\xLoc/tilesize),Floor(unit\zLoc/tilesize)) = 0
	;Move toward the next path node
	remainingDistance# = MoveTowardNode#(unit.unit,unit\speed)	
	
	;If there is any remaining distance left after moving toward the node, then
	;check for path step advances and move to the next one. This two step
	;process ensures smooth movement from node to node.
	If remainingDistance <> 0 And unit\startNewPath = False	
		MoveTowardNode#(unit.unit,remainingDistance#)		
	End If
	PositionEntity unit\point\entity,unit\xLoc,0,unit\zLoc,True
	PointEntity unit\entity,unit\point\entity
	PositionEntity unit\entity,unit\xLoc,0,unit\zLoc,True
	unit_walkability(Floor#(unit\xLoc/tilesize),Floor#(unit\zLoc/tilesize)) = unit\entity		
End Function

Function MoveTowardNode#(unit.unit,distanceTravelled#)
	CheckPathStepAdvance(unit.unit)
	If unit\pathStatus <> found Then Return
	If distanceTravelled# <= unit\distanceToNextNode#
		xVector# = unit\xPath-unit\xLoc
		zVector# = unit\zPath-unit\zLoc	
		angle# = ATan2(zVector#,xVector#)
		unit\xLoc = unit\xLoc + Cos(angle)*distanceTravelled
		unit\zLoc = unit\zLoc + Sin(angle)*distanceTravelled
		unit\distanceToNextNode# = unit\distanceToNextNode#-distanceTravelled# 
	Else ;next path node has been reached
		unit\xLoc = unit\xPath : unit\zLoc = unit\zPath	
		remainingDistance# = distanceTravelled#-unit\distanceToNextNode# 
		unit\distanceToNextNode = 0
		Return remainingDistance#	
	End If	
End Function



does this completely change it and is a bad idea, or does it help to simplify the problem?

If the player/cpu was to move to each square each turn, it would be moving at lightspee! Right now it moves about .2 units per square.

I fixed the bug where the unit was placed in the wrong position! Thanks to everyone who helped with that one, it was a error when I changed the program from being 2d ( my original idea) to 3d (what it is now).

*By the way, in Blitz3d mode what is the unit size? It definately doesn't seem to be pixels, because a cube 1,1,1 is fairly huge...*


H&K(Posted 2006) [#34]
The program model is yours. It is not for us to say if its a bad Idea or not. Also unless the problem is an obvious one of syntax or conception, nobody else but you will be able to find the error.

Run you program in Debug, and put loads of checks on the variables you expect are to blame. Everyone learns more by finding their own mistakes, and in this sort of case you are the only one who could find them anyway.


Sir Gak(Posted 2006) [#35]
If we told you it was bad, you would be sad; if we told you it was good, you would ask why then doesn't it work, and so be sad. So, we won't say one way or the other, so you can be glad so many fine people are helping.

I know that pathfinding works with answers that can be floating (ie fractions). So, why not use whole numbers for the position, but use floats for the answers resulting from the pathfinding calculations? That way, you still get to compare one float against another for the results, but you won't have confusion in the whole number positions


H&K(Posted 2006) [#36]
I thought I was saying I couldnt see what was wrong, so dont ask me again, cos I'll be sad :(


mindstorms(Posted 2006) [#37]
Thanks for the help guys, I will keep working on it.