
线程游戏的实现 2关于缓冲区经过线程游戏的初步设计直接在窗口分层绘制图像时画面频繁闪烁是因为分层绘图按代码顺序逐次刷新清屏与重绘交替出现形成视觉频闪因此引入图像缓冲区所有图层预先绘制至缓冲画布整帧绘制完毕后一次性输出至窗口解决闪烁问题。1.缓冲初始化所有画面元素都调用 buffG.xxx() 绘制不要用窗口原始画笔g// 创建缓冲图片尺寸与游戏窗口一致BufferedImagebufferedImagenewBufferedImage(800,800,BufferedImage.TYPE_INT_BGR);// 获取缓冲画布画笔所有绘图统一使用 buffGGraphicsbuffGbufferedImage.getGraphics();2.最终统一刷新每一帧末尾// 整帧统一绘制完毕将缓冲图片贴到窗口g.drawImage(bufferedImage,0,0,null);实现背景图片的滚动效果准备两张相同的背景图一张放在可视窗口一张紧贴在第一张图片正上方两张同步向下移动当任意一张图片完全滑出屏幕底部立刻将它挪到另一张图片的头顶循环往复实现无限向下滚动1.设置滚动成员变量// 两张背景图相同publicImageback;publicImageback2;// 背景纵向偏移publicintbgY0;// 滚动速度数值越大滚动越快publicintbgSpeed2;// 窗口宽高和画布一致publicfinalintWIN_HEIGHT800;2.构造器加载背景backnewImageIcon(resources\\Starrysky.JPG).getImage();back2newImageIcon(resources\\Starrysky.JPG).getImage();3.坐标更新// 若暂停游戏不更新角色、子弹位置仍绘制当前画面if(!listener.isPause){bgYbgSpeed;// 图片滑出屏幕底部坐标归零循环if(bgYWIN_HEIGHT){bgY0;}}4.两张图片的拼接// 第一张正常下移buffG.drawImage(back,0,bgY,null);// 第二张紧贴第一张正上方无缝衔接buffG.drawImage(back2,0,bgY-WIN_HEIGHT,null);资源根导入照片项目文件夹 └── src ├── com/xxx/各类Java代码包GameThread、GameUI等 └── resources 【必须新建resources文件夹放在src同级】 └── Starrysky.JPG代码不用写电脑C盘/D盘完整路径使用资源相对根路径publicGameThread(Graphicsg,MPlanemp,ArrayListBulletbullets,GameListenerlistener){this.gg;this.mpmp;this.bulletsbullets;this.listenerlistener;backnewImageIcon(resources\\Starrysky.JPG).getImage();back2newImageIcon(resources\\Starrysky.JPG).getImage();//第二张初始放在第一张正上方bgY0;}实现图片按钮依靠缓冲画布绘制按钮图片配合鼠标监听坐标判断点击区域实现游戏内嵌图片按钮用于开始界面切换游戏画面1.设置按钮相关成员变量// 开始按钮图片对象publicImageIconstartImage;// 按钮绘制范围常量与绘图坐标匹配privatefinalintbtnX200;privatefinalintbtnY600;privatefinalintbtnW200;privatefinalintbtnH100;2.构造器加载按钮图片startImagenewImageIcon(resources\\Start Game Button.PNG);3.画布绘制按钮图片// 在缓冲画布绘制按钮图片确定按钮显示位置与大小buffG.drawImage(startImage.getImage(),200,600,200,100,null);4.鼠标点击坐标判定逻辑// 获取鼠标点击坐标判断是否落在按钮矩形范围内intmxe.getX();intmye.getY();booleanhitBtnmxbtnXmxbtnXbtnWmybtnYmybtnYbtnH;// 仅在开始界面、未创建玩家时点击生效切换游戏画面if(hitBtngt.startmpnull){mpnewMPlane(350,600);gt.setMp(mp);gt.isStart(false);}5.窗口绑定全套鼠标监听// 绑定鼠标移动监听、鼠标点击监听gamePanel.addMouseMotionListener(listener);gamePanel.addMouseListener(listener);添加背景音乐Java原生音频类 Clip 仅支持 .wav 无损音频文件通过自定义音频工具类实现多首音乐自由切换、游戏暂停同步控音功能1.音频资源准备完成后在游戏主线程、窗口类中创建音频对象// 1. 定义背景音乐路径数组String[]musicList{resources/bg1.wav,resources/bg2.wav,resources/bg3.wav};// 2. 创建音频工具对象AudioMusicaudionewAudioMusic(musicList);// 3. 加载并播放第一首audio.loadMusic(audio.currentIndex);audio.playLoop();2.控制音乐切换1键盘按键切换OverridepublicvoidkeyPressed(KeyEvente){// F1切换下一首if(e.getKeyCode()KeyEvent.VK_F1){audio.nextMusic();}}2画面图片按钮切换绘制按钮图片记录按钮坐标范围鼠标点击监听中判断坐标命中则执行切换OverridepublicvoidmouseClicked(MouseEvente){intxe.getX();intye.getY();// 判断是否点击音乐切换按钮区域if(x10x110y10y60){audio.nextMusic();}}3.游戏暂停/继续同步控制音乐if(isPause){audio.stopMusic();// 暂停游戏停止音乐}else{audio.playLoop();// 恢复游戏继续播放音乐}4.在画布绘制文字提示当前播放音乐// g为缓冲画笔buffGg.setColor(Color.WHITE);g.setFont(newFont(黑体,Font.BOLD,30));g.drawString(当前背景音乐第(audio.currentIndex1)首,20,60);