I am making pong in java but the enemy AI is not moving. It should move to the direction the ball goes to. Please can someone help me?
Main class:
import javax.swing.*;
public class Main extends JFrame{
final static int WW = 800;
final static int WH = 600;
public Main(){
setSize(WW,WH);
setResizable(false);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
setTitle("Pong");
add(new GamePanel());
setVisible(true);
}
public static void main(String[] args){
new Main();
}
}
GamePanel class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GamePanel extends JPanel implements ActionListener,KeyListener{
Player player = new Player();
Computer computer = new Computer();
Ball ball = new Ball();
public GamePanel(){
Timer time = new Timer(20, this);
time.start();
this.addKeyListener(this);
this.setFocusable(true);
}
private void update(){
player.update();
ball.update();
ball.Collision(player);
computer.update();
ball.Collision(computer);
}
public void paintComponent(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(0, 0, Main.WW, Main.WH);
player.paint(g);
ball.paint(g);
computer.paint(g);
}
public void actionPerformed(ActionEvent e){
update();
repaint();
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_UP){
player.setyv(-10);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN){
player.setyv(10);
}
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode()==KeyEvent.VK_UP || e.getKeyCode()==KeyEvent.VK_DOWN)
player.setyv(0);
}
public void keyTyped(KeyEvent e){
}
}
Player class:
import java.awt.*;
public class Player {
private int y = 300;
private int w = 20;
private int h = 120;
private int yv = 0;
private int x = 700;
public Player(){
}
public void update(){
y = y + yv;
}
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(x,y,w,h);
}
public void setyv(int speed){
yv = speed;
}
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
public int getW(){
return this.w;
}
public int getH(){
return this.h;
}
}
Ball class:
import java.awt.*;
public class Ball {
private int x = 400;
private int y = 300;
private int xv = -10;
private int yv = 10;
public void update(){
x = x += xv;
y = y += yv;
if(x < 10){
xv = 10;
}
if(x > 770){
xv = -10;
}
if(y < 10){
yv = 5;
}
if(y > 550){
yv = -5;
}
}
public int getY(){
return this.y;
}
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillOval(x, y, 20, 20);
}
public void Collision(Player player){
if(this.x > (player.getX()-10)){
if(this.y > player.getY() && (this.y < player.getY() + player.getH())){
xv = -10;
}
}
}
public void Collision(Computer cpu){
if(this.x < (cpu.getX()+10)){
if(this.y > cpu.getY() && (this.y < cpu.getY() + cpu.getH())){
xv = 10;
}
}
}
}
Computer class:
import java.awt.*;
public class Computer {
private int y = 300;
private int w = 20;
private int h = 120;
private int yv = 0;
private int x = 100;
Ball ballpos = new Ball();
public Computer(){
}
public void update(){
if(ballpos.getY() < this.y){
yv = -1;
}
else if(ballpos.getY() > this.y){
yv = 1;
}
y = y + yv;
}
public void paint(Graphics g){
g.setColor(Color.WHITE);
g.fillRect(x,y,w,h);
}
public int getX(){
return this.x;
}
public int getY(){
return this.y;
}
public int getW(){
return this.w;
}
public int getH(){
return this.h;
}
}
I am sorry if this is too much code, but if only send the AI class, you can not see where the problem is I guess. Please help me I do not know why it is not working. Sorry for my bad English.
Your Computer class creates a differrent ball (ballpos) that is never updated and therefore the AI never moves. You need to pass your Ball object from the GamePanel class to the Computers update method:
Computer:
public void update(Ball ball){
if(ball.getY() < this.y){
yv = -1;
}
else if(ball.getY() > this.y){
yv = 1;
}
y = y + yv;
}
GamePanel:
private void update(){
player.update();
ball.update();
ball.Collision(player);
computer.update(ball);
ball.Collision(computer);
}
Related
I am developing a space invaders application for a college assignment and I've come into a problem where the aliens change direction one by one as they hit a wall rather than the whole array of objects switching direction when any alien touches the boundary. I hae a feeling it is an issue in my for loop where my move method containing reverseDirection() method acts on each element individually but I do not know how to fix this and any help would be greatly appreciated. Here is my code for you;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.*;
import javax.swing.*;
import java.awt.image.*;
public class InvadersApplication extends JFrame implements Runnable {//, KeyListener {
private static final Dimension WindowSize = new Dimension(800, 600);
private static final int NUMALIENS = 16;
private Alien AliensArray[] = new Alien[NUMALIENS];
private Image alienImage;
private Image playerImage;
private String workingDirectory = "C:\\Users\\brads\\IdeaProjects\\Assignment3\\src\\workingDirectory\\";
private Player playerShip;
private BufferStrategy strategy;
public InvadersApplication() {
System.out.println(System.getProperty("user.dir"));
setDefaultCloseOperation(EXIT_ON_CLOSE);
Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
int x = screenSize.width / 2 - WindowSize.width / 2;
int y = screenSize.height / 2 - WindowSize.height / 2;
setBounds(x, y, WindowSize.width, WindowSize.height);
this.setTitle("Alien Invaders App");
ImageIcon playerIcon = new ImageIcon(workingDirectory + "player_ship.png");
playerImage = playerIcon.getImage();
ImageIcon alienIcon = new ImageIcon(workingDirectory + "alien_ship_1.png");
alienImage = alienIcon.getImage();
playerShip = new Player(playerImage);
// addKeyListener(this);
setVisible(true);
createBufferStrategy(2);
strategy = getBufferStrategy();
for (int i = 0; i < NUMALIENS; i++) {
AliensArray[i] = new Alien(alienImage);
AliensArray[i].setPosition(70 * (i%4), 70 * (i/4));
AliensArray[i].setXspeed(1);
}
Thread thread1 = new Thread(this);
thread1.start();
repaint();
}
#Override
public void run(){
while(true){
try{
for(int i = 0; i < NUMALIENS; i++) {
AliensArray[i].move();
}
repaint();
Thread.sleep(5);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/* public void keyPressed(KeyEvent e) {
int KeyCode = e.getKeyCode();
if (KeyCode == KeyEvent.VK_LEFT) {
playerShip.movePlayer(-8);
} else if (KeyCode == KeyEvent.VK_RIGHT) {
playerShip.movePlayer(8);
}
}
*/
public void keyReleased(KeyEvent e){
}
public void keyTyped(KeyEvent e){}
public void paint(Graphics g){
g = strategy.getDrawGraphics();
g.setColor(Color.BLACK);
g.fillRect(0,0,800,600);
for(int i=0; i < NUMALIENS; i++){
AliensArray[i].paint(g);
}
// playerShip.paint(g);
//playerShip.paintPlayer(g);
strategy.show();
this.repaint();
}
public static void main(String[] args){
InvadersApplication x = new InvadersApplication();
}
}
Sprite2D class;
public class Sprite2D{
protected int x = 0,y = 30;
protected Image myImage;
public Sprite2D(Image myImage){
this.x = x;
this.y = y;
this.myImage = myImage;
}
public void setPosition(int xx, int yy){
x = xx;
y = yy;
}
public void paint(Graphics g){
g.drawImage(myImage, x,y, null);
}
}
Alien subclass of sprite2D;
import java.awt.*;
import java.util.Random;
import javax.swing.*;
public class Alien extends Sprite2D {
private int xi;
private int xj;
public Alien(Image myImage) {
super(myImage);
this.myImage = myImage;
this.x = x;
this.y = y;
this.xi = xi;
this.xj = xj;
}
// #Override
// public void setPosition(int xx, int yy){
// xx = x;
// yy = y;
//
// }
public void move() {
y+=xj;
x+= xi;
if(x >= 750) {
reverseDirection();
x = x + xi;
}
else if (x < 0)
{
reverseDirection();
x = x + xi;
}
}
public void setXspeed(int xi) {
this.xi = xi;
}
public void setYspeed(int xj) {
this.xj = xj;
}
public void reverseDirection() {
xi = -xi;
System.out.println("reverse");
}
// #Override
// public void paint(Graphics g) {
//
//
// g.drawImage(myImage, xx, yy, null);
// }
}
So I created a simple simple simulation where squares are spawned randomly with random vectors and bounce of the edges of the window.
I wanted it to take into account the window being resized. So that if I change the dimensions of the window from 600x600 to 1200x600 the squares will bounce of the new border rather than 600x600.
I tried doing getWidth() getHeight() but it would return 0.
So I put it in the pain() (since it gets called on window resize) method and saved the return values as local variables. But I cannot call getjpWidth() from the Rect class.
So basically what I need is to get new window dimension into the move() method in the Rect class.
Please feel free to point out any other mistakes and things that can be done better. I'm new to 2D programming (studying Computer Science)
Application
import javax.swing.*;
public class Application {
private Application(){
//create a JFrame window
JFrame frame = new JFrame("Moving Squares");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//add a JPanel
GamePanel gamePanel = new GamePanel();
frame.add(gamePanel);
//pack the window around the content
frame.pack();
//center
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String args[]){
new Application();
}
}
GamePanel
import java.awt.*;
import java.util.ArrayList;
import javax.swing.*;
public class GamePanel extends JPanel implements Runnable{
private int jpWidth=0, jpHeight=0;
//set JPanel size
private static final Dimension DESIRED_SIZE = new Dimension(600,600);
#Override
public Dimension getPreferredSize(){
return DESIRED_SIZE;
}
//constructor
GamePanel(){
Thread t = new Thread(this);
t.start();
}
private ArrayList <Rect> rect=new ArrayList<>();
public void run(){
for(int i=0; i<15; i++){
rect.add(new Rect());
}
while(true){
for(Rect rect:rect){
rect.move();
}
//repaint still image for better frames
//should be 100fps instead it's >144fps
repaint();
try{Thread.sleep(10);}
catch(InterruptedException e){/**/};
repaint();
try{Thread.sleep(10);}
catch(InterruptedException e){/**/};
repaint();
try{Thread.sleep(10);}
catch(InterruptedException e){/**/};
}
}
public void paint(Graphics g){
Graphics2D g2d = (Graphics2D) g.create();
jpWidth=getWidth();
jpHeight=getHeight();
g2d.setColor(Color.white);
g2d.fillRect(0,0,jpWidth,jpHeight);
for(Rect rect:rect) {
g2d.setColor(Color.black);
g2d.fillRect(rect.getXcord()-1, rect.getYcord()-1, rect.getWidth()+2, rect.getHeight()+2);
g2d.setColor(Color.getHSBColor(rect.getR(), rect.getG(), rect.getB()));
g2d.fillRect(rect.getXcord(), rect.getYcord(), rect.getWidth(), rect.getHeight());
}
}
public int getJpWidth() {
return jpWidth;
}
public int getJpHeight() {
return jpHeight;
}
}
Rect
import java.util.Random;
public class Rect {
//properties
private int width=30, height=30;
private int R, G, B;
//movement
private int xCord, yCord;
private int xVector, yVector;
private int xSlope, ySlope;
public Rect(){
Random rand = new Random();
//random color
R=rand.nextInt(255);
G=rand.nextInt(255);
B=rand.nextInt(255);
//random spawn position
xCord=rand.nextInt(600-width);
yCord=rand.nextInt(600-height);
//direction
do{
xVector=rand.nextInt(3) - 1;
yVector=rand.nextInt(3) - 1;
}while(xVector==0 || yVector==0);
//slope
do{
xSlope=rand.nextInt(3);
ySlope=rand.nextInt(3);
}while(xSlope==0 || ySlope==0);
xVector*=xSlope;
yVector*=ySlope;
}
public void move(){
//if(xCord>=//how to get screen width ? ){}
if((xCord>=600-width) || (xCord<=0)){
bounceX();
}
if((yCord>=600-height) || (yCord<=0)) {
bounceY();
}
xCord+=xVector;
yCord+=yVector;
}
public void bounceX(){
xVector*=-1;
}
public void bounceY(){
yVector*=-1;
}
public int getR() {
return R;
}
public int getG() {
return G;
}
public int getB() {
return B;
}
public int getXcord() {
return xCord;
}
public int getYcord() {
return yCord;
}
public int getWidth(){
return width;
}
public int getHeight(){
return height;
}
}
So basically what I need is to get new window dimension into the move() method in the Rect class.
Don't know if it is the best design but I pass the "panel" as a parameter to the "move()" method so its width/height can be used.
Here is some old code I have lying around that shows this approach:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class BallAnimation4
{
private static void createAndShowUI()
{
BallPanel panel = new BallPanel();
JFrame frame = new JFrame("BallAnimation4");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.pack();
frame.setLocationRelativeTo( null );
//frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible( true );
panel.addBalls(5);
panel.startAnimation();
}
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowUI();
}
});
}
}
class BallPanel extends JPanel implements ActionListener
{
private ArrayList<Ball> balls = new ArrayList<Ball>();
public BallPanel()
{
setLayout( null );
// setBackground( Color.BLACK );
}
public void addBalls(int ballCount)
{
Random random = new Random();
for (int i = 0; i < ballCount; i++)
{
Ball ball = new Ball();
ball.setRandomColor(true);
ball.setLocation(random.nextInt(getWidth()), random.nextInt(getHeight()));
// ball.setMoveRate(32, 32, 1, 1, true);
ball.setMoveRate(16, 16, 1, 1, true);
// ball.setSize(32, 32);
ball.setSize(64, 64);
balls.add( ball );
}
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
for (Ball ball: balls)
{
ball.draw(g);
}
}
#Override
public Dimension getPreferredSize()
{
return new Dimension(800, 600);
}
public void startAnimation()
{
Timer timer = new Timer(1000/60, this);
timer.start();
}
public void actionPerformed(ActionEvent e)
{
move();
repaint();
}
private void move()
{
for (Ball ball : balls)
{
ball.move(this);
}
}
class Ball
{
public Color color = Color.BLACK;
public int x = 0;
public int y = 0;
public int width = 1;
public int height = 1;
private int moveX = 1;
private int moveY = 1;
private int directionX = 1;
private int directionY = 1;
private int xScale = moveX;
private int yScale = moveY;
private boolean randomMove = false;
private boolean randomColor = false;
private Random myRand = null;
public Ball()
{
myRand = new Random();
setRandomColor(randomColor);
}
public void move(JPanel parent)
{
int iRight = parent.getSize().width;
int iBottom = parent.getSize().height;
x += 5 + (xScale * directionX);
y += 5 + (yScale * directionY);
if (x <= 0)
{
x = 0;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (x >= iRight - width)
{
x = iRight - width;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
}
if (y <= 0)
{
y = 0;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
if (y >= iBottom - height)
{
y = iBottom - height;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
}
}
public void draw(Graphics g)
{
g.setColor(color);
g.fillOval(x, y, width, height);
}
public void setColor(Color c)
{
color = c;
}
public void setLocation(int x, int y)
{
this.x = x;
this.y = y;
}
public void setMoveRate(int xMove, int yMove, int xDir, int yDir, boolean randMove)
{
this.moveX = xMove;
this.moveY = yMove;
directionX = xDir;
directionY = yDir;
randomMove = randMove;
}
public void setRandomColor(boolean randomColor)
{
this.randomColor = randomColor;
switch (myRand.nextInt(3))
{
case 0: color = Color.BLUE;
break;
case 1: color = Color.GREEN;
break;
case 2: color = Color.RED;
break;
default: color = Color.BLACK;
break;
}
}
public void setSize(int width, int height)
{
this.width = width;
this.height = height;
}
}
}
Also, note that for animation you should be using a Swing Timer to schedule the animation. Updates to Swing components should be done on the Event Dispatch Thread (EDT). While not likely to cause a problem with this simple application it is a good habit to make sure this basic rule is followed otherwise you can have random problems and it is never easy to debug a random problem.
I have been working on a Breakout game and have just about everything done except for the brick collision. The ball bounces of the wall, paddle and the brick. However when the ball bounces of the brick, the brick does not disappear. I am really stuck on this. Any ideas are greatly appreciated.
What I have for brick, ball and main class:
Brick Class:
import java.awt.*;
import java.applet.*;
public class Brick2{
private int x;
private int y;
public Brick2(int X, int Y){
x =X;
y=Y;
}
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 <= 600; 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:
import java.awt.*;
import java.applet.*;
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);
}
}
}
Main Class:
import java.applet.*;
import java.awt.*;
public class Breakout extends Applet implements Runnable{
Thread thread = new Thread(this);
boolean running = true;
//Brick b;
Brick2 b2;
Paddle p;
Ball ba;
Image dbImage;
Graphics dbg;
public void init(){
setSize(800,600);
//b = new Brick(this);
b2 = new Brick2(0,0);
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(this,ba);
b2.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, Brick2 b){
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,this);
b2.paint(g);
p.paint(g,this);
ba.paint(g,this);
}
}
Thanks for your help.
You could add a boolean isDestroyed = false in your Brick Class. Once the Ball touches the Brick (in your collision() method), set isDestroyed = true and stop drawing/interacting with that Brick :) Don't forget to make that brick = null so it frees up memory later :)
The best way to do this would be to create the boolean isDestroyed as a private variable and get its' value with a isDestroyed method:
public class Brick2 {
private boolean isDestroyed = false;
public boolean isDestroyed() {
return isDestroyed;
}
public void setIsDestroyed(boolean newValue) {
isDestroyed = newValue;
}
}
Then, in your Main class, before calling b2.paint(), check if b2.isDestroyed returns true:
public class Breakout...{
public void paint(...) {
if(b2 != null && !b2.isDestroyed())
b2.paint(g);
else
b2 = null;
}
BUT, if I were you, I would create an ArrayList of Bricks and add/remove them through the ArrayList. They will be easier to manage that way :) Hola if you need anything else.
Treat an array of bricks the same way you would treat any other collection of objects. You can use List<brick> = new ArrayList<brick>();
Brick should have four coordinates and shape would fit well for this purpose, int brickLife = 1 that changes to zero once the ball breaks it. You might want to increase the value to add sturdy bricks.
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.
My program is throwing a NullPointerException error upon trying to call the paint method of a ship.
import java.awt.*;
import java.awt.event.*;
public class Ship extends Polygon implements ActionListener, KeyListener {
final static Point[] shape = new Point[4];
final static Point START_POSITION = new Point(400, 300);
private int windowX;
private int windowY;
Point pull;
public Ship(int maxX, int maxY) {
super(shape, START_POSITION, 0);
windowX = maxX;
windowY = maxY;
shipInit();
init(shape);
Point[] pointArray = getPoints();
pull = new Point(0, 0);
}
public void shipInit() {
shape[0] = new Point(0, 0);
shape[1] = new Point(30, 10);
shape[2] = new Point(0, 20);
shape[3] = new Point(10, 10);
}
public void paint(Graphics brush) {
brush.setColor(Color.white);
Point[] points = getPoints();
if (position.x > windowX) {
position.x -= windowX;
} else if (position.x < 0) {
position.x += windowX;
} else if (position.y > windowY) {
position.y -= windowY;
} else if (position.y < 0) {
position.x += windowY;
}
for (int i = 0; i < points.length; i++) {
int x1;
int y1;
int x2;
int y2;
if (i == points.length - 1) {
x1 = (int) points[i].x;
y1 = (int) points[i].y;
x2 = (int) points[0].x;
y2 = (int) points[0].y;
} else {
x1 = (int) points[i].x;
y1 = (int) points[i].y;
x2 = (int) points[i + 1].x;
y2 = (int) points[i + 1].y;
}
brush.drawLine(x1, y1, x2, y2);
}
}
public void move() {
position.x += 2;
position.y += 5;
// position.y += 1;
}
public void accelerate(double acceleration) {
pull.x += (acceleration * Math.cos(Math.toRadians(rotation)));
pull.y += (acceleration * Math.sin(Math.toRadians(rotation)));
}
public void keyPressed(KeyEvent e) {
int keyPressed = e.getKeyCode();
if (keyPressed == KeyEvent.VK_W)
System.out.println("Hi");
if (keyPressed == KeyEvent.VK_UP) {
accelerate(5);
position.x += pull.x;
position.y += pull.y;
}
if (keyPressed == KeyEvent.VK_RIGHT) {
rotation += 5;
}
if (keyPressed == KeyEvent.VK_LEFT) {
rotation -= 5;
}
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
}
}
And the class the calls the paint
import java.awt.*;
import java.awt.event.*;
class Asteroids extends Game {
private static int frameWidth = 800;
private static int frameHeight = 600;
Ship player;
public Asteroids() {
super("Asteroids!", frameWidth, frameHeight);
init();
}
public void init() {
player = new Ship(800, 600);
this.addKeyListener(player);
repaint();
}
public void paint(Graphics brush) {
brush.setColor(Color.black);
brush.fillRect(0, 0, width,height);
brush.setColor(Color.white);
String hi = "hi";
brush.drawString(hi, 299, 399);
player.paint(brush);
}
public static void main (String[] args) {
new Asteroids();
}
}
The error says that the error is thrown when calling player.paint(brush). Can anyone figure out why?
I have never coded in this before, but a quick trip to the universe of google explained to me that paint() and init() runs on 2 different threads.
That said, your paint() method gets called BEFORE the init() method.
A quick way to fix this would be to have a boolean that gets set inside init()
Like this:
import java.awt.*;
import java.awt.event.*;
class Asteroids extends Game {
private static int frameWidth = 800;
private static int frameHeight = 600;
Ship player;
private boolean hasInitialized; // Initialization check
public Asteroids() {
super("Asteroids!", frameWidth, frameHeight);
init();
}
public void init() {
player = new Ship(800, 600);
this.addKeyListener(player);
hasInitialized = true; // We set the boolean to true to indicate that we have initialized.
repaint();
}
public void paint(Graphics brush) {
if (!hasInitialized) return; // Nope, not ready yet, we'll stop here.
brush.setColor(Color.black);
brush.fillRect(0, 0, width,height);
brush.setColor(Color.white);
String hi = "hi";
brush.drawString(hi, 299, 399);
player.paint(brush);
}
public static void main (String[] args) {
new Asteroids();
}
}
I'm not 100% certain this will fix it, considering you already have init() inside the constructor.
But it's worth a try!
Source: Java, applet: How to block the activation of paint() before init() finishes it's work