前言
自学java前期做的小项目,主要灵感来源于天天跑酷和大家耳熟能详的flappy bird小游戏,当然在运行过程中也有许多瑕疵,欢迎指正
结构
1.显示窗口,绘制人物与背景
2.点击鼠标,人物即可跳跃
3.随机出现障碍物,检测撞击到障碍物人物死亡
4.人物成功避开障碍物积分加1
代码
1.背景包Ground
package game;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;
/*
地面
*/
public class Ground {
//图片
BufferedImage image1,image2;
//位置
int x1,x2;
//宽高
int width,height;
//初始化地面
public Ground() throws Exception{
image1=ImageIO.read(getClass().getResource("/images/ground1.png"));
image2=ImageIO.read(getClass().getResource("/images/ground1.png"));
x1=0;
x2=674;
}
//向左移动一步
public void step() {
x1-=2;
x2-=2;
//地面滚动拼接
if(x1<=-674) {
x1=674;
}else if (x2<=-674) {
x2=674;
}
}
}
2.人物包Human
在这里人物跳跃我用一个极其笨拙的方法,随时间人物y坐标变化,因为原本使用抛物线运动的时候人物容易闪烁掉帧,在加上比较匆忙没有用双缓冲,大佬们有什么好的建议尽管说
package game;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.Timer;
import java.util.TimerTask;/*
人物
*/
public class Human {
//图片
BufferedImage image;
//位置
int x,y;
//最低位置,即地面
public static final int LOW_Y = 320;
//宽高
int width,height;
//边框
int size;
//一组图片,记录人物的动画帧
BufferedImage[] images;
//动画帧数组的下标
int index;
//初始化人物
public Human() throws Exception{
//初始化基本参数
image =ImageIO.read(getClass().getResource("/images/r0.PNG"));
width=image.getWidth();
height=image.getHeight();
//初始化位移参数
x=130;
y=320;
size=30;
//初始化动画
images=new BufferedImage[6];
for(int i=0;i<6;i++) {
images[i] = ImageIO.read(getClass().getResource("/images/r" + i + ".PNG"));
}
index=0;
}
//移动一步
public void step() {
index++;
image=images[(index/12)%6];}
//向上跳跃
public void jump() throws Exception {
Timer timer=new Timer();
timer.schedule(new Task(timer),200,120);
}
class Task extends TimerTask{
private Timer timer;
public Task(Timer timer) {
this.timer = timer;
}
int i = 0;@Override
public void run() {
i++;
if (i<=3){
y-=30;
}else if(i>3 & i<=8) {
//
}else if(i>8 & i<=11) {
y += 30;
}else if (i==12) {
this.timer.cancel();
}
}
}
//检测人物是否撞到障碍物
public boolean hit(Obstacle obstacle) {
//先检测是否在障碍物的范围内
if(x+size>obstacle.x && x<obstacle.x+size) {
//再检测是否撞到障碍
if(y+height>obstacle.y+size && y+size<obstacle.y+ obstacle.height) {
return true;
}else {
return false;
}
}
return false;
}}
3.障碍包Obstacle
package game;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.util.Random;
public class Obstacle {
//图片
BufferedImage image;
//位置
int x,y;
//宽高
int width,height;
//随机数
int index;
//障碍之间的距离
int distance;
//随机数工具
Random random=new Random();
/*
初始化第N个障碍
*/
public Obstacle(int n) throws Exception{
index= random.nextInt(2);
switch (index) {
case 0:
image = ImageIO.read(getClass().getResource("/images/b0.PNG"));
y=200;
break;
case 1:
image = ImageIO.read(getClass().getResource("/images/s0.png"));
y=350;
break;
}
width=image.getWidth();
height=image.getHeight();
distance= random.nextInt(3)*100+200;
x=700+(n-1)*distance;
}
//向左移动一步
public void step() {
x-=2;
if(x+width<=0) {
x= random.nextInt(3)*50+700;
}
}
}
4.主函数RunningGame
package game;
/*
游戏界面
*/
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;public class RunningGame extends JPanel {
// 背景图片
BufferedImage background;
// 开始图片
BufferedImage startImage;
BufferedImage humanImage;
// 结束图片
BufferedImage gameOverImage;
// 地面
Ground ground;
// 障碍物
Obstacle obstacle1, obstacle2;
// 人物
Human human;
// 游戏分数
int score;
// 游戏状态
int state;// 状态常量
public static final int START = 0;// 开始
public static final int RUNNING = 1;// 运行
public static final int GAME_OVER = 2;// 结束/*
初始化游戏
*/
public RunningGame() throws Exception {
// 导入背景图片
background = ImageIO.read(getClass().getResource("/images/bg0.png"));
// 导入开始、结束图片
startImage = ImageIO.read(getClass().getResource("/images/start.png"));
gameOverImage = ImageIO.read(getClass().getResource("/images/gameover.png"));
humanImage = ImageIO.read(getClass().getResource("/images/ren.PNG"));// 导入地面、障碍、人物
ground = new Ground();
obstacle1 = new Obstacle(1);
obstacle2 = new Obstacle(2);
human = new Human();// 初始化分数
score = 0;
// 初始化状态
state = START;}
/*
绘制界面
*/
public void paint(Graphics g) {
// 绘制背景
g.drawImage(background, 0, 0, null);
// 绘制地面
g.drawImage(ground.image1, ground.x1, 360, null);
g.drawImage(ground.image2, ground.x2, 360, null);// 绘制障碍物
g.drawImage(obstacle1.image, obstacle1.x, obstacle1.y, null);
g.drawImage(obstacle2.image, obstacle2.x, obstacle2.y, null);// 绘制人物
g.drawImage(human.image, human.x, human.y, null);// 绘制分数
Font f = new Font(Font.MONOSPACED, Font.BOLD, 40);
g.setFont(f);
g.drawString("" + score, 40, 60);
g.setColor(Color.WHITE);
g.drawString("" + score, 40 - 3, 60 - 3);// 绘制开始与结束界面
switch (state) {
case START:
g.drawImage(startImage, 50, -120, null);
g.drawImage(humanImage,440,70,null);
break;
case GAME_OVER:
g.drawImage(gameOverImage, 150, -80, null);
break;
}
}// 开始游戏
public void action() throws Exception {MouseListener l = new MouseAdapter() {
// 鼠标按下事件
public void mousePressed(MouseEvent e) {
try {
switch (state) {
case START:
// 在开始时,点击鼠标则转为运行状态。
state = RUNNING;
break;
case RUNNING:
// 在运行时,点击鼠标则人物向上跳
human.jump();
break;
case GAME_OVER:
// 在结束时,点击鼠标则重置数据,返回开始界面。
obstacle1 = new Obstacle(1);
obstacle2 = new Obstacle(2);
human = new Human();
score = 0;
state = START;
break;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
};addMouseListener(l);
// 不断的移动与重绘
while (true) {
switch (state) {
case START:
// 地面及背景向左移动一步
human.step();
ground.step();
break;
case RUNNING:
//整个画面移动
ground.step();
obstacle1.step();
obstacle2.step();
human.step();
// 计算分数
if (human.x == obstacle1.x || human.x == obstacle2.x) {
score++;
}
//是否发生碰撞
if (human.hit(obstacle1) || human.hit(obstacle2)) {
state = GAME_OVER;
break;
}
}// 重新绘制界面
repaint();
// 休眠 1000/60 毫秒
Thread.sleep(1000 / 60);
}}
/*
启动方法
*/
public static void main(String[] args) throws Exception {
JFrame frame = new JFrame();
RunningGame game = new RunningGame();
frame.add(game);
frame.setSize(700, 480);
frame.setLocationRelativeTo(null);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
game.action();}
}
下面是运行界面截图