Hi guys,
So I've been working on a level editor that heavily relies on array lists to keep track of object properties, what type of object an object is and various other details that my game will need for re-creating the level at runtime.
My problem is that whenever I create an object, I instantly add it to the array list using "array insert at bottom arrayName()", and then I modify certain variables right then and there within the array (like what type of object it is). This works great and exactly how I want it to. So why is it a problem?
The problem shows up when I go to delete an object that isn't the last object in the array list (i.e., the last element in the array list). For example, say I created 10 objects on the screen. I go to delete object 4 out of 10. I do so, and now I delete the element from the array with the "array delete element arrayName(index)" command. But then if I click on object 10, the program crashes because the program is convinced that array element(9) no longer exists!
I thought I could get around the problem by making sure to specify what element each object gets put in to, and then when I go to delete the object I use another variable that holds the currently selected object's number to specify that I want THAT array element deleted. BUT THIS STILL SHRINKS THE ARRAY LIST, even though I specified what element to delete. It doesn't matter, it still shrinks the list.
Is there ANY workaround to this, or do I have to use an element with a set size and then do clever sorting later?
Here's all of my code so far...
Remstart ******************************************
A Little Epic Level Editor
******************************************** Remend
Rem Call all of the setup routines
gosub setupFile
gosub setupData
Rem Make "filler" object for first array element
createObject(1)
hide object 1
Rem Set collision off so it doesn't interfere with the cursor
set object collision off 1
Rem Reset "amountOfObjects" variable so it doesn't confuse the user
amountOfObjects = 0
Rem Initialize Cloggy's D3D
d3d_init
do
d3d_box 800, 0, 1024, 600, rgb(255, 255, 255)
d3d_box 801, 1, 1023, 599, rgb(25, 25,25)
text 802, 0, "Array count " + str$(array count(OBJ()))
text 802, 12, "Object count " + str$(amountOfObjects)
text 802, 24, "FPS " + str$(screen fps())
text 802, 585, "Cursor X " + str$(object position x(cursor)) + " Z " + str$(object position z(cursor))
Rem Call controls routine
gosub controls
sync
loop
Rem ****************************
Rem *** Setup File Routine
Rem ****************************
setupFile:
Rem Store file in path variable
filePath$ = "Editor Data\Setup.INI"
Rem Check for file's existence
readAgain:
if file exist(filePath$)
open to read 1, filePath$
Rem Display settings
read string 1, t$ : rWidth = val(t$)
read string 1, t$ : rHeight = val(t$)
read string 1, t$ : rDepth = val(t$)
read string 1, t$ : windowMode = val(t$)
read string 1, t$ : wWidth = val(t$)
read string 1, t$ : wHeight = val(t$)
read string 1, appTitle$
Rem Directory settings
read string 1, modelPath$
read string 1, soundPath$
read string 1, imagePath$
read string 1, ProjectPath$
read string 1, LevelPath$
close file 1
else
dWidth = desktop width()
dHeight = desktop height()
open to write 1, filePath$
Rem Display settings
write string 1, str$(dWidth)
write string 1, str$(dHeight)
write string 1, "32"
write string 1, "0"
write string 1, str$(dWidth)
write string 1, str$(dHeight)
write string 1, "Epic Editor [v0.01]"
Rem Directory settings
write string 1, "Editor Data\Models"
write string 1, "Editor Data\Sounds"
write string 1, "Editor Data\Images"
write string 1, "Projects"
write string 1, "Exported Levels"
close file 1
goto readAgain
endif
return
Rem ****************************
Rem *** Setup data routine
Rem ****************************
setupData:
Rem Set display mode
set display mode rWidth, rHeight, rDepth
sync on
sync rate 100
Rem Check for window mode
if windowMode = 1
set window on
set window size wWidth, wHeight
set window title appTitle$
set window position desktop width()/2-rWidth/2, desktop height()/2-rHeight/2
else
Rem Go fullscreen
set window off
endif
Rem *****************************************
Rem Set up all camera information
Rem *****************************************
Rem Default camera
make camera 1
Rem Default camera view
position camera 1, 0, 65, 0
xrotate camera 1, 90
set camera view 1, 0, 0, 800, 600
set camera view 1, 1, 1, 1
Rem Backdrop color
backdrop on
color backdrop 1, rgb(0, 0, 25)
Rem *****************************************
Rem Set up cursor object information
Rem *****************************************
global cursor
cursor = 25001
make object box cursor, 4.9, 15, 4.9
position object cursor, 0, 5, 0
ghost object on cursor
disable object zdepth cursor
color object cursor, rgb(0, 255, 0)
Rem Setup object highlighter
global highlight
highlight = 25002
make object box highlight, 5.5, 5.5, 5.5
position object highlight, 0, 0, 0
color object highlight, rgb(255, 0, 0)
set object highlight, 0, 0, 0
hide object highlight
set object collision off highlight
Rem Make grid
make matrix 1, 500.5, 500.5, 100, 100
position matrix 1, 500/2-502.45, -2.5, 500/2-502.45
Rem *****************************************
Rem Initialize all variables and type objects
Rem *****************************************
Rem Object properties object
type ObjectProperties
Rem Object position
objPosX# as float
objPosY# as float
objPosZ# as float
Rem Object type
objType as integer
Rem Special properties
ObjHidden as boolean
ObjTransparent as boolean
endtype
Rem Create empty array
dim OBJ() as ObjectProperties
Rem Initialize global variables
global maxObjectCount
global amountOfObjects
global selectedObject
global cameraMode
global editMode
global editLevel
global object
global water
Rem Set up variables
maxObjectCount = 25000 : Rem Absolutely no level can have more than 15000 objects
cameraMode = 1
editMode = 1
editLevel = 0 : Rem Default edit level
water = 1
object = 1
load image "Editor Data\sparkly.bmp", water
return
Rem ****************************
Rem *** Controls routine
Rem ****************************
controls:
Rem Change edit mode when spacebar is pressed
if spacekey() = 1 and spaceHold = 0
spaceHold = 1
editMode = editMode + 1
if editMode > 2 then editMode = 1
endif
if spacekey() = 0 then spaceHold = 0
Rem Check edit more
select editMode
case 1: Rem Object placement
show object cursor
moveCursor()
endcase
case 2: Rem Object editing mode
hide object cursor
gosub objectPicking
endcase
endselect
Rem Change camera mode when control key is pressed
if controlkey() = 1 and controlHold = 0
controlHold = 1
cameraMode = cameraMode + 1
if cameraMode > 2 then cameraMode = 1
endif
if controlkey() = 0 then controlHold = 0
Rem select object to create with returnkey
if returnkey() = 1 and enterHold = 0
enterHold = 1
object = object + 1
if object > 2 then object = 1
endif
if returnkey() = 0 then enterHold = 0
Rem Check camera mode
if cameraMode = 1
Rem Get camera's position
camX# = camera position x(1)
camY# = camera position y(1)
camZ# = camera position z(1)
Rem Position camera initially
position camera 1, camX#, 75, camZ#
xrotate camera 1, 90
Rem Update camera's position depending on user input
if upkey() = 1
move camera 1, 0.5 : inc camZ#
position camera 1, camX#, camY#, camZ#
endif
if downkey() = 1
move camera 1, -0.5 : dec camZ#
position camera 1, camX#, camY#, camZ#
endif
if leftkey() = 1
move camera 1, -0.5 : dec camX#
position camera 1, camX#, camY#, camZ#
endif
if rightkey() = 1
move camera 1, 0.5 : inc camX#
position camera 1, camX#, camY#, camZ#
endif
endif
return
objectPicking:
Rem Pick the object
pickObject = pick object(mousex(), mousey(), 1, maxObjectCount)
if mouseclick() = 1 and pickObject <> 0 then selectedObject = pickObject : sleep 25
if selectedObject <> 0
Rem Highlight the object
show object highlight
position object highlight, object position x(selectedObject), object position y(selectedObject), object position z(selectedObject)
Rem Print data to screen
text 802, 50, "X: " + str$(OBJ(selectedObject - 1).objPosX#) + " Y: " + str$(OBJ(selectedObject- 1).objPosY#) + " Z: " + str$(OBJ(selectedObject - 1).objPosZ#)
text 802, 65, "Object Type: " + str$(OBJ(selectedObject - 1).objType)
text 802, 77, "ID " + str$(selectedObject)
Rem Deselect the object
if mouseclick() = 1 then hide object highlight : selectedObject = 0
if keystate(211) = 1 and selectedObject <> 0
delete object selectedObject
array delete element OBJ(selectedObject - 1)
amountOfObjects = amountOfObjects - 1
selectedObject = 0
hide object highlight
endif
endif
return
Rem ****************************
Rem *** Create Object function
Rem ****************************
function createObject(objType)
Rem Find object number
objID = find free object()
Rem Determine what object to make
select objType
case 1: Rem A cube
load object "Editor Data\IndBlk.x", objID
xrotate object objID, 180
scale object objID, 250, 250, 250
position object objID, object position x(cursor), editLevel, object position z(cursor)
array insert at bottom OBJ()
OBJ().objType = 1
OBJ().objPosX# = object position x(objID)
OBJ().objPosY# = editLevel
OBJ().objPosZ# = object position z(objID)
endcase
case 2: Rem A magic tile
make object plain objID, 5, 5
xrotate object objID, -90
position object objID, object position x(cursor), editLevel-2.5, object position z(cursor)
texture object objID, water
array insert at bottom OBJ()
OBJ().objType = 2
OBJ().objPosX# = object position x(objID)
OBJ().objPosY# = editLevel
OBJ().objPosZ# = object position z(objID)
endcase
endselect
Rem Increase object amount variable
amountOfObjects = amountOfObjects + 1
endfunction
Rem ****************************
Rem *** Functions file
Rem ****************************
Rem Move cursor function
function moveCursor()
cx=camera position x(1)
cy=camera position y(1)
cz=camera position z(1)
null=make vector3(1)
null=make vector3(2)
null=make vector3(3)
null=make vector3(4)
set vector3 1,0,-1,0
pick screen mousex(), mousey(), 1
mx# = get pick vector x()
my# = get pick vector y()
mz# = get pick vector z()
set vector3 2,mx#,my#,mz#
angle# = acos(dot product vector3(2, 1))
cosangle# = cos(angle#)
hypolength# = cy/cosangle#
normalize vector3 2,2
scale vector3 2,2,hypolength#
set vector3 1,cx,cy,cz
add vector3 4,1,2
position object cursor, gridSnap(x vector3(4), 5),5,gridSnap(z vector3(4), 5)
Rem If space is inhabited color cursor red and stop object placement
if object collision(cursor, 0)
color object cursor, rgb(255, 0, 0)
clear = 0
else
color object cursor, rgb(0, 255, 0)
clear = 1
endif
Rem If space is clear create object
if clear = 1
if mouseclick() = 1 then createObject(object)
endif
endfunction
Rem Gridsnap function
function gridSnap(value#, gridSize#)
local result
result = value#/gridSize#
result = result*gridSize#
endfunction result
My problem lies exclusively in these lines, and the -1 NEEDS to be there or else the program crashes:
if selectedObject <> 0
Rem Highlight the object
show object highlight
position object highlight, object position x(selectedObject), object position y(selectedObject), object position z(selectedObject)
Rem Print data to screen
text 802, 50, "X: " + str$(OBJ(selectedObject - 1).objPosX#) + " Y: " + str$(OBJ(selectedObject- 1).objPosY#) + " Z: " + str$(OBJ(selectedObject - 1).objPosZ#)
text 802, 65, "Object Type: " + str$(OBJ(selectedObject - 1).objType)
text 802, 77, "ID " + str$(selectedObject)
Rem Deselect the object
if mouseclick() = 1 then hide object highlight : selectedObject = 0
if keystate(211) = 1 and selectedObject <> 0
delete object selectedObject
array delete element OBJ(selectedObject - 1)
amountOfObjects = amountOfObjects - 1
selectedObject = 0
hide object highlight
endif
endif
So does anyone know of a workaround this problem? Is there a way to make sure that no matter what object I delete, the end of the list still contains the last object I created?
EDIT:
The solution lies in shifting indices down, doesn't it? I just don't even know how to implement that.