Java学习笔记_17 项目实战之天天酷跑(四):游戏主界面
此文转载自:https://blog.csdn.net/qq_45909299/article/details/110306321#commentBox
接上文,本文将实现游戏主界面,功能如下:
移动的背景图片、动态的玩家、玩家的移动功能、 五种障碍物持续出现、玩家和障碍物的碰撞、 暂停、继续功能。
首先,看一下整体效果:
动图实在太大,几秒钟的 Gif 就十几兆了。无奈,图片展示效果。跳跃、得分、下落、障碍物:
碰到障碍物后,玩家被推着走。
下面,分别解释一下每个功能的逻辑:
一、创建一个显示窗体,承载游戏的主面板类。
GameFrame.javapackage 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.javapackage 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.6image = images[0];x = 90;//2.7y = 580;//脚踩地板index = 0;score = 0;distance = 0;}//玩家自由下落方法5.1public 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.2images = new Image[9];for(int i = 0; i<images.length; i ){//2.3try {//2.5images[i] = ImageIO.read(new File("Image/" (i 1) ".png"));//2.4} catch (IOException e) {//2.5// TODO Auto-generated catch blocke.printStackTrace();}}}//2.8 右键,Source,GGASpublic 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 blocke.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 blocke.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、结束逻辑
后面再实现。个人学习笔记,若有误还望不吝赐教。来源:https://www.icode9.com/content-1-771551.html