Asymmetricly placed, data containing, predefined movement locations for a 2d, top down turn based tactical game that takes place on a topographic map

Please forgive any misuse of terms, I am very new to game making in general. I am trying to make a 2d tactical game that takes place on a topographic map where I create the move spaces based off of terrain features. This means that each move space will have a different shape and I will also have to set which spaces each movement space has a LOS to.

Could anyone help point me in a direction for how to accomplish this or how to better pose this question if I am being unclear?

Thank you so much in advance for any help.

Edit: I updated the title to what I believe conveys the concept much better than the previous one.

Coding your own line of sight check is NOT easy, if you have a height map then I would suggest creating the terrain or mesh that goes with it and then using the built in raycast functions to check for each ‘grid space’ which other grid spaces it can see.

you can do that quite simply by having a few embedded for loops:

Vector3[,] gridSpace;

//For each grid space
for(int z = 0; z < depth; z++){
for(int x = 0; x < width; x++){
	Vector3 parentSpace = gridSpace[x, z];

	//Check all grid spaces
	for(int zi = 0; zi < depth; zi++){
	for(int xi = 0; xi < width; xi++){
		Vector3 childSpace = gridSpace[xi, zi];
	
		// shoot a ray from your gridSpace[x, z] to gridSpace[xi, zi] and see if it hits anything on the way, if not, then this 'childSpace' grid space if visible from the 'parentSpace'
		// save that information somewhere!
	}
	}
}
}

Because I had lots of work to do I decided to procrastinate and see if I could write my own line of sightcode so here is a basic (and bad) implementation of how you could do it from scratch using some heightmap data:

using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;

public class heightmap : MonoBehaviour {
	float[,] heights;
	HeightMap hMap;
	public int xSize = 12;
	public int zSize = 3;
	
	void Start(){
		heights = new float[xSize,zSize];
		for(int z = 0; z < zSize; z++){
			for(int x = 0; x < xSize; x++){
				heights[x, z] = UnityEngine.Random.Range(0f, 1f);
			}
		}
		hMap = new HeightMap(heights, Vector3.zero, 1, 0.5f);
	}
}

public class HeightMap {
	HeightPoint[,] hPoints;
	float pointSpacing;
	Vector3 origin;
	int width;
	int depth;
	float viewUpHeight;
	
	public HeightMap(float[,] h, Vector3 o, float space, float viewUH){
		pointSpacing = space;
		origin = o;
		width = h.GetLength(0);
		depth = h.GetLength(1);
		viewUpHeight = viewUH;
		hPoints = new HeightPoint[width, depth];
		for(int z = 0; z < depth; z++){
			for(int x = 0; x < width; x++){
				hPoints[x, z] = new HeightPoint(x, z, new Vector3(origin.x+x*pointSpacing, origin.y+h[x, z], origin.z+z*pointSpacing), this);
			}
		}
		CalcLineOfSight();
		CreateMap();
	}
	
	public void CreateMap(){
		for(int z = 0; z < depth; z++){
			for(int x = 0; x < width; x++){
				GameObject o = GameObject.CreatePrimitive(PrimitiveType.Plane);
				o.transform.position = hPoints[x, z].pos;
				o.transform.localScale = Vector3.one*pointSpacing/10;
				o.name = x + ", " + z;
			}
		}
	}
	
	public void CalcLineOfSight(){
		HeightPoint p;
		for(int z = 0; z < depth; z++){
			for(int x = 0; x < width; x++){
				List<Point> haveChecked = new List<Point>();
				p = hPoints[x, z];
				p.Add(p);
				for(int zi = 0; zi < depth; zi++){
					for(int xi = 0; xi < width; xi++){
						if(zi == z && xi == x){
							continue;
						}
						//check indexes on line to target
						List<Point> points = FindIntersectedIndexes(x, z, xi, zi);
						
						//check visibility through each index on line
						float maxViewGrad = viewUpHeight;
						float minViewGrad = Mathf.NegativeInfinity;
						float grad = 0;
						for(int i = 0; i < points.Count; i++){
							if(points_.x == x && points*.y == z){*_

* continue;*
* }*
grad = (hPoints[points.x, points.y].height - p.height)/(new Vector2(x-points_.x, z-points*.y).magnitude);
minViewGrad = Mathf.Max(minViewGrad, grad);
if(minViewGrad > maxViewGrad){
break;
}
if(grad > maxViewGrad){
break;
}
if(grad < minViewGrad){
continue;
}
if(p.visiblePoints.Contains(hPoints[points.x, points.y])){
continue;
}
p.Add(hPoints[points.x, points.y]);
}
}
}
}
}
}*_

* List FindIntersectedIndexes(int y1, int x1, int y2, int x2){*
* //Implements a variation on Bresenham’s line algorithm*
* List points = new List();*
* int i;*
* int ystep;*
* int xstep;*
* int error;*
* int errorprev;*
* int y = y1;*
* int x = x1;*
* int ddy, ddx;*
* int dx = x2 - x1;*
* int dy = y2 - y1;*
* points.Add(new Point(y1, x1));*
* if (dy < 0){*
* ystep = -1;*
* dy = -dy;*
* }else{*
* ystep = 1;*
* }*
* if (dx < 0){*
* xstep = -1;*
* dx = -dx;*
* }else{*
* xstep = 1;*
* }*
_ ddy = 2 * dy;
ddx = 2 * dx;
* if(ddx >= ddy){
errorprev = error = dx;
for (i=0 ; i < dx ; i++){
x += xstep;
error += ddy;
if (error > ddx){
y += ystep;
error -= ddx;
if (error + errorprev < ddx){
points.Add(new Point(y-ystep, x));
}else if (error + errorprev > ddx){
points.Add(new Point(y, x-xstep));
}else{
points.Add(new Point(y-ystep, x));
points.Add(new Point(y, x-xstep));
}
}
points.Add(new Point(y, x));
errorprev = error;
}
}else{
errorprev = error = dy;
for (i=0 ; i < dy ; i++){
y += ystep;
error += ddx;
if (error > ddy){
x += xstep;
error -= ddy;
if (error + errorprev < ddy){
points.Add(new Point(y, x-xstep));
}else if (error + errorprev > ddy){
points.Add(new Point(y-ystep, x));
}else{
points.Add(new Point(y, x-xstep));
points.Add(new Point(y-ystep, x));
}
}
points.Add(new Point(y, x));
errorprev = error;
}
}
return points;
}
}*_

public class HeightPoint{
* int x;*
* int y;*
* float h;*
* public Vector3 pos;*
* public List visiblePoints = new List();*
* HeightMap hMap;*

* public HeightPoint(int xi, int yi, Vector3 p, HeightMap container){*
* pos = p;*
* h = p.y;*
* hMap = container;*
* x = xi;*
* y = yi;*
* }*
* public HeightPoint(int xi, int yi, Vector2 p, float he, HeightMap container){*
* pos = new Vector3(p.x, h, p.y);*
* h = he;*
* hMap = container;*
* x = xi;*
* y = yi;*
* }*

* public void Add(HeightPoint hP){*
* visiblePoints.Add(hP);*
* }*

* public void DebugVisible(){*
* foreach(HeightPoint a in visiblePoints){*
* Debug.Log(a.x + ", " + a.y);*
* }*
* }*

* public float height{*
* get { return h; }*
* set { h = value; }*
* }*
}

public class Point{
* public int x;*
* public int y;*

* public Point(int xi, int yi){*
* x = xi;*
* y = yi;*
* }*
}
The each ‘HeightPoint’ instance should contain a list of the HeightPoint’s that it can ‘see’
I would not advise anyone to use that code over the former alternative I suggested, but it was an interesting challenge to get working, so enjoy that headache!
Scribe