入门java游戏——飞翔小鸟

 2023-09-11 阅读 29 评论 0

摘要:这是牛客网上一个开源的项目原网址如下:https://www.nowcoder.com/project/index/65 图片资源也可以在网站上进行下载。 目录: 目录 目录: 一:效果展示 二.原理 三:实现步骤 1.类的设计 2.代码结构 3.源码 一:效果展示 愤怒的小鸟数

这是牛客网上一个开源的项目原网址如下:https://www.nowcoder.com/project/index/65

图片资源也可以在网站上进行下载。

目录:

目录

目录:

一:效果展示

 二.原理

三:实现步骤

1.类的设计

2.代码结构

3.源码


一:效果展示

愤怒的小鸟数据结构?

 二.原理

预备知识:java类与对象、java常用GUI组件、动画相关知识。

这里稍微解释一下动画的相关知识。

我们看到的游戏画面为什么会动,简单来说是因为显示器一秒显示若干张相似有关联的图片,当每秒钟的图片数达到30张以上,在视觉上即可产生比较流畅的动画。当每秒显示的图片数越来越多,则动画越流畅。每一张图片也可称位帧——是影像动画中最小单位的单幅影像画面,相当于电影胶片上的每一格镜头。

canvas java?而飞翔小鸟这个游戏正是利用了这个原理,每秒钟若干次的刷新GUI界面,以模拟动画效果。实际上大部分用GUI做的游戏都是基于此原理。

三:实现步骤

1.类的设计

飞翔小鸟游戏一共需要四个类:小鸟类、地面类、柱子类、GUI界面类

小鸟类:用于控制小鸟的位置、小鸟飞行、碰撞

地面类:主要用于检测小鸟是否碰撞到地面以及利用运动的相对性,地面每一帧左移一个像素,在视觉上实现小鸟是向右飞行的。

什么小鸟,柱子类:同地面类。用于检测碰撞,以及模拟运动。

GUI界面类:负责游戏的逻辑控制以及游戏的整个界面显示


2.代码结构

开发工具——IDEA

代码结构:所有类全部放在games文件下,用到的图片文件放在resources文件下

java重写。


3.源码

 Bird类:

package FlyingBird.games;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;public class Bird {BufferedImage image;//加载小鸟图片int x,y;//小鸟中心点坐标int width,height;//小鸟宽度和高度,涉及到碰撞体积double g;//重力加速度double t;//一次位移设定的时间间隔double v0;//上抛初速度double speed;//小鸟当前速度double s;//一次时间间隔内的位移double alpha;//角度BufferedImage images[];//用于存放小鸟的动画帧int index;//动画帧下标public Bird() throws Exception{image=ImageIO.read(getClass().getResource("/FlyingBird/resources/0.png"));width=image.getWidth();height=image.getHeight();x=132;//小鸟初始x位置y=280;//小鸟初始y位置g=4;v0=20;t=0.25;speed=v0;s=0;alpha=0;images=new BufferedImage[8];//加载动画帧for (int i = 0; i < images.length; i++) {images[i]=ImageIO.read(getClass().getResource("/FlyingBird/resources/"+i+".png"));}index=0;}//飞行动画public void fly(){index++;image=images[(index/12)%8];//每12帧小鸟的动画帧更新一次}//移动一帧public void step(){double v1=speed;//这个v1是临时记录speeds=v1*t-0.5*g*t*t;//模拟自由落体,小鸟向上移动的距离y=y-(int)s;double v=v1-g*t;//更新速度speed=v;alpha=Math.atan(s/10);//更新小鸟的倾角}//鼠标点击后,小鸟向上飞行public void flappy(){speed=v0;//将小鸟速度重置}//检测小鸟是否碰撞到地面public boolean hit(Ground ground){boolean hit=y+height/2>ground.y;//当小鸟的模型下边缘碰到地面,视为碰撞if(hit){//更新小鸟倾角设为90度alpha=-Math.PI/2;}return hit;}//检测小鸟是否碰撞到柱子,这里用了方法重载。public boolean hit(Column column){if(x+width/2>column.x-column.width/2&&x-width/2<column.x+column.width/2){ //柱子左边界与右边界检测if(y-height/2>column.y-column.gap/2&&//小鸟是否在柱子缝隙中间y+height/2<column.y+column.gap/2) return false;return true;}return false;}
}

 Ground类:

package FlyingBird.games;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;public class Ground {BufferedImage image;//地面背景图int x;//地面的位置int y;int width;int height;public Ground() throws IOException {image= ImageIO.read(getClass().getResource("/FlyingBird/resources/ground.png"));width=image.getWidth();height=image.getHeight();x=0;//设定地面的位置y=500;}//模拟地面移动的动画public void step(){x--;if(x==-109){x=0;}}
}

Column类:

package FlyingBird.games;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;public class Column {BufferedImage image;int x,y;//柱子模型中心的坐标int width,height;//柱子模型的宽度和高度,这个高度其实是没用的int gap;//柱子间间隙int distance;//两根柱子间距离Random random=new Random();//初始化第n根柱子public Column(int n) throws IOException {image= ImageIO.read(getClass().getResource("/FlyingBird/resources/column.png"));width=image.getWidth();height=image.getHeight();gap=144;distance=245;x=550+(n-1)*distance;//初始化柱子中心坐标y=random.nextInt(218)+132;}//柱子的移动动画//这里用两根柱子的交替出现模拟小鸟所遇到的障碍(柱子)public void step(){x--;if(x==-width/2){x=distance*2-width/2;y=random.nextInt(218)+132;}}
}

小鸟像什么?GUI界面:

package FlyingBird.games;import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;public class FlyingBirdGUI extends JPanel {BufferedImage background;//背景图片BufferedImage startImage;//开始图片BufferedImage gameOverImage;//结束图片Bird bird;//小鸟Ground ground;//地面Column column1;//柱子1Column column2;//柱子2int score;//得分static int maxscore;//历史最高得分int state;//游戏状态//三个状态常量public static final int START=0;//开始public static final int RUNNING=1;//运行public static final int GAME_OVER=2;//结束//初始化public FlyingBirdGUI() throws Exception{this.background= ImageIO.read(getClass().getResource("/FlyingBird/resources/bg.png"));this.startImage= ImageIO.read(getClass().getResource("/FlyingBird/resources/start.png"));this.gameOverImage= ImageIO.read(getClass().getResource("/FlyingBird/resources/gameover.png"));ground=new Ground();column1=new Column(1);column2=new Column(2);bird=new Bird();score=0;state=START;}//绘制游戏界面public void paint(Graphics g) {g.drawImage(background, 0, 0, null);// 绘制背景g.drawImage(ground.image, ground.x, ground.y, null);//绘制地面//绘制柱子1、2g.drawImage(column1.image, column1.x - column1.width / 2, column1.y- column1.height / 2, null);g.drawImage(column2.image, column2.x - column2.width / 2, column2.y- column2.height / 2, null);//绘制小鸟,涉及到旋转坐标系Graphics2D g2 = (Graphics2D) g;g2.rotate(-bird.alpha, bird.x, bird.y);g.drawImage(bird.image,bird.x - bird.width / 2, bird.y - bird.height / 2, null);g2.rotate(bird.alpha, bird.x, bird.y);//设定字体样式Font f = new Font(Font.SANS_SERIF, Font.BOLD, 40);g.setFont(f);//运行阶段,显示当前分数if(state==RUNNING){g.drawString("" + score, 40, 60);g.setColor(Color.WHITE);g.drawString("" + score, 40 - 3, 60 - 3);//阴影效果}//开始截断,显示历史记录分数(历史最高分)if(state==START){g.setColor(Color.RED);g.drawString("历史记录:" + maxscore, 40, 60);}//绘制开始与结束界面switch (state) {case START:g.drawImage(startImage, 0, 0, null);break;case GAME_OVER:g.drawImage(gameOverImage, 0, 0, null);break;}}//main方法public static void main(String[] args) throws Exception{JFrame jFrame = new JFrame();FlyingBirdGUI flyingBirdGUI = new FlyingBirdGUI();jFrame.add(flyingBirdGUI);jFrame.setSize(440,670);jFrame.setLocationRelativeTo(null);jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);jFrame.setVisible(true);flyingBirdGUI.action();}public void action() throws Exception{//设置鼠标监视器MouseListener l=new MouseAdapter() {@Overridepublic void mousePressed(MouseEvent e) {try {switch (state) {case START:// 在开始状态,按下鼠标则转为运行状态。state = RUNNING;break;case RUNNING:// 在运行状态,按下鼠标则小鸟向上飞行。bird.flappy();break;case GAME_OVER:// 在结束状态,按下鼠标则重置数据,再次转为开始态。column1 = new Column(1);column2 = new Column(2);bird = new Bird();//更新历史最高分if(score>=maxscore){maxscore=score;}score = 0;state = START;break;}} catch (Exception ex) {ex.printStackTrace();}}};addMouseListener(l);//用while循环模拟游戏动画,即不断的移动和重绘while (true) {switch (state) {case START:// 小鸟做出飞行动作bird.fly();// 地面向左移动一步ground.step();break;case RUNNING:// 地面向左移动一步ground.step();// 柱子向左移动一步column1.step();column2.step();// 小鸟做出飞行动作bird.fly();// 小鸟上下移动一步bird.step();// 计算分数,小鸟飞过柱子右边界分数+1if (bird.x == column1.x+column1.width/2 || bird.x == column2.x+column2.width/2) {score++;}// 检测是否发生碰撞if (bird.hit(ground) || bird.hit(column1) || bird.hit(column2)) {state = GAME_OVER;}break;}// 重新绘制界面repaint();// 休眠 1000/120 毫秒,可以调节,间隔越短动画速度越快。Thread.sleep(1000 /120);}}
}

 可以调节下面这行代码控制游戏的速度。1000/120可以理解为1秒钟(1000毫秒)刷新120次界面。刷新次数越快,画面变化越快,即游戏难度越高。可以尝试将120调整为60,90。

Thread.sleep(1000 /120);

()的小鸟?

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://808629.com/53777.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 86后生记录生活 Inc. 保留所有权利。

底部版权信息