JAVA项目:Java实现飞扬的小鸟(Flappy Bird)_java项目飞行的小鸟(1)

还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!

王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。

对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!

【完整版领取方式在文末!!】

93道网络安全面试题

需要体系化学习资料的朋友,可以加我V获取:vip204888 (备注网络安全)

内容实在太多,不一一截图了

黑客学习资源推荐

最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

😝朋友们如果有需要的话,可以联系领取~

1️⃣零基础入门
① 学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

image

② 路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

image-20231025112050764

2️⃣视频配套工具&国内外网安书籍、文档
① 工具

② 视频

image1

③ 书籍

image2

资源较为敏感,未展示全面,需要的最下面获取

在这里插入图片描述在这里插入图片描述

② 简历模板

在这里插入图片描述

因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!


step4:创建Main类,表示程序的入口:


代码实现:



package com.ruby.demo;
/**

  • 程序的入口
  • @author ruby

*/

public class Main {

public static void main(String[] args) {
GameFrame frame = new GameFrame();
frame.initFrame();
}

}


运行效果:


![](https://img-blog.csdnimg.cn/img_convert/e4d651e22aca708a8044e16903fc4ef0.png)


#### **2、实现地面移动**


思路:



首先得先在Constant常量类中,添加地面的图片路径,并且将地面图片拷贝到pics资源目录下。



// 地面图片路径
public static String PATH_GROUND = PATH_PIC + “ground.png”;


然后创建Ground类:


然后创建Ground类:



package com.ruby.demo;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;

/**

  • step1:地面类
  • @author ruby

*/
public class Ground {
public BufferedImage img = null;// 地面图片
public int x, y;// 地面绘制的起始坐标
public int width = 0;// 地面的宽度
public int height = 0;// 地面的高度
private static Ground instance = null;

private Ground() {
try {
// 单例模式
BackGround bg = BackGround.getInstance();
// ImageIO用于加载图片资源
// this.getClass().getResource根据当前路径加载图片
img = ImageIO.read(this.getClass().getResource(Constant.PATH_GROUND));

// 获取地面图片的长度和高度
width = img.getWidth();// 获取图片的宽度
height = img.getHeight();// 获取图片的宽度

x = 0;
y = bg.height - height;// 背景高度与地面图片高度的差值就是地面图片的起始Y坐标
System.out.println(“widthGround=” + width + “, heightGround=” + height);
System.out.println(“x=” + x + “, y=” + y);

} catch (IOException e) {
e.printStackTrace();
}
}

// 实现懒汉式
public static Ground getInstance() {
if (instance == null) {
instance = new Ground();
}
return instance;
}
}


说明:在该类中要计算出地面的坐标点x和y。


x为0即可,而y的值为背景图片的高度减去地面图片的高度。


然后添加一个地面移动的方法:



// 地面移动
public void move(BackGround bg) {
x–;
if (x == bg.width +9 - width) {// 9为修正值,根据地面移动效果调整该数值,保证图片移动自然流畅。是地面图片中条纹间距的一半数值。
x = 0;
}
System.out.println(“x=” + x);
}


所谓的运动地面,就是就是修改x的值,地面向左侧移动,所以x--。


然后要修改GamePanel中的paint()方法,绘制地面:



@Override
public void paint(Graphics g) {
super.paint(g);
System.out.println(“paint方法被调用” + getCurrentTime());
// Graphics对象绘制背景图案
g.drawImage(bg.img, 0, 0, null);

// 绘制地面
g.drawImage(ground.img, ground.x, ground.y, null);
}


然后在GamePanel类中添加一个新增的方法action(),表示游戏的动作,我们需要设置一个死循环,来让地面不停的移动。


多久移动一次呢,我们可以设置一个速度,其实就表示游戏的速度,可以初始化一个常量,每当过一关,游戏的速度可以适当的增加。


现在定义一个常量:



public static int MOVE_SPEED = 40;// 地面及柱子移动初始速度。当积分累加,速度会递增


在GamePanel类中添加一个变量speed,表示速度:



private int speed = 0;// 柱子和地面的移动速度


修改GamePanel()构造方法:



// 初始化速度
speed = Constant.MOVE_SPEED;


然后添加一个action()方法,



public void action() {
// 设置鼠标监听

// 设置键盘监听

// 通过监听鼠标事件,监听到state的变化,无限循环,不断切换状态
while (true) {
// 地面移动
ground.move(bg);

// 线程休眠(因为是无限循环,下一次循环开始需要一段休息时间,这样才能让程序有缓冲的执行时间)
try {
Thread.sleep(1000 / speed);// 调节游戏速度
// 重新绘制(重新调用面板paint方法)
this.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}

}


为了不让地面移动太快,频繁的绘制界面,我们需要让程序睡眠一下,这个睡眠的时间,其实表示游戏的速度,就是地面和柱子移动的速度。


然后在GameFrame的initFrame()方法中,调用action()方法:



// 面板运行
panel.action();


运行效果:


![](https://img-blog.csdnimg.cn/img_convert/1af0e4eb88a1c828720d8bc49fcc6094.png)


#### **3、显示开始和结束**


思路:整个游戏分为3个状态:游戏开始前,开始玩,游戏结束。定义一个变量state,0表示未开始,1表示玩ing,2表示game over,游戏结束。


当游戏未开始状态,显示开始图片。


点击开始游戏后,可以玩,当小鸟撞到地面或者天空或者柱子,游戏结束。


游戏结束时,显示结束图片。


在GamePanel类中,添加一个变量state



private static int state = 0;// 游戏状态,0表示游戏未开始,1表示游戏正在进行,2表示游戏结束


然后在构造方法中,初始化state的状态,以及加载开始和结束的图片:



/*

  • 构造函数
    */
    public GamePanel() {

    // 初始化数据

    // 单例模式声明背景对象和地面对象
    bg = BackGround.getInstance();
    ground = Ground.getInstance();
    // state = 0表示游戏未开始
    state = 0;

    try {

    // 加载开始和结束图片
    imgStart = ImageIO.read(this.getClass().getResource(Constant.PATH_START));
    imgOver = ImageIO.read(this.getClass().getResource(Constant.PATH_GAMEOVER));

    } catch (IOException e) {
    e.printStackTrace();
    }

    }

同时将两张图片,添加到pics目录下,并且在Constant类中,添加常量值:



public static String PATH_START = PATH_PIC + “start.png”;
public static String PATH_GAMEOVER = PATH_PIC + “gameover.png”;


修改绘图的方法paint(),先绘制背景,然后根据状态不同,绘制不同的图案,最后绘制地面:



@Override
public void paint(Graphics g) {
super.paint(g);
System.out.println(“paint方法被调用” + getCurrentTime());
// Graphics对象绘制背景图案
g.drawImage(bg.img, 0, 0, null);

// 根据状态,绘制不同的图案
if (state == 0) {//游戏未开始
// 游戏未开始时,绘制开始图案及小鸟
g.drawImage(imgStart, 0, 0, null);

} else if (state == 1) {// 游戏开始后

} else if (state == 2) {// 游戏结束
  // 游戏结束时,绘制结束图案
  g.drawImage(imgOver, 0, 0, null);
}


// 绘制地面
g.drawImage(ground.img, ground.x, ground.y, null);
}


修改action()方法,添加鼠标事件:



public void action() {
// 设置鼠标监听
this.addMouseListener(new MouseAdapter() {
//点击鼠标后
@Override
public void mouseReleased(MouseEvent e) {
super.mouseReleased(e);
switch (state) {
case 0://游戏未开始
// 切换到状态1时的数据
state = 1;
break;

    case 1://开始游戏
      state = 2;//...
      break;
      
    case 2://游戏结束
      //游戏结束后,更改状态为0,可以继续下一次游戏
      state = 0;
      break;


default:
break;
}

  }
});

// 设置键盘监听

//…

}


运行效果:


![](https://img-blog.csdnimg.cn/img_convert/aa7fd617fa0f8a7a8a47df6aabaf25c0.png)


点击一下,开始游戏,再点一下结束游戏,效果如图:


![](https://img-blog.csdnimg.cn/img_convert/f014210efbbc5cfe452e52d224f53ab8.png)


开始游戏的时候,小鸟是灰色的,我们希望小鸟能一直扇动翅膀。


小鸟翅膀扇动,其实就是小鸟的8张图循环轮播。我们可以通过数组来实现。


现在Constant类中定义小鸟的图片数量,以及小鸟的初始位置:



public static int BIRD_PIC_COUNT = 8;// 小鸟皮肤个数
public static int BIRD_POSITION_X = 190;// 小鸟初始化坐标
public static int BIRD_POSITION_Y = 220;


然后创建一个小鸟类Bird:



package com.ruby.demo;

import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageIO;

/**

  • 小鸟类
  • @author ruby

*/
public class Bird {
public BufferedImage img = null;// 小鸟图片
public BufferedImage imgs[] = new BufferedImage[Constant.BIRD_PIC_COUNT];// 数组,存储所有小鸟图案
public static int index = 0;// 当前皮肤的序号
public int x, y;// 初始坐标
public int width = 0;// 小鸟的宽度
public int height = 0;// 小鸟的高度

public Bird() {
try {
for (int i = 0; i < 8; i++) {
imgs[i] = ImageIO.read(getClass().getResource(Constant.PATH_PIC + i + “.png”));
}
img = imgs[0];
// 获取小鸟的宽度和高度
width = img.getWidth();
height = img.getHeight();

// 初始化小鸟的坐标位置
x = Constant.BIRD_POSITION_X;
y = Constant.BIRD_POSITION_Y;
} catch (IOException e) {
e.printStackTrace();
}
}

}


添加一个小鸟扇动翅膀的方法:



// 小鸟飞翔的图片切换
public void fly() {
index++;
// 小鸟图形切换的频率,index/x,x越大,翅膀切换频率越慢
img = imgs[index / 6 % Constant.BIRD_PIC_COUNT];
if (index == 6 * Constant.BIRD_PIC_COUNT) {
index = 0;
}
}


然后在GamePanel类中添加小鸟对象,



private Bird bird = null;// 声明小鸟对象


并在构造方法中初始化:



// 声明小鸟对象
bird = new Bird();


修改paint()方法,在未开始游戏的时候,就要绘制小鸟了:



// 根据状态,绘制不同的图案
if (state == 0) {// 游戏未开始
// 游戏未开始时,绘制开始图案及小鸟
g.drawImage(imgStart, 0, 0, null);
g.drawImage(bird.img, bird.x, bird.y, null);

} else if (state == 1) {// 游戏开始后

} else if (state == 2) {// 游戏结束
// 游戏结束时,绘制结束图案
g.drawImage(imgOver, 0, 0, null);
}


修改action()方法,在循环中,除了移动地面外,还要让小鸟扇动翅膀:



// 通过监听鼠标事件,监听到state的变化,无限循环,不断切换状态
while (true) {
// 地面移动
ground.move(bg);
bird.fly();

// 线程休眠(因为是无限循环,下一次循环开始需要一段休息时间,这样才能让程序有缓冲的执行时间)
try {
Thread.sleep(1000 / speed);// 调节游戏速度
// 重新绘制(重新调用面板paint方法)
this.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}


运行结果:


![](https://img-blog.csdnimg.cn/img_convert/c5b84cc4cb6283a541e18e737ad30f94.png)


#### **4、游戏开始**


游戏开始后,小鸟就要移动了。还要添加上下两根柱子,柱子向左侧移动,通过点击鼠标,让小鸟上下移动,来躲避柱子。


#### **小鸟上下飞动**


我们现在实现小鸟的部分:


游戏开始时,小鸟在距离屏幕左侧120左右的位置就可以:


在Constant类中定义,游戏开始时小鸟的位置:



public static int BIRD_FLY_POSITION_X = 120;// 小鸟开始飞翔时初始坐标


首先修改action()中,case 0里,先修改小鸟的位置



public void action() {
// 设置鼠标监听
this.addMouseListener(new MouseAdapter() {
// 点击鼠标后
@Override
public void mouseReleased(MouseEvent e) {
super.mouseReleased(e);
switch (state) {
case 0:// 游戏未开始
// 切换到状态1时的数据
state = 1;
bird.x = Constant.BIRD_FLY_POSITION_X;// 小鸟飞的初始x坐标
break;

}


然后在paint()方法中,state如果为1,代表游戏开始,应该绘制小鸟和两根柱子,我们先画小鸟:



else if (state == 1) {// 游戏开始后
//绘制小鸟和两根柱子
g.drawImage(bird.img, bird.x, bird.y, null);

}


运行效果:


![](https://img-blog.csdnimg.cn/img_convert/d4ca8691b678b4949eb9025ac82f26f4.png)


小鸟默认会向下掉,要考虑重力加速度。当点击鼠标的时候,会向上移动。


先在Constant提供常量:



public static double GRAVITATIONAL_ACCELERATION = 9.8;
public static double DOWN_TIME = 0.18; // 小鸟自然下降的时长


  
 在小鸟Bird类中,提供一些变量:



public double g = Constant.GRAVITATIONAL_ACCELERATION; // 重力加速度
public double v = 0;// 下降速度
public double t = Constant.DOWN_TIME;// 下降时间
public double h;// 下降的距离


再添加两个方法:down()表示下降



// 小鸟自然下降
public void down() {
v = v - g * t; // 末速度Vt=Vo-gt
h = v * t - g * t * t / 2; // 位移h=Vot-gt²/2
y = y - (int) h;
}


然后修改action()方法:



while (true) {
// 地面移动
ground.move(bg);
bird.fly();
if(state == 0){

  }else if(state == 1){
    bird.down();//小鸟下降
  }else if(state == 2){
    
  }
  
  // 线程休眠(因为是无限循环,下一次循环开始需要一段休息时间,这样才能让程序有缓冲的执行时间)
  try {
    Thread.sleep(1000 / speed);// 调节游戏速度
    // 重新绘制(重新调用面板paint方法)
    this.repaint();
  } catch (Exception e) {
    e.printStackTrace();
  }
}

运行结果:


![](https://img-blog.csdnimg.cn/img_convert/029e080d9840f94382bfd106ec532767.png)


  
 当点击鼠标时,小鸟会向上飞,每次向上20。先在Constant中添加一个常量:



public static double UP_SPEED = 20;// 上升的速度


在Bird中,再添加一个方法:



// 上升,点鼠标或点键盘向上键
public void up() {
v = Constant.UP_SPEED;
}


修改action(),在鼠标抬起的事件中,如果state为1,那么要调用up()方法,让小鸟上升:





public void mouseReleased(MouseEvent e) {
super.mouseReleased(e);
switch (state) {
case 0:// 游戏未开始
// 切换到状态1时的数据
state = 1;
bird.x = Constant.BIRD_FLY_POSITION_X;// 小鸟飞的初始x坐标
break;

case 1:// 开始游戏
// 当状态1时,小鸟点击向上移动
bird.up();
break;


#### **柱子左右移动**


首先在pics下放图片资源pillar.png。然后在Constant类中,添加常量:



// 柱子参数
public static String PATH_PILLAR = PATH_PIC + “pillar.png”;
public static int PILLAR_GAP = 144;// 柱子通道距离
public static int PILLAR_DISTANCE = 244;// 柱子间距


然后创建柱子类Pillar类:



package com.ruby.demo;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;

/**

  • 柱子类 其中构造方法中需要背景对象和地面对象
  • @author ruby

*/
public class Pillar {
public BufferedImage img;// 图片
public int x, y;// 坐标
public int width = 0;// 柱子宽度
public int height = 0;// 柱子高度
Random random = new Random();// 一个生成随机数的对象
private int max, min = 0;// 为了保证柱子通道能够完全显示在屏幕上,所以存在柱子在Y坐标的最大值和最小值

public Pillar(BackGround bg, Ground ground) {
try {
img = ImageIO.read(getClass().getResource(Constant.PATH_PILLAR));
width = img.getWidth();
height = img.getHeight();
System.out.println(“柱子width=” + width + “,height=” + height);
x = bg.width;

max = (height - Constant.PILLAR_GAP) / 2;
min = (height - Constant.PILLAR_GAP) / 2 - (bg.height - Constant.PILLAR_GAP - ground.height);
y = -(min + random.nextInt(max - min));
// System.out.println(“y=” + y);

} catch (IOException e) {
e.printStackTrace();
}
}



}


小鸟闯关的柱子,每隔244间距,就要再产生一根柱子。柱子的高度通过随机数来产生,先计算出柱子的高度:柱子图片高度-柱子通道距离114,然后除以2。柱子的最小高度,就是柱子的高度减去背景图高度-地面高度-通道距离。


柱子的y坐标,就因该是柱子的高度和柱子最小高度之间的随机数。


再添加一个移动柱子的方法:



// 柱子移动,游戏一旦开始则柱子移动
public void move(BackGround bg) {
x–;
if (x == -width) {
x = bg.width;
y = -(min + random.nextInt(max - min));
// System.out.println(“y=” + y);
}
}



然后修改GamePanel类,创建2个柱子对象,因为游戏界面中,最多出现2根柱子。然后再构造方法中,实例化两个柱子对象,并设置x坐标,柱子是从游戏界面右侧,移入到游戏界面上,所以第一个柱子的x值为游戏界面的宽度,第二个柱子要再加柱子间距。



// 声明两个柱子,并分别设置柱子的起始X坐标
p1 = new Pillar(bg, ground);
p1.x = bg.width;
p2 = new Pillar(bg, ground);
p2.x = bg.width + Constant.PILLAR_DISTANCE;


修改paint()方法,游戏开始后,绘制柱子:



else if (state == 1) {// 游戏开始后
// 绘制小鸟和两根柱子
g.drawImage(bird.img, bird.x, bird.y, null);
g.drawImage(p1.img, p1.x, p1.y, null);
g.drawImage(p2.img, p2.x, p2.y, null);

}


  
 然后再action()的循环里,调用两个柱子的移动方法:



while (true) {
// 地面移动
ground.move(bg);
bird.fly();
if (state == 0) {

} else if (state == 1) {
// 游戏开始。地面移动、柱子移动、小鸟飞并自然下降
bird.down();
p1.move(bg);
p2.move(bg);
} else if (state == 2) {

  }


// 线程休眠(因为是无限循环,下一次循环开始需要一段休息时间,这样才能让程序有缓冲的执行时间)
try {
Thread.sleep(1000 / speed);// 调节游戏速度
// 重新绘制(重新调用面板paint方法)
this.repaint();
} catch (Exception e) {
e.printStackTrace();
}
}


运行结果:


![](https://img-blog.csdnimg.cn/img_convert/5ae5ac4372b01c04cc06cbdc31f4f950.png)


#### **5、计算得分**


然后在Constant类中,添加和得分相关的常量:



// 得分信息的字体大小及坐标
public static int FONT_SIZE = 20;
public static int SCORE_X = 20;
public static int SCORE_Y = 40;


在GamePanel中定义score,表示分数,然后在paint()方法中,绘制分数:



// 绘制文字
Font font = new Font(Font.SERIF, Font.ITALIC, Constant.FONT_SIZE);//字体,倾斜,大小
g.setFont(font);
g.setColor(Color.white);// 这里font和color导包都导java.awt
g.drawString(“得分:” + score, Constant.SCORE_X, Constant.SCORE_Y);



要想统计分数,得先计算小鸟的各种碰撞,首先在小鸟的类中,添加一个是否碰撞地面的方法,其实就是检测小鸟y的值:



// 碰撞检测
// 掉落到地面时
public boolean hitGround(BackGround bg, Ground ground) {
if (y + height >= (bg.height - ground.height)) {
return true;
}
return false;
}


再添加一个检测是否碰撞天空的方法,就是游戏界面的顶部:



// 碰撞到舞台顶部时
public boolean hitSky() {
if (y <= 0) {
return true;
}
return false;
}


再添加一个检测碰撞柱子的方法:



// 碰到柱子时的检测
public boolean hitPillar(Pillar p) {
// x方向小鸟和柱子碰撞的条件
if ((x + width) >= p.x && x <= p.x + p.width) {
if (y <= p.y + (p.height - Constant.PILLAR_GAP) / 2
|| y >= p.y + (p.height + Constant.PILLAR_GAP) / 2 - height) {
return true;
}
}
return false;
}


要判断小鸟的横向上,碰撞柱子。


在小鸟类里添加一个方法:



// 碰到柱子时的检测
public boolean hitPillar(Pillar p) {
// x方向小鸟和柱子碰撞的条件
if ((x + width) >= p.x && x <= p.x + p.width) {
if (y <= p.y + (p.height - Constant.PILLAR_GAP) / 2
|| y >= p.y + (p.height + Constant.PILLAR_GAP) / 2 - height) {
return true;
}
}
return false;
}


再添加一个积分的方法:



// 增加积分,通过柱子通道后调用该方法
public boolean addScore(Pillar p) {
// System.out.println(“x=” + x + “,p.x=” + p.x);
if (x == p.x + p.width) {
return true;
}
return false;
}


然后在GamePanel类中修改action()方法:



while (true) {
if (state == 0) {
// 游戏未开始。地面移动,小鸟展翅
ground.move(bg);
bird.fly();
} else if (state == 1) {
// 游戏开始。地面移动、柱子移动、小鸟飞并自然下降
ground.move(bg);
p1.move(bg);
p2.move(bg);
bird.fly();
bird.down();
// 碰到地面、天空、柱子都显示游戏结束。
if (bird.hitGround(bg, ground) || bird.hitSky() || bird.hitPillar(p1) || bird.hitPillar(p2)) {
state = 2;
} else {
// 小鸟每通过一个竹子通道,累计积分,并提高柱子和地面移动速度。
if (bird.addScore(p1) || bird.addScore(p2)) {
score++;
// 每通过一个柱子,速度会递增
speed += 2;
// System.out.println(“speed=” + speed);
}
}
}


然后修改鼠标事件的监听:



public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
super.mousePressed(e);
switch (state) {
case 0:
// 切换到状态1时的数据
state = 1;
bird.x = Constant.BIRD_FLY_POSITION_X;// 小鸟飞的初始x坐标
musicThread = new MusicThread();
musicThread.start();

      break;
    case 1:
      // 当状态1时,小鸟点击向上移动
      bird.up();
      break;
    case 2:
      // 切换到状态0时的数据
      musicThread.stopBGM();
      state = 0;
      score = 0;
      // 重置小鸟的位置
      bird.x = Constant.BIRD_POSITION_X;
      bird.y = Constant.BIRD_POSITION_Y;
      bird.v = 0;
      // 重置柱子的坐标
      p1.x = bg.width;
      p2.x = bg.width + Constant.PILLAR_DISTANCE;
      // System.out.println("p1==" + p1 + ", p2==" + p2);
      break;
    default:
      break;
    }
  }

当游戏结束的时候,要初始化小鸟和柱子的数据。


#### **6、添加小鸟的键盘事件**


在Constant中添加常量:



public static int DISTANCE_PER_PRESS = 10;// 每点一次鼠标或键盘,移动的位置


然后在小鸟类中,添加键盘的上下左右事件方法:



// 后退,点键盘向左键
public void backward() {
x -= Constant.DISTANCE_PER_PRESS;
}

// 前进,点键盘向右键
public void foward() {
x += Constant.DISTANCE_PER_PRESS;
}

// 点击键盘下降,点键盘向下键
public void pressdown() {
y += Constant.DISTANCE_PER_PRESS;
}


然后在action()中,添加鼠标事件监听:



// 设置键盘监听事件
this.addKeyListener(new KeyAdapter() {
@Override
public void keyPressed(KeyEvent e) {
super.keyPressed(e);
switch (e.getKeyCode()) {
case KeyEvent.VK_UP:
bird.up();
break;
case KeyEvent.VK_RIGHT:
bird.foward();
break;
case KeyEvent.VK_LEFT:
bird.backward();
break;
case KeyEvent.VK_DOWN:
bird.pressdown();
break;
}
}
});

本人从事网路安全工作12年,曾在2个大厂工作过,安全服务、售后服务、售前、攻防比赛、安全讲师、销售经理等职位都做过,对这个行业了解比较全面。

最近遍览了各种网络安全类的文章,内容参差不齐,其中不伐有大佬倾力教学,也有各种不良机构浑水摸鱼,在收到几条私信,发现大家对一套完整的系统的网络安全从学习路线到学习资料,甚至是工具有着不小的需求。

最后,我将这部分内容融会贯通成了一套282G的网络安全资料包,所有类目条理清晰,知识点层层递进,需要的小伙伴可以点击下方小卡片领取哦!下面就开始进入正题,如何从一个萌新一步一步进入网络安全行业。

需要体系化学习资料的朋友,可以加我V获取:vip204888 (备注网络安全)

学习路线图

其中最为瞩目也是最为基础的就是网络安全学习路线图,这里我给大家分享一份打磨了3个月,已经更新到4.0版本的网络安全学习路线图。

相比起繁琐的文字,还是生动的视频教程更加适合零基础的同学们学习,这里也是整理了一份与上述学习路线一一对应的网络安全视频教程。

网络安全工具箱

当然,当你入门之后,仅仅是视频教程已经不能满足你的需求了,你肯定需要学习各种工具的使用以及大量的实战项目,这里也分享一份我自己整理的网络安全入门工具以及使用教程和实战。

项目实战

最后就是项目实战,这里带来的是SRC资料&HW资料,毕竟实战是检验真理的唯一标准嘛~

面试题

归根结底,我们的最终目的都是为了就业,所以这份结合了多位朋友的亲身经验打磨的面试题合集你绝对不能错过!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化资料的朋友,可以点击这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值