坦克大战

后面开始学习怎么使用java制造一个坦克大战游戏
但是不是直接开始做,而是随着这个游戏程序的制造,一边学习新知识融入到游戏中。包括多线程,反射,IO流…

Java坐标体系

在几乎所有的坐标中都有一个x轴和y轴,根据x,y的不同数据可以从x轴和y轴出发一条线,而这两条线就会形成一个交叉点。
x轴和y轴的出发点交叉点,叫做原点。如图所示

像素

计算机在屏幕上显示的内容都是由像素组成的,例如1080*1920,表示每行有1920个像素,每列有1080个像素。所以整个屏幕有2073600个像素,所以像素是密度单位,不是长度单位。

例如:你在1080的显示屏上使用x,y轴画了两条线,再使用2k的显示屏打开时,你会发现缩小了。
这里就是因为屏幕能显示的像素变多了,所以整体看着就觉得缩小了

Java绘图

使用Java画一个圆
在现实中绘画,需要{ 画框,画板,笔},在java中也有对应的类

  1. 定义一个自己的面板类,继承Java的面板类JPanel相当于画板。
    JPanel有个方法paint,可以使用画笔Graphics类对象的方法进行绘制
  2. 定义一个自己的框架类,也就是显示的窗口,继承Java的框架类JFrame
    在框架类的无参构造器中 把画板添加到框架里,且设置框架的尺寸和什么时候关闭程序
    JFrame有add方法可以将画板添加到框架里,setDefaultCloseOperation方法觉得啥时候关闭框架,结束程序
    还可以设置框架的尺寸,
public class test {public static void main(String[] args) {//11.实例化一个框架(框架的无参构造器,已经创建了面板和画笔了)new CircleFrame();}
}
//1.先定义一个自己的面板类(画板),继承Java的面板类,画画就是在画板上画
class MyPanel extends JPanel{//2.重写JPanel的paint方法(画笔方法),这里编写你要用画笔干啥,Graphics g可以理解为画笔@Overridepublic void paint(Graphics g) {super.paint(g);//调用父类的方法,完成初始化System.out.println("paint方法运行");//3.画一个圆g.drawOval(20,20,100,100);//画圆的方法,x,y定义圆的起始位置,后面定义圆的宽和高}
}//4.定义一个展示面板的框架(窗口,可以理解为画框),继承Java的JFrame框架类
class CircleFrame extends JFrame{//5.定义一个面板变量MyPanel myPanel = null;public CircleFrame(){//无参构造器//6.初始化面板,实例化面板myPanel = new MyPanel();//7.将面板放到框架(窗口)里面this.add(myPanel);//8.设置框架(窗口)的尺寸this.setSize(500,500);//9.让窗口显示出来this.setVisible(true);//10.当点击了窗口的关闭键后退出程序this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

Graphics类的常用方法

  1. 画直线-drawLine(int x,int,y,int x2,int y2)
  2. 画矩形边框-drawRect(int x,int y,int width,int height)
  3. 画椭圆-drawOval(int x,int y,int width,int height)
  4. 填充矩形fillRect((int x,int y,int width,int height)
  5. 填充椭圆fillOval(int x,int y,int width,int height)
  6. 画图片-drawImage(Image img,int,int y…)
  7. 画字符串drawString(String str,int x,int y)
  8. 设置画笔的字体setFont(Font font)
  9. 设置画笔的颜色 setColor(Color c )

使用演示:

public class test {public static void main(String[] args) {new CircleFrame();}
}
class MyPanel extends JPanel{@Overridepublic void paint(Graphics g) {super.paint(g);System.out.println("paint方法运行");
//        1. 画直线-drawLine(int x,int,y,int x2,int y2)g.drawLine(10,10,50,50);
//        2. 画矩形边框-drawRect(int x,int y,int width,int height)g.drawRect(20,20,70,70);
//        3. 画椭圆-drawOval(int x,int y,int width,int height)g.drawOval(20,20,100,100);
//        4. 填充矩形fillRect((int x,int y,int width,int height)//需要先设置一下画笔的颜色g.setColor(Color.BLACK);g.fillRect(70,70,100,90);
//        5. 填充椭圆fillOval(int x,int y,int width,int height)//如果不改其他颜色,就不用再设置一下了,要换其他颜色,再重新调用setColorg.fillOval(30,30,60,60);
//        6. 画图片-drawImage(Image img,int,int y...)//需要先获取一下图片,需要提前把图片放在根目录,不然编译器找不到Image image = Toolkit.getDefaultToolkit().getImage(Panel.class.getResource("/4.jpg"));g.drawImage(image,70,70,860,360,this);
//        7. 画字符串drawString(String str,int x,int y)//可以先设置一个颜色和设置一下字体g.setColor(Color.PINK);g.setFont(new Font("微软雅黑",Font.BOLD,30));//字体,加粗,字体大小g.drawString("Java",90,110);
//        8. 设置画笔的字体setFont(Font font)
//        9. 设置画笔的颜色 setColor(Color c )}
}
class CircleFrame extends JFrame{MyPanel myPanel = null;public CircleFrame(){myPanel = new MyPanel();this.add(myPanel);this.setSize(500,500);this.setVisible(true);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}

绘制坦克大战的背景区域

思路:
按照前面的学习
定义画板类和画框类,然后直接在画板上新建一个和框架(窗口)大小一样的矩形(需要填充)即可

public class Tank {int x ;//坦克的横坐标int y ;//坦克的纵坐标
}
public class MyPanel extends Panel {@Overridepublic void paint(Graphics g){super.paint(g);g.fillRect(0,0,1000,950);}
}
public class myWindow extends JFrame {MyPanel  m = null;public myWindow(){m = new MyPanel();this.add(m);this.setSize(1000,950);this.setVisible(true);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}public static void main(String[] args) {new myWindow();}
}

绘制坦克

可以坦克有两个特性

不同朝向
不同阵营
所以可以将绘制坦克封装到方法里,根据不同参数绘制不同的坦克

public class MyPanel extends Panel {Tank tank;@Overridepublic void paint(Graphics g) {super.paint(g);System.out.println("调用paint");g.fillRect(0,0,500,600);drawTank(20,460,g,0,0);drawTank(90,350,g,0,1);}/**@param x 坦克的起始横坐标@param y 坦克的起始纵坐标@param g 画笔@param direct 根据方向绘制不同朝向的坦克@param type  根据0或者1 绘制不同颜色的坦克*/public void drawTank(int x,int y,Graphics g,int direct,int type){switch (type){case 0:g.setColor(Color.PINK);//自己的坦克就粉色break;case 1:g.setColor(Color.RED);//敌人的坦克就红色break;}switch (direct){case 0://0表示绘制方向朝上的坦克g.fill3DRect(x,y,10,50,false);g.fill3DRect(x+10,y+5,25,40,false);g.fill3DRect(x+35,y,10,50,false);g.fillOval(x+10,y+15,25,25);g.drawLine(x+22,y-5,x+22,y+25);break;default://其他情况暂不考虑break;}}
}

键盘监听

坦克大战肯定是要根据键盘的操作,坦克做出不同的动作
为了实现这个目标,需要了解一个接口

KeyListener接口,可以对键盘做出监听,获取到键盘的操作
KeyListener接口有三个方法

//字符输出时,该方法触发
public void keyTyped(KeyEvent e) {}

//有按键按下时,该方法触发
public void keyPressed(KeyEvent e) {}

//有按键松开时,该方法触发
public void keyReleased(KeyEvent e) { }

我们可以使用 e.getCode,获取到键盘对应的ASCII码
然后再根据ASCII码是对应的动作时 调用repaint方法,触发paint方法重绘画板

但是要在框架类 使用this.addKeyListener();方法把画板传进去

java事件处理机制

java事件处理是采取“委派事件模型”,当事件发生时,产生事件的对象,会把此“信息”,传递给“事件的监听者”处理,所谓“信息”实际上就是java.awt.event事件类库里某个类所创建的对象,把它称之为“事件的对象”

委派事件模型
什么是委派事件模型?

举例说明:
我通过微信向同学说“借我300块”,同学收到后,就发了红包给我

那么 事件源就是我要借钱,事件/对象,就是一条微信,同学就是事件监听者。他给我发红包就是对事件进行处理

在上面已经演示了键盘监听类 KeyEvent
java中还有其他的事件监听类

事件类 说明
ActionEvent 通常在按下按钮,或双击一个列表项或选中某个菜单时发生)
AdjustmentEvent 当操作一个滚动条时发生。
ComponentEvent: 当一个组件隐藏,移动,改变大小时发送。
ContainerEvent 当一个组件从容器中加入或者删除时发生。
FocusEvent 当一个组件获得或是失去焦点时发生。
ItemEvent 当一个复选框或是列表项被选中时,当一个选择框或选择菜
KeyEvent 当从键盘的按键被按下,松开时发生。
MouseEvent 当鼠标被拖动,移动,点击,按下…2
TextEvento 当文本区和文本域的文本发生改变时发生。
WindowEvent 当一个窗口激活,关闭,失效,恢复,最小化.

事件监听器接口

  1. 当事件源产生一个事件,可以传送给事件监听者处理
  2. 事件监听者,实际上就是一个类,这个类实现了某个事件监听器接口
  3. 事件监听者接口可以有多种,不同的事件监听者接口可以监听不同事件,一个类可以实现多个监听接口
  4. 这些接口通常在java.awt.event包和javax.swing.event包中定义,

让坦克动起来

要让坦克动起来,得先画出不同朝向的坦克
首先前面已经画出了朝上的,那么横坐标和纵坐标其实不用动,将宽和高调整即可

朝上的:
g.fill3DRect(x,y,10,50,false);
g.fill3DRect(x+10,y+5,25,40,false);
g.fill3DRect(x+35,y,10,50,false);
g.fillOval(x+10,y+15,25,25);
g.drawLine(x+22,y-5,x+22,y+25);
朝右的:
g.fill3DRect(x,y+7,50,10,false);
g.fill3DRect(x+5,y+14,40,25,false);
g.fill3DRect(x,y+37,50,10,false);
g.fillOval(x+10,y+15,25,25);
g.drawLine(x+25,y+25,x+58,y+25);
朝下的:
g.fill3DRect(x,y,10,50,false);
g.fill3DRect(x+10,y+5,25,40,false);
g.fill3DRect(x+35,y,10,50,false);
g.fillOval(x+10,y+12,25,25);
g.drawLine(x+22,y+55,x+22,y+25);
朝左的:
g.fill3DRect(x,y+7,50,10,false);
g.fill3DRect(x+5,y+14,40,25,false);
g.fill3DRect(x,y+37,50,10,false);
g.fillOval(x+10,y+15,25,25);
g.drawLine(x+25,y+25,x-8,y+25);

不同的方向都制造了好后,由于前面绘制坦克的是由drawTank方法的direct来决定的
所以我们在Tank类把他变成一个属性,方便后面监听事件的更改

public class MyPanel extends Panel implements KeyListener {int speek = 1;Tank tank;public MyPanel(){tank = new Tank(20,460,0);}@Overridepublic void paint(Graphics g) {super.paint(g);System.out.println("调用paint");g.fillRect(0,0,500,600);drawTank(tank.x,tank.y,g,tank.direct,0);}/**@param x 坦克的起始横坐标@param y 坦克的起始纵坐标@param g 画笔@param direct 根据方向绘制不同朝向的坦克@param type  根据0或者1 绘制不同颜色的坦克*/public void drawTank(int x,int y,Graphics g,int direct,int type){switch (type){case 0:g.setColor(Color.PINK);//自己的坦克就粉色break;case 1:g.setColor(Color.RED);//敌人的坦克就红色break;}switch (direct){//0上,1右,2下,3左case 0://0表示绘制方向朝上的坦克g.fill3DRect(x,y,10,50,false);g.fill3DRect(x+10,y+5,25,40,false);g.fill3DRect(x+35,y,10,50,false);g.fillOval(x+10,y+15,25,25);g.drawLine(x+22,y-5,x+22,y+25);break;case 1://1表示绘制方向朝右的坦克g.fill3DRect(x,y+7,50,10,false);g.fill3DRect(x+5,y+14,40,25,false);g.fill3DRect(x,y+37,50,10,false);g.fillOval(x+10,y+15,25,25);g.drawLine(x+25,y+25,x+58,y+25);break;case 2://2表示绘制方向朝下的坦克g.fill3DRect(x,y,10,50,false);g.fill3DRect(x+10,y+5,25,40,false);g.fill3DRect(x+35,y,10,50,false);g.fillOval(x+10,y+12,25,25);g.drawLine(x+22,y+55,x+22,y+25);break;case 3://3表示绘制方向朝左的坦克g.fill3DRect(x,y+7,50,10,false);g.fill3DRect(x+5,y+14,40,25,false);g.fill3DRect(x,y+37,50,10,false);g.fillOval(x+10,y+15,25,25);g.drawLine(x+25,y+25,x-8,y+25);break;default://其他情况暂不考虑break;}}@Override //字符输出时,该方法触发public void keyTyped(KeyEvent e) {}@Override//有按键按下时,该方法触发public void keyPressed(KeyEvent e) {if (e.getKeyCode() == 87){//前进moveUp();tank.direct = 0;}else if(e.getKeyCode() == 83){moveDown();tank.direct = 2;}else if(e.getKeyCode() == 65){moveLeft();tank.direct = 3;}else if(e.getKeyCode() == 68){moveRight();tank.direct = 1;}else if(e.getKeyCode() == 32){System.out.println("氮气加速~");speek +=5;}else{System.out.println(e.getKeyCode());}repaint();}@Override//有按键松开时,该方法触发public void keyReleased(KeyEvent e) {}public void moveUp(){tank.y-=speek;}public void moveLeft(){tank.x-=speek;}public void moveRight(){tank.x+=speek;}public void moveDown(){tank.y+=speek;}
}

画出敌人坦克

因为敌人坦克后面肯定是有自己的特性的所以新建一个EnemyTanks类
敌人坦克肯定不止一个,所以需要集合
且后面会运用到多线程,所以使用Vector集合来存储敌人坦克,提高安全性
然后遍历集合绘制敌人坦克

public class MyPanel extends Panel implements KeyListener {int speek = 1;Tank tank;Vector<EnemyTanks> enemyTanks = new Vector<>();public MyPanel(){tank = new Tank(20,460,0);for (int i = 0; i < 3; i++) {EnemyTanks enemyTank = new EnemyTanks(100*(i+1),0,2);enemyTanks.add(enemyTank);}}@Overridepublic void paint(Graphics g) {super.paint(g);System.out.println("调用paint");g.fillRect(0,0,500,600);//画我方坦克drawTank(tank.x,tank.y,g,tank.direct,0);for (int i = 0; i < enemyTanks.size(); i++) {EnemyTanks e = enemyTanks.get(i);//画敌方坦克drawTank(e.x,e.y,g,e.direct,1);}}/**@param x 坦克的起始横坐标@param y 坦克的起始纵坐标@param g 画笔@param direct 根据方向绘制不同朝向的坦克@param type  根据0或者1 绘制不同颜色的坦克*/public void drawTank(int x,int y,Graphics g,int direct,int type){switch (type){case 0:g.setColor(Color.PINK);//自己的坦克就粉色break;case 1:g.setColor(Color.RED);//敌人的坦克就红色break;}switch (direct){//0上,1右,2下,3左case 0://0表示绘制方向朝上的坦克g.fill3DRect(x,y,10,50,false);g.fill3DRect(x+10,y+5,25,40,false);g.fill3DRect(x+35,y,10,50,false);g.fillOval(x+10,y+15,25,25);g.drawLine(x+22,y-5,x+22,y+25);break;case 1://1表示绘制方向朝右的坦克g.fill3DRect(x,y+7,50,10,false);g.fill3DRect(x+5,y+14,40,25,false);g.fill3DRect(x,y+37,50,10,false);g.fillOval(x+10,y+15,25,25);g.drawLine(x+25,y+25,x+58,y+25);break;case 2://2表示绘制方向朝下的坦克g.fill3DRect(x,y,10,50,false);g.fill3DRect(x+10,y+5,25,40,false);g.fill3DRect(x+35,y,10,50,false);g.fillOval(x+10,y+12,25,25);g.drawLine(x+22,y+55,x+22,y+25);break;case 3://3表示绘制方向朝左的坦克g.fill3DRect(x,y+7,50,10,false);g.fill3DRect(x+5,y+14,40,25,false);g.fill3DRect(x,y+37,50,10,false);g.fillOval(x+10,y+15,25,25);g.drawLine(x+25,y+25,x-8,y+25);break;default://其他情况暂不考虑break;}}@Override //字符输出时,该方法触发public void keyTyped(KeyEvent e) {}@Override//有按键按下时,该方法触发public void keyPressed(KeyEvent e) {if (e.getKeyCode() == 87){//前进moveUp();tank.direct = 0;}else if(e.getKeyCode() == 83){moveDown();tank.direct = 2;}else if(e.getKeyCode() == 65){moveLeft();tank.direct = 3;}else if(e.getKeyCode() == 68){moveRight();tank.direct = 1;}else if(e.getKeyCode() == 32){System.out.println("氮气加速~");speek +=5;}else{System.out.println(e.getKeyCode());}repaint();}@Override//有按键松开时,该方法触发public void keyReleased(KeyEvent e) {}public void moveUp(){tank.y-=speek;}public void moveLeft(){tank.x-=speek;}public void moveRight(){tank.x+=speek;}public void moveDown(){tank.y+=speek;}
}

1.0完成

至此坦克大战1.0完成,后面学习了多线程再制造2.0版本,让敌人坦克也动起来。

java坦克大战(1.0)相关推荐

  1. [ java ] 坦克大战 5.0 ~ 最终完整版

    坦克大战5.0 新增功能内容:(加入IO流内容) 防止敌坦克间重叠 击杀数显示 保存上局游戏进度–>两种开局方式 加入开局音乐 修复记录文件丢失后的异常 5.0版本为最终版 提示:爆炸图片需自行 ...

  2. java坦克大战(2.0)

    坦克大战(2.0) 在前面的坦克大战1.0已经完成了移动 绘制我方/敌方坦克. 接下来会运用到前面学习的多线程的基础,来实现发射子弹的效果 发射子弹 想要坦克发射子弹,可以用以下思路 按J发射子弹 将 ...

  3. java 坦克大战_java课程设计之坦克大战

    本文实例为大家分享了java坦克大战的具体代码,供大家参考,具体内容如下 环境要求: 操作系统:Windows 10 JAVA虚拟机:JDK1.8以上 开发环境:Eclipse(4.5以上) 功能提示 ...

  4. 坦克大战2.0,3.0,4.0版本

    1.坦克大战 0.3 在坦克大战游戏(0.2版)基础上添加如下功能:当玩家按一下j键,就发射一颗子弹. 编写Shot类 package com.yt.tankgame03;/*** 射击子弹*/ pu ...

  5. 韩老师坦克大战2.0版本

    本博文源于对b站视频韩老师(韩顺平)的java学习,本章学习坦克大战2.0版本,用多线程实现,本章内容还是比较多的,先看内容效果 内容效果 开局 被打死(黄色是hero) 打死别人 源码 Bomb.j ...

  6. java坦克大战课设报告_java课程设计之坦克大战

    本文实例为大家分享了java坦克大战的具体代码,供大家参考,具体内容如下 环境要求: 操作系统:Windows 10 JAVA虚拟机:JDK1.8以上 开发环境:Eclipse(4.5以上) 功能提示 ...

  7. Java坦克大战游戏源码(java坦克大战)

    Java坦克大战游戏源码(java坦克大战) public Swingtest002() {// 设置标题setTitle("请登陆");// 绝对布局setLayout(null ...

  8. java 坦克大战 教程_[Java教程]坦克大战(一)

    [Java教程]坦克大战(一) 0 2016-09-16 08:00:05 坦克大战(一) 相信大家对坦克大战都不陌生,并且网上也有很多用java实现的小程序,最近用了几天时间将其使用javaScri ...

  9. Java坦克大战,基于Swing编写很哇塞的小游戏,可以做课程设计毕业设计

    Java坦克大战,基于Swing编写很哇塞的小游戏,可以做课程设计毕业设计 有图有真相 操作方法:ASDW控制移动,鼠标控制炮筒旋转,鼠标左键开枪,空格发射炮弹, 开发思路是标准的游戏开发思路,单线程 ...

最新文章

  1. 第十七篇:信息抽取Information Extraction
  2. 2021-07-27查看图像像素值类别
  3. AI(人工智能)下一个偏门行业赚钱的契机
  4. python【数据结构与算法】多字段条件排序
  5. Linux网络编程(一):Linux内核
  6. Scala里的类型擦除 - type erase
  7. 10G_Ethernet_01 万兆以太网设计引言
  8. 使用SpringBoot AOP 记录操作日志、异常日志
  9. spark mysql 交互_Spark - 直接操作数据源 MySQL
  10. [python] 函数小结
  11. anguarjs 上传图片预览_JS控制上传图片个数,预览上传图片
  12. artTemplate-3.0
  13. [2014.3.23]cse::lab2::partD 简明攻略
  14. SimpleDateFormat多线程下的安全问题(解决方法)
  15. MATLAB--求解矩阵方程
  16. Centos中安装memcached
  17. 保密安全风险自评估单机版检查工具V1.5
  18. Bartender编辑数据小标题中嵌入的数据更改无效,无法在条码中显示已经扫描的条码号
  19. 使用 UICollectionView 实现网格化视图效果
  20. 计算机信息检索自考知识点,计算机信息检索02139自考资料.docx

热门文章

  1. MacOS连接VPN 提醒 “IPSec共享密钥”丢失。请验证您的设置并尝试重新连接。
  2. 遐想:Android Nexus One Flan
  3. 贵有恒,何必三更眠五更起;最无益,莫过一日暴十日寒。
  4. vim的安装以及基础使用方法;
  5. Linux网络流量控制工具—Netem
  6. 实现链表的插入——头插/尾插
  7. 怎么把苹果手机通讯录导入华为手机_怎么恢复手机通讯录?最完整手机通讯录恢复方法大公开...
  8. 如何使用python进行等额本金-等额本息贷款计算
  9. 增加内存会让计算机变快吗?
  10. 批量修改计算机用户名,域环境下批量修改计算机名