How to handle the collision between two arraylist objects? - java

I have a problem with my code here. I want to make a game with thow ball on each side of screen, on ball being controlled by the user and the other one by the computer. Both ball shoot to each other, and if the bullets intersects one with another, i need to make something happen. I managed to do some thing here, and I have two class, one for the player bullets, and the other one for the enemies bullets, and the bullets are created trough arraylists. All works fin until now, but if I try ti make them collision with each other,it doesnt work at all. I've tried a lot of things but none of it worked, and I would really appreciate if someone could help me.
That is the Player Projectile class:
import java.awt.Rectangle;
public class Projectiles {
private int x, y, speedX;
private boolean visible;
private int width = 10;
private int height = 10;
private Rectangle r;
public Projectiles(){
}
public Projectiles(int startX, int startY) {
x = startX;
y = startY;
speedX = 1;
visible = true;
r = new Rectangle(0, 0, 0, 0);
}
public void update(){
x += speedX;
r.setBounds(x, y, width, height);
if (x > 800){
visible = false;
r = null;
}
if (x < 800){
checkCollision();
}
}
private void checkCollision() {
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeedX() {
return speedX;
}
public boolean isVisible() {
return visible;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
public Rectangle getR() {
return r;
}
public void setR(Rectangle r) {
this.r = r;
}
}
And this one is the Enemy_Projectile class:
import java.awt.Rectangle;
public class Enemy_Projectiles {
private int x, y, speedX;
private boolean visible;
private int width = 30;
private int height = 20;
public static Rectangle r;
Projectiles p1;
public Enemy_Projectiles(int startX, int startY) {
x = startX;
y = startY;
speedX = 1;
visible = true;
r = new Rectangle(0, 0, 0, 0);
}
public void update() {
x -= speedX;
r.setBounds(x, y, width, height);
if (x < 0) {
visible = false;
r = null;
}
if (x > 0){
checkCollision();
}
}
private void checkCollision() {
if(r.intersects(p1.getR())){
visible = false;
System.out.println("Coliziune!!");
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeedX() {
return speedX;
}
public boolean isVisible() {
return visible;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setSpeedX(int speedX) {
this.speedX = speedX;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public void setWidth(int width) {
this.width = width;
}
public void setHeight(int height) {
this.height = height;
}
}

Do not check intersection after the frame has been drawn. Let's say you have a slow computer and your bullets intersect, but they have moved out of intersection in one frame.
You need to apply high school physics/geometry. Calculate where the bullet will be well before you render it. Then, calculate where the ball will be, and construct a line segment for each from where they are now, to where they will be on the next frame. Check if these segments intersect. Then you will have a fool-proof method of checking for intersection.
This method is similar to how physics and intersections between objects are handled inside of a game engine like Unity.

Related

Switching sprites after a set amount of time

so I have an object, and I want to make it so that whenever a projectile collides with that object, it gradually switches its sprites, and finally disappear. How can I do that?
Here are my codes (sprites is a list of sprites that I need to set, and fireballs is a list of fireballs)
Firstly, the chunk of code that I want to fix:
for(int i = 0; i < this.fireballs.size(); i++){
if(this.brickwall.wallExist()){
if((fireballs.get(i).getX() <= this.brickwall.getX()+10 & fireballs.get(i).getX() >= this.brickwall.getX()-10) &&
(fireballs.get(i).getY() <= this.brickwall.getY()+10 & fireballs.get(i).getY() >= this.brickwall.getY()-10)){
fireballs.remove(i);
int counter = 0;
for(PImage p : sprites){
if(counter == 4){
this.brickwall.setSprite(p);
this.brickwall.draw(this);
counter = 0;
}
else{
counter++;
}
}
}
}
}
fireball is an extension of the class projectile:
public abstract class Projectile {
protected int x;
protected int y;
protected PImage sprite;
public Projectile(int x, int y){
this.x = x;
this.y = y;
}
public void draw(PApplet app) {
// The image() method is used to draw PImages onto the screen.
// The first argument is the image, the second and third arguments are coordinates
app.image(this.sprite, this.x, this.y);
}
//set sprite
public void setSprite(PImage sprite) {
this.sprite = sprite;
}
public abstract void Up();
public abstract void Down();
public abstract void Left();
public abstract void Right();
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
}
public class Fireball extends Projectile {
public char dir = 'n';
public Fireball(int x, int y) {
super(x, y);
}
public void Right() {
this.x += 4;
}
public void Left(){
this.x -= 4;
}
public void Up() {
this.y -= 4;
}
public void Down() {
this.y += 4;
}
}
brickwall is an extension to the class wall:
import processing.core.PImage;
import processing.core.PApplet;
public abstract class wall extends PApplet {
protected int x;
protected int y;
protected PImage sprite;
protected int size;
public wall(int x, int y){
this.x = x;
this.y = y;
}
public void setSprite(PImage sprite) {
this.sprite = sprite;
}
public void draw(PApplet app){
app.image(this.sprite, this.x, this.y);
}
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
public void tick(){
}
}
import processing.core.PImage;
public class brickwall extends wall {
public PImage sprite;
public int counter = 0;
protected PImage[] destroyed = new PImage[4];
public brickwall(int x, int y){
super(x, y);
}
public boolean wallExist(){
return true;
}
public void destroy(){
//erase the sprite
this.sprite = null;
}
public void tick(){
if(this.counter < 4){
this.sprite = destroyed[this.counter];
this.counter++;
}
}
}

Java awt Why can I only remove most recent addition to Linked List

I'm creating a space shooter game in Java awt for my college computer science project.
The enemies that I have spawn every 3 seconds via a timer and are added to a LinkedList, and a for loop renders them all.
In the class I have for my player's bullet object, there are if statements to check whether the laser comes into the bounds of an enemy, and if they are all true it removes the enemy from the LinkedList.
However, only the most recent addition to the LinkedList is being removed; the bullet passes through the others and nothing happens. This is my first time making a game, and the first time I've ever used a LinkedList, so excuse any misunderstandings.
The controller class controls the enemies, the Laser class is the bullet and the Enemy class is the Enemy object. There's also a player, Main and GUI class.
import java.awt.*;
import java.util.LinkedList;
import java.util.Timer;
import java.util.TimerTask;
public class Controller
{
private LinkedList<Enemy> e = new LinkedList<Enemy>();
Enemy tempEnemy, tempEnemy2
;
Main main;
int refreshSpawn = 3000; //move timer refresh rate
int xpos;
int width;
int ypos;
int height;
Timer spawnTimer = new Timer();
public Controller(Main main)
{
this.main = main;
spawn();
}
public void spawn()
{
spawnTimer.schedule(new TimerTask()
{
public void run() //run method and timer
{
addEnemy(new Enemy(main, (int)(Math.random()*4+2)));
}
}, 0, refreshSpawn);
}
public void render(Graphics g)
{
for(int i = 0; i < e.size(); i++)
{
tempEnemy = e.get(i);
xpos = tempEnemy.getX();
width = tempEnemy.getXsize();
ypos = tempEnemy.getY();
height = tempEnemy.getYsize();
tempEnemy.render(g);
}
}
public void update()
{
for(int i = 0; i < e.size(); i++)
{
tempEnemy2 = e.get(i);
tempEnemy2.move();
}
}
public void addEnemy(Enemy enemy)
{
e.add(enemy);
System.out.println(e.size());
//spawn();
}
public void removeEnemy()
{
e.remove(tempEnemy);
}
public int getX()
{
return xpos;
}
public int getY()
{
return ypos;
}
public int getXsize()
{
return width;
}
public int getYsize()
{
return height;
}
public Enemy getEnemy()
{
return tempEnemy;
}
}
import java.awt.*;
public class Enemy
{
Image ship; //image of enemy ship
int x, y; //ship position
int speed;
public Enemy(Main main, int speed) //constructing enemy
{
this.speed = speed;
ship = main.getImage(main.getDocumentBase(), "enemyShip"+(int)(Math.random()*6+1)+".png"); //picture for enemy ship
x = (int)(Math.random()*900+1); //enemy has a starting position at a random x point
y = -100; //start ship slightly off screen so it doesn't suddenly appear
}
public void move()
{
y += speed;
if(y > 600)
{
y = -100;
x = (int)(Math.random()*900);
}
}
public void render(Graphics g)
{
g.drawImage(ship, x, y, null);
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public int getXsize()
{
return ship.getWidth(null);
}
public int getYsize()
{
return ship.getHeight(null);
}
}
import java.awt.*;
public class Laser
{
Image img; //image of laser
int laserSpeed = 10; //speed of laser
int x, y; //position of laser
int xSize, ySize; //size of laser
Controller cont;
GUI gui;
public Laser(Image img, int x, int y, Controller cont, GUI gui) //constructing laser
{
this.cont = cont;
this.img = img; //setting laser image
this.gui = gui;
xSize = x; //size of laser
ySize = y; //size of laser
}
public void shoot(int x, int y, int shipSize)
{
this.x = x + (shipSize/2) - (xSize/2);
this.y = y;
}
public void move()
{
y -= laserSpeed;
if(x <= cont.getX() + cont.getXsize() && x + xSize >= cont.getX() - cont.getXsize())
{
if(y <= cont.getY() + cont.getYsize() && y > 0)
{
remove();
cont.removeEnemy();
gui.scoreUp(5);
}
}
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public int getXSize()
{
return xSize;
}
public int getYSize()
{
return ySize;
}
public Image getImage()
{
return img;
}
public void remove()
{
y = -ySize;
x = -100;
}
}
From what I can tell, tempEnemy is assigned to the last element in the LinkedList by the render method. This means that when you call removeEnemy it is removing the last rendered object (likely the last object you added).
What you should be doing is telling the Controller which Enemy it should be using, it has absolutely no idea what your intentions are when you call it...

How come the collision detection only works sometimes?

I am creating an android app and I am creating a game and the droid has to be able to bounce off the walls and the edge of the screen. Here is my update method in my MainGamePanel.java file where I call the collision detection.
It works when it just has to bounce off the edge of the screen. However when I try to get it bounce off the wall objects it sometimes works. When it doesn't, it goes through the wall sometimes, although this only happens when it moves up and down. It also sometimes gets stuck in the wall. How would I modify the collision detection so I won't have these issues. Any help would be much appreciated.
public void update()
{
// check collision with right wall if heading right
if (droid.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
&& droid.getX() + droid.getBitmap().getWidth() / 2 >= getWidth()) {
droid.getSpeed().toggleXDirection();
}
// check collision with left wall if heading left
else if (droid.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
&& droid.getX() - droid.getBitmap().getWidth() / 2 <= 0) {
droid.getSpeed().toggleXDirection();
droid.getSpeed().setYv(0);
}
// check collision with bottom wall if heading down
else if (droid.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
&& droid.getY() + droid.getBitmap().getHeight() / 2 >= getHeight()) {
droid.getSpeed().toggleYDirection();
droid.getSpeed().setXv(0);
}
// check collision with top wall if heading up
else if (droid.getSpeed().getyDirection() == Speed.DIRECTION_UP
&& droid.getY() - droid.getBitmap().getHeight() / 2 <= 0) {
droid.getSpeed().toggleYDirection();
droid.getSpeed().setXv(0);
}
for (int i = 0 ; i < listOfWs.length ; i++)
{
if (droid.getX() +(droid.getBitmap().getWidth()/2)+1 > listOfWs [i].giveLeft ()
&& droid.getX()-(droid.getBitmap().getWidth()/2)-1 < listOfWs [i].giveRight ()
&& droid.getY()+(droid.getBitmap().getHeight()/2)+1 > listOfWs [i].giveTop ()
&& droid.getY()-(droid.getBitmap().getHeight()/2)-1 < listOfWs [i].giveBottom () )
{
if(droid.getSpeed().getYv()==0){
droid.getSpeed().toggleXDirection();//Takes the speed and multiplies it by -1 so it changes direction
}
else{
droid.getSpeed().toggleYDirection();
}
}
}
// Update the lone droid
droid.update();
}
Here is my droid.java file that I used.
public class Droid {
private Bitmap bitmap; // the actual bitmap
private int x; // the X coordinate
private int y; // the Y coordinate
public Speed speed;
public Droid(Bitmap bitmap, int x, int y) {
this.bitmap = bitmap;
this.x = x;
this.y = y;
speed= new Speed();
}
public Bitmap getBitmap() {
return bitmap;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void draw(Canvas canvas) {
canvas.drawBitmap(bitmap, x - (bitmap.getWidth() /2), y - (bitmap.getHeight() / 2), null);
}
public void update() {
x += (int)(speed.getXv() * speed.getxDirection());
y += (int)(speed.getYv() * speed.getyDirection());
}
public Speed getSpeed(){
return speed;
}
}
This is the speed.java file.
public class Speed {
public static final int DIRECTION_RIGHT = 4;
public static final int DIRECTION_LEFT = -4;
public static final int DIRECTION_UP = -4;
public static final int DIRECTION_DOWN = 4;
private float xv = 1; // velocity value on the X axis
private float yv = 1; // velocity value on the Y axis
private int xDirection = DIRECTION_RIGHT;
private int yDirection = DIRECTION_DOWN;
public Speed() {
this.xv = 1;
this.yv = 1;
}
public Speed(float xv, float yv) {
this.xv = xv;
this.yv = yv;
}
public float getXv() {
return xv;
}
public void setXv(float xv) {
this.xv = xv;
}
public float getYv() {
return yv;
}
public void setYv(float yv) {
this.yv = yv;
}
public int getxDirection() {
return xDirection;
}
public void setxDirection(int xDirection) {
this.xDirection = xDirection;
}
public void setRight() {
xDirection = DIRECTION_RIGHT;
}
public void setLeft() {
xDirection = DIRECTION_LEFT;
}
public void setUp() {
yDirection = DIRECTION_UP;
}
public void setDown() {
yDirection = DIRECTION_DOWN;
}
public int getyDirection() {
return yDirection;
}
public void setyDirection(int yDirection) {
this.yDirection = yDirection;
}
// changes the direction on the X axis
public void toggleXDirection() {
xDirection = xDirection * -1;
}
// changes the direction on the Y axis
public void toggleYDirection() {
yDirection = yDirection * -1;
}
}
in the update method, in for circulation, it seems you make your logical operation there, would you make it more specific?

Java swing, need to draw rectangles using the mouse without losing previous rectangles with overlap

in this class that i have extending JLabel I need to be able to use the mouse to left click, then drag down and/or right to create a rectangle and be able to repeat that process to draw multiple rectangles without losing any of the previous ones and drawing boxes for overlap as well as being able to find the rectangle made by the union of all rectangles like this
my current code was adapted as much as i could from the java demo on Performing Custom Painting the program seems to be behaving in odd ways because of how the repaint method is used to update the JLabel but i have no idea how to fix it
JLabel class
import javax.swing.*;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class JLabelx extends JLabel {
private int squareX = 0;
private int squareY = 0;
private int squareW = 0;
private int squareH = 0;
public JLabelx() {
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
squareX = e.getX();
squareY = e.getY();
//set coordinates of next rectangle
}
});
addMouseMotionListener(new MouseAdapter() {
public void mouseDragged(MouseEvent e) {
newDraw(e.getX(),e.getY());
//find length and width of next rectangle
}
});
}
protected void newDraw(int x, int y) {
int OFFSET = 1;
if ((squareX!=x) || (squareY!=y)) {
// repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
squareW=x-squareX;
squareH=y-squareY;
repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
}
}
protected void paintComponent(Graphics g) {
super.paintComponents(g);
g.setColor(Color.GREEN);
g.fillRect(squareX,squareY,squareW,squareH);
g.setColor(Color.BLACK);
g.drawRect(squareX,squareY,squareW,squareH);
}
}
I have also been given a Rectangle class that looks similar to java.awt.Rectangle which has methods that find the rectangles made by overlaps and the rectangles made by the union of all rectangles, but I don't know how to create rectangle objects with mouse movements and then paint them in this JLabel
public class Rectangle {
private int x,y,width,height;
public Rectangle(int x,int y,int width,int height)
{
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
public Rectangle(Rectangle a)
{
this.x = a.x;
this.y = a.y;
this.width = a.width;
this.height = a.height;
}
public String toString()
{
return "Start: ("+x+","+y+"), Width: "+width+", Height: "+height+"\n";
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public int getWidth()
{
return width;
}
public int getHeight()
{
return height;
}
public void setX(int x)
{
this.x = x;
}
public void setY(int y)
{
this.y = y;
}
public void setWidth(int width)
{
this.width = width;
}
public void setHeight(int height)
{
this.height = height;
}
public int area()
{
return width*height;
}
public boolean overlaps(Rectangle a)
{
if ((x>a.x+a.width) || (a.x>x+width) || (y>a.y+a.height) || (a.y>y+height))
{
return false;
}
return true;
}
public Rectangle intersect(Rectangle a)
{
if (!overlaps(a))
return null;
int left,right,top,bottom;
if (x<a.x)
left = a.x;
else
left = x;
if (y<a.y)
bottom = a.y;
else
bottom = y;
if ((x+width)<(a.x+a.width))
right = x+width;
else
right = a.x+a.width;
if ((y+height)<(a.y+a.height))
top = y+height;
else
top = a.y+a.height;
return new Rectangle(left,bottom,right-left,top-bottom);
}
public Rectangle union(Rectangle a)
{
int left,right,top,bottom;
if (x<a.x)
left = x;
else
left = a.x;
if (y<a.y)
bottom = y;
else
bottom = a.y;
if ((x+width)<(a.x+a.width))
right = a.x+a.width;
else
right = x+width;
if ((y+height)<(a.y+a.height))
top = a.y+a.height;
else
top = y+height;
return new Rectangle(left,bottom,right-left,top-bottom);
}
}
Not sure why you are extending a JLabel to do custom painting. The tutorial showed you how to use a JPanel.
For the two common ways to do incremental paint, check out Custom Painting Approaches:
Use a List to keep track of the Rectangles (this is probably what you want since you want to be able to test for intersections.
Use a BufferedImage.

Tic Tac Toe game in Java using MouseAdapter

I have a CLickableBox class that creates boxes for me and now I need to make it so that when clicked, either an X or an O will be displayed in place. Here is the ClickableBox class.
import java.awt.event.MouseAdapter;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.Container;
public class ClickableBox extends MouseAdapter {
private int x, y, width, height;
private Color borderColor, backColor, oldColor;
private boolean drawBorder, clicked;
private Container parent;
public ClickableBox(int x, int y, int width, int height, Color borderColor,
Color backColor, boolean drawBorder, Container parent) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.borderColor = borderColor;
this.backColor = backColor;
this.drawBorder = drawBorder;
this.parent = parent;
}
public void draw(Graphics g) {
oldColor = g.getColor();
g.setColor(backColor);
g.fillRect(x, y, width, height);
if(drawBorder) {
g.setColor(borderColor);
g.drawRect(x, y, width, height);
}
g.setColor(oldColor);
}
public void mouseReleased(MouseEvent e) {
if(x < e.getX() && e.getX() < x + width &&
y < e.getY() && e.getY() < y + height) {
clicked = true;
parent.repaint();
}
}
public boolean isClicked() {
return clicked;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public Color getBorderColor() {
return borderColor;
}
public void setBorderColor(Color borderColor) {
this.borderColor = borderColor;
}
public Color getBackColor() {
return backColor;
}
public void setBackColor(Color backColor) {
this.backColor = backColor;
}
public Color getOldColor() {
return oldColor;
}
public void setOldColor(Color oldColor) {
this.oldColor = oldColor;
}
public boolean isDrawBorder() {
return drawBorder;
}
public void setDrawBorder(boolean drawBorder) {
this.drawBorder = drawBorder;
}
public void setClicked(boolean clicked) {
this.clicked = clicked;
}
}
The TicTacToeBox class should extend ClickableBox, so that each box will be a listener. It needs to be designed so that each Box object will take care of itself- it knows if it's been clicked or not, and if so, whether it's going to be showing an x or an o.
The TicTacToeBox class is what I am having trouble with. This is what I will need for my game board. Any suggestions on how to implement this, simply? Below is my TicTacToeBox so far (not much):
Some direction and/or assistance would be greatly appreciated! Thanks.
import java.awt.Color;
import java.awt.Container;
public class TicTacToeBox extends ClickableBox {
public TicTacToeBox(int x, int y, int width, int height, Color borderColor,
Color backColor, boolean drawBorder, boolean mask, Container parent)
{
super(x, y, width, height, borderColor, backColor, drawBorder, parent);
}
}
Perhaps you need to override mouseReleased() - something like this:
public void mouseReleased(MouseEvent e) {
if ( this.value == NONE ) {
if ( currentTurn == Turn.X ) {
this.value = X;
}
else {
this.value = O;
}
}
super.mouseReleased();
}
With some global currentTurn variable to keep track of whose turn it is, and a value field to represent what the current value of this box is. You'd also probably want to override draw() to make it render the "X" or "O"...

Categories

Resources