java 课设-超级玛丽游戏

news2024/11/27 18:40:40

题目:

本程序是针对超级玛丽小游戏的 JAVA 程序,进入游戏后首先用鼠标点击 GUI 窗口,然后开始游 戏,利用方向键来控制的马里奥的移动,同时检测马里奥与场景中的障碍物和敌人的碰撞,并判断马里 奥的可移动性和马里奥的生命。踩死蘑菇敌人与撞击金币砖块可获得积分与金币。记录马里奥获得的分 数与金币个数。当马里奥通过最后一个场景后游戏结束。利用多线程技术,给游戏分别添加背景音乐、 跳跃音乐、死亡音乐、顶金币音乐、游戏胜利音乐。

运行窗口

 

 

 代码解析:

窗体类–MyF rame.java

该类主要用于存放游戏的场景以及其他各类,并且实现 KeyListener 接口,用于从键盘的按键中 读取信息。该类中的一些属性主要包括了用于存放所有场景的 list 集合 allBG,马里奥类 mario,当前 的场景 nowBG 以及其他一些游戏中需要的标记等。而且在该类中,运用双缓存的技术使得游戏的流畅 度更高,解决了游戏中出现的闪屏问题。 将该类的名字定义为 MyF rame,并且要在该类中实现 KeyListener 接口和 Runnable 接口。然 后首先要在该类中定义一个 List 集合,集合的泛型为背景类 BackGround,集合的名字定义为 allBG, 用于存放所有的背景。接着定义一个 M ario 类属性,名字为 mario,这个就是游戏运行时候的所需要 的 mario。接下来还要在类中定义一个 BackGround 属性,nowBG,默认值应当为空,会在构造方法 中赋予该属性初值,这个属性主要是用来存放当前游戏运行时马里奥所处的游戏场景。另外该类中还应 该有一个 T hread 类属性 thread,这个属性主要是为了在游戏运行的时候控制游戏的线程。然后就可以 在类中定义 main() 方法,将该类实现就可以了。 在该类的构造方法中,应当首先绘制窗体类的标题,以及窗体类的大小,并且要对窗体类在初始化 的时候的位置,也就是在屏幕中显示的位置,最好是显示的时候居中,这样的话在游戏运行时会比较美 观一些。考虑到玩家随意改变游戏的窗口大小可能会对游戏的体验造成影响,所以在这里应该设置游戏 的窗体默认不可以被拉伸。

当这些都设置好以后,接下来就应当在构造方法中绘制了,当然最先应当将游戏的场景绘制到窗体 类中,然后在窗体类中还应当绘制马里奥类,这是游戏中必不可少的。当然在绘制场景类的时候因为不 知一个场景,所以可以使用循环,将所有的场景全部绘制。然后在将所需要的所有监视设置好以后就可 以开启该类的线程了, 然后创建一个 Music 类播放背景主题音乐

在这些最基本的东西设置完以后,还需要一个方法来解决游戏中经常会出现的闪屏问题。这个方法 就是双缓存方法,现在类中定义一个 BufferedImage 的图片,然后从该图片中获取到图片的 Graphics graphics,然后利用画笔 graphics 将所要绘制的东西绘制到这个空的图片中,然后在利用窗体类中的 paint 方法中的画笔 graphics 将这个已经绘制好的图片绘制到窗体类中,这样利用空白图片作为程序运 行中的中转,就可以很好的解决游戏运行过程中出现的闪屏问题。

对于玩家对游戏中的马里奥的控制。在该类中实现 KeyListener 接口,这个接口的作用就是使该类 中实现一些方法,以便于达到玩家在游戏进行时可以对游戏中的马里奥进行控制。我们这里拟定对于马 里奥的控制可以使用我们常见的四个方向键,即我们说的上下左右。并且通过控制台打印,可以知道上 对应的是 38,右对应的是 39,左对应的是 37。并且游戏的设定是开始后游戏不会直接运行,而是要使 用鼠标点击以后游戏才会真正开始,所以还要加入鼠标监听

对于按键,那么相对应的就是当抬起按键的时候。因为你向右移动的时候,如果这时候突然停止, 那么很可能马里奥会保持一个运动的状态停下来,那么就必须在玛丽奥停止的时候给他一个指令,让他 的移动图片变为静止。相对于运动的时候是类似的,。

package ClassPackage;

import javazoom.jl.decoder.JavaLayerException;

import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;

// 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);

    public static final int START = 0;
    public static final int RUNNING = 1;
    private int state = START;

    public MyFrame() {
        //设置窗口的大小
        this.setSize(800, 600);
        // 设置窗口居中显示
        this.setLocationRelativeTo(null);
        //设置窗口可见
        this.setVisible(true);
        //设置点击窗口关闭见关闭程序
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //设置窗口大小不可变
        this.setResizable(false);
        //向键盘添加键盘监听器  KeyListener接口
        this.addKeyListener(this);
        //设置窗口名称
        this.setTitle("超级玛丽");
        // 初始化图片
        StaticValue.init();
        //初始化马里奥对象
        mario = new Mario(10, 355);
        //创建全部场景
        for (int i = 1; i <= 3; i++) {
            allBg.add(new BackGround(i, i == 3 ? true : false));
        }
        // 将第一个场景设置为当前场景
        nowBg = allBg.get(0);
        mario.setBackGround(nowBg);
        //调用鼠标点击方法
        action();
        //若游戏未开始 无限 停止线程
        while (state == START) {
            Thread.yield();
        }
        //绘制图像
        repaint();
        thread.start();
        //加入音乐
        try {
            Music m1 = new Music(1);
        } catch (FileNotFoundException | JavaLayerException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void action() {
        //鼠标侦听器
        MouseAdapter m = new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                //鼠标点击时若为游戏未开始状态则开始游戏
                if (state == START) {
                    state = RUNNING;
                }
            }
        };
        this.addMouseListener(m);
        this.addMouseMotionListener(m);
    }

    public 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 o : nowBg.getEnemyList()) {
            graphics.drawImage(o.getShow(), o.getX(), o.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.GRAY);
        graphics.setFont(new Font("楷体", Font.BOLD, 18));
        graphics.drawString("当前分数:" + mario.getScore(), 16, 100);
        graphics.drawString("当前金币:" + mario.getGold(), 16, 123);
        graphics.setColor(c);
        //如果游戏未开始 画封面覆盖游戏画面
        if (state == START) {
            graphics.drawImage(BackGround.getStart(), 0, 0, this);
        }
        // 将图像绘制到窗口中
        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();
        }
    }

    //当键盘松开时
    @Override
    public void keyReleased(KeyEvent e) {
        //向左停止
        if (e.getKeyCode() == 37) {
            mario.leftStop();
        }
        //向右停止
        if (e.getKeyCode() == 39) {
            mario.rightStop();
        }
    }

    @Override
    public void run() {
        System.out.println(this.getName());
        while (true) {
            //调用鼠标点击方法
            action();
            //若游戏未开始 无限 停止线程
            while (state == START) {
                Thread.yield();
            }
            //如果马里奥达到了屏幕的最右  那么切换场景
            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();
            }

        }

    }
}

常量类–StaticV alue.java

用于存放游戏所需要的所有图片文件,在游戏开始的时候将所有图片导入,提高游戏的运行速度。 并且在该类中将所有需要用到的图片进行分类,分为障碍物类,马里奥类,敌人类以及背景图片。当游 戏运行时可以直接调用这些集合中的图片进行遍历,在调用的时候更加方便,而且可以使马里奥或者敌 人在移动的时候产生动态效果。 首先在类中应当几个定义 BufferedImage 类型,属性名字为 jump_L,jump_R,stand_L,stand_R, 列表 run_L 和 run_R,这些属性的作用在于存放所有的马里奥图片,里面包括了马里奥的移动图片, 站立图片以及马里奥跳跃的图片。这样在程序运行的时候就可以从该类中的这个属性里面将所需要的马 里奥图片直接调用出来,并且还可以在马里奥移动时不断遍历里面的图片,这样就可以使马里奥产生移 动的动态效果。接下来要在该类中定义开始图片,结束图片以及背景图片,默认的初始值都为 null。注 意这些所有的属性都是静态的,包括下面要提到的所有的属性,这样做的目的是为了在程序运行时先加 载这些图片。然后应当定义存放食人花的 List 集合 flower,这个集合将食人花的不同形态,张嘴、闭嘴 图片存放进去,这样在运行的时候进行遍历就可以打到动态效果。同理存放蘑菇怪的集合 mogu,以及 存放所有障碍物的集合 obstacle。

package ClassPackage;

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 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 BufferedImage gold1 = 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<>();
    //乌龟
    public static List<BufferedImage> turtle = new ArrayList<>();
    //路径
    public static String path = System.getProperty("user.dir") + "/src/imgs/";
    //未开始界面
    public static BufferedImage start = null;

    //初始化方法
    public static void init() {
        try {
            //加载未开始图片
            start = ImageIO.read(new File(path + "start.jpg"));
            //加载背景图片
            bg = ImageIO.read(new File(path + "bg.png"));
            bg2 = ImageIO.read(new File(path + "bg2.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"));
            //加载马里奥向左站立
            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"));
            //加载金币
            gold1 = ImageIO.read(new File(path + "gold1.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 + "questionmark1.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")));
            // 加载金币
            obstacle.add(ImageIO.read(new File(path + "gold1.png")));
            // 加载无金币砖块
            obstacle.add(ImageIO.read(new File(path + "questionmark2.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();
            }
        }
        //加载食人花敌人
        for (int i = 1; i <= 2; i++) {
            try {
                flower.add(ImageIO.read(new File(path + "flower1." + i + ".png")));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        //加载w乌龟敌人
        for (int i = 1; i <= 6; i++) {
            try {
                turtle.add(ImageIO.read(new File(path + "tortoise" + i + ".png")));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

背景类–BackGround.java

该类表示马里奥及障碍物和敌人所处的场景,并且将障碍物和敌人绘制到场景中。在该类中包括用 于存放敌人和障碍物的 list 集合,在敌人或者马里奥死亡时,将对应图像移出列表,以达到重新绘制图 像效果。 首先背景类中肯定要有一个标记来表示现在是第几个场景,因为不同的背景中所绘制的场景,障碍 物等也不同,所以该类中要有一个 int 类型的场景顺序 sort。并且在游戏的设定中,如果玩家玩到最后 一关的时候马里奥碰到棋子会失去玩家的控制,自己走向城堡。那么这里就要这几一个标记,是否为最 后的棋子与城堡,类型为 boolean 类型。。 接下来就应当定义背景类的构造方法了,通过获取场景的顺序,即场景的 sort,来判断是哪一个场 景,同时将场景绘制好。下面为绘制第一关的图像

package ClassPackage;

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

public class BackGround {
    //显示当前场景的图片
    private BufferedImage bgImage = null;
    //记录当前第几个场景
    private int sort;
    //判断是否为最后一个场景
    private boolean flag;
    //用于显示旗杆
    private BufferedImage gan = null;
    //用于显示城堡
    private BufferedImage tower = null;
    //判断马里奥是否到达旗杆位置
    private boolean isReach = false;
    //判断棋子是否落地
    private boolean isBase = false;
    // 存放金币
    private static BufferedImage start = null;
    //用于存放所有的敌人
    private List<Enemy> enemyList = new ArrayList<>();
    //用于存放我们所有的障碍物
    private List<Obstacle> obstacleList = new ArrayList<>();

    // 空参构造方法
    public BackGround() {
    }

    // 两个参数构造方法
    public BackGround(int sort, boolean flag) {
        this.sort = sort;
        this.flag = flag;
        start = StaticValue.start;
        if (flag) {
            // 最后一个场景
            bgImage = StaticValue.bg2;
        } else {
            bgImage = StaticValue.bg;
        }
        if (sort == 1) {
            //地面
            //type是StaticValue类的障碍物
            //绘制第一关的地面  上地面type=1  下地面type=2
            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));
            }
            //绘制砖块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));
                }
            }
            // 绘制第一关的蘑菇敌人
            enemyList.add(new Enemy(580, 385, true, 1, this));
            //食人花
            enemyList.add(new Enemy(635, 420, true, 2, 328, 428, this));
            //乌龟
            //enemyList.add(new Enemy(570, 390,  3,  this));
        }
        if (sort == 2) {
            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));
                }
            }
            //妨碍砖块
            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) {
            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));
            //蘑菇
            enemyList.add(new Enemy(150, 385, true, 1, this));
        }
    }

    // 顶金币
    public void createMoney(int x, int y, int type) {
        obstacleList.add(new Obstacle(x, y, type, 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 static BufferedImage getStart() {
        return start;
    }


}

马里奥类–M ario.java

用来控制马里奥的行动,并且在该类中加入碰撞检测,判断马里奥是否与障碍物或者敌人发生碰 撞。该类中的属性主要定义了马里奥所在的场景,马里奥的移动和跳跃的速度,以及马里奥在移动过程 中需要显示的图片。另外该类中还定义了玩家的生命值和所获得的分数。并且在 run()方法中还定义 了当马里奥到达最后一关的旗子时,玩家将失去对马里奥的控制,剩下的由程序控制走到城堡,完整全 部游戏。在游戏中,玛丽奥要在玩家的控制下完成移动、跳跃等动作,那么这些动作首先肯定要涉及到 坐标,那么我们在该类中首先要定义两个属性,这两个属性即为马里奥的坐标 x 和 y。并且该类还要实 现 Runnable 接口,在 run() 方法中写马里奥的移动规则。 为了玩家在游戏过程中的良好体验,那么对于马里奥的移动速度和跳跃速度就必须要定义好。所以 该类里面还应当定义马里奥的移动速度和跳跃速度,其本质就是马里奥在移动过程中坐标加减的值。当 然初始值为零,必须等到马里奥构造的时候,再将这些属性赋予相对应的值。在本类中还要定义游戏的 分数以及马里奥的生命数,这些都是必不可少的。 在马里奥这个类中,还要定义马里奥的移动和跳跃方法,以便玩家在按下方向键后调用这些方法, 来达到控制马里奥的移动。。在定义马里奥的跳跃方法的时候,不单单定义一个方法就行,而且还要判 断马里奥的状态。如果马里奥是在地面或者是在障碍物的上方,那么马里奥可以进行跳跃,如果马里奥 处于空中,那么马里奥就不可以继续跳跃. 下面是马里奥向左移动的方法,其他方法同理

然后对当前马里奥所处的场景中的所有障碍物进行遍历,获取到所有障碍物的坐标,通过障碍物的 坐标和马里奥的坐标的之间的关系的判断,来决定马里奥是否与障碍物发生了碰撞,并且通过判断的结 果来对马里奥和障碍物的状态进行相应的变化,若撞击金块则产生金币,原金块就会变成空金块。还有 对碰撞怪物以及怪物和马里奥是存活状态进行判断。部分代码如下,其他功能可查看代码

package ClassPackage;

import javazoom.jl.decoder.JavaLayerException;

import java.awt.image.BufferedImage;
import java.io.FileNotFoundException;

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 index;
    //马里奥的移动速度
    private int xSpeed;
    //马里奥的跳跃速度
    private int ySpeed;
    //表示马里奥的上升的时间
    private int upTime = 0;
    //判断马里奥是否走到了 城堡的门口
    private boolean isOK;
    //用于判断马里奥是否死亡
    private boolean isDeath = false;
    // 积分,金币
    private int score = 0;
    private int gold = 0;

    public int getScore() {
        return score;
    }

    public int getGold() {
        return gold;
    }

    //马里奥死亡方法
    public void death() {
        try {
            new Music(4);
        } catch (FileNotFoundException | JavaLayerException | InterruptedException e) {
            e.printStackTrace();
        }
        isDeath = true;
    }

    public boolean isDeath() {
        return isDeath;
    }

    public boolean isOK() {
        return isOK;
    }

    //马里奥跳跃
    public void jump() {
        // 判断马里奥是否为跳跃状态
        if (status.indexOf("jump") == -1) {
            try {
                new Music(3);
            } catch (FileNotFoundException | JavaLayerException | InterruptedException e) {
                e.printStackTrace();
            }
            //判断马里奥的跳跃方向是否为左
            if (status.indexOf("left") != -1) {
                status = "jump--left";
            } else {
                //不为左  则为右
                status = "jump--right";
            }
            ySpeed = -10;
            upTime = 7;
        }
        //判断马里奥是否碰到了旗子
        if (backGround.isReach()) {
            ySpeed = 0;
        }

    }

    //马里奥下落
    public void fall() {
        //判单马里奥的跳跃方向是否为左
        if (status.indexOf("left") != -1) {
            status = "jump--left";
        } else {
            //不为左  则为   右
            status = "jump--right";
        }
        ySpeed = 10;
    }

    public Mario() {

    }

    public Mario(int x, int y) {
        this.x = x;
        this.y = y;
        //初始马里奥向右站立
        show = StaticValue.stand_R;
        //马里奥当前状态
        this.status = "status--right";
        thread = new Thread(this);
        thread.start();
    }

    //向左移动
    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 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 String getStatus() {
        return status;
    }

    public BackGround getBackGround() {
        return backGround;
    }

    public Thread getThread() {
        return thread;
    }

    @Override
    public void run() {
        while (true) {
            //判断马里奥是否在障碍物上
            boolean onObstacle = false;
            //判断是否可以向右走
            boolean canRight = true;
            //判断是否可以向左走
            boolean canLeft = true;

            //判断是否到达旗杆位置
            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) {
                            backGround.getObstacleList().remove(ob);
                            backGround.createMoney(ob.getX(), ob.getY() - 40, 9); //金币
                            try {
                                new Music(2);
                            } catch (FileNotFoundException | JavaLayerException | InterruptedException e) {
                                e.printStackTrace();
                            }
                            try {
                                Thread.sleep(100);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            score += 50;
                        }
                        upTime = 0;
                    }
                    if (ob.getType() == 9) {
                        backGround.getObstacleList().remove(ob);
                        backGround.createMoney(ob.getX(), ob.getY() + 40, 10);
                        gold += 1;
                    }
                    //判断是否可以往右走
                    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();
                            upTime = 3;
                            ySpeed = -10;
                            score += 100;
                        } 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;
            }

            try {
                //让线程休眠50毫秒
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

障碍物类–Obstacle.java

绘制场景中所需要的障碍物,例如地面、砖块、水管等等。该类中的属性包括了障碍物的坐标,障 碍物所需要显示的图片等。游戏中的场景是由背景中的障碍物绘制而成的,不同的障碍物所在的位置肯 定也不相同,那么对于障碍物而言,就必须要有坐标属性来使绘制的时候将不同的障碍物绘制到不同的 位置,所以必须要有两个 int 属性 x 和 y 来表示障碍物的坐标。同时该类也必须要实现 Runnable 接口, 实现这个接口的作用主要是为了在最有一个场景中控制旗子的运动,当然同时还要为该类加入线程。 最后该类中的 run 方法主要是为了控制最后一个场景中的旗子的移动,并且在旗子移动完毕后要 设置一个标记,并且将该标记表示给马里奥类,这样马里奥就可以开始自主移动了。部分代码如下:

package ClassPackage;

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;
    }

    @Override
    public void run() {
        while (true) {
            if (this.bg.isReach()) {
                if (this.y < 375) {
                    this.y += 5;
                } else {
                    this.bg.setBase(true);
                }

            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

敌人类–Enemy.java

该类中主要设置了两种敌人,一种是蘑菇怪,可以被马里奥踩死,另一种是食人花,不能被踩死。 该类中的属性包括了敌人的坐标,需要显示的图片,以及敌人的移动方向和移动范围等。。 在该类中首先要实现 Runnable 接口,因为在游戏中的敌人是可以移动的,所以一定要通过重写 run() 方法来达到敌人可以移动的效果。当然还要在该类中定义一个 Thread 属性,用于控制线程。在 该类中就要定义两个 int 属性 x 和 y,用于控制敌人的位置以及敌人的移动。 这个类中应当有两个构造方法,对于不同的敌人,所需要的属性都是不同的。对于蘑菇则需要判断 是否移动到窗口边界,以及是否死亡。对于食人花则需要判断是否移动到上下限。

package ClassPackage;

import java.awt.image.BufferedImage;

public class Enemy implements Runnable {
    //存储当前的坐标
    private int x;
    private int y;
    //存储敌人的类型
    private int type;
    //判断敌人运动的方向
    private boolean face_tc = 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_tc, int type, BackGround bg) {
        this.x = x;
        this.y = y;
        this.type = type;
        this.face_tc = face_tc;
        this.bg = bg;
        this.show = StaticValue.mogu.get(0);
        //启动线程实现蘑菇的移动
        thread.start();
    }

    //食人花敌人的构造函数
    public Enemy(int x, int y, boolean face_tc, int type, int max_up, int max_down, BackGround bg) {
        this.x = x;
        this.y = y;
        this.type = type;
        this.face_tc = face_tc;
        this.show = StaticValue.flower.get(0);
        this.bg = bg;
        this.max_up = max_up;
        this.max_down = max_down;
        //启动线程实现食人花的移动
        thread.start();
    }

    //乌龟敌人的构造函数
    public Enemy(int x, int y, int type, BackGround bg) {
        this.x = x;
        this.y = y;
        this.type = type;
        this.show = StaticValue.flower.get(0);
        this.bg = bg;
        //启动线程实现乌龟的移动
        thread.start();
    }

    // 敌人的死亡方法
    public void death() {
        show = StaticValue.mogu.get(2);
        this.bg.getEnemyList().remove(this);
    }

    public int getType() {
        return type;
    }

    public BufferedImage getShow() {
        return show;
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }

    @Override
    public void run() {
        while (true) {
            //判断是否是蘑菇敌人
            if (type == 1) {
                if (face_tc) {
                    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_tc && !canLeft || this.x == 0) {
                face_tc = false;
            } else if ((!face_tc) && (!canRight) || this.x == 764) {
                face_tc = true;
            }
            //判断是否是食人花敌人
            if (type == 2) {
                if (face_tc) {
                    this.y -= 2;
                } else {
                    this.y += 2;
                }
                image_type = image_type == 1 ? 0 : 1;
                //食人花是否到达了极限位置
                if (face_tc && (this.y == max_up)) {
                    face_tc = false;
                }
                if ((!face_tc) && (this.y == max_down)) {
                    face_tc = true;
                }
                show = StaticValue.flower.get(image_type);
            }
            if (type == 3) {
                this.x -= 1;
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                image_type = image_type == 0 ? 1 : 0;
                show = StaticValue.turtle.get(image_type);
            }

            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

音乐类–Music.java

对于音乐类,则通过变量 type 来判断是播放哪种音乐,为了让播放音乐时人物不会卡住,采用单 独一个线程播放音乐,对于不同音乐则创建多个线程实现。然后只需要在其他类中,通过在不同场景中 定义 Music 对象 new Music(type),t 来实现触发该 type 对应的音乐播放。部分代码如下:

package ClassPackage;

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(int type) throws FileNotFoundException, JavaLayerException, InterruptedException {

        if (type == 1) {
            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();
        } else if (type == 2) {
            Player playerGold;
            String str = System.getProperty("user.dir") + "/src/Music/MarioTopGoldCoins.mp3";
            BufferedInputStream name = new BufferedInputStream(new FileInputStream(str));
            playerGold = new Player(name);
            new Thread(() -> {
                //调用播放方法进行播放
                try {
                    playerGold.play();
                } catch (JavaLayerException e) {
                    e.printStackTrace();
                }
            }).start();

        } else if (type == 3) {
            Player playerJump;
            String str = System.getProperty("user.dir") + "/src/Music/jump.mp3";
            BufferedInputStream name = new BufferedInputStream(new FileInputStream(str));
            playerJump = new Player(name);
            new Thread(() -> {
                //调用播放方法进行播放
                try {
                    playerJump.play();
                } catch (JavaLayerException e) {
                    e.printStackTrace();
                }
            }).start();

        } else if (type == 4) {
            Player playerDeath;
            String str = System.getProperty("user.dir") + "/src/Music/death.mp3";
            BufferedInputStream name = new BufferedInputStream(new FileInputStream(str));
            playerDeath = new Player(name);
            new Thread(() -> {
                //调用播放方法进行播放
                try {
                    playerDeath.play();
                } catch (JavaLayerException e) {
                    e.printStackTrace();
                }
            }).start();

        } else if (type == 5) {
            Player playerCity;
            String str = System.getProperty("user.dir") + "/src/Music/AccelerateToTheCastle.mp3";
            BufferedInputStream name = new BufferedInputStream(new FileInputStream(str));
            playerCity = new Player(name);
            new Thread(() -> {
                //调用播放方法进行播放
                try {
                    playerCity.play();
                } catch (JavaLayerException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }


}


 

项目结构:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/85780.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

.net 移动开发 MAUI

.net 移动开发 MAUI新建一个Hello World运行效果修改一下&#xff0c;做个加法运算吧运行效果创建新的内容页修改xaml内容添加逻辑内容主页面添加一个按钮并且增加路由按钮事件添加路由整体感受第一&#xff1a;WPF第二&#xff1a;小程序所有的页面跳转都是借助路由第三&#…

Win11怎么更改时区?

Win11可以自动检测配置用户的时区来显示正确的时间&#xff0c;如果由于一些特殊原因导致系统时区错误&#xff0c;显示时间也错误的话&#xff0c;这时候要怎么调整呢&#xff1f;下面小编就来教教大家更换Windows 11时区的方法。 方法一&#xff1a;在 Windows 11 上更改时区…

新旧电脑数据如何迁移?电脑数据导入到另一台电脑

新旧电脑数据如何迁移&#xff1f;换电脑是一件好事&#xff0c;换更新版本的电脑&#xff0c;还可以体验新功能。您需要找到将数据传输到新电脑的有效方法。电脑数据导入到另一台电脑&#xff0c;接下来的内容将为大家揭晓答案&#xff01; 方法1、使用专业的数据传输迁移数据…

[附源码]计算机毕业设计的玉石交易系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis MavenVue等等组成&#xff0c;B/S模式…

cookie 和 session 的区别

1. 前言 cookie 和 session 的区别是什么&#xff1f;这个问题在面试中问到的频率非常高 cookie 和 session 的共同点: 都是用来记录用户访问浏览器时保存的数据&#xff0c;比如&#xff1a;用户的身份信息等 2. cookie 和 session 的工作原理 cookie 工作原理: 浏览器端第…

【自然语言处理】隐马尔科夫模型【Ⅲ】估计问题

有任何的书写错误、排版错误、概念错误等&#xff0c;希望大家包含指正。 由于字数限制&#xff0c;分成六篇博客。 【自然语言处理】隐马尔可夫模型【Ⅰ】马尔可夫模型 【自然语言处理】隐马尔科夫模型【Ⅱ】隐马尔科夫模型概述 【自然语言处理】隐马尔科夫模型【Ⅲ】估计问题…

Rsyslog+MariaDB搭建Rsyslog日志服务器

rsyslog是一个linux系统日志服务的工具&#xff0c;主要用来监控收集系统从开机运行之后所发生的所有日志&#xff0c;包括内核日志&#xff0c;服务日志&#xff0c;应用日志等等&#xff1b;记录的日志全部都写到/var/log下面&#xff0c;常用的有dmsg&#xff08;内核日志&a…

带你手把手实操一个RPC框架

前言&#xff1a; 这篇文章我们来聊一聊RPC框架&#xff0c;为什么要聊RPC呢 &#xff1f; 首先从个人成长角度&#xff0c;如果一个新时代码农能清楚的了解RPC框架所具备的要素&#xff0c;掌握RPC框架中涉及的服务注册发现、负载均衡、序列化协议、RPC通信协议、Socket通信…

Linux 安装 Redis教程

1.切换到目录/use/local/src cd /use/local/src 2.下载文件 wget https://download.redis.io/releases/redis-6.2.6.tar.gz 3.文件解包 tar xzf redis-6.2.6.tar.gz 4.将解压后的包移动到/usr/local/redis目录下 mv redis-6.2.6 /usr/local/redis 5.切换到/usr/local/r…

Vue3这样子结合hook写弹窗组件更快更高效

为什么会有这个想法 在管理后台开发过程中&#xff0c;涉及到太多的弹窗业务弹窗&#xff0c;其中最多的就是“添加XX数据”&#xff0c;“编辑XX数据”&#xff0c;“查看XX详情数据”等弹窗类型最多。 这些弹窗组件的代码&#xff0c;很多都是相同的&#xff0c;例如组件状…

DBCO-PEG-NHS,二苯并环辛炔(DBCO)PEG-NHS衍生物,分子量MV 3.4K 5K

1、产品描述&#xff1a; 二苯并环辛炔&#xff08;DBCO&#xff09;PEG-NHS衍生物可以在不需要任何金属催化剂的情况下进行化学反应。菌株促进的环辛炔和叠氮化合物的1,3-偶极环加成反应&#xff0c;也称为无铜点击反应&#xff0c;是一种双正交反应&#xff0c;可使两个分子…

【Java版oj】day05统计回文

目录 一、原题再现 二、问题分析 三、完整代码 一、原题再现 统计回文_牛客题霸_牛客网 描述 “回文串”是一个正读和反读都一样的字符串&#xff0c;比如“level”或者“noon”等等就是回文串。花花非常喜欢这种拥有对称美的回文串&#xff0c;生日的时候她得到两个礼物分别…

ADI Blackfin DSP处理器-BF533的开发详解50:RGBtoGary (图像灰度提取处理)(含源码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 功能介绍 代码实现了图像灰度提取处理&#xff0c;代码运行时&#xff0c;会通过文件系统打开工程文件根目下" …/ImageView"路径中的…

OPENGL ES 2.0 知识串讲(1)――OPENGL ES 2.0 概括

前言 电脑是做什么用的? 电脑又被称为计算机,那么最重要的工作就是计算。看过三体的同学都知道, 电脑中有无数纳米级别的计算单元,通过 0 和 1 的转换,完成加减乘除的操作。 是什么使得电脑工作? 驱动,驱使着硬件完成工作。 谁来写驱动? 制造电脑的公司自己来写驱动,因…

#芯片# N25Q128A21BSF40F

数据手册下载链接&#xff1a;N25Q128A21BSF40F 0. 指令集 1.基本介绍 SPI兼容串行总线接口。108 MHz&#xff08;最大&#xff09;时钟频率。推荐工作电压&#xff1a;1.8 V。单电源电压1.7 V至2 V。支持传统SPI协议&#xff0c;Quad I/O或Dual I/O SPI协议。四路/双路I/O指…

bug的生命周期你知道吗?一张图带你看懂它!

目录 1、什么是bug 2、bug的生命周期 3、如何描述一个bug 4、bug的级别 1、什么是bug 软件的bug狭义方面可以理解为是指软件程序的漏洞或缺陷&#xff0c;广义方面除找到程序漏洞之外&#xff0c;还包括测试工程师或用户所发现和提出的软件可改进的细节、或与需求文档存在差…

【全网惟一面向软件测试人员的Python基础教程】- 你知道Python代码是怎样运行的吗?

全网惟一面向软件测试人员的Python基础教程 起点&#xff1a;《python软件测试实战宝典》介绍 第一章 为什么软件测试人员要学习Python 第二章 学Python之前要搞懂的道理 第三章 你知道Python代码是怎样运行的吗&#xff1f; 文章目录全网惟一面向软件测试人员的Python基础教程…

如何写好科研论文:Introduction(2)

导读 本系列[1]将切片介绍如何写好科研论文&#xff0c;包含了&#xff1a;摘要&#xff0c;背景介绍&#xff0c;方法&#xff0c;结果&#xff0c;讨论等。 由于翻译能力有限&#xff0c;强力推荐有需要的伙伴&#xff0c;直接在文末找到参考链接&#xff0c;阅读原文&#x…

外汇天眼:Swissquote获得CySEC许可证、BUX收购Ninety Nine

新的一周开始了&#xff0c;那么在过去的一周里备受大家关注的外汇行业新闻都有哪些呢&#xff1f;天眼君现在带大家回顾&#xff0c;比如Swissquote获得CySEC许可证、BUX收购西班牙新交易商Ninety Nine的零售经纪部门、Saxo Bank以“时机不合适”为理由终止与SPAC IPO合作。具…

12.3、后渗透测试--持久化后门

攻击主机&#xff1a; Kali 192.168.11.106靶机&#xff1a;windows server 2008 r2192.168.11.134零、为何要创建后门 当成功获取目标系统的访问权限后&#xff0c;需要寻找方法来恢复与目标主机的连接&#xff0c;而无需再进入目标系统。如果目标用户破坏了该连接&#xff0c…