Joining shapes together and tracing their outline - java

EDIT: Found solution. I've added it after the question.
I'm designing a game for Android and I'm trying to come up with ways to reduce the calculations at the render stage. I've got a method at the moment which takes all the metal and rubber blocks in the level and stores a texture id into a int[][] grid so that the renderer just reads that instead of calculating every blocks tiled textures every frame.
This works fine but now I'm trying to create a list of corner and straight pieces for the level edges and the laser blocks in the level. The level bounds and laser blocks are drawn using a set of straight laser textures and corner textures. I'm not sure how best to tackle working out where not to render lasers where blocks overlap with other blocks and with the level edges. The pictures below shows what I mean:
drawing
ingame
Here you can see the level edge (the L shaped laser path extending beyond the pictures edges) and three/two internal laser blocks (respectively to picture order). As far as I can tell I should create a similar grid to above but with booleans so any square that kills the player on upon touching (highlighted in red) is true and the safe squares are false.
I then first thought of going through all the true (red) cells in the grid and work out what the laser outline would look like using their neighbouring grid cells but I realised this could very difficult so I'm certain now that I use the false squares to find it out. I'm sure I could get a rough solution working by starting at the lower left square of the level bounds and iterate through the grid until I find a false tile (unless the first square is false) and then travel through the grid going right until I reach a true cell to the right and so I would turn left and continue up through the grid until a true is found above to turn left OR a false is found on the right to turn right. I'd repeat this process until I reach my starting false cell.
I came up with this while writing this question out lol. It seems like the easiest way so I guess my question is is this a good way to do it and how would I work out the laser blocks which touch each other but not touch the level bounds as the above method would only trace the outer most laser path.
Thank you for taking the time to read through this. I hope I've explained it well enough and I look forward to any light that can be shed on this subject.

SOLUTION:
public static boolean[][] laserField = new boolean[(int) Static.WORLD_SIZE][(int)Static.WORLD_SIZE];
public static List<LaserData> laserData = new ArrayList<LaserData>();
public static void calcLaserBoundryAreas() {
laserField = new boolean[(int) Level.levelBounds.bounds.width+5][(int) Level.levelBounds.bounds.height+5];
for (int i=0;i<laserField.length;i++) {
for (int j=0;j<laserField[i].length;j++) {
if(i==0 || i==laserField.length-1 || j==0 || j==laserField[i].length-1)
laserField[i][j] = true;
else
laserField[i][j] = false;
}
}
for (LaserBlock lBlock : lBlocks) {
int cols = (int)lBlock.bounds.width;
int rows = (int)lBlock.bounds.height;
float startX = lBlock.position.x - (cols-1f)/2f;
float startY = lBlock.position.y - (rows-1f)/2f;
for (int i=0;i<cols;i++) {
for (int j=0;j<rows;j++) {
addLaserCell(startX+i, startY+j);
}
}
}
addLaserData();
}
private static void addLaserCell(float x, float y) {
int cellX = (int)(x- Level.levelBounds.bounds.lowerLeft.x+2);
int cellY = (int)(y- Level.levelBounds.bounds.lowerLeft.y+2);
if (cellX < 0 || cellX > laserField.length-1) return;
if (cellY < 0 || cellY > laserField[cellX].length-1) return;
laserField[cellX][cellY] = true;
}
private static void addLaserData() {
laserData = new ArrayList<LaserData>();
for (int i=1;i<laserField.length-1;i++) {
for (int j=1;j<laserField[i].length-1;j++) {
if (!laserField[i][j]) {
checkNeighbours(i,j);
}
}
}
optimiseLaserData();
}
private static void checkNeighbours(int x, int y) {
boolean u = laserField[x][y+1];
boolean ul = laserField[x-1][y+1];
boolean l = laserField[x-1][y];
boolean bl = laserField[x-1][y-1];
boolean b = laserField[x][y-1];
boolean br = laserField[x+1][y-1];
boolean r = laserField[x+1][y];
boolean ur = laserField[x+1][y+1];
/*
* TOP LEFT CORNER
*/
float posX, posY;
posX = Level.levelBounds.bounds.lowerLeft.x+x-2.5f;
posY = Level.levelBounds.bounds.lowerLeft.y+y-1.5f;
if(u && ul && l)
laserData.add(new LaserData(posX, posY, true, 0, 0));
else if(!u && ul && l)
laserData.add(new LaserData(posX, posY, false, 1, 0));
else if(!u && ul && !l)
laserData.add(new LaserData(posX, posY, true, 0, 2));
/*
* BOTTOM LEFT CORNER
*/
posX = Level.levelBounds.bounds.lowerLeft.x+x-2.5f;
posY = Level.levelBounds.bounds.lowerLeft.y+y-2.5f;
if(l && bl && b)
laserData.add(new LaserData(posX, posY, true, 0, 1));
else if(!l && bl && b)
laserData.add(new LaserData(posX, posY, false, 1, 1));
else if(!l && bl && !b)
laserData.add(new LaserData(posX, posY, true, 0, 3));
/*
* BOTTOM RIGHT CORNER
*/
posX = Level.levelBounds.bounds.lowerLeft.x+x-1.5f;
posY = Level.levelBounds.bounds.lowerLeft.y+y-2.5f;
if(b && br && r)
laserData.add(new LaserData(posX, posY, true, 0, 2));
else if(!b && br && r)
laserData.add(new LaserData(posX, posY, false, 1, 2));
else if(!b && br && !r)
laserData.add(new LaserData(posX, posY, true, 0, 0));
/*
* TOP RIGHT CORNER
*/
posX = Level.levelBounds.bounds.lowerLeft.x+x-1.5f;
posY = Level.levelBounds.bounds.lowerLeft.y+y-1.5f;
if(r && ur && u)
laserData.add(new LaserData(posX, posY, true, 0, 3));
else if(!r && ur && u)
laserData.add(new LaserData(posX, posY, false, 1, 3));
else if(!r && ur && !u)
laserData.add(new LaserData(posX, posY, true, 0, 1));
}
private static void optimiseLaserData() {
List<LaserData> optiLaserData = new ArrayList<LaserData>();
for(LaserData ld : laserData) {
if(ld.cornerPiece)
optiLaserData.add(ld);
else if(ld.dir == 0 || ld.dir == 2){
float x = ld.x;
float bottomY = ld.y;
float topY = ld.y;
float count = 1;
while (searchStraightLaserData(laserData, x, topY+1, ld.dir)) {
count++;
topY++;
}
while (searchStraightLaserData(laserData, x, bottomY-1, ld.dir)) {
count++;
bottomY--;
}
float centerY = bottomY + (topY-bottomY)/2;
if(!searchStraightLaserData(optiLaserData, x, centerY, ld.dir))
optiLaserData.add(new LaserData(x, centerY, false, count, ld.dir));
} else {
float y = ld.y;
float leftX = ld.x;
float rightX = ld.x;
float count = 1;
while (searchStraightLaserData(laserData, rightX+1, y, ld.dir)) {
count++;
rightX++;
}
while (searchStraightLaserData(laserData, leftX-1, y, ld.dir)) {
count++;
leftX--;
}
float centerX = leftX + (rightX-leftX)/2;
if(!searchStraightLaserData(optiLaserData, centerX, y, ld.dir))
optiLaserData.add(new LaserData(centerX, y, false, count, ld.dir));
}
}
laserData = optiLaserData;
}
private static boolean searchStraightLaserData(List<LaserData> data, float x, float y, int dir) {
for(LaserData ld : data)
if(ld.x == x && ld.y == y && ld.dir == dir && !ld.cornerPiece)
return true;
return false;
}
These methods first create a boolean grid that is the size of the level edge bounds with a 1 square extra edge on each side. This is initialised to false to represent safe areas and the extra edge is set to true so that we have a kind of hollow box. The extra edge helps later by eliminating the need to check for incorrect indices on the laserField.
After the level extents are mapped to a grid individual cells are changed to true where ever is covered by a laser block.
Once the boolean grid is fully mapped it then iterates through each grid cell and when it finds a cell which is false it passes it grid coordinates to the next method which looks at 12 different neighbour patterns to determine if any lasers should be rendered around this cell. The LaserData constructor takes the following args (float x, float y, boolean cornerPiece, float length, int direction)
The last section does a brute force search to check if any adjacent straight pieces can be replaced by a single longer straight piece to save rendering extra sprites.
The renderer can then just read through the laserData list each frame and it has all the information it needs to render the correct texture, its position, length etc...
NOTE: The width and height of the Level bounds are 3 units smaller than the actual playing area to account for width of player outside the boundry. That's where the levelBounds.lowerleft+5, +2 and + 1.5f etc... come from. It's a little hacky I know but it's old code and I daren't touch it xD

Related

Processing angle calculation on rotated object

I am making a little ant colony simulation in Processing (4).
I have an Ant class, with a sense() , a move()and a render() function.
I also have a Food class with only a position PVector.
My sense class loops through all Foods in a given radius, and it is meant to only 'see' the ones inside a given view angle.
In my render() function I have an arc to visualise this (I do some division and addition so the arc centres in front of the rectangle):
void render() {
// Draw a rectangl rotated in the direction of velocity
float theta = velocity.heading() + radians(90);
if(detectFood) // a Boolean set in sense()
fill(0,173,67); // turns green
else {
stroke(255);
pushMatrix();
translate(position.x, position.y);
fill(200, 100);
rotate(theta); // I copied the rotation code from somewhere :)
rect(0-r/2,0-r,r,r*2); // r is a float used to control size
arc(0, 0, viewRadius * 2, viewRadius * 2, radians(270 - viewAngle/2), radians(270 + viewAngle/2)); // viewRadius is a float set in the constructor
popMatrix();
}
}
This ends up looking like this:
My sense() code uses trigonometry to calculate the angle and the distance (I am using my own calculations because wasn't sure the inbuilt ones did what I thought they did):
void sense() {
if (!detectFood) {
float closest = viewRadius;
Food selected = null;
for (Food fd : foods){
float foodDist = position.dist(fd.position);
if(foodDist <= viewRadius) {
float xs = position.x-fd.position.x;
float ys = position.y-fd.position.y;
float Angle = atan2(abs(ys), abs(xs));
float begin = radians(270 - viewAngle/2);
float end = radians(270 + viewAngle/2);
if(begin < Angle && Angle < end && foodDist < closest){
selected = fd;
closest = foodDist;
println("found food");
}
}
}
if (selected != null){
detectFood = true;
foodFocused = selected;
}
} else {
if(position.dist(foodFocused.position) < r) {
takeFood();
detectFood = false;
}
}
}
The problem is that because I rotate the shape (and the arc with it), my sensing code basically never works. Is there a way to account for rotation in trigonometry or maybe an easier way of doing this? Any help would be apreciated

randomWalk.java what am i missing (Beginner)

I have most of the code written im just having some difficulty finishing up. I am supposed to create some code that will have a square randomly walk around on the drawing board until it walks off the screen. I can get it to work a little bit but i have a feeling it's not correct. Any help will be appreciate.
Here is an example of what it is supposed to look like
Here is my code so far the problem im most concerned about is the walkingRandom method it has stars by it
public class RandomWalk {
// DrawingPanel will have dimensions DIM by DIM
public static final int DIM = 400;
// Start the random walk in the center of the screen
public static final int CENTER = DIM / 2;
// how big should the cursor appear?
public static final int CURSOR_DIM = 10;
// how long should the cursor saty in one place?
public static final int SLEEP_TIME = 5; // milliseconds
public static void main( String[] args ) {
DrawingPanel panel = new DrawingPanel( DIM, DIM );
Random rand = new Random();
walkRandomly( panel, rand );
}
/**
* Draw a random walk on the panel.
* Stop as soon as you walk off the panel.
* Each random step should go only in one
* of these directions: left, right, up, down.
* #param panel a DrawingPanel to draw the
* random walk on
* #param rand a Java Random object to be
* used to generate random steps
*/
public static void walkRandomly( DrawingPanel panel, Random rand ) {
Graphics g = panel.getGraphics();
// start in center of panel
int x = CENTER;
int y = CENTER;
// Randomly step left, right, up, or down
// until cursor goes off screen.
while ( onScreen( x, y ) ) {
// Draw the cursor in BLACK
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
// Wait a bit.
panel.sleep( SLEEP_TIME );
// Show a shadow version of the cursor
g.setColor(Color.GRAY);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
// Choose a new location for the cursor
//*********************************
if (rand.nextInt() < DIM - 300){
x--;
} else if (rand.nextInt() < DIM / 2){
x++;
} else if (rand.nextInt() < DIM - 100){
y--;
} else if (rand.nextInt() < DIM) {
y++;
}
//*********************************
// draw the cursor at its new location
g.setColor(Color.BLACK);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
}
}
/**
* determine whether (x, y) is a point on the panel.
* #param x the x-coord of the cursor
* #param y the y-coord of the cursor
* #return true if (x,y) is on the screen,
* false if (x,y) is off the screen
*/
public static boolean onScreen( int x, int y ) {
// x/y high = 400, x/y low = 0
//*********************************
return (x <= DIM && x >= 0 || y <= DIM && y >= 0);
}
}
There's a few issues with your code. You did not quite clarify in your question, but I assume that:
All directions should have the same probability of occurring
The cursor can only move "full steps" i.e. it has to move by CURSOR_DIM at a time, not less (that's what seems to be happening in your example)
The problem is mainly in the method walkRandomly, I suggest that you select the next direction as follows:
// Choose a new location for the cursor
int direction = rand.nextInt(4); //0=left, 1=right, 2=up, 3=down
if (direction == 0){
x -= CURSOR_DIM; //The step should be equal to the cursor width, not 1
} else if (direction == 1){
x += CURSOR_DIM;
} else if (direction == 2){
//you usually subtract to go up, the origin being the upper-left corner
y -= CURSOR_DIM;
} else if (direction == 3) {
y += CURSOR_DIM;
}
There's two other issues:
You are drawing the cursor in black at the beginning and at the end of the loop, this is redundant. You could remove one of them and have the same result.
In the onScreen method, x and y values equaling DIM should return false, since usually the bounds of an image/array are 0 to DIM exclusive. Also you should replace the || by an AND, because the cursor should be within the x AND y range, not OR.
return (x < DIM && x >= 0 && y < DIM && y >= 0);
Hope it helps

How can I detect the proximity between two images [duplicate]

I have two characters displayed in a game I am writing, the player and the enemy. defined as such:
public void player(Graphics g) {
g.drawImage(plimg, x, y, this);
}
public void enemy(Graphics g) {
g.drawImage(enemy, 200, 200, this);
}
Then called with:
player(g);
enemy(g);
I am able to move player() around with the keyboard, but I am at a loss when trying to detect a collision between the two. A lot of people have said to use Rectangles, but being a beginner I cannot see how I would link this into my existing code. Can anyone offer some advice for me?
I think your problem is that you are not using good OO design for your player and enemies. Create two classes:
public class Player
{
int X;
int Y;
int Width;
int Height;
// Getters and Setters
}
public class Enemy
{
int X;
int Y;
int Width;
int Height;
// Getters and Setters
}
Your Player should have X,Y,Width,and Height variables.
Your enemies should as well.
In your game loop, do something like this (C#):
foreach (Enemy e in EnemyCollection)
{
Rectangle r = new Rectangle(e.X,e.Y,e.Width,e.Height);
Rectangle p = new Rectangle(player.X,player.Y,player.Width,player.Height);
// Assuming there is an intersect method, otherwise just handcompare the values
if (r.Intersects(p))
{
// A Collision!
// we know which enemy (e), so we can call e.DoCollision();
e.DoCollision();
}
}
To speed things up, don't bother checking if the enemies coords are offscreen.
First, use the bounding boxes as described by Jonathan Holland to find if you may have a collision.
From the (multi-color) sprites, create black and white versions. You probably already have these if your sprites are transparent (i.e. there are places which are inside the bounding box but you can still see the background). These are "masks".
Use Image.getRGB() on the mask to get at the pixels. For each pixel which isn't transparent, set a bit in an integer array (playerArray and enemyArray below). The size of the array is height if width <= 32 pixels, (width+31)/32*height otherwise. The code below is for width <= 32.
If you have a collision of the bounding boxes, do this:
// Find the first line where the two sprites might overlap
int linePlayer, lineEnemy;
if (player.y <= enemy.y) {
linePlayer = enemy.y - player.y;
lineEnemy = 0;
} else {
linePlayer = 0;
lineEnemy = player.y - enemy.y;
}
int line = Math.max(linePlayer, lineEnemy);
// Get the shift between the two
x = player.x - enemy.x;
int maxLines = Math.max(player.height, enemy.height);
for ( line < maxLines; line ++) {
// if width > 32, then you need a second loop here
long playerMask = playerArray[linePlayer];
long enemyMask = enemyArray[lineEnemy];
// Reproduce the shift between the two sprites
if (x < 0) playerMask << (-x);
else enemyMask << x;
// If the two masks have common bits, binary AND will return != 0
if ((playerMask & enemyMask) != 0) {
// Contact!
}
}
Links: JGame, Framework for Small Java Games
You don't want to have the collision check code inside the painting code. The painting needs to be fast. Collision can go in the game loop. Therefore you need an internal representation of the objects independent of their sprites.
Here's the main class from my collision detection program.
You can see it run at: http://www.youtube.com/watch?v=JIXhCvXgjsQ
/**
*
* #author Tyler Griffin
*/
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.GraphicsDevice.*;
import java.util.ArrayList;
import java.awt.Graphics;
import java.awt.geom.Line2D;
public class collision extends JFrame implements KeyListener, MouseMotionListener, MouseListener
{
ArrayList everything=new ArrayList<tile>();
int time=0, x, y, width, height, up=0, down=0, left=0, right=0, mouse1=0, mouse2=0;
int mouseX, mouseY;
GraphicsEnvironment environment = GraphicsEnvironment.getLocalGraphicsEnvironment();
GraphicsDevice screen = environment.getDefaultScreenDevice();
DisplayMode displayMode = screen.getDisplayMode();
//private BufferStrategy strategy;
JLayeredPane pane = new JLayeredPane();
tile Tile;
circle Circle;
rectangle Rectangle;
textPane text;
public collision()
{
setUndecorated(screen.isFullScreenSupported());
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setVisible(true);
setLayout(null);
setResizable(false);
screen.setFullScreenWindow(this);
width=displayMode.getWidth();
height=displayMode.getHeight();
Circle=new circle(-(int)Math.round((double)height/7*2),-(int)Math.round((double)height/7*2),(int)Math.round((double)height/7*.85),this);
Rectangle=new rectangle(-(int)Math.round((double)height/7*1.5),-(int)Math.round((double)height/7*1.5),(int)Math.round((double)height/7*1.5),(int)Math.round((double)height/7*1.5),this);
Tile=Circle;
Tile.move(mouseX-Tile.width/2, mouseY-Tile.height/2);
text=new textPane(0,0,width,height,this);
everything.add(new circle((int)Math.round((double)width/100*75),(int)Math.round((double)height/100*15),(int)Math.round((double)width/100*10),this));
everything.add(new rectangle((int)Math.round((double)width/100*70),(int)Math.round((double)height/100*60),(int)Math.round((double)width/100*20),(int)Math.round((double)height/100*20),this));
//everything.add(new line(750,250,750,750,this));
/*everything.add(new line(width/700*419,height/700*68,width/700*495,height/700*345,this));
everything.add(new line(width/700*495,height/700*345,width/700*749,height/700*350,this));
everything.add(new line(width/700*749,height/700*350,width/700*549,height/700*519,this));
everything.add(new line(width/700*549,height/700*519,width/700*624,height/700*800,this));
everything.add(new line(width/700*624,height/700*800,width/700*419,height/700*638,this));
everything.add(new line(width/700*419,height/700*638,width/700*203,height/700*800,this));
everything.add(new line(width/700*203,height/700*800,width/700*279,height/700*519,this));
everything.add(new line(width/700*279,height/700*519,width/700*76,height/700*350,this));
everything.add(new line(width/700*76,height/700*350,width/700*333,height/700*345,this));
everything.add(new line(width/700*333,height/700*345,width/700*419,height/700*68,this));
everything.add(new line(width/950*419,height/700*68,width/950*624,height/700*800,this));
everything.add(new line(width/950*419,height/700*68,width/950*203,height/700*800,this));
everything.add(new line(width/950*76,height/700*350,width/950*624,height/700*800,this));
everything.add(new line(width/950*203,height/700*800,width/950*749,height/700*350,this));
everything.add(new rectangle(width/950*76,height/700*350,width/950*673,1,this));*/
everything.add(new line((int)Math.round((double)width/1350*419),(int)Math.round((double)height/1000*68),(int)Math.round((double)width/1350*624),(int)Math.round((double)height/1000*800),this));
everything.add(new line((int)Math.round((double)width/1350*419),(int)Math.round((double)height/1000*68),(int)Math.round((double)width/1350*203),(int)Math.round((double)height/1000*800),this));
everything.add(new line((int)Math.round((double)width/1350*76),(int)Math.round((double)height/1000*350),(int)Math.round((double)width/1350*624),(int)Math.round((double)height/1000*800),this));
everything.add(new line((int)Math.round((double)width/1350*203),(int)Math.round((double)height/1000*800),(int)Math.round((double)width/1350*749),(int)Math.round((double)height/1000*350),this));
everything.add(new rectangle((int)Math.round((double)width/1350*76),(int)Math.round((double)height/1000*350),(int)Math.round((double)width/1350*673),1,this));
addKeyListener(this);
addMouseMotionListener(this);
addMouseListener(this);
}
public void keyReleased(KeyEvent e)
{
Object source=e.getSource();
int released=e.getKeyCode();
if (released==KeyEvent.VK_A){left=0;}
if (released==KeyEvent.VK_W){up=0;}
if (released==KeyEvent.VK_D){right=0;}
if (released==KeyEvent.VK_S){down=0;}
}//end keyReleased
public void keyPressed(KeyEvent e)
{
Object source=e.getSource();
int pressed=e.getKeyCode();
if (pressed==KeyEvent.VK_A){left=1;}
if (pressed==KeyEvent.VK_W){up=1;}
if (pressed==KeyEvent.VK_D){right=1;}
if (pressed==KeyEvent.VK_S){down=1;}
if (pressed==KeyEvent.VK_PAUSE&&pressed==KeyEvent.VK_P)
{
//if (paused==0){paused=1;}
//else paused=0;
}
}//end keyPressed
public void keyTyped(KeyEvent e){}
//***********************************************************************************************
public void mouseDragged(MouseEvent e)
{
mouseX=(e.getX());
mouseY=(e.getY());
//run();
}
public void mouseMoved(MouseEvent e)
{
mouseX=(e.getX());
mouseY=(e.getY());
//run();
}
//***********************************************************************************************
public void mousePressed(MouseEvent e)
{
if(e.getX()==0 && e.getY()==0){System.exit(0);}
mouseX=(e.getX()+x);
mouseY=(e.getY()+y);
if(Tile instanceof circle)
{
Circle.move(0-Circle.width, 0-Circle.height);
Circle.setBounds(Circle.x, Circle.y, Circle.width, Circle.height);
Tile=Rectangle;
}
else
{
Rectangle.move(0-Rectangle.width, 0-Rectangle.height);
Rectangle.setBounds(Rectangle.x, Rectangle.y, Rectangle.width, Rectangle.height);
Tile=Circle;
}
Tile.move(mouseX-Tile.width/2, mouseY-Tile.height/2);
}
public void mouseReleased(MouseEvent e)
{
//run();
}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseClicked(MouseEvent e){}
//***********************************************************************************************
public void run()//run collision detection
{
while (this == this)
{
Tile.move(Tile.x + ((mouseX - (Tile.x + (Tile.width / 2))) / 10), Tile.y + ((mouseY - (Tile.y + (Tile.height / 2))) / 10));
//Tile.move((mouseX - Tile.width / 2), mouseY - (Tile.height / 2));
for (int i = 0; i < everything.size(); i++)
{
tile Temp = (tile) everything.get(i);
if (Temp.x < (Tile.x + Tile.width) && (Temp.x + Temp.width) > Tile.x && Temp.y < (Tile.y + Tile.height) && (Temp.y + Temp.height) > Tile.y)//rectangles collided
{
if (Temp instanceof rectangle)
{
if (Tile instanceof rectangle){rectangleRectangle(Temp);}
else {circleRectangle(Temp);}//Tile instanceof circle
}
else
{
if (Temp instanceof circle)
{
if (Tile instanceof rectangle) {rectangleCircle(Temp);}
else {circleCircle(Temp);}
}
else//line
{
if (Tile instanceof rectangle){rectangleLine(Temp);}
else{circleLine(Temp);}
}
}
}//end if
}//end for
try {Thread.sleep(16L);}
catch (Exception e) {}
Tile.setBounds(Tile.x, Tile.y, Tile.width, Tile.height);
//Rectangle.setBounds(x, y, width, height);
//Circle.setBounds(x, y, width, height);
repaint();
text.out=" ";
}//end while loop
}//end run
//***************************************special collision detection/handling functions************************************************
void rectangleRectangle(tile Temp)
{
int lapTop, lapBot, lapLeft, lapRight, small, scootX=0, scootY=0;
lapTop=(Temp.y+Temp.height)-Tile.y;
lapBot=(Tile.y+Tile.height)-Temp.y;
lapLeft=(Temp.x+Temp.width)-Tile.x;
lapRight=(Tile.x+Tile.width)-Temp.x;
small=999999999;
if (lapTop<small){small=lapTop; scootX=0; scootY=lapTop;}
if (lapBot<small){small=lapBot; scootX=0; scootY=lapBot*-1;}
if (lapLeft<small){small=lapLeft; scootX=lapLeft; scootY=0;}
if (lapRight<small){small=lapRight; scootX=lapRight*-1; scootY=0;}
Tile.move(Tile.x+scootX, Tile.y+scootY);text.out="collision detected!";
}
void circleRectangle(tile Temp)
{
if((Tile.x+Tile.width/2<=Temp.x+Temp.width && Tile.x+Tile.width/2>=Temp.x)||(Tile.y+Tile.height/2>=Temp.y && Tile.y+Tile.height/2<=Temp.y+Temp.height))
{
rectangleRectangle(Temp);
}
else//push from nearest corner
{
int x,y;
if(Tile.x+Tile.width/2>Temp.x+Temp.width && Tile.y+Tile.height/2<Temp.y){x=Temp.x+Temp.width; y=Temp.y;}
else if(Tile.x+Tile.width/2<Temp.x && Tile.y+Tile.height/2<Temp.y){x=Temp.x; y=Temp.y;}
else if(Tile.x+Tile.width/2>Temp.x+Temp.width && Tile.y+Tile.height/2>Temp.y+Temp.height){x=Temp.x+Temp.width; y=Temp.y+Temp.height;}
else {x=Temp.x; y=Temp.y+Temp.height;}
double distance = Math.sqrt(Math.pow(Tile.x+(Tile.width/2) - x, 2) + Math.pow(Tile.y+(Tile.height/2) - y, 2));
if((int)Math.round(distance)<Tile.height/2)
{
double normY = ((Tile.y+(Tile.height/2) - y) / distance);
double normX = ((Tile.x+(Tile.width/2) - x) / distance);
Tile.move(x-Tile.width/2+(int)Math.round(normX*((Tile.width/2))) , y-Tile.height/2+(int)Math.round(normY*((Tile.height/2))));text.out="collision detected!";
}
}
}
void rectangleCircle(tile Temp)
{
if((Temp.x+Temp.width/2<=Tile.x+Tile.width && Temp.x+Temp.width/2>=Tile.x)||(Temp.y+Temp.height/2>=Tile.y && Temp.y+Temp.height/2<=Tile.y+Tile.height))
{
rectangleRectangle(Temp);
}
else//push from nearest corner
{
int x,y;
if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2<Tile.y){x=Tile.x+Tile.width; y=Tile.y;}
else if(Temp.x+Temp.width/2<Tile.x && Temp.y+Temp.height/2<Tile.y){x=Tile.x; y=Tile.y;}
else if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2>Tile.y+Tile.height){x=Tile.x+Tile.width; y=Tile.y+Tile.height;}
else {x=Tile.x; y=Tile.y+Tile.height;}
double distance = Math.sqrt(Math.pow(Temp.x+(Temp.width/2) - x, 2) + Math.pow(Temp.y+(Temp.height/2) - y, 2));
if((int)Math.round(distance)<Temp.height/2)
{
double normY = ((Temp.y+(Temp.height/2) - y) / distance);
double normX = ((Temp.x+(Temp.width/2) - x) / distance);
if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2<Tile.y){Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2)))-Tile.width,(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2))));text.out="collision detected!";}
else if(Temp.x+Temp.width/2<Tile.x && Temp.y+Temp.height/2<Tile.y){Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2))),(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2))));text.out="collision detected!";}
else if(Temp.x+Temp.width/2>Tile.x+Tile.width && Temp.y+Temp.height/2>Tile.y+Tile.height){Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2)))-Tile.width,(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2)))-Tile.height);text.out="collision detected!";}
else {Tile.move((Temp.x+Temp.width/2)-(int)Math.round(normX*((Temp.width/2))),(Temp.y+Temp.height/2)-(int)Math.round(normY*((Temp.height/2)))-Tile.height);text.out="collision detected!";}
}
}
}
void circleCircle(tile Temp)
{
double distance = Math.sqrt(Math.pow((Tile.x+(Tile.width/2)) - (Temp.x+(Temp.width/2)),2) + Math.pow((Tile.y+(Tile.height/2)) - (Temp.y+(Temp.height/2)), 2));
if((int)distance<(Tile.width/2+Temp.width/2))
{
double normX = ((Tile.x+(Tile.width/2)) - (Temp.x+(Temp.width/2))) / distance;
double normY = ((Tile.y+(Tile.height/2)) - (Temp.y+(Temp.height/2))) / distance;
Tile.move((Temp.x+(Temp.width/2))+(int)Math.round(normX*(Tile.width/2+Temp.width/2))-(Tile.width/2) , (Temp.y+(Temp.height/2))+(int)Math.round(normY*(Tile.height/2+Temp.height/2))-(Tile.height/2));text.out="collision detected!";
}
}
void circleLine(tile Temp)
{
line Line=(line)Temp;
if (Line.x1 < (Tile.x + Tile.width) && (Line.x1) > Tile.x && Line.y1 < (Tile.y + Tile.height) && Line.y1 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x1, Line.y1, 1, 1, this);
circleRectangle(rec);
remove(rec);
}
if (Line.x2 < (Tile.x + Tile.width) && (Line.x2) > Tile.x && Line.y2 < (Tile.y + Tile.height) && Line.y2 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x2, Line.y2, 1, 1, this);
circleRectangle(rec);
remove(rec);
}
int x1=0, y1=0, x2=Tile.x+(Tile.width/2), y2=Tile.y+(Tile.height/2);
x1=Tile.x+(Tile.width/2)-Line.height;//(int)Math.round(Line.xNorm*1000);
x2=Tile.x+(Tile.width/2)+Line.height;
if(Line.posSlope)
{
y1=Tile.y+(Tile.height/2)-Line.width;
y2=Tile.y+(Tile.height/2)+Line.width;
}
else
{
y1=Tile.y+(Tile.height/2)+Line.width;
y2=Tile.y+(Tile.height/2)-Line.width;
}
Point point=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
if (point.x < (Line.x + Line.width) && point.x > Line.x && point.y < (Line.y + Line.height) && point.y > Line.y)//line intersects within line segment
{
//if(point!=null){System.out.println(point.x+","+point.y);}
double distance = Math.sqrt(Math.pow((Tile.x+(Tile.width/2)) - point.x,2) + Math.pow((Tile.y+(Tile.width/2)) - point.y, 2));
if((int)distance<Tile.width/2)
{
//System.out.println("hit");
double normX = ((Tile.x+(Tile.width/2)) - point.x) / distance;
double normY = ((Tile.y+(Tile.height/2)) - point.y) / distance;
Tile.move((point.x)+(int)Math.round(normX*(Tile.width/2))-(Tile.width/2) , (point.y)+(int)Math.round(normY*(Tile.height/2))-(Tile.height/2));text.out="collision detected!";
//System.out.println(point.x+","+point.y);
}
}
//new bullet(this, (int)Math.round(tryX), (int)Math.round(tryY));
}
void rectangleLine(tile Temp)
{
line Line=(line)Temp;
if(new Line2D.Double(Line.x1,Line.y1,Line.x2,Line.y2).intersects(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height)))
{
if (Line.x1 < (Tile.x + Tile.width) && (Line.x1) > Tile.x && Line.y1 < (Tile.y + Tile.height) && Line.y1 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x1, Line.y1, 1, 1, this);
rectangleRectangle(rec);
remove(rec);
}
if (Line.x2 < (Tile.x + Tile.width) && (Line.x2) > Tile.x && Line.y2 < (Tile.y + Tile.height) && Line.y2 > Tile.y)//circle may be hitting one of the end points
{
rectangle rec=new rectangle(Line.x2, Line.y2, 1, 1, this);
rectangleRectangle(rec);
remove(rec);
}
if(Line.posSlope)//positive sloped line
{
//first we'll do the top left corner
int x1=Tile.x-Line.height;
int x2=Tile.x+Line.height;
int y1=Tile.y-Line.width;
int y2=Tile.y+Line.width;
Point topPoint=new Point(-99,-99), botPoint=new Point(-99,-99);
double topDistance=0, botDistance=0;
topPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
topDistance = Math.sqrt(Math.pow(Tile.x - topPoint.x,2) + Math.pow(Tile.y - topPoint.y, 2));
//new let's do the bottom right corner
x1=Tile.x+Tile.width-Line.height;
x2=Tile.x+Tile.width+Line.height;
y1=Tile.y+Tile.height-Line.width;
y2=Tile.y+Tile.height+Line.width;
botPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
botDistance = Math.sqrt(Math.pow((Tile.x+Tile.width) - botPoint.x,2) + Math.pow((Tile.y+Tile.height) - botPoint.y, 2));
if(topDistance<botDistance)
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(topPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(topPoint))
{
Tile.move(topPoint.x,topPoint.y);text.out="collision detected!";
}
}
else
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(botPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(botPoint))
{
Tile.move(botPoint.x-Tile.width,botPoint.y-Tile.height);text.out="collision detected!";
}
}
}
else//negative sloped lne
{
//first we'll do the top right corner
int x1=Tile.x+Tile.width-Line.height;
int x2=Tile.x+Tile.width+Line.height;
int y1=Tile.y+Line.width;
int y2=Tile.y-Line.width;
Point topPoint=new Point(-99,-99), botPoint=new Point(-99,-99);
double topDistance=0, botDistance=0;
topPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
topDistance = Math.sqrt(Math.pow(Tile.x + Tile.width - topPoint.x,2) + Math.pow(Tile.y - topPoint.y, 2));
//new let's do the bottom left corner
x1=Tile.x-Line.height;
x2=Tile.x+Line.height;
y1=Tile.y+Tile.height+Line.width;
y2=Tile.y+Tile.height-Line.width;
botPoint=intersection((double)x1,(double)y1,(double)x2,(double)y2,(double)Line.x1,(double)Line.y1,(double)Line.x2,(double)Line.y2);//find intersection
botDistance = Math.sqrt(Math.pow(Tile.x - botPoint.x,2) + Math.pow((Tile.y+Tile.height) - botPoint.y, 2));
if(topDistance<botDistance)
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(topPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(topPoint))
{
Tile.move(topPoint.x-Tile.width,topPoint.y);text.out="collision detected!";
}
}
else
{
if(new Rectangle(Tile.x,Tile.y,Tile.width,Tile.height).contains(botPoint) && new Rectangle(Line.x,Line.y,Line.width,Line.height).contains(botPoint))
{
Tile.move(botPoint.x,botPoint.y-Tile.height);text.out="collision detected!";
}
}
}
}
}
public Point intersection(double x1, double y1, double x2, double y2,double x3, double y3, double x4, double y4)//I didn't write this. got it from http://www.ahristov.com/tutorial/geometry-games/intersection-lines.html (I altered it)
{
double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4)) / d;
double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4)) / d;
int x=(int)Math.round(xi);
int y=(int)Math.round(yi);
return new Point(x, y);
}
//***************************************************************************************
public static void main(String[] args)
{
final collision Collision=new collision();
Collision.run();
}//end main
}//end class
Since Java doesn't have an intersect function (really!?) you can do collision detection by simply comparying the X and Y, Width and Height values of the bounding boxes (rectangle) for each of the objects that could potentially collide.
So... in the base object of each colliding object... i.e. if your player and enemy have a common base you can put a simple Rectangle object called something like BoundingBox. If the common base is a built in Java class then you'll need to create a class that extends the build in class and have the player and enemy objects extend your new class or are instances of that class.
At creation (and each tick or update) you'll need to set the BoundingBox paremeters for both your player and enemy. I don't have the Rectangle class infront of me but its most likely something like X, Y, Width and finally Height. X and Y are that objects location in your game world. The width and height are self explanatory I think. They'll most likely come out from the right of the players location though so, if the X and Y were bothe at 0 and your Width and Height were both at 256 you wouldn't see anything because the character would be at the top left outside of the screen.
Anyways... to detect a collision, you'll want to compare the attributes of the player and enemy BoundingBoxes. So something like this...
if( Player.BoundingBox.X = Enemy.BoundingBox.X && If( Player.BoundingBox.Y = Enemy.BoundingBox.Y )
{
//Oh noes! The enemy and player are on top of eachother.
}
The logic can get sort of complicated but you'll need to compare the distances between each BoundingBox and compare locations.
Here's a useful of an open source game that uses a lot of collisions: http://robocode.sourceforge.net/
You may take a look at the code and complement with the answers written here.
is there a problem with:
Rectangle box1 = new Rectangle(100,100,100,100);
Rectangle box2 = new Rectangle(200,200,100,100);
// what this means is if any pixel in box2 enters (hits) box1
if (box1.contains(box2))
{
// collision occurred
}
// your code for moving the boxes
this can also be applied to circles:
Ellipse2D.Double ball1 = new Ellipse2D.Double(100,100,200,200);
Ellipse2D.Double ball2 = new Ellipse2D.Double(400,100,200,200);
// what this means is if any pixel on the circumference in ball2 touches (hits)
// ball1
if (ball1.contains(ball2))
{
// collision occurred
}
// your code for moving the balls
to check whether youve hit the edge of a screen you could use the following:
Rectangle screenBounds = jpanel.getBounds();
Ellipse2D.Double ball = new Ellipse2D.Double(100,100,200,200); // diameter 200
Rectangle ballBounds = ball.getBounds();
if (!screenBounds.contains(ballBounds))
{
// the ball touched the edge of the screen
}
Use a rectangle to surround each player and enemy, the height and width of the rectangles should correspond to the object you're surrounding, imagine it being in a box only big enough to fit it.
Now, you move these rectangles the same as you do the objects, so they have a 'bounding box'
I'm not sure if Java has this, but it might have a method on the rectangle object called .intersects() so you'd do if(rectangle1.intersectS(rectangle2) to check to see if an object has collided with another.
Otherwise you can get the x and y co-ordinates of the boxes and using the height/width of them detect whether they've intersected yourself.
Anyway, you can use that to either do an event on intersection (make one explode, or whatever) or prevent the movement from being drawn. (revert to previous co-ordinates)
edit: here we go
boolean
intersects(Rectangle r)
Determines whether or not this Rectangle and the specified
Rectangle intersect.
So I would do (and don't paste this code, it most likely won't work, not done java for a long time and I didn't do graphics when I did use it.)
Rectangle rect1 = new Rectangle(player.x, player.y, player.width, player.height);
Rectangle rect2 = new Rectangle(enemy.x, enemy.y, enemy.width, enemy.height);
//detects when the two rectangles hit
if(rect1.intersects(rect2))
{
System.out.println("game over, g");
}
obviously you'd need to fit that in somewhere.
No need to use rectangles ... compare the coordinates of 2 players constantly.
like
if(x1===x&&y1==y)
remember to increase the range of x when ur comparing.
if ur rectangle width is 30 take as if (x1>x&&x2>x+30)..likewise y
It's Java code for collision of two or more ImageViews not rectangles or other,use ImageViews Instead.
1.This code of Collision works every where in any views or layouts.
2.Add a timer to repeat it and to detect collision repeatedly.
3.It only works with views and layout.
if ((getLocationX(_v1) > (getLocationX(_v2) - ((_w2*3) + 40))) && (getLocationX(_v1) < (getLocationX(_v2) + ((_w2*3) +40)))){
if ((getLocationY(_v1) > (getLocationY(_v2) - ((_h2*3) + 40))) && (getLocationY(_v1) < (getLocationY(_v2) + ((_h2*3) +40)))){
showMessage("Collided");
}
}

kinect Gesture recognition in SimpleOpenNI

I want to implement a kind of drums. For every hit I want to play a song. So I need to detect every "hit" and the position. before I start implementing a function who will analyse the positions and detect "hits" I want to be sure that there is no other solution, so is there any event, gesture detection who allow me to detect that ?
As far as I know there is no "event" that is defined natively other than stream callbacks which are called when you receive data such as the joint positions and depth image which should be enough to get you started.
I would take a look at this:https://code.google.com/p/kineticspace/ in order to know what to expect or how to proceed with your own code.
Once you manage to get the skeleton data just find where the hand is at that time, put a threshold to its position and start tracking for a certain amount time and see if its movement path fits your pattern for a particular gesture such as "translation in y direction for x amount of seconds". Then you have very simple "hit" gesture detection. This can get as complex as you need, but there is not much to it at the basics in terms of what you receive from the library side.
Good luck.
I made a drum kit with the Kinect using this is a wonderful class for placing and using boxes in Kinect.
Import Libraries:
import processing.opengl.*;
import SimpleOpenNI.*;
Use something like this bit of code inside your Setup()
myTrigger = new Hotpoint(200, 10, 800, size);
Use the methods inside your draw()
if(myTrigger.currentlyHit()) {
myTrigger.play();
println("trigger hit");
}
Use the following methods inside this class!
class Hotpoint {
PVector center;
color fillColor;
color strokeColor;
int size;
int pointsIncluded;
int maxPoints;
boolean wasJustHit;
int threshold;
Hotpoint(float centerX, float centerY, float centerZ, int boxSize) {
center = new PVector(centerX, centerY, centerZ);
size = boxSize;
pointsIncluded = 0;
maxPoints = 1000;
threshold = 0;
fillColor = strokeColor = color(random(255), random(255), random(255));
}
void setThreshold( int newThreshold ){
threshold = newThreshold;
}
void setMaxPoints(int newMaxPoints) {
maxPoints = newMaxPoints;
}
void setColor(float red, float blue, float green){
fillColor = strokeColor = color(red, blue, green);
}
boolean check(PVector point) {
boolean result = false;
if (point.x > center.x - size/2 && point.x < center.x + size/2) {
if (point.y > center.y - size/2 && point.y < center.y + size/2) {
if (point.z > center.z - size/2 && point.z < center.z + size/2) {
result = true;
pointsIncluded++;
}
}
}
return result;
}
void draw() {
pushMatrix();
translate(center.x, center.y, center.z);
fill(red(fillColor), blue(fillColor), green(fillColor),
255 * percentIncluded());
stroke(red(strokeColor), blue(strokeColor), green(strokeColor), 255);
box(size);
popMatrix();
}
float percentIncluded() {
return map(pointsIncluded, 0, maxPoints, 0, 1);
}
boolean currentlyHit() {
return (pointsIncluded > threshold);
}
boolean isHit() {
return currentlyHit() && !wasJustHit;
}
void clear() {
wasJustHit = currentlyHit();
pointsIncluded = 0;
}
}

Game programming ai: scaling walls to find a player?

I have been working on this artificial intelligence method for a while. It basically has an int for each direction the enemy could go if a wall were blocking his path to the player. This doesn't work in most cases. Sometimes the enemy will go through cracks it can't fit through. Other times it will be stuck on walls that have obvious gaps in them. I will attach my code, but if it looks too inefficient or just not the way to solve it I'm not opposed to changing my approach altogether. I just would like to know how these things are done normally, so that I can implement it in a better (and working!) way.
My code:
public void update(ArrayList<Wall> walls, Player p){
findPlayer(p.getX(), p.getY());
boolean isCollision = false;
System.out.println(isCollision);
//if movement straight towards the player is blocked, move along the walls
for(Wall w : walls){
if(Helper.isBoundingBoxCollision((int)(x + vectorToPlayer.getDX() * SPEED), (int)(y + vectorToPlayer.getDY() * SPEED), width, height, w.getX(), w.getY(), w.width, w.height)){
isCollision = true;
if(Math.abs(vectorToPlayer.getDX()) > Math.abs(vectorToPlayer.getDY())){
if(vectorToPlayer.getDX() > 0)
WALL_COLLISION = 3;
else
WALL_COLLISION = 1;
}
else if(Math.abs(vectorToPlayer.getDX()) < Math.abs(vectorToPlayer.getDY())){
if(vectorToPlayer.getDY() > 0)
WALL_COLLISION = 0;
else
WALL_COLLISION = 2;
}
}
}
//System.out.println(isCollision);
//set the direction to the straight on vector, to be reset if there is a collision on this path
direction = vectorToPlayer;
if(isCollision){
//reset the variable, don't mind that what this is named is completely opposite = PIMPIN'
isCollision = false;
//scale dem walls son, and see when the path is clear
for(Wall w : walls){
if(WALL_COLLISION == 0 && !Helper.isBoundingBoxCollision(x + SPEED, y, width, height, w.getX(), w.getY(), w.width, w.height)){
WALL_COLLISION = 3;
isCollision = true;
}
else if(WALL_COLLISION == 1 && !Helper.isBoundingBoxCollision(x, y + SPEED, width, height, w.getX(), w.getY(), w.width, w.height)){
WALL_COLLISION--;
isCollision = true;
}
else if(WALL_COLLISION == 2 && !Helper.isBoundingBoxCollision(x - SPEED, y, width, height, w.getX(), w.getY(), w.width, w.height)){
WALL_COLLISION--;
isCollision = true;
}
else if(WALL_COLLISION == 3 && !Helper.isBoundingBoxCollision(x, y - SPEED, width, height, w.getX(), w.getY(), w.width, w.height)){
WALL_COLLISION--;
isCollision = true;
}
}
//if there is NOT a wall on the designated side, set the vector accoridingly
if(isCollision){
if(WALL_COLLISION == 0)
direction = new NVector(0, 1);
else if(WALL_COLLISION == 1)
direction = new NVector(1, 0);
else if(WALL_COLLISION == 2)
direction = new NVector(0, -1);
else if(WALL_COLLISION == 3)
direction = new NVector(-1, 0);
}
}
x += Math.round(direction.getDX()*SPEED);
y += Math.round(direction.getDY()*SPEED);
}
It appears that what you are currently trying to implement is known as Steering, but the way these things are normally done would be Pathfinding. Which you decide to use depends on your application. Steering is done by moving toward your target but changing direction if there is an obstacle, and it is not guaranteed to reach its destination. Pathfinding is usually done by constructing a graph of waypoints or areas that are "walkable" and then using an algorithm such as Dijkstra's to traverse it.

Categories