java - 破砖机砖颜色

标签 java swing animation graphics

我试图让游戏中的每个砖 block 具有随机颜色,但是当我尝试这样做时,整组砖 block 会变成相同的颜色。如何使每 block 砖 block 具有随机颜色?如有任何帮助,我们将不胜感激。

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();        
}
}

最佳答案

我会扔掉该代码并重新开始,因为您的绘画方法中既有程序逻辑又有重画,这两者都不会帮助您,而且您的代码似乎是一个巨大的“上帝”类,所有其中留下的代码对于调试来说是一场可怕的噩梦。建议:

  • 创建至少两个单独的 JPanel 来显示您的程序,一个 GamePanel 和一个 MenuPanel。
  • 使用 CardLayout 交换这些 JPanel .
  • 在 JPanel 的 PaintComponent 方法中绘制所有图形,而不是在 JFrame 或 JApplet 的 Paint 方法中绘制。
  • 不要忘记调用 super 的绘制方法,该方法与您的覆盖中的覆盖方法相同。这是为了清理所有脏像素。
  • 将程序逻辑与 GUI 分开
  • 这意味着您应该拥有单个 Brick 类的逻辑非 GUI 表示以及这些非 GUI Brick 的集合。
  • 您始终可以为您的 Brick 类提供一个 Color 字段, View 或 GUI 可以使用它来绘制它。
  • 创建一个游戏循环,一个您可以控制的游戏循环,一个不涉及在绘画方法中调用repaint()的游戏循环,因为这会导致完全无法控制的循环。
  • 优先使用Key Bindings通过 KeyListener。
  • 尽量避免使用“神奇”数字,例如在类本身中对砖 block 宽度和间距进行硬编码。最好使用常量,因为这也使调试和增强变得更加容易。

例如,一些代码只是为了演示显示随机颜色:

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);
    }
}

请注意,我喜欢使用 Color 的静态 getHSBColor(float h, float s, float b) 方法来创建随机颜色,因为这有助于我避免创建暗淡的颜色,因为我可以保证饱和度和亮度高于最小值。所有三个参数必须是 0f 到 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);

关于java - 破砖机砖颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37494416/

相关文章:

java - Swing 的骨架应用程序

ios - 使用自动布局更改 uiview 的大小并使其始终居中

Java 如何从 JSONArray 中删除字符串

java - 按下按钮时将文本附加到 JTextArea?

java - 从现有字符串中提取两个字符串

java - 如何获取Java应用程序的鼠标位置?

javascript - 数字动画师 - wordpress

jquery - 如何使用 jQuery.animate() 创建 "non-linear"轨迹?

java - 为什么CopyOnWriteArrayList需要自定义序列化

java - 如何通过Optional或stream或lambda简化代码?