0

I am trying to have each brick in my game have a random color, however when I try to do this the whole set of bricks become the same color. How do I make each individual brick a random color? Any help is appreciated.

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;


public class Game extends JoeApplet implements KeyListener
{
    String status;
    int ballx = 294; // ball spawn x coordinate
    int bally = 640; // ball spawn y coordinate
    int batx = 294; 
    int baty = 654;
    int brickx = 32;
    int bricky = 50;    
    double movex = -16;  // x speed of ball
    double movey = -16;  //y speed of ball
    int count = 0;
    int currentLevel=0;
    int score=0;      //starts score at 0
    int lives=3;      //lives start at 3
    static boolean right = false;
    static boolean left = false;
    boolean ballFallDown = false;
    boolean bricksOver = false;
    Rectangle Ball = new Rectangle(ballx, bally, 14, 14); //creates ball
    Rectangle Bat = new Rectangle(batx, baty, 100, 12);   //creates bat(paddle)
    Rectangle[] Brick = new Rectangle[49];    //creates desired number of bricks

    public void paint(Graphics art)
    {
        switch(currentLevel)
        {
        case 0:
            menuScreen(art);
            break;
        case 1:
            game(art);
            break;
        }
    }
    public void menuScreen(Graphics art)
    {
         setSize(700, 700);
         art.setColor(Color.BLACK);
         art.fillRect(0, 0, 698, 698);
         Color ballcolor=new Color(0,0,66);
         art.setColor(ballcolor);
         art.fillOval(Ball.x, Ball.y, Ball.width, Ball.height);
         Color batcolor=new Color(0,0,66);
         art.setColor(batcolor);
         art.fill3DRect(Bat.x, Bat.y, Bat.width, Bat.height, true); 
         art.setColor(Color.green);
         art.drawRect(0, 0, 698, 698);
         art.setColor(Color.yellow);
         Font menu = new Font("Arial", Font.BOLD, 20);
         art.setFont(menu);
         art.drawString("Brick Breaker", 100,400);
         art.drawString("Press P to Play", 100,425);
         art.drawString("Press Q to Quit game", 100,450);
         for (int i = 0; i < Brick.length; i++) 
         {
             if (Brick[i] != null)
             {
                 Color mycolor=new Color(100,0,0);
                 art.setColor(mycolor);
                 art.fill3DRect(Brick[i].x, Brick[i].y, Brick[i].width,
                 Brick[i].height, true);
             }

         }
             art.setColor(Color.YELLOW);
             if (ballFallDown || bricksOver) 
             {
                 Font f = new Font("Arial", Font.BOLD, 20);
                 art.setFont(f);
                 art.drawString(status, 294, 349);
                 ballFallDown = false;
                 bricksOver = false;
             }      
    }

    public void game(Graphics art) 
    {
         setSize(700, 700);
         art.setColor(Color.BLACK);
         art.fillRect(0, 0, 698, 698);
         Color ballcolor=new Color(0,0,225);
         art.setColor(ballcolor);
         art.fillOval(Ball.x, Ball.y, Ball.width, Ball.height);
         Color batcolor=new Color(0,0,139);
         art.setColor(batcolor);
         art.fill3DRect(Bat.x, Bat.y, Bat.width, Bat.height, true); 
         art.setColor(Color.green);
         art.drawRect(0, 0, 698, 698);
         for (int i = 0; i < Brick.length; i++) 
         {
             if (Brick[i] != null)
             {
                 Color mycolor=new Color(200,0,0);
                 art.setColor(mycolor);
                 art.fill3DRect(Brick[i].x, Brick[i].y, Brick[i].width,
                 Brick[i].height, true);
             }

         }

             if (ballFallDown || bricksOver) 
             {
                 Font f = new Font("Arial", Font.BOLD, 20);
                 art.setFont(f);
                 art.drawString(status, 100,425);
                 ballFallDown = false;
                 bricksOver = false;
             }  

             for (int i = 0; i < Brick.length; i++)
             {
                    if (Brick[i] != null) 
                    {
                        if (Brick[i].intersects(Ball)) 
                        {
                            score=score+10;
                            Brick[i] = null;
                            movey = -movey;
                            count++;
                        }   
                    }
             }      


               if (count == Brick.length) 
               {
                   bricksOver = true;
                   movex=0;
                   movey=0;
                   art.setColor(Color.green);
                   status = "YOU BEAT THE LEVEL!!";
                   art.drawString("Press E to Exit", 100,450);
                   art.drawString("Press N for Next Level", 100,475);
                   repaint();
               }

             repaint();
             Font f = new Font("Arial", Font.BOLD, 20);
             art.setFont(f);
             art.setColor(Color.white);
             art.drawString("Score:"+score, 600, 684);
             Ball.x += movex;
             Ball.y += movey;
             if (left == true) 
             {
                 Bat.x -= 18;
                 right = false;
             }
             if (right == true) 
             {
                 Bat.x += 18;
                 left = false;
             }
             if (Bat.x <= 4)
             {
                 Bat.x = 4;
             } 
             else if (Bat.x >= 586)
             {
                 Bat.x = 596;
             }    
             if (Ball.intersects(Bat))
             {
                 movey = -movey-.1;
             }   
             if (Ball.x <= 0 || Ball.x + Ball.height >= 698)
             {
                 movex = -movex;
             }
             if (Ball.y <= 0) 
             {
                 movey = -movey;
             }
             Font f1 = new Font("Arial", Font.BOLD, 20);
             art.setFont(f1);
             art.setColor(Color.white);
             art.drawString("Lives:"+ lives, 5, 684);
             if (Ball.y >= 698 && (bricksOver==false) && lives>0) 
             {
                   ballFallDown = true;
                   art.setColor(Color.red);
                   status = "";
                   art.drawString("", 100,450);
                   lives=lives-1;
                   ballx = 294; 
                   bally = 640;
                   Ball = new Rectangle(ballx, bally, 14, 14);
                   movex = -16;
                   movey = -16;
                   repaint();  
             } 
             if(lives==0 && Ball.y >= 698)
             {
                 art.setColor(Color.red);
                 art.drawString("You lost!!", 100,425);
                 art.drawString("Press E to Exit", 100,450);
             }
        }   

    public void init() 
    {
        addKeyListener(this);
        for (int i = 0; i < Brick.length; i++)  //creates bricks
        {
            Brick[i] = new Rectangle(brickx, bricky, 40, 20);
            if (i == 12)        //1st row of bricks
            {
                brickx = 32;
                bricky = 84;
            }
            if (i == 23)    //2nd row of bricks
            {
                brickx = 82;
                bricky = 118;
            }
            if (i == 32)    //3rd row of bricks
            {
                brickx = 132;
                bricky = 152;
            }
            if (i == 39)        //4th row of bricks
            {
                brickx = 182;
                bricky = 186;
            }
            if (i == 44)    //5th row of bricks
            {
                brickx = 232;
                bricky = 220;
            }
            if (i == 47)        //6th row of bricks
            {
                brickx = 282;
                bricky = 254;
            }
            if (i == 48)        //7th row of bricks
            {
                brickx = 144;
                bricky = 132;
            }
            brickx += 50;   //spacing between each brick        
        }   
    }

    public void restart() 
    {

         ballx = 294; 
         bally = 640;
         batx = 294;
         baty = 654;
         brickx = 32;
         bricky = 50;   
         Ball = new Rectangle(ballx, bally, 14, 14);
         Bat = new Rectangle(batx, baty, 100, 12);
         movex = -16;
         movey = -16;
         ballFallDown = false;
         bricksOver = false;
         count = 0;
        status = null;
        for (int i = 0; i < Brick.length; i++)  //recreates bricks
        {
            Brick[i] = new Rectangle(brickx, bricky, 40, 20);
            if (i == 12)        
            {
                brickx = 32;
                bricky = 84;
            }
            if (i == 23)    
            {
                brickx = 82;
                bricky = 118;
            }
            if (i == 32)    
            {
                brickx = 132;
                bricky = 152;
            }
            if (i == 39)        
            {
                brickx = 182;
                bricky = 186;
            }
            if (i == 44)    
            {
                brickx = 232;
                bricky = 220;
            }
            if (i == 47)        
            {
                brickx = 282;
                bricky = 254;
            }
            if (i == 48)        
            {
                brickx = 144;
                bricky = 132;
            }
            brickx += 50;           
        }   
          repaint();
    }

@Override
public void keyPressed(KeyEvent e)  //allows each key to do desired action
{
     int keyCode = e.getKeyCode();
     if (keyCode == KeyEvent.VK_LEFT) 
     {
      left = true;   
     }

     if (keyCode == KeyEvent.VK_RIGHT) 
     {
      right = true;
     }
     if (keyCode == e.VK_P && currentLevel == 0)
        {
            currentLevel = 1;
        }       
     else if (keyCode == e.VK_E && currentLevel == 1)
        {
            currentLevel = 0;
            score=0;
            lives=3;
            restart();
        }   
    else if(keyCode == e.VK_Q)
        {
            System.exit(0);
        }
}

@Override
public void keyReleased(KeyEvent e) 
{
     int keyCode = e.getKeyCode();
     if (keyCode == KeyEvent.VK_LEFT) 
     {
      left = false;
     }

     if (keyCode == KeyEvent.VK_RIGHT)
     {
      right = false;
     }
}

@Override
public void keyTyped(KeyEvent e)
{

}

public static void main(String[] args)
{   
    Game prog = new Game();
    prog.init();        
}
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373

2 Answers2

5

I'd throw that code out and start over as you've got both program logic and repaints within your painting methods, neither of which will help you, and your code appears to be one big huge "God" class, all of which will leave you with code that's a horrific nightmare to debug. Recommendations:

  • Create at least two separate JPanels to display your program with, a GamePanel and a MenuPanel.
  • Swap these JPanels using a CardLayout.
  • Do all graphics within a JPanel's paintComponent method and not within a JFrame's or JApplet's paint method.
  • Don't forget to call the super's painting method, the same method as your override within your override. This is to clean up any dirty pixels.
  • Separate your program logic from your GUI
  • This means that you should have a logical non-GUI representation of a single Brick class as well as a collection of these non-GUI bricks.
  • You can always give your Brick class a Color field, one that the view or gui uses to paint it with.
  • Create a game-loop, one that you can control, one that doesn't involve calling repaint() within a painting method, since this leads to a completely uncontrollable loop.
  • Favor use of Key Bindings over KeyListeners.
  • Try to avoid use of "magic" numbers, such as hard-coding your brick width and spacing in the class itself. Better to use constants as this too makes debugging and enhancing much easier.

For example, some code that's just to demonstrate showing random colors:

enter image description here

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;

import javax.swing.*;

public class BrickBreak {
    private static void createAndShowGui() {
        GamePanel gamePanel = new GamePanel();

        JFrame frame = new JFrame("Brick Break");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(gamePanel);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> createAndShowGui());
    }
}

// JPanel that draws the game
class GamePanel extends JPanel {   
    private static final long serialVersionUID = 1L;
    private static final Color BACK_GRND = Color.BLACK;
    private int prefW;
    private int prefH;
    private Bricks bricks = new Bricks();

    public GamePanel() {
        // wide enough to hold the complete top-row of Bricks
        // using constants, so GUI automatically resizes if any sizes change
        prefW = (Brick.WIDTH + Bricks.X_SPACING) * Bricks.ROW_COUNTS[0] + Bricks.X_SPACING;
        prefH = prefW;
        setBackground(BACK_GRND);
    }

    @Override
    public Dimension getPreferredSize() {
        if (isPreferredSizeSet()) {
            return super.getPreferredSize();
        }
        return new Dimension(prefW, prefH);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D) g;
        for (Brick brick : bricks) {
            brick.draw(g2);
        }
    }
}

// non-GUI class that represents a logical Brick
class Brick {
    public static final int WIDTH = 40;
    public static final int HEIGHT = 20;
    private int x;
    private int y;
    private Color color;
    private Rectangle boundingRectangle;

    public Brick(int x, int y, Color color) {
        this.x = x;
        this.y = y;
        this.color = color;
        boundingRectangle = new Rectangle(x, y, WIDTH, HEIGHT);
    }

    // yeah,  I'm mixing some view with model here.
    public void draw(Graphics2D g2) {
        g2.setColor(color);
        g2.fill3DRect(x, y, WIDTH, HEIGHT, true);
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public Color getColor() {
        return color;
    }

    // use this to test for collisions
    public boolean contains(Point p) {
        return boundingRectangle.contains(p);
    }

    @Override
    public String toString() {
        return "Brick [x=" + x + ", y=" + y + ", color=" + color + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + x;
        result = prime * result + y;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Brick other = (Brick) obj;
        if (x != other.x)
            return false;
        if (y != other.y)
            return false;
        return true;
    }

}

// logical class that holds all Bricks
// Have class implement Iterable<Brick> so we can easily iterate through its containing
// Brick objects in a for-each loop
class Bricks implements Iterable<Brick> {
    public static final int X_SPACING = 10;
    public static final int Y_SPACING = X_SPACING;
    public static final int[] ROW_COUNTS = {13, 11, 9, 7, 5, 3, 1};
    private static final float MIN_SAT = 0.8f;
    private List<Brick> brickList;
    private Random random = new Random();

    public Bricks() {
        init(); // safe to call since it's final
    }

    public final void init() {
        // recreate the brickList ArrayList
        brickList = new ArrayList<>();
        int y = Y_SPACING;
        //  for each row of bricks
        for (int row = 0; row < ROW_COUNTS.length; row++) {
            int x = X_SPACING + ((ROW_COUNTS[0] - ROW_COUNTS[row]) / 2) * (X_SPACING + Brick.WIDTH);
            // for each column
            for (int j = 0; j < ROW_COUNTS[row]; j++) {
                // create a random color
                float hue = random.nextFloat();
                float saturation = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
                float brightness = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);

                Color color = Color.getHSBColor(hue, saturation, brightness);
                Brick brick = new Brick(x, y, color); // create a new Brick with this Color
                brickList.add(brick);
                x += X_SPACING + Brick.WIDTH;
            }
            y += Y_SPACING + Brick.HEIGHT;
        }
    }

    // returns null if no collision
    public Brick collision(Point p) {
        for (Brick brick : brickList) {
            if (brick.contains(p)) {
                return brick;
            }
        }
        return null;
    }

    @Override
    public Iterator<Brick> iterator() {
        return brickList.iterator();
    }

    public boolean remove(Brick brick) {
        // because Brick implements equals and hashCode, we can do this
        return brickList.remove(brick);
    }
}

Note that I like using Color's static getHSBColor(float h, float s, float b) method for creating random Colors as this helps me to avoid creating dull Colors, since I can guarantee that the saturation and brightness are above minimum values. All three parameters must be float values between 0f and 1.0f

float hue = random.nextFloat();
float saturation = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);
float brightness = MIN_SAT + random.nextFloat() * (1f - MIN_SAT);

Color color = Color.getHSBColor(hue, saturation, brightness);
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
2

Your code has quite a lot of issues, which @HovercaftFullOfEels answer already points out.

As for why your code doesn't work:

for (int i = 0; i < Brick.length; i++) 
{
    if (Brick[i] != null)
    {
        Color mycolor=new Color(100,0,0);
        art.setColor(mycolor);
        art.fill3DRect(Brick[i].x, Brick[i].y, Brick[i].width,
        Brick[i].height, true);
    }
}

This is the part that renders the bricks. You never create a random-number, but use the same Color for each brick (new Color(100, 0, 0);). Instead introduce a new variable into Brick that specifies the color of each brick and is initialized once with a random color.

The Brick-class would afterwards look like this:

public class Brick{
    public int x;
    public int y;

    ...

    public Color color;

    ...
}

The ... are just placeholders for other code that may be content of the class. Regarding public access of Class-variables: Encapsulation is a fundamental concept of OOP and should be used (on encapsulation). E.g. instead of giving direct access to Brick.x consider introducing a method Brick#getX().

Community
  • 1
  • 1
  • Thank you for the help, where would Introduce the new variable for the color? I will defiantly be replacing this code soon, first I just want to get this whole random color thing down. –  May 28 '16 at 02:28
  • This answer follows along the lines of avoiding using hard-coded "magic" numbers. 1+ – Hovercraft Full Of Eels May 28 '16 at 03:14
  • I'm not too familiar with Jpanel or Jframe yet, so would it be possible to have that same code in the jframe and japplet format? –  May 28 '16 at 15:28
  • @Kytex The simplest (and hopefully performant enough) way of checking, whether the ball touches any block would be to simply compare the position of the ball against the rectangles spanned by the Bricks. If the ball touches any of these, you've got a hit. It's hard to alter your code to this though, since it's spaghetti-code and - to be honest - though I'm willing to help, I'm not going to wrap my head around this sort of code. Should've added that to the answer: you're using OOP far too little. Encapsulate functionality inside classes, to make things more structured and understandable. –  May 28 '16 at 19:30