1. 程式人生 > >面向對象經典案例坦克大戰

面向對象經典案例坦克大戰

菜單 記錄 沒有 間隔 mes sets font 爆炸效果 private


package Tank;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.*;
import javax.swing.*;

/**
* @author Administrator
*包含主方法, MyPanel面板繪制我的坦克
*2.畫黃色坦克
*lession3.畫四個方向的坦克
*4.坦克動起來+繪制3個敵人坦克
*5.繪制子彈,子彈做成線程類
*6.子彈連發,安排子彈只在畫布中活動
*7.限制子彈連發數在 KeyEvent.VK_J,子彈打中坦克方法 2層for循環
*8.放入爆炸類圖片 myPanel()新建圖片對象,在原材料裏新建爆炸類,在paint()裏畫爆炸效果,圖片是和包同一級目錄
*9.敵人坦克動起來 做成線程類,難點自動調用重繪
*10.敵人坦克圍著屏幕轉,敵人坦克發射子彈 在畫坦克時 畫敵人子彈
*11.敵人坦克不能互相碰撞
*12.制作開始遊戲時的關卡顯示面板
*13.繪制新遊戲菜單 開始我的面板 在原材料類新建Jilu類 定義靜態方法敵人數量減少,然後在擊中雙方方法裏調用
*MyPanel裏有tjsl()畫出來 敵我坦克數量減少 顯示在面板
*14.每次開啟遊戲時,自動獲得上次打死坦克數量 在右上面板顯示
*15.存盤退出 在記錄類新建2個方法 MyPanel()裏調用讀取記錄方法
*16.新建存盤退出方法 新建位置類
*17.Jilu類新建讀盤方法 MyPanel()修改構造方法 增加if else判斷
*18.加上出場聲音
*/
public class Tank1 extends JFrame implements ActionListener{
private MyPanel mp=null;
private GuangkaPanel gkmp=null;
private JMenuBar jmenuBar;
private JMenu cd1;
private JMenuItem cdx1,cdx2,cdx3,cdx4;
public Tank1() {
jmenuBar=new JMenuBar();
cd1=new JMenu("遊戲(G)");
cd1.setMnemonic(‘G‘);
cdx1=new JMenuItem("新遊戲(N)");
cdx2=new JMenuItem("退出遊戲(E)");
cdx3=new JMenuItem("存盤退出(C)");
cdx4=new JMenuItem("繼續遊戲(S)");
cdx1.addActionListener(this);cdx2.addActionListener(this);
cdx3.addActionListener(this);cdx4.addActionListener(this);
cdx1.setActionCommand("newGame");cdx2.setActionCommand("exit");
cdx3.setActionCommand("saveExit");cdx4.setActionCommand("goonGame");
cd1.add(cdx1);cd1.add(cdx2);cd1.add(cdx3);cd1.add(cdx4);
jmenuBar.add(cd1);
this.setJMenuBar(jmenuBar);
this.setIconImage((new ImageIcon("tank.jpg")).getImage());

gkmp=new GuangkaPanel();
Thread t=new Thread(gkmp);
t.start();
this.add(gkmp);

this.setSize(600, 500);
this.setLocation(300, 280);
this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
this.setTitle("坦克大戰");
}
public static void main(String[] args) {
Tank1 t1=new Tank1();
}
@Override
public void actionPerformed(ActionEvent e) {
if(e.getActionCommand().equals("newGame"))//新遊戲事件
{
mp=new MyPanel("newGame");
this.remove(gkmp);
this.add(mp);
this.addKeyListener(mp);
Thread t=new Thread(mp);
t.start();
this.setVisible(true);
}
else if(e.getActionCommand().equals("goonGame"))//繼續遊戲
{
//封裝
mp=new MyPanel("goonGame");
Thread t=new Thread(mp);
t.start();
this.remove(gkmp);
this.add(mp);
this.addKeyListener(mp);
this.setVisible(true);
}
else if(e.getActionCommand().equals("saveExit"))//保存退出
{
Jilu jl=new Jilu();
jl.setDtk(mp.dtk);//設置下敵人坦克的面板
jl.cunpan();
System.exit(0);
}
else if(e.getActionCommand().equals("exit"))//直接退出遊戲
{
Jilu.bcjl();
System.exit(0);
}
}
}
class GuangkaPanel extends JPanel implements Runnable{
int times=0;
public void paint(Graphics g) {
super.paint(g);
g.fillRect(0, 0, 400, 300);
if(times%2==0) {//畫關卡面板,時間出現閃爍的效果
g.setColor(Color.yellow);
Font myFont=new Font("華文行楷",Font.BOLD,38);
g.setFont(myFont);
g.drawString("第1關", 140, 140);
}
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(600);//間隔多少出現閃爍
} catch (Exception e) {e.printStackTrace();}
times++;
this.repaint();
}
}
}
/**
* @author Administrator
*面板繪制坦克
*/
class MyPanel extends JPanel implements KeyListener, Runnable{

MyTank mt=null;
DiTank dt=null;
//敵人坦克多線程 使用vector集合 坦克組 向量
Vector<DiTank> dtk=new Vector<DiTank>();
Vector<Baozha> bzjh=new Vector<Baozha>();
static Vector<Weizhi> wzjh=new Vector<Weizhi>();

int tksl=3;
//爆炸也需要做向量,有3張圖片
Image tp1=null;
Image tp2=null;
Image tp3=null;

public MyPanel(String ss) {
//第一個讀取硬盤數據
Jilu.dqjl();
mt=new MyTank(140,232);
if(ss=="newGame") {
for(int i=0;i<tksl;i++) {
dt=new DiTank((i)*180+5, 0);
dt.setFangxiang(2);
Thread t2=new Thread(dt);
t2.start();//敵人坦克啟動線程
Zidan zd=new Zidan(dt.x+10,dt.y+30,2);
dt.dzd.add(zd);
Thread t3=new Thread(zd);//敵人發射子彈線程
t3.start();
dtk.add(dt);
dt.dtkxl(dtk);//?
}
}else if(ss.equals("goonGame")) {
wzjh=Jilu.dupan();
for(int i=0;i<wzjh.size();i++) {
Weizhi wz=wzjh.get(i);
DiTank dt=new DiTank(wz.x,wz.y);
dt.setFangxiang(wz.fangxiang);
dt.dtkxl(dtk);
Thread t2=new Thread(dt);
t2.start();//敵人坦克啟動線程
Zidan zd=new Zidan(dt.x+10,dt.y+30,2);
dt.dzd.add(zd);
Thread t3=new Thread(zd);//敵人發射子彈線程
t3.start();
dtk.add(dt);
}
}
Shengyin sy=new Shengyin("./tank.wav");
sy.start();
tp1=Toolkit.getDefaultToolkit().getImage(("src/bzxg1.gif"));
tp2=Toolkit.getDefaultToolkit().getImage(("src/bzxg2.gif"));
tp3=Toolkit.getDefaultToolkit().getImage(("src/bzxg3.gif"));

}
//畫敵我坦克數量減少方法
public void tjsl(Graphics g) {
this.drawTank(80, 330, g, 0, 0);
g.setColor(Color.black);
g.drawString(Jilu.getMtsl()+"", 116, 350);
this.drawTank(150, 330, g, 0, 1);
g.setColor(Color.black);
g.drawString(Jilu.getDtsl()+"", 186, 350);

this.drawTank(450, 86, g, 0, 1);
g.setColor(Color.black);
g.drawString(Jilu.getSdtj()+"", 486, 107);
g.setColor(Color.BLACK);
Font f=new Font("華文彩雲",Font.BOLD,20);
g.setFont(f);
g.drawString("你消滅的坦克總數", 410, 40);
}
public void paint(Graphics g) {

super.paint(g);
g.fillRect(0, 0, 400, 300);
this.tjsl(g);
//畫我的坦克
if(mt.shengming) {
this.drawTank(mt.getX(),mt.getY(),g,mt.fangxiang,0);
}
//畫敵人的坦克 3輛
for(int i=0;i<dtk.size();i++) {
DiTank dt=dtk.get(i);
if(dt.shengming) {
this.drawTank(dtk.get(i).getX(),dtk.get(i).getY(),g,dt.fangxiang,1);
for(int j=0;j<dt.dzd.size();j++) {

Zidan dtzd=dt.dzd.get(j);//每次往裏裝一顆子彈
if(dtzd!=null && dtzd.shengming==true) {
g.setColor(Color.white);
g.fill3DRect(dtzd.x, dtzd.y, 3, 3, false);
}
if(dtzd.shengming==false) {//子彈碰墻 後進行刪除
dt.dzd.remove(dtzd);
}
}
}
}
//畫我的坦克子彈
for(int i=0;i<mt.aa.size();i++) {
Zidan zd=mt.aa.get(i);//每次往裏裝一顆子彈
if(mt.zd!=null && mt.zd.shengming==true) {
g.setColor(Color.white);
g.fill3DRect(zd.x, zd.y, 3, 3, false);
}
if(zd.shengming==false) {//子彈碰墻 後進行刪除
mt.aa.remove(zd);
}
}
/* //畫敵人坦克子彈 已經放到畫敵人坦克循環裏了
for(int i=0;i<dt.dzd.size();i++) {
//DiTank dt=dtk.get(i);
Zidan dtzd=dt.dzd.get(i);//每次往裏裝一顆子彈
if(dtzd!=null && dtzd.shengming==true) {
g.setColor(Color.white);
g.fill3DRect(dtzd.x, dtzd.y, 3, 3, false);
}
if(dtzd.shengming==false) {//子彈碰墻 後進行刪除
dt.dzd.remove(dtzd);
}
}*/
//畫爆炸類
for(int i=0;i<bzjh.size();i++) {

Baozha bz=bzjh.get(i);
if(bz.shengcunqi>6) {
g.drawImage(tp1, bz.x, bz.y, 30, 30, this);
}else if(bz.shengcunqi>3) {
g.drawImage(tp2, bz.x, bz.y, 30, 30, this);
}else {
g.drawImage(tp3, bz.x, bz.y, 30, 30, this);
}
bz.suqsd();
if(bz.shengcunqi==0) {
bzjh.remove(bz);
}
}

}
//擊中我方坦克的方法
public void jzwf() {
for(int i=0;i<this.dtk.size();i++) {//將敵人坦克一個個取出來
DiTank dt=dtk.get(i);
for(int j=0;j<dt.dzd.size();j++) {//將敵人子彈一個個取出來,2者進行比較
Zidan zd=dt.dzd.get(j);
if(mt.shengming) {
this.jzdf(zd, mt);
}
}
this.repaint();
}
}
//擊中敵人坦克方法
public void jzdf1() {
for(int i=0;i<mt.aa.size();i++) {//每取出一顆子彈
Zidan zd=mt.aa.get(i);
if(zd.shengming) {
for(int j=0;j<dtk.size();j++) {//每取出一個敵人坦克
DiTank dt=dtk.get(i);
if(dt.shengming) {
if(this.jzdf(zd, dt)) {//b2值為真
Jilu.dtjs();
Jilu.sdsl();
}
}
}
}
this.repaint();
}
}
//子彈擊中敵人坦克方 法 升級為擊中雙方坦克的方法
public boolean jzdf(Zidan zd,Tank dt) {//多態 父類引用指向子類對象
//子彈不分敵我的 這裏
DiTank dt1;
boolean b2=false;
switch(dt.fangxiang) {
case 0:
case 2:
if(zd.x>dt.x && zd.x<dt.x+20 && zd.y>dt.y && zd.y<dt.y+30)
{
Baozha bz=new Baozha(dt.x,dt.y);//需要給爆炸圖傳入x,y坐標值
bzjh.add(bz);
zd.shengming=false;
dt.shengming=false;
b2=true;
/*if(dt instanceof DiTank) {//判斷當前傳入的對象是屬於哪個類的,然後執行操作
Jilu.dtjs();
Jilu.sdsl();
}*/
}
break;
case 1:
case 3:
if(zd.x>dt.x && zd.x<dt.x+30 && zd.y>dt.y && zd.y<dt.y+20)
{
Baozha bz=new Baozha(dt.x,dt.y);
bzjh.add(bz);
zd.shengming=false;
dt.shengming=false;
b2=true;
//if(dt instanceof DiTank) {Jilu.dtjs();Jilu.sdsl();}
}
}
return b2;
}


public void drawTank(int x, int y, Graphics g, int fangxiang, int leixing) {
switch(leixing) {
case 0://我的坦克 黃色
g.setColor(Color.yellow);
break;
case 1://敵人的坦克 綠色
g.setColor(Color.green);
}
switch(fangxiang) {
case 0://上
g.fill3DRect(x, y, 5, 30, false);//左邊的矩形
g.fill3DRect(x+15, y, 5, 30, false);//右邊的矩形
g.fill3DRect(x+5, y+5, 10, 20, false);//中間的矩形
g.fillOval(x+5, y+10, 10, 10);
g.drawLine(x+10, y+15, x+10, y-3);
break;
case 1://左
g.fill3DRect(x, y, 30, 5, false);//左邊的矩形
g.fill3DRect(x, y+15, 30, 5, false);//右邊的矩形
g.fill3DRect(x+5, y+5, 20, 10, false);//中間的矩形
g.fillOval(x+10, y+5, 10, 10);
g.drawLine(x+15, y+10, x-3, y+10);
break;
case 2://下
g.fill3DRect(x, y, 5, 30, false);//左邊的矩形
g.fill3DRect(x+15, y, 5, 30, false);//右邊的矩形
g.fill3DRect(x+5, y+5, 10, 20, false);//中間的矩形
g.fillOval(x+5, y+10, 10, 10);
g.drawLine(x+10, y+15, x+10, y+33);
break;
case 3://右
g.fill3DRect(x, y, 30, 5, false);//左邊的矩形
g.fill3DRect(x, y+15, 30, 5, false);//右邊的矩形
g.fill3DRect(x+5, y+5, 20, 10, false);//中間的矩形
g.fillOval(x+10, y+5, 10, 10);
g.drawLine(x+15, y+10, x+33, y+10);
break;
}
}
@Override
public void keyTyped(KeyEvent e) {}
public void keyReleased(KeyEvent e) {}
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_W) {
this.mt.setFangxiang(0);
mt.xiangshang();
}else if(e.getKeyCode()==KeyEvent.VK_A){
this.mt.setFangxiang(1);
mt.xiangzuo();
}else if(e.getKeyCode()==KeyEvent.VK_S){
this.mt.setFangxiang(2);
mt.xiangxia();
}else if(e.getKeyCode()==KeyEvent.VK_D){
this.mt.setFangxiang(3);
mt.xiangyou();
}
if(e.getKeyCode()==KeyEvent.VK_J) {
if(mt.aa.size()<3) {//限制子彈數為8個
this.mt.fszd();
}
}
this.repaint();
}

@Override
/* public void run() {
while(true) {
try {
Thread.sleep(100);//合理利用資源 隔100ms重繪制
} catch (Exception e) {}
//子彈和坦克在面板碰撞
for(int i=0;i<mt.aa.size();i++) {
//二層循環的目的每發子彈和每量敵人坦克碰撞
Zidan zd=mt.aa.get(i);
if(zd.shengming) {
for(int j=0;j<dtk.size();j++) {
DiTank dt=dtk.get(j);
if(dt.shengming) {
this.jzdf(zd,dt);
}
}
}
this.repaint();
}
// 因為敵方坦克沒有線程來自動調用重繪,
//你可以在Mypanel的run方法判斷子彈和坦克的那個線程this.repaint()再外面一個循環再加一個this.repaint()
this.repaint();
}

}//run()
*/
public void run() {//第10課後直接在MyPanel線程類調用方法
while(true) {
try {
Thread.sleep(100);//合理利用資源 隔100ms重繪制
} catch (Exception e) {}
this.jzdf1();
this.jzwf();
this.repaint();
}
}
}

面向對象經典案例坦克大戰