日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java坦克大战爆炸效果_Java坦克大战 (五) 之产生敌方坦克和爆炸效果

發布時間:2023/12/31 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java坦克大战爆炸效果_Java坦克大战 (五) 之产生敌方坦克和爆炸效果 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在此小易將坦克大戰這個項目分為幾個版本,以此對J2SE的知識進行回顧和總結,希望這樣也能給剛學完J2SE的小伙伴們一點啟示!

(此版本基本上就可以和電腦對打了,不信把源碼放到你的電腦上就可以馬上開啟坦克大戰之旅哦)

坦克大戰V0.5實現功能:

1、產生一個敵方坦克

2、將敵人坦克擊斃,相應的子彈和坦克都消失

3、添加爆炸效果

4、添加多輛坦克,并能夠打掉敵方坦克

5、讓敵方坦克可以隨機運動,可以打出子彈打掉我方坦克

6、加兩堵墻出來,可以吞沒子彈,擋住敵方坦克

7、敵方坦克相撞不能穿透過去

注意事項:

1、畫一輛敵人的坦克,步驟:加入區別敵我的量good,根據敵我的不同設置不同的顏色更新Tank的構造函數,加入good,TankClient中new 出敵人的坦克并畫出(注意如果新增加了成員變量,就要馬上考慮是否要更改或新增構造方法)

2、將敵人坦克擊斃,分析:一顆子彈擊中敵人坦克,步驟:Missle中加入hitTank(Tank)方法,返回布爾類型;利用碰撞檢測的輔助類Rectangle;為Tank和Missle都加入getRect方法;當擊中敵人坦克時,坦克被打死,子彈也死去;增加控制Tank生死的量live,如果死去就不畫了

3、加入爆炸,步驟:添加爆炸類;用不同直徑的圓模擬爆炸;加入live;加入位置屬性;加入draw方法。爆炸應該存在于集合類中;TankClient加入集合;將集合中的爆炸逐一畫出(如果死去就去除)。擊斃一輛坦克后應產生爆炸;hitTank時應產生爆炸

4、添加多輛坦克,步驟:用容器來裝敵人的Tank;向容器中裝入多輛敵人Tank;畫出來;運行,不能打掉;添加hitTanks方法,打一系列Tank;TankClient里面每發子彈都打tanks

5、讓敵軍坦克更加智能,步驟:

==>讓敵軍坦克動起來:構造函數中可以指定方向;new敵軍坦克的時候指定敵軍坦克的方向。

==>讓敵軍坦克向隨機方向移動:(Tank)靜態的,添加隨機數產生器 java.util.Random;move完成后,如果是敵軍坦克的,隨機產生一個數,來設定坦克下一個方向;Direction.values()。

==>讓敵軍坦克向隨機方向移動隨機的步驟:添加變量,記錄隨機步驟;當==0時,改變方向,否則,只是隨機步驟遞減;

==>讓敵軍坦克發射炮彈:本軍炮彈不打本軍;炮彈添加好壞bGood,根據好壞畫不同顏色;修改炮彈的構造方法;修改Tank的fire方法;修改hitTank方法,好不能打好,壞不能打壞

6、添加兩堵墻,步驟:建Wall類、建立Wall對象、畫出來。

==>讓每一顆子彈打擊每一堵墻:hitWall()方法;注意子彈速度不能太快,否則很容易穿過墻;

==>讓坦克不能穿過墻:記錄上一次的位置oldX, oldY;修改構造函數;每次move之前紀錄上一次位置;添加stay方法;記錄移動前的位置;當撞到時回到移動前的位置;當碰到墻的時候stay

坦克大戰V0.5源代碼:

TankClient類:

import java.awt.*;

import java.awt.event.*;

import java.util.List; //java.awt包中也有個List,所以此處要導包明確

import java.util.ArrayList;

public class TankClient extends Frame {

public static final int GAME_WIDTH = 800;

public static final int GAME_HEIGHT = 600;

Tank myTank = new Tank(350, 450, true, Tank.Direction.STOP, this); //我方坦克

Wall w1 = new Wall(100, 300, 20, 100, this), w2 = new Wall(300, 250, 150, 20, this);

List missiles = new ArrayList(); //定義一個集合來裝子彈

List explodes = new ArrayList();

List tanks = new ArrayList();

Image offScreenImage = null; //定義一個屏幕后的虛擬圖片

@Override

public void paint(Graphics g) {

g.drawString("missiles Count: " + missiles.size(), 10, 50); //用來記錄missiles中子彈的個數

g.drawString("explodes Count: " + explodes.size(), 10, 70);

g.drawString("tanks Count: " + tanks.size(), 10, 90);

for (int i = 0; i < missiles.size(); i++) { //遍歷集合,把其中的子彈畫出來

Missile m = missiles.get(i);

m.hitTanks(tanks);

m.hitTank(myTank);

m.hitWall(w1); //檢測子彈是否撞墻

m.hitWall(w2);

m.drawMissile(g);

}

for (int i = 0; i < explodes.size(); i++) {

Explode e = explodes.get(i);

e.draw(g);

}

for (int i = 0; i < tanks.size(); i++) {

Tank t = tanks.get(i);

t.collidesWithWall(w1); //檢測敵方坦克是否撞墻

t.collidesWithWall(w2);

t.collidesWithTanks(tanks);

t.drawTank(g);

}

myTank.drawTank(g);

w1.draw(g);

w2.draw(g);

}

//利用雙緩沖消除圓圈移動時屏幕的閃動

@Override

public void update(Graphics g) {

if (offScreenImage == null) {

offScreenImage = this.createImage(GAME_WIDTH, GAME_HEIGHT); //判斷是為了避免每次重畫時都給offScreenImage賦值

}

Graphics gOffScreen = offScreenImage.getGraphics(); //定義虛擬圖片上的畫筆gOffScreen

Color c = gOffScreen.getColor();

gOffScreen.setColor(Color.GREEN);

gOffScreen.fillRect(0, 0, GAME_WIDTH, GAME_HEIGHT); //重畫背景,如果沒有這句則在屏幕上會保留圓圈的移動路徑

gOffScreen.setColor(c);

paint(gOffScreen); //把圓圈畫到虛擬圖片上

g.drawImage(offScreenImage, 0, 0, null); //再一次性把虛擬圖片畫到真實屏幕上,在真實屏幕上畫則要用真實屏幕的畫筆g

}

public void luanchFrame() {

for(int i = 0; i < 10; i++) {

tanks.add(new Tank(50 + 40*(i+1), 50, false,Tank.Direction.D, this));

}

this.setLocation(300, 50);

this.setSize(GAME_WIDTH, GAME_HEIGHT);

this.setTitle("坦克大戰 - By:小易 - QQ:381740148");

this.setResizable(false); //不允許改變窗口大小

this.addWindowListener(new WindowAdapter() {

@Override

public void windowClosing(WindowEvent e) {

System.exit(0);

}

}); //添加關閉功能,此處使用匿名類比較合適

this.setBackground(Color.GREEN);

this.addKeyListener(new KeyMonitor());

setVisible(true);

new Thread(new PaintThread()).start(); //啟動線程,實例化線程對象時不要忘了new Thread(Runnable對象);

}

public static void main(String[] args) {

TankClient tc = new TankClient();

tc.luanchFrame();

}

//PaintThread只為TankClient服務,所以寫成內部類好些

public class PaintThread implements Runnable {

public void run() {

while (true) {

repaint(); //repaint()是TankClient或者他的父類的方法,內部類可以訪問外部包裝類的成員,這也是內部類的好處

try {

Thread.sleep(50); //每隔50毫秒重畫一次

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

public class KeyMonitor extends KeyAdapter {

@Override

public void keyReleased(KeyEvent e) {

myTank.keyReleased(e);

}

@Override

public void keyPressed(KeyEvent e) {

myTank.keyPressed(e);

}

}

}

Tank類:

import java.awt.*;

import java.awt.event.*;

import java.util.Random;

public class Tank {

public static final int XSPEED = 5; //定義常量X軸速度

public static final int YSPEED = 5;

public static final int WIDTH = 30;

public static final int HEIGHT = 30;

//定義一個隨機數產生器,此時的Random類是java.util.Random,不同于Math中的

private static Random r = new Random(); //隨機數產生器只需要一個,所以定義成靜態,防止每次new一個坦克是都會產生一個隨機數產生器

private boolean good; //定義變量說明是我方還是敵方坦克,為true表示我方坦克

private boolean live = true; //定義變量說明是坦克是否存活

TankClient tc;

private int x , y; //定義變量畫圓圈(坦克)時四邊形左上點的x、y左邊

private int oldX , oldY; //定義坦克上個位置的坐標

private boolean bL = false, bU = false, bR = false, bD = false; //定義變量左上右下的按鍵是否被按下

enum Direction {L,LU,U,RU,R,RD,D,LD,STOP}; //定義枚舉類型,值為左、左上、上、右上、右、右下、下、左下、停止

private Direction dir = Direction.STOP; //定義變量坦克的方向

private Direction ptDir = Direction.D; //定義變量坦克炮筒的方向,起初向下

private int step = r.nextInt(12) + 3; //定義坦克朝著一個方向移動幾步

public Tank(int x, int y, boolean good) {

this.x = x;

this.y = y;

this.good = good;

this.oldX = x;

this.oldY =y;

}

public Tank(int x, int y, boolean good, Direction dir, TankClient tc) {

this(x, y, good); //相當于調用上面的構造方法

this.dir = dir;

this.tc = tc;

}

public void drawTank(Graphics g) {

if(!live) {

if(!good) {

tc.tanks.remove(this);

}

return; //如果坦克沒有存活就直接返回,不用畫坦克了

}

Color c = g.getColor(); //取得g(以后稱為畫筆)的顏色

if(good) g.setColor(Color.RED);

else g.setColor(Color.BLUE);

g.fillOval(x, y, WIDTH, HEIGHT); //"畫圓",利用填充一個四邊形(四邊形的內切圓),參數分別代表:四邊形左上點的坐標X,Y,寬度,高度

g.setColor(c); //用完畫筆后把畫筆默認的顏色(黑色)設置回去

//根據炮筒的方向,畫直線代表炮筒

switch (ptDir) {

case L:

g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x, y+Tank.HEIGHT/2);

break;

case LU:

g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x, y);

break;

case U:

g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y);

break;

case RU:

g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH, y);

break;

case R:

g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH, y+Tank.HEIGHT/2);

break;

case RD:

g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH, y+Tank.HEIGHT);

break;

case D:

g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x+Tank.WIDTH/2, y+Tank.HEIGHT);

break;

case LD:

g.drawLine(x+Tank.WIDTH/2, y+Tank.HEIGHT/2, x, y+Tank.HEIGHT);

break;

}

move(); //每次按鍵都會重畫,就會調用drawTank,在這里重畫坦克的此時位置

}

public void keyPressed(KeyEvent e) {

int key = e.getKeyCode(); //得到按鍵的虛擬碼,再和下面的KeyEvent.VK_LEFT等虛擬碼比較看是否是某按鍵

switch (key) {

case KeyEvent.VK_LEFT:

bL = true;

break;

case KeyEvent.VK_UP:

bU = true;

break;

case KeyEvent.VK_RIGHT:

bR = true;

break;

case KeyEvent.VK_DOWN:

bD = true;

break;

}

locateDraction();

if (dir != Direction.STOP) {

ptDir = dir;

}

}

public void keyReleased(KeyEvent e) {

int key = e.getKeyCode();

switch (key) {

case KeyEvent.VK_R: //按R就發射子彈調用fire方法

fire(); //只有松開R才能發出子彈

break;

case KeyEvent.VK_LEFT:

bL = false;

break;

case KeyEvent.VK_UP:

bU = false;

break;

case KeyEvent.VK_RIGHT:

bR = false;

break;

case KeyEvent.VK_DOWN:

bD = false;

break;

}

locateDraction();

}

//通過上右下的按鍵是否被按下判斷坦克要運動的方向

void locateDraction() {

if(bL && !bU && !bR && !bD) dir =Direction.L;

else if(bL && bU && !bR && !bD) dir =Direction.LU;

else if(!bL && bU && !bR && !bD) dir =Direction.U;

else if(!bL && bU && bR && !bD) dir =Direction.RU;

else if(!bL && !bU && bR && !bD) dir =Direction.R;

else if(!bL && !bU && bR && bD) dir =Direction.RD;

else if(!bL && !bU && !bR && bD) dir =Direction.D;

else if(bL && !bU && !bR && bD) dir =Direction.LD;

else if(!bL && !bU && !bR && !bD) dir =Direction.STOP;

}

public void move() {

oldX = x;

oldY = y;

switch (dir) {

case L:

x -= XSPEED;

break;

case LU:

x -= XSPEED;

y -= YSPEED;

break;

case U:

y -= YSPEED;

break;

case RU:

x += XSPEED;

y -= YSPEED;

break;

case R:

x += XSPEED;

break;

case RD:

x += XSPEED;

y += YSPEED;

break;

case D:

y += YSPEED;

break;

case LD:

x -= XSPEED;

y += YSPEED;

break;

case STOP:

break;

}

if(this.dir != Direction.STOP) {

this.ptDir = this.dir;

}

//防止坦克出界

if (x < 0) x = 0;

if (y < 25) y = 25; //考慮了標題欄的高度

if (x + Tank.WIDTH > TankClient.GAME_WIDTH) x = TankClient.GAME_WIDTH - Tank.WIDTH;

if (y + Tank.HEIGHT > TankClient.GAME_HEIGHT) y = TankClient.GAME_HEIGHT - Tank.HEIGHT;

if (!good) {

Direction[] dirs = Direction.values(); //把枚舉轉換成數組

if (step == 0) {

int rn = r.nextInt(dirs.length);

dir = dirs[rn]; //如果移動步數為0就改變方向

step = r.nextInt(12) + 3;

}

step --;

if(r.nextInt(40) > 37) this.fire();

}

}

public void stay() {

x = oldX;

y = oldY;

}

//坦克開火,就new一個子彈出來

private Missile fire() {

if(!live) return null;

int x = this.x + Tank.WIDTH/2 - Missile.WIDTH/2; //讓子彈從坦克中心打出

int y = this.y + Tank.HEIGHT/2 - Missile.HEIGHT/2;

Missile m = new Missile(x, y,good, ptDir , this.tc);

tc.missiles.add(m); //每new一個Missile對象就把他裝到集合中

return m; //返回的m,其他地方可調用可不調用

}

public Rectangle getRect() {

return new Rectangle(x, y, WIDTH, HEIGHT); //得到坦克的探測方塊,Rectangle是java.awt包中專門用于游戲碰撞的類

}

public boolean isLive() {

return live;

}

//Tank類的成員方法可生成對應的get和set方法,那么在其他類中就可以訪問了

public void setLive(boolean live) {

this.live = live;

}

public boolean isGood() {

return good;

}

//檢測坦克是否撞墻

public boolean collidesWithWall(Wall w) {

if(this.live && this.getRect().intersects(w.getRect())) {

stay(); //如果坦克撞到墻就讓他回到上一個位置

return true;

}

return false;

}

//檢測坦克是否相撞,java.util.List接口或者類的另一種寫法,java.awt中也有List,所以要寫明確

public boolean collidesWithTanks(java.util.List tanks) {

for (int i = 0; i < tanks.size(); i++) {

Tank t = tanks.get(i);

if (this != t) {

if(this.live && t.isLive() && this.getRect().intersects(t.getRect())) {

this.stay();

t.stay();

return true;

}

}

}

return false;

}

}

Missile類:

import java.awt.*;

import java.util.List;

public class Missile {

public static final int XSPEED = 10;

public static final int YSPEED = 10;

public static final int WIDTH = 10;

public static final int HEIGHT = 10;

int x, y;

Tank.Direction dir;

private boolean good; //定義變量表示是否是我方子彈

private boolean live = true; //定義一個判斷子彈是否出界的變量

private TankClient tc;

public Missile(int x, int y, Tank.Direction dir) {

this.x = x;

this.y = y;

this.dir = dir;

}

public Missile(int x, int y,boolean good, Tank.Direction dir, TankClient tc) {

this(x, y, dir);

this.good = good;

this.tc = tc;

}

public void drawMissile(Graphics g) {

if(!live) {

tc.missiles.remove(this);

return;

}

Color c = g.getColor();

g.setColor(Color.BLACK);

g.fillOval(x, y, WIDTH, HEIGHT);

g.setColor(c);

move();

}

private void move() {

switch (dir) {

case L:

x -= XSPEED;

break;

case LU:

x -= XSPEED;

y -= YSPEED;

break;

case U:

y -= YSPEED;

break;

case RU:

x += XSPEED;

y -= YSPEED;

break;

case R:

x += XSPEED;

break;

case RD:

x += XSPEED;

y += YSPEED;

break;

case D:

y += YSPEED;

break;

case LD:

x -= XSPEED;

y += YSPEED;

break;

}

if (x < 0 || y < 0 || x > tc.GAME_WIDTH || y > tc.GAME_HEIGHT) {

live = false;

}

}

public boolean isLive() {

return live;

}

public Rectangle getRect() {

return new Rectangle(x, y, WIDTH, HEIGHT); //得到子彈的探測方塊,Rectangle是java.awt包中專門用于游戲碰撞的類

}

//判斷子彈是否打到了坦克

public boolean hitTank(Tank t) {

//intersects是Rectangle的一個方法;t.isLive()是為了判斷坦克是否存活,如果沒有則打掉這個坦克后,之后的子彈到達原來這個坦克的位置就會消失

if (this.live && this.getRect().intersects(t.getRect()) && t.isLive() && this.good != t.isGood()) {

t.setLive(false);

this.live = false;

Explode e = new Explode(x, y, tc);

tc.explodes.add(e);

return true;

}

return false;

}

public boolean hitTanks(List tanks) {

for (int i = 0; i < tanks.size(); i++) {

if (hitTank(tanks.get(i))) {

return true;

}

}

return false;

}

public boolean hitWall(Wall w) {

if(this.live && this.getRect().intersects(w.getRect())) {

this.live = false;

return true;

}

return false;

}

}

Explode類:

import java.awt.*;

//爆炸類(爆炸的英文:explode)

public class Explode {

int x, y;

private TankClient tc;

private boolean live = true;

int[] diameter = {4, 10, 20, 36, 56, 24, 12, 6}; //定義畫不同直徑的圓表示爆炸(直徑的英文:diameter)

int step = 0; //定義變量代表畫爆炸的圓畫到第幾個了

public Explode(int x, int y, TankClient tc) {

this.x = x;

this.y = y;

this.tc = tc;

}

public void draw(Graphics g) {

if(!live) {

tc.explodes.remove(this);

return;

}

if (step == diameter.length) {

live = false;

step = 0;

return;

}

Color c = g.getColor();

g.setColor(Color.ORANGE);

g.fillOval(x, y, diameter[step], diameter[step]);

g.setColor(c);

step ++ ;

}

}

Wall類:

import java.awt.*;

public class Wall {

private int x, y, w, h;

private TankClient tc;

public Wall(int x, int y, int w, int h, TankClient tc) {

this.x = x;

this.y = y;

this.w = w;

this.h = h;

this.tc = tc;

}

public void draw(Graphics g) {

g.fillRect(x, y, w, h);

}

public Rectangle getRect() {

return new Rectangle(x, y, w, h);

}

}

知識點回顧:

1、碰撞檢測的輔助類Rectangle,屬于java.awt.Rectangle中,用法:

==>首先獲取兩個要檢測物體的邊界,相當于一個Rectangle對象,可以給他們定義相應的getRect()方法,返回值為一個Rectangle對象,在函數內return

new Rectangle(x, y, w, h);

==>定義一個方法判斷是否碰撞到了,返回值為boolean,物體1.getRect().intersects(物體2.getRect())的返回值也是一個boolean類型,返回真則表示碰撞到了,再執行相應的功能,反之亦然。

2、將枚舉轉換成數組:枚舉名.values(),返回的是相應的數組。如:Direction[] dirs = Direction.values();返回的是Direction類型的數組

3、隨機數的使用:

==>java.util.Random比較方便,可以直接產生隨機整數,使用時先定義一個隨機數產生器,如:定義隨機數產生器:Random

r = new Random(); 產生隨機數整數:r.nextInt(12)表示產生一個0-11的隨機整數

==>math.random()產生的是一個0-1的數,使用時一般要通過計算轉換,比較麻煩

總結

以上是生活随笔為你收集整理的java坦克大战爆炸效果_Java坦克大战 (五) 之产生敌方坦克和爆炸效果的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。