Collision detection does not seem to work - java

I am currently working on a school project where I am creating a side scrolling game. I am at the stage where I require collision detection. I would like my character sprite's visibility to be set to false when it intersects the evil character sprite.
Rectangle d = character.getCharRec();
for (EvilCharacter eChar1 : eChar) {
EvilCharacter m = (EvilCharacter) eChar1;
Rectangle wolfRec = m.getEvilCharRec();
if (d.intersects(wolfRec)) {
System.out.println("WASTED");
character.setAlive(false);
gameOver = true;
}
}
The above code unfortunately does not work (when the character sprite intersects the evil character sprite nothing happens) but strangely enough the code below does (when the rock sprite intersects the evil character sprite both sprites visibility's are set to false). If anyone is able to provide assistance it would be much appreciated.
ArrayList rocks = character.getRocks();
for (Object rock : rocks) {
Rock t = (Rock) rock;
Rectangle t1 = t.getRockRec();
for (EvilCharacter eChar1 : eChar) {
EvilCharacter m = (EvilCharacter) eChar1;
Rectangle wolfRec = m.getEvilCharRec();
if (t1.intersects(wolfRec) && m.Living()) {
t.setVisible(false);
m.setDead(false);
score = score + 10;
}
}
}
(Apologies for the simplistic coding, we don't go over complex or efficient coding in school all that much...)

Related

My game collision system doesn't work on more than one tile

I'm working on a collision system for my game, however I can't get it to work, if I add more than one wall (which is the object I'm rendering) the collision system doesn't work and I can get through the block.
However if I leave only one wall the collision works correctly, or if at the end of the loop I add a break;
the collision works but only on the first wall of the map, the others don't get the collision.
Would anyone know how to solve this? I've been trying to solve it for 2 days and I couldn't.
public boolean checkCollisionWall(int xnext, int ynext){
int[] xpoints1 = {xnext+3,xnext+3,xnext+4,xnext+3,xnext+3,xnext+4,xnext+10,xnext+11,xnext+11,xnext+10,xnext+11,xnext+11};
int[] ypoints1 = {ynext+0,ynext+8,ynext+9,ynext+11,ynext+12,ynext+15,ynext+15,ynext+12,ynext+11,ynext+9,ynext+8,ynext+0};
int npoints1 = 12;
Polygon player = new Polygon(xpoints1,ypoints1,npoints1);
Area area = new Area(player);
for(int i = 0; i < Game.walls.size(); i++){
Wall atual = Game.walls.get(i);
int[] xpoints2 = {atual.getX(),atual.getX(),atual.getX()+16,atual.getX()+16};
int[] ypoints2 = {atual.getY(),atual.getY()+16,atual.getY()+16,atual.getY()};
int npoints2 = 4;
Polygon Wall = new Polygon(xpoints2,ypoints2,npoints2);
area.intersect(new Area(Wall));
if(area.isEmpty()){
return true;
}
}
return false;
}
I'm pretty sure the problem is this call:
area.intersect(new Area(Wall));
Here's the JavaDoc for that method:
public void intersect(Area rhs)
Sets the shape of this Area to the intersection of its current shape
and the shape of the specified Area. The resulting shape of this Area
will include only areas that were contained in both this Area and also
in the specified Area.
So area, which represents the shape of your player, is going to be modified by each test with a wall, which is why it's only working with one wall.
You could fix the issue by simply making the player Area the argument of the call, as in:
Area wallArea = new Area(Wall);
wallArea.intersect(area);
if(wallArea.isEmpty()){
return true;
}
By the way, this logic is reversed isn't it. Don't you want to check that the resulting area is not empty, i.e. there was an overlap between the player and the wall?
The other option, if each Wall is actually a rectangle, would be to use the this Area method instead:
public boolean intersects(double x,
double y,
double w,
double h)
Tests if the interior of the Shape intersects the interior of a
specified rectangular area. The rectangular area is considered to
intersect the Shape if any point is contained in both the interior of
the Shape and the specified rectangular area.
Something like this:
if(area.intersects(atual.getX(), atual.getY(), 16, 16)) {
return true;
}
As this avoids the creation of an Area object for each wall, and the intersection test is going to be much simpler, and faster.

Optimal Path-finding technique in a non-standard maze

So, my problem is that I'm currently working on a path-finding technique in an open world with tiles of various sizes. The object needs to find an optimal path to a destination inside an infinite world (it generates on the fly), which is filled with tiles of various sizes (which are not located on a set grid - they can have any location and size - and neither have to be integers). (The object has access to the data of all the tiles via and ArrayList). Now some factors that make this problem more difficult:
The objects itself has a size and cannot move through tiles. Therefore, it is possible for a path to exist that is too narrow for the object to move through.
The target destination may itself be a moving object.
It is possible for there to be dozens of such objects at the same time - so it is necessary for the algorithm to either be light on the system or for the path to be calculated in a few separate ticks of the program.
I tried implementing solutions for maze-solving techniques, but the main problem is the in most mazes, the tiles can only have very specific coordinates (such as whole numbers) and are always the same size.
I also tried rendering the scene as a giant conventional maze where tiles are actually pixels of tiles (so if i have a 20x40 tile it becomes a 20x40 block of 1x1 tiles), but ran into performance issues and the still didn't solve the issue with a path potentially being to narrow for the object to fit through.
EDIT:
Terribly sorry for my poor wording before, that happens when I'm trying to rush to a solution without fully understanding the question. So what I'm using the algorithm for at the moment is for NPC enemies to find their way to the player around obstacles. Here is an example of a scene:
The black circle with an arrow is the player, the black bush-like blobs are the NPC enemies. So this my my current algorithm I'm using for the enemy AI:
void move() { //part of the Enemy class, this function is called once each tick for every enemy
PVector velocity = new PVector(speed*game.dt, 0); //speed is a pre-set float denoting the enemy's speed, game.dt is deltatim
velocity.rotate(atan2(game.player.location.y-location.y, game.player.location.x-location.x)); //game.player.location is a PVector of the player's position, location is a PVector of this enemy's position
boolean init_collision = getTileCollision(); //getTileCollision is a boolean of whether this enemy is colliding with any tile
location.add(velocity);
boolean collision = getTileCollision();
if (!init_collision && collision) { //if the enemy happens to spawn inside a tile, let is move out of it before checking for collision
location.sub(velocity);
if (desired_heading != -1) { //desired heading is the angle, in radians, of which 90-degree angle the enemy wants to move in, by default set to -1 (see my descrition of this algorithm below)
velocity = new PVector(speed*game.dt, 0);
velocity.rotate(desired_heading);
location.add(velocity);
if (getTileCollision()) {
location.sub(velocity);
velocity = new PVector(speed*game.dt, 0);
velocity.rotate(current_heading); //current heading the an angle, in radians, of which 90-degree angle the enemy is currently moving in. set to -1 by default but can not equal -1 if desired_heading is not -1
location.add(velocity);
if (getTileCollision()) {
location.sub(velocity);
desired_heading = -1;
current_heading = -1;
}
} else {
desired_heading = -1;
current_heading = -1;
}
} else {
float original_heading = velocity.heading();
desired_heading = radians(round(degrees(velocity.heading())/90.0)*90.0); //round to the nearest 90 degrees
velocity = new PVector(speed*game.dt, 0);
velocity.rotate(desired_heading);
location.add(velocity);
if (getTileCollision()) {
location.sub(velocity);
}
float turn = radians(90);
while (true) { //if it cant move, try rotating 90 degrees and moving
velocity.rotate(turn);
location.add(velocity);
if (!getTileCollision() && abs(round(degrees(current_heading)) - round(degrees(velocity.heading()))) != 180) {
current_heading = velocity.heading();
break;
} else {
location.sub(velocity);
}
}
}
} else {
desired_heading = -1;
current_heading = -1;
}
}
So what my terrible code hopes to accomplish is the the enemy first tries to move directly at the player. If it encounters an obstacle, it will round its angle to the nearest 90 degrees, set desired_heading to this and try to move through. If it cant, it will rotate another 90 degrees and so forth, always keeping the original rounded angle in mind.
This doesn't work remotely well as first of all, rotating 90 degrees has a 50% chance to go in the exact wrong diretion, so I tried adding
if (abs(original_heading - velocity.heading()+turn) < abs(original_heading - velocity.heading()-turn)) {
turn = radians(-90);
}
right before the while (true) but that broke the algorithm completely (sometimes the enemy will freeze in deep thought and not move ever again).
What am I doing terribly wrong? Should I try a different algorithm or does this one have potential?
I hope this is a better question now...

LibGDX - Collision detection between Player and a Platform (or tile) WITHOUT using TiledMap

In my game the character is constantly moving from left to right, so there will never be a situation where he hits the right side of a platform. I had a very brief talk with somebody and he suggested me to model my platform as 4 rectangles so that I would only need 3 cases in my algorithm (i.e. Player can only collide with the rectangles shaded green in the image below). Here's a visual description of what I mean:
I gave it a try but the collision detection is still messed up. It doesn't go through the side of the platform (this is good news since we want this to happen) but you can't glide on top of it or bounce under it. Can anyone see where I may have gone wrong?
public void checkCollisions(ArrayList<GameObject> list) {
for (int i = 0; i < list.size(); i++) {
for (int j = i + 1; j < list.size(); j++) {
GameObject go1 = list.get(i);
GameObject go2 = list.get(j);
boolean playerPlatformCollision = go1.getType()
.equalsIgnoreCase("player") && go2.getType().equalsIgnoreCase("platform");
if (playerPlatformCollision) {
Rectangle playerRect = go1.getRect();
Rectangle platformRect = go2.getRect();
if (playerRect.overlaps(platformRect)) {
float platformRectX, platformRectY, platformRectWidth, platformRectHeight;
platformRectX = go2.getRect().getX(); // x position of the platform
platformRectY = go2.getRect().getY(); // y position of the platform
platformRectWidth = go2.getRect().getWidth(); // width of platform
platformRectHeight = go2.getRect().getHeight(); // height of platform
Rectangle caseA = new Rectangle(platformRectX,
platformRectY, platformRectX + 1,
platformRectHeight);
Rectangle caseB = new Rectangle(platformRectX + 1,
(platformRectY + platformRectHeight) - 1,
platformRectWidth - 1, platformRectHeight);
Rectangle caseC = new Rectangle(platformRectX + 1,
platformRectY, platformRectWidth, 1);
if (playerRect.overlaps(caseA)) {
go1.setxSpeed(0);
} else if (playerRect.overlaps(caseB)) {
go1.setySpeed(0);
} else if (playerRect.overlaps(caseC)) {
go1.setySpeed(-3f);
}
}
}
}
}
}
Please let me know if you are not clear with any parts of the code.
I can't be sure that this is the issue, but it seems that this problem is not addressed in your code, and I have had similar problems myself when ignoring this. When your player collides with the platform, it means that its rectangle is already intersecting the platform, by anywhere between 1 and how fast you are going number of pixels. Just adjusting the x and y speed is not enough. You must also remove the player rectangle from the platform, or else the player will get stuck. This can be done by using a loop and checking if your player is still colliding. if so, move 1 pixel over in the direction you came from, until no longer colliding.

Java 2D gravity?

I am making a 2D Java game and i'm trying to figure out how to add basic "gravity"
my current code is this:
public void checkCollision() {
Rectangle player_rectangle = new Rectangle(player.getX(),player.getY(),32,32);
for(Wall wall : walls) {
Rectangle wall_rectangle = new Rectangle(wall.getX(), wall.getY(), 32,32);
if(player_rectangle.intersects(wall_rectangle)) {
player.yspeed = 0;
} else {
player.yspeed = 1;
}
}
For some reason my code just goes straight through the walls even if it is touching it. I want it to hit the wall if one is present beneath it and if there isnt then keep falling.
you're iterating over all your walls. If the wall intersected is not the last wall in the list, subsequent walls may reset your speed to 1. Break your loop when you detect intersection. Specifically:
if(player_rectangle.intersects(wall_rectangle)) {
player.yspeed = 0;
break;

Maze Navigation in Player Stage with Roomba

Here is my code:
/*
Scott Landau
Robot Lab Assignment 1
*/
// Standard Java Libs
import java.io.*;
// Player/Stage Libs
import javaclient2.*;
import javaclient2.structures.*;
import javaclient2.structures.sonar.*;
// Begin
public class SpinningRobot
{
public static Position2DInterface pos = null;
public static LaserInterface laser = null;
public static void main(String[] args)
{
PlayerClient robot = new PlayerClient("localhost", 6665);
laser = robot.requestInterfaceLaser(0, PlayerConstants.PLAYER_OPEN_MODE);
pos = robot.requestInterfacePosition2D(0,PlayerConstants.PLAYER_OPEN_MODE);
robot.runThreaded (-1, -1);
pos.setSpeed(0.5f, -0.25f);
// end pos
float x, y;
x = 46.0f;
y = -46.0f;
boolean done = false;
while( !done ){
if(laser.isDataReady()) {
float[] laser_data = laser.getData().getRanges();
System.out.println("== IR Sensor ==");
System.out.println("Left Wall Distance: "+laser_data[360]);
System.out.println("Right Wall Distance: " +laser_data[0]);
// if laser doesn't reach left wall, move to detect it
// so we can guide using left wall
if ( laser_data[360] < 0.6f ) {
while ( laser_data[360] < 0.6f ) {
pos.setSpeed(0.5f, -0.5f);
}
} else if ( laser_data[0] < 0.6f ) {
while(laser_data[0<0.6f) { pos.setSpeed(0.5f, 0.5f);
}
}
pos.setSpeed(0.5f, -0.25f);
// end pos?
done = ( (pos.getX() == x) && (pos.getY() == y) );
}
}
}
} // End
I was trying to have the Roomba go continuously at a slight right curve, quickly turning away from each wall it came to close to if it recognized it with it's laser. I can only use laser_data[360] and laser_data[0] for this one robot. I think this would eventually navigate the maze.
However, I am using the Player Stage platform, and Stage freezes when the Roomba comes close to a wall using this code, I have no idea why.
Also, if you can think of a better maze navigation algorithm, please let me know.
Thank you!
It seems like you get stuck against a wall because you are oscillating around distance 0.6.
For instance:
Drive angling toward wall, eventually reaching < 0.6f
Rotate away from wall, stop when > 0.6f. In other words 0.6000001f (for instance)
Resume normal trajectory.
Almost immediately < 0.6f
Goto 2
You will get stuck angling slightly toward and slightly away from the wall.
You need a buffer zone. Once you get within MIN_DIS distance from the wall you need to rotate away until you reach some BUFFER_DIS from the wall where BUFFER_DIS > MIN_DIS by a fair amount.
EDIT:
Looks like you have a few issues. First you are checking if the laser_data is close to a wall, and if it is you are rotating toward the wall. You need to check if it is NOT close to a wall, and rotate toward it.
Second, you are in a very tight while loop, adjusting wheel speeds. This will probably result in bad things. You need to call a trackWall() function when you are too far from the wall, which will poll laser.isDataReady() in a separate loop. Either that, or you need a state-machine in your main polling loop. If not, you are pointlessly adjusting wheel speed with stale laser data.
Third, can you guarantee that the wall will always be within 0.6f? If not, your robot will spin infinitely if it gets to far from the wall.

Categories

Resources