1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Java实现超级玛丽小游戏教程

Java实现超级玛丽小游戏教程

时间:2020-01-14 06:36:27

相关推荐

Java实现超级玛丽小游戏教程

1.实现了哪些功能?

1.按键←、→、↑实现玛丽奥的基本移动和跳跃。

2.获取特殊道具后可以发射子弹、可以巨大化以及提升跳跃能力。

3.玛丽奥头顶特殊方块后会生成可以旋转的金币,吃到金币可以增加分数。

4.敌人会不断移动,接触到障碍物后会自动改变移动方向。

5.玛丽奥可以踩敌人或者用枪击杀敌人,同时增加分数。

6.有背景音乐,以及玛丽奥跳跃、射击等音效。

2.需要哪些基础?

线程、IO流、面向对象、集合、Swing等

3.设计思路。

①加载图片

加载图片的方式有五种,详细可见此博客:/qq827245563/article/details/79302217?spm=1001..3001.5506

我这里是通过ImageIO读取图片文件的方式来获取加载图片。

例如这样:

public static BufferedImage bg = null;bg = ImageIO.read(new File(path + "bg.png"));

设置为静态变量可以在使用时更便利的调用,同时也能最先加载图片。

②游戏窗口的创建与绘图

游戏窗口类继承了JFrame类,自然也担任其绘图的任务。

对于窗体的基本设置,在这里就不多赘述。

对于绘图,我们可以重写JFrame类中的paint()方法,通过g.drawImage(Image,int x,int y,Object observer)来绘制玛丽奥、敌人、障碍物等等。

这里需要利用图形界面编程的双缓冲技术。

先提出问题,为什么需要使用双缓冲技术?

在单缓冲绘图中,会出先屏幕闪烁的问题。而出现屏幕闪烁的原因通常是由于快速地多次绘制同一个区域所导致的,因为我们需要不断重绘界面来更新游戏进程(玛丽奥的移动、道具的i显示等等)。这种情况下,由于绘制的速度过快,屏幕上的图像可能会出现闪烁或者部分未被绘制的情况。这是因为屏幕的刷新率是有限的,如果在两次屏幕刷新之间绘制了新的图像,那么屏幕上原来的图像就会消失,从而导致闪烁的效果。

什么是双缓冲技术?它是如何解决屏幕闪烁的问题的?

使用双缓冲技术,可以先将要绘制的图像绘制到一个缓冲区中,待所有绘制完成后再一次性地将缓冲区中的图像绘制到屏幕上,这样就可以避免图像闪烁的问题。

具体实现的代码案例:

import java.awt.*;import java.awt.image.BufferedImage;public class DoubleBufferingExample extends Canvas {private BufferedImage buffer;public DoubleBufferingExample() {// 创建一个大小为 500x500 的缓冲区buffer = new BufferedImage(500, 500, BufferedImage.TYPE_INT_ARGB);}public void paint(Graphics g) {// 获取缓冲区的 Graphics 对象Graphics bufferGraphics = buffer.getGraphics();// 在缓冲区中绘制图像bufferGraphics.setColor(Color.WHITE);bufferGraphics.fillRect(0, 0, buffer.getWidth(), buffer.getHeight());bufferGraphics.setColor(Color.RED);bufferGraphics.fillRect(100, 100, 200, 200);// 将缓冲区中的图像绘制到屏幕上g.drawImage(buffer, 0, 0, null);}public static void main(String[] args) {Frame f = new Frame("Double Buffering Example");DoubleBufferingExample example = new DoubleBufferingExample();f.add(example);f.setSize(500, 500);f.setVisible(true);}}

在该示例中,创建了一个大小为 500x500 的缓冲区,并在缓冲区中绘制了一个红色的矩形。最后,将缓冲区中的图像绘制到屏幕上,从而避免了图像闪烁的问题。

键盘监听器

让该类实现KeyListener接口,并重写keyPressed()和 keyReleased()方法,在对应的键盘监听事件中调用对应的方法即可。如下:

@Overridepublic 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();}}//当键盘松开按键时调用@Overridepublic void keyReleased(KeyEvent e) {//想左停止if (e.getKeyCode() == 37) {mario.leftStop();}//向右停止if (e.getKeyCode() == 39) {mario.rightStop();}}

③如何实现玛丽奥的移动?

我们可以定义一个xSpeed的int类型变量,来改变玛丽奥的坐标,控制玛丽奥的移动方向和速度。再定义一个status的String类型变量来表示玛丽奥的运动状态。通过move()方法来改变玛丽奥的运动状态和移动速度。

然后在一个线程中,不断判断玛丽奥的运动状态来改变玛丽奥的坐标,实现玛丽奥的移动。

④如何让玛丽奥发射子弹?

子弹的本质是什么?

玛丽奥只有发射这个行为,发射之后,子弹就跟玛丽奥没有关系。所以子弹需要单独封装为一个类,拥有自己的属性和行为。

如何实现子弹的正确发射和移动?

1.首先对于子弹的方向:我们需要获取玛丽奥的方向,然后将其作为参数传入子弹的构造方法,来控制子弹的移动方向。

2.对于子弹的出现位置:子弹的出现位置一定是在玛丽奥的位置,所以在发射子弹的时候,创建子弹的对象,并传入玛丽奥的坐标作为子弹的初始坐标,进行发射。

如何消除子弹?

我们可以把创建好的子弹放在一个子弹集合中,当子弹被创建出来就存放在集合中,paint()方法对集合进行遍历绘制。如果子弹碰撞到障碍物或者敌人,就从子弹集合中删除该子弹对象。

⑤如何实现动图效果?

动图效果的实现其实是通过多个静态图片不断切换来实现的。例如玛丽奥的走路、金币的转动等等。我们只需要提前准备好几张图片,通过线程或定时器,轮番展示即可。如果是两张图片可以用三目运算符解决,如果是三张或三张以上的图片,可以通过switch-case语句来实现。示例如下:

//如果是金币if(this.type==2){switch (image_type) {case 0 -> image_type = 1;case 1 -> image_type = 2;case 2 -> image_type = 3;case 3 -> image_type = 4;case 4 -> image_type = 5;case 5 -> image_type = 0;}show=StaticValue.coins.get(image_type);}

⑥如何实现碰撞检测?

对于碰撞检测有三种方法,我在简书的游戏考核复盘上有写过,这里引入链接:/p/d1ccf963f76b

对于用Java实现一个小游戏,则推荐使用矩形碰撞检测,在玛丽奥对障碍物的阻碍,子弹碰撞到敌人或者障碍物的检测,都可以使用。原理就是,在障碍物的坐标周围形成一个与图片像素大小相应的矩形。通过intersects()来判断两个矩形是否接触。

⑦如何添加背景音乐?

我们可以在指定位置创建一个匿名内部类的线程来播放音乐。示例:

new Thread("sheji"){public void run(){String filename="src//Music//attack.mp3";try {BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(filename));Player player = new Player(buffer);player.play();} catch (Exception e) {System.out.println(e);}}}.start();

在此之前我们需要导入一个jre包。链接在这里:http://链接:/s/1iEeJ8pufKouQrBzzBPIhew?pwd=fncd 提取码:fncd

4.源码

1.MyFrame类(主方法所在)

package com.sxt;import javazoom.jl.player.Player;import javax.swing.*;import java.awt.*;import java.awt.event.KeyEvent;import java.awt.event.KeyListener;import java.io.BufferedInputStream;import java.io.FileInputStream;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 Image offScreenImage = null;//马里奥对象private Mario mario = new Mario();public static boolean isStart;//定义一个线程对象,用于实现马里奥的运动private Thread thread = new Thread(this);public MyFrame() {//设置窗口的大小为800 * 600this.setSize(800, 600);//设置窗口居中显示this.setLocationRelativeTo(null);//设置窗口的可见性this.setVisible(true);//设置点击窗口上的关闭键,结束程序this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//设置窗口大小不可变this.setResizable(false);//向窗口对象添加键盘监听器this.addKeyListener(this);//设置窗口名称this.setTitle("超级玛丽");//初始化图片StaticValue.init();isStart = true;//初始化马里奥mario = new Mario(0, 355,this.getHeight(),this.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();new Thread("backMusic"){public void run(){String filename="src//Music//music.wav";try {sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}try {BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(filename));Player player = new Player(buffer);player.play();} catch (Exception e) {System.out.println(e);}}}.start();}@Overridepublic void paint(Graphics g) {if (offScreenImage == null) {offScreenImage = createImage(800,600);}Graphics graphics = offScreenImage.getGraphics();graphics.fillRect(0,0,800,600);//绘制背景graphics.drawImage(nowBg.getBgImage(),0,0,this);//绘制敌人for (Enemy e : nowBg.getEnemyList()) {graphics.drawImage(e.getShow(),e.getX(),e.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(), 40, 25, this);}else {graphics.drawImage(mario.getShow(), mario.getX(), mario.getY()-15, 50, 40, this);}//绘制子弹for(Bullet bullet:nowBg.getBulletList()){graphics.drawImage(bullet.getShow(),bullet.getX()+5,bullet.getY()+7,this);}//绘制道具for(DaoJv daoJv:nowBg.getDaoJvList()){graphics.drawImage(daoJv.getShow(), daoJv.getX(), daoJv.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();}@Overridepublic void keyTyped(KeyEvent e) {}//当键盘按下按键时调用@Overridepublic 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();}}//当键盘松开按键时调用@Overridepublic void keyReleased(KeyEvent e) {//想左停止if (e.getKeyCode() == 37) {mario.leftStop();}//向右停止if (e.getKeyCode() == 39) {mario.rightStop();}}@Overridepublic 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(355);}//判断马里奥是否死亡if (mario.isDeath()) {JOptionPane.showMessageDialog(this,"马里奥死亡!!!");System.exit(0);}//判断游戏是否结束if (mario.isOK()) {JOptionPane.showMessageDialog(this,"恭喜你!成功通关了");System.exit(0);}} catch (InterruptedException e) {e.printStackTrace();}}}}

2.BackGround类

package com.sxt;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 List<Bullet> bulletList = new ArrayList<>();//用于存放我们的所有道具private List<DaoJv> daoJvList = new ArrayList<>();//用于显示旗杆private BufferedImage gan = null;//用于显示城堡private BufferedImage tower = null;//判断马里奥是否到达旗杆位置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) {//绘制第一关的地面,上地面type=1,下地面type=2for (int i = 0;i < 27;i++) {obstacleList.add(new Obstacle(i*30,420,1,this));}for (int j = 0;j <= 120;j += 30) {for (int i = 0;i < 27;i++) {obstacleList.add(new Obstacle(i*30,570-j,2,this));}}//绘制砖块for (int i = 120;i <= 150;i += 30) {obstacleList.add(new Obstacle(i,300,7,this));}obstacleList.add(new Obstacle(210,300,7,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,7,this));} else {obstacleList.add(new Obstacle(i,300,0,this));}}//绘制砖块for (int i = 420;i <= 450;i += 30) {obstacleList.add(new Obstacle(i,240,7,this));}//绘制特殊物品obstacleList.add(new Obstacle(445,150,9,this));//绘制道具方块obstacleList.add(new Obstacle(180,300,10,this));obstacleList.add(new Obstacle(480,300,10,this));//绘制水管for (int i = 360;i <= 600;i += 25) {if (i == 360) {obstacleList.add(new Obstacle(620,i,3,this));obstacleList.add(new Obstacle(645,i,4,this));}else {obstacleList.add(new Obstacle(620,i,5,this));obstacleList.add(new Obstacle(645,i,6,this));}}//绘制第一关的蘑菇敌人enemyList.add(new Enemy(580,385,true,1,this));//绘制第一关的食人花敌人enemyList.add(new Enemy(635,420,true,2,328,428,this));}//判断是否是第二关if (sort == 2) {//绘制第二关的地面,上地面type=1,下地面type=2for (int i = 0;i < 27;i++) {obstacleList.add(new Obstacle(i*30,420,1,this));}for (int j = 0;j <= 120;j += 30) {for (int i = 0;i < 27;i++) {obstacleList.add(new Obstacle(i*30,570-j,2,this));}}//绘制第一个水管for (int i = 360;i <= 600;i += 25) {if (i == 360) {obstacleList.add(new Obstacle(60,i,3,this));obstacleList.add(new Obstacle(85,i,4,this));}else {obstacleList.add(new Obstacle(60,i,5,this));obstacleList.add(new Obstacle(85,i,6,this));}}//绘制第二个水管for (int i = 330;i <= 600;i += 25) {if (i == 330) {obstacleList.add(new Obstacle(620,i,3,this));obstacleList.add(new Obstacle(645,i,4,this));}else {obstacleList.add(new Obstacle(620,i,5,this));obstacleList.add(new Obstacle(645,i,6,this));}}//绘制砖块obstacleList.add(new Obstacle(300,330,0,this));//绘制道具方块obstacleList.add(new Obstacle(210,300,10,this));obstacleList.add(new Obstacle(285,270,10,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,7,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,7,this));}}//绘制妨碍砖块obstacleList.add(new Obstacle(240,300,0,this));//绘制空砖块for (int i = 360;i <= 540;i += 60) {obstacleList.add(new Obstacle(i,270,7,this));}//绘制第二关的第一个食人花敌人enemyList.add(new Enemy(75,420,true,2,328,418,this));//绘制第二关的第二个食人花敌人enemyList.add(new Enemy(635,420,true,2,298,388,this));//绘制第二关的第一个蘑菇敌人enemyList.add(new Enemy(200,385,true,1,this));//绘制第二关的第二个蘑菇敌人enemyList.add(new Enemy(500,385,true,1,this));}//判断是否是第三关if (sort == 3) {//绘制第三关的地面,上地面type=1,下地面type=2for (int i = 0;i < 27;i++) {obstacleList.add(new Obstacle(i*30,420,1,this));}for (int j = 0;j <= 120;j += 30) {for (int i = 0;i < 27;i++) {obstacleList.add(new Obstacle(i*30,570-j,2,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,7,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,7,this));}temp += 30;}//绘制旗杆gan = StaticValue.gan;//绘制城堡tower = StaticValue.tower;//添加旗子到旗杆上obstacleList.add(new Obstacle(515,220,8,this));//绘制第三关的蘑菇敌人enemyList.add(new Enemy(150,385,true,1,this));enemyList.add(new Enemy(500,385,true,1,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 List<Bullet> getBulletList() {return bulletList;}public boolean isBase() {return isBase;}public void setBase(boolean base) {isBase = base;}public List<Enemy> getEnemyList() {return enemyList;}public List<DaoJv> getDaoJvList() {return daoJvList;}}

3.Bullet类

package com.sxt;import java.awt.*;import java.awt.image.BufferedImage;public class Bullet implements Runnable{//子弹坐标private int x;private int y;//子弹的朝向private boolean face_to=true;//子弹的图像private BufferedImage show=null;//创建一个背景类private BackGround bg;//子弹图像的状态private int image_type=0;//子弹移动的线程private Thread thread=new Thread(this);public Bullet(int x,int y,boolean face_to,BackGround bg){this.x=x;this.y=y;this.face_to=face_to;this.bg=bg;show=StaticValue.bullet_R;thread.start();}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 boolean isFace_to() {return face_to;}public void setFace_to(boolean face_to) {this.face_to = face_to;}public BufferedImage getShow() {return show;}public void setShow(BufferedImage show) {this.show = show;}public BackGround getBg() {return bg;}public void setBg(BackGround bg) {this.bg = bg;}public Rectangle getRec(){return new Rectangle(this.x,this.y,15,15);}@Overridepublic void run() {while(true){if(face_to){this.x-=10;show=StaticValue.bullet_L;}else {this.x+=10;show=StaticValue.bullet_R;}//遍历所有障碍物for(int i=0;i<bg.getObstacleList().size();i++){Obstacle ob=bg.getObstacleList().get(i);if(this.getRec().intersects(ob.getRec())){//this.y=900;this.bg.getBulletList().remove(this);}}//遍历所有敌人for(int i=0;i<bg.getEnemyList().size();i++){Enemy e=bg.getEnemyList().get(i);if(this.getRec().intersects(e.getRec())){this.y=900;this.bg.getBulletList().remove(this);e.death();}}try {thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}

4.DaoJv类

package com.sxt;import java.awt.image.BufferedImage;public class DaoJv implements Runnable{//定义道具坐标private int x,y;//定义道具类型private int type;//定义道具显示图片private BufferedImage show=null;//定义线程private Thread thread = new Thread(this);//定义一个背景类private BackGround bg;//显示图片的状态private int image_type=0;public DaoJv(){}public DaoJv(int x,int y,int type,BackGround bg){this.x=x;this.y=y;this.type=type;this.bg=bg;show=StaticValue.bigD;thread.start();}public void eat(){bg.getDaoJvList().remove(this);}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 getType() {return type;}public void setType(int type) {this.type = type;}public BufferedImage getShow() {return show;}public void setShow(BufferedImage show) {this.show = show;}public BackGround getBg() {return bg;}public void setBg(BackGround bg) {this.bg = bg;}public int getImage_type() {return image_type;}public void setImage_type(int image_type) {this.image_type = image_type;}@Overridepublic void run() {while(true){//是否是变大道具if(this.type==0){show=StaticValue.bigD;}//如果是跳跃提升道具if(this.type==1){show=StaticValue.jumpD;}//如果是金币if(this.type==2){switch (image_type) {case 0 -> image_type = 1;case 1 -> image_type = 2;case 2 -> image_type = 3;case 3 -> image_type = 4;case 4 -> image_type = 5;case 5 -> image_type = 0;}show=StaticValue.coins.get(image_type);}try {thread.sleep(50);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}

5.Enemy类

package com.sxt;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(int x, int y, boolean face_to, int type, BackGround bg) {this.x = x;this.y = y;this.face_to = face_to;this.type = type;this.bg = bg;show = StaticValue.mogu.get(0);thread.start();}//食人花敌人的构造函数public Enemy(int x, int y, boolean face_to, int type, int max_up, int max_down, BackGround bg) {this.x = x;this.y = y;this.face_to = face_to;this.type = type;this.max_up = max_up;this.max_down = max_down;this.bg = bg;show = StaticValue.flower.get(0);thread.start();}//死亡方法public void death() {show = StaticValue.mogu.get(2);this.bg.getEnemyList().remove(this);}public int getX() {return x;}public int getY() {return y;}public BufferedImage getShow() {return show;}public int getType() {return type;}public Rectangle getRec(){return new Rectangle(this.x,this.y,35,35);}@Overridepublic 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);}//定义两个布尔变量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)) {canRight = false;}//判断是否可以左走if (ob1.getX() == this.x - 36 && (ob1.getY() + 65 > this.y && ob1.getY() - 35 < this.y)) {canLeft = 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(20);} catch (InterruptedException e) {e.printStackTrace();}}}}

6.Mario类

package com.sxt;import javazoom.jl.player.Player;import java.awt.image.BufferedImage;import java.io.BufferedInputStream;import java.io.FileInputStream;public class Mario implements Runnable{//用于表示横纵坐标private int x;private int y;//用于表示当前的运动状态private String status;//用于显示当前状态对应的图像private BufferedImage show = null;//定义一个BackGround对象,用来获取障碍物的信息private BackGround backGround = new BackGround();//用来实现马里奥的动作private Thread thread = null;//马里奥的移动速度private int xSpeed;//马里奥的跳跃速度private int ySpeed;//定义一个索引来遍历玛丽奥的动作private int index;//表示马里奥上升的时间private int upTime = 0;//用于判断马里奥是否走到了城堡的门口private boolean isOK;//用于判断马里奥是否死亡private boolean isDeath = false;//定义玛丽奥的朝向private boolean face_to;//定义玛丽奥的枪里是否有子弹private boolean isEmpty=true;//表示分数private int score = 0;private int flag=0;private boolean isBig=false;private boolean isJump=false;private int height=25;private int width=25;public Mario() {}public Mario (int x,int y,int height,int width) {this.x = x;this.y = y;this.height=height;this.width=width;show = StaticValue.stand_R;this.status = "stand--right";this.face_to=true;thread = new Thread(this);thread.start();}//马里奥的死亡方法public void death() {isDeath = true;}//马里奥向左移动public void leftMove() {//改变速度xSpeed = -5;//判断马里奥是否碰到旗子if (backGround.isReach()) {xSpeed = 0;}//判断马里奥是否处于空中if (status.indexOf("jump") != -1) {status = "jump--left";}else {status = "move--left";}this.face_to=true;}//马里奥向右移动public void rightMove() {xSpeed = 5;//判断马里奥是否碰到旗子if (backGround.isReach()) {xSpeed = 0;}if (status.indexOf("jump") != -1) {status = "jump--right";}else {status = "move--right";}this.face_to=false;}//马里奥向左停止public void leftStop() {xSpeed = 0;if (status.indexOf("jump") != -1) {status = "jump--left";}else {status = "stop--left";}this.face_to=true;}//马里奥向右停止public void rightStop() {xSpeed = 0;if (status.indexOf("jump") != -1) {status = "jump--right";}else {status = "stop--right";}this.face_to=false;}//马里奥跳跃public void jump() {if (status.indexOf("jump") == -1) {if (status.indexOf("left") != -1) {status = "jump--left";this.face_to = true;} else {status = "jump--right";this.face_to = false;}if(!isJump) {ySpeed = -10;upTime = 7;}else{ySpeed=-20;upTime=7;}new Thread("jump"){public void run(){String filename="src//Music//jump.mp3";try {sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}try {BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(filename));Player player = new Player(buffer);player.play();} catch (Exception e) {System.out.println(e);}}}.start();//判断马里奥是否碰到旗子if (backGround.isReach()) {ySpeed = 0;}}}//马里奥下落public void fall() {if(status.indexOf("left")!=-1){status="jump--left";this.face_to=true;}else{status="jump--right";this.face_to=false;}ySpeed=10;}//玛丽奥发射子弹public void fire(){if(!isEmpty) {backGround.getBulletList().add(new Bullet(this.x + 8, this.y + 7, this.face_to, backGround));new Thread("sheji"){public void run(){String filename="src//Music//attack.mp3";try {BufferedInputStream buffer = new BufferedInputStream(new FileInputStream(filename));Player player = new Player(buffer);player.play();} catch (Exception e) {System.out.println(e);}}}.start();}}@Overridepublic void run() {while (true) {flag=0;//判断是否处于障碍物上boolean onObstacle = false;//判断是否可以往右走boolean canRight = true;//判断是否可以往左走boolean canLeft = true;//System.out.println(x);//判断马里奥是否到达旗杆位置if (backGround.isFlag() && this.x >= 500) {this.backGround.setReach(true);//判断旗子是否下落完成if (this.backGround.isBase()) {status = "move--right";if (x < 690) {x += 5;} else {isOK = true;}} else {if (y < 395) {xSpeed = 0;this.y += 5;status = "jump--right";}if (y > 395) {this.y = 395;status = "stop--right";}}} else {//遍历当前场景里所有的障碍物for (int i = 0; i < backGround.getObstacleList().size(); i++) {Obstacle ob = backGround.getObstacleList().get(i);//判断马里奥是否位于障碍物上if (ob.getY() == this.y + 25 && (ob.getX() > this.x - 30 && ob.getX() < this.x + 25)) {onObstacle = true;}//判断是否跳起来顶到砖块if ((ob.getY() >= this.y - 30 && ob.getY() <= this.y - 20) && (ob.getX() > this.x - 30 && ob.getX() < this.x + 25)) {if (ob.getType() == 0||ob.getType()==9) {backGround.getObstacleList().remove(ob);score += 1;flag=1;if(ob.getType()==9){isEmpty=false;}}if (ob.getType()==10){if(backGround.getSort()!=1) {if (isBig) {backGround.getDaoJvList().add(new DaoJv(ob.getX(), ob.getY() - 35, 1, backGround));} else {backGround.getDaoJvList().add(new DaoJv(ob.getX(), ob.getY() - 35, 0, backGround));}}else{backGround.getDaoJvList().add(new DaoJv(ob.getX()+5, ob.getY() - 30, 2, backGround));}}upTime = 0;}//判断是否可以往右走if (ob.getX() == this.x + 25 && (ob.getY() > this.y - 30 && ob.getY() < this.y + 25)) {canRight = false;}//判断是否可以往左走if (ob.getX() == this.x - 30 && (ob.getY() > this.y - 30 && ob.getY() < this.y + 25)) {canLeft = false;}}//判断马里奥是否碰到敌人死亡或者踩死蘑菇敌人for (int i = 0; i < backGround.getEnemyList().size(); i++) {Enemy e = backGround.getEnemyList().get(i);if (e.getY() == this.y + 20 && (e.getX() - 25 <= this.x && e.getX() + 35 >= this.x)) {if (e.getType() == 1) {e.death();score += 2;upTime = 3;ySpeed = -10;} else if (e.getType() == 2) {//马里奥死亡death();}}if ((e.getX() + 35 > this.x && e.getX() - 25 < this.x) && (e.getY() + 35 > this.y && e.getY() - 20 < this.y)) {//马里奥死亡death();}}//判断马里奥是否碰到道具for(int i=0;i<backGround.getDaoJvList().size();i++){DaoJv d=backGround.getDaoJvList().get(i);if((d.getX()+35>this.x&&d.getX()-25<this.x)&&d.getY()+35>this.y&&d.getY()-25<this.y){//如果是变大道具if(d.getType()==0){d.eat();this.setBig(true);}//如果是跳跃提升道具if(d.getType()==1){d.eat();this.setJump(true);}//如果是金币道具if(d.getType()==2){d.eat();score+=5;}}}//进行马里奥跳跃的操作if (onObstacle && upTime == 0) {if (status.indexOf("left") != -1) {if (xSpeed != 0) {status = "move--left";} else {status = "stop--left";}} else {if (xSpeed != 0) {status = "move--right";} else {status = "stop--right";}}} else {if (upTime != 0) {upTime--;} else {fall();}y += ySpeed;}}if ((canLeft && xSpeed < 0) || (canRight && xSpeed > 0)) {x += xSpeed;//判断马里奥是否到了最左边if (x < 0) {x = 0;}}//判断当前是否是移动状态if (status.contains("move")) {index = index == 0 ? 1 : 0;}//判断是否向左移动if ("move--left".equals(status)) {show = StaticValue.run_L.get(index);}//判断是否向右移动if ("move--right".equals(status)) {show = StaticValue.run_R.get(index);}//判断是否向左停止if ("stop--left".equals(status)) {show = StaticValue.stand_L;}//判断是否向右停止if ("stop--right".equals(status)) {show = StaticValue.stand_R;}//判断是否向左跳跃if ("jump--left".equals(status)) {show = StaticValue.jump_L;}//判断是否向右跳跃if ("jump--right".equals(status)) {show = StaticValue.jump_R;}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}}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 getShow() {return show;}public void setShow(BufferedImage show) {this.show = show;}public void setBackGround(BackGround backGround) {this.backGround = backGround;}public boolean isOK() {return isOK;}public boolean isDeath() {return isDeath;}public int getScore() {return score;}public boolean isBig() {return isBig;}public boolean isJump() {return isJump;}public void setBig(boolean big) {isBig = big;}public void setJump(boolean jump) {isJump = jump;}public int getHeight() {return height;}public void setHeight(int height) {this.height = height;}public int getWidth() {return width;}public void setWidth(int width) {this.width = width;}}

7.Music类

package com.sxt;import javazoom.jl.decoder.JavaLayerException;import javazoom.jl.player.Player;import java.io.BufferedInputStream;import java.io.FileInputStream;import java.io.FileNotFoundException;public class Music {public Music() throws FileNotFoundException, JavaLayerException {Player player;String str = System.getProperty("user.dir") + "/src/Music/music.wav";BufferedInputStream name = new BufferedInputStream(new FileInputStream(str));player = new Player(name);player.play();}}

8.Obstacle类

package com.sxt;import java.awt.*;import java.awt.image.BufferedImage;public class Obstacle implements Runnable{//用于表示坐标private int x;private int y;//用于记录障碍物类型private int type;//用于显示图像private BufferedImage show = null;//定义当前的场景对象private BackGround bg = null;//定义一个线程对象private Thread thread = new Thread(this);public Obstacle(int x,int y,int type,BackGround bg) {this.x = x;this.y = y;this.type = type;this.bg = bg;show = StaticValue.obstacle.get(type);//如果是旗子的话,启动线程if (type == 8) {thread.start();}}public int getX() {return x;}public int getY() {return y;}public int getType() {return type;}public BufferedImage getShow() {return show;}//在障碍物周围生成一个矩形public Rectangle getRec(){return new Rectangle(this.x,this.y,30,30);}@Overridepublic void run() {while (true) {if (this.bg.isReach()) {if (this.y < 374) {this.y += 5;}else {this.bg.setBase(true);}}try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}}}}

9.StaticValue类

package com.sxt;import javax.imageio.ImageIO;import java.awt.*;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import java.security.PrivilegedExceptionAction;import java.util.ArrayList;import java.util.List;public class StaticValue {//背景public static BufferedImage bg = null;public static BufferedImage bg2 = null;//马里奥向左跳跃public static BufferedImage jump_L = null;//马里奥向右跳跃public static BufferedImage jump_R = null;//马里奥向左站立public static BufferedImage stand_L = null;//马里奥向右站立public static BufferedImage stand_R = null;//城堡public static BufferedImage tower = null;//BufferedImage=null//旗杆public static BufferedImage gan = null;//障碍物public static List<BufferedImage> obstacle = new ArrayList<>();//金币public static List<BufferedImage> coins=new ArrayList<>();//变大道具public static BufferedImage bigD=null;//跳跃提升道具public static BufferedImage jumpD=null;//马里奥向左跑public static List<BufferedImage> run_L = new ArrayList<>();//马里奥向右跑public static List<BufferedImage> run_R = new ArrayList<>();//蘑菇敌人public static List<BufferedImage> mogu = new ArrayList<>();//食人花敌人public static List<BufferedImage> flower = new ArrayList<>();//子弹public static BufferedImage bullet_R=null;public static BufferedImage bullet_L=null;//路径的前缀,方便后续调用public static String path = System.getProperty("user.dir") + "/src/images/";//初始化方法public static void init() {try {//加载背景图片bg = ImageIO.read(new File(path + "bg.png"));bg2 = ImageIO.read(new File(path + "bg2.png"));//加载马里奥向左站立stand_L = ImageIO.read(new File(path + "s_mario_stand_L.png"));//加载马里奥向右站立stand_R = ImageIO.read(new File(path + "s_mario_stand_R.png"));//加载城堡tower = ImageIO.read(new File(path + "tower.png"));//加载旗杆gan = ImageIO.read(new File(path + "gan.png"));//加载马里奥向左跳跃jump_L = ImageIO.read(new File(path + "s_mario_jump1_L.png"));//加载马里奥向右跳跃jump_R = ImageIO.read(new File(path + "s_mario_jump1_R.png"));//加载子弹bullet_L=ImageIO.read(new File(path+"bullet1_left.png"));bullet_R=ImageIO.read(new File(path+"bullet1_right.png"));} catch (IOException e) {e.printStackTrace();}//加载马里奥向左跑for (int i = 1;i <= 2;i++) {try {run_L.add(ImageIO.read(new File(path + "s_mario_run"+ i +"_L.png")));} catch (IOException e) {e.printStackTrace();}}//加载马里奥向右跑for (int i = 1;i <= 2;i++) {try {run_R.add(ImageIO.read(new File(path + "s_mario_run"+ i +"_R.png")));} catch (IOException e) {e.printStackTrace();}}try {//加载障碍物obstacle.add(ImageIO.read(new File(path + "brick.png")));obstacle.add(ImageIO.read(new File(path + "soil_up.png")));obstacle.add(ImageIO.read(new File(path + "soil_base.png")));} catch (IOException e) {e.printStackTrace();}//加载水管for (int i = 1;i <= 4;i++) {try {obstacle.add(ImageIO.read(new File(path + "pipe"+ i +".png")));} catch (IOException e) {e.printStackTrace();}}//加载不可破坏的砖块和旗子try {obstacle.add(ImageIO.read(new File(path + "brick2.png")));obstacle.add(ImageIO.read(new File(path + "flag.png")));} catch (IOException e) {e.printStackTrace();}//加载特殊物品try {obstacle.add(ImageIO.read(new File(path+"danjia.png")));obstacle.add(ImageIO.read(new File(path+"wenhaofangkuai.jpg")));} catch (IOException e) {throw new RuntimeException(e);}//加载蘑菇敌人for (int i = 1;i <= 3;i++) {try {mogu.add(ImageIO.read(new File(path + "fungus"+i+".png")));} catch (IOException e) {e.printStackTrace();}}//加载食人花敌人for (int i = 1;i <= 2;i++) {try {flower.add(ImageIO.read(new File(path + "flower1."+i+".png")));} catch (IOException e) {e.printStackTrace();}}//加载变大道具try {bigD=ImageIO.read(new File(path+"big.png"));} catch (IOException e) {throw new RuntimeException(e);}//加载跳跃提升道具try {jumpD=ImageIO.read(new File(path+"jump.png"));} catch (IOException e) {throw new RuntimeException(e);}//记载金币道具for(int i=1;i<=6;i++){try {coins.add(ImageIO.read(new File(path+"coin"+i+".png")));} catch (IOException e) {throw new RuntimeException(e);}}}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。