Search code examples
swiftcoordinates2d-games

Secure way of checking coordinates in Swift and smart way to present vision overlay map


I have a coordinate map of [[Int]], which I use to determine if a player has already been to a place and gives vision to the spot.

examle Image

In order to make it look nicer, I want to have a dissolved border at the edges of the black spots. see example 2:

image with nice borders

in order to do so I am checking my vision array for the 9 fields around the area and if a specific constellation is black it will pick the corresponding image to display.

   func getTileImage(index: Int) -> String {
        let tileCoordinates = convertInto2D(index: index)
        var tile : [Bool] = [false,false,false,false,false,false,false,false,false,false]
        
        if (tileCoordinates.x >= 1) && (tileCoordinates.y >= 1)  { if visionMap[tileCoordinates.x - 1][tileCoordinates.y - 1] == 0 { tile[1] = true } }
        if (tileCoordinates.x >= 1) && (tileCoordinates.y >= 0)  { if visionMap[tileCoordinates.x - 1][tileCoordinates.y - 0] == 0 { tile[2] = true } }
        if (tileCoordinates.x >= 1) && (tileCoordinates.y < 19) { if visionMap[tileCoordinates.x - 1][tileCoordinates.y + 1] == 0 { tile[3] = true } }
        if (tileCoordinates.x >= 0) && (tileCoordinates.y >= 1)  { if visionMap[tileCoordinates.x - 0][tileCoordinates.y - 1] == 0  { tile[4] = true } }
        if visionMap[tileCoordinates.x - 0][tileCoordinates.y - 0] == 0  { tile[5] = true }
        if (tileCoordinates.x >= 0) && (tileCoordinates.y < 19) { if visionMap[tileCoordinates.x - 0][tileCoordinates.y + 1] == 0  { tile[6] = true } }
        if (tileCoordinates.x < 14) && (tileCoordinates.y >= 1) { if visionMap[tileCoordinates.x + 1][tileCoordinates.y - 1] == 0  { tile[7] = true } }
        if (tileCoordinates.x < 14) && (tileCoordinates.y >= 0) { if visionMap[tileCoordinates.x + 1][tileCoordinates.y - 0] == 0  { tile[8] = true } }
        if (tileCoordinates.x < 14) && (tileCoordinates.y < 19) { if visionMap[tileCoordinates.x + 1][tileCoordinates.y + 1] == 0  { tile[9] = true } }

  
        if tile[2] == true && tile[3] == true  && tile[6] == true  {return "righttop"}
        if tile[3] == true && tile[6] == true  && tile[7] == true  && tile[8] == true && tile[9] == true {return"rightbottom"}
        if tile[3] == true && tile[6] == true  && tile[8] == true  && tile[9] == true {return"rightbottom"}
        if tile[6] == true && tile[7] == true  && tile[8] == true  && tile[9] == true {return"rightbottom"}
        if tile[1] == true && tile[2] == true  && tile[4] == true  {return "lefttop"}
        if tile[2] == true && tile[6] == false && tile[4] == false {return "top"}
        if tile[4] == true && tile[2] == false && tile[8] == false {return "left"}
        if tile[6] == true && tile[2] == false && tile[8] == false {return "right"}
        if tile[7] == true && tile[4] == true  && tile[8] == true  {return "leftbottom"}
        if tile[8] == true && tile[4] == false && tile[5] == false {return "bottom"}
        if tile[9] == true && tile[6] == true  && tile[8] == true  {return "bottomright"}
        if tile[4] == true && tile[1] == true  && tile[2] == true  && tile[3] == true && tile[6] == true {return "lefttopright"}
        if tile[4] == true && tile[6] == true  && tile[7] == true  && tile[8] == true && tile[9] == true {return "leftrightbottom"}
        if tile[1] == true && tile[2] == true  && tile[4] == true  && tile[7] == true && tile[8] == true {return "lefttopbottom"}
        if tile[2] == true && tile[3] == true  && tile[6] == true  && tile[8] == true && tile[9] == true {return"righttopbottom"}

        
        return ""
        
    }

This code does not look very smart in my opinion.

First of all is there a general way to check if I am at the borders of my coordinate system so I do not have to check the map size for each tile: e.g. getting rid of

if (tileCoordinates.x >= 1) && (tileCoordinates.y >= 1)

because this is dependent on the map size, which is currently 15x20.

2nd: is there a smarter way to return the corresponding image instead of checking all potential possibilities?

I am pretty sure this is used for many games. So if anyone can help that would be greatly appreciated.


Solution

  • After realising I only need to take horizontal and vertical adjacent fields into account, I renamed my images in the following order depending on the sides that they cover:

    "top", "left", "right", "bottom"

    for example an overlay image covering top and left would be called "topleft"

    this allowed me to reduce the code to 4 if conditions that checks if the side is not visible and in that case adds the name of the side to the string:

        func getTileImage(index: Int) -> String {
            let tileCoordinates = convertInto2D(index: index)
            var tile : [Int] = [1,1,1,
                                1,1,1,
                                1,1,1]
                
            if (tileCoordinates.x >= 1) && (tileCoordinates.y >= 0)  { if visionMap[tileCoordinates.x - 1][tileCoordinates.y - 0] == 0  { tile[1] = 0 } }
            if (tileCoordinates.x >= 0) && (tileCoordinates.y >= 1)  { if visionMap[tileCoordinates.x - 0][tileCoordinates.y - 1] == 0  { tile[3] = 0 } }
            if (tileCoordinates.x >= 0) && (tileCoordinates.y < 19)  { if visionMap[tileCoordinates.x - 0][tileCoordinates.y + 1] == 0  { tile[5] = 0 } }
            if (tileCoordinates.x < 14) && (tileCoordinates.y >= 0)  { if visionMap[tileCoordinates.x + 1][tileCoordinates.y - 0] == 0  { tile[7] = 0 } }
    
            
            if (tile[1] == 1) && (tile[3] == 1) && (tile[5] == 1) && (tile[7] == 1) {return "noOverlay" }
            
            var returnString = ""
            
            if tile[1] == 0 {returnString.append("top")}
            if tile[3] == 0 {returnString.append("left")}
            if tile[5] == 0 {returnString.append("right")}
            if tile[7] == 0 {returnString.append("bottom")}
    
            return returnString
            
        }