I have a 2d grid that I'm trying to create links between all walls.
The grid is constructed like so:
grid = new State[8][8];
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
grid[i][j] = State.blank;
}
}
I have a robot that should be able to pass through the walls to the opposite side like on a game of snake.
So for example if the robot is facing NORTH and is in position x[0]y[1] then it should connect to x[7]y[1].
The robot should also be able to read whats in the three blocks in front of it, one to the left, one to the right and one directly infront.
# x = empty space
# R = robot
# S = spaces robots sensors pick up
If it were facing north this is what the robot would pick up:
[S][S][S][x][x][x][x][x]
[x][R][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
Like wise if the robot was facing east this is what it would pick up:
[x][x][S][x][x][x][x][x]
[x][R][S][x][x][x][x][x]
[x][x][S][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
The problem I'm having is finding the right algorithm to make sure that the robot can not only pass through walls but also read sensors through the walls.
If the robot was in the top left corner and facing NORTH then it would read through the wall like so:
[R][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[x][x][x][x][x][x][x][x]
[S][S][x][x][x][x][x][S]
As you can imagine I've already tried doing length chunks of IF statements but there is too many possiblities to cover them all without going insane!
I've also wrote down the changes to X & Y on paper when placed in certain circumstances but I can't really see any pattern that hints toward an algorithm.
Any help would be appreciated!
public class Robot {
public int x;
public int y;
public Robot(int x,int y) {
this.x = x;
this.y = y;
}
public void move(int direction, int steps) {
switch(direction) {
case 1: //north
int temp1 = (x-steps)%8;
x = temp1<0?(temp1+8):temp1;
break;
case 2: //south
x = (x+steps)%8;
break;
case 3: //west
int temp3 = (y-steps)%8;
y = temp3<0?(temp3+8):temp3;
break;
case 4: //east
y = (y+steps)%8;
break;
default:
System.out.println("I'm not smart enough to handle the direciton provided!");
}
}
public static void main(String[] args) {
int[][] grid = new int[8][8];
Robot robot = new Robot(0,0);
System.out.println("I'm starting at (0,0).");
robot.move(3, 9);
System.out.println("I'm moving west by 9 steps.");
System.out.println("I've arrived at ("+robot.x+","+robot.y+").");
}
}
Hope the code above gives an idea. I've tested it. Feel free to have a try. The computation of the three blocks in front of the robot is similar. You can figure it out on your own.
Use an iterator like x = (x + 1) % array.length
(or x = (x - 1) % array.length)
I'll try to break it down into different parts, hopefully that will help you.
So, you have a 8x8 grid, represented by X and Y coordinates, with (0,0) being the top left corner and (7,7) being the bottom right corner.
Your algorithm will look like this:
walking through walls:
N -> x = x, y = (y==0)?7:y-1
S -> x = x, y = (y==7)?0:y+1
E -> x = (x==7)?0:x+1, y = y
W -> x = (x==0)?7:x-1, y = y
Look ahead
N -> LH1 = x=x, y=y-1
LH2 = x=x-1, y=y-1
LH3 = x=x+1, y=y-1
S -> LH1 = x=x, y=y+1
LH2 = x=x-1, y=y+1
LH3 = x=x+1, y=y+1
E -> LH1 = x=x+1, y=y
LH2 = x=x+1, y=y-1
LH3 = x=x+1, y=y+1
W -> LH1 = x=x-1, y=y
LH2 = x=x-1, y=y-1
LH3 = x=x-1, y=y+1
Now if I convert this algorithm into java methods, they will look like this:
public int getNextX (int currentX, String direction)
{
if ("N".equals (direction) || "S".equals (direction))
{
return currentX;
}
else if ("E".equals (direction))
{
return ((currentX==7) ? 0 : currentX + 1);
}
else if ("W".equals (direction))
{
return ((currentX==0) ? 7 : currentX - 1);
}
}
public int getNextY (int currentY, String direction)
{
if ("E".equals (direction) || "W".equals (direction))
{
return currentY;
}
else if ("S".equals (direction))
{
return ((currentY==7) ? 0 : currentY + 1);
}
else if ("N".equals (direction))
{
return ((currentY==0) ? 7 : currentY - 1);
}
}
public ArrayList getLookAheads (int currentX, int currentY, String direction)
{
ArrayList lookAheads = new ArrayList ();
int x[3];
int y[3];
if ("N".equals (direction))
{
// LH1
x[0] = currentX;
y[0] = currentY - 1;
// LH2
x[1] = currentX - 1;
y[1] = currentY - 1;
// LH3
x[2] = currentX + 1;
y[2] = currentY - 1;
}
else if ("S".equals (direction))
{
// LH1
x[0] = currentX;
y[0] = currentY + 1;
// LH2
x[1] = currentX - 1;
y[1] = currentY + 1;
// LH3
x[2] = currentX + 1;
y[2] = currentY + 1;
}
else if ("E".equals (direction))
{
// LH1
x[0] = currentX + 1;
y[0] = currentY;
// LH2
x[1] = currentX + 1;
y[1] = currentY - 1;
// LH3
x[2] = currentX + 1;
y[2] = currentY + 1;
}
else if ("E".equals (direction))
{
// LH1
x[0] = currentX - 1;
y[0] = currentY;
// LH2
x[1] = currentX - 1;
y[1] = currentY - 1;
// LH3
x[2] = currentX - 1;
y[2] = currentY + 1;
}
for (int i=0;i < 3;i++)
{
HashMap h = new HashMap ();
h.put ("X", new Integer (getNextX (x[i], direction)));
h.put ("Y", new Integer (getNextY (y[i], direction)));
lookAheads.add (h);
}
return lookAheads;
}
I didn't test the syntax of the methods (I just wrote them in a notepad), so pardon me if there are some compilation errors, but you should be able to figure that out.
Hope that helps.
This can be solved quite simply, by using the modulus operator (%). Modulo cycles values around under a certain upper bound. So if the robot's x value steps over the maximum boundary, it simply jumps back to 0. This way the robot can move through one wall on the right, and the x co-ordinate is reset back to 0 and they will appear on the left side of the stage.
Related
I'm having problems with completing the algorithm based on this link.
After building a wall I choose the upper or left part of the maze and it seems to create itself only to the point where it needs to break the recursion and enter another divide method call. I'm not sure if I understand the values needed to be passed to the last call of the divide method correctly.
public void divide(int x, int y, int width, int hight) {
if (width< 2 || hight< 2) ;
else {
boolean horizontal = chooseOrientation(width,hight);
if (horizontal) {
int randomNumber = r.nextInt(hight - 1);
wallY = randomNumber + y;
for (int i = x; i < width; i++) {
fields[wallY][i].setHorizontalWall();
}
fields[wallY][r.nextInt(width- 1)].deleteHorizontalWall();
hight = wallY - y + 1;
divide(x, y, width, hight);
}
else {
int randomNumber = r.nextInt(width- 1);
WallX = randomNumber + x;
for (int i = y; i < hight; i++) {
fields[i][WallX].setVerticalWall();
}
fields[r.nextInt(hight - 1) + y][WallX].deleteVerticalWall();
width = WallX - x + 1;
}
if(horizontal){
hight = y + hight + WallY-1;
y = WallY + 1;
}
else {
width = WallX - 1 + width + x;
x = WallX + 1;
}
divide(x, y, width, hight);
}
}
In the "recursive-division" algorithm you start with a full 2-dimensional grid graph and you then start removing edges (= building "walls") alternating in horizontal and vertical "stripes". In every "stripe" only a single edge ("door") is left.
A graph-based version of this algorithm can be found here:
https://github.com/armin-reichert/mazes
https://github.com/armin-reichert/mazes/blob/master/mazes-algorithms/src/main/java/de/amr/maze/alg/others/RecursiveDivision.java
Add a method to your code that checks each of the four edges of the ball one by one, checking if that edge has collided with the edge of the window. If so, it should change direction accordingly. For instance, if the ball was moving north-east (↗) and the top edge had hit the top of the screen, it would change the direction to south-east (↘) so that the ball would appear to bounce off the edge. (Remember that if the ball goes directly into a corner in a diagonal direction, two edges could hit at once, making it bounce straight back in the opposite diagonal direction.)
I am not sure how to get the four edges of an oval. I have the other 4 directions done (up, down, left, right) done but am not sure how to handle corners of the window.
public void move()
{
//direction right
if(dir == 1)
{
int x = ball.getX();
int y = ball.getY();
ball.setLocation(x + 1,y);
if(x>425)
{
dir = 2;
}
}
//direction left
if(dir == 2)
{
int x = ball.getX();
int y = ball.getY();
ball.setLocation(x - 1,y);
if(x<0)
{
dir = 1;
}
}
//direction down
if(dir == 3)
{
int x = ball.getX();
int y = ball.getY();
ball.setLocation(x,y + 1);
if(y>425)
{
dir = 4;
}
}
//direction up
if(dir == 4)
{
int x = ball.getX();
int y = ball.getY();
ball.setLocation(x ,y - 1);
if(y<0)
{
dir = 3;
}
}
//direction bottom right corner
if(dir == 5)
{
int x = ball.getX();
int y = ball.getY();
ball.setLocation(x + 1,y + 1);
}
//direction upper right corner
if(dir == 6)
{
int x = ball.getX();
int y = ball.getY();
ball.setLocation(x + 1,y - 1);
}
//direction bottom left corner
if(dir == 7)
{
int x = ball.getX();
int y = ball.getY();
ball.setLocation(x - 1,y + 1);
}
//direction upper left corner
if(dir == 8)
{
int x = ball.getX();
int y = ball.getY();
ball.setLocation(x - 1,y - 1);
}
}
Finally, make sure to call this method whenever you move the ball. That way, after you move the ball 1 pixel in its current direction, you run the method to check if it has hit any edge, and change direction. At this point, your ball should move about the screen ricocheting as it goes.
Don't think too much about it being an oval. For the purposes of this assignment, it might just as well be a box. The only difference between the case for corners compared to the case for an edge is that you need to distinguish between 4 outcomes:
You hit a horizontal and vertical wall: Change to the opposite direction of the diagonal movement.
You hit a horizontal wall: Keep the vertical direction and switch the horizontal to the opposite.
You hit a vertical wall: Keep the horizontal direction and switch the vertical to the opposite.
You hit no wall at all: Do nothing.
Furthermore, the instructions specifically recommend that you separate movement logic from the logic for changing direction. In your initial approach, you are doing both at once.
In my example, I introduce a method changeDirection() that only checks if any boundary is hit and then turns you around, but no actual movement is taking place. You still need to implement move() and take care of that, but you can just call this method and assume that the ball is heading towards the correct direction afterwards.
Also, the code becomes easier to understand once you introduce named constants to refer to the directions:
private static final int RIGHT = 1;
private static final int LEFT = 2;
private static final int DOWN = 3;
private static final int UP = 4;
private static final int DOWN_RIGHT = 5;
private static final int UP_RIGHT = 6;
private static final int DOWN_LEFT = 7;
private static final int UP_LEFT = 8;
private static final int WIDTH = 425;
private static final int HEIGHT = 425;
public void changeDirection()
{
int x = ball.getX();
int y = ball.getY();
switch ( dir )
{
case RIGHT:
if ( x >= WIDTH )
{
dir = LEFT;
}
break;
case LEFT:
if ( x <= 0 )
{
dir = RIGHT;
}
break;
case DOWN:
if ( y >= HEIGHT )
{
dir = UP;
}
break;
case UP:
if ( y <= 0 )
{
dir = DOWN;
}
break;
case DOWN_RIGHT:
if ( y >= HEIGHT )
{
if ( x >= WIDTH )
{
dir = UP_LEFT;
}
else
{
dir = UP_RIGHT;
}
}
else if ( x >= WIDTH )
{
dir = DOWN_LEFT;
}
break;
case UP_RIGHT:
if ( y <= 0 )
{
if ( x >= WIDTH )
{
dir = DOWN_LEFT;
}
else
{
dir = DOWN_RIGHT;
}
}
else if ( x >= WIDTH )
{
dir = UP_LEFT;
}
break;
case DOWN_LEFT:
if ( y >= HEIGHT )
{
if ( x <= 0 )
{
dir = UP_RIGHT;
}
else
{
dir = UP_LEFT;
}
}
else if ( x <= 0 )
{
dir = DOWN_RIGHT;
}
break;
case UP_LEFT:
if ( y <= 0 )
{
if ( x <= 0 )
{
dir = DOWN_RIGHT;
}
else
{
dir = UP_LEFT;
}
}
else if ( x <= 0 )
{
dir = UP_RIGHT;
}
break;
}
}
I'm brand new to game development and have chosen to start working on a 2D top-down scroller game. I'm using the Slick2D library for this game.
My question is about best practices for taking multiple direction input for sprite movement (UP + RIGHT = Diagonal)
Currently, I have a rather ugly looking if/elseif chain to read in the input from the keyboard that is then checked in the 'Mob' class to determine how the sprite will move. The current setup works just fine, but my question is if there is another, better way of going about taking multiple inputs for diagonals (or any combo of keys, for that matter)
Here is the main class's update method that reads the input (blooper is the instance of 'Mob'):
public void update(GameContainer container, StateBasedGame arg1, int delta) throws SlickException {
Input input = container.getInput();
if(input.isKeyDown(Input.KEY_RIGHT)) { //RIGHT
if(input.isKeyDown(Input.KEY_UP)){ //RIGHT + UP
blooper.direction = 2;
} else if(input.isKeyDown(Input.KEY_DOWN)){ //RIGHT + DOWN
blooper.direction = 3;
}
else {
blooper.direction = 1;
}
} else if(input.isKeyDown(Input.KEY_LEFT)){ //LEFT
if(input.isKeyDown(Input.KEY_UP)){ //LEFT + UP
blooper.direction = 5;
} else if(input.isKeyDown(Input.KEY_DOWN)){ //LEFT + DOWN
blooper.direction = 6;
} else{
blooper.direction = 4;
}
} else if(input.isKeyDown(Input.KEY_UP)){ //UP
if(input.isKeyDown(Input.KEY_RIGHT)){ //UP + RIGHT
blooper.direction = 8;
} else if(input.isKeyDown(Input.KEY_LEFT)){ //UP + LEFT
blooper.direction = 9;
} else{
blooper.direction = 7;
}
} else if(input.isKeyDown(Input.KEY_DOWN)){ //DOWN
if(input.isKeyDown(Input.KEY_RIGHT)){ //DOWN + RIGHT
blooper.direction = 11;
} else if(input.isKeyDown(Input.KEY_LEFT)){ //DOWN + LEFT
blooper.direction = 12;
} else{
blooper.direction = 10;
}
} else{
blooper.direction = -1;
}
blooper.update(delta);
}
And here is how that input is processed in the Mob class:
public class Mob {
private final int RIGHT = 1;
private final int RIGHTUP = 2;
private final int RIGHTDOWN = 3;
private final int LEFT = 4;
private final int LEFTUP = 5;
private final int LEFTDOWN = 6;
private final int UP = 7;
private final int UPRIGHT = 8;
private final int UPLEFT = 9;
private final int DOWN = 10;
private final int DOWNRIGHT = 11;
private final int DOWNLEFT = 12;
private final int IDLE = -1;
int direction = IDLE;
int x, y;
Image sprite;
public Mob() throws SlickException{
x = 20;
y = 20;
sprite = new Image("res/blooper.png");
}
public void update(int delta){
move();
}
public void draw(){
sprite.draw(x, y);
}
public void move(){
switch(direction){
case RIGHT:
x += 1;
break;
case RIGHTUP:
x += 1;
y -= 1;
break;
case RIGHTDOWN:
x += 1;
y += 1;
break;
case LEFT:
x -= 1;
break;
case LEFTUP:
x -= 1;
y -= 1;
break;
case LEFTDOWN:
x -= 1;
y += 1;
break;
case UP:
y -= 1;
break;
case UPRIGHT:
y -= 1;
x += 1;
break;
case UPLEFT:
y -= 1;
x -= 1;
break;
case DOWN:
y += 1;
break;
case DOWNRIGHT:
y += 1;
x += 1;
break;
case DOWNLEFT:
y += 1;
x -= 1;
break;
case IDLE:
//nothing
}
}
}
Like I said...this works, but doesn't seem like the best way to go about it. Any tips?
Make left/right and up/down movement independent. You (or the framework - I'm unfamiliar with it) seems to work with x/y coordinates, which are mathematically independent.
Thus make one function that treats the up/down movement, and one function that treats the left/right movement, and you can get rid of their 'combinations'. Is there a reason why the directions are positive integers? Try making left = -1, right = 1, and no x-direction movement 0, and then do the same for y. That should hopefully make it more intuitive.
Happy coding
Make a blooper.direction a bitwise, like:
blooper.direction=0;
if(input.isKeyDown(Input.KEY_RIGHT)) blooper.direction|=1;
if(input.isKeyDown(Input.KEY_LEFT)) blooper.direction|=2;
if(input.isKeyDown(Input.KEY_UP)) blooper.direction|=4;
if(input.isKeyDown(Input.KEY_DOWN)) blooper.direction|=8;
then in move do the move, like:
if ((blooper.direction&1)!=0) x+=1;
if ((blooper.direction&2)!=0) x-=1;
if ((blooper.direction&4)!=0) y-=1;
if ((blooper.direction&8)!=0) y+=1;
I am writing a isometric tile based game where the characters can walk freely amongst the tiles, but not be able to cross over to certain tiles that have a collides flag. Sounds easy enough, just check ahead of where the player is going to move using a Screen Coordinates to Tile method and check the tiles array using our returned xy indexes to see if its collidable or not. if its not, then don't move the character. The problem I'm having is my Screen to Tile method isn't spitting out the proper X,Y tile indexes. This method works flawlessly for selecting tiles with the mouse. NOTE: My X tiles go from left to right, and my Y tiles go from up to down. Reversed from some examples on the net. Here's the relevant code:
public Vector2 ScreentoTile(Vector2 screenPoint) {
//Vector2 is just a object with x and y float properties
//camOffsetX,Y are my camera values that I use to shift everything but the
//current camera target when the target moves
//tilescale = 128, screenheight = 480, the -46 offset is to center
// vertically + 16 px for some extra gfx in my tile png
Vector2 tileIndex = new Vector2(-1,-1);
screenPoint.x -= camOffsetX;
screenPoint.y = screenHeight - screenPoint.y - camOffsetY - 46;
tileIndex.x = (screenPoint.x / tileScale) + (screenPoint.y / (tileScale / 2));
tileIndex.y = (screenPoint.x / tileScale) - (screenPoint.y / (tileScale / 2));
return tileIndex;
}
The method that calls this code is:
private void checkTileTouched () {
if (Gdx.input.justTouched()) {
if (last.x >= 0 && last.x < levelWidth && last.y >= 0 && last.y < levelHeight) {
if (lastSelectedTile != null) lastSelectedTile.setColor(1, 1, 1, 1);
Sprite sprite = levelTiles[(int) last.x][(int) last.y].sprite;
sprite.setColor(0, 0.3f, 0, 1);
lastSelectedTile = sprite;
}
}
if (touchDown) {
float moveX=0,moveY=0;
Vector2 pos = new Vector2();
if (player.direction == direction_left) {
moveX = -(player.moveSpeed);
moveY = -(player.moveSpeed / 2);
Gdx.app.log("Movement", String.valueOf("left"));
} else if (player.direction == direction_upleft) {
moveX = -(player.moveSpeed);
moveY = 0;
Gdx.app.log("Movement", String.valueOf("upleft"));
} else if (player.direction == direction_up) {
moveX = -(player.moveSpeed);
moveY = player.moveSpeed / 2;
Gdx.app.log("Movement", String.valueOf("up"));
} else if (player.direction == direction_upright) {
moveX = 0;
moveY = player.moveSpeed;
Gdx.app.log("Movement", String.valueOf("upright"));
} else if (player.direction == direction_right) {
moveX = player.moveSpeed;
moveY = player.moveSpeed / 2;
Gdx.app.log("Movement", String.valueOf("right"));
} else if (player.direction == direction_downright) {
moveX = player.moveSpeed;
moveY = 0;
Gdx.app.log("Movement", String.valueOf("downright"));
} else if (player.direction == direction_down) {
moveX = player.moveSpeed;
moveY = -(player.moveSpeed / 2);
Gdx.app.log("Movement", String.valueOf("down"));
} else if (player.direction == direction_downleft) {
moveX = 0;
moveY = -(player.moveSpeed);
Gdx.app.log("Movement", String.valueOf("downleft"));
}
//Player.moveSpeed is 1
//tileObjects.x is drawn in the center of the screen (400px,240px)
// the sprite width is 64, height is 128
testX = moveX * 10;
testY = moveY * 10;
testX += tileObjects.get(player.zIndex).x + tileObjects.get(player.zIndex).sprite.getWidth() / 2;
testY += tileObjects.get(player.zIndex).y + tileObjects.get(player.zIndex).sprite.getHeight() / 2;
moveX += tileObjects.get(player.zIndex).x + tileObjects.get(player.zIndex).sprite.getWidth() / 2;
moveY += tileObjects.get(player.zIndex).y + tileObjects.get(player.zIndex).sprite.getHeight() / 2;
pos = ScreentoTile(new Vector2(moveX,moveY));
Vector2 pos2 = ScreentoTile(new Vector2(testX,testY));
if (!levelTiles[(int) pos2.x][(int) pos2.y].collides) {
Vector2 newPlayerPos = ScreentoTile(new Vector2(moveX,moveY));
CenterOnCoord(moveX,moveY);
player.tileX = (int)newPlayerPos.x;
player.tileY = (int)newPlayerPos.y;
}
}
}
When the player is moving to the left (downleft-ish from the viewers point of view),
my Pos2 X values decrease as expected but pos2 isnt checking ahead on the x tiles, it is checking
ahead on the Y tiles(as if we were moving DOWN, not left), and vice versa, if the player moves down, it will check ahead on the X values (as if we are moving LEFT, instead of DOWN).
instead of the Y values.
Basically I want to move my enemy from one position to another.
There starting position is not a problem... neither is the place where they are suppose to go.
The problem lies with the how they get there. With the code I wrote they just teleport off the map.
So I am not even going to post it. Using triangles... what would be the most efficient way to get them from point A to point B?
Lets say point A is 10, 10; and point B is 123, 349. But there is also the chance that A will be B and B will be A. So it also has to deal with negatives.
Now the last thing that complicates the matter is that it moves between 1 and 5 pixels every time it repaints... so if it goes over the position I am not sure how to check to see if its in the general area.
Thanks! Btw I don't need full code... just IDEAS!!! I can code myself. Thank you!!!
current code:
if (enemyList.length > 0) {
for (int[] x : enemyList) {
double changeX;
double changeY;
//if already in spot, anounce it
if (x[0] == x[2] && x[1] == x[3]) {
x[2] = -1;
x[3] = -1;
}
//if anounced generate new spot of interest
if (x[2] == -1 || x[3] == -1) {
x[2] = generateRandom(0, 550);
x[3] = generateRandom(0, 400);
}
//find distance from target and move there
int _y = x[1] - x[3];
int _x = x[0] - x[2];
if (_x > _y) {
changeX = _x / _y;
changeY = _y / _y;
} else {
changeY = _y / _x;
changeX = _x / _x;
}
changeY = changeY * generateRandom(0, 10);
changeX = changeX * generateRandom(0, 10);
//change physical position
x[0] += (int) changeX;
x[1] += (int) changeY;
}
}
Based on the code it looks like your enemy will sort of wiggle to its destination in maybe a curved fashion, but it's hard to tell just by inspection. Maybe you just need to swap your source and destination because it looks like you may just have it backwards:
int _y = x[3] - x[1];
int _x = x[2] - x[0];
Is this what you intended, or should it make a beeline?
speed = 5; // "pixels" per frame
deltaX = destX - sourceX;
deltaY = destY - sourceY;
distance = sqrt(deltaX^2 + deltaY^2);
moveX = speed / distance * deltaX;
moveY = speed / distance * deltaY;
newX = sourceX + moveX;
newY = sourceY + moveY;
I used similar triangles to calculate moveX and moveY. Note the square root is slow, but that may be ok for your purposes... once you have it working, there are ways to optimize out the square root.