推箱子游戏带音乐版开发

目的:使用Java开发一个带音乐版推箱子游戏

素材文件夹:

推箱子游戏带音乐版开发_第1张图片

推箱子游戏带音乐版开发_第2张图片

素材分析:pic1是墙,pic2是箱子,pic3是箱子位于目标点上时的状态,pic4是目标点,pic5是向下移动,pic6是向左移动,pic7是向右移动,pic8是向上移动,pic9是空地,pic10是向下移动并位于目标点上,pic11是向左移动并位于目标点上,pic12是向右移动并位于目标点上,pic13是向上移动并位于目标点上;nor.mid是背景音乐文件

素材及完整源码链接:https://pan.baidu.com/s/1Qxb_7-X7RH6cwIhEl5_wmQ  提取码:7s4e

场景分析:

游戏开始时,人物位于指定位置,可以进行上下左右移动操作;

②如果人物移动方向前面是空地,直接移动;

③如果人物移动方向前面有箱子,并且箱子前面是空地或者目标点,人物向前移动并推动箱子向前移动;

④如果人物移动方向前面是箱子,但是箱子前面是墙或者箱子,则人物不移动;

⑤如果人物移动方向前面是墙,人物不移动;

⑥将所有箱子推动到目标点,即当前关通过

 

游戏的地图信息我们采用二维数组来存储,创建地图工厂类MapFactory,存储每关的地图信息:

package 推箱子;

public class MapFactory {//地图数据类
	
	static byte map[][][] = {
		{
			{0,0,1,1,1,0,0,0},
			{0,0,1,4,1,0,0,0},
			{0,0,1,9,1,1,1,1},
			{1,1,1,2,9,2,4,1},
			{1,4,9,2,5,1,1,1},
			{1,1,1,1,2,1,0,0},
			{0,0,0,1,4,1,0,0},
			{0,0,0,1,1,1,0,0}
		},
		{
			{1,1,1,1,1,0,0,0,0},
			{1,9,9,5,1,0,0,0,0},
			{1,9,2,2,1,0,1,1,1},
			{1,9,2,9,1,0,1,4,1},
			{1,1,1,9,1,1,1,4,1},
			{0,1,1,9,9,9,9,4,1},
			{0,1,9,9,9,1,9,9,1},
			{0,1,9,9,9,1,1,1,1},
			{0,1,1,1,1,1,0,0,0}
		},
		{
			{1,1,1,1,1,0,0,0,0},
			{1,9,9,9,1,1,0,0,0},
			{1,9,2,9,9,1,0,0,0},
			{1,1,9,2,9,1,1,1,1},
			{0,1,1,1,5,4,9,9,1},
			{0,0,1,9,9,4,1,9,1},
			{0,0,1,9,9,9,9,9,1},
			{0,0,1,1,1,1,1,1,1}			
		},
		{
			{0,0,1,1,1,1},
			{0,1,1,9,9,1},
			{1,1,9,2,9,1},
			{1,4,2,9,5,1},
			{1,2,4,9,1,1},
			{1,4,9,1,1,0},
			{1,1,1,1,0,0}
		},
		
		{
			{1,1,1,1,1,1},
			{1,9,5,9,9,1},
			{1,9,2,9,9,1},
			{1,2,9,1,1,1},
			{1,4,9,4,1,0},
			{1,1,1,1,1,0}
		},
		{
			{0,0,0,1,1,1,1,0,0},
			{0,0,1,1,9,9,1,1,0},
			{1,1,1,9,5,2,4,1,1},
			{1,9,9,9,9,2,4,9,1},
			{1,9,9,9,1,2,4,9,1},
			{1,1,1,1,1,9,1,9,1},
			{0,0,0,0,1,9,9,9,1},
			{0,0,0,0,1,1,1,1,1}
		},
		
		
		{
			{0,0,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0},//19行
			{0,0,0,0,1,9,9,9,1,0,0,0,0,0,0,0,0,0,0},
			{0,0,0,0,1,2,9,9,1,0,0,0,0,0,0,0,0,0,0},
			{0,0,1,1,1,9,9,2,1,1,0,0,0,0,0,0,0,0,0},
			{0,0,1,9,9,2,9,2,9,1,0,0,0,0,0,0,0,0,0},
			{1,1,1,9,1,9,1,1,9,1,0,0,0,1,1,1,1,1,1},
			{1,9,9,9,1,9,1,1,9,1,1,1,1,1,9,9,4,4,1},
			{1,9,2,9,9,2,9,9,9,9,9,9,9,9,9,9,4,4,1},
			{1,1,1,1,1,9,1,1,1,9,1,5,1,1,9,9,4,4,1},
			{0,0,0,0,1,9,9,9,9,9,1,1,1,1,1,1,1,1,1},
			{0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0}
		},
		{
			{1,1,1,1,1,1,1,1,1,1,1,1,0,0},//14行
			{1,4,4,9,9,1,9,9,9,9,9,1,1,1},
			{1,4,4,9,9,1,9,2,9,9,2,9,9,1},
			{1,4,4,9,9,1,2,1,1,1,1,9,9,1},
			{1,4,4,9,9,9,9,5,9,1,1,9,9,1},
			{1,4,4,9,9,1,9,1,9,9,2,9,1,1},
			{1,1,1,1,1,1,9,1,1,2,9,2,9,1},
			{0,0,1,9,2,9,9,2,9,2,9,2,9,1},
			{0,0,1,9,9,9,9,1,9,9,9,9,9,1},
			{0,0,1,1,1,1,1,1,1,1,1,1,1,1}
		},
		{
			{0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0},//17行
			{0,0,0,0,0,0,0,0,1,9,9,9,9,9,5,1,0},
			{0,0,0,0,0,0,0,0,1,9,2,1,2,9,1,1,0},
			{0,0,0,0,0,0,0,0,1,9,2,9,9,2,1,0,0},
			{0,0,0,0,0,0,0,0,1,1,2,9,2,9,1,0,0},
			{1,1,1,1,1,1,1,1,1,9,2,9,1,9,1,1,1},
			{1,4,4,4,4,9,9,1,1,9,2,9,9,2,9,9,1},
			{1,1,4,4,4,9,9,9,9,2,9,9,2,9,9,9,1},
			{1,4,4,4,4,9,9,1,1,1,1,1,1,1,1,1,1},
			{1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0}	
		},
		{
			{0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0},//19行
			{0,0,0,0,0,1,1,1,1,0,1,9,9,1,0,0,0,0,0},
			{0,0,0,1,1,1,9,5,1,1,1,2,9,1,0,0,0,0,0},
			{0,0,1,1,9,9,9,9,9,9,2,9,9,1,0,0,0,0,0},
			{0,1,1,9,9,2,9,2,2,1,1,9,1,1,0,0,0,0,0},
			{0,1,9,9,1,2,1,1,9,9,9,9,9,1,0,0,0,0,0},
			{0,1,9,1,9,2,9,2,2,9,1,9,1,1,1,0,0,0,0},
			{0,1,9,9,9,2,9,1,9,9,1,9,2,9,1,1,1,1,1},
			{1,1,1,1,9,9,9,9,1,9,9,2,2,9,1,9,9,9,1},
			{1,1,1,1,9,1,1,9,2,9,9,9,9,9,9,9,9,9,1},
			{1,4,9,9,9,9,1,1,1,9,9,1,1,1,1,1,1,1,1},
			{1,4,4,9,4,4,1,0,1,1,1,1,0,0,0,0,0,0,0},
			{1,4,4,4,1,4,1,0,0,0,0,0,0,0,0,0,0,0,0},
			{1,4,4,4,4,4,1,0,0,0,0,0,0,0,0,0,0,0,0},
			{1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}
			
		}
		
	};
	static int count = map.length;
	
	
	public static byte[][] getMap(int grade){
		byte[][] temp;
		if(grade>=0&&grade

 

数组其中的信息解读:0表示墙外的空余区域,1表示墙,2表示箱子,3表示箱子位于目标点上,4表示目标点,5表示人物向下,6表示人物向左,7表示人物向右,8表示人物向下,9表示空地;

按照关卡参数可以获取到指定关卡地图的拷贝;

接下来创建Map类,存储地图的行列数,以及一些地图的方法:

package 推箱子;

public class Map {
	int manX = 0;
	int manY = 0;
	byte map[][];
	int grade;
	
	public Map(int manX,int manY,byte[][] map){
		this.manX = manX;
		this.manY = manY;
		int row = map.length;
		int column = map[0].length;
		byte temp[][] = new byte[row][column];
		for(int i=0;i

现在要分析下主要的游戏逻辑了,假设玩家点击了向上按键,可能出现的场景如下:

如果人物当前位置上面一格是空地,人物向上移动,否则保持不动。

当人物当前位置上面一格是箱子,判断人物上面第二格是什么

①如果是墙或者箱子,玩家保持不动;

②如果是目标点或者过道,箱子和玩家同时向上移动一格;如果人物上面两格是目标点,箱子状态修改为箱子在目标点上,否则正常显示;如果人物上面一格是目标点,人物状态修改为人物在目标点上,否则正常显示;如果人物当前位置是目标点,移动后,人物原有位置恢复目标点,否则恢复成空地;

代码实现如下:

	private void moveUp(){
		if(map[row-1][column]==WALL)
			return;
		byte tempBox;
		byte tempMan;
		
		if(map[row-1][column]==BOX||map[row-1][column]==BOXONEND){		//如果向上一格是箱子
			if(map[row-2][column]==GRASS||map[row-2][column]==END){     //如果向上第二格是过道或者终点
				Map currentMap = new Map(row,column,map);
				list.add(currentMap);//用于撤回操作
				tempBox = map[row-2][column]==END?BOXONEND:BOX;
				tempMan = map[row-1][column]==BOXONEND?MANUPONEND:MANUP;
				map[row][column] = grassOrEnd(map[row][column]);
				map[row-2][column] = tempBox;
				map[row-1][column] = tempMan;
				row--;
			}
		}else{//如果向上一格是过道或者终点
			Map currentMap = new Map(row,column,map);
			list.add(currentMap);//用于撤回操作
			tempMan = map[row-1][column]==GRASS?MANUP:MANUPONEND;
			map[row][column] = grassOrEnd(map[row][column]);
			map[row-1][column] = tempMan;
			row--;
		}
		
	}

其他的移动事件可以依次类推,话不多说,上GameFrame类代码:

package 推箱子;

import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JOptionPane;

public class GameFrame extends JFrame implements ActionListener ,MouseListener,KeyListener{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int grade = 0;//关卡数
	private int row = 7,column = 7,leftX = 0,leftY = 0;//row,column表示人物坐标;leftX,leftY记载左上角图片位置
	private int mapRow = 0,mapColumn = 0;//地图的行列数
	private int width = 0,height = 0;//屏幕大小
	private boolean acceptKey = true;
	private Image pic[] = null;
	private byte[][] map = null;
	private ArrayList list = new ArrayList();//用于撤回操作
	Sound sound;
	
	final byte WALL = 1,BOX = 2,BOXONEND = 3,END = 4,MANDOWN = 5,
			MANLEFT = 6,MANRIGHT = 7,MANUP = 8,GRASS = 9,MANDOWNONEND = 10,MANLEFTONEND = 11,
			MANRIGHTONEND = 12,MANUPONEND = 13;
	
	public GameFrame(){
		super("推箱子游戏带音乐版");
		setSize(600,600);
		setVisible(true);
		setResizable(false);
		setLocation(300,20);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		Container cont = getContentPane();
		cont.setLayout(null);
		cont.setBackground(Color.black);
		getPic();
		width = this.getWidth();
		height = this.getHeight();
		this.setFocusable(true);
		initMap();
		this.addKeyListener(this);
		this.addMouseListener(this);
		//播放音乐
		sound = new Sound();
		sound.loadSound();
	}
	
	public void initMap(){
		map = getMap(grade);
		list.clear();
		byte[][] temp = map;
		for(int i=0;i0){
				Map priorMap = (Map)list.get(list.size()-1);
				map = priorMap.getMap();
				row = priorMap.getManX();
				column = priorMap.getManY();
				repaint();
				list.remove(list.size()-1);
			}else{
				DisplayToast("不能再撤销");
			}
		}else{
			DisplayToast("此关已完成,不能撤销");
		}
	}
	
	public void priorGrade(){
		grade--;
		acceptKey = true;
		if(grade<0)
			grade = 0;
		initMap();
		clearPaint(this.getGraphics());
		repaint();
	}
	
	public void nextGrade(){
		if(grade>=MapFactory.getCount()-1){
			DisplayToast("恭喜你完成所有关卡");
			acceptKey = false;
		}else{
			grade++;
			initMap();
			clearPaint(this.getGraphics());
			repaint();
			acceptKey = true;
		}
	}
	
	private void clearPaint(Graphics g) {
	 g.clearRect(0, 0, width+leftX, height+leftY);
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		if(e.getButton() == MouseEvent.BUTTON3)
		{
			undo();
		}
	}

	@Override
	public void mousePressed(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
		
	}
	
	
	public static void main(String[] args){
		new GameFrame();
	}
	
}

其中list是用来进行撤回操作的,玩家除了按上下左右键移动外,可以按A上一关,按D下一关;

现在还差音乐类Sound类的实现,代码如下:

package 推箱子;

import javax.sound.midi.*;

import java.io.File;
import java.io.IOException;

public class Sound {

	String path = new String("D:/Music/");
	String file = new String("nor.mid");
	Sequence seq;
	Sequencer midi;
	boolean sign;
	public void loadSound(){
		try {
			seq = MidiSystem.getSequence(new File(path+file));
			midi = MidiSystem.getSequencer();
			midi.open();
			midi.setSequence(seq);
			midi.start();
			midi.setLoopCount(Sequencer.LOOP_CONTINUOUSLY);
			
		} catch (InvalidMidiDataException | IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (MidiUnavailableException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		sign = true;
	}
	
	public Sound(){
		
	}
	

	
	void mystop(){midi.stop();midi.close();sign=false;}
	boolean isplay(){return sign;}
	void setMusic(String e){file=e;}
	
}

至此,推箱子游戏制作已经完成,运行效果如下:

推箱子游戏带音乐版开发_第3张图片

推箱子游戏带音乐版开发_第4张图片

你可能感兴趣的:(游戏开发,Java小游戏开发合集)