前言
嘛,这次是用java编写的Flappy bird,主要是本人最近新学习了多线程的使用,想试试手,变想出来做一个flappy bird的游戏,做出来后的大致效果还行吧2333但也需要进一步改进,还得多搞点事情
使用到的类
这一次使用了比较多的类,算下来好像10个(?)主要是对主要的部分都进行了一定程度的封装,虽然数量多了些,但代码更加清晰了,还算挺划算的
代码
话不多说,直接上代码吧(说太多也不知道有没有人看2333)
zhu类
因为Flappy bird 里面有障碍物,这里是用这个类来记录柱子的长度,并且在这里面执行后续话柱子的操作
public class zhu {
int lenth;
zhanai za;
public zhu(int lenth,zhanai za){
this.lenth=lenth;
this.za=za;
}
public int draw(Graphics g,int width,int high,int n,int i,zhu zu){
System.out.println("Next");
ImageIcon ol = new ImageIcon("c:\\Users\\lenovo\\Desktop\\Flappy bird\\下柱.png");
Image ii = ol.getImage();
g.drawImage(ii, width / 4 * (i + 1) - n, high - zu.lenth - 18, 30, zu.lenth, null);
ol = new ImageIcon("c:\\Users\\lenovo\\Desktop\\Flappy bird\\上柱.png");
ii = ol.getImage();
g.drawImage(ii, width / 4 * (i + 1) - n, 0, 30, (high) * 2/3 - zu.lenth, null);
for(int x=Math.max(width / 4 * (i + 1) - n,0);x<Math.min(width / 4 * (i + 1) - n+30,width);x++)
{
for(int y=high - zu.lenth - 18;y<high-18;y++)za.tu[x][y]=1;
for(int y=0;y<(high) * 2/3 - zu.lenth;y++)za.tu[x][y]=1;
}
return 0;
}
}
bird类
这个类就是对鸟的位置的一个确定,并在该类中画鸟和确定游戏是否结束。
public class Bird {
int x;
int y;
int width, high;
int zen = 0;
newzhu k1;
ClearScreen k2;
JButton bu1;
zhanai za;
public Bird(int x, int y, JButton bu1, zhanai za, int width, int high) {
this.x = x;
this.y = y;
this.width = width;
this.high = high;
this.bu1 = bu1;
this.za = za;
}
public void draw(Graphics g) {
y++;
if (zen > 0) {
y -= 4;
zen--;
}
ImageIcon ol = new ImageIcon("c:\\Users\\lenovo\\Desktop\\Flappy bird\\鸟.png");
Image ii = ol.getImage();
g.drawImage(ii, x, y, 30, 30, null);
for (int i = x; i < x + 30; i++)
for (int j = y; j < y + 30; j++) {
if (za.tu[i][j] == 1) {
k1.change();
k2.change();
bu1.setText("游戏结束");
BufferedImage bi = new BufferedImage(width, high, BufferedImage.TYPE_INT_ARGB);
Graphics g2 = bi.getGraphics();
ol = new ImageIcon("c:\\Users\\lenovo\\Desktop\\Flappy bird\\游戏结束.png");
ii = ol.getImage();
g2.drawImage(ii, 0, 0, width, high, null);
g.drawImage(bi,350,100,width-700,high-200,null);
return;
}
}
}
}
Back类
这个就是用来画背景的,天空和陆地啥的,这样每次调用就比较方便
public class Back {
Bird niao;
public void draw(Graphics g,int width,int high,int n1){
ImageIcon ol = new ImageIcon("c:\\Users\\lenovo\\Desktop\\Flappy bird\\背景.jpg");
Image ii = ol.getImage();
g.drawImage(ii, 0, 0, width, high, null);
ol = new ImageIcon("c:\\Users\\lenovo\\Desktop\\Flappy bird\\陆地.png");
ii = ol.getImage();
g.drawImage(ii, -n1, high - 18, width + width / 4 * 3, 40, null);
}
public void csh(Graphics g,int width,int high,Bird niao){
ImageIcon ol = new ImageIcon("c:\\Users\\lenovo\\Desktop\\Flappy bird\\背景.jpg");//加背景;
Image ii = ol.getImage();
g.drawImage(ii, 0, 0, width, high, null);
this.niao=niao;
niao.draw(g);
}
}
UI类
这个就是这个程序的启动的地方了,就是对界面的一个初始化的类。
public class UI {
Graphics g;
int width = 1000, high = 400;
JFrame k = new JFrame();
JPanel j1 = new JPanel();
JPanel j2 = new JPanel();
JButton bu1 = new JButton("开始");
public void show() {
k.setSize(width, high);
k.setLocationRelativeTo(null);
k.add(j1, BorderLayout.CENTER);//中心画布
k.add(j2, BorderLayout.NORTH);
j2.add(bu1);
k.setVisible(true);
g = j1.getGraphics();
zhanai za=new zhanai(width,high-90);//识别柱子
Bird niao=new Bird(width/2,high/2-45,bu1,za,width,high-90);//鸟
Back bg=new Back();
bg.csh(g, width, high-90, niao);//初始化
mouslis mou=new mouslis(niao);
j1.addMouseListener(mou);
java.util.ArrayList<zhu> kk = new java.util.ArrayList<zhu>();
ButtonLis u1 = new ButtonLis(high - 90, width, g, kk,bu1,niao,j2,za);
bu1.addActionListener(u1);//按钮监听器
}
public static void main(String[] args) {
UI wor = new UI();
wor.show();
}
}
ButtonLis类
给按钮加的一个监听器,按下开始后游戏开始,游戏结束后点击则恢复到开始界面。
public class ButtonLis implements ActionListener {
int high, width;
Graphics g;
JButton bu1, bu2 = new JButton();
int flag = 0;
java.util.ArrayList<zhu> kk = new java.util.ArrayList<zhu>();
newzhu k1;
ClearScreen k2;
Bird niao;
JPanel j2;
zhanai za;
int ci = 0;
public ButtonLis(int high, int width, Graphics g, java.util.ArrayList<zhu> kk, JButton bu1, Bird niao, JPanel j2,
zhanai za) {
this.j2 = j2;
this.za = za;
j2.add(bu2);
this.high = high;
this.width = width;
this.g = g;
this.kk = kk;
this.bu1 = bu1;
k1 = new newzhu(kk, high, za);
this.niao = niao;
k2 = new ClearScreen(g, width, high, kk, niao, bu2, za);
k2.csh();
niao.k1 = k1;
niao.k2 = k2;// 使鸟的位置可以控制游戏的结束与否
}
public void actionPerformed(ActionEvent e) {
if (flag == 0) {
bu2.setText("0");
k1.change();
k2.change();
if (ci == 0) {
k1.start();
k2.start();
}
ci++;
flag++;
bu1.setText("暂停");
} else if (flag % 2 == 1) {
bu1.setText("继续");
flag++;
k1.change();
k2.change();
} else if (flag % 2 == 0) {
bu1.setText("暂停");
flag++;
k1.change();
k2.change();
}
String c1 = e.getActionCommand();
if (c1.equals("游戏结束")) {
flag = 0;
k2.csh();
k1.csh();
za.csh();
niao.y = high / 2;
bu1.setText("开始");
bu2.setText("0");
Back bg=new Back();
bg.csh(g, width, high, niao);
}
}
}
ClearScreen类
绘图函数,主要就是实时绘制,从而使画面更新,(丝般顺滑),这里为了解决屏幕老是乱闪的问题,还用了BufferImage,顺利搞定~这里是第一个线程
public class ClearScreen extends Thread {
Graphics g2;
int width, high;
int qi;
int score=0;
boolean flag=false;
java.util.ArrayList<zhu> k = new java.util.ArrayList<zhu>();
Bird niao;
JButton bu2=new JButton();
zhanai za;
int n = -width / 4 * 3;
int n2= -width / 4;
int n1 = 0, ci = 0;
public ClearScreen(Graphics g, int width, int high, java.util.ArrayList<zhu> k,Bird niao,JButton bu2,zhanai za) {
this.g2 = g;
this.width = width;
this.high = high;
this.k = k;
this.niao=niao;
this.za=za;
this.bu2=bu2;
}
public void csh(){
n = -width / 4 * 3;
n2= -width / 4;
n1 = 0;ci = 0;
flag=false;
score=0;
}
public void run() {
while (true) {
String s=""+score;
bu2.setText(s);
BufferedImage bi = new BufferedImage(width, high, BufferedImage.TYPE_INT_ARGB);
Graphics g = bi.getGraphics();
try {
Thread.sleep(3);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if (flag == true) {
ci++;
Back jj = new Back();
jj.draw(g, width, high, n1);
za.csh();//绘图前清空
for (int i = 0; i < k.size() && i <= 4; i++) {
zhu zu = k.get(i);
zu.draw(g, width, high, n, i, zu);//画出柱子并且加上标记
}
if (n >= width / 4)// 柱子动
{
k.remove(0);
n = 0;
}
if(n2>=width/4)
{
n2=0;
score++;
music df=new music(1);
df.start();
}
if (n1 >= width / 4)// 陆地动
n1 = 0;
if (ci >= 11) {
n += 10;
n1 += 10;
n2+=10;
ci = 0;
}
niao.draw(g);
g2.drawImage(bi, 0, 0, width, high, null);// 整个画上去;
}
}
}
public void change(){
flag=!flag;
}
}
newzhu类
创建新的柱子加到队列中,使其可以顺利的继续下去,这是第二个线程。
public class newzhu extends Thread {// 添加新柱子
private java.util.ArrayList<zhu> k;
int high;
boolean flag=false;
zhanai za;
public newzhu(java.util.ArrayList<zhu> k, int high,zhanai za) {
this.k = k;
this.high = high;
this.za=za;
}
public void csh(){
flag=false;
}
public void run() {
while (true) {
int lenth = (int) (Math.random() * high / 2) + 10;
zhu zz = new zhu(lenth,za);
if(flag==true)
k.add(zz);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public void change(){
flag=!flag;
}
}
mouslis类
这个类主要是作为鼠标监听器使用,每次点击使鸟向上飞一段距离,完成跳跃的效果。
public class mouslis implements MouseListener,MouseMotionListener{
Bird niao;
public mouslis(Bird niao){
this.niao=niao;
}
public void mouseClicked(MouseEvent e){
}
public void mousePressed(MouseEvent e){
//music fly=new music(2);
niao.zen+=20;
// fly.start();
}
public void mouseReleased(MouseEvent e){
niao.zen=0;
}
public void mouseEntered(MouseEvent e){
}
public void mouseExited(MouseEvent e){
}
public void mouseDragged(MouseEvent e){
}
public void mouseMoved(MouseEvent e){
}
}
zhanai类
这个类用来存个二维数组,从而来判定是否出现了碰撞。
public class zhanai {
int width, high;
int[][] tu = new int[2000][2000];// 储存当前的障碍
public zhanai(int width,int high){
this.high=high;
this.width=width;
}
public void csh()// 初始化
{
for (int i = 0; i <= width; i++) {
for (int j = 0; j <= high; j++) {
tu[i][j]=0;
}
tu[i][0] = tu[i][high - 18] = 1;
}
}
}
music类
顾名思义,放音乐用的~
public class music extends Thread{
int n;
File f = new File("c:\\Users\\lenovo\\Desktop\\Flappy bird\\fly.wav");
File f2 = new File("c:\\Users\\lenovo\\Desktop\\Flappy bird\\得分.wav");
URL sy;
public music(int n){
this.n=n;
}
public void run(){
if(n==1)this.df();
if(n==2)this.fly();
}
private void fly() {
try {
sy = f.toURL();
AudioClip aau;
aau = Applet.newAudioClip(sy);// 播放声音文件
aau.play();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
aau.stop();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void df() {
try {
sy = f2.toURL();
AudioClip aau;
aau = Applet.newAudioClip(sy);// 播放声音文件
aau.play();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
aau.stop();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
和之前的国际跳棋不大同,这次算是我做的第一个灵活性较高的游戏了,下一步准备继续玩些大的23333