软件工程—黄金矿工

 周二去实验室完善了游戏的详细设计所需的图(附加上传第一版黄金矿工的代码,代码有借鉴)。



package minegame;
import javax.swing.*;

import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
public class GoldMiner extends JFrame{
    Stage stage;
    static boolean tag = true;
//    static final double TIME_STEP = 1.0; //单位事件步长
    static final double PERIOD = 20.0;


    public GoldMiner() throws IOException{
    	setTitle("Gold Miner");
        setSize(800,600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        stage = new Stage();
		stage.setFocusable(true);
		stage.requestFocusInWindow();
        stage.addMouseListener(new MouseAdapter() {
                                   @Override
                                   public void mouseClicked(MouseEvent e) {
                                       super.mouseClicked(e);
                                       int x=e.getX(), y=e.getY();
                                       if(stage.stageState==Stage.StageState.MENU){

                                           if(x>340&&x<490 && y>200 && y<250){
                                               try{
                                                   stage.load(0);
                                                   stage.start();
                                               }catch (IOException e1){
                                                   e1.printStackTrace();
                                               }
                                           }else if(x>340&&x<490&& y>280 && y<330){
                                               //游戏设置
                                               stage.setting();
                                           }else if (x > 340&&x < 490 && y > 360 && y < 410){
                                               stage.openOptions();
                                           }
                                           else if (x > 340 && x < 490 && y > 440 && y < 490){
                                               dispose();
                                           }
                                       }else if(stage.stageState== Stage.StageState.GAME_OVER){
                                           int distance = (x-412)*(x-412)+(y-432)*(y-432);
                                           if (x > 10 && x < 81 && y > 10 && y < 50){
                                               stage.openMenu();
                                           }
                                           if(distance<1024){
                                               try{
                                                   stage.load(0);
                                                   stage.start();
                                                   stage.hook = new Hook(stage.width, 180);
                                               }catch (IOException e1){
                                                   e1.printStackTrace();
                                               }
                                           }

                                       }else if (stage.stageState == Stage.StageState.GAME_SETTING){
                                           int distance1 = (x - 365) * (x - 365) + (y - 315) * (y - 315);
                                           int distance2 = (x - 445) * (x - 445) + (y - 315) * (y - 315);
                                           if (x > 10 && x < 81 && y > 10 && y < 50){
                                               stage.openMenu();
                                           }
                                           if (distance1 <= 625){
                                               Stage.setFlag(true);
                                               tag = true;
                                               stage.openMenu();
                                               System.out.println("123");
                                           }
                                           if (distance2 <= 625){
                                               Stage.setFlag(false);
                                               tag = false;
                                               stage.openMenu();
                                           }
                                       }else if (stage.stageState == Stage.StageState.GAME_OPTIONS){
                                           if(x>340&&x<490&& y>280 && y<330){
                                               stage.keyplain();
                                           }else if (x > 340&&x < 490 && y > 360 && y < 410){
                                               stage.aboutGame();
                                           }else if (x > 10 && x < 81 && y > 10 && y < 50){
                                               stage.openMenu();
                                           }
                                       }else if (stage.stageState == Stage.StageState.GAME_MOVE){
                                           if (x > 10 && x < 81 && y > 10 && y < 50){
                                               stage.openOptions();
                                           }
                                       }else if (stage.stageState == Stage.StageState.GAME_EXPLAIN){
                                           if (x > 10 && x < 81 && y > 10 && y < 50){
                                               stage.openOptions();
                                           }
                                       }

                                   }
                               }
        );


        stage.addKeyListener(new KeyAdapter() {
            @Override
            public void keyPressed(KeyEvent e) {
                super.keyPressed(e);
                switch (e.getKeyCode()) {
                    case KeyEvent.VK_SPACE:
                        stage.hook.launch();
                        break;
                    case KeyEvent.VK_P:
                        stage.pause();
                        break;
                    case KeyEvent.VK_ESCAPE:
                        stage.configure();
                        break;
                }
            }
        });

        stage.stageState = Stage.StageState.MENU;
        add(stage);


        //stage.start();
    }

    public static void main(String[] args) throws IOException{
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
			        GoldMiner goldMiner = new GoldMiner();
			        goldMiner.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
    }

}


package minegame;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.SourceDataLine;



public class Hook {
    private boolean flag = true;
    private double sourceX; //悬挂点
    private double sourceY; //悬挂点
    private double theta=0.0; //角度
    private double d=0.0; //绳长
    final double r = 30.0; //钩子大小
    private double weight=800.0; //钩子本身的重量

    private Mineral mineral;//钩到的物体
    

    HookState state; //钩子的行进状态
    enum HookState{WAIT, FORWARD, BACKWARD}
    
    int hookWaitDirection = 1; //控制钩子晃动的方向

    public Hook(double width, double height){
        sourceX = width/2;
        sourceY = height; //需要根据背景调节到合适的起始高度

        state = HookState.WAIT;
    }

    double getX(){
        return sourceX + d * Math.cos(theta);
    }

    double getY(){
        return sourceY + d * Math.sin(theta);
    }

    double getWeight(){
        return mineral == null ? weight : weight 
        		+ mineral.density * mineral.r * mineral.r;
    }

    /*分别计算拉的速度和放的速度(放的速度偏慢,不能用钩子的重量来算)*/
    /*TODO 计算速度的参数可以调整*/
    double getPullVelocity(){
    	return 40000.0 / getWeight();
    }    
    double getPushVelocity(){
    	return 20.0;
    }
    
    boolean hasMineral() {
    	return mineral != null;
    }

    /*逐个判断是否钩到物体*/
    /*TODO 钩子触发的范围可以调整*/
    boolean hookMineral(Mineral m){
        if(distance(getX(),getY(),m.x,m.y) < (r/2 + m.r)){
            mineral = m;
            state = HookState.BACKWARD;
            return true;
        } else {
        	return false;
        }
    }
    
    /*逐个判断是否触碰炸弹*/
    boolean explodeBomb(Bomb b){
    	if(distance(getX(), getY(), b.x, b.y) < (r/2 + b.r)){
    		state = HookState.BACKWARD;
    		return true;
    	} else {
    		return false;
    	}
    }
    
    /*每次时间循环时更新钩子位置和角度, 速度与钩子重量有关; 判断是否抓到矿物 */
    void refresh(Stage stage){

        switch (state){
            case WAIT:
            	theta += hookWaitDirection * Math.PI / GoldMiner.PERIOD;
            	
            	/*控制钩子的方向,到达边界转向*/
            	/*TODO 钩子晃动的范围可以调整*/
            	if (theta >= Math.PI * 19 / 20) {
            		hookWaitDirection = -1;
            	}
            	else if (theta <= Math.PI / 20) {
            		hookWaitDirection = 1;
            	}
                break;
                
            case FORWARD:
            	d += getPushVelocity();
            	
            	/*判断是否超出边界*/
            	if (getX() < 50 || getX() > 750 || getY() > 550) {
            		state = HookState.BACKWARD;
            		break;
            	}
            	
            	/*判断是否钩到物体*/
                for(int i=0; i<stage.mineralList.size(); i++){
                    Mineral testMineral = stage.mineralList.get(i);
                	if(hookMineral(testMineral)){
                    	testMineral.hooked(stage,i);
                    	break;
                    }
                }
                /*判断是否碰到炸弹*/
                for(int i=0, len = stage.bombList.size(); i<len; ++i) {
                	Bomb testBomb = stage.bombList.get(i);
                	if (explodeBomb(testBomb)) {
                		stage.bombList.remove(i);
                		testBomb.explode(GoldMiner.tag);
                		len = stage.bombList.size();
                		--i;
                	}
                }
                break;
                
            case BACKWARD:
            	d -= getPullVelocity();
            	
            	/*需要判断是超出边界造成的拉回还是钩到东西造成的拉回*/
            	if (mineral != null){
            		/*给钩到的东西加了个位移*/
            		/*TODO 加位移的多少可以调整*/
            		mineral.refresh(getX() + r * Math.cos(theta), 
            				getY() + r * Math.sin(theta));
            	}
            	
            	/*到达后加分并回到等待状态*/
            	/*TODO 判断高分物体和低分物体的界限可以调整*/
            	if (d <= 0){
            		if (mineral != null) {
            			stage.score += mineral.value;
            			
            			/*播放声音*/
            			String soundName; //指定播放声音文件名
            			if (mineral.value < 50) {
            				soundName = "res/sounds/low-value.wav";
            			} else if (mineral.value >= 300) {
            				soundName = "res/sounds/high-value.wav";
            			} else {
            				soundName = "res/sounds/normal-value.wav";
            			}
            			
            			/*在新线程中播放声音*/
                        if (GoldMiner.tag){
                            Thread playSound = new Thread(new SoundPlayer(soundName));
                            playSound.start();
                        }

            			mineral = null;
            		}
            		d = 0;
            		state = HookState.WAIT;
            	}
            	break;
        }
    }

    /*画线, 钩子, 钩到的物体*/
    void paint(Graphics g) throws IOException{
    	switch (state) {
    	case BACKWARD:
    		if (mineral != null){
    			mineral.paint(g);	// 先画钩到的物体,再进入default画钩子和线
    		}    		
    	default:
    		/*画线*/
    		Graphics2D g2= (Graphics2D)g;
    		g2.setStroke(new BasicStroke(2.0f)); // 设置线条粗细
        	g2.drawLine((int)sourceX, (int)(sourceY), (int)getX(), (int)getY());
    		/*画钩子*/
    		BufferedImage hookImage = ImageIO.read(new File("res/images/hook2.png"));
        	BufferedImage rotatedImage = rotateImage(hookImage, theta);
        	g.drawImage(rotatedImage,
        			(int)(getX() - r), (int)(getY() - r), 2*(int)r, 2*(int)r, null);
    	}    	
    }

    void launch(){
        if(state==HookState.WAIT)
            state = HookState.FORWARD;
    }

    private static double distance(double x1, double y1, double x2, double y2){
        return Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
    }
    
    /*旋转图片*/
    public static BufferedImage rotateImage(final BufferedImage bufferedimage,
            final double theta) {
        int w = bufferedimage.getWidth();
        int h = bufferedimage.getHeight();
        int type = bufferedimage.getColorModel().getTransparency();
        BufferedImage img;
        Graphics2D graphics2d;
        (graphics2d = (img = new BufferedImage(w, h, type))
                .createGraphics()).setRenderingHint(
                RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        graphics2d.rotate(theta, w / 2, h / 2);
        graphics2d.drawImage(bufferedimage, 0, 0, null);
        graphics2d.dispose();
        return img;
    }    
}

/*播放声音的类,在独立线程中执行*/
class SoundPlayer implements Runnable {
	public boolean canplay=true;
	private String soundName;
	SoundPlayer(String soundName) {
		this.soundName = soundName;
	}
	
	public void run() {
		final File file = new File(soundName);

        try {
            final AudioInputStream in = 
            		AudioSystem.getAudioInputStream(file);
            
            final int ch = in.getFormat().getChannels();  
            final float rate = in.getFormat().getSampleRate();  
            final AudioFormat outFormat = new AudioFormat(
            		AudioFormat.Encoding.PCM_SIGNED, rate,
            		16, ch, ch * 2, rate, false);
            
            final DataLine.Info info = 
            		new DataLine.Info(SourceDataLine.class, outFormat);
            final SourceDataLine line = 
            		(SourceDataLine) AudioSystem.getLine(info);

            if (line != null) {
                line.open(outFormat);
                line.start();
                canplay=true;
                final byte[] buffer = new byte[65536];  
                for (int n = 0; n != -1&&canplay;
                		n = AudioSystem
                				.getAudioInputStream(outFormat, in)
                				.read(buffer, 0, buffer.length)) {  
                    line.write(buffer, 0, n);
                }
                line.drain();
                line.stop();
            }
            line.close();
            in.close();
            
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }
	}
}
package minegame;

import javax.swing.*;
import javax.swing.plaf.FontUIResource;

import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by lzc on 4/2/16.
 */
public class Stage extends JPanel {
    double width = 800;
    double height = 600;
    static boolean flag = true;

    int order;
    final int totalOrder = 5;

  
    int lifetime;
    int totaltime;
    int requireScore;
    List<Mineral> mineralList = new ArrayList<Mineral>();
    List<Bomb> bombList = new ArrayList<Bomb>();

    enum StageState {MENU, GAME_SETTING,PLAYING, CONFIGURE, PAUSE, GAME_OVER,GAME_OPTIONS,GAME_EXPLAIN,GAME_MOVE}

    StageState stageState;

    int score;
    
    List<ExplodeEffect> explodeEffectList = new ArrayList<ExplodeEffect>();

    Hook hook = new Hook(width, 180);
    Timer timer;
    
   
    SoundPlayer playLastSoundThreadTarget=new SoundPlayer("res/sounds/last-10s-sound.wav");

    /*Updated by Yangan*/
    void load(int order) throws IOException {
    	int minercount=0;
        this.order = order;
        mineralList.clear();
        File filepath=new File("dat/stage"+order+".dat");
        InputStreamReader isr=new InputStreamReader(new FileInputStream(filepath));
        BufferedReader br=new BufferedReader(isr); 
        String linedata=br.readLine();
        StringTokenizer st=new StringTokenizer(linedata,",");
        lifetime=Integer.parseInt(st.nextToken());
        totaltime=lifetime;
        requireScore=Integer.parseInt(st.nextToken());
        minercount=Integer.parseInt(st.nextToken());
        for(int i=0;i<minercount;i++){  
        	linedata=br.readLine();
        	st=new StringTokenizer(linedata,","); 
        	String mineralType=st.nextToken();
        	switch(mineralType){  
        		case "S":
        		{
                	double x=Double.parseDouble(st.nextToken());
                	double y=Double.parseDouble(st.nextToken());
                	double r=Double.parseDouble(st.nextToken());
                	int value=Integer.parseInt(st.nextToken());
        			mineralList.add(new Stone(x,y,r,value));
        			break;
        		}
        		case "G":
        		{
                	double x=Double.parseDouble(st.nextToken());
                	double y=Double.parseDouble(st.nextToken());
                	double r=Double.parseDouble(st.nextToken());
                	int value=Integer.parseInt(st.nextToken());
        			mineralList.add(new Gold(x,y,r,value));
        			break;
        		}
        		case "D":
        		{
                	double x=Double.parseDouble(st.nextToken());
                	double y=Double.parseDouble(st.nextToken());
                	double r=Double.parseDouble(st.nextToken());
                	int value=Integer.parseInt(st.nextToken());
        			mineralList.add(new Diamond(x,y,r,value));
        			break;
        		}
        		case "B":
        		{
                	double x=Double.parseDouble(st.nextToken());
                	double y=Double.parseDouble(st.nextToken());
                	double r=Double.parseDouble(st.nextToken());
        			bombList.add(new Bomb(x,y,r,this));
        			break;
        		}
        		case "M":
        		{
        			double x=Double.parseDouble(st.nextToken());
                	double y=Double.parseDouble(st.nextToken());
                	double r=Double.parseDouble(st.nextToken());
                	int value=Integer.parseInt(st.nextToken());
                	int movingDirection=Integer.parseInt(st.nextToken());
                	double movingSpeed=Double.parseDouble(st.nextToken());
                	boolean withDiamond=st.nextToken().equals("D");
        			mineralList.add(new Mouse(x,y,r,value,
        					movingDirection,movingSpeed, withDiamond));
        			break;
        		}
        	}
        }
        br.close();
        isr.close();
    }


   
    public Stage() throws IOException {
       
        this.stageState=StageState.MENU;
        this.requestFocus();
    }

    void pause() {
        if (stageState == StageState.PLAYING)
            stageState = StageState.PAUSE;
        else if (stageState == StageState.PAUSE) {
            stageState = StageState.PLAYING;
        }
    }

    void configure() {
        if (stageState == StageState.CONFIGURE)
            stageState = StageState.PLAYING;
        else if (stageState == StageState.PLAYING)
            stageState = StageState.CONFIGURE;
    }

    void setting(){
        stageState = StageState.GAME_SETTING;
        repaint();
    }

    void openOptions(){
        stageState = StageState.GAME_OPTIONS;
        repaint();
    }

    void gameOver() {
        score = 0;
        stageState = StageState.GAME_OVER;
    }

   
    void next() throws IOException{
        if(lifetime>0&&lifetime<=100){
            flag = false;
        	playLastSoundThreadTarget.canplay=flag;
        }
        if (score < requireScore) {
            timer.cancel();
            bombList.clear();
            gameOver();
        } else {
            order++;
            if (order < totalOrder) {
            	bombList.clear(); 
            	load(order);
            } else {
            	order = 0;
            	score = 0;
            	bombList.clear(); 
            	load(order);
            }
        }
    }

	void refresh() throws IOException {
        if (stageState != StageState.PLAYING) return;

     
        if ((mineralList.isEmpty() && ! hook.hasMineral())||lifetime <= 0) {
        	next();
        }
        lifetime--;
       
        hook.refresh(this);
        for (Mineral i : mineralList) {
        	
        	if (i instanceof Mouse) {
        		((Mouse)i).runMouse();
        	}
        }

        if (lifetime == 100) {
            if (flag){
                Thread playLastSound = new Thread(playLastSoundThreadTarget);
                playLastSound.start();
            }
        }

        repaint();
    }

    void start() {
        stageState = StageState.PLAYING;
        timer = new Timer();

        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                try {
					refresh();
				} catch (IOException e) {
					e.printStackTrace();
				}
            }
        }, 0, 100);
    }

    void keyplain(){
        stageState = StageState.GAME_MOVE;
        repaint();
    }

    void aboutGame(){
        stageState = StageState.GAME_EXPLAIN;
        repaint();
    }

    void openMenu(){
        stageState = StageState.MENU;
        repaint();
    }

    public static void setFlag(boolean flag) {
        Stage.flag = flag;
    }

    Image scoreboard=Toolkit.getDefaultToolkit().createImage("res/images/scoreboard.png");
    Image gameoverPic=Toolkit.getDefaultToolkit().createImage("res/images/gameover.jpg");
    Image gamebgPic=Toolkit.getDefaultToolkit().createImage("res/images/map_bg_0.png");
    Image timeLineBg=Toolkit.getDefaultToolkit().createImage("res/images/timebg.png");
    Image timeLineGreen=Toolkit.getDefaultToolkit().createImage("res/images/timegood.png");
    Image timeLineRed=Toolkit.getDefaultToolkit().createImage("res/images/timepoor.png");
    Image buttonBg=Toolkit.getDefaultToolkit().createImage("res/images/text-background.png");
    Image timeLineCenter=Toolkit.getDefaultToolkit().createImage("res/images/timecenter.png");
    Image retryBtn=Toolkit.getDefaultToolkit().createImage("res/images/replay.png");
    Image setAudioOpen = Toolkit.getDefaultToolkit().createImage("res/images/vg_mute_off.png");
    Image setAudioClose = Toolkit.getDefaultToolkit().createImage("res/Images/vg_mute_on.png");
    Image openMusic = Toolkit.getDefaultToolkit().createImage("res/images/vg_mute_off.png");
    Image closeMusic = Toolkit.getDefaultToolkit().createImage("res/images/vg_mute_on.png");


    @Override
    public void paint(Graphics g) {
        g.clearRect(0, 0, (int)width, (int)height);
        double leftPercent=1.0;
		switch (stageState) {
            case PLAYING:
            case PAUSE:
            	g.drawImage(gamebgPic,0,0,(int)width,(int)height,this);
            	g.drawImage(scoreboard,30,20,145,80,this);
            	g.setFont(new Font("Tahoma", Font.BOLD, 28));
            	g.setColor(Color.white);
            	g.drawString(""+requireScore,75,50);
            	g.drawString(""+score,75,90);
            	g.drawImage(timeLineBg,15,115,165,15,this);
            	
            	if(totaltime-lifetime>5)
            		leftPercent=(1.0*lifetime)/(1.0*totaltime);
        		g.drawImage(timeLineRed,(int)(20+165*(1.0-leftPercent)),115,180,130,
								(int)((1.0-leftPercent)*timeLineGreen.getWidth(this)),0,(int)timeLineGreen.getWidth(this),(int)timeLineGreen.getHeight(this),this);
            	if((1.0*lifetime)/(1.0*totaltime)>=0.3)
            		g.drawImage(timeLineGreen,(int)(20+165*(1.0-leftPercent)),115,180,130,
            						(int)((1.0-leftPercent)*timeLineGreen.getWidth(this)),0,(int)timeLineGreen.getWidth(this),(int)timeLineGreen.getHeight(this),this);
            	g.setColor(Color.black);
            	try {
                	hook.paint(g);
                } catch (IOException error) {}
                for (Mineral m : mineralList) {
                    m.paint(g);
                }
                for (Bomb b : bombList) {
                	b.paint(g);
                }
                for (int i=0, len = explodeEffectList.size(); i < len; ++i) {
                	if (explodeEffectList.get(i) != null) {
                    	explodeEffectList.get(i).paint(g);
                    	if (explodeEffectList.get(i).isEnd()) {
                        	explodeEffectList.remove(i);
                        	--i;
                        	--len;
                        }
                    }
                }
                g.setColor(Color.red);
                break;
            case MENU:
                g.drawImage(gamebgPic,0,0,(int)width, (int)height, this);
                g.drawImage(buttonBg,330,210,150, 50,this);
                g.drawImage(buttonBg,330,290,150, 50,this);
                g.drawImage(buttonBg,330,370,150,50,this);
                g.setFont(new Font("宋体", 0, 28));
                g.setColor(Color.white);
                g.drawString("开始游戏�",350,242);
                g.drawString("游戏设置",350,322);
                g.drawString("游戏介绍",350,402);
                g.drawImage(buttonBg,330,450,150,50,this);
                g.drawString("退出游戏",350,482);

                break;
            case GAME_SETTING:
                g.drawImage(gamebgPic,0,0,(int)width,(int)height,this);
                g.setColor(Color.white);
                g.drawImage(buttonBg,10,10,71,40,this);
                g.setFont(new Font("宋体",0,24));
                g.drawString("返回",20,40);

                g.drawImage(buttonBg,170,290,150,50,this);
                g.drawImage(openMusic,340,290,50,50,this);
                g.drawImage(closeMusic,420,290,50,50,this);
                g.setFont(new Font("宋体",0,28));
                g.drawString("声音开关",190,322);
                break;
            case CONFIGURE:
                break;
            case GAME_MOVE:
                g.drawImage(gamebgPic,0,0,(int)width,(int)height,this);
                g.setColor(Color.white);
                g.drawImage(buttonBg,10,10,71,40,this);
                g.setFont(new Font("宋体",0,24));
                g.drawString("返回",20,40);
                g.setFont(new Font("宋体",0,14));
                g.drawString("按键说明",100,100);
                g.drawString("空格/SPACE:放钩子",100,150);
                g.drawString("怕,ESC:暂停",100,200);
                break;
            case GAME_EXPLAIN:
                g.drawImage(gamebgPic,0,0,(int)width,(int)height,this);
                g.setColor(Color.white);
                g.drawImage(buttonBg,10,10,71,40,this);
                g.setFont(new Font("宋体",0,24));
                g.drawString("返回",20,40);
                g.setColor(Color.white);
                g.setFont(new Font("宋体",0,14));
                g.drawString("黄金矿工是一款让玩家放松身心的游戏",100,100);
                g.drawString("游戏中玩家扮演一个挖狂的小工人",100,150);
                g.drawString("控制钩子挖矿,在一定时间内获得分数达到标准即可通关",100,200);
                g.drawString("矿物分为以下几种",100,250);
                g.drawString("黄金:加分物,分数多少一般和黄金大小有关",100,300);
                g.drawString("老鼠,加分物",100,350);
                g.drawString("钻石,加分物",100,400);
                g.drawString("石头,加分物",100,450);
                g.drawString("炸弹:障碍物,无分数",100,500);
                break;
            case GAME_OPTIONS:
                g.drawImage(gamebgPic,0,0,(int)width,(int)height,this);
                g.setColor(Color.white);
                g.drawImage(buttonBg,10,10,71,40,this);
                g.setFont(new Font("宋体",0,24));
                g.drawString("返回",20,40);
                g.setFont(new Font("宋体",0,28));
                g.drawImage(buttonBg,330,290,150, 50,this);
                g.drawImage(buttonBg,330,370,150,50,this);
                g.drawString("操作介绍",350,322);
                g.drawString("关于游戏",350,402);
                break;

            case GAME_OVER:
            
            	g.drawImage(gameoverPic,0,0,(int)width,(int)height,this);
                g.setColor(Color.white);
                g.drawImage(buttonBg,10,10,90,40,this);
                g.setFont(new Font("宋体",0,24));
                g.drawString("主菜单",20,40);
                g.drawImage(retryBtn, 380,400, 64, 64, this);

                break;
        }
    }

}




package minegame;

import java.awt.*;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;


class Bomb {
	double x;
	double y;
	double r;
	Stage stage;
	List<Bomb> chainReaction = new ArrayList<Bomb>();
	boolean marked2Explode;

	//炸药
	Bomb(double x, double y, double r, Stage stage) {
		this.x = x;
		this.y = y;
		this.r = r;
		this.stage = stage;
		this.marked2Explode = false;
	}


	//画炸药
	void paint(Graphics g) {
		Image icon = new ImageIcon("res/images/mine_tnt.png").getImage();
		g.drawImage(icon, (int)(x-r), (int)(y-r), 
				(int)(2*r), (int)(2*r), null);
	}

	//爆炸
	void explode(boolean flag) {
		for (int i = 0, len = stage.mineralList.size(); i < len; ++i) {
			if (distance(stage.mineralList.get(i).x, 
					stage.mineralList.get(i).y, x, y) < 5 * r) {
				stage.mineralList.remove(i);
				--len;
				--i;
			}
		}
		
		/*播放声音*/
    	if (flag){
			Thread playSound = new Thread(new SoundPlayer("res/sounds/explosive.wav"));
			playSound.start(); //SoundPlayer定义在Hook.java中
		}


		//移除炸弹
		for (int i=0, len = stage.bombList.size(); i<len; ++i) {
			Bomb testBomb = stage.bombList.get(i);
			if(distance(x,y,testBomb.x, testBomb.y) < (r + testBomb.r)
					&& testBomb.marked2Explode == false) {
				stage.bombList.remove(i);
				len = stage.bombList.size();
				--i;
				testBomb.marked2Explode = true;
				chainReaction.add(testBomb);
				/* 利用一个List来储存要爆的炸弹,目的是避免递归引爆炸弹的时候造成bombList不可预计的变化,
				 * 比如后排元素因为前排的爆炸往前移,而下标i不能准确知道递归引爆后应该从哪里继续检查可爆炸弹,
				 * 从而miss掉一些应该爆掉的炸弹*/
			}
		}
		for (int i=0; i<chainReaction.size(); ++i) {
			chainReaction.get(i).explode(flag);
		}
		chainReaction.clear();
		stage.explodeEffectList.add(new ExplodeEffect(x, y, r));
	}
	private static double distance(double x1, double y1, double x2, double y2){
        return Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
    }
}


class ExplodeEffect {
	double x;
	double y;
	double r;
	int effectCount;
	
	ExplodeEffect(double x, double y, double r) {
		this.x = x;
		this.y = y;
		this.r = 3 * r;
		this.effectCount = 1;
	}
	
	void paint(Graphics g) {
		Image icon = new ImageIcon("res/images/effect_blast_" 
				+ effectCount + ".png").getImage();
		g.drawImage(icon, (int)(x-r), (int)(y-r), (int)(3*r), (int)(3*r), null);
		++this.effectCount;
	}
	
	boolean isEnd() {
		return effectCount == 6; //一共5张图
	}
}

顺序图:


类图:







阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页