【Java】推箱子小游戏(带背景音乐)完整代码
程序员文章站
2024-03-19 17:03:58
...
Java实现推箱子小游戏
文章比较长,请耐心看完。
一、整体框架
该程序由四个类组成,GameFrame类(程序主体)、Map类(地图基础设置)、MapFactory类(地图构图)、Sound类(添加音乐),下面是程序结构图。
注意音乐格式要转MIDI序列(直接改文件后缀名不可行,如果想更换背景音乐,建议下载widi进行格式转换)
二、游戏效果图
游戏画面没有设置的很炫酷,因为绿色比较护眼。
正在看这篇博客的你,让眼睛休息一下吧!
图片音乐素材及游戏源码链接:
https://pan.baidu.com/wap/init?surl=PvUnMYBukB7A_2K-uNhzxw
.
提取码:5k71
言归正传,我们来看游戏代码
代码直接复制粘贴就能运行(素材包放在项目src目录下)
二、推箱子四大类
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{
/**
* 序列化ID,相当于身份认证,
* 主要用于程序的版本控制,保持不同版本的兼容性,
* 在程序版本升级时避免程序报出版本不一致的错误。
*/
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("推箱子游戏带音乐版");
//1.窗体设置
setSize(600,600);//窗体大小
setVisible(true);//窗体可见
setResizable(false);//窗体大小不可被用户改变
setLocation(680,200);//窗体位置
setBackground(Color.green);//窗体背景颜色
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗体结束程序
//2.cont容器设置
Container cont = getContentPane();
/**
* 因为JFrame是一个框架,所以JFrame不能通过add方法直接添加组件,
* 创建一个content pane容器,方便向框架内添加组件
*/
cont.setLayout(null);//清空默认的流式布局管理器
cont.setBackground(Color.green);//容器背景颜色
getPic();//获取图片
width = this.getWidth();
height = this.getHeight();
this.setFocusable(true);//设置组件可以被选中
initMap();
this.addKeyListener(this);
this.addMouseListener(this);
//播放音乐
Sound sound = new Sound();
sound.loadSound();//加载音乐
}
//初始化地图
public void initMap(){
map = getMap(grade);//获取每个地图的关卡数
list.clear();//清除列表
byte[][] temp = map;
//创建地图
for(int i=0;i<temp.length;i++)
{
for(int j=0;j<temp[0].length;j++){
System.out.print(temp[i][j]+" ");
}
System.out.println();
}
getMapSizeAndPosition();
getManPosition();
}
//获取人物当前位置
public void getManPosition(){
for(int i=0;i<map.length;i++){
for(int j=0;j<map[0].length;j++){
if(map[i][j]==MANDOWN||map[i][j]==MANUP||map[i][j]==MANLEFT||map[i][j]==MANRIGHT){
row = i;
column = j;
break;
}
}
}
}
//获取游戏区域大小及显示游戏的左上角位置
public void getMapSizeAndPosition(){
mapRow = map.length;
mapColumn = map[0].length;
leftX = (width - map[0].length * 30)/2;
leftY = (height - map.length * 30)/2;
System.out.println(leftX);
System.out.println(leftY);
System.out.println(mapRow);
System.out.println(mapColumn);
}
//获取图片
public void getPic(){
pic = new Image[14];
for(int i=0;i<=13;i++){
pic[i] = Toolkit.getDefaultToolkit().getImage
("E:\\kkkkk\\\\推箱子\\\\src\\\\img/pic"+i+".png");
}
}
//人走过变草地
public byte grassOrEnd(byte man){
byte result = GRASS;
if(man == MANLEFTONEND || man == MANRIGHTONEND || man == MANUPONEND || man == MANDOWNONEND){
result = END;
}
return result;
}
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--;
}
}
private void moveDown(){
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]==END||map[row+2][column]==GRASS){
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempBox = map[row+2][column] == END?BOXONEND:BOX;
tempMan = map[row+1][column] == BOXONEND?MANDOWNONEND:MANDOWN;
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?MANDOWN:MANDOWNONEND;
map[row][column] = grassOrEnd(map[row][column]);
map[row+1][column] = tempMan;
row++;
}
}
private void moveLeft(){
if(map[row][column-1]==WALL)
return ;
byte tempBox;
byte tempMan;
if(map[row][column-1]==BOX||map[row][column-1]==BOXONEND){
if(map[row][column-2]==END||map[row][column-2]==GRASS){
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempBox = map[row][column-2] == END?BOXONEND:BOX;
tempMan = map[row][column-1] == BOXONEND?MANLEFTONEND:MANLEFT;
map[row][column] = grassOrEnd(map[row][column]);
map[row][column-2] = tempBox;
map[row][column-1] = tempMan;
column--;
}
}else{
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempMan = map[row][column-1]==GRASS?MANLEFT:MANLEFTONEND;
map[row][column] = grassOrEnd(map[row][column]);
map[row][column-1] = tempMan;
column--;
}
}
private void moveRight(){
if(map[row][column+1]==WALL)
return ;
byte tempBox;
byte tempMan;
if(map[row][column+1]==BOX||map[row][column+1]==BOXONEND){
if(map[row][column+2]==END||map[row][column+2]==GRASS){
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempBox = map[row][column+2] == END?BOXONEND:BOX;
tempMan = map[row][column+1] == BOXONEND?MANRIGHTONEND:MANRIGHT;
map[row][column] = grassOrEnd(map[row][column]);
map[row][column+2] = tempBox;
map[row][column+1] = tempMan;
column++;
}
}else{
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempMan = map[row][column+1]==GRASS?MANRIGHT:MANRIGHTONEND;
map[row][column] = grassOrEnd(map[row][column]);
map[row][column+1] = tempMan;
column++;
}
}
//判断游戏是否结束
public boolean isFinished(){
for(int i=0;i<mapRow;i++) {
for(int j=0;j<mapColumn;j++){
// System.out.println("值是"+map[i][j]+",END 的值是"+END+",他们相等吗?:"+(map[i][j]==END));
if(map[i][j]==END||map[i][j]==MANDOWNONEND||map[i][j]==MANUPONEND||map[i][j]==MANLEFTONEND||map[i][j]==MANRIGHTONEND){
return false;
}
}
}
return true;
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){
moveUp();
}
if(e.getKeyCode() == KeyEvent.VK_DOWN){
moveDown();
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
moveLeft();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
moveRight();
}
if(e.getKeyCode() == KeyEvent.VK_A){//上一关
acceptKey = true;
priorGrade();
return ;
}
if(e.getKeyCode() == KeyEvent.VK_D){//下一关
acceptKey = true;
nextGrade();
return ;
}
if(e.getKeyCode() == KeyEvent.VK_B){//撤回
undo();
}
repaint();
if(isFinished()){
//禁用按键
acceptKey = false;
if(grade==10){JOptionPane.showMessageDialog(this, "恭喜通过最后一关");}
else{
String msg = "恭喜你通过第"+(grade+1)+"关!!!\n是否要进入下一关?";
int type = JOptionPane.YES_NO_OPTION;
String title = "过关";
int choice = 0;
choice = JOptionPane.showConfirmDialog(null, msg,title,type);
if(choice==1){
System.exit(0);
}else if(choice == 0){
acceptKey = true;
nextGrade();
}
}
}
}
//画图
public void paint(Graphics g){
//System.out.println("我被调用了");
for(int i=0;i<mapRow;i++) {
for(int j=0;j<mapColumn;j++){
if(map[i][j]!=0){
// System.out.println("这个位置 不是0,它的值是"+map[i][j]);
// g.drawRect(10, 30, getWidth()/2-50, getHeight()/2-50);
g.drawImage(pic[map[i][j]],leftX+j*30,leftY+i*30,30,30,this);
}
}
}
g.setColor(Color.black);
g.setFont(new Font("楷体_2312",Font.BOLD,30));
g.drawString("现在是第", 150, 140);
g.drawString(String.valueOf(grade+1),310,140);
g.drawString("关", 360, 140);
}
public int getManX(){
return row;
}
public int getManY(){
return column;
}
public int getGrade(){
return grade;
}
public byte[][] getMap(int grade){
return MapFactory.getMap(grade);
}
public void DisplayToast(String str){
JOptionPane.showMessageDialog(null, str,"提示",JOptionPane.ERROR_MESSAGE);
}
//过关后不可撤销
public void undo(){
if(acceptKey){
if(list.size()>0){
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){
GameFrame a = new GameFrame();
}
}
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<row;i++){
for(int j=0;j<column;j++){
temp[i][j] = map[i][j];
}
}
this.map = temp;//避免直接引用
}
public Map(int manX,int manY,byte[][] map,int grade){
this(manX,manY,map);
this.grade = grade;
}
//人物X坐标
public int getManX(){
return manX;
}
//人物Y坐标
public int getManY(){
return manY;
}
//地图数组
public byte[][] getMap(){
return map;
}
//关卡
public int getGrade(){
return grade;
}
}
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<count) {
temp = map[grade];
}else {
temp = map[0];
}
int row = temp.length;
int column = temp[0].length;
byte[][] result = new byte[row][column];//备份关卡版本
for(int i=0;i<row;i++){
for(int j=0;j<column;j++){
result[i][j] = temp[i][j];
}
}
return result;
}
public static int getCount(){
return count;
}
}
Sound类
package 推箱子;
import javax.sound.midi.*;
import java.io.File;
import java.io.IOException;
public class Sound {
String path = new String("E:/kkkkk/推箱子/src/img/");
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;
}
}
四、游戏分析
游戏操作
键盘上下左右键控制人物的移动,按A回到上一关,按D直接进入下一关。
数组解读
很多人对这个庞大的数组很好奇,其实呢,它们非常简单,下面我来解读一下。
0(墙外的空余区域);1(墙);2(箱子);3(箱子位于目标点上);
4(目标点);5(人物向下);9(空地);
五、wav格式音乐代码
由于mid格式比较少见,一般的软件无法实现该格式的转换,所以我们使用javax.sound实现简单的音频播放(只支持AU,RA,WAV格式),相比而言比较大众化。可以自己挑选喜欢的音乐作为背景音乐。
更新后代码如下(只修改GameFrame类和Sound类)
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 java.util.concurrent.TimeUnit;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
public class GameFrame extends JFrame implements ActionListener ,MouseListener,KeyListener{
/**
* 序列化ID,相当于身份认证,
* 主要用于程序的版本控制,保持不同版本的兼容性,
* 在程序版本升级时避免程序报出版本不一致的错误。
*/
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("推箱子游戏带音乐版");
//1.窗体设置
setSize(600,600);//窗体大小
setVisible(true);//窗体可见
setResizable(false);//窗体大小不可被用户改变
setLocation(680,200);//窗体位置
setBackground(Color.green);//窗体背景颜色
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//窗体结束程序
//2.cont容器设置
Container cont = getContentPane();
/**
* 因为JFrame是一个框架,所以JFrame不能通过add方法直接添加组件,
* 创建一个content pane容器,方便向框架内添加组件
*/
cont.setLayout(null);//清空默认的流式布局管理器
cont.setBackground(Color.green);//容器背景颜色
getPic();//获取图片
width = this.getWidth();
height = this.getHeight();
this.setFocusable(true);//设置组件可以被选中
initMap();
this.addKeyListener(this);
this.addMouseListener(this);
}
//初始化地图
public void initMap(){
map = getMap(grade);//获取每个地图的关卡数
list.clear();//清除列表
byte[][] temp = map;
//创建地图
for(int i=0;i<temp.length;i++)
{
for(int j=0;j<temp[0].length;j++){
System.out.print(temp[i][j]+" ");
}
System.out.println();
}
getMapSizeAndPosition();
getManPosition();
}
//获取人物当前位置
public void getManPosition(){
for(int i=0;i<map.length;i++){
for(int j=0;j<map[0].length;j++){
if(map[i][j]==MANDOWN||map[i][j]==MANUP||map[i][j]==MANLEFT||map[i][j]==MANRIGHT){
row = i;
column = j;
break;
}
}
}
}
//获取游戏区域大小及显示游戏的左上角位置
public void getMapSizeAndPosition(){
mapRow = map.length;
mapColumn = map[0].length;
leftX = (width - map[0].length * 30)/2;
leftY = (height - map.length * 30)/2;
System.out.println(leftX);
System.out.println(leftY);
System.out.println(mapRow);
System.out.println(mapColumn);
}
//获取图片
public void getPic(){
pic = new Image[14];
for(int i=0;i<=13;i++){
pic[i] = Toolkit.getDefaultToolkit().getImage
("E:\\kkkkk\\\\推箱子\\\\src\\\\img/pic"+i+".png");
}
}
//人走过变草地
public byte grassOrEnd(byte man){
byte result = GRASS;
if(man == MANLEFTONEND || man == MANRIGHTONEND || man == MANUPONEND || man == MANDOWNONEND){
result = END;
}
return result;
}
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--;
}
}
private void moveDown(){
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]==END||map[row+2][column]==GRASS){
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempBox = map[row+2][column] == END?BOXONEND:BOX;
tempMan = map[row+1][column] == BOXONEND?MANDOWNONEND:MANDOWN;
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?MANDOWN:MANDOWNONEND;
map[row][column] = grassOrEnd(map[row][column]);
map[row+1][column] = tempMan;
row++;
}
}
private void moveLeft(){
if(map[row][column-1]==WALL)
return ;
byte tempBox;
byte tempMan;
if(map[row][column-1]==BOX||map[row][column-1]==BOXONEND){
if(map[row][column-2]==END||map[row][column-2]==GRASS){
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempBox = map[row][column-2] == END?BOXONEND:BOX;
tempMan = map[row][column-1] == BOXONEND?MANLEFTONEND:MANLEFT;
map[row][column] = grassOrEnd(map[row][column]);
map[row][column-2] = tempBox;
map[row][column-1] = tempMan;
column--;
}
}else{
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempMan = map[row][column-1]==GRASS?MANLEFT:MANLEFTONEND;
map[row][column] = grassOrEnd(map[row][column]);
map[row][column-1] = tempMan;
column--;
}
}
private void moveRight(){
if(map[row][column+1]==WALL)
return ;
byte tempBox;
byte tempMan;
if(map[row][column+1]==BOX||map[row][column+1]==BOXONEND){
if(map[row][column+2]==END||map[row][column+2]==GRASS){
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempBox = map[row][column+2] == END?BOXONEND:BOX;
tempMan = map[row][column+1] == BOXONEND?MANRIGHTONEND:MANRIGHT;
map[row][column] = grassOrEnd(map[row][column]);
map[row][column+2] = tempBox;
map[row][column+1] = tempMan;
column++;
}
}else{
Map currentMap = new Map(row,column,map);
list.add(currentMap);//用于撤回操作
tempMan = map[row][column+1]==GRASS?MANRIGHT:MANRIGHTONEND;
map[row][column] = grassOrEnd(map[row][column]);
map[row][column+1] = tempMan;
column++;
}
}
//判断游戏是否结束
public boolean isFinished(){
for(int i=0;i<mapRow;i++) {
for(int j=0;j<mapColumn;j++){
// System.out.println("值是"+map[i][j]+",END 的值是"+END+",他们相等吗?:"+(map[i][j]==END));
if(map[i][j]==END||map[i][j]==MANDOWNONEND||map[i][j]==MANUPONEND||map[i][j]==MANLEFTONEND||map[i][j]==MANRIGHTONEND){
return false;
}
}
}
return true;
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@Override
public void keyPressed(KeyEvent e) {
if(e.getKeyCode() == KeyEvent.VK_UP){
moveUp();
}
if(e.getKeyCode() == KeyEvent.VK_DOWN){
moveDown();
}
if(e.getKeyCode() == KeyEvent.VK_LEFT){
moveLeft();
}
if(e.getKeyCode() == KeyEvent.VK_RIGHT){
moveRight();
}
if(e.getKeyCode() == KeyEvent.VK_A){//上一关
acceptKey = true;
priorGrade();
return ;
}
if(e.getKeyCode() == KeyEvent.VK_D){//下一关
acceptKey = true;
nextGrade();
return ;
}
if(e.getKeyCode() == KeyEvent.VK_B){//撤回
undo();
}
repaint();
if(isFinished()){
//禁用按键
acceptKey = false;
if(grade==10){JOptionPane.showMessageDialog(this, "恭喜通过最后一关");}
else{
String msg = "恭喜你通过第"+(grade+1)+"关!!!\n是否要进入下一关?";
int type = JOptionPane.YES_NO_OPTION;
String title = "过关";
int choice = 0;
choice = JOptionPane.showConfirmDialog(null, msg,title,type);
if(choice==1){
System.exit(0);
}else if(choice == 0){
acceptKey = true;
nextGrade();
}
}
}
}
//画图
public void paint(Graphics g){
//System.out.println("我被调用了");
for(int i=0;i<mapRow;i++) {
for(int j=0;j<mapColumn;j++){
if(map[i][j]!=0){
// System.out.println("这个位置 不是0,它的值是"+map[i][j]);
// g.drawRect(10, 30, getWidth()/2-50, getHeight()/2-50);
g.drawImage(pic[map[i][j]],leftX+j*30,leftY+i*30,30,30,this);
}
}
}
g.setColor(Color.black);
g.setFont(new Font("楷体_2312",Font.BOLD,30));
g.drawString("现在是第", 150, 140);
g.drawString(String.valueOf(grade+1),310,140);
g.drawString("关", 360, 140);
}
public int getManX(){
return row;
}
public int getManY(){
return column;
}
public int getGrade(){
return grade;
}
public byte[][] getMap(int grade){
return MapFactory.getMap(grade);
}
public void DisplayToast(String str){
JOptionPane.showMessageDialog(null, str,"提示",JOptionPane.ERROR_MESSAGE);
}
//过关后不可撤销
public void undo(){
if(acceptKey){
if(list.size()>0){
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) throws InterruptedException{
GameFrame a = new GameFrame();
Sound player = new Sound("E:/kkkkk/推箱子/src/img/XiongDi.wav"); //创建音乐播放器
player.start(true);//以开始以循环的形式播放,player(false)为不循环播放
TimeUnit.SECONDS.sleep(5);
player.stop(); //暂停播放音频
TimeUnit.SECONDS.sleep(4);
player.continues(); //继续开始播放音频
}
}
Sound类
package 推箱子;
/**
*
* Description: 简易音频播放器(只支持AU,RA,WAV)
* 在不使用JMF的情况下快速实现音频播放
*
*/
import javax.sound.sampled.*;
import java.io.*;
import java.util.concurrent.TimeUnit;
public class Sound {
private String musicPath; //音频文件
private volatile boolean run = true; //记录音频是否播放
private Thread mainThread; //播放音频的任务线程
private AudioInputStream audioStream;
private AudioFormat audioFormat;
private SourceDataLine sourceDataLine;
public Sound(String musicPath) {
this.musicPath = musicPath;
prefetch();
}
//数据准备
private void prefetch(){
try{
//获取音频输入流
audioStream = AudioSystem.getAudioInputStream(new File(musicPath));
//获取音频的编码对象
audioFormat = audioStream.getFormat();
//包装音频信息
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,
audioFormat,AudioSystem.NOT_SPECIFIED);
//使用包装音频信息后的Info类创建源数据行,充当混频器的源
sourceDataLine = (SourceDataLine)AudioSystem.getLine(dataLineInfo);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
}catch(UnsupportedAudioFileException ex){
ex.printStackTrace();
}catch(LineUnavailableException ex){
ex.printStackTrace();
}catch(IOException ex){
ex.printStackTrace();
}
}
//析构函数:关闭音频读取流和数据行
protected void finalize() throws Throwable{
super.finalize();
sourceDataLine.drain();
sourceDataLine.close();
audioStream.close();
}
//播放音频:通过loop参数设置是否循环播放
private void playMusic(boolean loop)throws InterruptedException {
try{
if(loop){
while(true){
playMusic();
}
}else{
playMusic();
//清空数据行并关闭
sourceDataLine.drain();
sourceDataLine.close();
audioStream.close();
}
}catch(IOException ex){
ex.printStackTrace();
}
}
private void playMusic(){
try{
synchronized(this){
run = true;
}
//通过数据行读取音频数据流,发送到混音器;
//数据流传输过程:AudioInputStream -> SourceDataLine;
audioStream = AudioSystem.getAudioInputStream(new File(musicPath));
int count;
byte tempBuff[] = new byte[1024];
while((count = audioStream.read(tempBuff,0,tempBuff.length)) != -1){
synchronized(this){
while(!run)
wait();
}
sourceDataLine.write(tempBuff,0,count);
}
}catch(UnsupportedAudioFileException ex){
ex.printStackTrace();
}catch(IOException ex){
ex.printStackTrace();
}catch(InterruptedException ex){
ex.printStackTrace();
}
}
//暂停播放音频
private void stopMusic(){
synchronized(this){
run = false;
notifyAll();
}
}
//继续播放音乐
private void continueMusic(){
synchronized(this){
run = true;
notifyAll();
}
}
//外部调用控制方法:生成音频主线程;
public void start(boolean loop){
mainThread = new Thread(new Runnable(){
public void run(){
try {
playMusic(loop);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
mainThread.start();
}
//外部调用控制方法:暂停音频线程
public void stop(){
new Thread(new Runnable(){
public void run(){
stopMusic();
}
}).start();
}
//外部调用控制方法:继续音频线程
public void continues(){
new Thread(new Runnable(){
public void run(){
continueMusic();
}
}).start();
}
}
修改后就可以自己修改喜欢的背景音乐了
上一篇: ORACLE中多条数据合并某个字段
下一篇: 制作自己的图像语义分割数据集