坦克大戰,咋做下一關
//坦克大戰:-換關卡,IO聲音流沒做,還有寫BUG,沒做完 ,本人純外行自學的,不知道怎麼做下一關,請大家指導一下,比一般坦克大戰加了小道具
包1如下:
Tank1
import java.awt.;
import javax.swing.;
import java.awt.event.;
import java.util.;
import java.io.*;
public class Tank1 extends JFrame implements ActionListener{
MyPanel mp=null;
StartPanel gkmp=null;
//Record record=null;
JMenuBar cd=null;//??不熟
JMenu cd1=null;//??不熟
JMenu cd2=null;
JMenuItem cd1xl1=null;//菜單欄1系列的1
JMenuItem cd1xl2=null;//菜單欄1系列的2
JMenuItem cd1xl3=null;//菜單欄1系列的1
JMenuItem cd1xl4=null;//菜單欄1系列的2
JMenuItem cd2xl1=null;//菜單欄2系列的1
JLabel imageJLabel=null;
String newGame=“newGame”;//?
//Image tp1=null;
public static void main(String[] args)
{
Tank1 t1=new Tank1();
}
public Tank1(){
gkmp=new StartPanel();
mp=new MyPanel(newGame);//??
Record record=new Record();//建立一個記錄對象
Thread t=new Thread(gkmp);
t.start();
cd=new JMenuBar();//菜單欄 不熟
cd1=new JMenu("遊戲(G)");//第一個菜單欄的第一個菜單
cd1.setMnemonic('G');//快界鍵
cd2=new JMenu("設定(Z)");
cd2.setMnemonic('Z');
cd1xl1=new JMenuItem("開始新遊戲(N)");//菜單系列 cdxl
cd1xl1.setMnemonic('N');
cd1xl1.addActionListener(this);//加元件監聽
cd1xl1.setActionCommand("newGame");//設定鍵值,和上文同名參數有啥關系沒?
cd1.add(cd1xl1);
cd1xl2=new JMenuItem("繼續遊戲(H)");//菜單系列 cdxl
cd1xl2.setMnemonic('H');
cd1xl2.addActionListener(this);//加元件監聽
cd1xl2.setActionCommand("goonGame");//設定鍵值
cd1.add(cd1xl2);
cd1xl3=new JMenuItem("儲存退出(S)");//菜單系列 cdxl
cd1xl3.setMnemonic('S');
cd1xl3.addActionListener(this);//加元件監聽
cd1xl3.setActionCommand("saveOut");//設定鍵值
cd1.add(cd1xl3);
cd1xl4=new JMenuItem("退出(Q)");
cd1xl4.setMnemonic('Q');
cd1xl4.addActionListener(this);//加元件監聽
cd1xl4.setActionCommand("exit");//設定鍵值
cd1.add(cd1xl4);
cd.add(cd1);//給菜單欄 cd 添加菜單 cd1
cd2xl1=new JMenuItem("速度(F)");//菜單系列 cdxl 沒做好效果?
cd1xl4.setMnemonic('F');
cd1xl4.addActionListener(this);//加元件監聽
cd1xl4.setActionCommand("FSpeed");//設定鍵值
cd2.add(cd2xl1);
cd.add(cd2);
ImageIcon img = new ImageIcon("E:/Tank1/tankebig.PNG");
JLabel imageJLabel = new JLabel(img);
gkmp.add(imageJLabel);
this.add(gkmp);
this.setJMenuBar(cd);
this.setTitle("坦克大戰");
ImageIcon tp1=new ImageIcon("E:/Tank1/tankexiao.PNG");//設定小圖示位址要寫全路徑嗎
this.setIconImage(tp1.getImage());
this.setSize(700,620);
this.setLocation(300,80);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);//可見
this.setResizable(false);//可調
// this.setResizable(true);
}
public void actionPerformed(ActionEvent e){
//boolean flag=true;
if(e.getActionCommand().equals("newGame"))
{
this.remove(gkmp);//取消界面 gkmp
if(mp.flag==false)//因為在主類構造函數開始就建立了mp,是以可以引用flag變量
{
this.remove(mp);
mp=new MyPanel("newGame");
}
this.add(mp);
this.addKeyListener(mp);
Thread t=new Thread(mp);//啟動我的MyPanel模闆對象mp的線程
t.start();//叫醒線程
this.setVisible(true);//因為預設的是不可見,必須寫這個!!
Record.bcjl();//????
}else if(e.getActionCommand().equals("saveOut"))
{
Record record0=new Record();
// record0.setDtk(mp.dtk);
record0.cunpan();///???
System.exit(0);//遊戲退出
}else if(e.getActionCommand().equals(“exit”))
{
Record.bcjl();
System.exit(0);//遊戲退出
}else if(e.getActionCommand().equals(“goonGame”)){
this.remove(gkmp);
if(mp.flag==false)//因為在主類構造函數開始就建立了mp,是以可以引用flag變量
{
this.remove(mp);
mp=new MyPanel(“goonGame”);
}
Thread t=new Thread(mp);
t.start();
this.add(mp);
this.addKeyListener(mp);
this.setVisible(true);
}
}
class StartPanel extends JPanel implements Runnable //開始界面類
{
int time=0;
public void paint(Graphics g){
super.paint(g);
// g.fillRect(0, 0, 600, 500);//設定畫布
g.setColor(Color.black);//設定顔色
Color mycolor1=new Color(250,50,0);//自定義紅色
g.setFont(new Font(“華文琥珀”,Font.BOLD,80));//設定字型//?
g.drawString(“坦克大戰”,190 , 460);//繪字元串
g.setColor(Color.black);//設定顔色
g.setFont(new Font(“黑體”,1,14));//設定字型
g.drawString(“李晉祥”,648 , 552);//繪字元串
if(time%2==0)
{
g.setColor(Color.white);//設定顔色
g.setFont(new Font(“華文行楷”,3,35));//字型:華康楷體, Ravie, OCR A Extended
g.drawString(“準備戰鬥”,270 , 345);//繪字元串
}
}
StartPanel(){
}
public void run(){
while(true){
try{
Thread.sleep(400);
}catch(Exception e){}
time++;
this.repaint();
}
}
}
class MyPanel extends JPanel implements KeyListener,Runnable
{
//Vector mts=new Vector();//建立一個我的坦克集合類可以出無限個坦克
MyTank mt=null;
MyTank mt0=null;
MyTank mt01=null;
MyTank mt02=null;
Vector dtk=new Vector();//建立一個敵坦克集合類
Props props=null;
Vector bzjh=new Vector();//建立一個爆炸類的集合
Vector wzjh=new Vector();//建立一個位置集合類,為啥建立這集合類
int tksl=3;//坦克數量
int a=122;
int b=455;
int n=10;
int myzdNum=4;//?
int propsSort=5;
int time=0;
boolean flag=true;//标記是不是已經建立過MyPanel類
boolean b1=false;
int x=1;//總關卡數?
int rocket=1;//沒用?
int huopao=0;//?
Color mycolor1=new Color(250,50,0);//自定義紅色
Color mycolor2=new Color(0,250,50);//自定義綠色
Color mycolor3=new Color(0,50,250);//自定義蘭色
Color mycolor11=new Color(130,200,0);//自定義土黃
Color mycolor31=new Color(0,100,200);//自定義蘭色
Color mycolor21=new Color(0,250,0);//自定義綠色
JLabel imageJLabel0=null;
JLabel imageJLabel1=null;
ImageIcon img0=null;//?
ImageIcon img1=null;//?
public MyPanel(String ss)
{
ImageIcon img0 = new ImageIcon(“e:/Tank1/background.jpg”);
JLabel imageJLabel0 = new JLabel(img0);
this.add(imageJLabel0);
Record.dqjl();//?
mt=new MyTank(600,280);//new多個可改為多個坦克,循環數組
mt0=new MyTank(550,280);//new多個可改為多個坦克,循環數組
mt01=new MyTank(550,330);//new多個可改為多個坦克,循環數組
mt02=new MyTank(600,330);//new多個可改為多個坦克,循環數組
props=new Props(30,30);//沒有實際意義,為了new對象,必須要有個參數?
if(ss.equals(“newGame”)){
// record=new Record();
for(int i=0;i<tksl;i++){
DiTank dt=new DiTank((i)*a,b);//添加出場敵坦
// dt.dtkxl(dtk);///???是不是敵人坦克血量
dt.setFangxiang(1);//給一個初始值,調drawTank()賦初值要用
Thread t2=new Thread(dt);
t2.start();
Zidan zd=new Zidan(dt.x,dt.y,1);//?這是幹啥加子彈元素嗎?
Thread t3=new Thread(zd);//?
t3.start();
dtk.add(dt);
}
}else if(ss.equals(“goongame”)){//繼續遊戲有問題 感覺讀取存盤資訊有問題
wzjh=Record.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);//?敵坦克血量,好像暫時用不着
// dt.setFangxiang(1);//給一個初始值,調drawTank()賦初值要用
Thread t2=new Thread(dt);
t2.start();
Zidan zd=new Zidan(dt.x,dt.y,1);//?這是幹啥加子彈元素嗎?
Thread t3=new Thread(zd);//?
t3.start();
dtk.add(dt);
}
}
flag=false;//MyPanel類的mp建立過一次就标記為假
// this.repaint();
// Record.next();
// if(Record.next()%2!=0){
// Record.reMtNum();//需要嗎?
// Record.reDtNum();//需要嗎?
// Record.reAddMtNum();
// }
}
public void outNum(Graphics g)//畫出統計資料的方法也即使顯示數量的函數
{
g.setColor(Color.cyan);
this.drawTank(500,150,g,0,0);//引用drawtank()的不能是g,而是this
this.drawTank(570,150,g,0,1);
this.drawTank(500,70,g,0,1);
g.setColor(Color.black);
g.setFont(new Font("仿宋",2,20));//??換換字型效果
g.drawString(Record.getDtNum()+"",600,170);
if((Record.getMtNum()+Record.getAddMtNum())>=0){
g.drawString((Record.getMtNum()+Record.getAddMtNum())+"",530,170);//
}else{
g.drawString((Record.getAddMtNum())+"",530,170);
}
g.setColor(Color.blue);
g.setFont(new Font("方正小标宋",1,17));
g.drawString("幹掉的坦克總數:",510,40);
g.setColor(Color.black);
g.setFont(new Font("仿宋",2,20));
g.drawString(Record.getSumDtNum()+"",530,90);
g.setColor(Color.MAGENTA);//設定顔色
g.setFont(new Font("隸書",0,20));//設定字型
g.drawString("第"+x+"關",500 , 200);//繪字元串
}
public void paint(Graphics g){//這個方法每當視窗激活,最小化,調用repaint()方法都會運作,線程中調用就一直顯示
super.paint(g);
// g.fillRect(0,0,400,300);//做個背景畫布,預設黑色
this.outNum(g);//調用顯示數量的函數
g.setColor(Color.red);//設定顔色
g.fillRect(530, 210, 30, 20);
g.setColor(Color.black);//設定顔色
g.drawLine(530, 210, 530, 320);
g.setColor(mycolor11);//設定顔色
if(mt.livetrue){
this.drawTank(mt.getX(),mt.getY(),g,mt.fangxiang,0);
}
if(mt0.livetrue){
this.drawTank(mt0.getX(),mt0.getY(),g,mt0.fangxiang,2);
}
if(mt01.livetrue){
this.drawTank(mt01.getX(),mt01.getY(),g,mt01.fangxiang,2);
}
if(mt02.livetrue){
this.drawTank(mt02.getX(),mt02.getY(),g,mt02.fangxiang,2);
}
if(mt.getLive()false){
g.setColor(mycolor11);//設定顔色
g.setFont(new Font(“Gill Sans Ultra Bold Condensed”,1,40));//字型:華康楷體, Ravie, OCR A Extended
g.drawString(“game over…”,200 , 220);//繪字元串
this.repaint();
}
if(Record.getDtNum()%60&&(Record.getDtNum()>10)){
// if(time%20)
// {
g.setColor(Color.blue);//設定顔色
g.setFont(new Font(“華文行楷”,1,35));//字型:華康楷體, Ravie, OCR A Extended
g.drawString(“你行不行?”,310 , 265);//繪字元串
// }
}
if(Record.getDtNum()0){
g.setColor(Color.red);//設定顔色
g.setFont(new Font(“華文行楷”,1,35));//字型:華康楷體, Ravie, OCR A Extended
g.drawString(“過關!”,300 , 265);//繪字元串
}
for(int i=0;i<dtk.size();i++)//畫敵人坦克asd
{
DiTank dt=dtk.get(i);
if(dt.livetrue){
this.drawTank(dt.getX(),dt.getY(),g,dt.fangxiang,1);//??!!注意用法用dtk 還是dt調用
}
}
for(int i=0;i<mt.aa.size();i++)//畫我的子彈
{
Zidan zd=mt.aa.get(i);
if(mt.zd!=null&&mt.zd.livetrue) //???畫子彈的條件
{
//g.fill3DRect((mt.zd.x-2),(mt.zd.y-2), 8, 8, false); //???畫子彈火力圈
g.setColor(Color.black);//子彈顔色設定為白色
g.fillOval(zd.x+1,zd.y+1, 4,4);
}
if(zd.livefalse)
{
mt.aa.remove(zd);
}
}
//this.repaint();//?
for(int i=0;i<dtk.size();i++)//畫敵人的子彈
{
DiTank dt=dtk.get(i);
for(int j=0;j<dt.dzd.size();j++)
{
Zidan zd=dt.dzd.get(j);
if(zd!=null&&dtk.get(i).livetrue)
{
g.setColor(Color.red);//子彈顔色設定為紅色,次處不進循環是不是更好?
g.fillOval(zd.x+1,zd.y+1, 4,4);
}
if(zd.livefalse)//删除生命為假的敵人子彈???
{
dt.dzd.remove(zd);
}
}
}
for(int i=0;i<bzjh.size();i++) //畫爆炸
{
Baozha bz=bzjh.get(i);
if(bzjh.get(i).livetime>140){
g.setColor(Color.red);
g.fillOval(bz.x, bz.y+5, 20,20 );//代替上面的句子
//g.fillOval(bz.x, bz.y, 20,5 );//可以用來做合成圖形,但是要定好坐标點
}else if((bzjh.get(i).livetime<=100)&&(bzjh.get(i).livetime>50)){
g.setColor(Color.orange);
g.fillOval(bz.x+4, bz.y+9, 12,12 );
}else if((bzjh.get(i).livetime<=50)&&(bzjh.get(i).livetime>20)){
g.setColor(Color.yellow);
g.fillOval(bz.x+7, bz.y+11,5,5 );
}else{
g.setColor(Color.pink);
g.fillOval(bz.x+10, bz.y+13,2,2 );
}
bz.ltjs(); //生存時間減少函數
if(bz.livetime0){
bzjh.remove(bz);
}
}
//
if(props.live==true){//畫道具
this.drawProps(props.getX(),props.getY(),g,props.getleixing());
}
//}
this.repaint();//教學視訊少了這句,子彈無法自主運作,主類啟動線程後仍然可動
}
public void keyPressed(KeyEvent e)//鍵盤輸入事件
{
if(mt.getLive()==true){
if(e.getKeyCode()==KeyEvent.VK_W){
this.mt.setFangxiang(0);
this.mt.xiangshang();
}else if(e.getKeyCode()==KeyEvent.VK_S){
this.mt.setFangxiang(1);
this.mt.xiangxia();
}else if(e.getKeyCode()==KeyEvent.VK_A){
this.mt.setFangxiang(2);
this.mt.xiangzuo();
}else if(e.getKeyCode()==KeyEvent.VK_D){
this.mt.setFangxiang(3);
this.mt.xiangyou();
}
if(e.getKeyCode()KeyEvent.VK_J)
{
if((mt.aa.size()<myzdNum)&&(mt.livetrue))//子彈設定最多 myzdNum 發
{
this.mt.fszd();//調用發射子彈函數
}
}
}
}
public void crash(){
}
public boolean addprops(Props props,MyTank mt)//吃道具觸發 方法 (道具功能觸發模型為邊長20的正方形)
{
boolean b2=false;
switch(props.leixing){
case 0://我的坦克速度提高//mt.fangxiang 0\1\2\3
if((mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15<props.getY()+20&&mt.getY()+15>props.getY())||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+15>props.getX()&&mt.getX()+15<props.getX()+20&&mt.getY()+10>props.getY()&&mt.getY()+10<props.getY()+20)){
props.live=false;
mt.sudu=20;
b2=true;
}
break;
case 1://效果回到出生地
if((mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15<props.getY()+20&&mt.getY()+15>props.getY())||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+15>props.getX()&&mt.getX()+15<props.getX()+20&&mt.getY()+10>props.getY()&&mt.getY()+10<props.getY()+20)){
props.live=false;
mt.setX(630);
mt.setY(280);
b2=true;
}
break;
case 2://提高我可以發射的子彈數目
//mt.fangxiang 0\1\2\3
if((mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15<props.getY()+20&&mt.getY()+15>props.getY())||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+15>props.getX()&&mt.getX()+15<props.getX()+20&&mt.getY()+10>props.getY()&&mt.getY()+10<props.getY()+20)){
props.live=false;
this.myzdNum=30;
this.huopao=1;
this.n=4;
b2=true;
}
break;
case 3://顯示的敵人坦克全死,但實際效果是..是不出敵方坦克了!!!!
if((mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15<props.getY()+20&&mt.getY()+15>props.getY())||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+15>props.getX()&&mt.getX()+15<props.getX()+20&&mt.getY()+10>props.getY()&&mt.getY()+10<props.getY()+20)){
props.live=false;
for(int i=0;i<dtk.size();i++){
if(dtk.get(i).live==true){
dtk.get(i).live=false;
Record.setDtNum();//有幾個活坦克生命變假,就累計幾輛dtNum
}
}
b1=true;
b2=true;
}
break;
case 4://吃道具加命
if((mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15<props.getY()+20&&mt.getY()+15>props.getY())||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+10>props.getX()&&mt.getX()+10<props.getX()+20&&mt.getY()+15>props.getY()&&mt.getY()+15<props.getY()+20)||(mt.getX()+15>props.getX()&&mt.getX()+15<props.getX()+20&&mt.getY()+10>props.getY()&&mt.getY()+10<props.getY()+20)){
props.live=false;
Record.setAddMtNum();
b2=true;
// System.out.println(“吃道具加命程式,正常運作”);
}
break;
}
return b2;
}
// addMyTank++;
//MyTank mt1=new MyTank(mt.getX(),mt.getY());//??建立另一個MyTank對象
// public void setAddMytank(){
// addMyTank++;
// };
// public static int getAddMytank(){
// return addMyTank;
// };
public void run() //我的畫闆的 線程函數
{
while(true){
try{
Thread.sleep(50);//
}catch(Exception e){}
for(int i=0;i<mt.aa.size();i++)//我的子彈集中敵坦克的線程
{
Zidan myzd=mt.aa.get(i);
if(myzd.live){
for(int j=0;j<dtk.size();j++){
DiTank dt=dtk.get(j);
// Zidan zd=dt.dzd.get(j);//為啥dzd可以直接用,不用建立// ||(b1==true&&Record.getDtNum()>0)
if(dt.live)//内關聯敵人坦克重生的一種情況,有敵人坦克被打中
{
if(this.jzsf(myzd,dt)&&((Record.getDtNum()-tksl)>=0)){//調用jzsf(),打中同時,坦克定點?及時重生
DiTank dt0=new DiTank((int)(Math.random()*50+5)*10,(int)(Math.random()*100+450));
Thread t2=new Thread(dt0);
t2.start();
Zidan zd0=new Zidan(dt0.x,dt0.y,dt0.fangxiang);
Thread t3=new Thread(zd0);
t3.start();
dt0.dzd.add(zd0);
dtk.add(dt0);
}
}
}
}
}
if(Record.getDtNum()>=tksl&&b1==true){ //炸彈爆炸,敵坦克按條件重生,
for(int i=0;i<tksl;i++){
DiTank dt1=new DiTank((int)(Math.random()*20)*10,(int)(Math.random()*100+450));
Thread t6=new Thread(dt1);
t6.start();
Zidan zd1=new Zidan(dt1.x,dt1.y,dt1.fangxiang);
Thread t7=new Thread(zd1);
t7.start();
dt1.dzd.add(zd1);
dtk.add(dt1);
}
b1=false;
}
if((Record.getDtNum()==(tksl-1))&&(b1==true)){
for(int i=0;i<tksl-1;i++){
DiTank dt1=new DiTank((int)(Math.random()*20)*10,(int)(Math.random()*100+450));
Thread t6=new Thread(dt1);
t6.start();
Zidan zd1=new Zidan(dt1.x,dt1.y,dt1.fangxiang);
Thread t7=new Thread(zd1);
t7.start();
dt1.dzd.add(zd1);
dtk.add(dt1);
}
b1=false;
}
if((Record.getDtNum()==(tksl-2))&&(b1==true)){
// for(int i=0;i<tksl-1;i++){
DiTank dt1=new DiTank((int)(Math.random()*20)*10,(int)(Math.random()*100+450));
Thread t6=new Thread(dt1);
t6.start();
Zidan zd1=new Zidan(dt1.x,dt1.y,dt1.fangxiang);
Thread t7=new Thread(zd1);
t7.start();
dt1.dzd.add(zd1);
dtk.add(dt1);
b1=false;
}
for(int j=0;j<dtk.size();j++)//敵人的子彈擊中我的坦克的線程
{
DiTank dt=dtk.get(j);//取出所有敵方坦克
for(int i=0;i<dt.dzd.size();i++)
{
Zidan zd=dt.dzd.get(i);//?
if(zd.live)
{
if(this.jzsf(zd,mt)true){//調用 擊中敵坦 函數
}
}
}
}
if((this.time%120)0){//6秒發生1次 道具随機重置//draw mt hit props
props.live=true;
// props.leixing=2;
props.leixing=(int)(Math.random()*propsSort);
props.x=(int)(Math.random()*370);
props.y=(int)(Math.random()*270);
props.livetime=100;//道具生存期
}
if(props.livetime>0){//道具生存期變化
props.livetime–;
}else{
props.live=false;
}
if(mt.livetrue&&props.livetrue){//調用 吃道具 方法
this.addprops(props,mt);
}
time++;
// if(SaveData.getSumDtNum()%200){
// Record.next();
// }
this.repaint();//線程運作中重繪??
}
}
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++){
Zidan zd=dt.dzd.get(j);
this.jzsf(zd, mt);
}
}
}
public void jzdf() //我的子彈擊中坦克的方法
{
for(int i=0;i<mt.aa.size();i++){
Zidan zd=mt.aa.get(i);//從我的子彈集合類取我的各個子彈
if(zd.livetrue){
for(int j=0;j<dtk.size();j++){
DiTank dt=dtk.get(j);//從敵坦克集合類取出各個敵坦克
if(dt.live){
this.jzsf(zd,dt);
// levelDtNum–;
}
}
}
this.repaint();
}
}
public boolean jzsf(Zidan zd,Tank tk)//擊中雙方的方法
{
boolean b2=false;
switch(tk.fangxiang)
{
case 0:
case 1:
if(zd.x>tk.x&&zd.x<tk.x+20&&zd.y>tk.y&&zd.y<tk.y+30)//分辨率判斷?
{
if(tk instanceof DiTank){//隻改這就實作 判斷tk是不是DiTank的執行個體
Record.setDtNum();
Record.setSumDtNum();
// Record.setAddMtNum();
tk.live=false;
b2=true;
}else{
// System.out.println(“Record.getMtNum()=”+Record.getMtNum());
Record.setMtNum();//Record.getSumMtNum()一直小于0 ?bug
if(Record.getMtNum()+1<=0){
Record.lowAddMtNum();
}
// System.out.println(“Record.getMtNum()=”+Record.getMtNum());
// System.out.println(“Record.AddMtNum()=”+Record.getAddMtNum());
if(Record.getMtNum()+Record.getAddMtNum()>0){//bug 被打一下就遊戲結束 已經解決
mt.setX(140);
mt.setY(232);
}
if(Record.getMtNum()+Record.getAddMtNum()<=0){
tk.live=false;
}
}
zd.live=false;
Baozha bz=new Baozha(tk.x,tk.y);
bzjh.add(bz);
}
break;
case 2:
case 3:
if(zd.x>tk.x&&zd.x<tk.x+30&&zd.y>tk.y&&zd.y<tk.y+20){
if(tk instanceof DiTank){//隻改這就實作 判斷tk是不是DiTank的執行個體
Record.setDtNum();//每次敵人坦克數量-1
Record.setSumDtNum();
// Record.setAddMtNum();
tk.live=false;
b2=true;
}else{
// System.out.println(“Record.getMtNum()=”+Record.getMtNum());
Record.setMtNum();//Record.getSumMtNum()一直小于0 ?bug
if(Record.getMtNum()+1<=0){
Record.lowAddMtNum();
}
// System.out.println(“Record.getMtNum()=”+Record.getMtNum());
// System.out.println(“Record.AddMtNum()=”+Record.getAddMtNum());
if(Record.getMtNum()+Record.getAddMtNum()>0){//bug 被打一下就遊戲結束 已經解決
mt.setX(550);
mt.setY(270);
}
if(Record.getMtNum()+Record.getAddMtNum()<=0){
tk.live=false;
}
}
zd.live=false;
Baozha bz=new Baozha(tk.x,tk.y);
bzjh.add(bz);
}
break;
}
return b2;
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
public void drawTank(int x,int y,Graphics g,int fangxiang,int leixing)//畫坦克函數
{
int m=10;
//double n=1;
switch(leixing)//不同陣營坦克
{
case 0://我的坦克
g.setColor(Color.yellow);// 我的坦克顔色 黃色
// g.fillOval(170huopao, 240huopao, 30huopao, 30huopao);
m=11;
break;
case 1://敵人的坦克
g.setColor(mycolor3);//敵人坦克顔色 藍色
// m=15;
break;
case 2://玩家2的坦克
g.setColor(mycolor1);//敵人坦克顔色 綠色
break;
}
switch(fangxiang)//不同方向的坦克(0,1,2,3)分别代表上下左右,中心原點不變做坐标變換
{
case 0://上
g.fill3DRect(x,y,5,30,true);
g.fill3DRect(x+15,y,5,30,true);
g.fill3DRect(x+5,y+5,10,20,true);
g.drawLine(x+10,y-5,x+10,(y+10));
g.setColor(Color.black);
g.fillOval(x+5,y+10,10,10);
break;
case 1://下
g.fill3DRect(x,y,5,30,true);
g.fill3DRect(x+15,y,5,30,true);
g.fill3DRect(x+5,y+5,10,20,true);
g.drawLine(x+10,y+10,x+10,(y+35));
g.setColor(Color.black);
g.fillOval(x+5,y+10,10,10);
break;
case 2://左
g.fill3DRect(x-5,y+5,30,5,true);
g.fill3DRect(x-5,y+20,30,5,true);
g.fill3DRect(x,y+10,20,10,true);
g.drawLine((x-10)+n-m,y+15,(x+10),(y+15));
g.setColor(Color.black);
g.fillOval(x+5,y+10,10,10);
break;
case 3://右
g.fill3DRect(x-5,y+5,30,5,true);
g.fill3DRect(x-5,y+20,30,5,true);
g.fill3DRect(x,y+10,20,10,true);
g.drawLine((x+10)-n+m,y+15,(x+30),(y+15));
g.setColor(Color.black);
g.fillOval(x+5,y+10,10,10);
break;
}
}
public void drawProps(int x,int y,Graphics g,int leixing)//畫道具
{
if(time%8==0){
switch(leixing)
{
case 0://畫車輪對應坦克加速
g.setColor(Color.white);
g.fillOval(x, y, 21, 21);
g.setColor(Color.black);
g.fillOval(x+2,y+2,16,16);
g.setColor(Color.white);
g.drawOval(x+2,y+2,16,16);
g.drawLine(x+2,y+10,x+18,y+10);
g.drawLine(x+10,y+2,x+10,y+18);
g.drawLine(x+16,y+4,x+4,y+16);
g.drawLine(x+4,y+4,x+16,y+16);
break;
case 1://畫回出生道地具圖示
g.setColor(Color.white);
g.drawRoundRect(x, y, 20, 20, 5, 5);
g.setColor(mycolor3);
g.fillRoundRect(x+5, y+5, 10, 10, 5, 5);
break;
case 2://畫增加子彈數目道具//?
g.setColor(mycolor2);
g.fill3DRect(x-15,y+8,30,5,false);
g.fill3DRect(x-15,y+6,10,10,true);
g.fillOval(x+15,y+7,7,7);
break;
case 3://畫炸彈
g.setColor(mycolor2);
g.fillRect(x, y, 21, 21);
g.setColor(Color.black);
g.fillRect(x+8,y+6,6,2);
g.fillOval(x+3,y+7,14,14);
g.drawLine(x+11, y+3, x+11, y+6);
g.setColor(Color.white);
g.drawLine(x+11, y+15, x+8, y+14);
break;
case 4://畫小坦克道具
g.setColor(Color.yellow);
g.fill3DRect(x,y,20,3,true);
g.fill3DRect(x,y+10,20,3,true);
g.fill3DRect(x+3,y+3,14,7,false);
g.fillOval(x+6,y+3,7,7);
g.drawLine(x-7,y+6,x+7,y+6);
break;
}
}
}
}
}
//this.add(mt1);///
//tp1=Toolkit.getDefaultToolkit().getImage(Panel.class.getResource(“baozha1.jpg”));//添加圖檔
//tp3=Toolkit.getDefaultToolkit().getImage(baozha3);//添加圖檔
//if(dt0.live=false){//在敵人坦克重新的run()裡隻要加上就出問題,這段程序就不走了
//dtk.remove(dt);//隻要加上就出問題,這段程序就不走了
//Zidan zd=null;//在MyPanel類内的開頭,因為子彈都是随着Tank動,是以在不建立對象,而且建立的子彈超過邊界就死了,
//生存期很短,單獨操作意義不大
//Baozha bz=null;在MyPanel類内的開頭,到底要不要寫這?不用,因為爆炸時間較短,但要完成畫面效果變化.而且可能同時有很多爆炸,
//是以建立爆炸類集合是必須的
//吃道具圖檔和功能觸發不一緻不同步在一個線程的裡面就同步了
//不同步的可以分寫在不同縣城裡,同步的程式段必須由一個線程裡進行
//for(int i=0;i<mt.aa.size();i++){//這樣隻是在吃道具前發出的子彈速度增加,不能改變後續子彈速度,因為子彈的速度隻有子彈類可以改變,
//但是我的子彈和敵人的子彈是同一類子彈是以不能這樣改,如果要改變,應該建立兩個不同的子彈類,分别有雙方引用.!!!
// mt.aa.get(i).sudu=30;
//}
包2如下:
Ycl
import java.util.;
import java.io.;
class Tank //坦克類
{
int x=0,y=0; //坐标
int fangxiang=0; //方向
int sudu=5; //速度
boolean live=true;//生命
public Tank(int x,int y){//為什麼不定義為3個或者5個變量的構造函數??
this.x=x;
this.y=y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getFangxiang() {
return fangxiang;
}
public void setFangxiang(int fangxiang) {
this.fangxiang = fangxiang;
}
public boolean getLive() {
return live;
}
public void setLive() {
this.live=false;
}
}
class MyTank extends Tank//因為子彈的功能大多跟着坦克走,是以在這裡加連發功能 //我的坦克
{
Vector aa=new Vector();//建立我的子彈集合類aa
Zidan zd=null;//為什麼這裡又要寫定義為空??
int sudu=7;
public MyTank(int x,int y){
super(x,y); //???
}
public void fszd()//發射子彈函數 發射子彈就子彈的 啟動線程!!
{
switch(this.fangxiang){
case 0:
zd=new Zidan(x+9,y-15,0);//建立一個子彈
aa.add(zd);//再添加一個子彈
break;
case 1:
zd=new Zidan(x+9,y+44,1);
aa.add(zd);
break;
case 2:
zd=new Zidan(x-18,y+15,2);
aa.add(zd);
break;
case 3:
zd=new Zidan(x+35,y+15,3);
aa.add(zd);
break;
}
Thread t=new Thread(zd);//???
t.start();//???
}
public void xiangshang(){
if(y>0){
y-=sudu;
}else{
y=0;
}
}
public void xiangxia(){
if(y<530){
y+=sudu;
}else{
y=533;
}
}
public void xiangzuo(){
if(x>0){
x-=sudu;
}else{
x=0;
}
}
public void xiangyou(){
if(x<660){
x+=sudu;
}else{
x=660;
}
}
}
class DiTank extends Tank implements Runnable//敵坦克類
{
int sudu=6;
int time=0;
int pinlv=4;//敵人子彈發射間隔頻率
Vector dzd=new Vector();//定義敵人子彈集合類dzd
static Vector dtk=new Vector();//建立一個敵坦克集合類
//Zidan zd=null;//為什麼這裡不能再指向空?
//Tank dtk;
public DiTank(int x,int y){
super(x,y);
}
public void run()//重寫接口的run()
{
while(true)
{
try{
Thread.sleep(40);//線程睡眠
}catch(Exception e){}//System.exit(-1);//??參數放0還是-1?啥差別
switch(this.fangxiang)//敵人坦克運動的線程
{
case 0:
for(int i=0;i<10;i++){
if(y>=260&&this.dtHit()!=true){
y-=sudu;//寫到循環裡面可以,寫到for前面不行嗎?
try{
Thread.sleep(50);//線程睡眠
}catch(Exception e){}//System.exit(-1);//??參數放0還是-1?啥差別
}
}
break;
case 1:
for(int i=0;i<10;i++){
if(y<=525&&this.dtHit()!=true){
y+=sudu;
try{
Thread.sleep(50);//線程睡眠
}catch(Exception e){}
}
}
break;
case 2:
for(int i=0;i<10;i++){
if(x>=5&&this.dtHit()!=true){
x-=sudu;
try{
Thread.sleep(50);//線程睡眠
}catch(Exception e){}
}
}
break;
case 3:
for(int i=0;i<10;i++){
if(x<=634&&this.dtHit()!=true){
x+=sudu;
try{
Thread.sleep(50);//線程睡眠
}catch(Exception e){}
}
}
break;
}
this.fangxiang=(int)(Math.random()*4);//使用随機函數 控制fangxiang變量 實作随機變方向
this.efire();//發射子彈 方法
if(this.live==false)//生命假跳出該系列線程的循環
{
break;
}
this.time++;//設定自+1的時間變化
}
}
public void efire() {
if((time%pinlv)==0)//用時間這個量控制敵人坦克子彈發射頻率
{
if(live)
{
if(dzd.size()<4)//控制敵坦克子彈數量
{
Zidan zd=null;//為什麼這裡教學視訊寫到if判斷switch之前?
switch(fangxiang)//為什麼這裡是教學視訊不寫this
{
case 0:
zd=new Zidan(x+10,y-5,0);//坐标要算
dzd.add(zd);
//zd.x-=sudu;為啥不用控制坐标?因為還沒有子彈對象,而且子彈類中定義了運動坐标
break;
case 1:
zd=new Zidan(x+10,y+35,1);
dzd.add(zd);
break;
case 2:
zd=new Zidan(x-15,y+15,2);
dzd.add(zd);
break;
case 3:
zd=new Zidan(x+35,y+15,3);
dzd.add(zd);
break;
}
Thread t5=new Thread(zd);//怎麼在這裡啟動線程??
t5.start();
}
}
}
}
// public void dtkxl(Vector dtl){
// this.dtk=dtl;
// }
// public void dtkxl(Vector dxl){//?貌似是敵坦克血量 暫時用不着
// this.dtk=dxl;
// }
public boolean dtHit(){
boolean b=false;
switch(this.fangxiang){
case 0:
for(int i=0;i<dtk.size();i++){
DiTank dt=dtk.get(i);
if(dt!=this&&dt.livetrue){
if(dt.fangxiang 0||dt.fangxiang1){
if((this.x>=dt.x&&this.x<=dt.x+20&&this.y>=dt.y&&this.y<=dt.y+30)){
b=true;
}
if(this.x+20>=x&&this.x+20<=dt.x+20&&this.y>=dt.y&&this.y<=dt.y+30){
b=true;
}
}
if(dt.fangxiang 2||dt.fangxiang3){
if(this.x>=dt.x&&this.x<=dt.x+30&&this.y>=dt.y&&this.y<=dt.y+20){
b=true;
}
if(this.x+20>=dt.x&&this.x+20<=dt.x+30&&this.y>=y&&this.y<=dt.y+20){
b=true;
}
}
}
}
case 1:
for(int i=0;i<dtk.size();i++){
DiTank dt=dtk.get(i);
if(dt!=this&&dt.livetrue){//&&dt.livetrue
if(dt.fangxiang0||dt.fangxiang1){
if(this.x>=dt.x&&this.x<=dt.x+20&&this.y+30>=dt.y&&this.y+30<=dt.y+30){
b=true;
}
if(dt.x+20>x&&dt.x+20<x+30&&dt.y+30>y&&dt.y+30<y+20){
b=true;
}
}
if(dt.fangxiang2||dt.fangxiang3){
if(this.x>=dt.x&&this.x<=dt.x+30&&this.y+30>=dt.y&&this.y+30<=dt.y+20){
b=true;
}
if(this.x+20>=dt.x&&this.x+20<=dt.x+30&&this.y+30>=dt.y&&this.y+30<=dt.y+20){
b=true;
}
}
}
}
case 2:
for(int i=0;i<dtk.size();i++){
DiTank dt=dtk.get(i);
if(dt!=this&&dt.livetrue){
if(dt.fangxiang 0||dt.fangxiang1){
if(this.x>=dt.x&&this.x<=dt.x+20&&this.y>=dt.y&&this.y<=dt.y+30){
b=true;
}
if(this.x>=dt.x&&this.x<=dt.x+20&&this.y+20>=dt.y&&this.y+20<=dt.y+30){
b=true;
}
}
if(dt.fangxiang2||dt.fangxiang3){
if(this.x>=dt.x&&this.x<=dt.x+30&&this.y>=dt.y&&this.y<=dt.y+20){
b=true;
}
if(this.x>=dt.x&&this.x<=dt.x+30&&this.y+20>=dt.y&&this.y+20<=dt.y+20){
b=true;
}
}
}
}
case 3:
for(int i=0;i<dtk.size();i++){
DiTank dt=dtk.get(i);
if(dt!=this&&dt.live==true){
if(dt.fangxiang ==0||dt.fangxiang==1){
if(this.x+30>=dt.x&&this.x+30<=dt.x+20&&this.y>=dt.y&&this.y<=dt.y+30){
b=true;
}
if(this.x+30>=dt.x&&this.x+30<=dt.x+20&&this.y+20>=dt.y&&this.y+20<=dt.y+30){
b=true;
}
}
if(dt.fangxiang ==2||dt.fangxiang==3){
if(this.x+30>=dt.x&&this.x+30<=x+30&&this.y>=dt.y&&this.y<=dt.y+20){
b=true;
}
if(this.x+30>=dt.x&&this.x+30<=dt.x+30&&this.y+20>=dt.y&&this.y+20<=dt.y+20){
b=true;
}
}
}
}
}
return b;
}
}
class Zidan implements Runnable//用實作接口方法把子彈作成線程, 子彈類
{
int x;int y;
int fangxiang;
int sudu=10;
boolean live=true;
public Zidan(int x,int y,int fangxiang){
this.x=x;
this.y=y;
this.fangxiang=fangxiang;
}
public void run()//子彈可以活動的線程
{
while(true)//線程的死循環裡都要有睡眠
{
try{
Thread.sleep(50);
}catch(Exception e){}
switch(this.fangxiang){
case 0:
y-=sudu;
break;
case 1:
y+=sudu;
break;
case 2:
x-=sudu;
break;
case 3:
x+=sudu;
break;
}
if(x<0||y<220||x>710||y>710)//邊界限制子彈(生命為假的條件)
{
this.live=false;
break;
}
}
}
}
class Baozha //爆炸類
{
int x,y;
int livetime=180;
boolean live=true;
Baozha(int x,int y){
this.x=x;
this.y=y;
}
public void ltjs()//生存時間減少函數
{
if(livetime>0){
livetime–;
}else{
this.live=false;//不寫this行不行??
}
}
}
class Props //implements Runnable//道具好象不用建立?直接寫入别的程式中=no;不實作Runnable接口
{
int x=0,y=0;
int leixing=0;//0,1
//int perleixing=2;
boolean live=false;
//int perlive=200;//每次live變化的時間系數
int livetime=200;//每次的生存期時間系數
//int lifeFactor=100;
Props(int x,int y){
this.x=x;
this.y=y;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public int getleixing(){
return leixing;
}
public void setleixing(int leixing){
this.leixing=leixing;
}
public void setLivetime(){
if(live==true&&livetime>0){
livetime–;
}else{
live=false;
}
}
public int getLivetime(){
return livetime;
}
public boolean getLive(){
return live;
}
}
class Record//做成靜态的方法靜态的變量友善、安全,不然可能出錯,由于線程不同時統計
{
private static Vector dtk=new Vector();//建立一個敵坦克集合類
private static Vector wzjh=new Vector();//建立一個位置集合類
private static FileReader fr=null;
private static FileWriter fw=null;
private static BufferedReader br=null;
private static BufferedWriter bw=null;
private static int mtNum=2;//設定為靜态,在整個程式裡好用
private static int dtNum=20;
private static int addMtNum=0;//獲得的hero命
// private static int sumMtNum=0;//我的坦克現有總命
private static int sumDtNum=0;//殺敵坦克總數
public static int next=0;
// private static int sum=3;//總關數
public Record(){
}
// public static int getSum(){
// return sum;
// }
public static void setDtNum()//敵人坦克數量減少方法
{
if(dtNum>0){
dtNum–;
}
}
public static int getDtNum() {
return dtNum;
}
public static void setMtNum()//我的坦克數量統計方法
{
if(mtNum>0){
mtNum–;
}
}
public static int getMtNum() {
return mtNum;
}
public static void reMtNum() {//重置MtNum
mtNum=2;
}
public static void reDtNum() {//重置敵人坦克數量方法MtNum
dtNum=20;
}
public static void reAddMtNum() {//重置敵人坦克數量方法MtNum
addMtNum=0;
}
public static void setAddMtNum0(){//得分獎命 方法
if((sumDtNum==30)||((sumDtNum%40)==0)&&(sumDtNum!=0)){
addMtNum++;
}
}
public static void setAddMtNum(){//吃道具獎命 方法
addMtNum++;
}
public static void lowAddMtNum()//我的坦克數量統計方法
{
if(addMtNum>=0){
addMtNum--;
}
}
public static int getAddMtNum(){//取獎命 方法
return addMtNum;
}
public static int next(){
next++;
return next;
}
public static int reNext(){
next=0;
return next;
}
public static void setSumDtNum()//殺敵坦克統計方法
{
sumDtNum++;
}
public static int getSumDtNum(){
return sumDtNum;
}
public static void bcjl()//儲存記錄
{
try{
fw=new FileWriter("e:\\tanksavedata.txt");//斜杠方向是捺,非撇?
bw=new BufferedWriter(fw);
bw.write(sumDtNum+"\r\n");
}catch(Exception e){}
finally{
try{
// bw.flush();
// fw.flush();
bw.close();
fw.close();
}catch(Exception e){}
}
}
public static void dqjl()//讀取記錄
{
try{
fr=new FileReader(“e:\tanksavedata.txt”);
br=new BufferedReader(fr);
String b=br.readLine();
sumDtNum=Integer.parseInt(b);
}catch(Exception e){}
finally{
try{
br.close();
fr.close();
}catch(Exception e){}
}
}
public static void cunpan()//存盤
{
try{
fw=new FileWriter("e:\\tanksavedata.txt");
bw=new BufferedWriter(fw);
bw.write(sumDtNum+"\r\n");
for(int i=0;i<dtk.size();i++){
DiTank dt=dtk.get(i);
if(dt.live==true){
String zb=dt.x+" "+dt.y+" "+dt.fangxiang+"";
bw.write(zb+"\r\n");
}
}
}catch(Exception e){}
finally{
try{
// bw.flush();//?
// fw.flush();//?
bw.close();
fw.close();
}catch(Exception e){}
}
}
public static Vector dupan()//讀取cunpan記錄
{
try{
fr=new FileReader(“e:\tanksavedata.txt”);
br=new BufferedReader(fr);
String b="";
b=br.readLine();
sumDtNum=Integer.parseInt(b);
while((b=br.readLine())!=null){
String[] st=b.split(" ");//用字元做間隔來确定數組元素
Weizhi wz=new Weizhi(Integer.parseInt(st[0]),Integer.parseInt(st[1]),Integer.parseInt(st[2]));
wzjh.add(wz);
}
}catch(Exception e){}
finally{
try{
br.close();
fr.close();
}catch(Exception e){}
}
return wzjh;
}
public Vector getDtk(){
return dtk;
}
public void setDtk(Vector dtk){
this.dtk=dtk;
}
}
class Weizhi//位置類
{
int x;
int y;
int fangxiang;
Weizhi(int x,int y,int fangxiang){
this.x=x;
this.y=y;
this.fangxiang=fangxiang;
}
}
// public static void setDtk(Vector dtk){
// this.dtk=dtk;
// }
// public static int getSumMtNum()//我的坦克數量統計方法
// {
// return sumMtNum;
// }
// br.read((char)aaaa);
// int a;
// for(int i=0;i<fw.size();i++){
// //a=bw.writer(“fw+/r+/n”);
// a=bw.write(i);
//
// }
// br=new BufferedReader(fr); fr=new FileReader(“e:/tanksavedata.txt”);
// public static void setSumMtNum()//我的坦克數量統計方法 這個方法寫的有問題!bug
// {
// sumMtNum=mtNum+addMtNum;
// }
//public static void setKillRecord()
//{
// killNum++;
//}
//public static int getKillRecord()
//{
// return killNum;
//}
//class Hit
//{
//
//
// }
// public void run(){
// while(true){
// try{
// Thread.sleep(1000);
// }catch(Exception e){}
if(time%4000){
// if(livetime>0){
// livetime–;
// }else{
// live=false;
// }
// if(this.livefalse)//重置生存時間
// {
// break;
// }
// }
// }