I just start learning Java. I write a program like this:
Bacteria.class
import java.awt.*;
public class Bacteria extends Creature{
public static final int COLOR_STEP = 256/MAX_AGE;
Bacteria(Board board, int _x, int _y){
super.board = board;
//initialize age, x, y
super.age = 1;
super.x = _x;
super.y = _y;
}
//Draw a circle representing the creature at its position
//This function is done.
public void draw(Graphics g) {
g.setColor(new Color(0, COLOR_STEP * age, 0));
g.fillOval(x * board.CELL_SIZE, y * board.CELL_SIZE, board.CELL_SIZE, board.CELL_SIZE);
}
public void tick() {
//your code
// this is how the creature lives in one tick
// make the creature get older if it is not dead.
// if it's got older than MAX_AGE then it should die
// ...call board.addDead() to register the dead creature
// if it can have baby then try reproduce()
age++;
if (this.canHaveBaby()) {
this.reproduce();
}
//this.reproduce();
if (age > MAX_AGE) {
board.addDead(this);
}
}
}
Creature.class
import java.awt.*;
public class Creature {
public static final int MAX_AGE = 5;
public Board board;
public int age; // age of the creature measures in ticks
public int x; // (x,y) is the position of the creature
public int y;
Creature(Board board, int _x, int _y) {
this.board = board;
//initialize age, x, y
age = 1;
x = _x;
y = _y;
}
public Creature() {
}
//Draw a circle representing the creature at its position
//This function is done.
public void draw(Graphics g){}
public void tick(){}
public void reproduce() {
//your code
// if it can have a baby then produce a baby
// ...in an empty cell next to its cell.
// board.emptyCell() should be used
// ....to check whether a cell in the board is empty
// and call board.addBaby() to place the baby to the board
//int x_current = x, y_current = y;
if(board.emptyCell(x, y+1)){
Creature baby = new Creature(board,x, y+1);
//System.out.println("1");
board.addBaby( baby);
}
else if(board.emptyCell(x+1,y)){
Creature baby = new Creature(board,x+1, y);
board.addBaby(baby);
}
else if(board.emptyCell(x+1,y+1)){
Creature baby = new Creature(board,x+1, y+1);
board.addBaby(baby);
}
else if(board.emptyCell(x-1,y)){
Creature baby = new Creature(board,x-1, y);
board.addBaby(baby);
}
else if(board.emptyCell(x,y-1)){
Creature baby = new Creature(board,x, y-1);
board.addBaby(baby);
}
else if(board.emptyCell(x-1,y-1)){
Creature baby = new Creature(board,x-1, y-1);
board.addBaby(baby);
}
else if(board.emptyCell(x-1,y+1)){
Creature baby = new Creature(board,x-1, y+1);
board.addBaby(baby);
}
else if(board.emptyCell(x+1,y-1)){
Creature baby = new Creature(board,x+1, y-1);
board.addBaby(baby);
}
}
public boolean canHaveBaby() {
//your code
// if the creature is dead or it is too young
// then it cannot have a baby
if(age == 0 || age > MAX_AGE){
return false;
}
return true;
}
public boolean atPosition(int _x, int _y) {
//your code
// return true if the creature is at the position (_x,_y)
// you need this function for board.empty to function correctly
if(_x == x && _y == y){
return true;
}
return false;
}
}
Board.class
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class Board extends JPanel {
public static final int CELL_SIZE = 10;
private final int rows = 10;
private final int cols = 20;
ArrayList<Creature> creatureList;
ArrayList<Creature> babies, dead;
// ArrayList<Bacteria> bacteriaList;
// ArrayList<Bacteria> babies_bac, dead_bac;
Board() {
super();
setBackground(Color.white);
creatureList = new ArrayList<Creature>();
//creatureList.size();
babies = new ArrayList<Creature>();
dead = new ArrayList<Creature>();
setPreferredSize(new Dimension(cols * CELL_SIZE, rows * CELL_SIZE));
creatureList.add(new Bacteria(this, 1, 1));
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
for (Creature creature: creatureList) {
creature.draw(g);
}
}
public void tick() {
dead = new ArrayList<Creature>();
babies = new ArrayList<Creature>();
for (Creature creature: creatureList) {
creature.tick();
}
creatureList.addAll(babies);
creatureList.removeAll(dead);
}
public void addBaby(Creature baby) {
if (baby != null) babies.add(baby);
}
public void addDead(Creature deadCreature) {
if (deadCreature != null) dead.add(deadCreature);
}
public boolean emptyCell(int x, int y) {
if (x < 0 || y < 0 || x >= cols || y >= rows) return false;
for (Creature creature : creatureList) {
if (creature.atPosition(x, y)) {
return false;
}
}
for (Creature creature : creatureList) {
if (creature.atPosition(x, y)) {
return false;
}
}
return true;
}
public String getPopulation() {
return String.format("%d", creatureList.size());
}
}
and BacteriaSimulator.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class BacteriaSimulator extends JFrame {
private Board board;
private JLabel label;
public BacteriaSimulator() {
initUI();
setTitle("Bacteria Simulator");
setSize(350, 200);
setLocationRelativeTo(null);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
private void initUI() {
JPanel panel = new JPanel();
board = new Board();
panel.add(board);
label = new JLabel(board.getPopulation());
panel.add(label);
JButton button = new JButton("Tick");
button.addActionListener(new ButtonNextListener());
panel.add(button);
add(panel);
pack();
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
BacteriaSimulator ex = new BacteriaSimulator();
ex.setVisible(true);
}
});
}
private class ButtonNextListener implements ActionListener {
#Override
public void actionPerformed(ActionEvent e) {
board.tick();
label.setText(board.getPopulation());
repaint();
}
}
}
I want Board.class work with creatureList. However, Board is still initialized with a bacteria (creatureList.add(new Bacteria(this, 1, 1));). I got a problem that is Board.class can not run draw() and tick() method which I want. How to draw objects bacteria and make the right method of tick ()? Can you help me! Thank you!
Your draw() and tick() functions are part of Bacteria.java. They cannot be used from Board.java unless you create an instance of Bacteria and then invoke the methods using that.
Related
I'm making a top-down shooter game in java where I have a stationary player who can turn side to side and can shoot a gun at enemies that move to the center(where the player is). I have made different faces for each side when my player turns, but I'm not able to figure out how to switch the faces when I use the arrow keys. Here is my main panel:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
public class FinalPanel extends JPanel
{
private static final int FRAME = 1600;
private static final Color BACKGROUND = new Color(255, 255, 255);
private Player player;
private ImageIcon faces;
private ImageIcon playerFace = new ImageIcon("PlayerUpImage.png");
private BufferedImage myImage;
private Graphics myBuffer;
private Timer timer;
public FinalPanel()
{
myImage = new BufferedImage(FRAME, FRAME, BufferedImage.TYPE_INT_RGB);
myBuffer = myImage.getGraphics();
addKeyListener(new Key());
setFocusable(true);
}
private class Listener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
ImageIcon player = new ImageIcon("PlayerUpImage.png");
myBuffer.drawImage(player.getImage(), 800, 800, null);
repaint();
}
}
public void paintComponent(Graphics g)
{
super.paintComponenet(g);
g.drawImage(myImage, 0, 0, getWidth(), getHeight(), null);
}
private class Key extends KeyAdapter//The arrow keys make the player change directions and it replaces his face with a different animation to show the change in direction
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_W)
{
playerFace = new ImageIcon("PlayerUpImage.png");
}
if(e.getKeyCode() == KeyEvent.VK_S)
{
playerFace = new ImageIcon("PlayerDownImage.png");
}
if(e.getKeyCode() == KeyEvent.VK_A)
{
playerFace = new ImageIcon("PlayerLeftImage.png");
}
if(e.getKeyCode() == KeyEvent.VK_D)
{
playerFace = new ImageIcon("PlayerRightImage.png");
}
repaint();
}
}
}
Player class:
import java.awt.*;
import javax.swing.*;
public class Player
{
//Private fields for player class
private int myX;
private int myY;
private int myXWidth;
private int myYWidth;
public Player()
{
myX = 775;
myY = 775;
myXWidth = 50;
myYWidth = 50;
}
public Player(int x, int y, int xWidth, int yWidth)
{
myX = x;
myY = y;
myXWidth = xWidth;
myYWidth = yWidth;
}
//I borrowed this health code from: https://stackoverflow.com/questions/9834609/how-to-make-a-player-class-that-holds-lives-inheritance//
int liveCount = 10;
public boolean damage() {
--liveCount;
return isDead();
}
public boolean isDead() {
return liveCount < 1;
}
public void boostLives(int moreLives) {
liveCount += moreLives;
}
//Accessor Methods//
public int getX()
{
return myX;
}
public int getY()
{
return myY;
}
public int getXWidth()
{
return myXWidth;
}
public int getYWidth()
{
return myYWidth;
}
//Modifier Methods//
public void setX(int x)
{
myX = x;
}
public void setY(int y)
{
myY = y;
}
public void setXWidth(int xWidth)
{
myXWidth = xWidth;
}
public void setYWidth(int yWidth)
{
myYWidth = yWidth;
}
}
I have some suggestions that might help:
Don’t use the variable faces, instead, have an ImageIcon called playerFace with a default direction of up
private ImageIcon playerFace = new ImageIcon(“PlayerUpImage.png”);
Your paint method could then look like this
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(playerFace.getImage(), 800, 800, null);
}
In your keyPressed method, all you have to do is change the player image and call the method repaint so that the panel calls the paintComponent method again:
public void keyPressed(KeyEvent e) {
//pressed d for example
if(e.getKeyCode() == KeyEvent.VK_D)
playerFace = new ImageIcon(“PlayerImageRight.png”);
... //if else’s for other keys
repaint();
}
Preferably, you’d want to have playerFaces as an attribute of the Player class with a getter method to get the playerFace direction (so making playerFace a variable of Player). But this is to get you started
You’ll also want to set up a frame instead of using your current variable FRAME
public FinalPanel() {
JFrame frame = new JFrame();
frame.setSize(1600, 1600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(this);
frame.setVisible(true);
addKeyListener(new Key());
setFocusable(true);
}
I'm making an java app (for exercise) where there must be a panel and 2 buttons.
Each time you press the start button a ball must be displayed and it moves based on thread. The user can display all the way up to 10 independent balls.
By pressing the stop button, 1 ball must be removed with each time the stop button is pressed (example, when there is 4 balls, the user must press 4 times stop button to remove all the balls independently)
All the x- and y coordinates of the balls must be stored in a Matrix
When 1 or more ball(s) are colliding with each other, only the colliding balls must change color from red to blue
Ok I'm almost done with it completely ( from point 1 to 4 ), but here comes my problem. When a ball is colliding with another, instead of changing the colors of the colliding balls to blue, my code is changing all the balls color from red to blue. I know that my error lies at the new Balls().setColor(Color.Blue), but I have no idea how to change only the colliding balls.
Below follows a screen shot of the java app and the code.
Can anyone help me with this headache?
Printscreen:
source code:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;`
public class BouncingBalls extends JPanel implements ActionListener {
protected List<Ball> balls = new ArrayList<Ball>(10);
private final Container container;
private final DrawCanvas canvas;
private int canvasWidth;
private int canvasHeight;
public JButton start, stop;
int [][] coords= new int[11][2];
int ammountOfBalls = 0;
static Color clr= Color.RED;
public static int random(int maxRange) {
return (int) Math.round((Math.random() * maxRange));
}
public BouncingBalls(int width, int height) {
setLayout(new FlowLayout());
start= new JButton("start");
start.addActionListener(this);
stop= new JButton("stop");
stop.addActionListener(this);
add(start);
add(stop);
add(new JLabel(""));
container = new Container();
canvasWidth = width;
canvasHeight = height;
canvas = new DrawCanvas();
this.setLayout(new FlowLayout());
this.add(canvas);
start();
}
public void start() {
Thread t = new Thread() {
#Override
public void run() {
while (true) {
update();
getPositions();
collisionDetection();
repaint();
try {
Thread.sleep(30);
} catch (InterruptedException e) {
}
}
}
private void collisionDetection() {
// The algorithm that detects collision
for(int i=0;i<ammountOfBalls;i++){
for(int j=i+1; j<ammountOfBalls; j++){
if(collisionMethod(i,j)){ // my collision method
//HOW DO I CHANGE ONLY THE COLLIDING BALLS COLOR HERE????
new Ball().setColor(Color.BLUE); // this line here changes the color of all the balls on the panel
System.out.println("Its a hit");
}
}
}
}
private void getPositions() {
int row=0;
for (Ball ball : balls) {
int x =ball.getXPosition();
int y =ball.getYPosition();
coords[row][0]=x;
coords[row][1]=y;
row++;
}
}
private boolean collisionMethod(int i, int j) {
float xd = coords[i][0]-coords[j][0];
float yd=coords[i][1]-coords[j][1];
float radius= new Ball().ballRadius;
float sqrRadius= radius * radius;
float distSqr= (xd * xd) + (yd * yd);
if(distSqr <= sqrRadius)
return true;
return false;
}
};
t.start();
}
public void update() {
for (Ball ball : balls) {
ball.move(container);
}
}
#Override
public void actionPerformed(ActionEvent e) {
if(e.getSource() == start){
if(ammountOfBalls < 10){
// to limit the ammount of balls to 10
balls.add(new Ball());
ammountOfBalls++;
}
}
else if( e.getSource() == stop){
if(ammountOfBalls > 0){
ammountOfBalls --;
balls.remove(ammountOfBalls);
}
}
}
class DrawCanvas extends JPanel {
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
container.draw(g);
for (Ball ball : balls) {
ball.draw(g);
}
}
#Override
public Dimension getPreferredSize() {
return (new Dimension(700, 400));
}
}
public static void main(String[] args) {
JFrame f = new JFrame("Bouncing Balls");
f.setDefaultCloseOperation(f.EXIT_ON_CLOSE);
f.setPreferredSize(new Dimension(800,500));
f.setContentPane(new BouncingBalls(800,800));
f.pack();
f.setVisible(true);
}
public static class Ball {
public int random(int maxRange) {
return (int) Math.round(Math.random() * maxRange);
}
int x = random(700); // method to get random coords for the x-value
int y = random(400); // method to get random coords for the y-value ...... these are used to get random positions for the balls instead of only static
int xMovement = 10;
int yMovement = 10;
int ballRadius = 20;
int i = 0;
public Color getColor(){
return clr;
}
public Color setColor(Color color){
clr=color;
return clr;
}
public void draw(Graphics g) {
g.setColor(getColor());
g.fillOval(x,y,ballRadius,ballRadius);
}
public int getXPosition(){
return x;
}
public int getYPosition(){
return y;
}
public void move(Container container) {
x += xMovement;
y += yMovement;
if (x - ballRadius < 0) {
xMovement = -xMovement;
x = ballRadius;
}
else if (x + ballRadius > 700) {
xMovement = -xMovement;
x = 700 - ballRadius;
}
if (y - ballRadius < 0) {
yMovement = -yMovement;
y = ballRadius;
}
else if (y + ballRadius > 400) {
yMovement = -yMovement;
y = 400 - ballRadius;
}
}
}
public static class Container {
private static final int hightPanel = 800;
private static final int widthPanel= 800;
public void draw(Graphics g) {
g.setColor(Color.WHITE);
g.fillRect(0, 0, widthPanel, hightPanel);
}
}
}
`
You have defined clr as a static field of your application. When your Ball class calls setColor() you are changing the value of clr to blue... and then any Ball that calls getColor() will see that clr is blue.
Solution: Don't make clr an application-wide static field. Define it in the Ball class as a non-static field, so each Ball has its own color.
I have a very strange bug in my 2d game made using Java.
Description of the game: the player can move a rocket sprite with the mouse, and must dodge a rectangle that is going to follow the player and kill the player(by collision). Instead of following the player, it only moves to the beginning coordinates of the player, which is 400,400. It should move to the direction the player goes to. Please help me if you know what is wrong.
Main class:
import javax.swing.*;
public class Main extends JFrame{
private static final long serialVersionUID = 1L;
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("Space Game");
add(new GameClass());
setVisible(true);
}
public static void main(String[] args) {
new Main();
}
}
GameClass class:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class GameClass extends JPanel implements ActionListener, KeyListener{
private static final long serialVersionUID = 1L;
Enemy enemy = new Enemy();
Player player = new Player();
public GameClass(){
Timer time = new Timer(15, this);
time.start();
this.addKeyListener(this);
this.setFocusable(true);
player.openImage();
}
public void update(){
player.update();
enemy.update();
}
public void paintComponent(Graphics g){
g.setColor(Color.BLACK);
g.fillRect(0,0,Main.WW,Main.WH);
player.paint(g);
enemy.paint(g);
g.dispose();
}
public void actionPerformed(ActionEvent e){
update();
repaint();
}
public void keyPressed(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT){
player.setSpeed(-5);
}
else if(e.getKeyCode() == KeyEvent.VK_RIGHT){
player.setSpeed(5);
}
else if(e.getKeyCode() == KeyEvent.VK_UP){
player.setFly(-5);
}
else if(e.getKeyCode() == KeyEvent.VK_DOWN){
player.setFly(5);
Player.goDown = true;
}
}
public void keyReleased(KeyEvent e){
if(e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_RIGHT){
player.setSpeed(0);
}
if(e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() == KeyEvent.VK_DOWN){
player.setFly(0);
Player.goDown = false;
}
}
public void keyTyped(KeyEvent e){
}
}
Enemy class:
import java.awt.*;
public class Enemy {
private int x = -100;
private int y = -100;
Player player = new Player();
public void update(){
System.out.println(player.getX());
if(player.getX() < this.x){
this.x -= 5;
}
if(player.getX() > this.x){
this.x += 5;
}
if(player.getY() > this.y){
this.y += 5;
}
if(player.getY() < this.y){
this.y -= 5;
}
}
public void paint(Graphics g){
g.setColor(Color.ORANGE);
g.fillRect(x, y, 50, 50);
}
}
Player class:
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import java.awt.*;
public class Player {
private Image image;
private int player_x = Main.WW/2;
private int player_xspeed = 0;
private int player_y = Main.WH/2;
private int player_yspeed = 0;
private int flamey = player_y + 100;
private int flamex;
private int newx;
private int newy;
static boolean goDown = false;
public Player(){
newx = player_x;
newy = player_x;
}
public void openImage(){
try {
image = ImageIO.read(new File("spaceship.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
public void paint(Graphics g){
flamex = player_x + 20;
g.drawImage(image,player_x,player_y,null);
g.setColor(Color.YELLOW);
g.fillRect(flamex, flamey+5, 6, 6);
g.fillRect(flamex+10, flamey, 6, 6);
g.fillRect(flamex+10, flamey+15, 6, 6);
g.fillRect(flamex+20, flamey+5, 6, 6);
}
public void update(){
player_x += player_xspeed;
player_y += player_yspeed;
if(flamey < (player_y + 125)){
if(goDown == false)
flamey += 5;
else
flamey += 10;
}else
flamey = player_y + 100;
newx = player_x;
newy = player_y;
}
public void setSpeed(int speed){
player_xspeed = speed;
}
public void setFly(int speed){
player_yspeed = speed;
}
public int getX(){
return newx;
}
public int getY(){
return newy;
}
}
Sorry for bad English, please help me.
Any help appreaciated :)
It's because the Player it follows is created inside Enemy via the line:
public class Enemy {
//...
Player player = new Player();
//...
}
so it's a different player instance to the one you are controlling, which is created in GameClass via:
public class GameClass extends JPanel implements ActionListener, KeyListener{
Enemy enemy = new Enemy();
Player player = new Player();
//...
}
You need to inject the controlled player instance either as a constructor parameter on Enemy, e.g.
public class GameClass extends JPanel implements ActionListener, KeyListener{
Player player = new Player();
Enemy enemy = new Enemy(player);
//...
}
public class Enemy {
//...
Player player;
public Enemy(Player player) { this.player = player; }
//...
}
or via a setter.
I am writing a code of game bean machine(Galton box), its mechanism that one ball fall and move randomly until it get to one of the slots (randomly) and then another ball comes doing the same thing and so on, the problem is that all balls fall at the same time which something I do not want, I want each ball to fall when the current one finishes its travel..can anyone helps me ! Thanks..
here is the code:
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Random;
import java.util.Scanner;
import java.lang.Iterable;
import javax.swing.*;
public class BallPanel extends JPanel {
int x=1, y=1;
Collection <Ball> ball;
public static void main(String [] args){
// create the list
SwingUtilities.invokeLater(new Runnable() {
public void run() {
JFrame frame= new JFrame("Bean game");
frame.add(new BallPanel());
frame.setSize(300,500);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
}
});
}
public BallPanel() {
JPanel panel = new JPanel();
ball=new ArrayList<>();
for(int i=1;i<=4;i++){
ball.add(new Ball(x,y));
x++;
y++;
}
Timer timer = new Timer(400, new ActionListener()
{
public void actionPerformed(ActionEvent e) {
for (Ball b: ball) {
b.move();repaint();
}
}
});
timer.start();
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int raduis=10;
int i=0;
int width=(getWidth()/8);
int space=(getWidth()-8*30)/2;
g.setColor(Color.BLACK);
for(i=0;i<=8;i++){
g.drawLine(space+(30*i),getHeight()-5*(raduis) ,space+(30*i) ,getHeight() );
if(i!=0 && i!=8)
g.fillOval(space+(30*i)-5, getHeight()-5*(raduis)-5, 10, 10);
if(i==0){
g.drawLine(space,getHeight()-5*(raduis) , space+((8)*15)-(raduis/2)-15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2);
g.drawLine(space+((8)*15)-(raduis/2)-15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 , space+((8)*15)-(raduis/2)-15 , getHeight()/2-8*8);//vertical line
}
if(i==8){
g.drawLine(space+(30*i), getHeight()-5*(raduis), space+((8)*15)+(raduis/2)+15, getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2);
g.drawLine(space+((8)*15)+(raduis/2)+15 , getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 , space+((8)*15)+(raduis/2)+15 , getHeight()/2-8*8);//vertical line
}
}
int o=1;
for(i=1;i<=8-2;i++){
int k=2;
for(int j=i;j<=8-2;j++){
g.fillOval(space+((i+k)*15)-raduis/2, getHeight()-(5*raduis)-(30*o)-raduis/2, raduis, raduis);
k=k+2;
}o++;
}
for (Ball b : ball) {
b.draw(g);
}
}
public class Ball {
Random rand=new Random();
private int n;
private int raduis = 10;
private int moveRaduis=12;
private int L = 0;
private int R = 0;
private int D = 0;
int x, y;
public Ball(int x, int y){
this.x=x;
this.y=y;
}
public void draw(Graphics g) {
g.setColor(Color.RED);
g.fillOval(getWidth()/2 -raduis/2 + R + L, 0 + D , moveRaduis, moveRaduis);
}
public void move() {
n=1+rand.nextInt(100);
if(n<=51){
D+=15;
if(D<=(getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2))
L=0;
else if(D>getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 && D<getHeight()-5*(raduis))
{
D+=15;
L-=15;
}
else if(D>=getHeight()-5*(raduis))
{
if(D==31*15)D-=15;
D=D;
}
}
else if (n>=51 && n<=100){
D+=15;
if(D<=getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2)
R=0;
else if(D>getHeight()-15-(5*raduis)-(30*(8-2))-raduis/2 && D<getHeight()-5*(raduis))
{
D+=15;
R+=15;
}
else if(D>=getHeight()-5*(raduis)){
if(D==31*15)D-=15;
D=D;
}
}
}
}
}
So, your movement code moves all the balls on each iteration, what you need to do is have an "active" ball, for example...
private Ball activeBall;
Timer timer = new Timer(400, new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (activeBall != null && activeBall.hasCompleted()) {
activeBall = null;
}
if (activeBall == null && ball.size() > 0) {
activeBall = ball.remove(0);
}
if (activeBall != null) {
activeBall.move();
repaint();
}
}
});
You'll need to add in some kind of check to determine the ball has completed it's run though
*Note: * I'm new here. If you're going to downvote please tell me why.
I'm writing a java chess program using swing. I'm able to display the board, initialize pieces, and store them in a two dimensional array. However, I can't figure out how to display the pieces on my canvas. I keep getting a null pointer error on line 65 of class Piece.
*Update: * I've included some of the suggested changes. The null pointer error has cleared up, but I'm still having trouble getting the pieces to display. I don't think I've correctly pointed them at the canvas I created in class Chess.
My program is broken into three classes as follows:
Class Chess
import java.util.Scanner;
import javax.swing.*;
//import java.awt.*;
public class Chess {
public static final int WINDOW_WIDTH=600;
public static final int WINDOW_HEIGHT=600;
public static final int SQUARE_WIDTH = (WINDOW_WIDTH-10)/8;
public static final int SQUARE_HEIGHT = (WINDOW_HEIGHT-40)/8;
public static int position[][] = {};
public BoardComponent mycanvas= new BoardComponent(this);
public Chess()
{
JFrame mywindow;
mywindow=new JFrame("ChessMaster 2012");
mywindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mywindow.setSize(WINDOW_WIDTH, WINDOW_HEIGHT);
//BoardComponent mycanvas= new BoardComponent(this);
mywindow.add(mycanvas);
mywindow.setVisible(true); //window appears here
}
public static void main(String[] args) {
position = new int [8][8];
new Chess();
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
import javax.swing.ImageIcon;
public class Piece extends JPanel{
Piece[] mypiece;
public ImageIcon piece;
int nextID = 0;
BoardComponent board;
Chess chess;
public int locx, locy;
public void setCanvas(BoardComponent board)
{
this.board=board;
}
public Piece(char color, char Type, int posX, int posY){
// each piece assigned a PK on creation, beginning sequentially from top left
// and looping back to the beginning of each row
int pieceID = nextID;
char pieceColor = color;
char pieceType = Type;
posX = locx;
posY = locy;
// P = pawn, K = knight, R = Rook, B = Bishop, Q = Queen,
//S = king (can't reuse K, so we use S instead)
if (pieceType == 'P'){
new Pawn(pieceColor);
}
else if (pieceType == 'K'){
new Knight(pieceColor);
}
else if (pieceType == 'R'){
new Rook(pieceColor);
}
else if (pieceType == 'B'){
new Bishop(pieceColor);
}
else if (pieceType == 'Q'){
new Queen(pieceColor);
}
else if (pieceType == 'S'){
new King(pieceColor);
}
nextID ++;
Chess.position[posX][posY] = pieceID;
setCanvas(board);
repaint();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
drawPiece(g);
}
public void drawPiece(Graphics g){
g.drawImage(piece.getImage(),(locx*Chess.SQUARE_WIDTH),(locy*Chess.SQUARE_HEIGHT),null);
}
public class Pawn{
public Pawn(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wpawn.gif");
}
else{
piece = new ImageIcon("src/gfx/bpawn.gif");
}
}
}
public class Knight{
public Knight(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wknight.gif");
}
else{
piece = new ImageIcon("src/gfx/bknight.gif");
}
}
}
public class Rook{
public Rook(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wrook.gif");
}
else{
piece = new ImageIcon("src/gfx/brook.gif");
}
}
}
public class Bishop{
public Bishop(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wbishop.gif");
}
else{
piece = new ImageIcon("src/gfx/bbishop.gif");
}
}
}
public class Queen{
public Queen(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wqueen.gif");
}
else{
piece = new ImageIcon("src/gfx/bqueen.gif");
}
}
}
public class King{
public King(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wking.gif");
}
else{
piece = new ImageIcon("src/gfx/bking.gif");
}
}
}
}
Class BoardComponent:
import java.awt.*;
import javax.swing.*;
//This class draws the board and places the initial pieces
public class BoardComponent extends JComponent{
Chess chess;
public BoardComponent(Chess chessobject)
{
super();
chess=chessobject;
}
#Override
public void paintComponent(Graphics g)
{
super.paintComponent(g);
int rowCount = 0;
int highCount = 0;
int wideCount = 0;
int squareCount = 0;
ImageIcon piece;
for(rowCount = 0; rowCount<8;rowCount++){
for(int i = 0; i < 8; i++){
if(squareCount%2==1){
g.setColor(Color.ORANGE);
}
else{
g.setColor(Color.darkGray);
}
g.fillRect(wideCount,highCount, Chess.SQUARE_WIDTH-5, Chess.SQUARE_HEIGHT-5);
squareCount = squareCount + 1;
wideCount = wideCount + Chess.SQUARE_WIDTH;
g.setColor(Color.RED);
}
squareCount +=1;
wideCount = 0;
highCount = highCount + Chess.SQUARE_HEIGHT;
}
}
}
Class Piece:
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferStrategy;
import javax.swing.ImageIcon;
public class Piece extends JPanel{
Piece[] mypiece;
public ImageIcon piece;
int nextID = 0;
BoardComponent board;
Chess chess;
public int locx, locy;
public void setCanvas(BoardComponent board)
{
this.board=board;
}
public Piece(char color, char Type, int posX, int posY){
// each piece assigned a PK on creation, beginning sequentially from top left
// and looping back to the beginning of each row
int pieceID = nextID;
char pieceColor = color;
char pieceType = Type;
posX = locx;
posY = locy;
// P = pawn, K = knight, R = Rook, B = Bishop, Q = Queen,
//S = king (can't reuse K, so we use S instead)
if (pieceType == 'P'){
new Pawn(pieceColor);
}
else if (pieceType == 'K'){
new Knight(pieceColor);
}
else if (pieceType == 'R'){
new Rook(pieceColor);
}
else if (pieceType == 'B'){
new Bishop(pieceColor);
}
else if (pieceType == 'Q'){
new Queen(pieceColor);
}
else if (pieceType == 'S'){
new King(pieceColor);
}
nextID ++;
Chess.position[posX][posY] = pieceID;
setCanvas(board);
repaint();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
drawPiece(g);
}
public void drawPiece(Graphics g){
g.drawImage(piece.getImage(),(locx*Chess.SQUARE_WIDTH),(locy*Chess.SQUARE_HEIGHT),null);
}
public class Pawn{
public Pawn(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wpawn.gif");
}
else{
piece = new ImageIcon("src/gfx/bpawn.gif");
}
}
}
public class Knight{
public Knight(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wknight.gif");
}
else{
piece = new ImageIcon("src/gfx/bknight.gif");
}
}
}
public class Rook{
public Rook(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wrook.gif");
}
else{
piece = new ImageIcon("src/gfx/brook.gif");
}
}
}
public class Bishop{
public Bishop(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wbishop.gif");
}
else{
piece = new ImageIcon("src/gfx/bbishop.gif");
}
}
}
public class Queen{
public Queen(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wqueen.gif");
}
else{
piece = new ImageIcon("src/gfx/bqueen.gif");
}
}
}
public class King{
public King(char color){
if(color == 'w'){
piece = new ImageIcon("src/gfx/wking.gif");
}
else{
piece = new ImageIcon("src/gfx/bking.gif");
}
}
}
}
I'm fairly new to java, and this is really throwing me for a loop. Can anyone help?
Thanks!
Dont call drawPiece() from your constructor for what reason? I think repaint() might be what you need.
dont use getGraphics() as it wont be initialized yet until the panel is added and first repaint is done if im not mistaken.
Also never forget to honor paint chain and have super.paintComponent(..) as your first call in your overridden paintComponent(..) method of panel.
Rather extend JPanel and not JComponent
I think you meant to call drawPiece() in paintComponent(..) in which place you should just pass the Graphics object to drawPiece() from paintComponent(..) like so:
public class Piece extends JPanel{
public Piece(char color, char Type, int posX, int posY){
// each piece assigned a PK on creation, beginning sequentially from top left
// and looping back to the beginning of each row
....
// P = pawn, K = knight, R = Rook, B = Bishop, Q = Queen,
//S = king (can't reuse K, so we use S instead (from Shah, the historical name))
....
nextID ++;
Chess.position[posX][posY] = pieceID;
repaint();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
drawPiece(g);
}
public void drawPiece(Graphics g){
g.drawImage(piece.getImage(),(locx*Chess.SQUARE_WIDTH),(locy*Chess.SQUARE_HEIGHT),null);
}
}
Other suggestions:
Create JFrame and other Swing components on EDT by wrapping UI creation code in
SwingUtilities.invokeLater(new Runnable(){
#Override
public void run() {
//create ui here
}
});
Dont call setSize(...) on JFrame
rather override JPanel getPreferredSize() and return an appropriate size which fits components etc than you can remove setSize call on JFrame and call pack() on JFrame instance before setting visible
It seems like your variable board is not initialized yet. You need to call setCanvas() first to initialize it, then you can call drawPiece().