Why does the height of the rectangle's jump vary? It seems to go in a cycle. First it jumps low then it doesn't jump at all then it jumps high then it doesn't jump at all. i can't figure out why as the same code is used and it is triggered by the same event.
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.KeyEvent;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
#SuppressWarnings("serial")
class Game extends JPanel{
Square square = new Square(this);
Ground ground = new Ground (this);
public Game() {
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
square.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
square.keyPressed(e);
}
});
setFocusable(true);
}
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("My Mario");
Game game = new Game();
frame.add(game);
frame.setSize(600, 700);
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
while (true) {
game.move();
game.repaint();
Thread.sleep(30);
}
}
private void move() {
square.move();
}
#Override
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
square.paint(g2d);
ground.paint(g2d);
}
}
public class Square {
Square square;
int x,xa;
static int y;
int ya;
private Game game;
public static int fistX,fistY;
static int d = 60;
int wide;
boolean onGround;
public Square(Game game) {
this.game = game;
x = 100;
y = 631;
xa = 0;
ya = 0;
onGround = false;
wide = game.getWidth();
}
public void move() {
if (x + xa > 0 && x + xa < game.getWidth()-30)
x = x + xa;
if (y + ya > 0 && y + ya < game.getHeight()-60){
for(int i=12; i< 0; i--);
ya+=10;
y = y + ya;
}
if ( collision() ) {
y-=10;
onGround = true;
}
Square.y+=10;
}
public void paint(Graphics2D g) {
g.setColor(Color.RED);
g.fillRoundRect(x, y-d, 30, d, 10, 10);
}
private boolean collision() {
return game.ground.getBounds().intersects(getBounds());
}
public Rectangle getBounds() {
return new Rectangle(x, y, 30, 60);
}
public void keyReleased(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa=0;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa=0;
if(e.getKeyCode() == KeyEvent.VK_DOWN)
d = 60;
if(e.getKeyCode() == KeyEvent.VK_UP);
}
public void keyPressed(KeyEvent e) {
// TODO Auto-generated method stub
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = xa -3;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = xa + 3;
if(e.getKeyCode() == KeyEvent.VK_DOWN)
d = 30;
if(e.getKeyCode() == KeyEvent.VK_UP)
ya -= 60;
}
}
class Ground {
int y,x,h,w;
public Ground(Game game){
x = 0;
y = game.getHeight()-30;
w = game.getWidth();
h = 30;
}
public void paint(Graphics2D g){
g.setColor(Color.BLACK);
g.fillRect(0, 700, 99999999, 30);
}
public Rectangle getBounds() {
return new Rectangle(0, 700, 99999999, 30);
}
}
Don't block the EDT (Event Dispatch Thread) - the GUI will 'freeze' when that happens. Instead of calling Thread.sleep(n) implement a Swing Timer for repeated tasks like animation. See Concurrency in Swing for more details.
frame.setSize(600, 700); I recommend instead setting a preferred size for the content and packing the frame around it. This suggests a constant size for the game on different PLAFs or OS'.
For Swing components other than top-level containers (e.g JFrame or JWindow), override paintComponent(Graphics) rather than paint(Graphics).
Look into key bindings instead of key listeners for Swing.
The first 3 are implemented, the last one (and other one commented in the code) is TODO - BNI.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
class SuperMarioGame extends JPanel {
private static final long serialVersionUID = 1L;
Square square = new Square(this);
Ground ground = new Ground (this);
public SuperMarioGame() {
// TODO Update to Key Bindings
addKeyListener(new KeyListener() {
#Override
public void keyTyped(KeyEvent e) {
}
#Override
public void keyReleased(KeyEvent e) {
square.keyReleased(e);
}
#Override
public void keyPressed(KeyEvent e) {
square.keyPressed(e);
}
});
setFocusable(true);
// Use a listener/timer combo.
ActionListener gameAnimation = new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
move();
repaint();
}
};
Timer timer = new Timer(30,gameAnimation);
timer.start();
// Set a preferred size for the panel.
Dimension preferred = new Dimension(600,700);
this.setPreferredSize(preferred);
}
public static void main(String[] args) throws InterruptedException {
JFrame frame = new JFrame("My Mario");
SuperMarioGame game = new SuperMarioGame();
frame.add(game);
// Pack the frame to the preferred size.
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
private void move() {
square.move();
}
#Override
// for Swing components, generally override
// paintComponent rather than paint
//public void paint(Graphics g) {
public void paintComponent(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
square.paint(g2d);
ground.paint(g2d);
}
}
class Square {
Square square;
int x,xa;
static int y;
int ya;
private SuperMarioGame game;
public static int fistX,fistY;
static int d = 60;
int wide;
boolean onGround;
public Square(SuperMarioGame game) {
this.game = game;
x = 100;
y = 631;
xa = 0;
ya = 0;
onGround = false;
wide = game.getWidth();
}
public void move() {
if (x + xa > 0 && x + xa < game.getWidth()-30)
x = x + xa;
if (y + ya > 0 && y + ya < game.getHeight()-60){
for(int i=12; i< 0; i--);
ya+=10;
y = y + ya;
}
if ( collision() ) {
y-=10;
onGround = true;
}
Square.y+=10;
}
public void paint(Graphics2D g) {
g.setColor(Color.RED);
g.fillRoundRect(x, y-d, 30, d, 10, 10);
}
private boolean collision() {
return game.ground.getBounds().intersects(getBounds());
}
public Rectangle getBounds() {
return new Rectangle(x, y, 30, 60);
}
public void keyReleased(KeyEvent e) {
// TODO Else-if would be better here..
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa=0;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa=0;
if(e.getKeyCode() == KeyEvent.VK_DOWN)
d = 60;
if(e.getKeyCode() == KeyEvent.VK_UP);
}
public void keyPressed(KeyEvent e) {
// TODO Else-if would be better here..
if (e.getKeyCode() == KeyEvent.VK_LEFT)
xa = xa -3;
if (e.getKeyCode() == KeyEvent.VK_RIGHT)
xa = xa + 3;
if(e.getKeyCode() == KeyEvent.VK_DOWN)
d = 30;
if(e.getKeyCode() == KeyEvent.VK_UP)
ya -= 60;
}
}
class Ground {
int y,x,h,w;
public Ground(SuperMarioGame game){
x = 0;
y = game.getHeight()-30;
w = game.getWidth();
h = 30;
}
public void paint(Graphics2D g){
g.setColor(Color.BLACK);
g.fillRect(0, 700, 99999999, 30);
}
public Rectangle getBounds() {
return new Rectangle(0, 700, 99999999, 30);
}
}
Don't block the Event Dispatching Thread any way, it will prevent the EDT from processing repaint requests (and other events) which will make it look like your program has crashed. Have a read of Concurrency in Swing for more information.
Only modify the UI from the EDT, NEVER from any other thread, this includes creating UI elements
Favor key bindings over KeyListeners, they are more capable of resolving focus issues amongst other things. Have a read of How to Use Key Bindings for more details
Favor overriding paintComponent rather then paint. Paint does a lot of important work which you should avoid messing with if you can. Apart from any thing else paintComponent is going to be included in the double buffering of the component where as paint isn't (as super.paint sets it up)
Avoid using static state variables where possible
I don't know if this was deliberate or not, but, for (int i = 12; i < 0; i--); isn't going to achive anything, as the semi colen at the end means, do nothing for a count of 1
Personally, try not to use absolute values for things like width and height, which is actually reliant on parent container. You should also, where possible, provide sizing hints to allow the parent container to make better decisions on how much space it actually needs
UPDATED
Fixed bug in my movement code :P
I had a look at your collision detection code (in move) and, frankly, couldn't make heads or tails of it. I corrected it as well as changed in the way the paint method works so that x,y is always the top, left corner
public class TestGame {
public static void main(String[] args) throws InterruptedException {
new TestGame();
}
public TestGame() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
Game game = new Game();
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(game);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class GameThread extends Thread {
private Game game;
public GameThread(Game game) {
setDaemon(false);
this.game = game;
}
#Override
public void run() {
while (true) {
game.move();
try {
long startedAt = System.currentTimeMillis();
SwingUtilities.invokeAndWait(new Runnable() {
#Override
public void run() {
game.repaint();
}
});
long completedAt = System.currentTimeMillis();
long sleepFor = 30 - (completedAt - startedAt);
if (sleepFor < 0) {
sleepFor = 30;
}
Thread.sleep(sleepFor);
} catch (Exception exp) {
exp.printStackTrace();
}
}
}
}
public class Game extends JPanel {
Square square = new Square(this);
Ground ground = new Ground(this);
public Game() {
// addKeyListener(new KeyListener() {
// #Override
// public void keyTyped(KeyEvent e) {
// }
//
// #Override
// public void keyReleased(KeyEvent e) {
// square.keyReleased(e);
// }
//
// #Override
// public void keyPressed(KeyEvent e) {
// square.keyPressed(e);
// }
// });
setFocusable(true);
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, false), "press-left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, false), "press-right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "press-down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "press-up");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, 0, true), "release-left");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, 0, true), "release-right");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "release-down");
im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "release-up");
am.put("press-left", new PressLeftAction(square));
am.put("press-right", new PressRightAction(square));
am.put("press-down", new PressDownAction(square));
am.put("press-up", new PressUpAction(square));
am.put("release-left", new ReleaseLeftAction(square));
am.put("release-right", new ReleaseRightAction(square));
am.put("release-down", new ReleaseDownAction(square));
am.put("release-up", new ReleaseUpAction(square));
new GameThread(this).start();
// public void keyReleased(KeyEvent e) {
//
//
//
// if (e.getKeyCode() == KeyEvent.VK_LEFT) {
// xa = 0;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
// xa = 0;
// }
// if (e.getKeyCode() == KeyEvent.VK_DOWN) {
// d = 60;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_UP);
// }
//
// public void keyPressed(KeyEvent e) {
//// TODO Auto-generated method stub
// if (e.getKeyCode() == KeyEvent.VK_LEFT) {
// xa = xa - 3;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
// xa = xa + 3;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_DOWN) {
// d = 30;
// }
//
// if (e.getKeyCode() == KeyEvent.VK_UP) {
// ya -= 60;
// }
//
//
//
//
//
// }
}
public void move() {
square.move();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(400, 400);
}
// Don't override paint, use paintComponent instead
// #Override
// public void paint(Graphics g) {
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
square.paint(g2d);
ground.paint(g2d);
g2d.dispose();
}
}
public class Square {
Square square;
private int x, xa;
// static int y;
private int y;
private int ya;
private Game game;
// public static int fistX, fistY;
private int fistX, fistY;
// static int d = 60;
private int d = 60;
private int wide;
private boolean onGround;
public Square(Game game) {
this.game = game;
x = 100;
y = 100;
xa = 0;
ya = 0;
onGround = false;
wide = game.getWidth();
}
public void move() {
y += ya;
x += xa;
if (x < 0) {
x = 0;
} else if (x + 30 > game.getWidth()) {
x = game.getWidth() - 30;
}
if (y < 0) {
y = 0;
} else if (collision()) {
onGround = true;
y = game.ground.getBounds().y - d;
}
// if (x + xa > 0 && x + xa < game.getWidth() - 30) {
// x = x + xa;
// }
//
// if (y + ya > 0 && y + ya < game.getHeight() - 60) {
// // This was never going to do anything, look at the
// // end of the line...the `;` is going to prevent the
// // statemt ya += 10 from begin called within the loop
//// for (int i = 12; i < 0; i--);
// for (int i = 12; i < 0; i--) {
// ya += 10;
// }
// y = y + ya;
// }
// if (collision()) {
// y -= 10;
// onGround = true;
//
// }
//
// y += 10;
}
public void paint(Graphics2D g) {
g.setColor(Color.RED);
System.out.println(x + "x" + (y - d));
g.fillRoundRect(x, y, 30, d, 10, 10);
}
private boolean collision() {
return game.ground.getBounds().intersects(getBounds());
}
public Rectangle getBounds() {
return new Rectangle(x, y, 30, 60);
}
}
public class Ground {
private Game game;
public Ground(Game game) {
this.game = game;
}
public void paint(Graphics2D g) {
g.setColor(Color.BLACK);
g.fillRect(0, game.getHeight() - 30, game.getWidth(), 30);
}
public Rectangle getBounds() {
return new Rectangle(0, game.getHeight() - 30, game.getWidth(), 30);
}
}
public abstract class AbstractSquareAction extends AbstractAction {
private Square square;
public AbstractSquareAction(Square square) {
this.square = square;
}
public Square getSquare() {
return square;
}
}
public class PressLeftAction extends AbstractSquareAction {
public PressLeftAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().xa = -3;
System.out.println("pressLeft");
}
}
public class PressRightAction extends AbstractSquareAction {
public PressRightAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().xa = 3;
}
}
public class PressDownAction extends AbstractSquareAction {
public PressDownAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().ya = 30;
}
}
public class PressUpAction extends AbstractSquareAction {
public PressUpAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().ya -= 30;
}
}
public class ReleaseLeftAction extends AbstractSquareAction {
public ReleaseLeftAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().xa = 0;
}
}
public class ReleaseRightAction extends AbstractSquareAction {
public ReleaseRightAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().xa = 0;
}
}
public class ReleaseDownAction extends AbstractSquareAction {
public ReleaseDownAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().ya = 0;
}
}
public class ReleaseUpAction extends AbstractSquareAction {
public ReleaseUpAction(Square square) {
super(square);
}
#Override
public void actionPerformed(ActionEvent e) {
getSquare().ya = 0;
}
}
}
Related
I am trying to create a snake clone just as a practice. ive drawn the snake and added the movement patterns but the snake eats on it self when I press any key to move. but its not moving. the array retracts the reactacles on the starting point and does nothing.
here is my snake class I have removed my comments as they where more than the code and the posting system was not allowing me to post
Edit
If you need anything from the other classes please let me know. but I think my error is somewhere in here
EDIT 2
Added the entire code, you can just copy paste in inside a new project and you will reproduce my error.
public class Snake {
List<Point> sPoints;
int xDir,yDir;
boolean isMoving,addTail;
final int sSize = 20, startX = 150 , startY = 150;
public Snake(){
sPoints = new ArrayList<Point>();
xDir = 0;
yDir = 0;
isMoving = false;
addTail = false;
sPoints.add(new Point(startX,startY));
for(int i=1; i<sSize; i++) {
sPoints.add(new Point(startX - i * 4,startY));
}
}
public void draw(Graphics g){
g.setColor(Color.white);
for(Point p : sPoints) {
g.fillRect(p.getX(),p.getY(),4,4);
}
}
public void move(){
if (isMoving) {
Point temp = sPoints.get(0);
Point last = sPoints.get(sPoints.size() - 1);
Point newstart = new Point(temp.getX() + xDir * 4, temp.getY() + yDir * 4);
for (int i = sPoints.size() - 1; i >= 1; i--) {
sPoints.set(i, sPoints.get(i - 1));
}
sPoints.set(0, newstart);
}
}
public int getxDir() {
return xDir;
}
public void setxDir(int x) {
this.xDir = xDir;
}
public int getyDir() {
return yDir;
}
public void setyDir(int y) {
this.yDir = yDir;
}
public int getX(){
return sPoints.get(0).getX();
}
public int getY(){
return sPoints.get(0).getY();
}
public boolean isMoving() {
return isMoving;
}
public void setIsMoving(boolean b) {
isMoving = b;
}
}
The following is the point class. just some getters setters for the points ,for those i used the IntelliJ to auto generate them.. (again i removed comments )
public class Point {
private int x,y;
public Point() {
x = 0;
y = 0;
}
public Point(int x, int y) {
this.x =x;
this.y =y;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
and finally my main class called game.
in here what I do is create my applet give it background color. create my threat for the runnable. and also add the movement patterns for up/right/down/left...
and use several classes to update my drawing patterns so it can simulate movement by updating each of state of my rect list.
import java.applet.Applet;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class Game extends Applet implements Runnable, KeyListener {
//setting up double buffering.
Graphics graphics;
Image img;
Thread thread;
Snake snake;
public void init() {
//setting the size of our Applet
this.resize(400,400);
//we gonna create the image just the same size as our applet.
img = createImage(400,400);
//this represents our offscreen image that we will draw
graphics = img.getGraphics();
this.addKeyListener(this);
snake = new Snake();
thread = new Thread(this);
thread.start();
}
public void paint(Graphics g) {
//Setting the background of our applet to black
graphics.setColor(Color.black);
//Fill rectangle 0 , 0 (starts from) for top left corner and then 400,400 to fill our entire background to black
graphics.fillRect(0,0,400,400);
snake.draw(graphics);
//painting the entire image
g.drawImage(img,0,0,null);
}
//Update will call on Paint(g)
public void update(Graphics g){
paint(g);
}
//Repaint will call on Paint(g)
public void repaint(Graphics g){
paint(g);
}
public void run() {
//infinite loop
for(;;) {
snake.move();
//drawing snake
this.repaint();
//Creating a time delay
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void keyTyped(KeyEvent keyEvent) {
}
public void keyPressed(KeyEvent keyEvent) {
if(!snake.isMoving()){ //this will allow the snake to start moving, but will disable LEFT for just the 1st move
if(keyEvent.getKeyCode() == KeyEvent.VK_UP || keyEvent.getKeyCode() == KeyEvent.VK_RIGHT ||
keyEvent.getKeyCode() == KeyEvent.VK_DOWN ) {
snake.setIsMoving(true);
}
}
//setting up Key mapping so when the user presses UP,RIGHT,DOWN,LEFT. the Snake will move accordingly
if(keyEvent.getKeyCode() == KeyEvent.VK_UP) {
if (snake.getyDir() != 1) {
snake.setyDir(-1);
snake.setxDir(0);
}
}
if(keyEvent.getKeyCode() == KeyEvent.VK_RIGHT) {
if (snake.getxDir() != -1) {
snake.setxDir(1);
snake.setyDir(0);
}
}
if(keyEvent.getKeyCode() == KeyEvent.VK_DOWN) {
if (snake.getyDir() != -1) {
snake.setyDir(1);
snake.setxDir(0);
}
}
if(keyEvent.getKeyCode() == KeyEvent.VK_LEFT) {
if (snake.getxDir() != 1) {
snake.setxDir(-1);
snake.setyDir(0);
}
}
}
public void keyReleased(KeyEvent keyEvent) {
}
}
Here is some opinion I have reading your code.
The reason your snake won't move is because your snake.setyDir() and
snake.setxDir() didn't take the input to overwrite xDir and yDir. They are assigning to itself.
There is a Point2D class ready for you in JDK
When moving the snake, you just need to remove the tail and add one
more block before the head. You can keep the body tight (according
to my common knowledge to snake).
Consider a L shape snake on the left, the bottom end is the head and it is currently heading right. To move the snake, remove the tail (green block) and add one more to the head according to its direction (red block). It final state become the snake on the right. LinkedList suit the needs.
If using two int (xDir and yDir) to control the snake direction
is confusing, you can help your self by creating a enum. Those -1,
0, 1 with x and y may confuse you.
Declare constant instead of magic number. e.g. the width of block 4,
image size 400
Is Snake.addTail unnecessary?
Attribute should has accessibility modifier
End result:
Game.java
import java.applet.Applet;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Arrays;
public class Game extends Applet implements Runnable, KeyListener {
private final int GAMEBOARD_WIDTH = 400;
// setting up double buffering.
private Graphics graphics;
private Image img;
private Thread thread;
private Snake snake;
public void init() {
// setting the size of our Applet
this.resize(GAMEBOARD_WIDTH, GAMEBOARD_WIDTH);
// we gonna create the image just the same size as our applet.
img = createImage(GAMEBOARD_WIDTH, GAMEBOARD_WIDTH);
// this represents our offscreen image that we will draw
graphics = img.getGraphics();
this.addKeyListener(this);
snake = new Snake();
thread = new Thread(this);
thread.start();
}
public void paint(Graphics g) {
// Setting the background of our applet to black
graphics.setColor(Color.BLACK);
// Fill rectangle 0 , 0 (starts from) for top left corner and then 400,400 to
// fill our entire background to black
graphics.fillRect(0, 0, GAMEBOARD_WIDTH, GAMEBOARD_WIDTH);
snake.draw(graphics);
// painting the entire image
g.drawImage(img, 0, 0, null);
}
// Update will call on Paint(g)
public void update(Graphics g) {
paint(g);
}
// Repaint will call on Paint(g)
public void repaint(Graphics g) {
paint(g);
}
public void run() {
// infinite loop
for (;;) {
snake.move();
// drawing snake
this.repaint();
// Creating a time delay
try {
Thread.sleep(40);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void keyTyped(KeyEvent keyEvent) {
}
public void keyPressed(KeyEvent keyEvent) {
int keyCode = keyEvent.getKeyCode();
if (!snake.isMoving()) {
// this will allow the snake to start moving, but will disable LEFT for just the
// 1st move
if (matchKey(keyCode, KeyEvent.VK_UP, KeyEvent.VK_RIGHT, KeyEvent.VK_DOWN)) {
snake.setIsMoving(true);
}
}
// setting up Key mapping so when the user presses UP,RIGHT,DOWN,LEFT. the Snake
// will move accordingly
if (matchKey(keyCode, KeyEvent.VK_UP)) {
snake.setDirection(Direction.UP);
}
if (matchKey(keyCode, KeyEvent.VK_RIGHT)) {
snake.setDirection(Direction.RIGHT);
}
if (matchKey(keyCode, KeyEvent.VK_DOWN)) {
snake.setDirection(Direction.DOWN);
}
if (matchKey(keyCode, KeyEvent.VK_LEFT)) {
snake.setDirection(Direction.LEFT);
}
}
// return true if targetKey contains the provided keyCode
private boolean matchKey(int keyCode, int... targetKey) {
return Arrays.stream(targetKey).anyMatch(i -> i == keyCode);
}
public void keyReleased(KeyEvent keyEvent) {
}
}
Snake.java
import java.awt.Color;
import java.awt.Graphics;
import java.awt.geom.Point2D;
import java.util.LinkedList;
public class Snake {
private final int sSize = 20, startX = 150, startY = 150;
private final int BLOCK_WIDTH = 4;
private LinkedList<Point2D.Float> sPoints;
private boolean isMoving;
private Direction direction;
public Snake() {
sPoints = new LinkedList<Point2D.Float>();
isMoving = false;
sPoints.add(new Point2D.Float(startX, startY));
for (int i = 1; i < sSize; i++) {
sPoints.add(new Point2D.Float(startX - i * BLOCK_WIDTH, startY));
}
}
public void draw(Graphics g) {
g.setColor(Color.white);
for (Point2D p : sPoints) {
g.fillRect((int) p.getX(), (int) p.getY(), BLOCK_WIDTH, BLOCK_WIDTH);
}
}
public void move() {
if (isMoving) {
sPoints.removeLast();
steer(sPoints.getFirst());
}
}
private void steer(Point2D head) {
Point2D.Float newHead = new Point2D.Float();
switch (this.getDirection()) {
case UP:
newHead.setLocation(head.getX(), head.getY() - BLOCK_WIDTH);
break;
case DOWN:
newHead.setLocation(head.getX(), head.getY() + BLOCK_WIDTH);
break;
case LEFT:
newHead.setLocation(head.getX() - BLOCK_WIDTH, head.getY());
break;
case RIGHT:
newHead.setLocation(head.getX() + BLOCK_WIDTH, head.getY());
break;
}
this.sPoints.addFirst(newHead);
}
public int getX() {
return (int) sPoints.get(0).getX();
}
public int getY() {
return (int) sPoints.get(0).getY();
}
public boolean isMoving() {
return isMoving;
}
public void setIsMoving(boolean b) {
isMoving = b;
}
public Direction getDirection() {
return direction;
}
public void setDirection(Direction d) {
if (this.getDirection() == null) {
this.direction = d;
} else if (!this.getDirection().isOpposite(d)) {
this.direction = d;
}
}
}
Direction.java
public enum Direction {
UP(-1), DOWN(1), LEFT(-2), RIGHT(2);
int vector;
Direction(int i) {
this.vector = i;
}
public boolean isOpposite(Direction d) {
return this.vector + d.vector == 0;
}
}
Snack.java
import java.awt.EventQueue;
import javax.swing.JFrame;
public class Snake extends JFrame {
public Snake() {
initUI();
}
private void initUI() {
add(new Board());
setResizable(false);
pack();
setTitle("Snake");
setLocationRelativeTo(null);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[] args) {
EventQueue.invokeLater(() -> {
JFrame ex = new Snake();
ex.setVisible(true);
});
}
}
Board.java
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Board extends JPanel implements ActionListener {
private final int B_WIDTH = 300;
private final int B_HEIGHT = 300;
private final int DOT_SIZE = 10;
private final int ALL_DOTS = 900;
private final int RAND_POS = 29;
private final int DELAY = 140;
private final int x\[\] = new int\[ALL_DOTS\];
private final int y\[\] = new int\[ALL_DOTS\];
private int dots;
private int apple_x;
private int apple_y;
private boolean leftDirection = false;
private boolean rightDirection = true;
private boolean upDirection = false;
private boolean downDirection = false;
private boolean inGame = true;
private Timer timer;
private Image ball;
private Image apple;
private Image head;
public Board() {
initBoard();
}
private void initBoard() {
addKeyListener(new TAdapter());
setBackground(Color.black);
setFocusable(true);
setPreferredSize(new Dimension(B_WIDTH, B_HEIGHT));
loadImages();
initGame();
}
private void loadImages() {
ImageIcon iid = new ImageIcon("src/resources/dot.png");
ball = iid.getImage();
ImageIcon iia = new ImageIcon("src/resources/apple.png");
apple = iia.getImage();
ImageIcon iih = new ImageIcon("src/resources/head.png");
head = iih.getImage();
}
private void initGame() {
dots = 3;
for (int z = 0; z < dots; z++) {
x\[z\] = 50 - z * 10;
y\[z\] = 50;
}
locateApple();
timer = new Timer(DELAY, this);
timer.start();
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
doDrawing(g);
}
private void doDrawing(Graphics g) {
if (inGame) {
g.drawImage(apple, apple_x, apple_y, this);
for (int z = 0; z < dots; z++) {
if (z == 0) {
g.drawImage(head, x\[z\], y\[z\], this);
} else {
g.drawImage(ball, x\[z\], y\[z\], this);
}
}
Toolkit.getDefaultToolkit().sync();
} else {
gameOver(g);
}
}
private void gameOver(Graphics g) {
String msg = "Game Over";
Font small = new Font("Helvetica", Font.BOLD, 14);
FontMetrics metr = getFontMetrics(small);
g.setColor(Color.white);
g.setFont(small);
g.drawString(msg, (B_WIDTH - metr.stringWidth(msg)) / 2, B_HEIGHT / 2);
}
private void checkApple() {
if ((x\[0\] == apple_x) && (y\[0\] == apple_y)) {
dots++;
locateApple();
}
}
private void move() {
for (int z = dots; z > 0; z--) {
x\[z\] = x\[(z - 1)\];
y\[z\] = y\[(z - 1)\];
}
if (leftDirection) {
x\[0\] -= DOT_SIZE;
}
if (rightDirection) {
x\[0\] += DOT_SIZE;
}
if (upDirection) {
y\[0\] -= DOT_SIZE;
}
if (downDirection) {
y\[0\] += DOT_SIZE;
}
}
private void checkCollision() {
for (int z = dots; z > 0; z--) {
if ((z > 4) && (x\[0\] == x\[z\]) && (y\[0\] == y\[z\])) {
inGame = false;
}
}
if (y\[0\] >= B_HEIGHT) {
inGame = false;
}
if (y\[0\] < 0) {
inGame = false;
}
if (x\[0\] >= B_WIDTH) {
inGame = false;
}
if (x\[0\] < 0) {
inGame = false;
}
if (!inGame) {
timer.stop();
}
}
private void locateApple() {
int r = (int) (Math.random() * RAND_POS);
apple_x = ((r * DOT_SIZE));
r = (int) (Math.random() * RAND_POS);
apple_y = ((r * DOT_SIZE));
}
#Override
public void actionPerformed(ActionEvent e) {
if (inGame) {
checkApple();
checkCollision();
move();
}
repaint();
}
private class TAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if ((key == KeyEvent.VK_LEFT) && (!rightDirection)) {
leftDirection = true;
upDirection = false;
downDirection = false;
}
if ((key == KeyEvent.VK_RIGHT) && (!leftDirection)) {
rightDirection = true;
upDirection = false;
downDirection = false;
}
if ((key == KeyEvent.VK_UP) && (!downDirection)) {
upDirection = true;
rightDirection = false;
leftDirection = false;
}
if ((key == KeyEvent.VK_DOWN) && (!upDirection)) {
downDirection = true;
rightDirection = false;
leftDirection = false;
}
}
}
}
So i started to learn Java and tried to create a basic pong game using java.awt.graphics.
After finishing it i saw that it was a lot of flickering to the point when the game was unplayable.
This is my main class named "pong"(What a creative name).
package pong;
import java.applet.Applet;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
public class pong extends Applet implements Runnable,KeyListener {
public static void main(String[] args){}
public final int W=700,L=500;
p1 player1;
p1 player2;
ball b;
Thread thread;
public void init() {
resize(W,L);
this.addKeyListener(this);
player2 = new p1(1);
b = new ball();
thread= new Thread(this);
player1 = new p1(2);
thread.start();
}
public void paint(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(0,0,W,L);
if(!(b.getX()<-10 || b.getX()>690)){
player1.draw(g);
b.draw(g);
player2.draw(g);
}else if(b.getX()<-10){
g.setColor(Color.WHITE);
g.drawString("Right Player Won!",350,250);
}else{
g.setColor(Color.WHITE);
g.drawString("Left Player Won!",350,250);
}
}
#Override
public void update(Graphics g){
paint(g);
}
public void run() {
for(;;){
player1.move();
player2.move();
b.move();
colitionchecker(1);
repaint();
try {
Thread.sleep(17);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void keyTyped(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_UP)
player1.setUp(true);
else if (e.getKeyCode()==KeyEvent.VK_DOWN)
player1.setDown(true);
else if(e.getKeyCode()==KeyEvent.VK_W)
player2.setUp(true);
else if(e.getKeyCode()==KeyEvent.VK_S)
player2.setDown(true);
}
public void keyReleased(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_UP)
player1.setUp(false);
else if (e.getKeyCode()==KeyEvent.VK_DOWN)
player1.setDown(false);
else if(e.getKeyCode()==KeyEvent.VK_W)
player2.setUp(false);
else if(e.getKeyCode()==KeyEvent.VK_S)
player2.setDown(false);
}
public void colitionchecker(int num){
if(num == 1){
if(b.getX()<50 && b.getX()>20 && b.getY()>player2.getY() &&
b.getY()>=player2.getY()-80){
b.xv=-b.xv;
}
else{
if(b.getX()<700 && b.getX()>660 && b.getY()>=player1.getY() && b.getY()<=player1.getY()+80){
b.xv=-b.xv;
}
}
}
}
}
package pong;
import java.awt.*;
public class p1 implements paddle{
final double GRAVITY = 0.94;
double y=210,yv;
boolean up,down;
int player,x;
public p1(int player){
up=false; down=false;
if(player==1)
x=20;
else
x=660;
}
#Override
public void draw(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(x, (int)y,20,80);
}
public void move() {
if (up){
yv -= 2;
}else if (down){
yv += 2;
}else if (!down && !up){
yv *= GRAVITY;
}
if(yv>=15)
yv=5;
else if(yv<=-5)
yv=-5;
y += yv;
if(y<=0)
y=0;
else if(y>=420)
y=420;
}
public void setUp(boolean up) {
this.up = up;
}
public void setDown(boolean down) {
this.down = down;
}
public int getY() {
return (int)y;
}
}
package pong;
import java.awt.*;
public class ball {
double xv, yv, x, y;
public ball(){
x = 350;
y = 250;
xv = 2;
yv = 1;
}
public int getY() {
return (int)y;
}
public int getX() {
return (int)x;
}
public void move(){
x+=xv;
y+=yv;
if(y<10)
yv=-yv;
if(y>490)
yv=-yv;
}
public void draw(Graphics g){
g.setColor(Color.WHITE);
g.fillOval((int)x-10,(int)y-10,20,20);
}
}
package pong;
import java.awt.*;
public interface paddle {
public void draw(Graphics g);
public int getY();
public void move();
}
I am really lost and any help will be much appreciated.
Thanks.
So i started to learn Java
So your first lesson is, Applets are dead - better to spend your time else where, either using Swing or JavaFX windows based UIs.
Applet is not double buffered, hence the flicker, both Swing and JavaFX, if used correctly are.
I'd also discourage you from using a Thread in this way, as most GUI frameworks are not thread safe
I'd recommend having a look at:
Creating a GUI With JFC/Swing
Getting Started with JavaFX
as a basic starting point
Swing based solution
Because I can do it quickly...
KeyListener is a poor choice which is going to haunt you, better to use the Key Bindings API, which has been designed to overcome its limitations
Things you're going to have to read up on...
2D Graphics
How to Use Key Bindings
How to Use Swing Timers
And as an overall basic example
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ActionMap;
import javax.swing.InputMap;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.KeyStroke;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class Test {
public static void main(String[] args) {
new Test();
}
public Test() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private DefaultPaddle player1;
private DefaultPaddle player2;
private Ball b;
public TestPane() {
setBackground(Color.BLACK);
player1 = new DefaultPaddle(1);
player2 = new DefaultPaddle(2);
b = new Ball();
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, false), "Player1.up.pressed", new UpAction(player1, true));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_UP, 0, true), "Player1.up.released", new UpAction(player1, false));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, false), "Player1.down.pressed", new DownAction(player1, true));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, 0, true), "Player1.down.released", new DownAction(player1, false));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, false), "Player2.up.pressed", new UpAction(player2, true));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_W, 0, true), "Player2.up.released", new UpAction(player2, false));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, false), "Player2.down.pressed", new DownAction(player2, true));
addKeyBinding(KeyStroke.getKeyStroke(KeyEvent.VK_S, 0, true), "Player2.down.released", new DownAction(player2, false));
Timer timer = new Timer(5, new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
player1.move();
player2.move();
b.move();
// colitionchecker(1);
repaint();
}
});
timer.start();
}
protected void addKeyBinding(KeyStroke ks, String name, Action action) {
InputMap im = getInputMap(WHEN_IN_FOCUSED_WINDOW);
ActionMap am = getActionMap();
im.put(ks, name);
am.put(name, action);
}
public void colitionchecker(int num) {
if (num == 1) {
if (b.getX() < 50 && b.getX() > 20 && b.getY() > player2.getY()
&& b.getY() >= player2.getY() - 80) {
b.xv = -b.xv;
} else {
if (b.getX() < 700 && b.getX() > 660 && b.getY() >= player1.getY() && b.getY() <= player1.getY() + 80) {
b.xv = -b.xv;
}
}
}
}
#Override
public Dimension getPreferredSize() {
return new Dimension(700, 500);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g.create();
g2d.setColor(Color.BLACK);
// if (!(b.getX() < -10 || b.getX() > 690)) {
player1.draw(g);
b.draw(g);
player2.draw(g);
// } else if (b.getX() < -10) {
// g.setColor(Color.WHITE);
// g.drawString("Right Player Won!", 350, 250);
// } else {
// g.setColor(Color.WHITE);
// g.drawString("Left Player Won!", 350, 250);
// }
g2d.dispose();
}
}
public class UpAction extends AbstractAction {
private DefaultPaddle paddle;
private boolean pressed;
public UpAction(DefaultPaddle paddle, boolean pressed) {
this.paddle = paddle;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
System.out.println("Up " + pressed);
paddle.setUp(pressed);
}
}
public class DownAction extends AbstractAction {
private DefaultPaddle paddle;
private boolean pressed;
public DownAction(DefaultPaddle paddle, boolean pressed) {
this.paddle = paddle;
this.pressed = pressed;
}
#Override
public void actionPerformed(ActionEvent e) {
paddle.setDown(pressed);
}
}
public interface Paddle {
public void draw(Graphics g);
public int getY();
public void move();
}
public class DefaultPaddle implements Paddle {
final double GRAVITY = 0.94;
double y = 210, yv;
boolean up, down;
int player, x;
public DefaultPaddle(int player) {
up = false;
down = false;
if (player == 1) {
x = 20;
} else {
x = 660;
}
}
#Override
public void draw(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(x, (int) y, 20, 80);
}
public void move() {
if (up) {
yv -= 1;
} else if (down) {
yv += 1;
} else if (!down && !up) {
yv *= GRAVITY;
}
if (yv >= 15) {
yv = 5;
} else if (yv <= -5) {
yv = -5;
}
y += yv;
if (y <= 0) {
y = 0;
} else if (y >= 420) {
y = 420;
}
}
public void setUp(boolean up) {
this.up = up;
}
public void setDown(boolean down) {
this.down = down;
}
public int getY() {
return (int) y;
}
}
public class Ball {
double xv, yv, x, y;
public Ball() {
x = 350;
y = 250;
xv = 2;
yv = 1;
}
public int getY() {
return (int) y;
}
public int getX() {
return (int) x;
}
public void move() {
x += xv;
y += yv;
if (y < 10) {
yv = -yv;
}
if (y > 490) {
yv = -yv;
}
}
public void draw(Graphics g) {
g.setColor(Color.WHITE);
g.fillOval((int) x - 10, (int) y - 10, 20, 20);
}
}
}
I am creating a simple game where shapes fall and the player shoots them, but I am having problems creating bullet at every click of the mouse. I have tried various logic with no help, so am just going to put the code up here so you guys can take a look at it and help me out.
The bullet I created is not been created on every click just one is created and it moves on every click which is wrong........I want one bullet to be created per click.
// My main class: mousework2
import java.awt.event.*;
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.awt.geom.*;
public class mousework2 extends JFrame
{
public static int Width = 300;
public static int Height = 400;
private JPanel p1;
private Image pixMage,gunMage;
public mousework2()
{
super("shoot-em-up");
this.setSize(Width, Height);
this.setResizable(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Dimension pos = Toolkit.getDefaultToolkit().getScreenSize();
int x = (pos.width - Width) / 2;
int y = (pos.height - Height) / 2;
this.setLocation(x, y);
p1 = new CreateImage();
this.add(p1);
this.getContentPane();
Thread t = new recMove(this);
t.start();
}
class recMove extends Thread
{
JFrame b;
public recMove(JFrame b)
{
this.b = b;
}
public void run()
{
while (true) {
b.repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
}
}
}
}
class CreateImage extends JPanel implements MouseListener
{
ArrayList<fallShape> rect = new ArrayList<fallShape>();
int x_pos = mousework.Width / 2;
int y_pos = mousework.Height - 50;
int bx_pos = mousework.Width / 2;
int by_pos = mousework.Height;
int y_speed = -10;
boolean clicked;
public CreateImage()
{
for (int i = 0; i < 10; i++) {
rect.add(new fallShape(15, 15, rect));
}
Toolkit picx = Toolkit.getDefaultToolkit();
gunMage = picx.getImage("gunner.jpg");
gunMage = gunMage.getScaledInstance(200, -1, Image.SCALE_SMOOTH);
Toolkit pic = Toolkit.getDefaultToolkit();
pixMage = pic.getImage("ballfall3.jpg");
pixMage = pixMage.getScaledInstance(200, -1, Image.SCALE_SMOOTH);
addMouseListener(this);
addMouseMotionListener(new MouseMotionAdapter() {
#Override
public void mouseMoved(MouseEvent e)
{
x_pos = e.getX() - 5;
}
});
}
public void mousePressed(MouseEvent e)
{
if (e.getButton() == 1) {
clicked = true;
}
}
public void mouseReleased(MouseEvent e)
{
if (e.getButton() == 1) {
clicked = false;
}
}
public void mouseExited(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseClicked(MouseEvent e)
{
}
public void paint(Graphics g)
{
super.paint(g);
g.drawImage(pixMage, 0, 0, Width, Height, null);
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.drawImage(gunMage,x_pos,y_pos,10,20,null);
if (clicked) {
by_pos += y_speed;
Shape bullet = new Rectangle2D.Float(bx_pos, by_pos, 3, 10);
g2.setColor(Color.BLACK);
g2.fill(bullet);
g2.draw(bullet);
}
g2.setColor(Color.RED);
for (fallShape b : rect) {
b.move();
g2.fill(b);
}
}
}
public static void main(String[] args)
{
java.awt.EventQueue.invokeLater(new Runnable() {
#Override
public void run()
{
new mousework2().setVisible(true);
}
});
}
}
And:
// My falling shapes class: fallShape
import java.awt.geom.*;
import java.util.*;
public class fallShape extends Rectangle2D.Float
{
public int x_speed, y_speed;
public int l, b;
public int height = mousework.Height;
public int width = mousework.Width;
public ArrayList<fallShape> fall;
public fallShape(int breadth, int length, ArrayList<fallShape> fall)
{
super((int) (Math.random() * (mousework.Width - 20) + 1), 0, breadth, length);
this.b = breadth;
this.l = length;
this.x_speed = (int) Math.random() * (10) + 1;
this.y_speed = (int) Math.random() * (10) + 1;
this.fall = fall;
}
public void move()
{
Rectangle2D rec = new Rectangle2D.Float(super.x, super.y, b, l);
for (fallShape f : fall) {
if (f != this && f.intersects(rec)) {
int rxspeed = x_speed;
int ryspeed = y_speed;
x_speed = f.x_speed;
y_speed = f.y_speed;
f.x_speed = rxspeed;
f.y_speed = ryspeed;
}
}
if (super.x < 0) {
super.x =+ super.x;
//super.y =+ super.y;
x_speed = Math.abs(x_speed);
}
if (super.x> mousework.Width - 30) {
super.x =+ super.x;
super.y =+ super.y;
x_speed =- Math.abs(x_speed);
}
if (super.y < 0) {
super.y = 0;
y_speed = Math.abs(y_speed);
}
super.x += x_speed;
super.y += y_speed;
}
}
if(clicked){
by_pos+=y_speed;
This code only draws the bullet when the mouse is down. This is because you are setting clicked to false in your mouseReleased method:
public void mouseReleased(MouseEvent e){
if(e.getButton()==1)
clicked=false;
}
If you were to remove the body of the mouseReleased method, your bullet would move properly.
However, say you wanted to have more than just one bullet. Currently, your paint method only draws one bullet at a time. To draw multiple bullets, you would need to create a list of the coordinates of the bullets, and add a new coordinate pair to the list whenever you click. Then, in the paint method, just update each position in a for loop.
ArrayList<Integer> by_poss = new ArrayList<>();
by_poss is the list of all the y-positions of your bullets.
public void mousePressed(MouseEvent e){
if(e.getButton() == 1)
by_poss.add(mousework.Height);
}
The mousePressed method adds a new "bullet", in the form of a y-position, to the coordinates.
public void mouseReleased(MouseEvent e){
//do nothing
}
Nothing needs to happen in the mouseReleased method.
//update the bullets
public void paint(Graphics g){
...
g2.setColor(Color.BLACK);
Shape bullet;
for(int i = 0; i < by_poss.size(); i++){
by_poss.set(i, by_poss.get(i) + y_speed); //move the bullet
bullet = new Rectangle2D.Float(bx_pos, by_poss.get(i), 3, 10);
g2.fill(bullet);
g2.draw(bullet);
}
...
}
The for loop in your paint method draws all the bullets, one by one, usin g the y-positions from the by_poss list.
I've been asked to make a game for my CS (high school) class as my end of semester assignment. We haven't been taught properly all of the coding required to make a game so my knowledge in this area is very poor. Anyways, the game I am trying to make is something like "Flappy Fall" (an Apple appstore game) where objects fall from the top of the screen and descend to the bottom of the screen. The objective is to catch these objects before they reach the bottom. I am able to get one object to fall and have also created the "catcher", but I am not sure how to create multiple falling objects, nor do I know how to remove the object once it has been caught by the catcher. So far I have classes "JavaGame", "Catcher", and "Ball". Any help would be greatly appreciated.
int x, y;
int t = 1;
private Image dbImage;
private Graphics dbGraphics;
Image player;
Image bkg;
static Catcher p = new Catcher(150, 450);
public JavaGame() {
//Game Images
ImageIcon b = new ImageIcon("bkg.png");
bkg = b.getImage();
//Game properties
setTitle("Game");
setSize(350, 600);
setResizable(false);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
addKeyListener(new Keys());
addMouseMotionListener(new Mouse());
}
public void paint(Graphics g) {
//
dbImage = createImage(getWidth(), getHeight());
dbGraphics = dbImage.getGraphics();
draw(dbGraphics);
g.drawImage(dbImage, 0, 0, this);
}
public void draw(Graphics g) {
g.drawImage(bkg, 0, 0, this); //Creates background
p.draw(g);
//while (t < 100) {
p.b.draw(g);
//t++;
//}
g.setColor(Color.WHITE);
g.drawString(""+p.score, 175, 50);
repaint();
}
public static void main(String[] args) {
JavaGame jg = new JavaGame();
//Threads
Thread p1 = new Thread(p);
p1.start();
Thread ball = new Thread(p.b);
ball.start();
}
public class Keys extends KeyAdapter {
public void keyPressed(KeyEvent e) {
p.keyPressed(e);
}
public void keyReleased(KeyEvent e) {
p.keyReleased(e);
}
}
public class Mouse implements MouseMotionListener {
public void mouseDragged(MouseEvent e) {
p.mouseDragged(e);
}
public void mouseMoved(MouseEvent e) {
p.mouseMoved(e);
}
}
}
int x, y, ranX, xDirection;
int score;
Rectangle catch1;
Ball b = new Ball(170, 1);
public Catcher (int x, int y) {
score = 0;
this.x = x;
this.y = y;
catch1 = new Rectangle(this.x, this.y, 50, 15);
}
public void run() {
try {
while(true) {
move();
Thread.sleep(5);
}
}
catch(Exception e) {
System.out.println("Error");
}
}
public void collision() {
if (b.ball.intersects(catch1)) {
b.ball(Color.blue);
score++;
System.out.println(score);
}
}
public void move() {
collision();
catch1.x += xDirection;
if (catch1.x <= 0)
catch1.x = 0;
if (catch1.x >= 300)
catch1.x = 300;
}
public void setXDirection(int xDir) {
xDirection = xDir;
}
public void keyPressed(KeyEvent m) {
int keyCode = m.getKeyCode();
if (keyCode == m.VK_LEFT) {
setXDirection(-1);
}
if (keyCode == m.VK_RIGHT) {
setXDirection(+1);
}
m.consume();
}
public void keyReleased(KeyEvent m) {
int keyCode = m.getKeyCode();
if (keyCode == m.VK_LEFT) {
setXDirection(0);
}
if (keyCode == m.VK_RIGHT) {
setXDirection(0);
}
m.consume();
}
public void mouseDragged(MouseEvent e) {
catch1.x = e.getX()-25;
e.consume();
}
public void mouseMoved(MouseEvent e) {
catch1.x = e.getX()-25;
e.consume();
}
public void draw(Graphics g) {
g.fillRect(catch1.x, catch1.y, catch1.width, catch1.height);
}
}
int x, y, yDirection;
Rectangle ball;
public Ball (int x, int y) {
this.x = x;
this.y = y;
ball = new Rectangle(this.x, this.y, 10, 10);
}
public void run() {
try{
while(true) {
move();
Thread.sleep(5);
}
}
catch(Exception e) {
System.out.println("Error");
}
}
public void move() {
if (ball.y >= 600) {
ball.y = 600;
}
if (ball.y > 0) {
ball.y++;
}
}
public void setYDirection(int yDir) {
yDirection = yDir;
}
public void draw(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(ball.x, ball.y, ball.width, ball.height);
System.out.println(ball.x+ " "+ ball.y+ " " + ball.width + " " + ball.height);
}
}
I'd re-organize the code a little. In the main game, you can have a collection of 'Ball' types. I'll leave the collection option up to you. But you'll want to add 'new' Balls to the collection and then remove them once they are caught.
Since I do not want to do your assignment, I am just giving a short answer:
By calling new Ball() multiple times.
Of course you might want to add them to a collection, like
List list = new ArrayList();
list.add(ball);
And remove them from that collection once they are finished.
I want to add 2 buttons to the following code that will let me "FREEZE" and "START" the ball move as it bounces on the window. I've been trying to do this for the last hour but I cant figure this out. I did some work but it mostly crap, if anyone wants please let me know to post it(avoided it in order not to extend my coding). Anyone can help me with this?
Open to any suggestions.
Thanks
import java.awt.*;
import javax.swing.*;
public class BallMoves extends JPanel implements Runnable {
Color color = Color.red;
int dia = 30;
long delay = 40;
private int x = 1;
private int y = 1;
private int dx = 3;
private int dy = 7;
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
g.fillOval(x,y,30,30); // adds color to circle
g.setColor(Color.red);
g2.drawOval(x,y,30,30); // draws circle
}
public void run() {
while(isVisible()) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move();
repaint();
}
}
public void move() {
if(x + dx < 0 || x + dia + dx > getWidth()) {
dx *= -1;
color = getColor();
}
if(y + dy < 0 || y + dia + dy > getHeight()) {
dy *= -1;
color = getColor();
}
x += dx;
y += dy;
}
private Color getColor() {
int rval = (int)Math.floor(255);
int gval = (int)Math.floor(0);
int bval = (int)Math.floor(0);
return new Color(rval, gval, bval);
}
private void start() {
while(!isVisible()) {
try {
Thread.sleep(25);
} catch(InterruptedException e) {
System.exit(1);
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
public static void main(String[] args) {
BallMoves test = new BallMoves();
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(test);
f.setSize(400,400);
f.setLocation(200,200);
f.setVisible(true);
test.start();
}
}
Update version
import java.awt.*;
import java.awt.event.ActionEvent;
import javax.swing.*;
public class BallMoves extends JPanel implements Runnable {
Color color = Color.red;
int dia = 30;
long delay = 40;
private int x = 1;
private int y = 1;
private int dx = 3;
private int dy = 7;
private boolean isRunning;
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2 = (Graphics2D)g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g.setColor(color);
g.fillOval(x,y,30,30); // adds color to circle
g.setColor(Color.red);
g2.drawOval(x,y,30,30); // draws circle
}
public void run() {
while(isVisible()) {
try {
Thread.sleep(delay);
} catch(InterruptedException e) {
System.out.println("interrupted");
}
move();
repaint();
}
}
public void move() {
if (isRunning) {
if(x + dx < 0 || x + dia + dx > getWidth()) {
dx *= -1;
color = getColor();
}
if(y + dy < 0 || y + dia + dy > getHeight()) {
dy *= -1;
color = getColor();
}
x += dx;
y += dy;
}
}
private Color getColor() {
int rval = (int)Math.floor(255);
int gval = (int)Math.floor(0);
int bval = (int)Math.floor(0);
return new Color(rval, gval, bval);
}
private void start() {
while(!isVisible()) {
try {
Thread.sleep(25);
} catch(InterruptedException e) {
System.exit(1);
}
}
Thread thread = new Thread(this);
thread.setPriority(Thread.NORM_PRIORITY);
thread.start();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
final BallMoves test = new BallMoves();
JFrame f = new JFrame();
JButton start = new JButton("start");
start.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
test.isRunning = true;
}
});
JButton stop = new JButton("stop");
stop.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent arg0) {
test.isRunning = false;
}
});
JPanel panel = new JPanel();
panel.add(start);
panel.add(stop);
f.add(panel, java.awt.BorderLayout.NORTH);
f.getContentPane().add(test);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(new Dimension(400, 400));
f.setLocationRelativeTo(null);
f.setVisible(true);
test.start();
}
});
}
}
Create a flag and switch it on button click.
private volatile boolean isRunning;
public void move() {
if (isRunning) {
// your existing code
...
}
}
on start button click
isRunning = true;
on stop button click
isRunning = false;