Hi,
I'm working on an indie RTS game (using Truevision 3D for anyone that is interested) where the player can build walls by placing a wall section.
I'm working on a function(s) that will alter the models of wall sections when you add new sections nearby. So that you automatically have corner section, center sections etc. based of if there is walls around and if so where.
This function is recursive and I seem to have a problem with it. I thinks it lacks a proper "end condition" but I'm not sure where or what that should be. I get a 'System.StackOverflowException' error.
The function works so that it checks the section you just placed and change it, it the checks all nearby sections if they need to be change, and they check their nearby sections and so on until all necesary section has changed. This works fine for the first section that is added nearby another.
Here is the code (the code in under development so there might be a better way to do this):
...And sorry for the long code but i'm not sure which bits are impotrant to show or not.
This first function checks if the player is placing an object and calls the "checkWallType" function.
CODE
private void placeNewObject() {
// If the player is placing an object
if (bIsPlacing == true){
// Can't place when paning the camera or the mouse is over the menu
if (B1 == true && B1pressed == false && Input.IsKeyPressed(CONST_TV_KEY.TV_KEY_LEFTSHIFT) == false && MX < (screenWidth - 210)){
TV_2DVECTOR vec;
bool isFull = false;
// Check if any grid(s) under the placemarker(s) is full or not
int c = 0;
for (int i = 1; i <= iPlaceWidth; i++){
for (int j = 1; j <= iPlaceHeight; j++){
c++;
// Convert position to grid vector
vec.x = (float)(System.Math.Round((mGridMarker[c].GetPosition().x / 64)));
vec.y = (float)(System.Math.Round((mGridMarker[c].GetPosition().z / 64)));
if (GridHandler.isGridVecFull(vec) == true) { isFull = true; }
}
}
// If not then place the object and make the grid(s) full
if(isFull == false){
c = 0;
// Make the grid(s) full
for (int i = 1; i <= iPlaceWidth; i++){
for (int j = 1; j <= iPlaceHeight; j++){
c++;
// Convert position to grid vector
vec.x = (float)(System.Math.Round((mGridMarker[c].GetPosition().x / 64)));
vec.y = (float)(System.Math.Round((mGridMarker[c].GetPosition().z / 64)));
GridHandler.addFullGridVector(vec);
}
}
// Also make the "special wall grid" full if the object is a wall section
// This is so that we don't need to check all grids when dealing with walls
if (mPlaceMarker.GetMeshName() == "Wall"){
// Convert position to grid vector
vec.x = (float)(System.Math.Round((mGridMarker[1].GetPosition().x / 64)));
vec.y = (float)(System.Math.Round((mGridMarker[1].GetPosition().z / 64)));
GridHandler.addFullWallGridVector(vec);
checkWallType(vec.x, vec.y, mPlaceMarker);
}
// Create and add the object to the object handler
clsObject elem = new clsObject(Scene, mPlaceMarker, Globals);
ObjectHandler.addObject(elem);
bIsPlacing = false;
B1pressed = true;
}
}
else if (B2 == true) { bIsPlacing = false; }
}
}
This function do's the check for nearby sections and determines is the model need to be changed. This is where the recursion occurs.
CODE
private void checkWallType(float X, float Y, TVMesh mModel)
{
if (mModel != null){
// There are walls all around - make a center + Section
if (checkWallsAround(true, true, true, true, X, Y))
{
changePlaceMarker(mModel, "Four_wall.tvm", "Wall");
checkWallType(X + 1, Y, ObjectHandler.getObjectByGridVec(X + 1, Y));
checkWallType(X - 1, Y, ObjectHandler.getObjectByGridVec(X - 1, Y));
checkWallType(X, Y + 1, ObjectHandler.getObjectByGridVec(X, Y + 1));
checkWallType(X, Y - 1, ObjectHandler.getObjectByGridVec(X, Y - 1));
}
// There is three walls around - make a T section
else if (checkWallsAround(true, true, true, false, X, Y))
{
changePlaceMarker(mModel, "Three_wall.tvm", "Wall");
mModel.SetRotation(mModel.GetRotation().x, mModel.GetRotation().y + 0, mModel.GetRotation().z);
checkWallType(X + 1, Y, ObjectHandler.getObjectByGridVec(X + 1, Y));
checkWallType(X - 1, Y, ObjectHandler.getObjectByGridVec(X - 1, Y));
checkWallType(X, Y + 1, ObjectHandler.getObjectByGridVec(X, Y + 1));
}
...
etc.
Have removed the other types to shorten the code but this just continues through all posibles types of sections
...
}
}
These two support functions are used by "checkWallType" to do the check.
CODE
private bool checkWallsAround(bool A, bool B, bool C, bool D, float X, float Y){
// Check is the grid vecs around vec is ful or not acording A,B,C and D
if (WVF(X + 1, Y) == A && WVF(X - 1, Y) == B && WVF(X, Y + 1) == C && WVF(X, Y - 1) == D){
return true;
}
return false;
}
CODE
private bool WVF(float X, float Y) {
// "Wall Vector Full" Checks if the grid if full (only check wall grids)
TV_2DVECTOR vec;
vec.x = X;
vec.y = Y;
if (GridHandler.isWallGridVecFull(vec) == true){
return true;
}
else { return false; }
}
A note is that all works fine the first time. If I place two sections between each other they change to two "end section" opposing each other (as they should) but when I add a third one to create a corner the error shows.
(And why is the code part width not to a 100 %)