Reputation: 449
I have made a very simple 2D Java game class made up of the general 2D game methods such as render and update, I have set up all my if statements so that the player moves around the map with the keyboard arrow input. I am now trying to set up what I have read is a collision detection, I know the basics of what I need to do because I did a lot of reading before I actually came here to ask the question, from what I have read it goes something like this:
Make 2 rectangles
Rectangle rectOne = new Rectangle(playerX, playerY, 40, 40);
//keep in mind that the variables playerX and playerY are already made previously
Rectangle rectTwo = new Rectangle(50, 50, 100,100);
Then under my update method I would say:
if(rectOne.intersects(rectTwo)){//change the player direction so that he
can go no further}
I just do not understand what would go inside my if statement, I need something that stops my player from going any further if the intersection occurs but how can I write this because the player can move in 4 different directions (UP, DOWN, LEFT, RIGHT). It would be much simpler if it was just 1 dimensional because I could just change the direction to the opposite of what it was but its two dimensions so it is a bit confusing.
Additional information:
The view my game is played at is similar to the following: http://www.2dplay.com/awesome-tanks/awesome-tanks-play.htm
EDIT 3:
package javagame;
import java.awt.Rectangle;
IMPORTS ARE HERE
public class Play extends BasicGameState{
Animation bucky, movingUp, movingDown, movingLeft, movingRight;
Image worldMap;
boolean quit = false;//gives user to quit the game
int[] duration = {200, 200};//how long frame stays up for
int buckyPositionX = 0;
int buckyPositionY = 0;
int x = buckyPositionX + 320;//keeps user in the middle of the screem
int y = buckyPositionY + 160;//the numbers are half of the screen size
Rectangle rectOne = new Rectangle(x, y,90,90);
Rectangle rectTwo = new Rectangle(500 + buckyPositionX, 330 + buckyPositionY, 210, 150);
private int xSpeed, ySpeed;///////////////////////////CODE FOR COLLISION
public Play(int state){
}
public void init(GameContainer gc, StateBasedGame sbg) throws SlickException{
worldMap = new Image("res/world.png");
Image[] walkUp = {new Image("res/b.png"), new Image("res/b.png")}; //these are the images to be used in the "walkUp" animation
Image[] walkDown = {new Image("res/f.png"), new Image("res/f.png")};
Image[] walkLeft = {new Image("res/l.png"), new Image("res/l.png")};
Image[] walkRight = {new Image("res/r.png"), new Image("res/r.png")};
movingUp = new Animation(walkUp, duration, false);
movingDown = new Animation(walkDown, duration, false);
movingLeft = new Animation(walkLeft, duration, false);
movingRight = new Animation(walkRight, duration, false);
bucky = movingDown;//facing screen initially on startup
}
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws SlickException{
worldMap.draw(buckyPositionX, buckyPositionY);//position 0,0
bucky.draw(x, y);//makes him appear at center of map
g.fillRect(x, y,90,90);
g.fillRect(500 + buckyPositionX, 330 + buckyPositionY, 210, 150);
if(quit==true){
g.drawString("Resume(R)", 250, 100);
g.drawString("Main(M)", 250, 150);
g.drawString("Quit Game(Q)", 250, 200);
if(quit==false){
g.clear();//wipe off everything from screen
}
}
}
public void setSpeedWithDirection(int speed, int direction)////////////CODE FOR COLLISION
{
xSpeed = (int) (Math.cos(direction) * speed);//////////////////////////CODE FOR COLLISION
ySpeed = (int) (Math.sin(direction) * speed);//////////////////////////CODE FOR COLLISION
}
public void update(GameContainer gc, StateBasedGame sbg, int delta)throws SlickException{
Input input = gc.getInput();
x += xSpeed;//////////////////////////////////////////CODE FOR COLLISION
y += ySpeed;//////////////////////////////////////////CODE FOR COLLISION
if(rectOne.intersects(rectTwo))///////////////////////CODE FOR COLLISION
{
xSpeed = 0;////////////////////////////CODE FOR COLLISION
ySpeed = 0;////////////////////////////CODE FOR COLLISION
}
//up
if(input.isKeyDown(Input.KEY_UP)){
bucky = movingUp;//changes the image to his back
buckyPositionY += 2;;//increase the Y coordinates of bucky (move him up)
if(buckyPositionY>162){//if I reach the top
buckyPositionY -= 2;//stops any further movement in that direction
}
}
//down
if(input.isKeyDown(Input.KEY_DOWN)){
bucky = movingDown;
buckyPositionY -= 2;
if(buckyPositionY<-550){
buckyPositionY += 2;//basically change the direction if + make -
}}
//left
if(input.isKeyDown(Input.KEY_LEFT)){
bucky = movingLeft;
buckyPositionX += 2;
if(buckyPositionX>324){
buckyPositionX -= 2;//delta * .1f
}}
//right
if(input.isKeyDown(Input.KEY_RIGHT)){
bucky = movingRight;
buckyPositionX -= 2;
if(buckyPositionX<-776){
buckyPositionX += 2;
}}
//escape
if(input.isKeyDown(Input.KEY_ESCAPE)){
quit=true;
}
//when the menu is up
if(quit==true){//is the menu on the screen
if(input.isKeyDown(Input.KEY_R)){
quit = false;//resumes the game, makes menu dissapear
}
if(input.isKeyDown(Input.KEY_M)){
sbg.enterState(0);//takes you to the main menu
}
if(input.isKeyDown(Input.KEY_Q)){
System.exit(0);//quits the game
}
}
}
public int getID(){
return 1;
}
}
Upvotes: 2
Views: 5307
Reputation: 14313
As a prerequisite, your player class (or one of its superclasses) should have a few fields describing their speed (a pair of fields for x-speed and y-speed works very well, although you'll need trig to set the player in a given direction). Here is an example of a simple player class with x- and y-speed fields:
public class Player
{
//coordinates of the player
private int x, y;
//horizontal and vertical components of the player's speed.
private int xSpeed, ySpeed;
//call a method similar to this one every time your player updates its position
public void updatePosition()
{
x += xSpeed;
y += ySpeed;
}
//Converts a speed and a direction (much easier to deal with)
//to an x speed and a y speed (much easier for actually moving)
//and sets the player's motion
public void setSpeedWithDirection(int speed, float direction)
{
xSpeed = Math.cos(direction) * speed;
ySpeed = Math.sin(direction) * speed;
}
}
In order for this to actually reflect your player's speed, add the x-speed to the player's x-coordinate every and add the y-speed to the player's y-coordinate every time the player updates. Now, there are a lot of things that could happen when the collision occurs. The simplest one is to stop the player by setting its x-speed and y-speed to zero. However, this can look glitchy as the player will stop moving regardless of what direction they are going in. A slightly better approach is to analyze the shape of the intersection (assuming you're using java.awt.Rectangle
you can use the intersection()
method, pretty much all Rectangle classes have something similar) and determine whether the x-speed, y-speed, or both should be set to zero. For instance, if the intersection is wider than it is tall (larger in the x-axis than the y-axis), you should probably set the y-speed to zero but but the x-speed unaffected. If you want the player to turn around (180 degrees), simply flip the sign of x-speed and y-speed. If you want the player to "bounce" instead of stop, analyze the intersection just as in the previous case but reverse the speed rather than set it to zero. Here are a few code examples (probably won't work exactly as written because I don't know how your classes are set up):
//simple stop
if(rectOne.intersects(rectTwo))
{
player.xSpeed = 0;
player.ySpeed = 0;
}
//variable-axis stop
if(rectOne.intersects(rectTwo))
{
//depending on Rectangle implementation may need to use other method
Rectangle overlap = rectOne.intersection(rectTwo);
if (overlap.height >= overlap.width)
{
player.xSpeed = 0;
}
if (overlap.width >= overlap.height)
{
player.ySpeed = 0;
}
}
//simple turn-around (about face)
if(rectOne.intersects(rectTwo))
{
player.xSpeed *= -1;
player.ySpeed *= -1;
}
//bounce (variable-axis turn around)
if(rectOne.intersects(rectTwo))
{
Rectangle overlap = rectOne.intersection(rectTwo);
if (overlap.height >= overlap.width)
{
player.xSpeed *= -1;
}
if (overlap.width >= overlap.height)
{
player.ySpeed *= -1;
}
}
Note that regardless of what you choose to do collisions tend to be very difficult to get working smoothly. I would consider all of these options good starting points that could always be built upon. I hope this helps.
Upvotes: 4
Reputation: 5087
I suggest creating an enum Way
.You should know the Way
he is going now, Then just change the Way
to the opposite Way
,or you can lock the current Way
and choose a random Way
to go.
Upvotes: 0