打砖块游戏小结
在学习了多线程之后,每个人都要完成一个 小游戏的开发。在多线程学习的过程中学习了利用线程创建多个对象,并且用一个独立的线程对球的运动进行监控。当时就在想弹球的游戏,脑海中当时只想到了打砖块的游戏。而其他同学都挑选了相对较难的项目来做,有人做坦克大战,雷电,泡泡堂,泡泡龙甚至有人还在尝试做植物大战僵尸。本来想在自己的打砖块的游戏中怎加一些独特的效果,可是当真正做起这个项目才感觉到,这个项目也并非像自己想象的那样简单,制作的过程也是步步艰辛。
我的打砖块游戏
1、实现了各个按钮的选择功能和菜单选项中各选项的功能;
2、初步实现计分功能;
3、在上图中难度菜单选项中可初步实现地图的转换和速度的变化;
二、在该游戏制作过程中所用到的主要技术总结
1 、界面窗体的设计;
2 、利用线程创建球体对象
Ball b = new Ball(BallUtil. this , array );
b.start();
3 、判定球体与窗体边界的碰撞算法的实现;
// 小球碰到左边窗体时反弹
if ( X0 <= 2) {
if ( x < 0) {
x = - x ;
}
}
// 小球碰到上边界时反弹
if ( Y0 <= 95) {
if ( y < 0) {
y = - y ;
}
}
// 小球碰到右边界时反弹
if ( X0 >= 580) {
if ( x > 0) {
x = - x ;
}
}
// 小球碰到左上角反弹
if ( X0 <= 2 && Y0 <= 90) {
X0 += Math.abs ( x );
Y0 += Math.abs ( y );
}
// 小球碰到右上角反弹
if ( X0 >= 550 && Y0 <= 90) {
X0 = X0 - Math.abs ( x );
Y0 += Math.abs ( y );
}
// 小球碰到左下角反弹
if ( X0 <= 2 && Y0 >= 580) {
Y0 = Y0 - Math.abs ( y );
X0 += Math.abs ( x );
}
// 小球碰到右下角反弹
if ( X0 >= 580 && Y0 >= 580) {
X0 = X0 - Math.abs ( x );
Y0 = Y0 - Math.abs ( x );
}
4 、生成滑板对象并且取得鼠标所在的横坐标,并以其作为滑板生成的起始点的横坐标不断重画滑板对象,在不断擦除和重绘的过程中就会使其轨迹不致显现。
5 、绘制地图,将所用到的图片加到窗体的画布上
public class Brick {
/**
* 创建一个读取地图的方法
*
* @param path
* 地图存储的路径
* @return
*/
public static int [][] readMap(String path) {
try {
// 创建文件输入流
FileInputStream fis = new FileInputStream(path);
BufferedInputStream bis = new BufferedInputStream(fis);
// 由于文件是一种字符串类型,读取时应创建一个 byte 数组
byte [] bt = new byte [bis.available()];
// 读取数据
bis.read(bt);
String st = new String(bt);
int [][] arr = changeToArray (st);
return arr;
} catch (Exception ef) {
ef.printStackTrace();
}
return null ;
}
/**
* 将字符串转化为数组
*
* @param st
* 需要转化的字符串
* @return
*/
public static int [][] changeToArray(String st) {
// 将字符串按照分行符进行切割
String[] str = st.split( "\r\n" );
int [][] array = new int [str. length ][str[0].length()];
for ( int i = 0; i < str. length ; i++) {
// 便利字符串数组
String s = str[i];
// 对字符串进行解析
char [] ch = s.toCharArray();
for ( int j = 0; j < ch. length ; j++) {
char c = ch[j];
// 将字符串转成数字
int num = Integer.parseInt (c + "" );
System. out .print(num);
array[i][j] = num;
}
System. out .println();
}
return array;
}
}
创建一个绘制地图的方法
/**
* 绘制地图
*
* @param array
* @param g
*/
public void createMap( int [][] array, Graphics g) {
for ( int i = 0; i < array. length ; i++) {
for ( int j = 0; j < array[i]. length ; j++) {
if (array[i][j] != 0) {
int num = array[i][j];
String path = "image/" + num + ".png" ;
// 根据路径取得图片
ImageIcon icon = getImageIcon (path);
g.drawImage(icon.getImage(), 40 * j, 40 * i, null );
}
}
}
}
设置地图路径调用创建地图的方法创建地图
String c ="src/javastudy/caidan/ 弹球游戏 0805/dzk.map"
array = Brick.readMap (c);
if (null != array)
createMap(array, g) ;
6 、游戏界面的重绘与刷新;
利用双缓冲对游戏界面进行重绘
class Mypaint extends JPanel {
Image img = null ;
Graphics gImage = null ;
public void update(Graphics g) {
if ( null == img ) {
img = this .createImage(600, 570);
gImage = img .getGraphics();
}
gImage .setColor(Color. WHITE );
gImage .fillRect(0, 0, 600, 570);
paint( gImage );
gImage .drawImage( img , 600, 570, null );
}
public void paint(Graphics g) {
if ( null == img ) {
img = this .createImage(600, 570);
gImage = img .getGraphics();
}
gImage .setColor(Color. WHITE );
gImage .fillRect(0, 0, 600, 570);
super .paint(g);
// 绘地图
if ( null != array )
createMap( array , g);
if ( ml != null ) {
ml .paintban(g);
}
gImage .drawImage( img , 600, 570, null );
}
/**
* 绘制地图
*
* @param array
* @param g
*/
public void createMap( int [][] array, Graphics g) {
for ( int i = 0; i < array. length ; i++) {
for ( int j = 0; j < array[i]. length ; j++) {
if (array[i][j] != 0) {
int num = array[i][j];
String path = "image/" + num + ".png" ;
// 根据路径取得图片
ImageIcon icon = getImageIcon (path);
g.drawImage(icon.getImage(), 40 * j, 40 * i, null );
}
}
}
}
}
刷新界面;
class FrashThread extends Thread {
public void run() {
while (!Ball. isStop ) {
repaint();
while (!Ball. isPause ) {
try {
Thread.sleep (1);
} catch (Exception ef) {
ef.printStackTrace();
}
}
try {
Thread.sleep (10);
} catch (Exception ef) {
ef.printStackTrace();
}
}
}
}
7 、在游戏中加入声音文件;
三、制作过程中遇到的主要问题
1 、 球碰砖块的算法,刚开始由于坐标判定不准确,会使小球在不该反弹的地方反弹,在该反弹的地方却将砖块擦出,细心更改坐标判定后,由于对球与砖块的相对为值界限判定不够精准导致球未碰砖块也会消失,数次修改后才把握准球与砖块碰撞的坐标判定
2 、添加地图时因为没有定义取得 url 路径的方法总是无法得到想要的地图
public static ImageIcon getImageIcon(String path) {
java.net.URL url = BallUtil. class .getResource(path);
ImageIcon icon = new ImageIcon(url);
return icon;
}
3 、制作完成后无法完成重绘的功能,利用上述所用的双缓冲就可解决
4 、虽然在用双缓冲解决了重绘和闪屏的问题但是由于我当时定义的滑板与地图所画得位置不在一起,因此虽然地图没有出现闪屏的现象,但是滑板和球却闪烁不止;
5 、添加背景音乐的格式( wav )与方法;
该添加音乐的方法为借鉴他人之法,由于要导入
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
import sun.audio.ContinuousAudioDataStream;
因此并不实用、方便
四、项目的拓展
1 、可以实现地图的完全转换和关卡的设置;
2 、增加其中的某些砖块可以随机掉落物品的功能,不同的物品其功效各不相同,加速,减速,板加长,板变短,增加球的个数等等