寫這個游戲已經有一段時間了,一直在實現各種新功能,從最開始的地圖上只有坦克,發子彈還是一個大問題到現在可以兩個人一起玩,還是花了不少心思的,現在坦克的速度更快,電腦坦克也不會撞牆.雖然游戲性沒有經典坦克大戰那麼強,但是還是可以用來休閒娛樂一下,這個用了很多最近學到的新知識,模仿俄羅斯方塊,還有一些小技巧,比如可以同時按觸發多個按鍵事件,對子彈的處理等.
左邊的坦克用W D S A控制移動,H發射子彈,每次最多出現5顆子彈,右邊的坦克用上下左右箭頭控制移動,L鍵發射子彈,互不干擾.Q鍵可以直接退出游戲,游戲結束後按Y鍵可以繼續游戲.為了結構清晰游戲分為Mywar Shoot Tanks 3個類.
(第二次用插入代碼,之前一直都不懂這功能,我奧特蛋了 (*^__^*) 嘻嘻……)
/********************MyWar類***********************/
package tank;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Arrays;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JFrame;
import javax.swing.JPanel;
public class MyWar{
public static void main(String[] args) {
JFrame frame = new JFrame("坦克大戰");//新建一個窗口
War war = new War();//創建一個War類的對象
frame.add(war);//把war添加到窗口中
frame.setSize(750,530);//窗口寬高
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//關閉時結束進程
frame.setLocationRelativeTo(null);//使窗口居中
frame.setVisible(true);//這句是干啥的?
war.action();//啟動(war)戰斗,親,可以游戲了!
}
}
class War extends JPanel{
private boolean sUp,sDown,sRight,sLeft,sH;//定義右邊坦克按鍵的開關
private boolean sW,sD,sS,sA,sL;//定義左邊坦克按鍵的開關
public static final int WIDTH=750;//定義地圖寬度
public static final int HEIGHT=530;//定義地圖高度
private int score;//設置分數
private boolean gameOver;//gameover=false表示游戲沒有結束
private Timer timer;//剛學的東西
private int shootNum,shootNum1;//可以射擊的子彈數,防止作弊
MyTank[] myTank=new MyTank[2];//定義一個我方坦克對象數組
EnemyTanks[] enemyTank=new EnemyTanks[5];//初始化敵人坦克的數量
EnemyTanks newEnemyTank;//用來產生一輛敵人的坦克,補充死去的T_T
Random r = new Random();
/**用於產生一輛新的敵人坦克,返回參數是EnemyTanks類型*/
public EnemyTanks nextTank(){
int x = r.nextInt(2)*WIDTH;//隨機x的值,坦克出生在角落
int y=r.nextInt(2)*HEIGHT;//隨機y的值,坦克出生在角落
int step=r.nextInt(4)+1;//速度
int direct=r.nextInt(4)+1;//方向
int who = r.nextInt(3)+1;//誰?
newEnemyTank=new EnemyTanks(x,y,step,direct,who,true);
return newEnemyTank;//返回一個新坦克
}
public void action(){
startGame();//開始游戲函數
KeyAdapter l = new KeyAdapter(){//鍵盤監聽
public void keyPressed(KeyEvent e){
int key = e.getKeyCode();
if(key==KeyEvent.VK_Q){
System.exit(0);//Q關閉進程結束游戲
}
if(gameOver){
if(key==KeyEvent.VK_Y){
startGame();//Y鍵開始游戲
}
return;
}
switch(key){
case KeyEvent.VK_W:sW=true;break;
case KeyEvent.VK_A:sA=true;break;
case KeyEvent.VK_D:sD=true;break;
case KeyEvent.VK_S:sS=true;break;
case KeyEvent.VK_L:sL=true;break;
case KeyEvent.VK_RIGHT:sRight=true;break;
case KeyEvent.VK_LEFT:sLeft=true;break;
case KeyEvent.VK_DOWN:sDown=true;break;
case KeyEvent.VK_UP:sUp=true;break;
case KeyEvent.VK_H:sH=true;break;
}
repaint();
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
switch(key){
case KeyEvent.VK_W:sW=false;break;
case KeyEvent.VK_A:sA=false;break;
case KeyEvent.VK_D:sD=false;break;
case KeyEvent.VK_S:sS=false;break;
case KeyEvent.VK_H:sH=false;break;
case KeyEvent.VK_RIGHT:sRight=false;break;
case KeyEvent.VK_LEFT:sLeft=false;break;
case KeyEvent.VK_DOWN:sDown=false;break;
case KeyEvent.VK_UP:sUp=false;break;
case KeyEvent.VK_L:sL=false;break;
}
}
};
this.requestFocus();
this.addKeyListener(l);
}
public void level(){//每5分增加一輛敵人的坦克
int length = score/5+5;
if(length>enemyTank.length){
enemyTank=Arrays.copyOf(enemyTank,enemyTank.length+1);//坦克數組擴容
enemyTank[enemyTank.length-1]=nextTank();//初始化數組最後的一輛坦克
enemyTank[enemyTank.length-1].start();//啟動這個坦克的線程
}
}
public void startGame(){
cleanShoot();//清空子彈
shootNum=5;//可以發射的子彈數為5
shootNum1=5;
score=0;
myTank[0]= new MyTank(550,370,4,1,-1,true);//初始化我的坦克
myTank[1]= new MyTank(100,100,4,1,0,true);
for (int i = 0; i < enemyTank.length; i++) {//初始化敵人的坦克
if(gameOver){//游戲結束,關閉每個坦克的線程
enemyTank[i].s=false;
}
}
enemyTank=new EnemyTanks[5];
for (int i = 0; i < enemyTank.length; i++) {//初始化敵人的坦克
enemyTank[i]=nextTank();
}
gameOver=false;//游戲沒有結束,表示開始
myTank[0].start();//啟動我的坦克線程
myTank[1].start();
for (int i = 0; i < enemyTank.length; i++) {//啟動敵人坦克線程
enemyTank[i].start();
}
timer = new Timer();//匿名內部類Timer
timer.schedule(new TimerTask(){
public void run(){//重寫run()函數
repaint();
shootAndRun();
}
}, 0,50);//50毫秒執行一次
}
/**檢查游戲是否結束*/
public void checkGameOver(){//模仿俄羅斯方塊裡面寫的
if(myTank[0].isLive()||myTank[1].isLive()){
return;
}
gameOver = true;
timer.cancel();
repaint();
}
public void shootAndRun(){
if(sW){//如果開關sW=true就執行{}裡面的代碼
myTank[1].moveUp();
}else if(sD){
myTank[1].moveRight();
}else if(sS){
myTank[1].moveDown();
}else if(sA){
myTank[1].moveLeft();
}if(sH&&myTank[1].isLive()){//如果sL=true並且坦克是活的,就執行
if(shootNum1>=0){//如果允許的子彈數小於於0了,不執行
myTank[1].shoot();
shootNum1--;//控制子彈數量,射擊一次,子彈減少,消失加1
}
}
if(sUp){
myTank[0].moveUp();
}else if(sRight){
myTank[0].moveRight();
}else if(sLeft){
myTank[0].moveLeft();
}else if(sDown){
myTank[0].moveDown();
}if(sL&&myTank[0].isLive()){
if(shootNum>=0){
myTank[0].shoot();
shootNum--;//控制子彈數量,射擊一次,子彈減少,消失加1
}
}
}
public void paint(Graphics g){
g.setColor(Color.white);
g.fillRect(0, 0, this.getWidth(), this.getHeight());//畫背景
paintWall(g);//畫牆
//畫我的坦克
paintTank(myTank[1].getX(),myTank[1].getY(),g,myTank[1].getDirect(),myTank[1].getWho(),myTank[1].isLive());
paintTank(myTank[0].getX(),myTank[0].getY(),g,myTank[0].getDirect(),myTank[0].getWho(),myTank[0].isLive());
for (int i = 0; i < enemyTank.length; i++) {//畫敵人的坦克
paintTank(enemyTank[i].getX(),enemyTank[i].getY(),g,enemyTank[i].getDirect(),enemyTank[i].getWho(),enemyTank[i].isLive());
}
paintShoot(g);//畫我射擊的子彈
paintEemyShoot(g);//畫敵人發出的子彈
paintScore(g);//畫分數,及字符
//paintMap(g);
}
/* public void paintMap(Graphics g){//這是個方法可以生成漂亮的東西
for (int j = 0; j < 3; j++) {
Random color=new Random(); //通過Random生成隨機顏色
int r = color.nextInt(256);
int g1 = color.nextInt(256);
int b = color.nextInt(256);
g.setColor(new Color(r, g1, b));
g.fillOval(color.nextInt(750), color.nextInt(530), 5, 5);
}
}*/
public void paintScore(Graphics g){//畫字符相關的
g.setColor(Color.lightGray);
Font f = getFont();
Font font = new Font(f.getName(),Font.BOLD,0x1e);
int x = 130;
int y = 275;
String str = "SCORE:"+this.score;
g.setFont(font);
g.drawString(str, x, y);
str="TANK:"+enemyTank.length ;
x+=170;
g.drawString(str, x, y);
x+=140;
str = "[Q]Quit!";
if(gameOver){
str = "[Y]Start!";
}
g.drawString(str, x, y);
}
public void paintWall(Graphics g){//畫中間的柱子
g.setColor(Color.LIGHT_GRAY);
g.fill3DRect(WIDTH/2-45,150 , 40, HEIGHT-300, false);
g.fill3DRect(130,HEIGHT/2-20 , WIDTH-300, 40, false);
}
/**畫自己坦克子彈,同時判斷子彈有沒有擊中敵人*/
public void paintShoot(Graphics g){
ShootDispeal();
for (int i = 0; i < Shoot.myShoot.length; i+=4) {
if(Shoot.myShoot[i]==0&&Shoot.myShoot[i+1]==0){
continue;
}
g.setColor(Color.RED);
g.fillOval(Shoot.myShoot[i], Shoot.myShoot[i+1], 10, 10);
int x = Shoot.myShoot[i];
int y = Shoot.myShoot[i+1];
for (int j = 0; j < enemyTank.length; j++) {
int ex = enemyTank[j].getX();
int ey = enemyTank[j].getY();
if(x>ex&&x<ex+40&&y>ey&&y<ey+40){
score+=1;
level();
enemyTank[j].s=false;//坦克死亡,線程關閉
enemyTank[j]=nextTank();
enemyTank[j].start();
Shoot.myShoot[i]=0;Shoot.myShoot[i+1]=0;//子彈消失
Shoot.myShoot[i+2]=0;Shoot.myShoot[i+3]=0;
shootNum++;
shootNum1++;
}
}
Shoot.myShoot[i]+=Shoot.myShoot[i+2];
Shoot.myShoot[i+1]+=Shoot.myShoot[i+3];
}
}
/**畫敵人發出的子彈,同時判斷是否擊中了我的坦克*/
public void paintEemyShoot(Graphics g){
ShootDispeal();
for (int i = 0; i < Shoot.enemyShoot.length; i+=4) {
if(Shoot.enemyShoot[i]==0&&Shoot.enemyShoot[i+1]==0){
continue;
}
g.setColor(Color.blue);
g.fillOval(Shoot.enemyShoot[i], Shoot.enemyShoot[i+1], 10, 10);
int x = Shoot.enemyShoot[i];
int y = Shoot.enemyShoot[i+1];
int mx = myTank[0].getX();
int my = myTank[0].getY();
int mx1 = myTank[1].getX();
int my1 = myTank[1].getY();
if(x>mx&&x<mx+40&&y>my&&y<my+40){
myTank[0].setLive(false);
checkGameOver();
}
if(x>mx1&&x<mx1+40&&y>my1&&y<my1+40){
myTank[1].setLive(false);
checkGameOver();
}
Shoot.enemyShoot[i]+=Shoot.enemyShoot[i+2];//根據步伐,改變子彈的坐標
Shoot.enemyShoot[i+1]+=Shoot.enemyShoot[i+3];
}
}
/**畫坦克*/
public void paintTank(int x,int y,Graphics g,int direct,int who,boolean isLive){
Color color = null;//設置顏色
if(isLive){
if(who==0){//我的坦克
color=Color.green;
}else if(who==-1){
color=Color.yellow;
}else if(who==1){//1,2,3敵人的坦克,3種顏色
color=Color.red;
}else if(who==2){
color=Color.magenta;
}else if(who==3){
color=Color.CYAN;
}
switch(direct){//根據方向畫出不同方向的坦克
case 1:g.setColor(color);paintUpTank(x,y,g);break;
case 2:g.setColor(color);paintRightTank(x,y,g);break;
case 3:g.setColor(color);paintDownTank(x,y,g);break;
case 4:g.setColor(color);paintLeftTank(x,y,g);break;
}
}
}
/**純畫圖打造坦克*/
public void paintUpTank(int x,int y,Graphics g){
g.fill3DRect(x, y, 15, 50, false);
g.fill3DRect(x+35, y, 15, 50, false);
g.fill3DRect(x+15, y+10, 20, 30, false);
g.setColor(Color.black);
g.fill3DRect(x+23, y-10, 5, 33, false);
g.setColor(Color.yellow);
g.fillOval(x+20, y+18, 10, 10);
}
public void paintLeftTank(int x,int y,Graphics g){
g.fill3DRect(x, y, 50, 15, false);
g.fill3DRect(x, y+35, 50, 15, false);
g.fill3DRect(x+10, y+15, 30, 20, false);
g.setColor(Color.black);
g.fill3DRect(x-10, y+22, 33, 5, false);
g.setColor(Color.yellow);
g.fillOval(x+20, y+18, 10, 10);
}
public void paintDownTank(int x,int y,Graphics g){
g.fill3DRect(x, y, 15, 50, false);
g.fill3DRect(x+35, y, 15, 50, false);
g.fill3DRect(x+15, y+10, 20, 30, false);
g.setColor(Color.black);
g.fill3DRect(x+23, y+25, 5, 33, false);
g.setColor(Color.yellow);
g.fillOval(x+20, y+18, 10, 10);
}
public void paintRightTank(int x,int y,Graphics g){
g.fill3DRect(x, y, 50, 15, false);
g.fill3DRect(x, y+35, 50, 15, false);
g.fill3DRect(x+10, y+15, 30, 20, false);
g.setColor(Color.black);
g.fill3DRect(x+23, y+22, 33, 5, false);
g.setColor(Color.yellow);
g.fillOval(x+20, y+18, 10, 10);
}
/**重新開始游戲的時候會清空子彈數組裡面的數據*/
public void cleanShoot(){
for (int i = 0; i < Shoot.enemyShoot.length; i++) {
Shoot.enemyShoot[i]=0;
}
for (int i = 0; i < Shoot.myShoot.length; i++) {
Shoot.myShoot[i]=0;
}
}
/**子彈消失了*/
public void ShootDispeal(){
for (int i = 0; i < Shoot.myShoot.length; i+=4) {//撞到邊緣
if(Shoot.myShoot[i]<0||Shoot.myShoot[i]>WIDTH||Shoot.myShoot[i+1]<0||Shoot.myShoot[i+1]>HEIGHT){
Shoot.myShoot[i]=0;Shoot.myShoot[i+1]=0;
Shoot.myShoot[i+2]=0;Shoot.myShoot[i+3]=0;
shootNum++;
shootNum1++;
}
int x=Shoot.myShoot[i];
int y=Shoot.myShoot[i+1];
//撞到柱子
if((x>330&&x<360&&y>150&&y<380)||(x>130&&x<570&&y>240&&y<280)){
Shoot.myShoot[i]=0;Shoot.myShoot[i+1]=0;
Shoot.myShoot[i+2]=0;Shoot.myShoot[i+3]=0;
shootNum++;
shootNum1++;
}
}
for (int i = 0; i < Shoot.enemyShoot.length; i+=4) {//撞到邊緣
if(Shoot.enemyShoot[i]<0||Shoot.enemyShoot[i]>WIDTH||Shoot.enemyShoot[i+1]<0||Shoot.enemyShoot[i+1]>HEIGHT){
Shoot.enemyShoot[i]=0;Shoot.enemyShoot[i+1]=0;
Shoot.enemyShoot[i+2]=0;Shoot.enemyShoot[i+3]=0;
}
int x=Shoot.enemyShoot[i];
int y=Shoot.enemyShoot[i+1];
//撞到柱子
if((x>330&&x<360&&y>150&&y<380)||(x>130&&x<570&&y>240&&y<280)){
Shoot.enemyShoot[i]=0;Shoot.enemyShoot[i+1]=0;
Shoot.enemyShoot[i+2]=0;Shoot.enemyShoot[i+3]=0;
}
}
}
}
/********************Tanks類***********************/
package tank;
import java.util.Random;
/**坦克父類,繼承了線程*/
public class Tanks extends Thread{
private int x;//坦克坐標x
private int y;//坦克坐標y
private int step;//坦克的速度
private int direct;//方向,1表示向上,2表示向右,3表示向下,4表示向左
private int who;//坦克標識,0和-1表示自己的坦克,1,2,3表示敵人的坦克,顏色隨機.
private boolean isLive = true;//判斷坦克是否死亡
Shoot shoot;//shoot坦克的射擊
public Tanks(int x, int y, int step, int direct,int who ,boolean isLive) {
super();
this.x = x;
this.y = y;
this.step = step+2;
this.direct = direct;
this.who = who;
this.isLive = isLive;
}
public boolean canMove(){//boolean返回值類型.判斷坦克是否能移動,比如撞牆了.
if(x<0){
x=0;
return false;
}else if(x>690){
x=690;
return false;
}else if(y<0){
y=0;
return false;
}else if(y>450){
y=450;
return false;
}else if(x>270&&x<370&&y>100&&y<380){//撞到豎著的柱子
if(x-270<20){
x=270;
}else{
x=370;
}
return false;
}else if(x>85&&x<570&&y>195&&y<290){//撞到橫著的柱子
if(y-195<10){
y=190;
}else{
y=290;
}
return false;
}
return true;
}
public void moveUp(){//坦克向上移動一步
if(canMove()){
y-=step;
direct=1;
}
}
public void moveDown(){//坦克向下移動一步
if(canMove()){
y+=step;
direct=3;
}
}
public void moveLeft(){//坦克向左移動一步
if(canMove()){
x-=step;
direct=4;
}
}
public void moveRight(){//坦克向右移動一步
if(canMove()){
x+=step;
direct=2;
}
}
public void shoot(){//每次射擊調用此函數
shoot = new Shoot(x,y,direct,step,who);
}
public String toString() {//用於調試
return "Tanks [direct=" + direct + ", isLive="
+ isLive + ", step=" + step + ", x=" + x + ", y=" + y + "]";
}
/**以下是get() set()函數*/
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 getStep() {
return step;
}
public void setStep(int step) {
this.step = step;
}
public int getDirect() {
return direct;
}
public void setDirect(int direct) {
this.direct = direct;
}
public boolean isLive() {
return isLive;
}
public void setLive(boolean isLive) {
this.isLive = isLive;
}
public void setWho(int who) {
this.who = who;
}
public int getWho() {
return who;
}
}
class MyTank extends Tanks{//我的坦克繼承了Tanks
public MyTank(int x, int y, int step, int direct, int who ,boolean isLive) {
super(x, y, step, direct, who, isLive);
}
}
class EnemyTanks extends Tanks{//敵人的坦克繼承了tanks,也繼承了父類的線程
private int time = 500;//線程占用時間500毫秒
boolean s=true;//定義一個boolean的開關,坦克死亡,關閉開關,線程死亡.
public EnemyTanks(int x, int y, int step, int direct, int who, boolean isLive) {
super(x, y, step, direct, who,isLive);
}
public void move(){//敵人的坦克自己移動
Random r = new Random();
int random = r.nextInt(50);
int r1=r.nextInt(4);
if(!(r1==0)){//如果r1=0,就射擊一次
shoot();
}
for (int i = 0; i < random; i++) {//random表示坦克的一次隨機移動的距離
try {
Thread.sleep(50);//線程sleep,移動使移動看起來自然一點
} catch (InterruptedException e) {
e.printStackTrace();
}
if(r1==0){//根據r1的值判斷,此次移動往那個方向
if(this.getY()==0||this.getY()==290){
r1=3;
}else{
moveUp();
}
}else if(r1==1){
if(this.getX()==690||this.getX()==270){
r1=2;
}else{
moveRight();
}
}else if(r1==2){
if(this.getX()==0||this.getX()==370){
r1=1;
}else{
moveLeft();
}
}else if(r1==3){
if(this.getY()==450||this.getY()==190){
r1=0;
}else{
moveDown();
}
}
}
}
public void run(){//繼承線程功能,必須實現run()函數
while(s){//s=true表示坦克沒有死亡.s=false跳出死循環,坦克死亡
move();
try {
Thread.sleep(time);//每次線程占用時間500毫秒
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
/********************Shoot類***********************/
package tank;
/**Shoot類,處理坦克的射擊*/
public class Shoot {
static int[] myShoot = new int[40];//我的坦克子彈放在數組裡面
static int[] enemyShoot = new int[100];//所有敵人共享這個數組
private int direct;//坦克的方向
private int who;//是敵人的坦克?還是自己的坦克
private int x1;//根據情況調整後子彈x的坐標
private int y1;//根據情況調整後子彈y的坐標
private int stepx;//子彈在x軸上移動的速度
private int stepy;//子彈在y軸上移動的速度
private int speed;//坦克的速度
static int indexMy=0;//我的子彈索引,數組滿了之後indexMy=0;每次加4
static int indexEnemy=0;//敵人子彈索引,數組滿了之後indexEnemy=0;每次加4
public Shoot(int x,int y,int direct,int step,int who){
speed=step+8;//根據坦克的速度,設定子彈的速度
this.direct=direct;
this.who=who;
if(direct==1){//if else用來調整子彈射擊出去的位置
x1=x+20;
y1=y;
stepx=0;
stepy=-speed;
}else if(direct==2){
x1=x+40;
y1=y+20;
stepx=speed;
stepy=0;
}else if(direct==3){
x1=x+20;
y1=y+40;
stepx=0;
stepy=speed;
}else if(direct==4){
x1=x;
y1=y+20;
stepx=-speed;
stepy=0;
}
if(indexEnemy==enemyShoot.length-4){//表示數組滿了
indexEnemy=0;
}if(indexMy==myShoot.length-4){//表示數組滿了
indexMy=0;
}
if(who==1||who==2||who==3){//敵人的坦克
enemyShoot[indexEnemy]=x1;//子彈的坐標x
enemyShoot[indexEnemy+1]=y1;//子彈的坐標y
enemyShoot[indexEnemy+2]=stepx;//子彈在x軸移動的步伐
enemyShoot[indexEnemy+3]=stepy;//在t軸移動的步伐
indexEnemy+=4;
}else if(who==0||who==-1){//我的坦克
myShoot[indexMy]=x1;
myShoot[indexMy+1]=y1;
myShoot[indexMy+2]=stepx;
myShoot[indexMy+3]=stepy;
indexMy+=4;
}
}
}