You select a bow or crossbow to one hand and an arrow or bolt to the other.
You select the Ranged Icon, then your target, you use Bresenham's Algorythm to determine if you can hit it, and deal damage to the creature.
Bresenham's is much faster than A*, which is already included for pathfinding if Im not mistaken, so this should be no problem for basic line of sight.
Here is the code I have in C# for Unity, it should be easy to port, Ill work on it as I have time or anyone else who wants o can modify it. I welcome the chance to extract and adapt the algorythm alongside other people. Since I wrote it, I can offer it to be adapted and hope to learn new ways to use it for my own projects.
Bresenham's has a lot of use in tile based games. Lets see if we can get it going.
Code: Select all
using UnityEngine;
using System.Collections;
using TileMethods;
/*
* author: storyteller (rqpaine)
*ai for games, d. hays
*c. c. community college
*/
public class BresenhamsMover : MonoBehaviour
{
static int pathLimit = 12;
public Cell target;
public Cell next;
public Cell current;
public Cell step;
public int pathStep;
public int deltax, deltay;
public int thisStep;
public int fraction;
public float tileSize = 2.0f;
public ArrayList moveList = new ArrayList();
public int[] pathRow = new int[pathLimit];
public int[] pathCol = new int[pathLimit];
public enum tileTypes
{
basic,
yellow,
red
};
public GameObject tile;
public GameObject stone;
public int[,] map =
{
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
// Use this for initialization
void Start()
{
Vector3 pos = new Vector3(0, 0, 0);
stone = (GameObject)Instantiate(stone, pos, Quaternion.identity);
//set grid
for (float y = 0f; y < 10; y++)
{
for (float x = 0f; x < 10; x++)
{
Vector3 npos = new Vector3(x, y, 0) * tileSize;
GameObject nextTile = (GameObject)Instantiate(tile, npos, Quaternion.identity);
SetTargetTile nextScript = nextTile.GetComponent<SetTargetTile>();
nextScript.cellx = (int)x;
nextScript.celly = (int)y;
//print(nextScript.xcol);
}
}
current.y = 0;
current.x = 0;
for (thisStep = 0; thisStep < pathLimit; thisStep++)
{
pathRow[thisStep] = -1;
pathCol[thisStep] = -1;
}
thisStep = 0;
InvokeRepeating("MoveStone", 1.0f, 0.5f);
}//st
// Update is called once per frame
void Update()
{
}//Up
public void NewTargetTile(int xrow, int ycol)
{
target.y = xrow;
target.x = ycol;
// print(target);
//bresenhams chase
next = current;
deltax = target.x - current.x;
deltay = target.y - current.y;
for (thisStep = 0; thisStep < pathLimit; thisStep++)
{
pathRow[thisStep] = -1;
pathCol[thisStep] = -1;
}
thisStep = 0;
if (deltay < 0) step.y = -1; else step.y = 1;
if (deltax < 0) step.x = -1; else step.x = 1;
deltax = Mathf.Abs(deltax * 2);
deltay = Mathf.Abs(deltay * 2);
//
//should be copy current to arraylist
pathRow[thisStep] = current.y;
pathCol[thisStep] = current.x;
//
thisStep++;
if (deltax > deltay)
{
fraction = deltay * 2 - deltax;
while (next.x != target.x)
{
if (fraction >= 0)
{
next.y = next.y + step.y;
fraction = fraction - deltax;
}
next.x = next.x + step.x;
fraction = fraction + deltay;
//add copy to list
pathRow[thisStep] = next.y;
pathCol[thisStep] = next.x;
//code hook here ~--!!!
thisStep++;
}
}
else
{
fraction = deltax * 2 - deltay;
while (next.y != target.y)
{
if (fraction >= 0)
{
next.x = next.x + step.x;
fraction = fraction - deltay;
}
next.y = next.y + step.y;
fraction = fraction + deltax;
pathRow[thisStep] = next.y;
pathCol[thisStep] = next.x;
thisStep++;
}
pathStep = 0;
}
thisStep = 0;
pathStep = 0;
}//BP
void MoveStone()
{
//get our position
Vector3 newPos = stone.transform.position;
//print(newPos);
#region basic tile chase
//basic tile chase,
//I think the use of breaks get rid of diagonal movement
//very simple, but very reliable, combined with pattern based movement
//can be very powerful
//
//
//if (target.row > current.row)
//{
// current.row++;
// newPos.x += 2.0f;
//}
//if (target.row < current.row)
//{
// current.row--;
// newPos.x -= 2.0f;
//}
//if (target.col > current.col)
//{
// current.col++;
// newPos.y += 2.0f;
//}
//if (target.col < current.col)
//{
// current.col--;
// newPos.y -= 2.0f;
//}
//
#endregion
if (pathCol[pathStep] != -1)
{
newPos.y = pathCol[pathStep] * tileSize;
current.x = pathCol[pathStep];
}
if (pathRow[pathStep] != -1)
{
newPos.x = pathRow[pathStep] * tileSize;
current.y = pathRow[pathStep];
}
if (pathCol[pathStep] == -1 || pathRow[pathStep] == -1)
{ return; }
else { pathStep++; }
//set stone to our new position
stone.transform.position = newPos;
}//MS
//////
}//End