Post by Caiger on May 24, 2018 6:14:31 GMT
Board:
using UnityEngine;
using System;
using System.Collections.Generic;
using Tactical.Grid.Model;
using Tactical.Grid.Component;
namespace Tactical.Battle.Component {
public class Board : MonoBehaviour {
public Dictionary<Point, Tile> tiles = new Dictionary<Point, Tile>();
public Point min {
get { return _min; }
}
public Point max {
get { return _max; }
}
[Header(" - Required - ")]
public Transform tilesContainer;
public Transform unitsContainer;
[SerializeField] private GameObject tileOverlayPrefab;
[SerializeField] private LevelData levelData;
[SerializeField] private GameObject[] tilePrefab;
public int currentBlockInt = 0;
Color selectedTileColor = new Color(0, 1, 1, 1);
Color defaultTileColor = new Color(1, 1, 1, 1);
private Point[] dirs = new Point[4] {
new Point(0, 1),
new Point(0, -1),
new Point(1, 0),
new Point(-1, 0)
};
private Point _min;
private Point _max;
public void Load () {
_min = new Point(int.MaxValue, int.MaxValue);
_max = new Point(int.MinValue, int.MinValue);
//for (int i = 0; i < data.tiles.Count; ++i) {
if (levelData == null) { return; }
foreach (Vector4 v in levelData.tiles) {
currentBlockInt = (int)v.w;
//
//
// var tileViewPrefab = tileViewPrefabs[currentBlockInt];
// var instance = Instantiate(tileViewPrefab);
// instance.transform.parent = transform;
// return instance.GetComponent<Tile>();
//
Tile t = Create();
t.Load(v);
tiles.Add(t.pos, t);
_min.x = Mathf.Min(_min.x, t.pos.x);
_min.y = Mathf.Min(_min.y, t.pos.y);
_max.x = Mathf.Max(_max.x, t.pos.x);
_max.y = Mathf.Max(_max.y, t.pos.y);
}
}
public Tile Create () {
var tilePrefabs = tilePrefab[currentBlockInt];
var instance = Instantiate(tilePrefabs);
instance.transform.parent = transform;
return instance.GetComponent<Tile>();
}
public void SelectTiles (List<Tile> tiles) {
for (int i = tiles.Count - 1; i >= 0; --i) {
GameObject instance = Instantiate(tileOverlayPrefab);
instance.transform.parent = tiles.transform;
instance.transform.localPosition = Vector3.up * 0.5f;
tiles.overlay = instance;
}
}
public void DeSelectTiles (List<Tile> tiles) {
for (int i = tiles.Count - 1; i >= 0; --i) {
Destroy(tiles.overlay);
tiles.overlay = null;
}
}
public List<Tile> Search (Tile start, Func<Tile, Tile, bool> addTile) {
var retValue = new List<Tile>();
retValue.Add(start);
ClearSearch();
var checkNext = new Queue<Tile>();
var checkNow = new Queue<Tile>();
start.distance = 0;
checkNow.Enqueue(start);
while (checkNow.Count > 0) {
Tile t = checkNow.Dequeue();
for (int i = 0; i < 4; ++i) {
Tile next = GetTile(t.pos + dirs);
if (next == null || next.distance <= t.distance + 1) {
continue;
}
if (addTile(t, next)) {
next.distance = t.distance + 1;
//Implement travel cost in the future for each unit type?
// next.distance = t.distance + t.travelCost();
next.prev = t;
checkNext.Enqueue(next);
retValue.Add(next);
}
}
if (checkNow.Count == 0) {
SwapReference(ref checkNow, ref checkNext);
}
}
return retValue;
}
public Tile GetTile (Point p) {
return tiles.ContainsKey(p) ? tiles
: null;
}
private void SwapReference (ref Queue<Tile> a, ref Queue<Tile> b) {
Queue<Tile> temp = a;
a = b;
b = temp;
}
private void ClearSearch () {
foreach (Tile t in tiles.Values) {
t.prev = null;
t.distance = int.MaxValue;
}
}
}
}
There are a few changes in my board script. I am using a modified map creater script. It basically takes in a Vector 4, passes data from the tile for the prefab type, based on a materialInt variable. It then stores that same value as the v.w reference. The same is loaded. (If you have any suggestion for an easier or cleaner system I am open to ideas~ Still learning and mostly use problem solving with trial and error to get things working haha)
tile script
using UnityEngine;
using Tactical.Grid.Model;
namespace Tactical.Grid.Component {
[ExecuteInEditMode]
public class Tile : MonoBehaviour {
public const float STEP_HEIGHT = 0.25f;
public Point pos;
public int height;
public int width = 1;
public int materialInt;
public int travelDifficulty;
public int travelCost(){
return travelDifficulty;
}
public Vector3 center {
get { return new Vector3(pos.x, height * STEP_HEIGHT, pos.y); }
}
public GameObject content;
[HideInInspector] public GameObject overlay;
[HideInInspector] public Tile prev;
[HideInInspector] public int distance;
public void Grow () {
height++;
Match();
}
public void Shrink () {
height--;
Match ();
}
public void Load (Point p, int h, int mi) {
pos = p;
height = h;
materialInt = mi;
Match();
}
public void Load (Vector4 v) {
Load(new Point((int)v.x, (int)v.z), (int)v.y, (int)v.w);
}
private void Update () {
Match();
}
private void Match () {
transform.localPosition = new Vector3(pos.x, height * STEP_HEIGHT / 2f, pos.y );
transform.localScale = new Vector3(width, height * STEP_HEIGHT, width);
}
}
}
Just so you can see what I already tried to do more clearly.
"""To help get you started, I didn’t intend you to put a “travelCost” method on the tile itself. Done this way, it would be the same for every unit traversing the tile regardless of the kind of unit. """
As you said, this leaves the problem that each unit has this same difficulty. (Also somehow the overlayprefab is not properly deleted after a move position is selected somehow. Perhaps the tile script is causing this to happen somehow.)
"""Instead, the component responsible for traversing a map will pass in its own method which accepts a tile as a parameter and returns a travel cost based on the unit it was attached to."""
By this do you mean that I would need to put this into the basic movement script? Or would I need to make a special movement type for each job class? I am afraid I do not follow exactly here. Perhaps you mean adding for example a knight walking in the MovementTypes Enum? Then copy the walking script but make a change somewhere? (I made a knight walk script from the walking one and now trying to play with it a bit to get it to work in the meantime.)