Java小游戏练习---超级玛丽代码实现

这篇具有很好参考价值的文章主要介绍了Java小游戏练习---超级玛丽代码实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

B站教学视频:

01_超级玛丽_创建窗口_哔哩哔哩_bilibili

素材提取:

【超级会员V2】我通过百度网盘分享的文件:Java游戏项目…
链接:百度网盘 请输入提取码
提取码:k6j1
复制这段内容打开「百度网盘APP 即可获取」
百度网盘 请输入提取码
百度网盘为您提供文件的网络备份、同步和分享服务。空间大、速度快、安全稳固,支持教育网加速,支持手机端。注册使用百度网盘即可享受免费存储空间
 

百度网盘 请输入提取码

百度网盘为您提供文件的网络备份、同步和分享服务。空间大、速度快、安全稳固,支持教育网加速,支持手机端。注册使用百度网盘即可享受免费存储空间

Java小游戏练习---超级玛丽代码实现

 

游戏构造思路:

首先需要创建一个窗口,游戏需要在该窗口中运行,其次我们需要添加游戏中要用到的图片,将其添加到一个专属包中,并在类中实现。(有些物品一样或只用一次,如旗杆,城堡等,普通添加即可;有些如:玛丽,蘑菇敌人等,需要移动以及其他动作,故需要创建列表方便实现不同图片来回使用)。此外,我们还需要给游戏添加背景图,设定游戏的关卡数,以及不同关卡之间的切换。

在以上基础步骤之后,就需要在场景中添加游戏中最关键的两个角色:玛丽和敌人,这两个角色需要运动以及一系列其他操作,因此我们需要分两个类来写,并通过线程来调用。

以下代码中额外添加了一个休眠用来进行判定,在运行之后如果在较长时间(5秒左右)后按下空格键,则敌人类将不会再运动,同时,若在运行开始后,立即按下空格,敌人类会在经历一小段休眠后再进行运动(因为添加了休眠,故经过一小段休眠后才会进行判断)

以上休眠的添加是因为在添加暂停功能时本人无法实现暂停功能而写的一个妥协方案,欢迎各位大佬在评论区提出有关添加暂停功能的方法

Java小游戏练习---超级玛丽代码实现

Java小游戏练习---超级玛丽代码实现

代码实现:

 MyFrame类:

package com.sxt;

import javazoom.jl.decoder.JavaLayerException;

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;

import static java.lang.Thread.sleep;

//创建窗口需要继承JFrame类,
//添加键盘监听,需要该类实现KeyListener接口,并重写其中抽象方法
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();
    //定义线程对象用于实现马里奥的运动
    private Thread thread = new Thread(this);
    static boolean isStart = false;


    //创建该类的空参构造
    public MyFrame() {
        //设置窗口大小
        this.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();
        //初始化马里奥
        mario = new Mario(10, 355);
        //创建全部的场景,一共有三个场景,因此需要用for循环来创建
        for (int i = 1; i <= 3; i++) {
            //要传入两个参数:当前关卡数i和是否为最后一关的布尔变量
            //要用三目运算符进行判断,判断这时的i是否是第三关
            allBg.add(new BackGround(i, i == 3 ? true : false));
        }
        //将第一个背景设置为当前场景
        nowBg = allBg.get(0);
        mario.setBackGround(nowBg);
        //绘制图像
        repaint();
        //启动线程并调用start方法
        thread.start();//绘制图像开始时同步播放音乐
        try {
            new Music();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (JavaLayerException e) {
            e.printStackTrace();
        }
    }
    //重写一下paint方法

    @Override
    public void paint(Graphics g) {
        //首先要判断,判断变量是否为null
        if (offScreenImage == null) {
            offScreenImage = createImage(800, 600);
        }
        //定义Graphics(画笔)对象
        Graphics graphics = offScreenImage.getGraphics();
        //调用graphics的fillRect方法对我们的图像进行填充
        graphics.fillRect(0, 0, 800, 600);
        //绘制背景,调用graphics的drawImage方法,将当前背景图像进行绘画
        //此时是将图像绘制到了缓冲区上
        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);
        //绘制马里奥
        graphics.drawImage(mario.getShow(), mario.getX(), mario.getY(), this);
        //添加分数
        Color c = graphics.getColor();
        graphics.setColor(Color.BLACK);
        graphics.setFont(new Font("黑体", Font.BOLD, 25));
        graphics.drawString("当前分数为:" + mario.getScore(), 300, 100);
        if (isStart == false) {
            graphics.setFont(new Font("宋体", Font.BOLD, 25));
            graphics.drawString("按下空格开始游戏", 270, 160);
        }

        //还原画笔颜色
        graphics.setColor(c);

        //接下来将缓冲区的图片绘制到窗口中,调用g.drawImage方法
        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 (isStart == false) {
            if (e.getKeyCode() == 32) {
                isStart = true;
            }
        } else {
            //向右移动
            if (e.getKeyCode() == 39) {
                mario.rightMove();
            }
            //向左移动
            if (e.getKeyCode() == 37) {
                mario.leftMove();
            }
            //跳跃
            if (e.getKeyCode() == 38) {
                mario.jump();
            }
        }
        }
        //当键盘松开按键时调用
        @Override
        public void keyReleased (KeyEvent e) {
            //向左停止
            if (isStart == true) {
                if (e.getKeyCode() == 37) {
                    mario.leftStop();
                }
                //向右停止
                if (e.getKeyCode() == 39) {
                    mario.rightStop();
                    //接下来让MyFrame类来实现Runnable接口并且重写抽象方法
                }
            }
        }

        @Override
        public void run () {
            //写一个死循环,在循环里调用repaint()方法,用于重新绘制我们的图像
            while (true) {
                repaint();
                //让线程休眠
                try {
                    sleep(50);
                    //判断此时马里奥是否移动到了最右端,是的话则要进行场景的切换
                    //当前窗口大小为800,马里奥宽度为25
                    if (mario.getX() >= 775) {
                        //满足就要切换当前场景,在这里可以调用now的sort,他表示第几关,索引为1和2
                        nowBg = allBg.get(nowBg.getSort());
                        //将当前场景对象传递给马里奥类
                        mario.setBackGround(nowBg);
                        mario.setX(10);
                        mario.setY(355);
                    }
                    //判断马里奥是否死亡
                    if (mario.isDeath()) {
                        JOptionPane.showMessageDialog(this, "马里奥死亡,游戏失败");
                        System.exit(0);
                    }
                    //判断游戏是否结束,即判断mario的isOK是否为true,若true则游戏结束
                    if (mario.isOK()) {
                        JOptionPane.showMessageDialog(this, "恭喜你!通关了");
                        System.exit(0);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

BackGround类:

package com.sxt;

import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;

public class BackGround {
    //当前场景要实现的图像,该对象用于显示当前场景的图片,赋初值为null
    private BufferedImage bgImage=null; //在bgImage上设置getter方法
    //记录当前是第几个场景,储存当前是第几关
    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 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;     //第一关和第二关背景
            //下一步生成getter方法
        }
        //判断是否为第一关
        if (sort==1){
            //绘制第一关的地面,上地面type=1,下地面type=2,
            // 窗口横坐标为800,一个地面为30
            for (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));
                }
            }
            //绘制砖块A
            for (int i=120;i<=150;i+=30){
                 obstacleList.add(new Obstacle(i,300,7,this));
                 //括号里是:横坐标,纵坐标,类型,this这个背景。
            }
            //绘制砖块B~~F
            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));
                }
            }
            //绘制砖块G
            for(int i=420;i<=450;i+=30){
                obstacleList.add(new Obstacle(i,240,7,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));
                    //接下来实现Obstacle列表的getter方法
                }
            }
            //绘制第一关的蘑菇敌人
            enemyList.add(new Enemy(580,385,true,1,this));
            enemyList.add(new Enemy(300,385,true,1,this));
            enemyList.add(new Enemy(100,385,true,1,this));
            enemyList.add(new Enemy(400,385,true,1,this));
            enemyList.add(new Enemy(400,265,true,1,this));
            //绘制第一关的食人花敌人
            enemyList.add(new Enemy(635,420,true,2,328,428,this));
        }
        //判断是否为第二关
        if(sort==2){
            //直接复制第一关的,三关的地砖一样
            //绘制第二关的地面,上地面type=1,下地面type=2,
            // 窗口横坐标为800,一个地面为30
            for (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));
                }
            }
            //绘制砖块C
            obstacleList.add(new Obstacle(300,330,0,this));
            //绘制砖块B,E,G
            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));
                }
            }
            //绘制砖块A,D,F,H,I
            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));
                }
            }
            //绘制妨碍1砖块
            obstacleList.add(new Obstacle(240,300,0,this));

            //绘制空1~4砖块
            for (int i=360;i<=540;i+=60){
                obstacleList.add(new Obstacle(i,270,7,this));
            }
            //绘制第二关的第一个蘑菇敌人
            enemyList.add(new Enemy(200,385,true,1,this));
            //绘制第二个蘑菇敌人
            enemyList.add(new Enemy(500,385,true,1,this));
            //第三个
            enemyList.add(new Enemy(400,205,true,1,this));
            //绘制第二关第一个食人花敌人
            enemyList.add(new Enemy(75,420,true,2,328,418,this));
            //绘制第二个食人花敌人
            enemyList.add(new Enemy(635,420,true,2,298,388,this));
        }
        //判断是否为第三关
        if (sort==3) {
            //绘制地面
            //绘制第三关的地面,上地面type=1,下地面type=2,
            // 窗口横坐标为800,一个地面为30
            for (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));
                }
            }
            //绘制第三个背景的A~O砖块
            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;
            }
            //绘制第三个背景的P~R砖块
            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));
            //接下来生成旗杆和城堡的getter方法

            //绘制第三关蘑菇敌人
            enemyList.add(new Enemy(150,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 boolean isBase() {
        return isBase;
    }

    public void setBase(boolean base) {
        isBase = base;
    }

    public List<Enemy> getEnemyList() {
        return enemyList;
    }
}

加载图片的StaticValue类:

package com.sxt;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.Buffer;
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;
    //旗杆
    public static BufferedImage gan=null;
    //障碍物,较多,需要列表
    public static List<BufferedImage> obstacle=new ArrayList<>();
    //马里奥向左跑
    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<>();
    //获取路径, 定义path变量,除了照片的名字以外前缀一直都一样,因此定义出来路径方便调用
    public static String path=System.getProperty("user.dir")+"/src/images/";

    //初始化方法
    public static void init(){
        //利用ImageIO流的read方法,注意在read处捕获异常all+enter
        try {
            //加载背景图片
            bg= ImageIO.read(new File(path+"bg.png"));
            bg2=ImageIO.read(new File(path+"bg2.png"));
            //加载玛丽向左站立
            stand_L=ImageIO.read(new File(path+"stand_L.png"));
            //加载玛丽向右站立
            stand_R=ImageIO.read(new File(path+"stand_R.png"));
            //加载马里奥向左跳跃
            jump_L=ImageIO.read(new File(path+"jump1_l.png"));
            //加载马里奥向右跳跃
            Jump_R=ImageIO.read(new File(path+"Jump1_R.png"));
            //加载城堡
            tower=ImageIO.read(new File(path+"tower.png"));
            //加载旗杆
            gan=ImageIO.read(new File(path+"gan.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        //加载马里奥向左跑
        for (int i=1;i<=2;i++){
            //向列表中添加
            try {
                run_L.add(ImageIO.read(new File(path+"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+"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();
        }
        //加载蘑菇敌人
        for(int i=1;i<=3;i++){
            try {
                mogu.add(ImageIO.read(new File(path+"fungus"+i+".png")));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

Obstacle类:该类设置了到旗子处后的后续操作

package com.sxt;

import java.awt.image.BufferedImage;

public class Obstacle implements Runnable{  //让该类实现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);    //初始化show,得到该类型的障碍物图像
        //下一步,生成这四个变量的getter方法
        //如果是旗子的话,启动线程
        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;
    }

    @Override
    public void run() {
        while(true){    //一个死循环
            //让线程休眠,休眠时间:50毫秒
            if (this.bg.isReach()) {  //判断马里奥是否到达旗子位置
            if (this.y<374){          //判断此时旗子是否落到了地上
                this.y+=5;            //若没有,则让旗子慢慢下降
            }else{
                this.bg.setBase(true);//将isBase设置为true,表示旗子已经成功落地
            }
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Strong类:

package com.sxt;

import java.awt.image.BufferedImage;

public class Strong implements Runnable{

    //储存食物坐标
    private int x,y;
    //显示图像
    private BufferedImage show;
    //定义一个背景对象
    private BackGround bg;
    //实现线程对象
    private Thread thread=new Thread(this);
    public Strong(int x,int y,BackGround bg){
        this.x=x;
        this.y=y;
        this.bg=bg;

    }
    @Override
    public void run() {

    }
}

Mario类:

package com.sxt;

import jdk.nashorn.internal.ir.SplitReturn;

import java.awt.image.BufferedImage;

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 int score=0;
    public Mario(){
    }
    public Mario(int x,int y){
        this.x=x;
        this.y=y;
        show=StaticValue.stand_R;
        this.status="stand--right"; //下一步使马里奥类实现Runnable接口并重写其中的抽象方法
        //初始化线程
        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";
        }
    }
    //向右移动
    public void rightMove(){
        xSpeed=5;
        //判断马里奥是否碰到了旗子
        if (backGround.isReach()){          //若是,则马里奥不可再移动
            xSpeed=0;
        }
        if (status.indexOf("jump")!=-1){
            status="jump--right";
        }else{
            status="move--right";
        }
    }
    //向左停止
    public void leftStop(){
        xSpeed=0;
        if(status.indexOf("jump")!=-1) {
            status="jump--left";
        }else{
            status="stop--left";
        }
    }
    //向右停止
    public void rightStop(){
        xSpeed=0;
        if(status.indexOf("jump")!=-1) {
            status="jump--right";
        }else{
            status="stop--right";
        }
    }
    //马里奥跳跃
    public void jump() {
        //判断是否是跳跃状态,判断status调用它的indexOF方法
        if (status.indexOf("jump")==-1) {
            //判断方向,不等于-1则方向向左
            if (status.indexOf("left")!=-1){
                status="jump--left";
            }else{
                status="jump--right";
            }
            //改变下降速度向上跳跃y值减少
            ySpeed=-10;
            //设置向上跳的高度
            upTime=7;       //向上跳一下70
        }
            //判断马里奥是否碰到了旗子
            if (backGround.isReach()){          //若是,则马里奥不可再移动
                ySpeed=0;
            }
    }
    //马里奥下落
    public void fall(){
        //下落时可能是从障碍物上掉下也可能是跳起后落下
        if (status.indexOf("left")!=-1){
            status="jump--left";
        }else{
            status="jump--right";
        }
        //下落时速度应该是正的,因为y值要++
        ySpeed=10;
    }
    @Override
    public void run() {
        while (true){
            //判断是否处于障碍物上
            boolean onObstacle=false;
            //判断是否可以向右走
            boolean canRight=true;
            //判断是否可以向左走
            boolean canLeft=true;
            //判断马里奥是否到达旗杆位置
            if (backGround.isFlag()&&this.x>=500){
                //setReach设置为true,表明此刻马里奥到达了旗杆的位置
                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)) {
                        //判断此时顶到的砖块类型是否是普通砖块(0),若是则移除
                        if (ob.getType() == 0) {
                            //如果是则调用backGround.getObstacleList().remove()方法将ob移出去
                            backGround.getObstacleList().remove(ob);
                            //破坏砖块+1分
                            score+=1;
                        }
                        upTime = 0;   //使马里奥顶到砖块后立刻下落
                    }
                    //判断是否可以向右走
                    if (ob.getX() == this.x + 25 && (ob.getY() > this.y - 30 && ob.getY() < this.y + 25)) {
                        //如果符合该判断条件,则说明马里奥右侧有障碍物,无法往右走,将canRight置为false
                        canRight = false;
                    }

                    //判断是否可以往左走
                    if (ob.getX() == this.x - 30 && (ob.getY() > this.y - 30 && ob.getY() < this.y + 25)) {
                        canLeft = false;
                    }
                }

                //判断马里奥是否碰到敌人死亡或者踩死蘑菇敌人
                //通过for循环来遍历每一个敌人
                for (int i=0;i<backGround.getEnemyList().size();i++){
                    Enemy e=backGround.getEnemyList().get(i);       //用e来储存我们当前的敌人
                    //判断马里奥是否位于敌人的头上
                    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();
                    }
                }

                //进行马里奥跳跃的操作
                //先判断马里奥此时是否在障碍物上
                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;
            }
            //设置线程休眠50毫秒
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    public BufferedImage getShow() {
        return show;
    }

    public void setShow(BufferedImage show){
        this.show=show;
    }

    public void setBackGround(BackGround backGround) {
        this.backGround = backGround;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public boolean isOK() {
        return isOK;
    }

    public boolean isDeath() {
        return isDeath;
    }

    public int getScore() {
        return score;
    }
}

Enemy(敌人类):

package com.sxt;

import javax.xml.ws.BindingType;
import java.awt.image.BufferedImage;

import static java.lang.Thread.sleep;

public class Enemy implements Runnable{
    //储存当前坐标
    private int x,y;
    //储存敌人类型
    private final int type;
    //判断敌人的运动方向
    private boolean face_to=true;
    //用于显示敌人当前的图像
    private BufferedImage show;
    //定义一个背景对象
    private final BackGround bg;
    //食人花运动的极限范围
    private int max_up=0;
    private int max_down=0;
    //实现线程对象,用于实现食人花和蘑菇的运动
    private final Thread thread=new Thread(this);
    //定义当前图片的状态
    private int image_type=0;

//    创建MyFrame对象
//    MyFrame myFrame = new MyFrame();

    //蘑菇敌人的构造函数
    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();     //调用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;
    }

    @Override
    public void run() {
        try {
            sleep(2000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        if (MyFrame.isStart == true) {

            while (true) {
                //判断是否是蘑菇敌人,type是蘑菇敌人
                if (type == 1) {
                    if (face_to) {       //true是向左移动,false时向右移动
                        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循环来遍历每一个障碍物
                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 {
                    sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
       }        
 }

    }


Music类:文章来源地址https://www.toymoban.com/news/detail-458613.html

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();//调用方法播放音乐
    }
}

到了这里,关于Java小游戏练习---超级玛丽代码实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 用Python实现超级玛丽游戏【示例代码】

    效果演示: 1.基础设置(tools部分) 这个部分设置马里奥以及游戏中蘑菇等怪的的移动设置。 2.设置背景音乐以及场景中的文字(setup部分) 该部分主要设置场景中的背景音乐,以及字体的显示等设置。 设置游戏内菜单等(main_menu) main() 调用以上函数实现

    2024年02月14日
    浏览(41)
  • Java实现五子棋小游戏(附思路讲解,全部代码,游戏截图)

    本文章是如何实现一个单机版双人五子棋小游戏,通过Swing技术进行可视操作. 个人简介: 🤦‍♂️个人主页:码云不秃头. 😜本人是一名大三学生,马上就要变成考研狗啦,通过一学期对Java学习,经过老师的教学,实现单机版的双人五子棋小游戏,大家互相学习,也同时为了完成我的实

    2024年02月07日
    浏览(48)
  • Java实现俄罗斯方块小游戏。(附完整源代码)

    大家好,我是百思不得小赵。 创作时间:2022 年 5 月 12 日 博客主页: 🔍点此进入博客主页 —— 新时代的农民工 🙊 —— 换一种思维逻辑去看待这个世界 👀 今天是加入CSDN的第1167天。觉得有帮助麻烦👏点赞、🍀评论、❤️收藏 目录 一、游戏背景 二、功能实现 三、效果

    2024年02月03日
    浏览(72)
  • 实现用java做一个简易版《羊了个羊》小游戏(附源代码)

    该项目是跟着这个b站视频一步一步写出来的,初学java有些地方我看不是很明白,但是讲解很仔细,大家可以看原视频,我没有添加背景音乐和背景图片,做出来的效果也勉勉强强。 代码已经上传到github上了,大家可以去github上直接下载代码,附上链接:点击进入github源码链接

    2024年02月04日
    浏览(92)
  • 基于Python开发的玛丽大冒险小游戏(源码+可执行程序exe文件+程序配置说明书+程序使用说明书)

    本项目是一套基于Python开发的玛丽冒险小游戏程序,主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Python学习者。 包含:项目源码、项目文档等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,确保可以运行! 本系统的软件开发及运行环境

    2024年02月09日
    浏览(51)
  • 2048小游戏 java版(代码+注释)

            一个纯纯小白,想写点什么,也想学习一下怎么在这里写东西,就简单的写个2048小游戏。写的不好,大佬就不用看了,希望和大家交流学习,有写的不好或有更好的建议也欢迎提出来。(需要用的可直接粘贴复制)(轻喷) 目录 游戏展示 讲解  代码        

    2024年02月09日
    浏览(51)
  • java 300行代码 冒险闯关小游戏(代码+讲解)

              作为一个男孩子,从小就喜欢晚一些游戏。今天就用java写一个类似马里奥的冒险闯关小游戏,但这也不是一两天能完成的事情,我将会持续更新这个游戏(有什么好的介意也非常欢迎大家提出来,也能在我的基础上自己接着写)。目前完成的功能有:人物的流

    2024年02月05日
    浏览(40)
  • Python自制“超级马里奥”小游戏

    ✅作者简介:华为开发者联盟优质内容创作者、CSDN内容合伙人、GitHub专业技术人员🏆 📃个人主页:北雨·寒冰~ 的CSDN博客 🔥系列专栏:PyGame 💬个人格言:书山有路勤为径,学海无涯苦作舟   前言 看效果 1.基础设置(tools部分) 2.设置背景音乐以及场景中的文字(setup部

    2024年01月25日
    浏览(45)
  • 五子棋小游戏 java版(代码+详细注释)

    游戏展示         这周闲来无事,再来写个五子棋小游戏。基本功能都实现了,包括人人对战、人机对战。界面布局和功能都写的还行,没做到很优秀,但也不算差。如有需要,做个java初学者的课程设计或者自己写着玩玩也都是不错的(非常简单,小白照着就能写出来)。

    2024年02月07日
    浏览(47)
  • python实现超级玛丽游戏

    1、需求分析 具备功能 播放与停止背景音乐 随机生成管道与导弹障碍 显示积分 跳跃躲避障碍 碰撞障碍 2、游戏功能结构 玛丽冒险的功能结构主要分为三类,分别为音效、主窗体以及随机出现的障碍物。如下图 3、游戏业务流程 根据该游戏的需求分析以及功能结构 4、游戏预

    2024年02月03日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包