第一阶段:界面设计
第一阶段:界面实现(success):
具体实现中上图中改动:
1.左边最小Block尺寸由原来设想BasicBlock =30; 改为BasicBlock =29,为了满足f的布局GridLayout(1,2)平分f大小的要求。改动之后尺寸不是很协调,改动f尺寸为f.setBounds(350, 150, 585, 465);
满足画布10*29 15*29正好为f的一半大小(左半边)
具体实现关键:
1.重写MyPanel类,使JPanel的四周留空间 return new Insets(30,50,30,50);分别实现上左下右留出空白尺寸
2.设置TextField凹入效果:tf.setBorder(BorderFactory.createLoweredBevelBorder());
3.实现Button突出效果:bt.setBorder(BorderFactory.createRaisedBevelBorder());
4.设置字体:bt.setFont(new Font("微软雅黑", Font.PLAIN, 16));
实现中的问题:
问题1:
组件大小控制 直接改变GridLayout()里面参数调节组件之间距离
p2.setLayout(new GridLayout(5,1,30,50));效果
但是无法改变最上面组件紧贴f问题
通过实现关键中第一点实现改变
问题2:(很有意思的问题,百度至今还没有让我找到答案)
用panel添加canvas 再添加panel到frame 无法实现画布 连paint()都无法执行
但是当在这个基础上添加语句my.setBounds(50,50,30,30)这句没有道理的语句 之后可以神一样的实现 paint也执行了
一般常规的做法是 不用panel添加canvas
直接在frame下添加canvas可以满足要求 ,如图
实现效果:
第二阶段:方块设计
第二阶段:方块实现(success)
实现关键:
1.注意pattern[][]的表示方法,每个行表示方块的一个种类,每个列表示特定方块种类的状态(方块有7种类型对应7行,每种类型有4种状态表示4列)。
2.pattern[][]中每个对象都是特定的一个方块,用十六进制表示。0x表示16进制,接下来四个数字表示4*4的方格中方块属性,具体见方块设计(类似编码过程)。
3.屏幕中的15*10的方格,每个方格设定一个属性,0表示黑色背景,1表示下落方块,2表示不动方块。
4.通过paint() 实现屏幕刷新 通过调用draw(i,j,scr[i][j])实现画方块
两个for用来遍历屏幕15*10方格。
5.draw()函数介绍
传入所需画的方格scr[][]坐标i ,j ,以及该方块的属性scr[i][j],实现画方块
6.初始化方块方法
随机产生1种方块
7.显示方块(很关键)
随机产生方块之后应该根据产生方块的属性去定义屏幕中方块的属性
定义完成之后通过、调用mycanvas实现屏幕的刷新,显示方块
实现效果:
方块随机产生,刷新显示
第三阶段:命令控制设计(success)
1.点击开始游戏实现出现初始化随机方块,不点击黑屏;
2.点击提高级数实现级数框里数字的增加1;(添加线程之后实现速度增加)
3.点击降低级数实现级数框里数字的减少1;(添加线程之后实现速度减少)
4.点击暂停游戏实现游戏暂停;(这个不去实现,添加线程控制之后实现)
5.点击退出游戏实现关闭游戏。
实现效果:
点击开始游戏才会出现初始化方块,如上一阶段图。
第四阶段:方块下落线程(success)
实现内容:
1.点击提高级数实现级数框里数字的增加1;(实现方块下落速度变快,sleep()实现)
2.点击降低级数实现级数框里数字的减少1;(实现方块下落速度变慢,sleep()实现)
3.由线程控制方块的下落,由按钮中的暂停游戏键控制线程的执行与暂停,当按下按钮暂停游戏时,游戏暂停,按钮变成恢复游戏,当按下恢复游戏时恢复游戏;
4.当下落方块到达底部(遇到障碍时)改变颜色,执行方块初始化,重新开始。
实现难点:
问题1:程序中存在repaint()调用paint()的延迟问题,之前执行在后台观看时发现执行paint()没有规律,在要执行语句之后没有执行,在没有执行语句之后会有执行。
经过思考:我猜测这个函数应该和线程的机理差不多,即调用了之后存在随机时间然后执行。
查阅资料发现:
repaint()方法用于重绘组件,该方法有下面四种形式:
1.public void repaint()
2.public void repaint(long tm)//指定调用update方法之前等待的最大毫秒数tm
3.public void repaint(int x,int y,int width,int height)//重绘组件的指定矩形区域
4.public void repaint(ling tm,int x,int y,int width,int height)
repaint方法不总是马上执行,Java虽然会尽可能快的执行repaint,当Applet运行在较慢的平台上或计算机较忙时,应该考虑使用第2或4种repaint方法,指定在多长时间内必须执行repaint,否则就放弃如下图所示:
Pait 2 2 2 2 2: 是在paint函数中run前后分别添加表示paint()函数开始执行和执行结束我用来判断paint()函数是否执行;
InitScr: 初始化屏幕时用 在点击开始时进行初始化;
InitBlock:初始化屏幕之后要初始化方块;
0: 表示display(0);
1: 表示display(1);
注意:display()函数中有repaint()调用paint()
如上图可以看出问题:
当执行完initBlock()时,应该是在执行display(1)后调用repaint进行画图操作的,然而此时因为repaint()的延迟,而使得线程先开始运行,打破了原来的运行顺序。然后方块下落需要等待时间(进入sleep(),时间相对比较长)使得方块在下落之前完成初始化的repaint(),即调用了paint().
方块下落时也有此问题,调用了0 和1 后应该是执行调用paint的,进行画图操作,然而图中程序显示,存在repaint()延迟,还是先执行了线程,甚至等到线程执行完一次进入第二次循环时又遇到sleep()函数时才执行第一次的0 和 1 中的repaint调用paint刷新画布,存在很大的问题。
解决方法:
想法是当display(0)和display(1)没有执行完时 线程不执行,但是存在repaint()延迟,那么我在display函数中设置线程延迟来平衡两个延迟。如图:
等待一个时间让repaint()执行,之后执行控制命令中的mark = true;执行线程。
实现效果:
如图在每次调用0 和 1 即display(0) 和display(0)时立即执行repaint()。
问题二:
下落到底部的方块颜色不变,而且执行到方块下落到最后一行时报出数组越界的错误.
从而导致没法执行initBlock();即重新下落方块.
解决方法:
如图添加语句if进行判断:是否判断时getscr(i+Row,J+Column);里面已经越界,如果越界直接返回false,执行display(0),display(2),把方块颜色变为固定颜色粉红色。
问题三:
执行完上述固定颜色变换之后,我们需要重新初始化方块,重新调用Row = mycanvas.initRow();和Column = mycanvas.initColumn();重新执行下落,之前因为没有重新给Row,Column赋值,初始化直接在下落到底下的方块执行,出现问题。
解决这些问题之后,基本实现方块下落,固定方块,以及初始化,基本实现!!!
实现效果:
第五阶段:方块在屏幕中的左、下、右、状态控制(Success)
1.通过添加画布的键盘监听器实现
实现基础请回看日记KeyListener-实现键盘按钮启动功能
主要通过那篇日记中的方法知道所需按键的code,然后通过键盘监听实现。
实现难点:
1.对画布实现监听器的添加,当按按钮实现开始游戏时,必须点击画布,不然聚焦在按钮上,无法实现控制。
解决方案:
如图对于按钮也实现键盘监听即可
主要实现当点击按钮开始、暂停等操作时,聚焦在按钮上也能实现键盘对方块左下右的控制
使用Scr.requestFocus();和f.addKeyListener(dir);没有实现预期效果,还是要之后探讨一下???
问题二:
方块下落时操作左下右频繁快速时出现问题,如图
经过思考得出结论:
原因出在了,同步问题(临界资源)问题,即当在下落刚刚刷新时,我是用了左右按钮控制键同时刷新,问题就出现了,就出现上面的情况了。
解决方案:
在调用刷新的函数实现同步于互斥,即解决问题,一次只允许一个操作执行刷新操作。
因为我之前实现刷新是在dispaly()函数执行完setscr()操作之后执行的
所以只要把display()函数实现同步于互斥即可。
如图添加语句synchronized即可实现
这样就实现了任意按按钮都不会出现上面的问题啦!!!如图所以快要接近完成啦!!
第六阶段:方块满行消行实现(underway)
第七阶段:游戏不足分析()
--------