超级马里奥
窗体类
package ui;
import javax.swing.JFrame;
//窗体类
public class GameFrame extends JFrame{
/**
* 构造方法:
* 根据提供的素材,去制作游戏窗体
*/
public GameFrame() {
//设置标题
setTitle("超级玛丽");
//设置尺寸(大小)
setSize(1920,600);
//设置位置居中显示
setLocationRelativeTo(null);
//禁止改变界面大小
setResizable(false);
//设置默认的关闭选项
//关闭窗体的时候退出程序
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
/**
*
*/
public static void main(String[] args) {
//使用模具 (构造方法)创建游戏面板
GameFrame frame = new GameFrame();
//使用模具 (构造方法)创建游戏面板
GamePanel panel = new GamePanel();
//将面板加入到窗体中
frame.add(panel);
//让窗体显示出来
frame.setVisible(true);
//让面板获取到焦点(一定要加,否则键盘监听器,使用不了)
panel.requestFocus();
}
}
package ui;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
/**
* 游戏的界面(面板)
* @author Administrator
*JPanel 面板的类
*/
public class GamePanel extends JPanel{
//定义背景图
BufferedImage bg = ImageUtil.getImg("/img/bac.png");
//使用玛丽奥的模具(构造方法),制作出马里奥
Mario mario = new Mario();
//定义集合,用来存放游戏中所有的蘑菇
List<Mushroom>ms =new ArrayList<Mushroom>();
int index = 0;//计算器,记录方法执行的次数
/**
* 出现蘑菇的方法
*/
protected void mushroomEnter() {
//美执行一次计算器增加
index ++;
if(index%200==0) {
//创建一个蘑菇出来
Mushroom m= new Mushroom();
//将蘑菇添加到集合中
ms.add(m);
}
}
/**
* 构造方法:模具
*/
public GamePanel() {
new MusicThread("/img/imgw/mario.wav");
//开始音乐播放
//mp.start();
//创建启动线程,让程序一直出现蘑菇
new Thread() {
public void run() {
while(true) {
//蘑菇入场
mushroomEnter();
//让蘑菇移动
for(int i=0;i<ms.size();i++) {
//获取一个蘑菇
Mushroom m = ms.get(i);
//如果蘑菇没有死亡
if(!m.isDie) {
//向左移动
m.x -= 5;
}
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
//创建并启动一个线程,控制马里奥垂直上抛运动
new Thread() {
public void run() {
while(true) {
mario.step();
//检查马里奥是否踩到了蘑菇
caimogu();
//Thread.sleep(毫秒数),让线程休眠指定的毫秒数
try {
//刷新界面
repaint();
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
//设置背景
setBackground(Color.black );
//添加键盘监听器(用键盘控制马里奥的活动)(固定格式)
//1.创建键盘适配器
KeyAdapter adapter = new KeyAdapter() {
//2.确定要监听的事件(编写对应的方法)
//当按下键盘的按键时,会执行的方法
//keyEvent e 事件记事本(会记录对键盘所有的操作)
@Override
public void keyPressed(KeyEvent e) {
//获取键盘上对应的数字
int code = e.getKeyCode();
//如果按的是A键
if(code==KeyEvent.VK_A) {
mario.dir = App.DIR_LEFT;
//让马里奥向左移动
mario.x -= mario.mvSpeed;
//改变马里奥显示的图片
mario.changeImg();
}
//如果按的是D键
if(code==KeyEvent.VK_D) {
mario.dir = App.DIR_RIGHT;
//让马里奥向左移动
mario.x += mario.mvSpeed;
//改变马里奥显示的图片
mario.changeImg();
}
//如果按的是空格键
if(code==KeyEvent.VK_SPACE) {
//重新设置马里奥上抛运动的初始速度
mario.jump();
}
//刷新界面,让马里奥显示到新的位置上
repaint();
}
};
//3.将适配器加入到监听器中
addKeyListener(adapter);
}
/**
* 检查马里奥采蘑菇的方法
*/
protected void caimogu() {
//所有的蘑菇有可能被马里奥踩到
for(int i=0;i<ms.size();i++) {
//获取一个蘑菇
Mushroom m = ms.get(i);
if(m.caiBy(mario)) {
//让马里奥挑一下
mario.jump();
//让蘑菇死亡
m.goDie();
//JAVA计时器
Timer timer = new Timer();
timer.schedule(new TimerTask(){
@Override
public void run() {
ms.remove(m);
}
},1000);
}
}
}
/**
* 画图专用方法
* 打paint 按键盘的 ALT+? 敲回车
* Graphics g 画笔
*/
@Override
public void paint(Graphics g) {
super.paint(g);
//设置画笔颜色(在画笔之前设置)
//g.setColor(Color.red);
//画背景图
//g.drawImage(图片,横坐标, 纵坐标,null);
g.drawImage(bg, 0, 0,1920, 600, null);
//画马里奥的图片
g.drawImage(mario.img,mario.x, mario.y, mario.w,mario.h,null);
//遍历所有的蘑菇,画蘑菇
for(int i=0;i<ms.size();i++) {
//获取一个蘑菇
Mushroom m = ms.get(i);
//画蘑菇
g.drawImage(m.img, m.x, m.y, m.w, m.h, null);
}
}
}
package ui;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageUtil{
public static BufferedImage getImg(String path) {
try {
BufferedImage img = ImageIO.read(ImageUtil.class.getResource(path));
return img;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}
package ui;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
/**
* 玛丽奥 的类
* @author Administrator
*
*/
public class Mario {
//玛丽奥当前显示的图片
BufferedImage img;
//横坐标
int x;
//纵坐标
int y;
//宽度
int w;
//高度
int h;
//定义一个集合,用来存放向右移动动画数组的图片
List<BufferedImage> imgR = new ArrayList<BufferedImage>();
//定义一个集合,用来存放向左移动动画数组的图片
List<BufferedImage> imgL = new ArrayList<BufferedImage>();
//定义向右跳跃的图片
BufferedImage jumpR = ImageUtil.getImg("/img/marioR5.gif");
//定义向左跳跃的图片
BufferedImage jumpL = ImageUtil.getImg("/img/10.gif");
int mvSpeed = 5;
//马里奥移动的方向
int dir = App.DIR_RIGHT;
//
double g = 8; //重力加速度
double t = 0.25; //移动的时间
double s; //t时间后位移
double speed = 40; //初始速度
int groundY;//马里奥在地面的纵坐标
boolean isJump;//是否处于跳跃状态下的开关
public void step() {
//定义初始速度
double v0 = speed;
//t时间后位移
s = v0*t - 1/2*g*t*t;
//计算t时间后当前速度
double vt = v0-g*t;
speed = vt;
//修改马里奥的纵坐标
y -=(int)s;
//如果马里奥下落到地面位置时
if(y>=groundY) {
//让马里奥停留在地面位置
y = groundY;
if(dir==App.DIR_RIGHT) {
img = imgR.get(0);
}else {
img = imgL.get(0);
}
}
}
/**
* 构造方法:玛丽奥的模具
*/
public Mario() {
for(int i=1;i<=4;i++) {
//加载向右移动的动画图片,并加入到向右的集合中
//imgR.add(ImageUtil.getImg("/img/marioL/"+i+".gif"));
//加载向左移动的动画图片,并加入到向右的集合中
//imgL.add(ImageUtil.getImg("/img/marioR/"+i+".gif"));
}
//确定玛丽奥显示的图片
img = ImageUtil.getImg("/img/marioR1.gif");
//确认玛丽奥的大小(用图片的大小,作为玛丽奥的大小)
w = img.getWidth();
h = img.getHeight();
//确定玛丽奥游戏开始时显示的位置
x = 400;
//确认马里奥在地位置
groundY = y = 600-h-50;
}
//下标: 0 1 2 3
//图片:{ 图1, 图2, 图3, 图4}
//定义下标,用来从集合中选取显示的图片
int index = 0;
public void changeImg() {
//下标增加
index ++;//自加1
if(index==imgR.size()) {
//让下标归0,继续从第一张图片开始显示
index = 0;
}
//如果方向向右
if(dir==App.DIR_RIGHT) {
//自加后,从集合中取出图片,替换马里奥当前显示的图片
img = imgR.get(index);
}else {
//从向左的集合中取出图片
img = imgL.get(index);
}
}
//马里奥跳跃
public void jump() {
isJump = true;//跳跃的开关打开
speed = 40;
if(dir==App.DIR_RIGHT) {
img = jumpR;
}else {
img = jumpL;
}
}
}
package ui;
import java.awt.image.BufferedImage;
//蘑菇类
public class Mushroom {
//蘑菇显示的图片
BufferedImage img;
int x;
int y;
int w;
int h;
//蘑菇死亡图片
BufferedImage deadImg = ImageUtil.getImg("/img/dead.png");
public Mushroom() {
//确定游戏开始时蘑菇显示的图片
img = ImageUtil.getImg("/img/0.png");
//确认蘑菇的大小
w = img.getWidth();
h = img.getHeight();
x = 1920-w;
y = 600-h-50;
}
public boolean caiBy(Mario m) {
boolean hit = x<=m.x+m.w&&x>=m.x-w&&y<=m.y+m.h;
return hit&&m.isJump;
}
boolean isDie;//蘑菇是否死亡开关
/**
* 让蘑菇死亡
*/
public void goDie() {
//修改蘑菇当前显示的图片为死亡图片
img = deadImg;
//判定蘑菇已经死亡
isDie = true;
//重新获取死亡图片的大小
w = img.getWidth();
h = img.getHeight();
//重新设置蘑菇地面的位置
y = 600-h-50;
}
}
package ui;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
//音频类
public class MusicThread extends Thread {
//定义一个成员变量fileName
private String fileName;
//音频格式
private AudioFormat format;
//存放音频文件的内用
private byte[] samples;
public MusicThread(String fileName){
this.fileName = fileName;
reverseMusic();
}
public void reverseMusic(){
try {
AudioInputStream stream =AudioSystem.getAudioInputStream(new File(fileName));
format = stream.getFormat();
samples = getSamples(stream);
}
catch (UnsupportedAudioFileException ex) {
ex.printStackTrace();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
public byte[] getSamples(AudioInputStream audioStream) {
int length = (int)(audioStream.getFrameLength() * format.getFrameSize());
byte[] samples = new byte[length];
DataInputStream is = new DataInputStream(audioStream);
try {
is.readFully(samples);
}catch (IOException ex) {
ex.printStackTrace();
}
return samples;
}
public void play(InputStream source) {
//获得每秒中播放的文件大小
int bufferSize = format.getFrameSize() *
Math.round(format.getSampleRate());//具有此格式的声音每秒播放或录制的样本数
byte[] buffer = new byte[bufferSize];
SourceDataLine line;
try {
DataLine.Info info =
new DataLine.Info(SourceDataLine.class, format);
line = (SourceDataLine)AudioSystem.getLine(info);
line.open(format, bufferSize);
}
catch (LineUnavailableException ex) {
ex.printStackTrace();
return;
}
line.start();
try {
int numBytesRead = 0;
while (numBytesRead != -1) {
numBytesRead =source.read(buffer, 0, buffer.length);
if (numBytesRead != -1) {
line.write(buffer, 0, numBytesRead);
}
}
}
catch (IOException ex) {
ex.printStackTrace();
}
line.drain();
line.close();
}
public void run(){
InputStream stream =new ByteArrayInputStream(samples);
play(stream);
}
}
package ui;
public class App {
/**
* 方向向左
*/
public static int DIR_LEFT =1;
/**
* 方向向右
*/
public static int DIR_RIGHT =2;
}