手把手教你做一个Java多线程游戏,仿真实例分享

手把手教你做一个Java多线程游戏,仿真实例分享

首页枪战射击多线程更新时间:2024-04-17

这是一篇学习分享文章,这篇文章将会介绍以下几项内容:

1、如何让一个程序同时做多件事?(多线程的创建、多线程的应用)

2、如何让小球在画面中真实地动起来?(赋予小球匀速直线、自由落体、上抛等向量运动)

3、多线程游戏仿真实例分享(飞机大战、接豆人、双线挑战三个游戏实例)

涉及的知识点有:多线程的应用、双缓冲绘图、小球的向量运动、游戏的逻辑判断、键盘监听器的使用、二维数组的使用、添加音乐效果等

文中所有素材和代码可以私信小编【游戏】获取

游戏效果:

怎么样?如果觉得还不错的话就请继续看下去吧!

热身第一步:创建画布

import java.awt.FlowLayout; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JFrame; public class Frame { //声明画布对象 public Graphics g; //主函数 public static void main(String[] args) { //创建Frame类,然后运行showFrame函数 Frame fr=new Frame(); fr.showFrame(); } //编写窗体显示的函数 public void showFrame(){ //创建窗体 JFrame jf=new JFrame(); jf.setTitle("小球演示");//设置窗体标题 jf.setSize(900,900);//设置窗体大小 jf.setDefaultCloseOperation(3);//设置点击窗体右上角的叉叉后做什么操作,这里的3代表点击叉叉后关闭程序 jf.setLocationRelativeTo(null);//设置窗体居中显示 FlowLayout flow=new FlowLayout();//设置窗体布局为流式布局 jf.setLayout(flow); Mouse mou=new Mouse();//创建监听器对象 JButton jbu=new JButton("START");//创建按钮,按下按钮后可以在画布中间画一个圆 jbu.addActionListener(mou);//为按钮添加事件监听器 jf.add(jbu); //设置窗体可见 jf.setVisible(true); //从窗体获取画布 g=jf.getGraphics(); } //创建内部类监听器(也可以重新创建一个文件编写该类) class Mouse implements ActionListener{ //重写按钮监听方法 public void actionPerformed(ActionEvent e){ //按下按钮后会执行这里的代码,下面这条代码指的是在画布中心画一个圆 g.fillOval(300,300,300,300); } } }

第二步:让小球动起来

//重复画100次小球,每次横纵坐标分别加1 for(int i=0;i<100;i ){ g.fillOval(300 i,300 i,30,30); /*下面这段代码的意思是每执行一次循环,系统暂停30毫秒,否则画的 太快我们就观察不到小球在动了*/ try{ Thread.sleep(30); }catch(Exception ef){ } }

一、如何让一个程序同时做多件事情?

创建线程对象

import java.awt.Graphics; import java.util.Random; public class ThreadClass extends Thread{ public Graphics g; //用构造器传参的办法将画布传入ThreadClass类中 public ThreadClass(Graphics g){ this.g=g; } public void run(){ //获取随机的x,y坐标作为小球的坐标 Random ran=new Random(); int x=ran.nextInt(900); int y=ran.nextInt(900); for(int i=0;i<100;i ){ g.fillOval(x i,y i,30,30); try{ Thread.sleep(30); }catch(Exception ef){ } } } }

public void actionPerformed(ActionEvent e){ ThreadClass thc=new ThreadClass(g); thc.start(); }

接下来我们试着运行一下吧!

加入清屏功能,让小球真正的动起来

让我们试着把run()方法中的代码改为下面这样:

public void run(){ //获取一个随机数对象 Random ran=new Random(); //生成一对随机的x,y坐标设为小球的坐标,范围都在0-399 int x=ran.nextInt(400); int y=ran.nextInt(400); for(int i=0;i<100;i ){ //画一个能够覆盖画面中一块区域的白色矩形来清屏(把原来的笔迹都覆盖掉) g.setColor(Color.white); g.fillRect(300,300,300,300); g.setColor(Color.black); g.fillOval(200 x i,200 y i,30,30); try{ Thread.sleep(30); }catch(Exception ef){ } } }

让我们试着运行一下

先创建坐标类

public class Location { public int x; public int y; public Location(int x,int y){ this.x=x; this.y=y; } }

然后在主类和ThreadClass类中创建列表

public ArrayList<Location> locs=new ArrayList<Location>();

然后在按钮监听器的方法下写入这段代码

public void actionPerformed(ActionEvent e){ Random ran=new Random(); int x=ran.nextInt(400); int y=ran.nextInt(400); Location loc=new Location(x,y); locs.add(loc); System.out.println(locs.size()); }

然后将画布g和列表locs传入创建的线程对象中,在主类的showFrame方法插入以下代码。

ThreadClass thc=new ThreadClass(g,locs); thc.start();重载Thread Class的run()方法

重载Thread Class的run()方法

public void run(){ while(true){ g.setColor(Color.white); g.fillRect(300,300,300,300); for(int i=0;i<locs.size();i ){ g.setColor(Color.black); //每次给小球坐标偏移一下 int x=locs.get(i).x ; int y=locs.get(i).y ; g.fillOval(200 x,200 y,30,30); } try{ Thread.sleep(30); }catch(Exception ef){ } } }

让我们再来试一下!

这下小球就没有闪烁的那么厉害了。

二、如何让小球在画面中真实地动起来?

在这里我们可以创建一个Vector类来描述位置、速度和加速度这三个物理量

public class Vector { public int x; public int y; public Vector(int x,int y){ this.x=x; this.y=y; } //向量的加和运算 public void add(Vector vec){ this.x =vec.x; this.y =vec.y; } }

然后我们再创建一个Ball类来代表小球(move函数是本部分的关键)

public class Ball { public Vector location;//位置 public Vector speed;//速度 public Vector acce;//加速度 //构造器传参,设定小球的基本参数 public Ball(Vector location,Vector speed,Vector acce){ this.location=location; this.speed=speed; this.acce=acce; } //小球移动,这是整个部分的关键!!!每画完一次小球就调用一次move函数,让小球依据速度和加速度来改变一次位置 public void move(){ this.speed.x =acce.x;//每调用一次move函数小球的速度就和加速度做一次加法 this.speed.y =acce.y; this.location.x =speed.x;//每调用一次move函数小球的位置坐标就和速度做一次加法 this.location.y =speed.y; } }

有了这两个类,我们就可以表示任意二维的向量运动了

Vector location=new Vector(0,0); Vector speed=new Vector(5,0); Vector acce=new Vector(10,0);

Vector location=new Vector(0,0); Vector speed=new Vector(5,10); Vector acce=new Vector(10,0);

需要改变的是主类中Mouse类的代码和ThreadClass类中run方法的代码

//创建内部类监听器(也可以重新创建一个文件编写该类) class Mouse implements ActionListener,MouseListener{ int prx=0; int pry=0;//记录按下鼠标的点的坐标 //重写按钮监听方法 public void actionPerformed(ActionEvent e){} public void mouseClicked(MouseEvent e) {} public void mousePressed(MouseEvent e) { prx=e.getX(); pry=e.getY();//获取按下鼠标的点的坐标 } public void mouseReleased(MouseEvent e) { int speedx=(int)((e.getX()-prx)/10); int speedy=(int)((e.getY()-pry)/10); Vector location=new Vector(e.getX(),e.getY()); Vector speed=new Vector(speedx,speedy); Vector acce=new Vector(0,1); Ball ball=new Ball(location,speed,acce); balls.add(ball); } public void mouseEntered(MouseEvent e) {} public void mouseExited(MouseEvent e) {} }ThreadClass下的run方法

public void run(){ while(true){ g.setColor(Color.white); g.fillRect(300,0,600,900); for(int i=0;i<balls.size();i ){ g.setColor(Color.black); g.fillOval(balls.get(i).location.x,balls.get(i).location.y,30,30); balls.get(i).move(); } try{ Thread.sleep(30); }catch(Exception ef){ } } }

执行效果如图所示(为了显示小球向量运动的效果,这里省去了清屏操作)

完整代码放到这里:
https://pan.baidu.com/s/10HcOSvuov14moes1jPe9JQ
提取码:z8ii

三、多线程游戏仿真实例分享

(三个游戏的源代码、图片素材链接在下文中获取)

游戏一:飞机大战

游戏演示:

额...上传不了

Java游戏制作

游戏说明:

飞机大战简介:

要实现飞机大战主要完成这几件事:

  1. 绘制我方飞机、不断发射子弹
  2. 不断随机生成怪物、宝箱
  3. 判断子弹与怪物、怪物与我方飞机之间是否碰撞
  4. 爆炸动效、刷新分数

由于时间关系,目前博主所制作的游戏暂时只具有以上这些功能,有兴趣的伙伴还可以试着增加关卡、Boss、新的怪物(比如会发射子弹的怪物)、剧情等等。

我们在游戏进行的过程中,难免会生成大量的图片对象。前面我们讲到,当我们需要在屏幕上绘制的图像过多时会出现卡顿闪屏现象,第二个解决方法就是双缓冲绘图,下面我来简单的介绍一下。

双缓冲绘图解决闪屏

要实现双缓冲绘图,首先我们要创建BufferedImage对象,然后从这个缓存对象中获取画布:

//创建缓存 BufferedImage bufImg=new BufferedImage(1200,1200,BufferedImage.TYPE_INT_ARGB); //最后的TYPE_INT_ARGB代表创建的是具有合成整数像素的 8 位 RGBA 颜色分量的图像,也可以选择其他类型,详见Java的API文件 //获取缓存上的画布 Graphics bufg=bufImg.getGraphics();

获取了Graphics bufg后,我们所有的绘图操作先在bufg上完成,等一轮图像画完之后,再把bufg上的图像画到原本的Graphics对象中

g.drawImage(bufImg,0,0,null);飞机大战制作Step1:飞行物

//有图片、有血量的飞行物 public FlyObject(Vector location,Vector speed,Vector acce,String imgName,int HP){ this.location=location;//位置 this.speed=speed;//速度 this.acce=acce;//加速度 this.HP=HP;//血量 this.imgName=fileAddress imgName;//图片地址 ImageIcon imgicon=new ImageIcon(this.imgName);//如果我们想要在画布上画一张图片,可以先用图片地址创建一个ImageIcon对象,然后再从这个对象中获取Image对象 img=imgicon.getImage(); } //前面介绍过的move方法 public void move(){ speed.add(acce); location.add(speed); } //将飞行物的图片画到画布上 public void drawFO(Graphics g){ //如果被绘制的对象有图片就画图片,没图片就画一个圆 if(imgName!=null){ // System.out.println(imgName); g.drawImage(img,location.x, location.y,null); }else{ g.fillOval(location.x, location.y,10,10); } }

游戏过程中,我方飞船是始终跟随着鼠标共同移动的。要实现这一点,我们需要在Listener类中实现MouseMotionListener,然后重写鼠标移动mouseMoved方法(记得最后要给窗体添加MouseMotionListener监听器)。当鼠标在窗体中进行移动时,该方法会不断地获取鼠标在窗体中的坐标,参考下面这段代码重写mouseMoved方法:

public void mouseMoved(MouseEvent e){ Vector location=new Vector(e.getX(),e.getY()); FlyObject mp=new FlyObject(location,null,null,"我机.png"); mps.add(mp);//mps是存放我方飞机对象的列表ArrayList<FlyObject> mps }

//不断发射子弹 public void generateBullet(){ //隔一段时间就生成一些子弹(int len是一个计数器,它记录的是run方法中的运行次数,所有代码跑完一次就加一) if(len%5==0){ for(int i=0;i<4;i ){ //设定子弹坐标 Vector location_fo=new Vector(mps.get(mps.size()-1).location.x,mps.get(mps.size()-1).location.y 20*i); Vector speed_fo=new Vector(100,0);//设定子弹速度 Vector acce_fo=new Vector(0,0);//设定子弹加速度(这里把加速度设为0意思就是让子弹做匀速运动) FlyObject fo=new FlyObject(location_fo,speed_fo,acce_fo,"子弹.png",1); fos.add(fo); } } }

public void generateEnemy(){ if(len ==0){ Random ran=new Random(); //怪物的横坐标是固定的(窗体的最右边),纵坐标是随机的 int loc_y=ran.nextInt(900) 100; //怪物只在x方向有速度 int spd_x=-ran.nextInt(10)-10; Vector location=new Vector(1200,loc_y); Vector speed=new Vector(spd_x,0); Vector acce=new Vector(0,0); FlyObject enemy=new FlyObject(location,speed,acce,"怪物.png",5); enemys.add(enemy); } }飞机大战制作Step2:判断碰撞

//判断子弹是否击中怪物、怪物是否触碰我机、是否拾得宝箱 public void judgeAttack(Graphics bufg_judgeAttack){ //判断子弹是否击中怪物 for(int i=0;i<enemys.size();i ){ //取出怪物对象 FlyObject en=enemys.get(i); for(int j=0;j<fos.size();j ){ //取出子弹对象 FlyObject fo=fos.get(j); //获取子弹和怪物的坐标位置 int fo_x=fo.location.x; int fo_y=fo.location.y; int en_x2=en.location.x; int en_y2=en.location.y; //计算怪物和子弹之间的距离(也可以采用if(横坐标的差值<某数&纵坐标的差值<某数) int distance_fo_en=(int)Math.sqrt(Math.pow((fo_x-en_x2),2) Math.pow((fo_y-en_y2),2)); if(distance_fo_en<=50){ //这里en(怪物)的HP是血量,fo(子弹)的HP是伤害值。 en.HP-=fo.HP; //在该子弹位置添加一个子弹爆炸效果,后面会介绍 explosion(fos.get(j)); //将该子弹从列表中移除 fos.remove(j); if(en.HP<=0){ //怪物爆炸效果 explosion(enemys.get(i)); //这里如果直接用enemys.remove(i)会导致循坏for(int j=0;j<fos.size();j )继续执行,误删其他元素 enemys.get(i).img=null; //把怪物图片去除(每次画图就不画该怪物了),然后把它移出屏幕 enemys.get(i).location=new Vector(-1000,0); if(en.imgName.equals(fileAddress "怪物.png")){ score =10; }else if(en.imgName.equals(fileAddress "怪物2.png")){ score =50; } } } } } }飞机大战制作Step3:爆炸动效 前面说到过爆炸动效也可以放进FlyObject类列表中,完成爆炸动效需要写两个方法,一个方法生成爆炸动效对象,一个方法绘制爆炸动效。因为爆炸动效一般都是在子弹或者怪物消失的时候才会生成,所以只生成一次;但是绘制爆炸动效需要多次绘制,所以生成爆炸动效对象和绘制爆炸动效需要分成两个方法来写。 ———————————————— 版权声明:本文为CSDN博主「一旭日东升一」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_44710412/article/details/113283913飞机大战制作Step3:爆炸动效

//爆炸动效 public void explosion(FlyObject flo){ //判断是什么对象爆炸 if(flo.imgName.equals(fileAddress "怪物.png")|flo.imgName.equals(fileAddress "怪物2.png")){ //获取爆炸对象的坐标 int x_explo=flo.location.x; int y_explo=flo.location.y; Vector location=new Vector(x_explo,y_explo); //生成爆炸动效对象 FlyObject explo=new FlyObject(location,null,null,"爆炸_1.png",10); //将爆炸动效对象添加到列表中 explotions.add(explo); } } //绘制爆炸动效 public void drawExplo(Graphics bufg_explotion){ //依次将列表中的每个爆炸图像画出 for(int i=0;i<explotions.size();i ){ explotions.get(i).drawFO(bufg_explotion); //这里的HP表示的是这个爆炸效果持续的时间,每画一次效果HP减一,当HP等于0时停止绘制该爆炸效果 explotions.get(i).HP--; if(explotions.get(i).imgName.equals(fileAddress "爆炸_1.png")){ //下面这条代码的作用是每画完一次图像就更换一次图片,以此达到动态变化的效果 ImageIcon imgicon=new ImageIcon(fileAddress "爆炸_" ((explotions.get(i).HP%3) 1) ".png");//因为我绘制的爆炸效果图片一共有三张,所以这里取除以三的余数来设定图片的文件名 explotions.get(i).img=imgicon.getImage(); } //当爆炸动效对象的HP等于0时移除该对象 if(explotions.get(i).HP==0){ explotions.remove(i); } } }飞机大战制作Step4:游戏暂停/继续,判定游戏结束

//游戏暂停/开始 public void on_off(){ gameRest=!gameRest; }

//判断游戏是否结束 public void judgeGameOver(Graphics g_judgeGameOver){ for(int i=0;i<enemys.size();i ){ FlyObject en=enemys.get(i); FlyObject mp=mps.get(mps.size()-1); int mp_x=mp.location.x; int mp_y=mp.location.y; int en_x=en.location.x; int en_y=en.location.y; int distance_mp_en=(int)Math.sqrt(Math.pow((mp_x-en_x),2) Math.pow((mp_y-en_y),2)); if(distance_mp_en<=60){ //绘制gameOver图片 ImageIcon imgicon_gamover=new ImageIcon(fileAddress "gameover.png"); Image img_gamover=imgicon_gamover.getImage(); g_judgeGameOver.drawImage(img_gamover,0,0,null); gameOver=true; } } }

if(gameOver==true){break;}飞机大战制作Step5:刷新分数

//获取万位 int number_5=score/10000; //获取千位 int number_4=(score-number_5*10000)/1000; //获取百位 int number_3=(score-number_5*10000-number_4*1000)/100; //获取十位 int number_2=(score-number_5*10000-number_4*1000-number_3*100)/10; //获取个位 int number_1=score-number_5*10000-number_4*1000-number_3*100-number_2*10;

//生成图片对象 ImageIcon imgicon_score=new ImageIcon(fileAddress "Score.png"); Image img_score=imgicon_score.getImage(); ImageIcon imgicon5=new ImageIcon(fileAddress number_5 ".png"); Image img5=imgicon5.getImage(); ImageIcon imgicon4=new ImageIcon(fileAddress number_4 ".png"); Image img4=imgicon4.getImage(); ImageIcon imgicon3=new ImageIcon(fileAddress number_3 ".png"); Image img3=imgicon3.getImage(); ImageIcon imgicon2=new ImageIcon(fileAddress number_2 ".png"); Image img2=imgicon2.getImage(); ImageIcon imgicon1=new ImageIcon(fileAddress number_1 ".png"); Image img1=imgicon1.getImage(); //bufg_score是该方法导入的Graphics类画布 bufg_score.drawImage(img_score, 340,50,null); bufg_score.drawImage(img5, 590,50,null); bufg_score.drawImage(img4, 650,50,null); bufg_score.drawImage(img3, 710,50,null); bufg_score.drawImage(img2, 770,50,null); bufg_score.drawImage(img1, 830,50,null);

游戏源代码及游戏素材链接可私信小编获取

可以优化的地方:

  1. 有的子弹会穿过怪物,或者有时候碰到怪物没有死,说明判断碰撞和物体移动的方法还有缺陷。
  2. 怪物血量减少到一定程度时出现破损效果,这样看起来对怪物剩余血量更直观
  3. 游戏玩法比较单一,可以给飞机适当增加新的技能,增加关卡和Boss,丰富玩法
  4. 缺少游戏开始界面、背景音乐、音效等
  5. 游戏玩到后期比较卡顿,因为飞出窗体的子弹、怪物等仍然存在列表中,每次绘制图片时都要将这些看不见的对象重新再画一遍,十分消耗性能。
游戏二:接豆人

游戏演示:

额...视频只允许添加一次

Java原创游戏分享

游戏介绍:

接豆人制作Step1:金币礼包和蜘蛛的触发效果

public int rewardTime;//奖励时间 public Boolean pause=false;//是否进入眩晕状态 public int pauseTime;//眩晕时间 public FlyObject mp_pause;//用于绘制眩晕时接豆人的图片

//生成下落物 public void generateDrop(){ if(rewardTime>0){ if(len%1==0){ rewardTime--;//每次rewardTime递减 Random ran=new Random(); Vector location=new Vector(ran.nextInt(750) 50,50); Vector speed=new Vector(0,ran.nextInt(1) 10); Vector acce=new Vector(0,2); FlyObject fo=new FlyObject(location,speed,acce,"金币1.png"); fos.add(fo); } }else{//生成其他掉落物 }

//绘制我机 public void draw_mp(){ if(pause==false){ if(mps.size()-5>=0){ FlyObject mp=mps.get(mps.size()-5); mp.drawFO(bufg); } }else{ //当pause为true时执行 pauseTime--;//pauseTime递减 mp_pause.drawFO(bufg);//绘制接豆人眩晕时的图片 if(pauseTime==0){ pause=false;//当pauseTime减少到0时将pause改回为false } } }接豆人制作Step2:游戏重新开始

if(thc.gameOver){ if(e.getX()>340&e.getX()<540&e.getY()>630&e.getY()<710){ thc.life=3; thc.fos.removeAll(fos); thc.mps.removeAll(mps); thc.score=0; thc.gameOver=false; } }接豆人制作Step3:清理列表数据,提升流畅度

//清理缓存(在run方法中调用该方法) public void clear(){ //每500轮清理一次 if(lenP0==0){ System.out.println("清理前:"); System.out.println("fos size is" fos.size()); System.out.println("mps size is" mps.size()); System.out.println("exps size is" explotions.size()); clearList(fos,0); clearList(mps,1); clearList(explotions,0); System.out.println("清理后:"); System.out.println("fos size is" fos.size()); System.out.println("mps size is" mps.size()); System.out.println("exps size is" explotions.size()); } } //清理列表(传入需要清理的列表,并传入清理类型) public void clearList(ArrayList<FlyObject> fos,int flag){ int fos_size=fos.size(); //其他飞行物类型的清理 if(flag==0){ for(int i=fos.size()-10;i>-1;i--){ //判断一下从哪个飞行物开始超出窗体可见范围(在它之前的飞行物一定是超过了) if(fos.get(i).location.y>1000){ for(int j=0;j<i;j ){ fos.remove(0);//不断删除列表的第一个元素,直到删到开始超出窗体范围的那一个 } break; } } //接豆人的列表的清理 }else if(flag==1){ //只保留列表中最后一百个元素,前面的全部删除 for(int i=0;i<fos_size-100;i ){ fos.remove(0); } } }

游戏源代码及游戏素材链接可私信小编获取

游戏三:双线挑战(双人游戏)

游戏截图:

游戏介绍:

游戏皮肤:

双线挑战制作Step1:键盘监听器的使用

class Listener implements KeyListener{ public void keyTyped(KeyEvent e) { } public void keyPressed(KeyEvent e) { //获取按下键的keycode int keyc=e.getKeyCode(); System.out.println(keyc " is pressed!"); //也可以使用String press=e.getKeyChar() "";这样获取到的就是键盘的字符 } public void keyReleased(KeyEvent e) { //获取松开键的keycode int keyc=e.getKeyCode(); System.out.println(keyc " is released!"); } }

//设置窗体可见,jf是创建的JFrame对象 jf.setVisible(true); jf.addKeyListener(mou);//为窗体添加键盘监听器 jf.requestFocusInWindow();//窗体获得焦点,记得要放在窗体可见之后

双线挑战制作Step2:用键盘控制线条的走向

//我们可以先定义一个整数flag1 public int flag1=0;

//只画一次图片 public void draw_just_once(int type){ //如果说flag1为0,则开始画图 if(flag1==0){ ImageIcon imgic=new ImageIcon(fileAddress "游戏背景_2.png"); Image img=imgic.getImage(); g.drawImage(img, 0,0,null); flag1 ;//更改flag1的值,表示图已画过 } }

lb_blue=new LineBall(new Vector(0,0),new Vector(1,0));

public void drawLB(Graphics g){ if(imgName==null){ g.fillRect(location.x*10 50, location.y*10 50, 10,10); }else{ ImageIcon imgic=new ImageIcon(fileAddress imgName); Image img=imgic.getImage(); g.drawImage(img,location.x*10 50, location.y*10 70, null); } }

lb_blue.imgName="蓝_4.png"; lb_blue.drawLB(g);//画完以后让小方块move移动一次 lb_blue.move(); try{ Thread.sleep(50); }catch(Exception ef){}

public void keyReleased(KeyEvent e) { int keyc=e.getKeyCode(); System.out.println(keyc " is released!"); int speed=1; if(lb_blue.len!=0){ if(lb_blue.speed.y==0){ if(keyc==87){//w lb_blue.len=0; lb_blue.speed=new Vector(0,-speed); } if(keyc==83){//s lb_blue.len=0; lb_blue.speed=new Vector(0,speed); } } if(lb_blue.speed.x==0){ if(keyc==65){//a lb_blue.len=0; lb_blue.speed=new Vector(-speed,0); } if(keyc==68){//d lb_blue.len=0; lb_blue.speed=new Vector(speed,0); } } } }

双线挑战制作Step3:利用二维数组设定“棋盘”

public static int[][] chessBoard=new int [70][70];

//判断游戏是否结束 public Boolean judge_gameover(){ //判断棋子是否超出边界 if(location.x>69|location.y>69|location.x<0|location.y<0){ gameOver=true; return true; //判断棋子要放下的位置上原本有没有棋子 }else if(chessBoard[location.x][location.y]==1){ gameOver=true; return true; //如果上面两种情况都不是,则返回false }else{ gameOver=false; return false; } }

public void drawLB(Graphics g){ if(imgName==null){ //当棋子走到某一格时,将棋盘的这一格状态改为“有棋子” chessBoard[location.x][location.y]=1; g.fillRect(location.x*10 50, location.y*10 50, 10,10); }else{ //当棋子走到某一格时,将棋盘的这一格状态改为“有棋子” chessBoard[location.x][location.y]=1; ImageIcon imgic=new ImageIcon(fileAddress imgName); Image img=imgic.getImage(); g.drawImage(img,location.x*10 50, location.y*10 70, null); } }

双线挑战制作Step4:给游戏添加背景音乐

import java.applet.AudioClip; import java.net.MalformedURLException; import java.net.URL; import javax.swing.JApplet; public class PlayMusic { public AudioClip music = loadSound("此处输入需要播放的音乐文件路径(文件格式必须为WAV格式)"); public static AudioClip loadSound(String filename) { URL url = null; try { url = new URL("file:" filename); } catch (MalformedURLException e) {;} return JApplet.newAudioClip(url); } //音乐播放 public void play() { //音乐播放 music.play(); //循环播放 music.loop(); } }

PlayMusic p=new PlayMusic(); p.play();

就这么简单!

游戏源代码及游戏素材链接可以私信小编获取

一点点总结心得:

实现一个程序的步骤——

我想要实现什么效果?

为了实现这样的效果我要怎么做?

(开干!)

做好的效果和我的预期符合吗?如果不符合我要怎么修改?

搜集资料,撰写博客,和同学交流,对程序进一步优化

写在最后:

java给了我一种前所未有的体验,或者说一种前所未有的快感。只需要敲击键盘,就可以像在广阔的平原,凭空升起一座城堡。

复杂纷繁的代码,从我的手中获得了意义,获得了生气。在这个世界里,犹如掌握了“生*大权”,游戏的一切都由我来定义。

飞机长什么样子,怪物又长什么样子;飞机一次打多少发子弹,怪物吃多少子弹会被*死;怪物以什么姿态出生,又以什么姿态死去……

每一个程序的活泼生动,都是用一条条朴实无华的代码堆砌的。手握代码,我们就是这个世界的造物主!

原文链接:https://blog.csdn.net/weixin_44710412/article/details/113283913

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved