冒险岛游戏简介

游戏界面简介

冒险岛游戏开始界面
冒险岛游戏主界面

技术选型

  • 编程语言及技术: java GUI
  • 框架:Frame
  • 多线程控制
  • 双缓冲

项目的目录结构

项目的目录结构

项目中所用到的技巧

  • 根据java的集成特性由继承的方式来基于frame框架定制适合自身的框架
  • 利用map来制作图片工具类,用来进行项目初始化时只加载需要的图片,提高效率。
  • 使用枚举类型的数据来标识项目中实体的方向和行为
  • 利用列表容器来装怪物和子弹
  • 将图片转换为字节流的工具类

tips:画笔使用的时候需要先取出然后清洗再进行重新赋值颜色

public class GameUtil {

/**
* 根据图片路径进行转换且可以设置图片放大倍数
* @param imgpath 图片路径
* @param beishu 放大的倍数
*/
public static Image getImage(String imgpath,double beishu) {
    InputStream imgInput = new GameUtil().getClass().getResourceAsStream(imgpath);
    Image image = null;
    try {
        BufferedImage imgBuffered = ImageIO.read(imgInput);
        int width = (int) (imgBuffered.getWidth()*beishu);
        int height = (int) (imgBuffered.getHeight()*beishu);
        image = imgBuffered.getScaledInstance(width, height, Image.SCALE_DEFAULT);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return image;
}

/**
    * 根据图片路径进行转换
    * @param imgpath 图片路径
    */
public static Image getImage(String imgpath) {
    InputStream imgInput = new GameUtil().getClass().getResourceAsStream(imgpath);
    Image image = null;
    try {
        BufferedImage imgBuffered = ImageIO.read(imgInput);
        int width = imgBuffered.getWidth();
        int height = imgBuffered.getHeight();
        image = imgBuffered.getScaledInstance(width, height, Image.SCALE_DEFAULT);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return image;
}

/**
    * 改变图片的一条边
    * @param imgpath 图片路径
    * @param bian 边的长度
    * @param state (0|1)(不改变宽|不改变长)
    */
public static Image getImage(String imgpath,int bian,int state) {
    InputStream imgInput = new GameUtil().getClass().getResourceAsStream(imgpath);
    Image image = null;
    try {
        BufferedImage imgBuffered = ImageIO.read(imgInput);
        int width = imgBuffered.getWidth();
        int height = imgBuffered.getHeight();
        if(state==0) {
            height = (int) ((double) bian / width * height) ;
            width = bian;
        }else {
            width = (int) ((double) bian / height * width) ;
            height = bian;
        }
        image = imgBuffered.getScaledInstance(width, height, Image.SCALE_DEFAULT);
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return image;
}
}

  • 自定义的frame框架及使用
/**
 * @ClassName FrameUtil
 * @Description: 窗口初始化工具类
 * @Author Xu Feng
 * @Date 2020/3/17
 * @Version V1.0
 **/
public class FrameUtil extends Frame implements KeyListener, MouseListener, MouseMotionListener{

    public void Init(){
        //设置窗口的初始位置
        this.setBounds(400,200,Constant.GAME_WIDTH,Constant.GAME_HEIGHT);
        //设置窗口的标题
        this.setTitle("冒险岛");
        //设置窗口关闭的监听事件
        this.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        //添加键盘监听映射
        this.addKeyListener(this);
        //添加鼠标监听映射
        this.addMouseListener(this);


        //设置可见性
        this.setVisible(true);
        //设置聚焦
        this.setFocusable(true);
        //启动线程
        new MyThread().run();
    }

    // 解决图片闪烁的问题,用双缓冲方法解决闪烁问题
    Image backImg = null;

    // 重写update()方法,在窗口的里层添加一个虚拟的图片
    @Override
    public void update(Graphics g) {
        if (backImg == null) {
            // 如果虚拟图片不存在,创建一个和窗口一样大小的图片
            backImg = createImage(Constant.GAME_WIDTH, Constant.GAME_HEIGHT);
        }
        // 获取到虚拟图片的画笔
        Graphics backg = backImg.getGraphics();
        Color c = backg.getColor();
        backg.setColor(Color.white);
        backg.fillRect(0, 0, Constant.GAME_WIDTH, Constant.GAME_HEIGHT);
        backg.setColor(c);
        // 调用虚拟图片的paint()方法,每50ms刷新一次
        paint(backg);
        g.drawImage(backImg, 0, 0, null);
    }

    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void mouseDragged(MouseEvent e) {

    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }


    //启动线程重画画布
    class MyThread extends Thread {

        @Override
        public void run() {
            for (; ; ) {
                repaint();
                try {
                    Thread.sleep(50);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}
  • 单独进行一个线程来加载音乐

需要的jl播放器jar包的下载

package com.feng.untils;

import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.Player;

import java.io.BufferedInputStream;
import java.io.File;

/**
 * @ClassName MusicUtil
 * @Description: 加载声音
 * @Author Xu Feng
 * @Date 2020/3/20
 * @Version V1.0
 **/
public class MusicUtil extends Thread {

    private Player player;
    private File music;

    private String musicPath;
    private boolean loop;

    public MusicUtil(String musicPath){
        this.musicPath = musicPath;
    }

    public MusicUtil(String musicPath,boolean loop){
        this.musicPath = musicPath;
        this.loop = loop;
    }

    @Override
    public void run() {
        super.run();
        try {
            if (loop){
                while (true){
                    play();
                }
            }else {
                play();
            }
        }catch (JavaLayerException e){
            e.printStackTrace();
        }
    }

    public void play() throws JavaLayerException {
        BufferedInputStream buff = new BufferedInputStream(MusicUtil.class.getClassLoader()
                .getResourceAsStream(musicPath));
        player = new Player(buff);
        player.play();
    }

    public static void main(String[] args) {
        MusicUtil musicUtil = new MusicUtil("music/Bruno Mars - Talking to the Moon (Acoustic Piano).mp3",true);
        musicUtil.start();
    }

}

  • 英雄自由落体的跳跃算法
    //英雄的跳算法

    public static List<Integer> jump(int y){
        double v0 = 30;
        double vt = 0;
        double g = 9.8;
        double t = 0.5;
        double d_h = 0;

        List<Integer> jumps = new ArrayList();

        boolean jump_up = true;


        //竖直上抛运动
        if (jump_up){
            for (;;){
                System.out.println(+y);
                vt = v0 - g * t;
                d_h = v0 * t;
                v0 = vt;
                y -= d_h;
                jumps.add(y);
                System.out.println("竖直上抛:"+y);
                if (vt<=0){
                    v0 = 0;
                    vt = 0;
                    jump_up = false;
                    System.out.println("自由落体最终:"+y);
                    break;
                }
            }
        }
        //自由落体
        if (!jump_up){
            for (;;){
                vt = v0 + g * t;
                d_h = v0 * t;
                v0 = vt;
                y += d_h;
                jumps.add(y);
                if (y>=400){
                    y = 400;
                    v0 = 30;
                    vt = 0;
                    jump_up = true;
                    System.out.println("自由落体最终:"+y);
                    break;
                }
            }
        }
        if (jumps.get(jumps.size()-1)>= y){
            Collections.replaceAll(jumps,jumps.get(jumps.size()-1),y);
        }
      return jumps;
    }

    static class jumpThread extends Thread{

        @Override
        public void run() {
            for (int dy : jump(400)){
                System.out.println(dy);
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

该项目完整代码的传送门


一个好奇的人