Hi guys so i have this game made where the user avoids aliens coming from the right side of the screen and then they go past the left side. I need the aliens to reappear from the right side once they leave the left side of the screen. How can i go about doing this?
Here is my existing code:
EDIT:
Added alien class underneath main class
PImage background;
int x=0; //global variable background location
Alien alien1;
Alien alien2;
Alien alien3;
Defender user1;
void setup(){
size(800,400);
background = loadImage("spaceBackground.jpg");
background.resize(width,height);
alien1 = new Alien(800,100,5);
alien2 = new Alien(800,200,5);
alien3 = new Alien(800,300,5);
user1 = new Defender(10,height/2);
}
void draw ()
{
drawBackground();
alien1.move();
alien1.render();
alien2.move();
alien2.render();
alien3.move();
alien3.render();
user1.render();
}
void drawBackground()
{
image(background, x, 0); //draw background twice adjacent
image(background, x+background.width, 0);
x -=4;
if(x == -background.width)
x=0; //wrap background
}
void keyPressed()
{
if(key == CODED) {
if (keyCode == UP) {
user1.y = user1.y - 5;
}
else if (keyCode == DOWN)
{
user1.y = user1.y + 5;
}
}
}
final color Alien1 = color(0,255,0);
final color Alien2 = color(50,100,0);
class Alien
{
int x,y;
int speedX, speedY;
Alien(int x, int y, int speedX)
{
this.x = x;
this.y = y;
this.speedX = speedX;
}
void move()
{
x=x-speedX;
float stepY = random(-5,5);
y = y + (int)stepY;
}
//draw an alien
void render()
{
fill(Alien1);
ellipse(x,y,30,30);
fill(Alien2);
ellipse(x,y,50,15);
}
}
If you upload your Alien class then we can give clearer directions but the idea is that your should add the following logic in your move() method.
void move()
{
x=x-speedX;
float stepY = random(-5,5);
y = y + (int)stepY;
if(this.x < 0) {
this.x = 800; // or width, startingPosition, ...
}
}
Edit: Alien class was added so adapted my solution to the code.
Related
Is it possible to add collision effects to an image in Java, drawn using the drawImage() method ? If so, how could I do it?
Example:
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
public class Racquet {
private static final int Y = 330;
private static final int WIDTH = 60;
private static final int HEIGHT = 10;
int x = 0;
int xa = 0;
private Game game;
public Racquet(Game game) {
this.game = game;
}
public void move() {
if (x + xa > 0 && x + xa < game.getWidth() - WIDTH)
x = x + xa;
}
public void paint(Graphics2D g) {
g.fillRect(x, Y, WIDTH, HEIGHT);
}
public void keyReleased(KeyEvent e) {
xa = 0;
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = -1;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = 1;
}
public Rectangle getBounds() {
return new Rectangle(x, Y, WIDTH, HEIGHT);
}
public int getTopY() {
return Y;
}
}
Ball class:
import java.awt.Graphics2D;
import java.awt.Rectangle;
public class Ball {
private static final int DIAMETER = 30;
int x = 0;
int y = 0;
int xa = 1;
int ya = 1;
private Game game;
public Ball(Game game) {
this.game= game;
}
void move() {
if (x + xa < 0)
xa = 1;
if (x + xa > game.getWidth() - DIAMETER)
xa = -1;
if (y + ya < 0)
ya = 1;
if (y + ya > game.getHeight() - DIAMETER)
game.gameOver();
if (collision()){
ya = -1;
y = game.racquet.getTopY() - DIAMETER;
}
x = x + xa;
y = y + ya;
}
private boolean collision() {
return game.racquet.getBounds().intersects(getBounds());
}
public void paint(Graphics2D g) {
g.fillOval(x, y, DIAMETER, DIAMETER);
}
public Rectangle getBounds() {
return new Rectangle(x, y, DIAMETER, DIAMETER);
}
}
The above code detects the collision between the racquet and the ball, now, if my racquet/racket was an image, How wuold I be able to detect the collision of it with the ball? Also, are there easier ways for collision detection?(just asking)
class MyImage extends BufferedImage {
int x, y, xa, ya;
public Rectangle getBounds() {
return new Rectangle(x, y, getWidth(), getHeight());
}
// all other methods in raquet remain the same except you remove paint()
private Game game;
public MyImage(Game game) {
this.game = game;
}
public void move() {
if (x + xa > 0 && x + xa < game.getWidth() - WIDTH)
x = x + xa;
}
public void keyReleased(KeyEvent e) {
xa = 0;
}
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = -1;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = 1;
}
public int getY() {
return y;
}
}
To start an image you read it like this
MyImage myImage=null;
try {
myImage=ImageIO.read(new File(...));
}
catch (Exception ex) { ex.printStackTrace(); }
How wuold I be able to detect the collision of it with the ball?
I see that you already have a getBounds() methods which returns a Rectangle object. You can use this to check for collision.
You can do it like:
if(racquet.getBounds().intersects(ball.getBounds()))
//collision happens
If the ball must be within the racquet, then:
if(racquet.getBounds().contains(ball.getBounds()))
//collision happens
However, if the height of your racquet object includes then length of the racquet handle, you may implement a getHitBox() method for the racquet something like this:
public Rectangle getHitBox(){
return new Rectangle(x, Y, WIDTH, HEIGHT-handleHeight);
}
Is it possible to add collision effects to an image in Java, drawn using the drawImage() method ? If so, how could I do it?
Not sure how your drawImage() was implemented, so I can't comment on that. However, it is definitely possible to add some "collision effects" with custom painting. Whenever a collision is detected, play the animation at specific location (which will be the location where collision occurs).
You may construct a method like:
playAnimation(int locX, int locY, Animation anima, int duration)
In this case Animation class can just play the sprites from a sprite sheet.
Also, are there easier ways for collision detection?(just asking)
You will probably only have 1 ball and at most 4 racquets in your game. In this case, you only need to check whether the ball hits any of the racquets:
for(int x=0; x<allRacquets.size(); x++)
if(allRacquets.get(x).collidesWith(ball))
collidedRacquet = allRacquets.get(x);
CollidesWith() method can be implemented from the collision detection approach mentioned above:
//implement within Racquet class
public boolean collidesWith(Ball ball){
return (this.getBounds().intersects(ball.getBounds()));
}
I need to create a JPanel, where upon a mouse click a new Sprite must appear in a new thread. This is what I have:
public class BouncingSprites {
private JFrame frame;
private SpritePanel panel = new SpritePanel();
private Sprite ball;
public BouncingSprites() {
frame = new JFrame("Bouncing Sprite");
frame.setSize(400, 400);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(panel);
frame.setVisible(true);
}
public void start(){
panel.animate(); // never returns due to infinite loop in animate method
}
public static void main(String[] args) {
new BouncingSprites().start();
}
}
Class SpritePanel:
public class SpritePanel extends JPanel
{
Sprite sprite;
public SpritePanel()
{
addMouseListener(new Mouse());
}
//method for creating a new ball
private void newSprite (MouseEvent event)
{
sprite = new Sprite(this);
}
public void animate()
{
}
private class Mouse extends MouseAdapter
{
#Override
public void mousePressed( final MouseEvent event )
{
newSprite(event);
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
if (sprite != null)
{
sprite.draw(g);
}
}
}
Class Sprite :
public class Sprite implements Runnable
{
public final static Random random = new Random();
final static int SIZE = 10;
final static int MAX_SPEED = 5;
SpritePanel panel;
private int x;
private int y;
private int dx;
private int dy;
private Color color = Color.BLUE;
private Thread animation;
public Sprite (SpritePanel panel)
{
this.panel = panel;
x = random.nextInt(panel.getWidth());
y = random.nextInt(panel.getHeight());
dx = random.nextInt(2*MAX_SPEED) - MAX_SPEED;
dy = random.nextInt(2*MAX_SPEED) - MAX_SPEED;
animation = new Thread(this);
animation.start();
}
public void draw(Graphics g)
{
g.setColor(color);
g.fillOval(x, y, SIZE, SIZE);
}
public void move()
{
// check for bounce and make the ball bounce if necessary
//
if (x < 0 && dx < 0){
//bounce off the left wall
x = 0;
dx = -dx;
}
if (y < 0 && dy < 0){
//bounce off the top wall
y = 0;
dy = -dy;
}
if (x > panel.getWidth() - SIZE && dx > 0){
//bounce off the right wall
x = panel.getWidth() - SIZE;
dx = - dx;
}
if (y > panel.getHeight() - SIZE && dy > 0){
//bounce off the bottom wall
y = panel.getHeight() - SIZE;
dy = -dy;
}
//make the ball move
x += dx;
y += dy;
}
#Override
public void run()
{
while (Thread.currentThread() == animation)
{
move();
panel.repaint();
try
{
Thread.sleep(40);
}
catch ( InterruptedException exception )
{
exception.printStackTrace();
}
}
}
}
This code creates a new moving sprite. However, the previous sprite gets removed from the panel. What I need to do is to add a new sprite with a mouse click, so that the previous sprite is not removed. If I click three times, three sprites should be painted.
How do I change my code to implement that?
Many thanks!
You could replace Sprite sprite; in the SpritePanel class with List<Sprite> sprites = new ArrayList<>();. Then, when you make a new Sprite, add it to the list. Then in your paintComponent method, you could iterate through the list, drawing all of the sprites.
I am working on a breakout game. i have almost everything done except for the collision for the bricks. so far, when the ball hits the brick the brick bounces back but the brick does not disappear. If someone could help me that would be great.
Main class:
public class Breakout extends Applet implements Runnable{
Thread thread = new Thread(this);
boolean running = true;
Brick2 b;
Paddle p;
Ball ba;
Image dbImage;
Graphics dbg;
public void init(){
setSize(800,600);
b = new Brick2();
p = new Paddle(this);
ba = new Ball(this);
}
public void start(){
thread.start();
}
public void destroy(){
running = false;
}
public void stop(){
running = false;
}
public void run(){
while(running){
b.update(ba);
p.update(this);
ba.update(this,p);
repaint();
try{
thread.sleep(20);
}
catch (InterruptedException e){
System.out.println("AN ERROR HAS OCCURED");
}
}
}
public void update(Graphics g){
dbImage = createImage(getWidth(),getHeight());
dbg = dbImage.getGraphics();
paint(dbg);
g.drawImage(dbImage,0,0,this);
}
public void paint(Graphics g){
g.fillRect(0,0,800,600);
b.paint(g);
p.paint(g,this);
ba.paint(g,this);
}
}
Brick Class:
public class Brick2{
private int x;
private int y;
public Brick2(){
}
public void update(Ball ba){
collision(ba);
}
public void collision(Ball ba){
int bX = ba.getX();
int bY = ba.getY();
int bHeight = ba.getImageHeight();
int bWidth = ba.getImageWidth();
for(int x=0; x <= 800; x+=55){
for (int y=0; y<= 100; y+=25){
if (bX-bWidth<=x && bX+bWidth>=x && bY-bHeight<=y && bY+bHeight>=y){
ba.setXVel(6);
}
}
}
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void paint(Graphics g){
for(int x=0; x <= 800; x+=55){
for (int y=0; y<= 100; y+=25){
g.setColor(Color.RED);
g.fillRect(x,y,50,20);
}
}
}
}
Ball Class:
public class Ball {
private int x=355 ;
private int y=200;
private int speed = 6;
private int xVel = -speed;
private int yVel = speed;
private boolean gameOver = false;
private Image ball;
public Ball (Breakout bR){
ball = bR.getImage(bR.getDocumentBase(),"ball.png");
}
public void update(Breakout bR, Paddle p){
x += xVel;
y += yVel;
if (x < 0){
xVel = speed;
}
else if (x > bR.getWidth()){
xVel = -speed;
}
if(y > bR.getHeight()){
gameOver = true;
}
else if (y < 0){
yVel = speed;
}
collision(p);
}
public void collision(Paddle p){
int pX = p.getX();
int pY = p.getY();
int pHeight = p.getImageHeight();
int pWidth = p.getImageWidth();
if (pX<=x && pX+pWidth>=x && pY-pHeight<=y && pY+pHeight>=y){
yVel = -speed;
}
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public int getImageWidth(){
return ball.getWidth(null);
}
public int getImageHeight(){
return ball.getHeight(null);
}
public void setXVel(int xv){
yVel = xv;
}
public void paint (Graphics g, Breakout bR){
g.drawImage(ball,x,y,bR);
if (gameOver){
g.setColor(Color.WHITE);
g.drawString("Game Over", 100,300);
}
}
}
Thanks for your help.
Nothing seems to happen in class Ball's collision function if a collision is detected.
After
ba.setXVel(6);
You need to have some code to make the brick no longer paint. Try giving the brick a visibility attribute in the class definition:
private Boolean visible;
When in the collision function after
ba.setXVel(6);
Insert
setVisible(false);
You'll need to write a setter and getter for the visible attribute. Then in the paint function, set it only to paint if visible is true.
You'll need to have more than one Brick2 instance. Each Brick2 instance will represent one individual brick. Put them in a collection like List and step through them to draw them.
One way to create the list would be:
List<Brick2> bricks = new List<Brick2>;
for (i = 0; i > num_bricks; i++ ) {
bricks.add(new Brick2());
}
But you'll need to have a way to set the position of each brick. Perhaps based on the brick number(i) and use the brick constructor to derive it's position based on the order in which they're created.
I have an application where you place tiles. You can place tiles over tiles and I don't want that. I know that I need something like if the tile rectangle contains the mouse then don't place a tile over it. But this doesn't work. Look at this code:
for (int i = 0; i < b.toArray().length; i++) {
b.get(i).tick();
if (b.get(i).r.contains(Comp.mx, Comp.my)) {
canPlaceATile = false;
// System.out.println("yes");
}
else {
canPlaceATile = true;
//System.out.println("no");
}
if (b.get(i).remove) {
b.remove(i);
i--;
}
}
This is how I check if the mouse is inside the area of one of the tiles.
Block class:
public abstract class block {
public int x,id;
public int y;
protected Image img;
public boolean remove;
public int rotate;
public Rectangle r;
protected int bx, by;
public block() {
}
public abstract void tick();
public abstract void render(Graphics g);
public void createCollisionRect() {
r.setBounds(x - (int) play.camx, y - (int) play.camy, 20, 20);
}
}
an example of a tile:
public class wall extends block {
public wall(int x, int y, int rot) {
this.x = x;
this.y = y;
this.rotate = rot;
r = new Rectangle(x - (int) play.camx, y - (int) play.camy, 20, 20);
id = 0;
}
public void tick() {
createCollisionRect();
if (Comp.mr && r.contains(new Point((Comp.mx), (Comp.my)))) {
remove = true;
}
}
public void render(Graphics g) {
ImageIcon i62 = new ImageIcon("res/tiles/wall.png");
img = i62.getImage();
g.drawImage(img, x - (int) play.camx, y - (int) play.camy, null);
g.setColor(Color.red);
// g.drawRect(x -(int)play.camx, y - play.camy, 20,20);
}
}
I want to check if any of the rectangles contains the mouse and set canPlaceATile to false if the mouse is inside one of the rectangles. The code above doesn't work because when I print the console and I have my mouse over one of the tiles it says:
yes
no
yes
no
yes
no
yes
no
yes
no
yes
no
yes
no
yes
no
yes
no
yes
no
yes
no
yes
and this is when my mouse is on the rectangle without moving it at all. How can I fix this so that I cannot place tiles on top of tiles. Her is where I place tiles:
public void mousePressed(MouseEvent e) {
if (e.getButton() == MouseEvent.BUTTON1) {
Comp.ml = true;
if (manager.isplay && play.dragging == false) {
if (play.canPlaceATile) {
if (play.selectedID == 0) {
play.b.add(new wall((Comp.mx / 20) * 20, (Comp.my / 20) * 20, play.selectedRot));
}
}
}
}
}
I really could use some help in order to find a working solution for my game.
My game is almost done, but the walls in my game are still not working as they should.
I have tried to find a solution on the internet for this problem, but i still haven't found a simple way to stop a rectangle just before it will collide with a wall (another rectangle).
Right now i have implemented a collision detection between the player rectangle and the wall rectangle and then stopped it to move, but then it gets stuck inside a wall when it hits.
Want it to stop just before, so it still can move. The code i have done this with so far is here:
Pacman Class
public class Pacman {
private String pacmanup = "pacmanup.png";
private String pacmandown = "pacmandown.png";
private String pacmanleft = "pacmanleft.png";
private String pacmanright = "pacmanright.png";
private int dx;
private int dy;
private int x;
private int y;
private int width;
private int height;
private boolean visible;
private Image imageup;
private Image imagedown;
private Image imageleft;
private Image imageright;
public Pacman() {
ImageIcon i1 = new ImageIcon(this.getClass().getResource(pacmanup));
imageup = i1.getImage();
ImageIcon i2 = new ImageIcon(this.getClass().getResource(pacmandown));
imagedown = i2.getImage();
ImageIcon i3 = new ImageIcon(this.getClass().getResource(pacmanleft));
imageleft = i3.getImage();
ImageIcon i4 = new ImageIcon(this.getClass().getResource(pacmanright));
imageright = i4.getImage();
width = imageup.getWidth(null);
height = imageup.getHeight(null);
visible = true;
x = 270;
y = 189;
}
public int getDx() {
return dx;
}
public void setDx(int dx) {
this.dx = dx;
}
public int getDy() {
return dy;
}
public void setDy(int dy) {
this.dy = dy;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public Image getImageup() {
return imageup;
}
public Image getImagedown() {
return imagedown;
}
public Image getImageleft() {
return imageleft;
}
public Image getImageright() {
return imageright;
}
public void setVisible(boolean visible) {
this.visible = visible;
}
public boolean isVisible() {
return visible;
}
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
public void move() {
x += dx;
y += dy;
}
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = -2;
dy = 0;
}
if (key == KeyEvent.VK_RIGHT) {
dx = 2;
dy = 0;
}
if (key == KeyEvent.VK_UP) {
dx = 0;
dy = -2;
}
if (key == KeyEvent.VK_DOWN) {
dx = 0;
dy = 2;
}
}
Here i have created a Rectangle getBounds method which i use to create an rectangle of the pacman and place an image over it.
Barrier class / Wall class
public class Barrier {
private String barrier = "barrier.png";
private int x;
private int y;
private int width;
private int height;
private boolean visible;
private Image image;
public Barrier(int x, int y) {
ImageIcon ii = new ImageIcon(this.getClass().getResource(barrier));
image = ii.getImage();
width = image.getWidth(null);
height = image.getHeight(null);
visible = true;
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public boolean isVisible() {
return visible;
}
public void setVisible(Boolean visible) {
this.visible = visible;
}
public Image getImage() {
return image;
}
public Rectangle getBounds() {
return new Rectangle(x, y, width, height);
}
This class also have the Rectangle getBounds class which i use to detect collision.
The last code i show is how i do the collision detection so far:
Code inside Board class
Rectangle r3 = pacman.getBounds();
for (int j = 0; j<barriers.size(); j++) {
Barrier b = (Barrier) barriers.get(j);
Rectangle r4 = b.getBounds();
if (r3.intersects(r4)) {
System.out.println("Wall hit");
pacman.setDx(0);
pacman.setDy(0);
}
}
Well, what i do, if there is a collision between r3 and r4, i gonna set Dx and Dy to 0.. what i want to find another solution so it detect for collision but i wont get stuck inside a wall, but i don't know how to :/
Hope someone will help.
There are two approaches you can follow. One is ugly but easier, the other one requires a deeper redesign of your classes.
1) Ugly/Simple Approach
In the ugly one, you keep moving your guy before doing the collision checks. Simply move your pacman back to the point where it was not stuck. You accomplish that by inverting the last directions used:
Code inside Board class
Change your reaction in case you find a collision: just walk the same distance, backwards.
if (r3.intersects(r4)) {
System.out.println("Wall hit, move back");
pacman.setDx(-pacman.getDx());
pacman.setDy(-pacman.getDy());
// Possibly need to call move() here again.
pacman.move();
break;
}
Ugly, but should work.
Not recommended to coding perfectionists with OCD and heart disease, though.
2) Redesign
In this approach, you test the position pacman will occupy before doing any actual moves. If that spot is not into any barrier, then perform the movement for real.
Code inside Pacman class
Add this method, so that you can check for collisions against the new bounds.
public Rectangle getOffsetBounds() {
return new Rectangle(x + dx, y + dy, width, height);
}
Code inside Board class
// Strip the call to pacman.move() prior to this point.
Rectangle r3 = pacman.getOffsetBounds(); // Check against the candidate position.
for (int j = 0; j<barriers.size(); j++) {
Barrier b = (Barrier) barriers.get(j);
Rectangle r4 = b.getBounds();
if (r3.intersects(r4)) {
System.out.println("Wall hit");
pacman.setDx(0);
pacman.setDy(0);
// Quit the loop. It's pointless to check other barriers once we hit one.
break;
}
}
// Now we're good to move only in case there's no barrier on our way.
pacman.move();
Particularly I prefer this approach, but it's up to you to pick the best one.