Java实现超级玛丽,老程序员的国庆假期泡汤了!
Posted 编程界明世隐
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java实现超级玛丽,老程序员的国庆假期泡汤了!相关的知识,希望对你有一定的参考价值。
作者简介
作者名:编程界明世隐
简介:CSDN博客专家,从事软件开发多年,精通Java、javascript,博主也是从零开始一步步把学习成长、深知学习和积累的重要性,喜欢跟广大ADC一起打野升级,欢迎您关注,期待与您一起学习、成长、起飞!
超级玛丽
系列目录
1. Java俄罗斯方块
2. Java五子棋小游戏
3. 老Java程序员花一天时间写了个飞机大战
4. Java植物大战僵尸
5. 老Java程序员花2天写了个连连看
6. Java消消乐(天天爱消除)
7. Java贪吃蛇小游戏
8. Java扫雷小游戏
9. Java坦克大战
10. Java迷宫小游戏
引言:
国庆前与群里的小伙伴们聊了一下,决定做一下超级玛丽这个游戏,毕竟以前也经常玩,网上找了一下资源,然后国庆就整起来了,果然程序员不配有假期,我的假期就这样泡汤了,超级玛丽你给我发工资。
实现思路
- 创建窗口。
- 创建加载所有图片的类。
- 创建场景,实例化场景。
- 创建障碍物,显示障碍物。
- 创建敌人,创建主线程,让敌人动起来。
- 创建马里奥,显示马里奥。
- 创建键盘事件。
- 马里奥的跳跃、左右移动、死亡等处理。
- 处理障碍物的消除,怪物的死亡等。
- 其他收尾处理(场景切换,背景音乐)。
代码实现
创建窗口
首先创建一个游戏窗体类GameFrame,继承至JFrame,用来显示在屏幕上(window的对象),每个游戏都有一个窗口,设置好窗口标题、尺寸、布局等就可以。
package main;
import javax.swing.JFrame;
/**
*窗体类
*/
public class GameFrame extends JFrame {
//构造方法
public GameFrame(){
setTitle("超级玛丽");//设置标题
setSize(900, 600);//设置窗体大小
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//关闭后进程退出
setLocationRelativeTo(null);//居中
setResizable(false);//不允许变大
}
}
创建面板容器GamePanel继承至JPanel
package main;
import javax.swing.JPanel;
/**
* 画布类
*/
public class GamePanel extends JPanel {
private GameFrame mainFrame = null;
private GamePanel panel = null;
//构造里面初始化相关参数
public GamePanel(GameFrame frame){
this.setLayout(null);
this.setOpaque(false);
this.mainFrame=frame;
this.panel =this;
}
}
再创建一个Main类,来启动这个窗口,用来启动。
package main;
//Main类
public class Main {
public static void main(String[] args) {
GameFrame frame = new GameFrame();
GamePanel panel = new GamePanel(frame);
frame.add(panel);
frame.setVisible(true);
}
}
右键执行这个Main类,窗口建出来了
加载所有的图片
创建StaticValue类,用来加载图片,属性全部定义为static 类型,其中 init 方法,只需调用一次,然后加载好所有的图片,方便后面使用。
package main;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.imageio.ImageIO;
public class StaticValue {
//存储马里奥的图片
public static List<BufferedImage> allMarioImage = new ArrayList<BufferedImage>();
//开始图片
public static BufferedImage startImage = null;
//结束图片
public static BufferedImage endImage = null;
//背景图片
public static BufferedImage bgImage = null;
//食人花图片
public static List<BufferedImage> allFlowerImage = new ArrayList<BufferedImage>();
//敌人图片
public static List<BufferedImage> allTriangleImage = new ArrayList<BufferedImage>();
//乌龟图片
public static List<BufferedImage> allTurtleImage = new ArrayList<BufferedImage>();
//障碍物图片
public static List<BufferedImage> allObstructionImage = new ArrayList<BufferedImage>();
//马里奥死亡图片
public static BufferedImage mariDeadImage = null;
//定义文件路径
public static String ImagePath = "/image/";
//将图片初始化
public static void init() {
String path = "";
//玛丽奥图片初始化
for (int i = 1; i <= 10; i++) {
try {
path = ImagePath + i + ".png";
allMarioImage.add(ImageIO.read(StaticValue.class.getResource(path)));
} catch (IOException e) {
e.printStackTrace();
}
}
//导入背景图片
try {
startImage = ImageIO.read(StaticValue.class.getResource(ImagePath + "start.jpg"));
bgImage = ImageIO.read(StaticValue.class.getResource(ImagePath + "firststage.jpg"));
endImage = ImageIO.read(StaticValue.class.getResource(ImagePath + "firststageend.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
//导入敌人图片
for (int i = 1; i <= 5; i++) {
try {
if (i <= 2) {
allFlowerImage
.add(ImageIO.read(StaticValue.class.getResource(ImagePath + "flower" + i + ".png")));
}
if (i <= 3) {
allTriangleImage.add(
ImageIO.read(StaticValue.class.getResource(ImagePath + "triangle" + i + ".png")));
}
allTurtleImage
.add(ImageIO.read(StaticValue.class.getResource(ImagePath + "Turtle" + i + ".png")));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//导入障碍物图片
for (int i = 1; i <= 12; i++) {
try {
allObstructionImage
.add(ImageIO.read(StaticValue.class.getResource(ImagePath + "ob" + i + ".png")));
} catch (IOException e) {
e.printStackTrace();
}
}
//导入玛丽奥死亡图片
try {
mariDeadImage = ImageIO.read(StaticValue.class.getResource(ImagePath + "over.png"));
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建场景
创建场景的背景
有7个场景,前6个的背景图如下:
第7个背景图如下:
其实就是多了个旗杆和城堡,用来结束游戏的,这里在设置背景的时候有些区别,我们来定义BackGround类。
定义BackGround类
- sort代表场景的数字,比如第一个场景就是1。
- flag为true就是最后一个场景,所以最后一个场景的图片有点不一样。
package main;
import java.awt.image.BufferedImage;
public class BackGround {
//当前场景图片
private BufferedImage bgImage = null;
//场景顺序
private int sort;
//是否为最后的场景
private boolean flag;
//游戏结束标记
private boolean isOver = false;
//定义降旗结束
private boolean isDown = false;
//构造方法
public BackGround(int sort,boolean flag) {
this.sort = sort;
this.flag = flag;
if (flag) {//最后一个场景
bgImage = StaticValue.endImage;
} else {//1-6场景
bgImage = StaticValue.bgImage;
}
}
//绘制
public void draw(Graphics g) {
g.drawImage(bgImage,0,0,null);
}
}
实例化场景
- 在GamePanel类中加入相关成员
//存全部7个场景的集合
private List<BackGround> allBG = new ArrayList<BackGround>();
//存当前场景
private BackGround nowBG = null;
- 在GamePanel类中加入init方法,此方法用来做游戏的全部初始化操作,比如 初始化图片、创建背景(包含障碍物、敌人等)、设置当前背景。
//初始化
private void init() {
//图片初始化
StaticValue.init();
//创建全部场景
for (int i = 1; i <= 7; i++) {
//i==7?true:false 最后一个场景有点区别,有个结束的城堡
this.allBG.add(new BackGround(i, i == 7 ? true : false));
}
//将第一个场景设置为当前场景
this.nowBG = this.allBG.get(0);
}
在GamePanel中重写paint方法,并在此方法中绘制背景。
@Override
public void paint(Graphics g) {
super.paint(g);
//绘制背景
this.nowBG.draw(g);
}
运行一下,背景被绘制到窗口上了。
创建障碍物类
package main;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
public class Obstruction implements Runnable{
//坐标
private int x;
private int y;
//控制旗子
private Thread t = new Thread(this);
//类型
private int type;
//初始类型
private int starttype;
//显示图片
private BufferedImage showImage = null;
//取得场景
private BackGround bg;
//构造方法
public Obstruction(int x,int y,int type,BackGround bg){
this.x = x;
this.y = y;
this.type = type;
this.starttype = type;
this.bg = bg;
setImage();
if(this.type == 11){
t.start();
}
}
//绘制
public void draw(Graphics g) {
g.drawImage(showImage,x,y,null);
}
//重置方法
public void reset(){
this.type = starttype;
this.setImage();
}
//根据状态改变显示图片
public void setImage(){
showImage = StaticValue.allObstructionImage.get(type);
}
public BufferedImage getShowImage() {
return showImage;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public void run() {
while(true){
if(this.bg.isOver()){
if(this.y < 420){
this.y += 5;
}else{
this.bg.setDown(true);
}
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
障碍物介绍
总共有12种障碍物,图片如下:
修改BackGround类
加入绘制障碍物的方法,比如第一个场景的 buildBackGround1()
注意点:
比如:this.allObstruction.add(new Obstruction(i * 60, 540, 9, this));
这里传入的是9,但其实取得是第10个障碍物
因为我们在StaticValue存障碍物的集合allObstructionImage,集合是从0开始的,所以这里传入9等于取到的是第10个障碍物,其他的一样的意思。
package main;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
public class BackGround {
//当前场景图片
private BufferedImage bgImage = null;
//场景顺序
private int sort;
//是否为最后的场景
private boolean flag;
//游戏结束标记
private boolean isOver = false;
//定义降旗结束
private boolean isDown = false;
//用集合保存障碍物
private List<Obstruction> allObstruction = new ArrayList<Obstruction>();
//被消灭的障碍物
private List<Obstruction> removeObstruction = new ArrayList<Obstruction>();
//构造方法
public BackGround(int sort,boolean flag) {
this.sort = sort;
this.flag = flag;
if (flag) {//最后一个场景
bgImage = StaticValue.endImage;
} else {//1-6场景
bgImage = StaticValue.bgImage;
}
//根据场景来配置对应的背景
switch (sort){
case 1:
buildBackGround1();
break;
case 2:
buildBackGround2();
break;
case 3:
buildBackGround3();
break;
case 4:
buildBackGround4();
break;
以上是关于Java实现超级玛丽,老程序员的国庆假期泡汤了!的主要内容,如果未能解决你的问题,请参考以下文章
ngMario —— 基于 AngularJS 实现的超级玛丽
国庆假期,整整七天,我使用SpringBoot终于做出了即时通信!!!