当初为了巩固java基础,写了一个雷霆战机小游戏,用到swing和javaSE线程那一块知识,后来学习了Spring和Mybatis,于是又基于TCP写了一个服务器,管理玩家的一些基本数据,这些都是后话,这一次我就来分享一点我写这个游戏的一些感悟。
首先先放图
登陆界面,主页面等等太多了就没放出来。简单介绍一下,玩法和雷霆战机差不多,鼠标或者键盘操控,里面有4个技能,放完技能有冷缩,图一是打小兵,图二是打boss。结束后结果上传服务器。
1、关于屏幕出现闪烁的问题我有写过两篇博客
https://blog.csdn.net/D1124615130/article/details/104436930
https://blog.csdn.net/D1124615130/article/details/104439034
2、游戏计算量太大导致屏幕卡顿
我的方法是开两个线程,一个专门用来绘图,另一个专门用于数据处理,数据处理线程的刷新频率最好大于绘图频率。
3、像雷霆战机游戏打得久了可能出现容器中对象,遍历的时候数据量太大导致卡顿,要及时清理过期对象(比如出屏幕范围,被玩家击杀等等)
while(!enemys.isEmpty()&&(enemys.peek()==null||!enemys.peek().isAlive()))
enemys.poll();
enemys是ConcurrentLinkedQueue对象,容器当然要选择线程安全的,
上面代码是在数据处理前调用的,将一些过时数据先给清理掉。
4、暂停,我的做法:
这是绘图线程,
Lock是我用单例模式写的一个类,类里面有一个信号量,一个boolean类型suspend,一个Object类型的lock。
信号量用于申请访问boolean类型suspend,然后利用lock调用wait
class DrawThread extends Thread{
@Override
public void run() {
while(true) {
try {
Lock.getSemaphore().acquire();
if(Lock.isSuspend()) {
Lock.getSemaphore().release();
Object lock=Lock.getLock();
synchronized (lock) {
lock.wait();
}
requestFocus();
}else
Lock.getSemaphore().release();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
repaint();
try {
sleep(Data.REFALSH_INTERVAL);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
唤醒正在休眠的线程,我是这样做的:
try {
Lock.getSemaphore().acquire();
Lock.setSuspend(false);
Lock.getSemaphore().release();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
Object lock=Lock.getLock();
synchronized (lock) {
lock.notifyAll();
}
经过挺多次试验,倒是没发生什么问题,我也觉得这代码写的挺麻烦的,如果大佬有更好的方法,欢迎给我评论,感谢。