网站建设 联系我们,外国可以做站外推广的网站,wordpress导入,长沙市天心区城乡建设局网站文章目录 一、效果展示二、代码编写1. 素材准备2. 创建窗口类3. 创建常量类4. 创建动作类5. 创建关卡类6. 创建障碍物类7. 创建马里奥类8. 编写程序入口 一、效果展示 二、代码编写
1. 素材准备
首先创建一个基本的 java 项目#xff0c;并将本游戏需要用到的图片素材 image… 文章目录 一、效果展示二、代码编写1. 素材准备2. 创建窗口类3. 创建常量类4. 创建动作类5. 创建关卡类6. 创建障碍物类7. 创建马里奥类8. 编写程序入口 一、效果展示 二、代码编写
1. 素材准备
首先创建一个基本的 java 项目并将本游戏需要用到的图片素材 image 导入。
图片素材如下 https://pan.baidu.com/s/1db_IcPvPKWKbVPtodPWO5Q?pwd03kv 提取码03kv 2. 创建窗口类 ① Java 内部已经给我们封装了窗口的各种方法我们只需创建一个窗口类并重写父类的方法即可使用 ② Alt Enter 键 → implement methods 可一键补全所有的重写方法 ③ 实现多线程有两种方法分别是继承 Thread 类和实现 Runnable 接口这里我们用 Runnable 方法因为 Java 不支持多继承。 重写 paint 方法实现场景、物体的绘制使用多线程无限绘制窗口。
完整代码如下
package com.zxe.beans;import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.List;/*** 窗口类*/
public class MyFrame extends JFrame implements KeyListener, Runnable {//定义一个集合用于所有的关卡private ListLevelMap levelMaps new ArrayList();//定义一个变量存放当前背景private LevelMap levelMap new LevelMap();//定义变量记录马里奥private Mario mario;//重写paint方法实现场景、物体的绘制Overridepublic void paint(Graphics g) {//创建一张图片Image image createImage(1045, 500);//设置图片Graphics graphics image.getGraphics();graphics.drawImage(levelMap.getBg(), 0, 0, 1045, 500, this);//绘制障碍物for (Obstacle obstacle : levelMap.getObstacles()){graphics.drawImage(obstacle.getObstacleImage(), obstacle.getX(), obstacle.getY(), this);}//绘制马里奥graphics.drawImage(mario.getMarioImage(), mario.getX(), mario.getY(), this);//将图片描绘到当前窗口中g.drawImage(image, 0, 0, this);}Overridepublic void keyTyped(KeyEvent e) {}Overridepublic void keyPressed(KeyEvent e) {if (e.getKeyCode() 37) {mario.runLeft();} else if (e.getKeyCode() 39) {mario.runRight();} else if (e.getKeyCode() 38) {mario.jump();}}public Mario getMario() {return mario;}public void setMario(Mario mario) {this.mario mario;}Overridepublic void keyReleased(KeyEvent e) {if (e.getKeyCode() 37) {mario.runLeftStop();} else if (e.getKeyCode() 39) {mario.runRightStop();} else if (e.getKeyCode() 38) {mario.jumpDown();}}Overridepublic void run() {//无限次绘制马里奥while (true) {repaint();try {Thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}//判断一下马里奥是否通关if (mario.getX() 1040) {levelMap levelMaps.get(levelMap.getLevel());mario.setLevelMap(levelMap);mario.setX(50);mario.setY(420);}}}public ListLevelMap getLevelMaps() {return levelMaps;}public void setLevelMaps(ListLevelMap levelMaps) {this.levelMaps levelMaps;}public LevelMap getLevelMap() {return levelMap;}public void setLevelMap(LevelMap levelMap) {this.levelMap levelMap;}
}
3. 创建常量类
小游戏中的各种元素画面其实都是一张张的图片而这些图片路径的定义都将放在常量类中完成。
package com.zxe.beans;import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** 常量类*/
public class Constant {//给窗口定义一张图片public static BufferedImage bg;//右跳图片public static BufferedImage jumpR;//左跳图片public static BufferedImage jumpL;//右边站立public static BufferedImage standR;//左边站立public static BufferedImage standL;//定义一个集合存放右跑动作public static ListBufferedImage runR new ArrayList();//定义一个集合存放左跑动作public static ListBufferedImage runL new ArrayList();//为障碍物定义一个集合public static ListBufferedImage onstacles new ArrayList();//定义一个变量记录文件路径前缀public static String prefix C:\\Users\\Lenovo\\Desktop\\demo\\file\\image\\;//初始化图片到系统中public static void initImage() {try {//加载图片bg ImageIO.read(new File(prefix bg2.jpeg));jumpR ImageIO.read(new File(prefix mario_jump_r.png));jumpL ImageIO.read(new File(prefix mario_jump_l.png));standR ImageIO.read(new File(prefix mario_stand_r.png));standL ImageIO.read(new File(prefix mario_stand_l.png));runR.add(ImageIO.read(new File(prefix mario_run_r1.png)));runR.add(ImageIO.read(new File(prefix mario_run_r2.png)));runL.add(ImageIO.read(new File(prefix mario_run_l1.png)));runL.add(ImageIO.read(new File(prefix mario_run_l2.png)));for (int i 1; i 6; i) {onstacles.add(ImageIO.read(new File(prefix ob i .png)));}} catch (IOException e) {e.printStackTrace();throw new RuntimeException(e);}}}常量用 static 修饰外部可直接通过类名调用常量而无需创建对象。 4. 创建动作类
记录玛丽的动作状态具体的常量名与代码分离可以降低代码的耦合度更规范化。 5. 创建关卡类
每个关卡的障碍物是不一样的这里需要外部传入关卡号在关卡类中把不同的障碍物拼成自定义的关卡。
完整代码如下
package com.zxe.beans;import com.zxe.utils.Constant;import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;/*** 关卡地图类*/
public class LevelMap {//记录当前场景需要的图片private BufferedImage bg;//记录当前关卡private int level;//创建一个集合用于存放障碍物private ListObstacle obstacles new ArrayList();public LevelMap() {}public LevelMap(int level) {this.level level;bg Constant.bg;if (level 1) {//绘制方块obstacles.add(new Obstacle(100, 370, 0, this));obstacles.add(new Obstacle(130, 370, 1, this));obstacles.add(new Obstacle(160, 370, 0, this));obstacles.add(new Obstacle(190, 370, 1, this));obstacles.add(new Obstacle(300, 260, 0, this));obstacles.add(new Obstacle(330, 260, 1, this));obstacles.add(new Obstacle(360, 260, 1, this));obstacles.add(new Obstacle(800, 300, 0, this));obstacles.add(new Obstacle(830, 300, 0, this));obstacles.add(new Obstacle(860, 300, 1, this));obstacles.add(new Obstacle(890, 300, 1, this));//绘制水管obstacles.add(new Obstacle(420, 420, 4, this));obstacles.add(new Obstacle(450, 420, 5, this));obstacles.add(new Obstacle(415, 390, 2, this));obstacles.add(new Obstacle(435, 390, 2, this));obstacles.add(new Obstacle(455, 390, 3, this));obstacles.add(new Obstacle(600, 420, 4, this));obstacles.add(new Obstacle(630, 420, 5, this));obstacles.add(new Obstacle(600, 390, 4, this));obstacles.add(new Obstacle(630, 390, 5, this));obstacles.add(new Obstacle(595, 360, 2, this));obstacles.add(new Obstacle(615, 360, 2, this));obstacles.add(new Obstacle(635, 360, 3, this));} else if (level 2) {int i 0;for (int y 420; y 300; y - 30) {for (int x 100; x 190 - 30 * i; x 30) {obstacles.add(new Obstacle(x 30 * i, y, 0, this));}for (int x 300; x 390 - 30 * i; x 30) {obstacles.add(new Obstacle(x, y, 0, this));}for (int x 550; x 640 - 30 * i; x 30) {obstacles.add(new Obstacle(x 30 * i, y, 0, this));}for (int x 670; x 790 - 30 * i; x 30) {obstacles.add(new Obstacle(x, y, 0, this));}i;}}}public BufferedImage getBg() {return bg;}public void setBg(BufferedImage bg) {this.bg bg;}public int getLevel() {return level;}public void setLevel(int level) {this.level level;}public ListObstacle getObstacles() {return obstacles;}public void setObstacles(ListObstacle obstacles) {this.obstacles obstacles;}
}
6. 创建障碍物类
障碍物的属性包括图片以及横纵坐标。
完整代码如下
package com.zxe.beans;import com.zxe.utils.Constant;import java.awt.image.BufferedImage;/*** 障碍物类*/
public class Obstacle {//记录障碍物的坐标private int x;private int y;//定义一个变量记录当前障碍物的图片信息private BufferedImage obstacleImage;//定义障碍物类型private int type;//定义变量存放当前的背景private LevelMap bg;public Obstacle(int x, int y, int type, LevelMap bg) {this.x x;this.y y;this.type type;this.bg bg;//根据障碍物的编号从常量中的障碍物集合中获取对应的图片this.obstacleImage Constant.onstacles.get(type);}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 BufferedImage getObstacleImage() {return obstacleImage;}public void setObstacleImage(BufferedImage obstacleImage) {this.obstacleImage obstacleImage;}public int getType() {return type;}public void setType(int type) {this.type type;}public LevelMap getBg() {return bg;}public void setBg(LevelMap bg) {this.bg bg;}
}
7. 创建马里奥类
马里奥的无限行走动作由多线程实现定义一个状态量status用于标记马里奥当前的运动状态以便进行不同动作的来回切换。
完整代码如下
package com.zxe.beans;import com.zxe.utils.Action;
import com.zxe.utils.Constant;import java.awt.image.BufferedImage;/*** 马里奥类*/
public class Mario implements Runnable {//记录马里奥坐标信息private int x;private int y;//记录马里奥状态private String status;//定义一个变量记录马里奥当前动作所对应的图片信息private BufferedImage marioImage;//定义变量记录当前的关卡地图也可以获取障碍物的信息private LevelMap levelMap new LevelMap();//创建线程执行马里奥的动作private Thread thread;//定义变量记录马里奥的移动速度private int xSpeed;//定义变量记录马里奥的跳跃速度private int ySpeed;//定义变量记录马里奥的上升状态private int up;public Mario() {}public Mario(int x, int y) {this.x x;this.y y;//默认马里奥的动作是朝右站立status Action.STAND_RIGHT;marioImage Constant.standR;thread new Thread(this);thread.start();}//马里奥向左移动的方法public void runLeft() {//判断当前是否为跳跃状态如果不是就改变状态if ( !status.contains(jump) ) {status Action.RUN_LEFT;} else {status Action.JUMP_LEFT;}xSpeed -5;}//马里奥向右移动的方法public void runRight() {//判断当前是否为跳跃状态如果不是就改变状态if ( !status.contains(jump) ) {status Action.RUN_RIGHT;} else {status Action.JUMP_RIGHT;}xSpeed 5;}public void jump() {if (status.contains(left)) {status Action.JUMP_LEFT;} else {status Action.JUMP_RIGHT;}ySpeed -12;}public void jumpDown() {ySpeed 12;}private void jumpStop() {if (status.contains(left)) {status Action.STAND_LEFT;} else {status Action.STAND_RIGHT;}ySpeed 0;}//马里奥向左移动停止的方法public void runLeftStop() {if (!status.contains(jump)) {status Action.STAND_LEFT;} else {status Action.JUMP_LEFT;}xSpeed 0;}//马里奥向右移动停止的方法public void runRightStop() {if (!status.contains(jump)) {status Action.STAND_RIGHT;} else {status Action.JUMP_RIGHT;}xSpeed 0;}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 String getStatus() {return status;}public void setStatus(String status) {this.status status;}public BufferedImage getMarioImage() {return marioImage;}public void setMarioImage(BufferedImage marioImage) {this.marioImage marioImage;}public LevelMap getLevelMap() {return levelMap;}public void setLevelMap(LevelMap levelMap) {this.levelMap levelMap;}public Thread getThread() {return thread;}public void setThread(Thread thread) {this.thread thread;}public int getxSpeed() {return xSpeed;}public void setxSpeed(int xSpeed) {this.xSpeed xSpeed;}public int getySpeed() {return ySpeed;}public void setySpeed(int ySpeed) {this.ySpeed ySpeed;}public int getUp() {return up;}public void setUp(int up) {this.up up;}Overridepublic void run() {int index 0;//控制马里奥无限移动while (true) {//判断当前是否移动xSpeed0左移动xSpeed0右移动if (xSpeed 0 || xSpeed 0) {x xSpeed;if (x 0) {x 0;}}if (ySpeed 0 || ySpeed 0) {y ySpeed;if (y 420) {y 420;jumpStop();}if (y 280) {y 280;}}//判断移动状态跑步状态图片切换if (status.contains(run)) {index index 0 ? 1 : 0;}//根据马里奥的状态切换不同的图片if (Action.RUN_LEFT.equals(status)) {marioImage Constant.runL.get(index);}if (Action.RUN_RIGHT.equals(status)) {marioImage Constant.runR.get(index);}if (Action.STAND_LEFT.equals(status)) {marioImage Constant.standL;}if (Action.STAND_RIGHT.equals(status)) {marioImage Constant.standR;}if (Action.JUMP_LEFT.equals(status)) {marioImage Constant.jumpL;}if (Action.JUMP_RIGHT.equals(status)) {marioImage Constant.jumpR;}// 控制线程的速度try {Thread.sleep(30);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}
8. 编写程序入口
创建游戏窗口并对窗口的基本属性进行设置创建三个关卡并调用 repaint 方法绘制场景。
package com.zxe;import com.zxe.beans.LevelMap;
import com.zxe.beans.Mario;
import com.zxe.utils.Constant;
import com.zxe.beans.MyFrame;import javax.swing.*;public class Main {public static void main(String[] args) {//创建窗口对象MyFrame myFrame new MyFrame();//设置窗口大小myFrame.setSize(1045,500);//设置窗口居中myFrame.setLocationRelativeTo(null);//设置窗口可见性myFrame.setVisible(true);//设置窗口关闭程序myFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置键盘监听事件myFrame.addKeyListener(myFrame);//设置窗口的大小不可改变myFrame.setResizable(false);//设置窗口标题myFrame.setTitle(超级玛丽);//加载图片Constant.initImage();//创建三个关卡地图for (int i 1; i 3; i) {myFrame.getLevelMaps().add(new LevelMap(i));}//设置当前关卡地图myFrame.setLevelMap(myFrame.getLevelMaps().get(0));//创建马里奥Mario mario new Mario(50, 420);myFrame.setMario(mario);mario.setLevelMap(myFrame.getLevelMap());//绘制场景myFrame.repaint();Thread thread new Thread(myFrame);thread.start();}
}