创建MyFrame类
import com.laoma.obj.*;
import com.laoma.util.BackGround;
import com.laoma.util.Start;
import com.laoma.util.StaticValue;
import jdk.jshell.Snippet;
import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
public class MyFrame extends JFrame implements KeyListener, Runnable {
//储存所有背景
private List<BackGround> allBg = new ArrayList<>();
//存储档当前背景
private BackGround nowBg = new BackGround();
//开始界面
private Start s = new Start();
//用于双缓存
private Image offScreenImage = null;
//马里奥对象
private Mario mario = new Mario();
//实现马里奥线程
private Thread thread = new Thread(this);
public MyFrame() {
//设置标题
this.setTitle("老马麻里奥");
//设置窗口大小
this.setSize(800, 600);
//设置窗口居中显示
this.setLocationRelativeTo(null);
//设置窗口关闭
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//设置窗口大小不可变
this.setResizable(false);
//添加键盘监听
this.addKeyListener(this);
//让窗口显示
this.setVisible(true);
//初始化图片
StaticValue.init();
//初始化马里奥
mario = new Mario(10, 355, getHeight(), getWidth());
//创建全部场景
for (int i = 1; i <= 3; i++) {
allBg.add(new BackGround(i, i == 3 ? true : false));
}
//将第一个场景设置为当前场景
nowBg = allBg.get(0);
mario.setBackGround(nowBg);
//绘制图像
repaint();
thread.start();
// try {
// new Music();
// } catch (FileNotFoundException e) {
// throw new RuntimeException(e);
// } catch (JavaLayerException e) {
// throw new RuntimeException(e);
// }
}
@Override
public void paint(Graphics g) {
if (offScreenImage == null) {
offScreenImage = createImage(800, 600);
}
Graphics graphics = offScreenImage.getGraphics();
graphics.fillRect(0, 0, 800, 600);
/*//绘制开始界面
graphics.drawImage(s.getsImage(), 0, 0, this);*/
//绘制背景
graphics.drawImage(nowBg.getBgImage(), 0, 0, this);
//绘制敌人
for (Enemy e : nowBg.getEnemyList()) {
graphics.drawImage(e.getShow(), e.getX(), e.getY(), this);
}
//绘制道具
for (DaoJu daoJu : nowBg.getDjlist()) {
graphics.drawImage(daoJu.getShow(), daoJu.getX(), daoJu.getY(), this);
}
//绘制障碍物
for (Obstacle ob : nowBg.getObstacleList()) {
graphics.drawImage(ob.getShow(), ob.getX(), ob.getY(), this);
}
//绘制城堡
graphics.drawImage(nowBg.getTower(), 620, 270, this);
//绘制旗杆
graphics.drawImage(nowBg.getGan(), 500, 220, this);
//绘制马里奥
if (!mario.isBig()) {
graphics.drawImage(mario.getShow(), mario.getX(), mario.getY(), 25, 25, this);
} else {
graphics.drawImage(mario.getShow(), mario.getX(), mario.getY() - 15, 28, 40, this);
}
//绘制火球
for (HuoQiu huoQiu : nowBg.getHuoQius()) {
graphics.drawImage(huoQiu.getShow(), huoQiu.getX(), huoQiu.getY(), this);
}
//绘制分数
Color c = graphics.getColor();
graphics.setColor(Color.black);
graphics.setFont(new Font("黑体", Font.BOLD, 25));
graphics.drawString("当前分数为:" + mario.getScore(), 300, 100);
graphics.setColor(c);
//将绘制的背景添加到窗口中
g.drawImage(offScreenImage, 0, 0, this);
}
public static void main(String[] args) {
MyFrame myFrame = new MyFrame();
}
@Override
public void keyTyped(KeyEvent e) {
}
//按下键盘调用
@Override
public void keyPressed(KeyEvent e) {
//向右移动
if (e.getKeyCode() == 39) {
mario.rightMove();
}
//向左移动
if (e.getKeyCode() == 37) {
mario.leftMove();
}
//跳跃
if (e.getKeyCode() == 38) {
mario.jump();
}
//发射火球
if (e.getKeyCode() == 32) {
mario.fire();
}
//向右奔跑
if (e.isShiftDown() && e.getKeyCode() == 39) {
mario.rightSpeed();
}
//向左奔跑
if (e.isShiftDown() && e.getKeyCode() == 37) {
}
/*//暂停
if (e.isAltDown()) {
JOptionPane.showMessageDialog(this, "暂停");
}*/
}
//松开键盘调用
@Override
public void keyReleased(KeyEvent e) {
//向左停止
if (e.getKeyCode() == 37) {
mario.leftStop();
}
//向右停止
if (e.getKeyCode() == 39) {
mario.rightStop();
}
}
@Override
public void run() {
while (true) {
repaint();
try {
Thread.sleep(50);
//判断马里奥是否进入下一关
if (mario.getX() >= 775) {
nowBg = allBg.get(nowBg.getSort());
mario.setBackGround(nowBg);
mario.setX(10);
mario.setY(395);
}
//判断马里奥是否死亡
if (mario.isDeath()) {
JOptionPane.showMessageDialog(this, "马里奥死了");
System.exit(0);
}
//判断游戏是否结束
if (mario.isOk()) {
JOptionPane.showMessageDialog(this, "恭喜,通关!");
System.exit(0);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
创建背景Background类
import com.laoma.obj.DaoJu;
import com.laoma.obj.Enemy;
import com.laoma.obj.HuoQiu;
import com.laoma.obj.Obstacle;
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 List<Obstacle> obstacleList = new ArrayList<>();
//存放敌人
private List<Enemy> enemyList = new ArrayList<>();
//用于存放旗杆
private BufferedImage gan = null;
//用于存放城堡
private BufferedImage tower = null;
//用于存放道具
private List<DaoJu> djlist = new ArrayList<>();
//用于存放火球
private List<HuoQiu> huoQius = new ArrayList<>();
//判断马里奥是否到达旗杆位置
private boolean isReach = false;
//判断旗子是否落地
private boolean isBase = false;
public BackGround() {
}
public BackGround(int sort, boolean flag) {
this.sort = sort;
this.flag = flag;
if (flag) {
bgImage = StaticValue.bg2;
} else {
bgImage = StaticValue.bg;
}
//判断是否为第一关
if (sort == 1) {
//绘制地面
for (int i = 0; i <= 27; i++) {
obstacleList.add(new Obstacle(i * 30, 420, 2, this));
}
for (int j = 0; j <= 120; j += 30) {
for (int i = 0; i < 27; i++) {
obstacleList.add(new Obstacle(i * 30, 570 - j, 1, this));
}
}
//绘制 砖块
for (int i = 120; i <= 150; i += 30) {
obstacleList.add(new Obstacle(i, 300, 3, this));
}
for (int i = 300; i <= 570; i += 30) {
if (i == 360 || i == 390 || i == 480 || i == 510 || i == 540) {
obstacleList.add(new Obstacle(i, 300, 3, this));
} else {
obstacleList.add(new Obstacle(i, 300, 0, this));
}
}
for (int i = 420; i <= 450; i += 30) {
obstacleList.add(new Obstacle(i, 240, 3, this));
}
obstacleList.add(new Obstacle(210, 300, 3, this));
//绘制水管
for (int i = 360; i <= 600; i += 25) {
if (i == 360) {
obstacleList.add(new Obstacle(620, i, 5, this));
obstacleList.add(new Obstacle(645, i, 6, this));
} else {
obstacleList.add(new Obstacle(620, i, 7, this));
obstacleList.add(new Obstacle(645, i, 8, this));
}
}
//绘制道具方块
obstacleList.add(new Obstacle(180, 300, 9, this));
//绘制蘑菇敌人
enemyList.add(new Enemy(580, 385, 1, true, this));
//绘制食人花敌人
enemyList.add(new Enemy(635, 420, 2, true, this, 328, 428));
//绘制乌龟敌人
enemyList.add(new Enemy(280, 385, 3, true, this));
}
//判断是否为第二关
if (sort == 2) {
for (int i = 0; i <= 27; i++) {
obstacleList.add(new Obstacle(i * 30, 420, 2, this));
}
for (int j = 0; j <= 120; j += 30) {
for (int i = 0; i < 27; i++) {
obstacleList.add(new Obstacle(i * 30, 570 - j, 1, this));
}
}
//绘制第一根水管
for (int i = 360; i <= 600; i += 25) {
if (i == 360) {
obstacleList.add(new Obstacle(60, i, 5, this));
obstacleList.add(new Obstacle(85, i, 6, this));
} else {
obstacleList.add(new Obstacle(60, i, 7, this));
obstacleList.add(new Obstacle(85, i, 8, this));
}
}
//绘制第二根水管
for (int i = 330; i <= 600; i += 25) {
if (i == 330) {
obstacleList.add(new Obstacle(620, i, 5, this));
obstacleList.add(new Obstacle(645, i, 6, this));
} else {
obstacleList.add(new Obstacle(620, i, 7, this));
obstacleList.add(new Obstacle(645, i, 8, this));
}
}
//绘制砖块
obstacleList.add(new Obstacle(300, 330, 0, this));
for (int i = 270; i <= 330; i += 30) {
if (i == 270 || i == 330) {
obstacleList.add(new Obstacle(i, 360, 0, this));
} else {
obstacleList.add(new Obstacle(i, 360, 3, this));
}
}
for (int i = 240; i <= 360; i += 30) {
if (i == 240 || i == 360) {
obstacleList.add(new Obstacle(i, 390, 0, this));
} else {
obstacleList.add(new Obstacle(i, 390, 3, this));
}
}
obstacleList.add(new Obstacle(240, 300, 0, this));
for (int i = 360; i <= 540; i += 60) {
obstacleList.add(new Obstacle(i, 270, 3, this));
}
//绘制道具方块
obstacleList.add(new Obstacle(210, 300, 9, this));
//绘制第二关第一个蘑菇敌人
enemyList.add(new Enemy(200, 385, 1, true, this));
//绘制第二关第二个蘑菇敌人
enemyList.add(new Enemy(500, 385, 1, true, this));
//绘制第二关第一个食人花敌人
enemyList.add(new Enemy(75, 420, 2, true, this, 328, 428));
//绘制第二关第二个食人花敌人
enemyList.add(new Enemy(635, 420, 2, true, this, 298, 388));
//第二关乌龟敌人
enemyList.add(new Enemy(580, 385, 3, true, this));
}
//判断是否为第三关
if (sort == 3) {
for (int i = 0; i <= 27; i++) {
obstacleList.add(new Obstacle(i * 30, 420, 2, this));
}
for (int j = 0; j <= 120; j += 30) {
for (int i = 0; i < 27; i++) {
obstacleList.add(new Obstacle(i * 30, 570 - j, 1, this));
}
}
//绘制砖块
int temp = 290;
for (int i = 390; i >= 270; i -= 30) {
for (int j = temp; j <= 410; j += 30) {
obstacleList.add(new Obstacle(j, i, 3, this));
}
temp += 30;
}
temp = 60;
for (int i = 390; i >= 360; i -= 30) {
for (int j = temp; j <= 90; j += 30) {
obstacleList.add(new Obstacle(j, i, 3, this));
}
temp += 30;
}
//绘制旗杆
gan = StaticValue.gan;
//绘制城堡
tower = StaticValue.tower;
//把旗子添加到旗杆上
obstacleList.add(new Obstacle(515, 220, 4, this));
//绘制第三关蘑菇敌人
enemyList.add(new Enemy(150, 385, 1, true, this));
}
}
public BufferedImage getBgImage() {
return bgImage;
}
public int getSort() {
return sort;
}
public boolean isFlag() {
return flag;
}
public List<Obstacle> getObstacleList() {
return obstacleList;
}
public BufferedImage getGan() {
return gan;
}
public BufferedImage getTower() {
return tower;
}
public boolean isReach() {
return isReach;
}
public void setReach(boolean reach) {
isReach = reach;
}
public boolean isBase() {
return isBase;
}
public void setBase(boolean base) {
isBase = base;
}
public List<Enemy> getEnemyList() {
return enemyList;
}
public List<DaoJu> getDjlist() {
return djlist;
}
public List<HuoQiu> getHuoQius() {
return huoQius;
}
}
创建敌人类Enemy类
import com.laoma.util.BackGround;
import com.laoma.util.StaticValue;
import java.awt.*;
import java.awt.image.BufferedImage;
public class Enemy implements Runnable {
//存储当前坐标
private int x;
private int y;
//存储敌人类型
private int type;
//判断敌人运动方向
private boolean face_to = true;
//用于显示当前敌人图像
private BufferedImage show;
//定义一个背景对象
private BackGround bg;
//食人花运动极限
private int max_up = 0;
private int max_down = 0;
//定义一个线程对象
private Thread thread = new Thread(this);
//用来表示当前图片状态
private int image_type = 0;
public Enemy() {
}
//蘑菇敌人
public Enemy(int x, int y, int type, boolean face_to, BackGround bg) {
this.x = x;
this.y = y;
this.type = type;
this.face_to = face_to;
this.bg = bg;
show = StaticValue.mogu.get(0);
thread.start();
}
//食人花敌人
public Enemy(int x, int y, int type, boolean face_to, BackGround bg, int max_up, int max_down) {
this.x = x;
this.y = y;
this.type = type;
this.face_to = face_to;
this.bg = bg;
this.max_up = max_up;
this.max_down = max_down;
show = StaticValue.flower.get(0);
thread.start();
}
//死亡方法
public void death() {
if (this.getType() == 1) {
show = StaticValue.mogu.get(2);
this.bg.getEnemyList().remove(this);
} else if (this.getType() == 3) {
//this.bg.getEnemyList().remove(this);
show = StaticValue.shell.get(0);
type = 4;
} else if (this.getType() == 4) {
this.bg.getEnemyList().remove(this);
}
}
@Override
public void run() {
while (true) {
//判断是否为蘑菇敌人
if (type == 1) {
if (face_to) {
this.x -= 2;
} else {
this.x += 2;
}
image_type = image_type == 1 ? 0 : 1;
show = StaticValue.mogu.get(image_type);
} else if (type == 3) {
//判断乌龟
if (face_to) {
this.x -= 2;
show = StaticValue.toise_L.get(image_type);
} else {
this.x += 2;
show = StaticValue.toise_R.get(image_type);
}
image_type = image_type == 1 ? 0 : 1;
} else if (type == 4) {
//判断龟壳
if (face_to) {
this.x -= 5;
} else {
this.x += 5;
}
image_type = image_type == 1 ? 0 : 1;
show = StaticValue.shell.get(image_type);
}
//定义两个布尔值
boolean canLeft = true;
boolean canRight = true;
for (int i = 0; i < bg.getObstacleList().size(); i++) {
Obstacle ob1 = bg.getObstacleList().get(i);
//判断是否可以向左走
if (ob1.getX() == this.x - 36 && (ob1.getY() + 65 > this.y && ob1.getY() - 35 < this.y)) {
canLeft = false;
}
//判断是否可以向右走
if (ob1.getX() == this.x + 36 && (ob1.getY() + 65 > this.y && ob1.getY() - 35 < this.y)) {
canRight = false;
}
}
//判断方向
if (face_to && !canLeft || this.x == 0) {
face_to = false;
} else if ((!face_to) && (!canRight) || this.x == 764) {
face_to = true;
}
//判断是否为食人花敌人
if (type == 2) {
if (face_to) {
this.y -= 2;
} else {
this.y += 2;
}
image_type = image_type == 1 ? 0 : 1;
//判断食人花是否到达极限位置
if (face_to && (this.y == max_up)) {
face_to = false;
}
if ((!face_to) && (this.y == max_down)) {
face_to = true;
}
show = StaticValue.flower.get(image_type);
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public Rectangle getRec(){
return new Rectangle(this.x,this.y,35,35);
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getType() {
return type;
}
public BufferedImage getShow() {
return show;
}
}
创建道具类DaoJu类
import com.laoma.util.BackGround;
import com.laoma.util.StaticValue;
import java.awt.image.BufferedImage;
public class DaoJu implements Runnable {
//位置
private int x;
private int y;
//显示当前图片状态
private BufferedImage show;
//类型
private int type;
//定义一个背景图像
private BackGround bg;
//图片状态
private int image_type=0;
//定义一个线程
private Thread thread = new Thread(this);
public DaoJu() {
}
public DaoJu(int x, int y, int type,BackGround bg) {
this.x = x;
this.y = y;
this.type = type;
this.bg = bg;
show = StaticValue.mg.get(0);
thread.start();
}
//吃掉道具
public void eat() {
this.bg.getDjlist().remove(this);
}
@Override
public void run() {
while (true) {
//判断道具类型0
if (type == 0) {
image_type = image_type == 1 ? 1 : 0;
show = StaticValue.mg.get(image_type);
} else if (type == 1) {
show = StaticValue.xh;
} else if (type == 2) {
image_type = image_type == 1 ? 1 : 0;
show = StaticValue.jinBi.get(image_type);
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public BufferedImage getShow() {
return show;
}
public int getType() {
return type;
}
}