How come the ball size wont increase?(Game) - java

I'm trying to make an addition to a pong game framework.I want the ball size to increase everytime the ball make contact with a paddle.
Here is my attempt. The first block of code is where I think the problem lays. The 2nd block is the whole class.
public class PlayState extends State {
private Paddle paddleRight, paddleLeft;
private static final int PADDLE_WIDTH = 30;
private static final int PADDLE_HEIGHT = 60;
private Ball ball;
//bDiam stands for ball diameter
private static int bDiam = 10;
private int playerScore = 0;
private Font scoreFont;
#Override
public void init() {
paddleLeft = new Paddle(0, 195, PADDLE_WIDTH, PADDLE_HEIGHT);
paddleRight = new Paddle(785, 195, PADDLE_WIDTH, PADDLE_HEIGHT);
scoreFont = new Font("SansSerif", Font.BOLD, 25);
ball = new Ball(300, 200, bDiam, bDiam);
}
#Override
public void onClick(MouseEvent e) {
// playerScore = 5;
}
#Override
public void update() {
paddleLeft.update();
paddleRight.update();
ball.update();
if (ballCollides(paddleLeft)) {
playerScore++;
bDiam+= 20;
ball.onCollideWith(paddleLeft);
Resources.hit.play();
} else
if (ballCollides(paddleRight)) {
playerScore++;
bDiam= bDiam + 20;
ball.onCollideWith(paddleRight);
Resources.hit.play();
} else if (ball.isDead()) {
playerScore -= 3;
ball.reset();
}
}
The Complete Class
public class PlayState extends State {
private Paddle paddleRight, paddleLeft;
private static final int PADDLE_WIDTH = 30;
private static final int PADDLE_HEIGHT = 60;
private Ball ball;
//bDiam stands for ball diameter
private static int bDiam = 10;
private int playerScore = 0;
private Font scoreFont;
#Override
public void init() {
paddleLeft = new Paddle(0, 195, PADDLE_WIDTH, PADDLE_HEIGHT);
paddleRight = new Paddle(785, 195, PADDLE_WIDTH, PADDLE_HEIGHT);
scoreFont = new Font("SansSerif", Font.BOLD, 25);
ball = new Ball(300, 200, bDiam, bDiam);
}
#Override
public void onClick(MouseEvent e) {
// playerScore = 5;
}
#Override
public void update() {
paddleLeft.update();
paddleRight.update();
ball.update();
if (ballCollides(paddleLeft)) {
playerScore++;
bDiam+= 20;
ball.onCollideWith(paddleLeft);
Resources.hit.play();
} else
if (ballCollides(paddleRight)) {
playerScore++;
bDiam= bDiam + 20;
ball.onCollideWith(paddleRight);
Resources.hit.play();
} else if (ball.isDead()) {
playerScore -= 3;
ball.reset();
}
}
#Override
public void render(Graphics g) {
// Draw Background
g.setColor(Resources.darkBlue);
g.fillRect(0, 0, GameMain.GAME_WIDTH, GameMain.GAME_HEIGHT);
g.setColor(Resources.darkRed);
g.fillRect(GameMain.GAME_WIDTH / 2, 0, GameMain.GAME_WIDTH / 2,
GameMain.GAME_HEIGHT);
// Draw Separator Line
g.drawImage(Resources.line, (GameMain.GAME_WIDTH / 2) - 2, 0, null);
// Draw Paddles
g.setColor(Color.white);
g.fillRect(paddleLeft.getX(), paddleLeft.getY(), paddleLeft.getWidth(),
paddleLeft.getHeight());
g.fillRect(paddleRight.getX(), paddleRight.getY(),
paddleRight.getWidth(), paddleRight.getHeight());
// Draw Ball
g.drawRect(ball.getX(), ball.getY(), ball.getWidth(), ball.getHeight());
// Draw UI
g.setFont(scoreFont); // Sets scoreFont as current font
g.drawString("" + playerScore, 350, 40); // Draws String using current
// font
}
#Override
public void onKeyPress(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP) {
paddleLeft.accelUp();
paddleRight.accelUp();
} else if (e.getKeyCode() == KeyEvent.VK_DOWN) {
paddleLeft.accelDown();
paddleRight.accelDown();
}
}
#Override
public void onKeyRelease(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_UP
|| e.getKeyCode() == KeyEvent.VK_DOWN) {
paddleLeft.stop();
paddleRight.stop();
}
}
private boolean ballCollides(Paddle p) {
return ball.getRect().intersects(p.getRect());
}
}

Your diameter variable is being passed by value into your Ball constructor. That means changing its value in your main program won't change it for the ball.
You need something like
ball.setDiameter(ball.getDiameter() +20)

Related

Background image in different place every time

I have a large program that I will post some classes of and hopefully you guys can find the problem. Basically, sometimes when I start it, it creates the game just fine, and others the background is up a few pixels to the north and west directions leaving very unsightly whitespace. I cannot seem to find the missing piece of code that decides whether not it does this. It honestly feel like some kind of rendering glitch on my machine. At any rate, I have put a background getX and getY method in for debugging and have noticed that whether the background is fully stretched to the screen(its a custom background so the pixel height and width match perfectly), or its up and to the left, the background still reads that it is displaying at (0,0). I will post all the methods from the main thread to the creating of the background in the menu. I will leave notes indicating the path it takes through this code that gets it to creating the background. Thank you for your help and I will check in regularly for edits and more information.
EDIT: added background.java
EDIT2: added pictures explaining problem
Menu.java *ignore the FileIO code, the main point is the creation of a new GamePanel()
public class Menu {
private static File file;
public static void main(String[] args) throws IOException {
file = new File("saves.txt");
if(file.exists()){
FileIO.run();
FileIO.profileChoose();
}
else{
FileIO.profileCreate();
FileIO.run();
}
JFrame window = new JFrame("Jolly Jackpot Land");
window.setContentPane(new GamePanel());
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setResizable(false);
window.pack();
window.setLocationRelativeTo(null);
window.setVisible(true);
}
}
Next is the GamePanel.java
public class GamePanel extends JPanel implements Runnable, KeyListener {
// ID
private static final long serialVersionUID = 1L;
// Dimensions
public static final int WIDTH = 320;
public static final int HEIGHT = 240;
public static final int SCALE = 2;
// Thread
private Thread thread;
private boolean running;
private int FPS = 30;
private long targetTime = 1000 / FPS;
// Image
private BufferedImage image;
private Graphics2D g;
// Game State Manager
private GameStateManager gsm;
public GamePanel() {
super();
setPreferredSize(new Dimension(WIDTH * SCALE, HEIGHT * SCALE));
setFocusable(true);
requestFocus();
}
public void addNotify() {
super.addNotify();
if (thread == null) {
thread = new Thread(this);
addKeyListener(this);
thread.start();
}
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
}
private void init() {
image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
g = (Graphics2D) image.getGraphics();
running = true;
gsm = new GameStateManager();
}
#Override
public void run() {
init();
long start;
long elapsed;
long wait;
// Game Loop
while (running) {
start = System.nanoTime();
update();
draw();
drawToScreen();
elapsed = System.nanoTime() - start;
wait = targetTime - (elapsed / 1000000);
if (wait < 0) {
wait = 5;
}
try {
Thread.sleep(wait);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void update() {
gsm.update();
}
private void draw() {
gsm.draw(g);
}
private void drawToScreen() {
Graphics g2 = getGraphics();
g2.drawImage(image, 0, 0, WIDTH * SCALE, HEIGHT * SCALE, null);
g2.dispose();
}
#Override
public void keyPressed(KeyEvent k) {
gsm.keyPressed(k.getKeyCode());
}
#Override
public void keyReleased(KeyEvent k) {
}
#Override
public void keyTyped(KeyEvent arg0) {
}
}
This calls for the creation of a new GameStateManager object in its init() method and the class for that is here.
GameStateManager.java
public class GameStateManager {
private ArrayList<GameState> gameStates;
private int currentState;
public static final int MENUSTATE = 0;
public static final int SLOTGAMESTATE = 1;
public static final int DICEGAMESTATE = 2;
public static final int ROULETTEGAMESTATE = 3;
public static final int LEADERBOARDSTATE = 4;
public static final int SETTINGSSTATE = 5;
public static final int HELPSTATE = 6;
public GameStateManager() {
gameStates = new ArrayList<GameState>();
currentState = 0;
gameStates.add(new MenuState(this));
gameStates.add(new SlotGameState(this));
gameStates.add(new DiceGameState(this));
gameStates.add(new RouletteGameState(this));
gameStates.add(new LeaderboardState(this));
gameStates.add(new SettingsState(this));
gameStates.add(new HelpState(this));
}
public void setState(int state){
currentState = state;
gameStates.get(currentState).init();
currentState = 0;
}
public int getState() {
return currentState;
}
public void update() {
gameStates.get(currentState).init();
}
public void draw(java.awt.Graphics2D g){
gameStates.get(currentState).draw(g);
}
public void keyPressed(int k){
gameStates.get(currentState).keyPressed(k);
}
public void keyReleased(int k) {
gameStates.get(currentState).keyReleased(k);
}
}
GameState is an abstract class I have so its not worth posting, it only contains init(), draw(), etc. This next class is the last and final class and is called because GameStateMananger starts at MENUSTATE or 0, and when GSM is initialized it initializes its current state, thus taking us to the class MenuState
MenuState.java
public class MenuState extends GameState {
private Background bg;
public FontMetrics fontMetrics;
private int choice = 0;
private String[] options = { "Slot Machine", "Dice Toss", "Roulette Wheel", "Leaderboards", "Settings", "Help",
"Quit" };
private Color titleColor;
private Font titleFont;
private Font font;
public MenuState(GameStateManager gsm) {
this.gsm = gsm;
try {
bg = new Background("/Backgrounds/happybg.png");
titleColor = Color.WHITE;
titleFont = new Font("Georgia", Font.PLAIN, 28);
} catch (Exception e) {
e.printStackTrace();
}
font = new Font("Arial", Font.PLAIN, 12);
}
#Override
public void init() {
}
#Override
public void update() {
}
#Override
public void draw(Graphics2D g) {
Canvas c = new Canvas();
fontMetrics = c.getFontMetrics(font);
// Draw BG
bg.draw(g);
// Draw title
g.setColor(titleColor);
g.setFont(titleFont);
String title = "Jolly Jackpot Land!";
g.drawString(title, 36, 60);
g.setFont(font);
for (int i = 0; i < options.length; i++) {
if (i == choice)
g.setColor(Color.RED);
else
g.setColor(Color.WHITE);
g.drawString(options[i], 30, 120 + i * 15);
}
g.setColor(Color.WHITE);
g.setFont(new Font("Arial", Font.PLAIN, 10));
g.drawString("v1.1", 165, 235);
Object[] a = { ("Name: " + Player.getName()), ("Gil: " + Player.getGil()),
("Personal Best: " + Player.getPersonalBest()), ("Winnings: " + Player.getWinnings()),
("Wins: " + Player.getWins()), ("Losses: " + Player.getLosses()),
("Win/Loss Ratio: " + String.format("%.2f", Player.getRatio()) + "%") };
g.setFont(font);
if (Player.getName() != null) {
for (int x = 0; x < a.length; x++) {
g.drawString(a[x].toString(), GamePanel.WIDTH - fontMetrics.stringWidth(a[x].toString()) - 30,
120 + x * 15);
}
}
}
private void select() {
if (choice == 0) {
// Slots
gsm.setState(GameStateManager.SLOTGAMESTATE);
}
if (choice == 1) {
// Dice
gsm.setState(GameStateManager.DICEGAMESTATE);
}
if (choice == 2) {
// Roulette
gsm.setState(GameStateManager.ROULETTEGAMESTATE);
}
if (choice == 3) {
// Leaderboards
gsm.setState(GameStateManager.LEADERBOARDSTATE);
}
if (choice == 4) {
// Settings
gsm.setState(GameStateManager.SETTINGSSTATE);
}
if (choice == 5) {
// Help
gsm.setState(GameStateManager.HELPSTATE);
}
if (choice == 6) {
// Quit
System.exit(0);
}
}
#Override
public void keyPressed(int k) {
if (k == KeyEvent.VK_ENTER) {
select();
}
if (k == KeyEvent.VK_UP) {
choice--;
if (choice == -1) {
choice = options.length - 1;
}
}
if (k == KeyEvent.VK_DOWN) {
choice++;
if (choice == options.length) {
choice = 0;
}
}
}
#Override
public void keyReleased(int k) {
}
}
Background.java
public class Background {
private BufferedImage image;
private double x;
private double y;
public Background(String s) {
try {
image = ImageIO.read(getClass().getResourceAsStream(s));
} catch (Exception e) {
e.printStackTrace();
}
}
public void setPosition(double x, double y) {
this.setX(x);
this.setY(y);
}
public void draw(Graphics2D g) {
g.drawImage(image, 0, 0, null);
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
}
This is where it waits for input in the game loop basically. I know this is a lot of code, but a lot of it is skimming till a method call takes you to the next class. I just can't figure out why it only happens sometimes, if it was consistent I could debug it. Any help would be extremely appreciated.
These are both from clicking the .jar of the above program, exact same .jar, exact same source code, different result. I am bewildered.

How to fix multiple threads running in java awt graphics

I am programming a game for a school project and when I run the code, it works sometimes and then ill run it again and the paddle or ball won't move and the print statements in my keylistener dont show up.
Now I am running two timers, one for the animation and one for a countdown, could this be an issue? It seems like multiple threads are running or when I close the jframe and then rerun the program is picking up where it left off?
public class LobPong extends JPanel implements KeyListener {
public static double xCoordinate;
public static double yCoordinate;
public static Timer timer;
static int xPaddleLeft;
private static int yPaddle = 800;
private static int score = 0;
private static int level = 1;
public static JLabel scoreLabel = new JLabel(" Score: 0 ");
public static JLabel timeLabel = new JLabel(" ");
public static JLabel levelLabel = new JLabel(" Level: ");
private static int life = 3;
private static int levelTime = 30000;
public static int dx, dy;
private static double times = 0;
public static void main(String[] args) {
JFrame LobPongApp = new JFrame();
LobPong canvas = new LobPong();
canvas.setBackground(Color.BLUE);
LobPongApp.add(canvas);
LobPongApp.setSize(800, 900);
LobPongApp.setTitle("Lob Pong");
LobPongApp.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
LobPongApp.setVisible(true);
canvas.setFocusable(true);
LobPongApp.addKeyListener(canvas);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.GREEN);
g.fillOval((int) xCoordinate, (int) yCoordinate, 50, 50);
g.fillRect(xPaddleLeft, yPaddle, 100, 10);
drawLife(g, getLife());
}
public LobPong() {
timer = new Timer(1, new timerCallBack());
timer.start();
setLayout(new FlowLayout());
scoreLabel.setOpaque(true);
timeLabel.setOpaque(true);
levelLabel.setOpaque(true);
scoreLabel.setBackground(Color.black);
timeLabel.setBackground(Color.black);
levelLabel.setBackground(Color.black);
scoreLabel.setForeground(Color.WHITE);
timeLabel.setForeground(Color.WHITE);
levelLabel.setForeground(Color.WHITE);
levelLabel.setText("Level: " + 1);
add(scoreLabel);
add(timeLabel);
add(levelLabel);
xPaddleLeft = 375; //debug
xCoordinate = 0;
yCoordinate = 0;
setTime(levelTime); //sets current level time (increases by 10 seconds every 2 levels)
}
public static void nextLevel(Graphics g, int levels) {
level += 1;
g.drawString("NEXT LEVEL!", 400, 400);
timer.stop();
//TODO call run() ?
}
public static void updateScore(int scoreAdd) {
score += scoreAdd;
scoreLabel.setText("Score: " + score);
}
public static int getScore() {
return score;
}
public static void updateLife(int x) {
life += x;
}
public static int getLife() {
return life;
}
public static void drawLife(Graphics g, int x) {
g.setColor(Color.RED);
for(int i = 0; i < (x * 10); i += 10) { //for loop to offset lives and draw enough balls per lives
g.fillOval(30 + i, 10, 10, 10);
}
}
public static void extraLife(boolean x) {
if (x == true) {
updateLife(1);
}
}
Timer timerDisplay = new Timer(1000, new TimerListener());
private static int totalTime;
public static void setTime(int time) {
totalTime = time;
}
public static int getTime() {
return totalTime;
}
protected class TimerListener implements ActionListener { //handles countdown timer
#Override
public void actionPerformed(ActionEvent arg0) {
setTime(getTime() - 1000);
LobPong.timeLabel.setText("Time Remaining: " + getTime()/1000 + " ");
if(getTime() <= 0) {
timerDisplay.stop();
timer.stop();
}
}
}
public void keyPressed(KeyEvent arg0) {
int key = arg0.getKeyCode();
System.out.println("testing");
if(key == 37) {
if (xPaddleLeft > 0) {
xPaddleLeft -= 50;
System.out.println("TEST"); //debug
}
}
if(key == 39) {
if (xPaddleLeft < (getWidth() - 50)) {
xPaddleLeft += 50;
}
}
if(key == KeyEvent.VK_ENTER) {
dx = 2;
timer.start();
timerDisplay.start();
System.out.println("start"); //debug
}
repaint();
}
boolean horizontal = true; //handles horizontal movement
boolean vertical = true; //handles vertical
double upwards;
public class timerCallBack implements ActionListener {
#Override
public void actionPerformed(ActionEvent arg0) {
times += .01;
if (horizontal == true) { //check
xCoordinate += dx;
}
if(xCoordinate <= 0) { //check
horizontal = true;
}
if(xCoordinate >= getWidth()) { //check
horizontal = false;
}
if(horizontal == false) { //check
xCoordinate -= dx;
}
if(vertical == true) { //check
dy = (int) times;
yCoordinate += dy;
}
if (vertical == false) { //check
dy = (int) (upwards - times);
yCoordinate -= dy;
}
if(dy == 0) { //check
vertical = true;
times = 0;
}
if(yCoordinate == getHeight()) { //check
updateLife(-1);
if (getLife() == 0) {
timer.stop();
timerDisplay.stop();
//TODO you lose and print high score
}
extraLife(false);
xCoordinate = 0;
yCoordinate = 0;
dy = 0;
dx = 0;
vertical = true;
}
if(xCoordinate <= (xPaddleLeft + 100) && xCoordinate >= xPaddleLeft && (yCoordinate + 50) == yPaddle) {
upwards = times;
times = 0;
vertical = false;
updateScore(1);
repaint();
//TODO plus one point, paddle bounce physics, direction
}
repaint();
}
}
#Override
public void keyReleased(KeyEvent arg0) {
// TODO Auto-generated method stub
}
#Override
public void keyTyped(KeyEvent arg0) {
// TODO Auto-generated method stub
}
}

Ball is moving all the way to the left of the screen when I don't want it to

Whenever I tell the rectangle to go left, it moves al the way to the left side of the screen when I only want it to move a little bit. And whenever I tell it to move right, it wont move at all. What am I doing wrong?
public class Balls {
private static final int MOVE_SPEED_X = 2;
private int x, y, width, height, velX, velY;
private Rectangle rect;
public Balls(int x, int y, int height, int width) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
velX = 0;
}
public void update() {
y += 3;
}
public void reset() {
y = 0;
}
public void accelLeft() {
x = -MOVE_SPEED_X;
}
public void accelRight() {
x = +MOVE_SPEED_X;
}
}
Second Block of relevant code
public class PlayState extends State {
private Paddle paddleRight, paddleLeft;
private static final int PADDLE_WIDTH = 30;
private static final int PADDLE_HEIGHT = 60;
private Ball ball;
private Balls balls;
// bDiam stands for ball diameter
private static int bDiam = 30;
private int playerScore = 0;
private Font scoreFont;
#Override
public void init() {
paddleLeft = new Paddle(0, 195, PADDLE_WIDTH, PADDLE_HEIGHT);
paddleRight = new Paddle(785, 195, PADDLE_WIDTH, PADDLE_HEIGHT);
scoreFont = new Font("SansSerif", Font.BOLD, 25);
//ball = new Ball(300, 200, bDiam, bDiam);
balls = new Balls(500, 0, bDiam, bDiam);
}
#Override
public void onClick(MouseEvent e) {
// bDiam = bDiam + 20;
}
#Override
public void update() {
balls.update();
if (balls.getY() > GameMain.GAME_HEIGHT) {
balls.reset();
}
}
#Override
public void onKeyPress (KeyEvent e){
if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
balls.accelRight();
}
if (e.getKeyCode() == KeyEvent.VK_LEFT) {
balls.accelLeft();
}
}
}
In accelLeft it should be x = x - MOVE_SPEED_X (and similar in accelRight)

SubKiller game not firing properly when press my fire key

I have the following program, it's a SubKiller game and I have one question. How do I make the boat launch the bomb anytime I press the down key? So far I have made to launch it multiple times. I can launch the first bomb but when I'm trying to launch the second one, the first one disappears and it doesn't continue it's way. I am stuck on this matter for almost two days, help me please.
I am going to provide you the SSCCE code.
This is the class called SubKillerPanel, basically everything is here, the boat is here, the bomb is here, the submarine is here.
import java.awt.event.*;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.Color;
public class SubKillerPanel extends JPanel {
private static final long serialVersionUID = 1L;
private Timer timer;
private int width, height;
private Boat boat;
private Bomb bomb;
private Submarine sub;
public SubKillerPanel() {
setBackground(Color.WHITE);
ActionListener action = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (boat != null) {
boat.updateForNewFrame();
bomb.updateForNewFrame();
sub.updateForNewFrame();
}
repaint();
}
};
timer = new Timer( 20, action );
addMouseListener( new MouseAdapter() {
public void mousePressed(MouseEvent evt) {
requestFocus();
}
}
);
addFocusListener( new FocusListener() {
public void focusGained(FocusEvent evt) {
timer.start();
repaint();
}
public void focusLost(FocusEvent evt) {
timer.stop();
repaint();
}
}
);
addKeyListener( new KeyAdapter() {
public void keyPressed(KeyEvent evt) {
int code = evt.getKeyCode(); // ce tasta a fost apasata
if (code == KeyEvent.VK_LEFT) {
boat.centerX -= 15;
}
else
if (code == KeyEvent.VK_RIGHT) {
boat.centerX += 15;
}
else
if (code == KeyEvent.VK_DOWN) {
if (bomb.isFalling == false)
bomb.isFalling = true;
bomb.centerX = boat.centerX;
bomb.centerY = boat.centerY;
}
}
}
);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
if (boat == null) {
width = getWidth();
height = getHeight();
boat = new Boat();
sub = new Submarine();
bomb = new Bomb();
}
if (hasFocus())
g.setColor(Color.CYAN);
else {
g.setColor(Color.RED);
g.drawString("CLICK TO ACTIVATE", 20, 30);
g.setColor(Color.GRAY);
}
g.drawRect(0,0,width-1,height-1);
g.drawRect(1,1,width-3,height-3);
g.drawRect(2,2,width-5,height-5);
boat.draw(g);
sub.draw(g);
bomb.draw(g);
}
private class Boat {
int centerX, centerY;
Boat() {
centerX = width/2;
centerY = 80;
}
void updateForNewFrame() {
if (centerX < 0)
centerX = 0;
else
if (centerX > width)
centerX = width;
}
void draw(Graphics g) {
g.setColor(Color.blue);
g.fillRoundRect(centerX - 40, centerY - 20, 80, 40, 20, 20);
}
}
private class Bomb {
int centerX, centerY;
boolean isFalling;
Bomb() {
isFalling = false;
}
void updateForNewFrame() {
if (isFalling) {
if (centerY > height) {
isFalling = false;
}
else
if (Math.abs(centerX - sub.centerX) <= 36 && Math.abs(centerY - sub.centerY) <= 21) {
sub.isExploding = true;
sub.explosionFrameNumber = 1;
isFalling = false; // Bomba reapare in barca
}
else {
centerY += 10;
}
}
}
void draw(Graphics g) {
if ( !isFalling ) {
centerX = boat.centerX;
centerY = boat.centerY + 23;
}
g.setColor(Color.RED);
g.fillOval(centerX - 8, centerY - 8, 16, 16);
}
}
private class Submarine {
int centerX, centerY;
boolean isMovingLeft;
boolean isExploding;
int explosionFrameNumber;
Submarine() {
centerX = (int)(width*Math.random());
centerY = height - 40;
isExploding = false;
isMovingLeft = (Math.random() < 0.5);
}
void updateForNewFrame() {
if (isExploding) {
explosionFrameNumber++;
if (explosionFrameNumber == 30) {
centerX = (int)(width*Math.random());
centerY = height - 40;
isExploding = false;
isMovingLeft = (Math.random() < 0.5);
}
}
else {
if (Math.random() < 0.04) {
isMovingLeft = ! isMovingLeft;
}
if (isMovingLeft) {
centerX -= 5;
if (centerX <= 0) {
centerX = 0;
isMovingLeft = false;
}
}
else {
centerX += 5;
if (centerX > width) {
centerX = width;
isMovingLeft = true;
}
}
}
}
void draw(Graphics g) {
g.setColor(Color.BLACK);
g.fillOval(centerX - 30, centerY - 15, 60, 30);
if (isExploding) {
g.setColor(Color.YELLOW);
g.fillOval(centerX - 4*explosionFrameNumber, centerY - 2*explosionFrameNumber,
8*explosionFrameNumber, 4*explosionFrameNumber);
g.setColor(Color.RED);
g.fillOval(centerX - 2*explosionFrameNumber, centerY - explosionFrameNumber/2,
4*explosionFrameNumber, explosionFrameNumber);
}
}
}
}
The SubKiller class, where the main method is located.
import javax.swing.JFrame;
public class SubKiller {
public static void main(String[] args) {
JFrame window = new JFrame("Sub Killer Game");
SubKillerPanel content = new SubKillerPanel();
window.setContentPane(content);
window.setSize(700, 700);
window.setLocation(0,0);
window.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
window.setResizable(false);
window.setVisible(true);
}
}
You only have a single Bomb being tracked by the graphics at any time. You should build a collection of Bombs and instantiate a new one whenever the down key is pressed, then iterate through all the collection of Bombs and draw them as needed.
So, instead of private Bomb bomb;
You would have private List<Bomb> bombs;
Afterwards, anywhere you update the single bomb you can use a for loop to go through the list of bombs and have them all update, and then if they are no longer being drawn, remove them from the list.

Java: MouseListener does not register when objects move on screen

I am making a simple game where a red ball and a blue ball move across the screen at a random speed along the x-axis (and a constant speed across the y axis). The player scores points by clicking on the balls, which resets their position and adds points to the player's score based on the speed the ball was moving along the x-axis. I have implemented a MouseListener to track the player's actions. When the ball movement is commented out, the MouseListener registers everything perfectly. When the balls are allowed to move, the MouseListener will only register at seemingly random intervals. I don't believe it is a hit detection problem anymore, because the program plays a sound whether you hit or you miss, and when the MouseListener is failing to register no sound plays.
Code:
Main Class
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class Main extends Applet implements Runnable, MouseListener{
private static final long serialVersionUID = 7526472295622776147L;
private int speed;
boolean isStopped=true;
private Player player;
private Ball redball;
private Ball blueball;
Thread t;
AudioClip shotnoise;
AudioClip hitnoise;
AudioClip outnoise;
Font f = new Font ("Serif", Font.BOLD, 20);
Cursor c;
private Image dbImage;
private Graphics dbg;
public void init(){
this.addMouseListener(this);
setSize(400,400);
c=new Cursor(Cursor.CROSSHAIR_CURSOR);
this.setCursor(c);
setBackground (Color.black);
setFont (f);
if (getParameter ("speed") != null)
{
speed = Integer.parseInt(getParameter("speed"));
}
else speed = 15;
hitnoise = getAudioClip (getCodeBase() , "gun.au");
hitnoise.play();
hitnoise.stop();
shotnoise = getAudioClip (getCodeBase() , "miss.au");
shotnoise.play();
shotnoise.stop();
outnoise = getAudioClip (getCodeBase() , "error.au");
outnoise.play();
outnoise.stop();
player = new Player ();
redball = new Ball (10, 190, 250, 1, -1, 4, Color.red, outnoise, player);
blueball = new Ball (10, 190, 150, 1, 1, 3, Color.blue, outnoise, player);
}
public void start ()
{
t = new Thread (this);
t.start ();
}
public void stop ()
{
}
public void run(){
Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
while(true){
if(player.getLives()>=0 && !isStopped){
redball.move();
blueball.move();
}
repaint();
try{
Thread.sleep(speed);
}
catch(InterruptedException e){
}
Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
}
}
public void paint(Graphics g){
if(player.getLives()>=0){
g.setColor(Color.yellow);
g.drawString("Score: " + player.getScore(),10,40);
g.drawString("Lives: "+ player.getLives(), 300, 40);
redball.DrawBall(g);
blueball.DrawBall(g);
if(isStopped){
g.setColor(Color.yellow);
g.drawString("Double Click to Start",40, 200);
}
}
else if(player.getLives()<0){
g.setColor(Color.yellow);
g.drawString("Game Over!",130,100);
g.drawString("You Scored: "+player.getScore()+"Points!",90, 140);
if (player.getScore() < 300) g.drawString ("Well, it could be better!", 100, 190);
else if (player.getScore() < 600 && player.getScore() >= 300) g.drawString ("That was not so bad", 100, 190);
else if (player.getScore() < 900 && player.getScore() >= 600) g.drawString ("That was really good", 100, 190);
else if (player.getScore() < 1200 && player.getScore() >= 900) g.drawString ("You seem to be very good!", 90, 190);
else if (player.getScore() < 1500 && player.getScore() >= 1200) g.drawString ("That was nearly perfect!", 90, 190);
else if (player.getScore() >= 1500) g.drawString ("You are the Champingon!",100, 190);
g.drawString("Double Click on the Applet to Play Again!",20,220);
isStopped=true;
}
}
public void update(Graphics g){
if(dbImage==null){
dbImage=createImage(this.getSize().width,this.getSize().height);
dbg=dbImage.getGraphics();
}
dbg.setColor(getBackground());
dbg.fillRect(0,0,this.getSize().width,this.getSize().height);
dbg.setColor(getForeground());
paint(dbg);
g.drawImage(dbImage,0,0,this);
}
public void mouseClicked(MouseEvent e){
if(!isStopped){
if(redball.userHit(e.getX(),e.getY())){
hitnoise.play();
redball.wasHit();
}
else if (blueball.userHit (e.getX(),e.getY())){
hitnoise.play();
blueball.wasHit();
}
else{
shotnoise.play();
}
}
else if(isStopped&&e.getClickCount()==2){
isStopped=false;
init();
}
}
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
public void mousePressed(MouseEvent e){
}
public void mouseReleased(MouseEvent e){
}
}
Ball Class
import java.applet.*;
import java.awt.*;
import java.util.*;
public class Ball{
private int x_pos;
private int y_pos;
private int x_speed;
private int y_speed;
private int radius;
private int first_x;
private int first_y;
private int max_speed;
private final int x_leftout = 10;
private final int x_rightout = 370;
private final int y_upout = 45;
private final int y_downout = 370;
Color color;
AudioClip out;
Player player;
Random rnd=new Random();
public Ball(int radius, int x, int y, int vx, int vy, int ms, Color color, AudioClip out, Player player){
this.radius=radius;
x_pos=x;
y_pos=y;
first_x=x;
first_y=y;
x_speed=vx;
y_speed=vy;
max_speed = ms;
this.color = color;
this.out = out;
this.player = player;
}
public void move(){
x_pos+= x_speed;
y_pos+=y_speed;
isOut();
}
public void wasHit(){
x_pos = first_x;
y_pos = first_y;
x_speed = (rnd.nextInt ()) % max_speed;
}
private boolean isOut(){
if(x_pos>x_rightout){
x_pos=first_x;
y_pos=first_y;
out.play();
x_speed=(rnd.nextInt())%max_speed;
player.looseLife();
return true;
}
else if(x_pos<x_leftout){
x_pos=first_x;
y_pos=first_y;
out.play();
x_speed=(rnd.nextInt())%max_speed;
player.looseLife();
return true;
}
else if(y_pos>y_downout){
x_pos=first_x;
y_pos=first_y;
out.play();
x_speed=(rnd.nextInt())%max_speed;
player.looseLife();
return true;
}
else if(y_pos<y_upout){
x_pos=first_x;
y_pos=first_y;
out.play();
x_speed=(rnd.nextInt())%max_speed;
player.looseLife();
return true;
}
else return false;
}
public boolean userHit(int mouse_x, int mouse_y){
int dx=Math.abs(x_pos-mouse_x);
int dy=Math.abs(y_pos-mouse_y);
if(dx>radius){
return false;
}
else if(dy>radius){
return false;
}
else{
player.AddScore(10*Math.abs(x_speed)+10);
return true;
}
}
public void DrawBall (Graphics g)
{
g.setColor (color);
g.fillOval (x_pos - radius, y_pos - radius, 2*radius, 2*radius);
}
}
Player Class
public class Player{
private int lives;
private int score;
public Player(){
lives=10;
score=0;
}
public int getScore(){
return score;
}
public int getLives(){
return lives;
}
public void looseLife(){
lives--;
}
public void AddScore(int points){
score+=points;
}
}

Categories

Resources