好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

Java实现经典游戏打砖块游戏的示例代码

前言

《JAVA打砖块》游戏是自制的游戏。玩家操作一根萤幕上水平的[棒子],让一颗不断弹来弹去的[球]在撞击作为过关目标消去的[砖块]的途中不会落到萤幕底下。

主要设计

设计游戏界面,用swing实现 设计砖块,砖块类, 设计小球,满屏乱跑的小球类,负责打碎砖块 设计棒子,左右移动的木头板类 球碰到砖块、棒子与底下以外的三边会反弹,落到底下会失去一颗球,把砖块全部消去就可以破关。 小球碰到砖块的回调算法设计 小球碰到棒子的回调算法设计 设计碰撞特效,一个负责显示爆炸效果的类 设计音效类,碰撞时发出音效。

功能截图

游戏开始:

碰撞效果:

代码实现

游戏核心类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

public class BricksGame extends BaseGame {

     private ArrayList<GameObject> list = new ArrayList<>();

     private RenderTask render;

     private Random random = new Random();

     private boolean over;

 

     private Image memImage;

     private Graphics memG; // 双缓冲的画布

 

     public BricksGame( int width, int height, String title) throws HeadlessException {

         super (width, height, title);

         super .setBgColor( new Color( 0x23 , 0x30 , 0x41 ));

         initGame(width, height);

     }

 

     private void initGame( int width, int height) {

         setFps( 60 );

         over= false ;

 

         // 获取窗口的内外大小

         Container contentPane = this .getContentPane();

         Dimension size = contentPane.getSize();

         int contentWidth = size.width;

         int contentHeight = size.height;

         this .setContentWidth(contentWidth);

         this .setContentHeight(contentHeight);

         //System.out.println(contentPane instanceof JPanel);// true

         //System.out.println(size.width);//582

         //System.out.println(size.height);//403

         // 窗口四个方向的边界值

         Insets insets = getInsets();

         //System.out.println(insets.top);

         //System.out.println(insets.bottom);

         //System.out.println(insets.left);

         //System.out.println(insets.right);

 

         Scene env = new Scene(width, height, new Margin(insets.left, insets.right, insets.top, insets.bottom));

 

         ImageIcon woodIcon = new ImageIcon( "image/wood.png" );

         int w = woodIcon.getIconWidth();

         int h = woodIcon.getIconHeight();

         Wood wood = new Wood(w, h, new Color( 0x97 , 0x5B , 0x12 ));

         wood.setScene(env);

         wood.setX(getWidth()/ 2 - w/ 2 );

         wood.setY(getHeight()- 50 );

         wood.setImage(woodIcon.getImage());

         list.add(wood);

 

         Ball ball = new Ball( 10 , Color.WHITE);

         ImageIcon iconBall = new ImageIcon( "image/ball2.png" );

         ball.setImage(iconBall.getImage());

         ball.setScene(env);

         ball.setCoordinator(width / 2 - ball.getRadius(), wood.getY()-ball.getRadius()* 2 );

         ball.setWoodBar(wood);

         list.add(ball);

 

         Color[] colors = new Color[]{

                 new Color( 0xAA , 0xCF , 0x51 ),

                 new Color( 0xFC , 0xA9 , 0x4B ),

                 new Color( 0x73 , 0xC7 , 0xFF ),

                 Color.PINK,

                 Color.GRAY

         };

         //ImageIcon brickIcon = new ImageIcon("image/brick_1.png");

         int brW = 60 ;

         int brH = 30 ;

         int start = 25 ;

         int brickX = start;

         int brickY = 100 ;

         int brickAreaWidth = getWidth() - start * 2 ;

         int count = brickAreaWidth / brW - 1 ;

         int remainWidth = brickAreaWidth - count * brW;

         int intervalHort = brW + 3 ;

         start = brickX = (getWidth() - intervalHort * (count)) / 2 ;

         int intervalVert = brH + 3 ;

 

         HitBrick hitBrick = new HitBrick();

         for ( int j = 0 ; j < 3 ; j++) { // brick line

             for ( int i = 0 ; i< count; i++){ // brick columns

                 Brick brick = new Brick();

                 brick.setColor(colors[i % colors.length]);

                 //brick.setImage(brickIcon.getImage());

                 brick.setWidth(brW);

                 brick.setHeight(brH);

                 brick.setX(brickX);

                 brick.setY(brickY);

                 brick.setBall(ball);

                 brick.setHitListener(hitBrick);

                 brickX += intervalHort;

                 list.add(brick);

             }

             brickX = start;

             brickY += intervalVert;

         }

 

         // 双缓冲,在内存里面创建一个和窗口JFrame一样大小的Image

         memImage = createImage(getWidth(), getHeight());

         memG = memImage.getGraphics();

         GameOver gameOver = new GameOver(memG);

         ball.setGameOverListener(gameOver);

 

         // 键盘事件的监听

         Input input = new Input();

         input.init();

         addKeyListener(input);

 

         // 重新渲染画面任务

         render = new RenderTask( this );

         render.start();

 

         addMouseListener( new MouseAdapter() {

             @Override

             public void mousePressed(MouseEvent e) {

                 //super.mousePressed(e);

                 System.out.println(String.format( "x:%d, y:%d" , e.getX(), e.getY()));

                 //x:218,y:305,w:164,h:45

                 if ((e.getX() >= 218 && e.getX() <=( 218 + 164 ))

                         && (e.getY() >= 305 && e.getY() <= ( 305 + 45 ))

                 ){

                     render.setExitd( true );

                     render = null ;

                     memImage = null ;

                     memG = null ;

                     removeKeyListener(input);

                     removeMouseListener( this );

                     list.clear();

 

                     initGame(width, height);

                 }

             }

         });

     }

 

     @Override

     public void paint(Graphics g) {

         clear(memG); // 将画布清空为背景色

 

         for ( int i = 0 ; i < list.size(); i++) {

             list.get(i).onTick();

             list.get(i).draw(memG);

         }

 

         if (list.size() == 2 ){ // 只剩下小球和挡板,则通关成功!

             Wood wood = (Wood) list.get( 0 );

             wood.setX(getWidth()/ 2 - wood.getWidth()/ 2 );

             wood.setY(getHeight()- 50 );

 

             Ball ball = (Ball) list.get( 1 );

             ball.setCoordinator(getWidth() / 2 - ball.getRadius(), /*bottom*/ wood.getY()-ball.getRadius()* 2 );

             ball.setMoving( false );

 

             String gameOver = "恭喜通关!" ;

             memG.setFont( new Font( "Serif" , Font.BOLD, 35 ));

             int stringWidth = memG.getFontMetrics().stringWidth(gameOver);

             memG.setColor(Color.RED);

             memG.drawString(gameOver, getWidth()/ 2 - stringWidth/ 2 , getHeight()/ 2 );

 

             stopRenderTask();

         }

 

         if (over) {

             String gameOver = "Game Over" ;

             memG.setFont( new Font( "Serif" , Font.BOLD, 35 ));

             int stringWidth = memG.getFontMetrics().stringWidth(gameOver);

             memG.setColor(Color.WHITE);

             memG.drawString(gameOver, getWidth()/ 2 - stringWidth/ 2 , getHeight()/ 2 );

 

             String playAgain = "重新开始" ;

             stringWidth = memG.getFontMetrics().stringWidth(playAgain);

             int increase = 16 ;

             int fontSize = memG.getFont().getSize();

             int rectH = ( int ) (fontSize * 1.3 );

             int rx=getWidth()/ 2 - stringWidth/ 2 - increase / 2 ;

             int ry=getHeight() - fontSize * 4 -(rectH-fontSize)/ 2 ;

             int rw = stringWidth + increase;

             int rh = rectH;

             //System.out.println(String.format("x:%d,y:%d,w:%d,h:%d", rx, ry, rw, rh));

             memG.drawRect(rx, ry, rw, rh);

             memG.setColor( new Color( 33 , 165 , 230 ));

             memG.drawString(playAgain, getWidth()/ 2 - stringWidth/ 2 , getHeight() - fontSize * 3 - 5 );

         }

 

         // 将内存Image的内容复制到窗口上

         g.drawImage(memImage, 0 , 0 , null );

 

         // 耗性能的轮询判断,一个对象是否要消失

         for ( int i = 2 ; i < list.size(); i++) { // 0,1位置是挡板和小球,不能消失

             GameObject gameObject = list.get(i);

             if (gameObject.isGone()) {

                 list.remove(i);

                 --i;

             }

         }

     }

 

     private void stopRenderTask() {

         new Thread( new Runnable() {

             @Override

             public void run() {

                 try {

                     Thread.sleep( 500 );

                 } catch (InterruptedException e) {

                     e.printStackTrace();

                 }

                 render.setExitd( true );

             }

         }).start();

     }

 

     public void exit(){

         //System.exit(1);

     }

 

     public void clear(Graphics g){

         if (g!= null ) {

             g.setColor(getBgColor());

             g.fillRect( 0 , 0 , getWidth(), getHeight());

         }

     }

 

     // 小球碰到砖块的回调

     class HitBrick implements Brick.HitListener{

         private ExecutorService executorService = Executors.newFixedThreadPool( 3 );

         private File file = new File( "audio/brick2.wav" );

         private AudioClip audio;

 

 

         public HitBrick() {

             try {

                 audio = Applet.newAudioClip(file.toURI().toURL());

             } catch (MalformedURLException e) {

                 e.printStackTrace();

             }

         }

 

         @Override

         public void hit(Brick brick) {

             executorService.execute( new PlayHitAudioTask(audio));

 

             ExplodeObject eo = new ExplodeObject();

             eo.x = brick.x;

             eo.y = brick.y;

             eo.width = brick.width;

             eo.height = brick.height;

             eo.color = brick.color;

             list.add(eo);

         }

     }

 

     // 游戏结束内容的绘制

     class GameOver implements Ball.GameOverListener{

         private Graphics memG;

 

         public GameOver(Graphics g) {

             this .memG = g;

         }

 

         @Override

         public void over() {

             over = true ;

         }

     }

}

小球类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

public class Ball extends RectGameObject{

     private int radius;

     private int speed = 4 ; // 小球移动速度

     private boolean moving; // 是否在移动

     private boolean gameOver; // 是否over

     private boolean postv; // 初始水平方向的移动左右方向

     private int horiMove; // 水平移动距离(正负号代表移动方向)

     private int vertMove; // 垂直移动距离(正负号代表移动方向)

     private Wood woodBar; //木头板

     private Image image;

     private Point center = new Point();

     private GameOverListener l;

 

     public Ball( int radius, Color color){

         this .radius = radius;

         this .color = color;

     }

 

     @Override

     public void draw(Graphics g) {

         g.setColor(color);

         //g.drawImage(image, x, y, null);

         g.fillOval(x, y, radius * 2 , radius * 2 );

     }

 

     @Override

     public void onTick() {

         if (!moving){

             if (Input.getKeyDown(KeyEvent.VK_UP)){

                 postv = (Math.random() * 10 ) <= 4 ? true : false ;

                 moving = true ;

                 gameOver = false ;

                 horiMove = postv ? speed : -speed;

                 vertMove = -speed;

             } /*else if(Input.getKeyDown(KeyEvent.VK_LEFT)){

                 Wood wb = woodBar;

                 if (!wb.isReachEdge()) {

                     transferBy(-wb.getSpeed(), 0);

                 }

             } else if(Input.getKeyDown(KeyEvent.VK_RIGHT)){

                 Wood wb = woodBar;

                 if (!wb.isReachEdge()) {

                     transferBy(wb.getSpeed(), 0);

                 }

             }*/

         }

 

         if (moving){

             // arrive at left and right edge

             Scene scene = getScene();

             Margin margin = scene.in;

             if (x <= margin.left || x >= scene.width - margin.right - radius * 2 ){

                 horiMove = -horiMove;

             }

 

             // arrive at top edge

             if (y <= margin.top && vertMove < 0 ){

                 vertMove = -vertMove;

             }

 

             // 小球落在了挡板上

             if (getCenter().x >= woodBar.getX()

                     && getCenter().x <= woodBar.getX() + woodBar.getWidth()

                     && Math.abs(getCenter().y - woodBar.y) <= radius

                     && vertMove > 0

             ){

                 vertMove = -vertMove;

             }

 

             // arrive at bottom edge

             // 小球落在了窗口的底部,停住小球 GAME OVER

             if (y >= scene.height - margin.bottom - radius * 2 ){

                 moving = false ;

                 gameOver = true ;

                 if (l != null )

                     l.over();

                 return ;

             }

 

             this .transferBy(horiMove, vertMove);

         }

 

     }

 

     public int getRadius() {

         return radius;

     }

 

     public void setRadius( int radius) {

         this .radius = radius;

     }

 

     public Wood getWoodBar() {

         return woodBar;

     }

 

     public void setWoodBar(Wood woodBar) {

         this .woodBar = woodBar;

     }

 

     public Image getImage() {

         return image;

     }

 

     public void setImage(Image image) {

         this .image = image;

     }

 

     public boolean isMoving() {

         return moving;

     }

 

     public void setMoving( boolean moving) {

         this .moving = moving;

     }

 

     public int getHoriMove() {

         return horiMove;

     }

 

     public void setHoriMove( int horiMove) {

         this .horiMove = horiMove;

     }

 

     public int getVertMove() {

         return vertMove;

     }

 

     public void setVertMove( int vertMove) {

         this .vertMove = vertMove;

     }

 

     @Override

     public int getWidth() {

         return 2 * radius;

     }

 

     @Override

     public int getHeight() {

         return getWidth();

     }

 

     public Point getCenter(){

         center.x = x + radius;

         center.y = y + radius;

         return center;

     }

 

     public boolean isGameOver() {

         return gameOver;

     }

 

     public void setGameOver( boolean gameOver) {

         this .gameOver = gameOver;

     }

 

     public GameOverListener getGameOverListener() {

         return l;

     }

 

     public void setGameOverListener(GameOverListener l) {

         this .l = l;

     }

 

     public interface GameOverListener{

         void over();

     }

}

砖块类

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

package game;

 

import java.awt.*;

 

public class Brick extends RectGameObject {

     private Ball ball;

     private Point leftTop = new Point();

     private Point leftBottom = new Point();

     private Point rightTop = new Point();

     private Point rightBottom = new Point();

 

     public Brick(){}

 

     @Override

     public void draw(Graphics g) {

         g.setColor(getColor());

         g.fillRect(x, y, getWidth(), getHeight());

     }

 

     @Override

     public void onTick() {

         if (ball.isMoving()) {

 

             //start 碰撞检测/////////////////////////////////////////////

             boolean is = isSameQuadrant(ball.getCenter(), getLeftTop(), getRightBottom());

             if (is) {

                 int r = ball.getRadius();

                 Point lt = getLeftTop();

                 Point lb = getLeftBottom();

                 Point rt = getRightTop();

                 Point rb = getRightBottom();

                 Point c = ball.getCenter();

                 int dx1 = Math.abs(c.x - lt.x), dy1 = Math.abs(c.y - lt.y);

                 int dx2 = Math.abs(c.x - lb.x), dy2 = Math.abs(c.y - lb.y);

                 int dx3 = Math.abs(c.x - rt.x), dy3 = Math.abs(c.y - rt.y);

                 int dx4 = Math.abs(c.x - rb.x), dy4 = Math.abs(c.y - rb.y);

 

                 if (((dx1*dx1) + (dy1*dy1) <= r*r)

                 ||((dx2*dx2) + (dy2*dy2) <= r*r)

                 ||((dx3*dx3) + (dy3*dy3) <= r*r)

                 ||((dx4*dx4) + (dy4*dy4) <= r*r)){

                     System.out.println( "发生了碰撞" );

                     if (hitListener != null ) {

                         hitListener.hit( this );

                     }

                     setGone( true );

                 }

 

             } else {

                 Point c = ball.getCenter();

                 int squareW = ball.getRadius() * 2 ;

                 int squareH = squareW;

 

                 int brcx = x + getWidth() / 2 ;

                 int brcy = y + getHeight() / 2 ;

 

                 if ((Math.abs(c.x - brcx) <= (squareW + getWidth())* 0.5 )

                         &&(Math.abs(c.y - brcy) <= (squareH + getHeight())* 0.5 )

                 ){

                     System.out.println( "......发生碰撞" );

                     if (hitListener != null ) {

                         hitListener.hit( this );

                     }

                     setGone( true );

 

                     /* 击中砖块,改变小球的方向 */

                     // 判断小球首先撞击的是砖块的左右还是上下侧,非常重要,否则出现不合理的移动方向。

                     double horizontal = (squareW + getWidth())* 0.5 - Math.abs(c.x - brcx);

                     double vertical = (squareH + getHeight())* 0.5 - Math.abs(c.y - brcy);

                     if (horizontal < vertical)

                         ball.setHoriMove(-ball.getHoriMove());

                     else

                         ball.setVertMove(-ball.getVertMove());

                 }

 

             }

             //end碰撞检测//////////////////////////////////////////////

         }

     }

 

     public Ball getBall() {

         return ball;

     }

 

     public void setBall(Ball ball) {

         this .ball = ball;

     }

 

     public Point getLeftTop(){

         leftTop.x = x;

         leftTop.y = y;

         return leftTop;

     }

 

     public Point getRightTop(){

         rightTop.x = x+getWidth();

         rightTop.y = y;

         return rightTop;

     }

 

     public Point getLeftBottom(){

         leftBottom.x = x;

         leftBottom.y = y + getHeight();

         return leftBottom;

     }

 

     public Point getRightBottom(){

         rightBottom.x = x + getWidth();

         rightBottom.y = y + getHeight();

         return rightBottom;

     }

 

     private HitListener hitListener;

     public void setHitListener(HitListener hitListener){

         this .hitListener = hitListener;

     }

 

     public interface HitListener {

         void hit(Brick brick);

     }

}

总结

通过此次的《JAVA打砖块》实现,让我对JAVA的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。

java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。

以上就是Java实现经典游戏打砖块游戏的示例代码的详细内容,更多关于Java打砖块游戏的资料请关注其它相关文章!

原文链接:https://juejin.cn/post/7067900690618089503

查看更多关于Java实现经典游戏打砖块游戏的示例代码的详细内容...

  阅读:16次