Java学习笔记_17 项目实战之天天酷跑(四):游戏主界面

此文转载自:https://blog.csdn.net/qq_45909299/article/details/110306321

接上文,本文将实现游戏主界面,功能如下:

移动的背景图片、动态的玩家、玩家的移动功能、
五种障碍物持续出现、玩家和障碍物的碰撞、
暂停、继续功能。

首先,看一下整体效果:

动图实在太大,几秒钟的 Gif 就十几兆了。无奈,图片展示效果。

跳跃、得分、下落、障碍物:
在这里插入图片描述
碰到障碍物后,玩家被推着走。
在这里插入图片描述

下面,分别解释一下每个功能的逻辑:

一、创建一个显示窗体,承载游戏的主面板类。

GameFrame.java

package cn.sqc.runday.view;

import javax.swing.ImageIcon;
import javax.swing.JFrame;

import cn.sqc.runday.controller.GamePanel;

/**
 * @author Huey
 *2020-11-27  下午12:40:22
 * 游戏主界面:显示窗体,承载游戏的主面板类
 */

public class GameFrame extends JFrame {
	//设置窗体宽高属性
	public static final int WIDTH=1500;
	public static final int HEIGHT=900;
	public GameFrame() {
		//2.4创建游戏面板对象,并添加到窗体上去
		GamePanel panel = new GamePanel();
		panel.action();//程序启动的方法
		this.addKeyListener(panel);//谁实现就监听谁
		this.add(panel);
		
		/**1.设置窗体基本属性*/
		this.setSize(WIDTH,HEIGHT);
		this.setLocationRelativeTo(null);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setIconImage(new ImageIcon("Image/115.png").getImage());
		this.setUndecorated(true);
		this.setVisible(true);	
	}
	
	public static void main(String[] args) {
		new GameFrame();
	}
}

二、游戏主面板类(核心逻辑类):

1、背景图片滚动效果

使用两张背景图片,实现背景图片滚动效果的逻辑如下:
在这里插入图片描述
下面用动图演示一下:
在这里插入图片描述

2、玩家动态效果

我国早期很有名的一部动画片《大闹天宫》,由于当时没有电脑,所以需要一帧一帧的画,随后快速播放图片,形成动态的画面(我愿称之:真——动画!!!),并为之配音,短短10分钟的动画却要画7000到10000张原画!

而此处,我们的玩家的奔跑姿态,同理是由九张图片构成。
在这里插入图片描述
下面动图演示:
在这里插入图片描述
下面是实现玩家的(生成、移动、绘制)的基本代码,后面的障碍物的实现,也都遵循这一编写逻辑。

为更方便读懂代码,已尽力注释,若仍有不清楚的地方,欢迎留言交流。

Person.java

package cn.sqc.runday.model;

import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import cn.sqc.runday.view.GameFrame;

/**
 * @author Huey
 * @date 2020-11-23
 * 玩家的实体类
 */
public class Person {//1.声明属性
	private Image image;//1.1 玩家当前显示图片
	private Image[] images;//1.2 玩家所有图片
	
	public static final int WIDTH = 120;//1.3玩家宽高
	public static final int HEIGHT = 120;
	
	//1.4玩家初始位置坐标
	private int x,y;
	int index;//下面用作切换图片
	//玩家得分
	private int score;
	//玩家跑酷距离
	private int distance;
	
	public Person() {//2.赋值
		//给图片数组images赋值
		init();//2.1	先写,会提示要不要实现!自动生成方法
		//默认当前显示图片位第一张图片 2.6
		image = images[0];
		
		x = 90;//2.7
		y = 580;//脚踩地板
		index = 0;
		score = 0;
		distance = 0;
	}
	//玩家自由下落方法5.1
	public void drop() {
		y += 5;
		if(y>=580){// 下落归下落,也得温柔点,不能让小人儿踩破了地板
			y = 580;
		}
	}
	//玩家移动的方法
	public void step(){
		//玩家图片的切换
		image = images[index ++ /3%images.length];
		//玩家坐标改变(玩家坐标通过键盘控制,此次不做处理)
	}
	//绘制玩家的方法
	public void paintPerson(Graphics g){
		g.drawImage(image, x, y, WIDTH, HEIGHT, null);
	}

	//判断玩家是否越界的方法
	public boolean outOfBounds(){
		return this.x >= GameFrame.WIDTH || this.x <= -WIDTH;
	}
	private void init() {//2.2
		images = new Image[9];
		for(int i = 0; i<images.length; i++){//2.3
			try {//2.5
				images[i] = ImageIO.read(new File("Image/"+(i+1) + ".png"));//2.4
			} catch (IOException e) {//2.5
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
//2.8  右键,Source,GGAS
	public Image getImage() {
		return image;
	}

	public void setImage(Image image) {
		this.image = image;
	}

	public Image[] getImages() {
		return images;
	}

	public void setImages(Image[] images) {
		this.images = images;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public static int getWidth() {
		return WIDTH;
	}

	public static int getHeight() {
		return HEIGHT;
	}
	public int getIndex() {
		return index;
	}
	public void setIndex(int index) {
		this.index = index;
	}
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	public int getDistance() {
		return distance;
	}
	public void setDistance(int distance) {
		this.distance = distance;
	}
	
}

3、几种障碍物的出现

障碍物一:螃蟹

在这里插入图片描述

package cn.sqc.runday.model;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Paint;
import java.io.File;

import javax.imageio.ImageIO;

import cn.sqc.runday.view.GameFrame;

public class Barrs_1 {
	private Image image;
	private Image [] images;
	public static final int WIDTH=100;
	public static final int HEIGHT=110;
	private int x,y;
	int  index;
	private int speed;
	
	public Barrs_1() {//		螃蟹!
		images = new Image[2];
		try {
			images[0]=ImageIO.read(new File("image/a2.png"));
			images[1]=ImageIO.read(new File("image/a4.png"));		
		} catch (Exception e) {
			// TODO: handle exception
		}		
		image = images[0];
		x=GameFrame.WIDTH+100;
		y=580;
		speed =30;
		index = 0;
	}
	
	public  void step() {//切换图片
		image =images[index++/5%images.length];
		x-=speed;//切换图片实现螃蟹爪子张合的动态效果的同时,使其向左移动
	}
  public void paintBarrs(Graphics g) {
	g.drawImage(image, x,y,WIDTH,HEIGHT, null);
}
  public boolean outofBounds(){
		return this.x <=-WIDTH;
	}
public Image getImage() {
	return image;
}
public void setImage(Image image) {
	this.image = image;
}
public Image[] getImages() {
	return images;
}
public void setImages(Image[] images) {
	this.images = images;
}
public int getX() {
	return x;
}
public void setX(int x) {
	this.x = x;
}
public int getY() {
	return y;
}
public void setY(int y) {
	this.y = y;
}
public int getIndex() {
	return index;
}
public void setIndex(int index) {
	this.index = index;
}
public int getSpeed() {
	return speed;
}
public void setSpeed(int speed) {
	this.speed = speed;
}
public static int getWidth() {
	return WIDTH;
}
public static int getHeight() {
	return HEIGHT;
}
  
}

需要注意的是,在创建后,记得添加set、get方法。以便在面板类中对其障碍物进行操作。

障碍物二:宠物

与其称之障碍物,不如说它是个跟着玩家的小跟班。

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

package cn.sqc.runday.model;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

import cn.sqc.runday.view.GameFrame;

public class Barrs_2{  //  宠物!
	private Image image;
	private Image images [] ;
	public static final int WIDTH= 70;
	public static final int HEIGHT = 60;
	private int x,y;
	int index;
	public Barrs_2() {
		init();
		image = images[0];
		x=300;
		y=460;
	}
	public void drop() {
		y ++;
		if(y>=460){
			y = 460;
		}
	}
	public void step(){
		image = images[index++/2%images.length];
	}
	 public void paintBarrs(Graphics g) {
			g.drawImage(image, x,y,WIDTH,HEIGHT, null);
		}
	public boolean outofBounds() {
		return this.x<=-WIDTH;
	}
public void init(){
	images = new Image[6];
	for( int i=0;i<6;i++){
		try {
			images[i]=ImageIO.read(new File ("Image/"+"d"+(i+1)+".png"));
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
public Image getImage() {
	return image;
}
public void setImage(Image image) {
	this.image = image;
}
public Image[] getImages() {
	return images;
}
public void setImages(Image[] images) {
	this.images = images;
}
public int getX() {
	return x;
}
public void setX(int x) {
	this.x = x;
}
public int getY() {
	return y;
}
public void setY(int y) {
	this.y = y;
}
public int getIndex() {
	return index;
}
public void setIndex(int index) {
	this.index = index;
}
public static int getWidht() {
	return WIDTH;
}
public static int getHeight() {
	return HEIGHT;
}

}

障碍物三、导弹

在这里插入图片描述

package cn.sqc.runday.model;

import java.awt.Graphics;
import java.awt.Image;
import java.io.File;

import javax.imageio.ImageIO;

import cn.sqc.runday.view.GameFrame;

public class Barrs_3 {// 		导弹!
	private Image image;
	private int x,y;
	public static final int WIDTH = 150;
	public static final int HEIGHT=70;
	private int speed;
	public Barrs_3() {
		try {
			image = ImageIO.read(new File("image/daodan.png"));
		} catch (Exception e) {
			// TODO: handle exception
		}
		x=GameFrame.WIDTH+1000;
		y=450;
		speed = 25 ;
	}
	public void step(){
		x-=speed;
	}
	public void paintBarrs(Graphics g) {
		g.drawImage(image, x, y, WIDTH, HEIGHT, null);

	}
	public boolean outofBounds(){
		return this.x<=-WIDTH;
	}
	public Image getImage() {
		return image;
	}
	public void setImage(Image image) {
		this.image = image;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public int getSpeed() {
		return speed;
	}
	public void setSpeed(int speed) {
		this.speed = speed;
	}
	public static int getWidth() {
		return WIDTH;
	}
	public static int getHeight() {
		return HEIGHT;
	}
	

}

障碍物四:鱼叉等障碍物

在这里插入图片描述

package cn.sqc.runday.model;

import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.util.Random;

import javax.imageio.ImageIO;

import cn.sqc.runday.view.GameFrame;

public class Barrs_4 {//		鱼叉障碍物!
	private Image image;
	private Image images[];
	public static final int WIDTH =150;
	public static final int HEIGHT =350;
	private int x,y;
	
	public Barrs_4() {//构造方法
		Random random = new Random();
		images = new Image[4] ;
	try {
		images[0] = ImageIO.read(new File("image/11.png"));
		images[1]= ImageIO.read(new File("image/12.png"));
		images[2]= ImageIO.read(new File("image/13.png"));
		images[3]= ImageIO.read(new File("image/14.png"));
	} catch (Exception e) {
		// TODO: handle exception
	}
		image= images[random.nextInt(4)];
		x=GameFrame.WIDTH+1500;
		y=0;
	}
	public void step(){
		x-=20;
	}
	public void paintBarrs(Graphics g){
		g.drawImage(image, x, y, WIDTH, HEIGHT, null);
	}
	public boolean outofBounds(){
		return this.x<=-WIDTH;
	}
	public Image getImage() {
		return image;
	}
	public void setImage(Image image) {
		this.image = image;
	}
	public Image[] getImages() {
		return images;
	}
	public void setImages(Image[] images) {
		this.images = images;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public static int getWidth() {
		return WIDTH;
	}
	public static int getHeight() {
		return HEIGHT;
	}
	
}
	

障碍物五、金币

在这里插入图片描述
在此,暂且先不写金币的动态效果。

package cn.sqc.runday.model;

import java.awt.Graphics;
import java.awt.Image;
import java.io.File;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;

import cn.sqc.runday.view.GameFrame;

/**
 * @author Huey
 *2020-11-30  下午03:44:51
 *金币障碍物类
 * 
 */
public class Barrs_5 {
		private Image image;//当前显示图片
		public static final int WIDTH = 30;
		public static final int HEIGHT = 30;
		private int x,y;
		private int speed;
		Random random = new Random();
		public Barrs_5() {
			try {
				image = ImageIO.read(new File("Image/"+(random.nextInt(6) + 21) + ".png"));
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			x = GameFrame.WIDTH + 10;
			y = random.nextInt(600);
			speed = 20;
		}
		
		public void step(){
			x -= speed;
		}
		
		public void paintBarrs(Graphics g){
			g.drawImage(image, x, y, WIDTH, HEIGHT, null);
		}
		public boolean outofBounds() {
			return this.x<=-WIDTH;
		}

		public Image getImage() {
			return image;
		}

		public void setImage(Image image) {
			this.image = image;
		}

		public int getX() {
			return x;
		}

		public void setX(int x) {
			this.x = x;
		}

		public int getY() {
			return y;
		}

		public void setY(int y) {
			this.y = y;
		}

		public int getSpeed() {
			return speed;
		}

		public void setSpeed(int speed) {
			this.speed = speed;
		}

		public Random getRandom() {
			return random;
		}

		public void setRandom(Random random) {
			this.random = random;
		}

		public static int getWidth() {
			return WIDTH;
		}

		public static int getHeight() {
			return HEIGHT;
		}

}

4、玩家和障碍物的碰撞逻辑

以玩家与导弹的碰撞举例:

for(int i = 0;i<barrs3.length;i++){
		if(person.getX() + Person.WIDTH >= barrs3[i].getX() &&
		person.getX() <= barrs3[i].getX()	 + Barrs_3.WIDTH  &&
		person .getY() +Person.getHeight() >= barrs3[i].getY() &&
		person.getY()	<= barrs3[i].getY () + Barrs_3.HEIGHT){
			if(person.getX() + Person.WIDTH <= barrs3[i].getX() + Barrs_3.WIDTH){//玩家的宽度(120px)是比障碍物小的
				//左碰撞
				person.setX(barrs3[i].getX()  - Barrs_3.WIDTH);
			}else{
				//右碰撞
				person.setX(barrs3[i].getX()+ Barrs_3.WIDTH	);
			}	
		}
	}

以下动图演示了玩家从右边与障碍物b发生碰撞和从左边碰撞的逻辑,上下碰撞同理。

上下左右碰撞的逻辑代码,在动图下方:
在这里插入图片描述

5、暂停、继续逻辑

在监听键盘按键的方法中。
在这里插入图片描述
代码如下:
在这里插入图片描述
此处的 flag 来源于上面程序启动的方法中,不难看出只要按了空格键,就能实现生成、移动、绘制方法的暂停,也就相当于画面的静止、游戏的暂停!
在这里插入图片描述

6、结束逻辑

后面再实现。

个人学习笔记,若有误还望不吝赐教。

   

更多内容详见微信公众号:Python测试和开发

Python测试和开发

原文地址:https://www.cnblogs.com/phyger/p/14073352.html