1. 程式人生 > >【Java小專案】打飛機

【Java小專案】打飛機


主要功能:

           1.w,a,s,d八個方向移動,j射擊

           2.預設會右有5個敵機,敵機會有一個隨機方向,並一直按著這個方向移動,碰到邊界會發生反彈

           3.每個飛機只能發5個子彈,只有玩家的子彈才能對敵機造成傷害。

           4.用ArrayList存放子彈,repaint的時候遍歷重繪

           5.用ConcurrentHashMap存放飛機,用HaskMap的話,當遍歷的時候如果改變HaskMap的元素的話就會有一個Concurrent異常,而ConcurrentHashMap會自己檢查變化。

遇到的問題:

            plane類:

                             問題:在按鍵觸發時執行,但是飛機的移動不順滑即按住一個方向它會頓一下才繼續向前。

                             解決方法:給飛機類加個Runnable介面,用執行緒來處理飛機移動,給4個方向boolean標誌。

完整程式碼:

package com.ztc.plane;

import javax.swing.*;
import java.awt.*;

/**
 * Created by ztc on 15-11-29.
 */
public class Plane implements Runnable{
    //座標
    double x,y;
    double speed;
    Image img;
    //移動方向,存活狀態
    boolean up,down,left,right,alive;
    //發射子彈數
    int bulletSum;
    String name;

    public void setUp(boolean up) {
        this.up = up;
    }


    public void setDown(boolean down) {
        this.down = down;
    }


    public void setLeft(boolean left) {
        this.left = left;
    }


    public void setRight(boolean right) {
        this.right = right;
    }
    public Plane(){}


    public void setAlive(boolean alive) {
        this.alive = alive;
    }

    public Plane(String path,double x,double y,double speed,String name){
        this.x=x;
        this.y=y;
        this.speed=speed;
        this.alive=true;
        this.name=name;
        img=Util.getImage(path);

    }
    public void draw(Graphics g){
        g.drawImage(img,(int)x,(int)y,null);
    }

    public void move(boolean up,boolean down,boolean left,boolean right){
        if(up&&y-speed>0)
            y-=speed;
        if(down&&y+speed<Constant.GrameHeight-new ImageIcon(img).getIconHeight())
            y+=speed;
        if(left&&x-speed>0)
            x-=speed;
        if(right&&x+speed<Constant.GrameWidht-new ImageIcon(img).getIconWidth())
            x+=speed;
    }
    public Rectangle getRect(){
        return new Rectangle((int)x,(int)y,new ImageIcon(img).getIconWidth(),new ImageIcon(img).getIconHeight());
    }
    public void boom(Graphics g) {
        for (int i = 3; i > 0; i--) {
            g.drawImage(Util.getImage("assets/boom0" + i + ".png"), (int) x, (int) y, null);
        }
    }

    public int getBulletSum() {
        return bulletSum;
    }

    public void setBulletSum(int bulletSum) {
        this.bulletSum = bulletSum;
    }

    public Bullet shot(){
        Bullet bullet=null;
        if(alive&&bulletSum<Constant.BulletSum) {
            bullet = new Bullet("assets/bullet02.png", (int) x - 7 + new ImageIcon(img).getIconWidth() / 2, (int) y-15, Constant.BulletSpeed, 0.5,name);
            new Thread(bullet).start();
            bulletSum++;
        }
        return bullet;
    }

    @Override
    public void run() {
        while(true){
            move(up,down,left,right);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
               Enemy類:

                                   Enemy類繼承Plane類,所以它的移動只要重寫run函式。

                                   隨機角度:double o=new Random().nextDouble()*Math.PI*2;

                               問題:遇到邊界後鏡面反彈;

                                         解決方法:以隨機出來的方向與垂直向下的方向的夾角為要計算的角度,顯然若碰到垂直的邊則o= Math.PI*2-o碰到水平方向則o=Math.PI-o;

完整程式碼:

package com.ztc.plane;

import javax.swing.*;
import java.util.Random;

/**
 * Created by ztc on 15-11-30.下午1:22
 */
public class Enemy extends Plane{
    //軌跡
    String track;
    double o=new Random().nextDouble()*Math.PI*2;
    public Enemy(){}
    public Enemy(String path,double x,double y,double speed,String name,String track){
        super(path,x,y,speed,name);
        this.track=track;
    }
    //隨機方向,遇邊鏡面反射
    public void myTrack(){
        x-=speed*Math.sin(o);
        y-=speed*Math.cos(o);
        if(x<0||x>Constant.GrameWidht-new ImageIcon(img).getIconWidth()){
            o= Math.PI*2-o;
        }
        if(y<0||y>Constant.GrameHeight-new ImageIcon(img).getIconHeight()-100){
            o=Math.PI-o;
        }
    }
    public void run(){
        while(true){
            myTrack();
            if(alive&&bulletSum<Constant.BulletSum) {
                Bullet bullet = new Bullet("assets/bullet01.png", (int) x - 7 + new ImageIcon(img).getIconWidth() / 2, (int) y + new ImageIcon(img).getIconHeight(), Constant.BulletSpeed, 0,name);
                new Thread(bullet).start();
                Util.bullets.add(bullet);
                bulletSum++;
            }
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

                   Bullet類:

                                 問題:剛開始時把移動寫了一個方法在repaint的時候呼叫,速度很怪異

                                 解決:加Runnable藉口,移動寫在run裡

package com.ztc.plane;

import javax.swing.*;
import java.awt.*;
import java.util.Random;

/**
 * Created by ztc on 15-11-29.下午12:35
 */
public class Bullet implements Runnable{
    //座標
    double x=200,y=200;
    double speed;
    Image img;
    //方向(0,1)
    double direct;
    double o=new Random().nextDouble()*Math.PI*2;
    boolean alive;
    String owner;
    public boolean isAlive() {
        return alive;
    }

    public void setAlive(boolean alive) {
        this.alive = alive;
    }

    public Bullet(){
    }
    public Bullet(String path,double x,double y,double speed,double direct,String owner){
        this.x=x;
        this.y=y;
        this.speed=speed;
        this.direct=direct;
        this.alive=true;
        this.owner=owner;
        img=Util.getImage(path);
    }
    public void draw(Graphics g){
        g.drawImage(img,(int)x,(int)y,null);
    }

    public String getOwner() {
        return owner;
    }
    //隨機方向,遇邊鏡面反射
    public void drawRandom(Graphics g){
        g.drawImage(img,(int)x,(int)y,null);
        x-=speed*Math.sin(o);

        y-=speed*Math.cos(o);
        if(x<0||x>Constant.GrameWidht){
            o=Math.PI*2-o;
        }
        if(y<0||y>Constant.GrameHeight){
            o=Math.PI-o;
        }
    }
    public Rectangle getRect(){
        return new Rectangle((int)x,(int)y,new ImageIcon(img).getIconWidth(),new ImageIcon(img).getIconHeight());
    }

    @Override
    public void run() {
        while(true){
            x+=speed*Math.sin(direct*Math.PI*2);
            y+=speed*Math.cos(direct*Math.PI*2);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(y<0||x<0||y>Constant.GrameHeight||x>Constant.GrameWidht) {
                alive=false;
                break;
            }
        }
    }
}