1 .主类 |
package s1230坦克大战; |
import java.awt.Color; |
import java.awt.Graphics; |
import java.awt.event.KeyEvent; |
import java.awt.event.KeyListener; |
import java.util.Vector; |
import javax.swing.ImageIcon; |
import javax.swing.JFrame; |
import javax.swing.JPanel; |
import 工具类.ThreadSleep; |
public class Tank1 extends JFrame { |
static int panelXLength= 700 ; |
static int panelYlength= 700 ; |
static int gameXLength= 500 ; |
static int gameYLength= 500 ; |
static int zidanNum= 0 ; |
MyPanel mp= null ; |
|
public static void main(String[] args) |
{ |
Tank1 t1= new Tank1(); |
} |
public Tank1() |
{ mp= new MyPanel(); |
this .add(mp); |
this .setTitle( "坦克大战" ); //设置窗体的标题 |
this .setLocationRelativeTo( null ); //设置窗体出现位置居中 |
this .setDefaultCloseOperation( 3 ); //设置窗体的关闭操作 |
this .setResizable( true ); //设置禁止调整窗体的大小 |
this .setIconImage(( new ImageIcon( "E:/Michael/javaImage/扫雷图片/bomb.png" ).getImage())); //设置标题栏图标 |
this .setSize(panelXLength,panelYlength); //设置窗体的大小 |
this .setLocationRelativeTo( null ); //设置窗体出现在屏幕中间 |
this .addKeyListener(mp); |
this .setVisible( true ); |
|
Thread o= new Thread(mp); //添加线程很重要 不然子弹不会动 |
o.start(); //这个线程的作用是不断执行MyPanel |
} |
|
class MyPanel extends JPanel implements KeyListener,Runnable |
{ |
MyTank mt= null ; //有什么作用? |
Vector<EnemyTank> dtk= new Vector<EnemyTank>(); //new 出一个新的vector对象,vector多线程 |
int tankNum= 3 ; |
|
public MyPanel() |
{ |
mt= new MyTank( 250 , 400 ); //创建我方坦克 |
for ( int i= 0 ;i<tankNum;i++) //批量创建敌方坦克,要用到vector |
{ EnemyTank dt= new EnemyTank((i)* 180 + 5 , 10 ); |
dtk.add(dt); |
Thread r= new Thread(dt); //让坦克动起来的线程 |
r.start(); |
} |
} |
public void paint(Graphics g) |
{ |
super .paint(g); |
g.fillRect( 0 , 0 ,gameXLength,gameYLength); |
this .drawTank(mt.getX(),mt.getY(),g,mt.leixing,mt.fangxiang); //在界面上绘制我方坦克,x(坐标),y(坐标),画笔g,类型,方向 |
|
for ( int i= 0 ;i<tankNum;i++) //在界面上批量绘制敌方坦克 |
{ if (dtk.get(i).life== true ) |
{ this .drawTank(dtk.get(i).getX(),dtk.get(i).getY(),g, 0 ,dtk.get(i).fangxiang); //x(坐标),y(坐标),画笔g,类型,方向 |
|
for ( int j= 0 ;j<dtk.get(i).dzd.size();j++) |
{ |
Zidan zd=dtk.get(i).dzd.get(j); |
dtk.get(i).shoot(); |
|
if (zd!= null &&zd.life== true ) //mt.zd.life==true 控制子弹的范围 |
{ |
g.setColor(Color.RED); //设置子弹颜色 |
g.fill3DRect(zd.x, zd.y, 3 , 3 , false ); //绘制子弹,如何让子弹动起来 |
} |
if (zd.life== false ) //除去Vector中的zd对象,目的是为了实现子弹数量限制 |
dtk.get(i).dzd.remove(zd); |
} |
} |
} |
|
|
for ( int i= 0 ;i<mt.aa.size();i++) //绘制我方坦克子弹 |
{ Zidan zd=mt.aa.get(i); |
|
if (zd!= null &&mt.zd.life== true ) //mt.zd.life==true 控制子弹的范围 |
{ |
g.setColor(Color.RED); //设置子弹颜色 |
g.fill3DRect(zd.x, zd.y, 3 , 3 , false ); //绘制子弹,如何让子弹动起来 |
} |
if (zd.life== false ) //除去Vector中的zd对象,目的是为了实现子弹数量限制 |
mt.aa.remove(zd); |
} |
|
} |
//子弹是否击中tank的判断方法************************************* |
public void jizhong(Zidan zd,EnemyTank dt) |
{ switch (dt.fangxiang) |
{ |
case 0 : |
case 1 : |
if (zd.x>dt.x&&zd.x<dt.x+ 20 &&zd.y>dt.y&&zd.y<dt.y+ 30 ) |
{ zd.life= false ; dt.life= false ;} |
break ; |
|
case 2 : |
case 3 : |
if (zd.x>dt.x&&zd.x<dt.x+ 30 &&zd.y>dt.y&&zd.y<dt.y+ 20 ) |
{ zd.life= false ; dt.life= false ;} |
break ; |
} |
} |
//子弹是否击中tank的判断方法************************************* |
|
|
private void drawTank( int x, int y, Graphics g, int leixing, int fangxiang) //绘制坦克的方法 |
{ |
|
switch (leixing) //设置坦克颜色,0为黄色,1为绿色 |
{ |
case 0 : g.setColor(Color.YELLOW); break ; |
case 1 : g.setColor(Color.GREEN); break ; |
} |
|
switch (fangxiang) //坦克方向,case0表示面朝上方的坦克,1表示面朝右方,2表示面朝下方,3表示面朝左方 |
{ |
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 ); //炮管:绝对长度为18 |
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 ); //炮管:绝对长度为18 |
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 ); //炮管:绝对长度为18 |
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+ 5 , y+ 5 , 10 , 10 ); //椭圆炮台 |
g.drawLine(x+ 10 , y+ 10 , x+ 28 , y+ 10 ); //炮管:绝对长度为18 |
break ; |
} |
} |
public void keyTyped(KeyEvent e) {} |
public void keyReleased(KeyEvent e) {} |
public void keyPressed(KeyEvent e) |
{ //坦克的方向控制,依次是上下左右,对应按键是w s a d。 |
if (e.getKeyCode()==KeyEvent.VK_W) |
{ |
this .mt.setFangxiang( 0 ); |
this .mt.upMove(); |
|
} |
|
if (e.getKeyCode()==KeyEvent.VK_S) |
{ this .mt.setFangxiang( 2 ); |
this .mt.downMove(); |
} |
if (e.getKeyCode()==KeyEvent.VK_A) |
{ this .mt.setFangxiang( 1 ); |
this .mt.leftMove(); |
} |
if (e.getKeyCode()==KeyEvent.VK_D) |
{ this .mt.setFangxiang( 3 ); |
this .mt.rightMove(); |
} |
|
if (e.getKeyCode()==KeyEvent.VK_J) //监听发射子弹的按钮 |
{ if (mt.aa.size()< 8 ) //限制子弹发射的数量为8颗 |
this .mt.shoot(); |
} |
|
this .repaint(); //还没搞懂这个是干嘛的? |
} |
|
public void run() |
{ |
while ( true ) |
{ |
ThreadSleep.threadSleep( 100 ); |
|
for ( int i= 0 ;i<mt.aa.size();i++) //2层循环的作用是,让每一颗子弹和每一辆坦克的坐标对比,来确定被打中的坦克 |
{ Zidan zd=mt.aa.get(i); //取出子弹 |
if (zd.life) //如果子弹有效 |
{ |
for ( int j= 0 ;j<dtk.size();j++) |
{EnemyTank dt=dtk.get(j); //取出坦克对象 |
if (dt.life) this .jizhong(zd,dt); //判断子弹是否击中tank |
} |
} |
} |
this .repaint(); //还没搞懂这个是干嘛的? |
} |
} |
} |
} |
2 .sucai类 |
package s1230坦克大战; |
import java.util.Random; |
import java.util.Vector; |
|
class Tank { |
int x= 0 ,y= 0 ; //横纵坐标 |
int speed= 9 ; |
int fangxiang= 0 ; |
int leixing= 1 ; |
int time= 0 ; |
boolean life= true ; |
|
public Tank( int x, int y) //构造方法 |
{ this .x=x; |
this .y=y; |
} |
public int getSpeed() { return speed;} |
public void setSpeed( int speed) { this .speed = speed;} |
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 void upMove() { if (y> 5 ) y-=speed;} //向上移动 |
public void downMove() { if (y< 460 )y+=speed;} //向下移动 |
public void leftMove() { if (x> 5 ) x-=speed;} //向左移动 |
public void rightMove() { if (x< 460 )x+=speed;} //向右移动 |
public int getFangxiang() { return fangxiang;} |
public void setFangxiang( int fangxiang) { this .fangxiang = fangxiang;} |
public int getLeixing() { return leixing;} |
public void setLeixing( int leixing) { this .leixing = leixing;} |
|
} |
class MyTank extends Tank |
{ Vector<Zidan> aa= new Vector<Zidan>(); //专门存放子弹,来解决一按发射键子弹消失的问题 |
Zidan zd= null ; |
|
public MyTank( int x, int y) |
{ super (x,y);} //调用父类的构造方法 |
public void shoot() |
{ switch ( this .fangxiang) |
{ case 0 : zd= new Zidan(x+ 10 ,y, 0 ); aa.add(zd); break ; //每发射一颗子弹都加入到容器Vector中 |
case 1 : zd= new Zidan(x,y+ 10 , 1 ); aa.add(zd); break ; |
case 2 : zd= new Zidan(x+ 10 ,y+ 30 , 2 ); aa.add(zd); break ; |
case 3 : zd= new Zidan(x+ 30 ,y+ 10 , 3 ); aa.add(zd); break ; |
} |
Thread t= new Thread(zd); //这个线程是为了让子弹动起来 |
t.start(); |
} |
} |
class EnemyTank extends Tank implements Runnable |
{ int speed= 1 ; //每次线程调用,坦克前进一次的距离 |
Zidan zd= null ; |
|
Vector<Zidan> dzd= new Vector<Zidan>(); //专门存放子弹,来解决一按发射键子弹消失的问题 |
public EnemyTank( int x, int y) |
{ super (x,y);} //调用父类的构造方法 |
|
|
public void shoot() |
{ switch ( this .fangxiang) |
{ case 0 : zd= new Zidan(x+ 10 ,y, 0 ); dzd.add(zd); break ; //每发射一颗子弹都加入到容器Vector中 |
case 1 : zd= new Zidan(x,y+ 10 , 1 ); dzd.add(zd); break ; |
case 2 : zd= new Zidan(x+ 10 ,y+ 30 , 2 ); dzd.add(zd); break ; |
case 3 : zd= new Zidan(x+ 30 ,y+ 10 , 3 ); dzd.add(zd); break ; |
} |
Thread t= new Thread(zd); //这个线程是为了让子弹动起来 |
t.start(); |
} |
|
public void run() |
{ |
while ( true ) |
{ |
int length; |
Random a= new Random(); |
this .fangxiang=( int )(Math.random()* 4 ); //随机产生方向 |
switch ( this .fangxiang) |
{ case 0 : |
length=a.nextInt( 59 )+ 13 ; //每次随机方向,坦克前进的距离为 次数*speed,就是每次随机方向前进的总距离 |
for ( int i= 0 ;i<length;i++) |
{ |
if (y> 5 )y-=speed; |
else break ; |
try {Thread.sleep( 50 );} //通过线程挂起的时间,控制地方坦克移动的频率,0.2秒前进一次 |
catch (Exception e) {} |
} |
break ; |
|
case 1 : |
length=a.nextInt( 59 )+ 13 ; //每次随机方向,坦克前进的次数 次数*speed,就是每次随机方向前进的总距离 |
for ( int i= 0 ;i<length;i++) |
{ |
if (x> 5 )x-=speed; |
else break ; |
try {Thread.sleep( 50 );} //通过线程挂起的时间,控制地方坦克移动的频率,0.2秒前进一次 |
catch (Exception e) {} |
} |
break ; |
|
case 2 : |
length=a.nextInt( 59 )+ 13 ; //每次随机方向,坦克前进的次数 次数*speed,就是每次随机方向前进的总距离 |
for ( int i= 0 ;i<length;i++) |
{ |
if (y< 480 )y+=speed; |
else break ; |
try {Thread.sleep( 50 );} //通过线程挂起的时间,控制地方坦克移动的频率,0.2秒前进一次 |
catch (Exception e) {} |
} |
break ; |
|
case 3 : |
length=a.nextInt( 59 )+ 13 ; //每次随机方向,坦克前进的次数 次数*speed,就是每次随机方向前进的总距离 |
for ( int i= 0 ;i<length;i++) |
{ |
if (x< 470 )x+=speed; |
else break ; |
try {Thread.sleep( 50 );} //通过线程挂起的时间,控制地方坦克移动的频率,0.2秒前进一次 |
catch (Exception e) {} |
} |
break ; |
} |
|
if ( this .life== false ) break ; //如果坦克被子弹击中,那么就退出循环 |
Vector<Zidan> dzd= new Vector<Zidan>(); |
//坦克发子弹的代码 |
time++; |
if (time% 2 == 0 ) |
{ if (life) |
{ |
if (dzd.size()< 5 ) |
{ Zidan zd= null ; |
switch (fangxiang) |
{ |
case 0 : zd= new Zidan(x+ 10 ,y, 0 ); |
dzd.add(zd); |
break ; |
|
case 1 : zd= new Zidan(x+ 10 ,y, 1 ); |
dzd.add(zd); |
break ; |
|
case 2 : zd= new Zidan(x+ 10 ,y, 2 ); |
dzd.add(zd); |
break ; |
|
case 3 : zd= new Zidan(x+ 10 ,y, 3 ); |
dzd.add(zd); |
break ; |
} |
|
Thread t5= new Thread(zd); |
t5.start(); |
} |
} |
|
} |
} |
|
|
} |
|
} |
|
class Zidan implements Runnable |
{ int x,y; |
int fangxiang; |
int speed= 9 ; |
boolean life= 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 (fangxiang) |
{ case 0 : y-=speed; break ; |
case 1 : x-=speed; break ; |
case 2 : y+=speed; break ; |
case 3 : x+=speed; break ; |
} |
|
if (x< 0 ||x> 500 ||y< 0 ||y> 500 ) //子弹出了游戏边界就自动就将生命值设为false |
{ this .life= false ; break ;} |
|
} |
} |
|
} |
初级程序员
by: 一梦三生 发表于:2015-12-28 10:33:26 顶(0) | 踩(0) 回复
import 工具类.ThreadSleep;
提示有错误。。
网友回复
回复尜尜 : 把ThreadSleep().threadsleep(100);方法换成Thread.sleep(100);就好
顶(0) 踩(0) 2015-12-30 17:55:54
永夜极光 : 把ThreadSleep().threadsleep(100);方法换成Thread.sleep(100);就好
顶(0) 踩(0) 2017-06-03 02:29:06
回复评论