FC版BattleCity(坦克大战)的Java实现!!!!!(一)

博主在五一假期尝试使用Java实现FC经典游戏BattleCity,首先搭建程序框架,包括主程序和主游戏类,采用双缓冲技术进行画面更新。游戏包含坦克的动画效果和两种类型。另外,创建了一个独立的数据处理类进行状态判断和AI计算。目前实现了游戏启动画面、坦克选择和键盘事件响应,未来挑战包括键盘控制、敌人AI、地图读取、战场初始化和音频处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

五一放假呆着没事儿,于是乎打算把battlecity用java写出来,实践一下<java游戏编程 >。

看了看第一章线程,第二章二维图形与动画和第三章交互性与用户界面,差不多了,开始做了!!!

一.大体程序框架先弄出来

主程序-啥也没写-只是初始化游戏类-估计以后会吧什么配置文件相关的东西写进来。

/**
 * 
@author WS
 * @created at 2006-5-3 20:49:39
 
*/


public   class  Tank  {

    
/**
     * 
@param args
     
*/

    
public static void main(String[] args) throws Exception {
        
// System.out.println("Fuck!");
        Tank tank = new Tank();
        tank.start();
    }


    
public void start() throws Exception {
        MainFrame mf 
= new MainFrame("Tank");
        mf.Start();
    }

}

主函数生成主程序类,由主类生成游戏类,够罗嗦的~~

二.凭想像写出主游戏类,以后随着做还会改,没有设计模式,全在一个类里写了。这是一个主线程。

import  java.awt.Color;
import  java.awt.Graphics;
import  java.awt.Graphics2D;
import  java.awt.Image;
import  java.awt.Toolkit;
import  java.awt.event.KeyEvent;
import  java.awt.event.KeyListener;
import  java.awt.event.WindowAdapter;
import  java.awt.event.WindowEvent;
import  java.awt.image.BufferStrategy;

import  javax.swing.ImageIcon;
import  javax.swing.JFrame;

/**
 * 
@author WS
 * @created at 2006-5-3 21:03:20
 
*/


public   class  MainFrame  extends  JFrame  implements  KeyListener  {

    
/* 开始从下网上番的大图片 */
    
private Image startImage;

    
/* 游戏坦克状态1 */
    
private Image tankImage1;

    
/* 游戏坦克状态2 */
    
private Image tankImage2;

    
/* 0-1 */
    
public int tankStatus = 0;

    
/* 无敌状态的白框1 */
    
private Image super1;

    
/* 无敌状态的白框2 */
    
private Image super2;

    
private Image tankBoom1;

    
private Image tankBoom2;

    
private Image tankBoom3;

    
private Image tankBoom4;

    
private Image tankBoom5;

    
private Image tankBoom6;

    
private Image enemyOne1;

    
private Image enemyOne2;

    
private Image enemyBig1;

    
private Image enemyBig2;

    
private Image wall;

    
private int tankX = 140;

    
private int tankY = 265;

    
/* Frames状态机 0-开始 1-选择 2-开始显示level 3-游戏中 4-Win 5-地图编辑 …… */
    
public int frames = 0;

    
public boolean gameRunning = true;

    
public int startY = 466;

    
/* 0-单人游戏 1-双人游戏 3-地图编辑 */
    
public int selectGame = 0;

    
public MainFrame(String title) {
        
super(title);
        loadImages();
        initFrame();
        Thread engine 
= new OperatorThread(this);
        engine.start();
        
this.addWindowListener(new WindowAdapter() {
            
public void windowClosing(WindowEvent e) {
                System.exit(
0);
            }

        }
);
    }


    
private void initFrame() {
        setSize(
512466);
        setVisible(
true);
        setBackground(Color.BLACK);
        createBufferStrategy(
2);
        addKeyListener(
this);
    }


    
private void loadImages() {
        startImage 
= loadImage("D:/eclipse/workspace/Tank/bin/start.gif");
        tankImage1 
= loadImage("D:/eclipse/workspace/Tank/bin/tank1.gif");
        tankImage2 
= loadImage("D:/eclipse/workspace/Tank/bin/tank2.gif");
        
if (startImage == null{
            System.out.println(
"Null");
        }

    }


    
private Image loadImage(String fileName) {
        
return new ImageIcon(fileName).getImage();
    }


    
public Graphics2D getDoubleGraphics() {
        BufferStrategy strategy 
= this.getBufferStrategy();
        
return (Graphics2D) strategy.getDrawGraphics();
    }


    
private void update() {
        BufferStrategy strategy 
= this.getBufferStrategy();
        
if (!strategy.contentsLost()) {
            strategy.show();
        }

        Toolkit.getDefaultToolkit().sync();
    }


    
private long fresh = 100;

    
// 0-开始 1-选择 2-开始显示level 3-游戏中 4-Win 5-地图编辑
    public void Start() throws Exception {
        
long startTime;
        
long tmp = 0;
        
while (gameRunning) {
            startTime 
= System.currentTimeMillis();
            repaint();
            tmp 
= System.currentTimeMillis() - startTime;
            
// System.out.println(fresh - tmp);
            Thread.sleep((fresh - tmp) < 0 ? 0 : tmp);
        }

    }


    
private void drawTank(Graphics2D g2, int direct, int posX, int posY,
            
int tankStatus) throws Exception {
        g2.drawImage(startImage, 
0, startY, null);
        
if (tankStatus == 0{
            g2.drawImage(tankImage1, posX, posY, 
null);
        }
 else {
            g2.drawImage(tankImage2, posX, posY, 
null);
        }

    }


    
public void paint(Graphics g) {
        
try {
            
switch (frames) {
            
case 0:
                getDoubleGraphics().drawImage(startImage, 
0, startY, null);
                update();
                
break;
            
case 1:
                drawTank(getDoubleGraphics(), 
4, tankX, tankY, tankStatus);
                update();
                
break;
            
case 2:
                
break;
            
case 3:
                
break;
            
case 4:
                
break;
            
case 5:
                
break;
            
case 6:
                
break;
            }

        }
 catch (Exception e) {

        }

    }


    
public void keyPressed(KeyEvent e) {
        System.out.println(
"Key:" + e.getKeyCode());
        
switch (e.getKeyCode()) {
        
case KeyEvent.VK_G:
            selectGame
++;
            
if (selectGame == 3{
                selectGame 
= 0;
            }

            
if (selectGame == 0{
                tankY 
= 265;
            }
 else if (selectGame == 1{
                tankY 
= 297;
            }
 else if (selectGame == 2{
                tankY 
= 330;
            }


        }

    }


    
public void keyReleased(KeyEvent e) {

    }


    
public void keyTyped(KeyEvent e) {

    }

}

类继承JFrame类,实现KeyListener接口。直接在Frame的Content里画。

createBufferStrategy(2);为Frame建立双缓冲及分页控制类BufferStrategy,一共2个缓冲页面。

三个图片分别是程序启动,从下网上移动的游戏名称等,直接从FC模拟器上截图下来,存为Gif,由于省事,就不一块一块分割了,分割的话最后运行jar文件会小很多。(图1)

 

(图1)

坦克共分2种外形,链条不一样,两种交替产生运动的感觉。(图2)

(图2)

三.数据处理类,数据和数据的处理分开写了,不知道合不合理,写写再说。这是一个单独的线程,不断判断状态,进行数据调整和AI的计算,另主游戏类的线程主要用来不断刷新屏幕,根据处理类处理的数据来画屏幕。

public   class  OperatorThread  extends  Thread  {
    
private MainFrame mainFrame = null;

    
public OperatorThread(MainFrame mainFrame) {
        
this.mainFrame = mainFrame;
    }


    
public void run() {
        
try {
            
while (mainFrame.gameRunning) {
                
switch (mainFrame.frames) {
                
case 0:
                    
for (int i = 0; i < 446; i++{
                        mainFrame.startY
--;
                        Thread.sleep(
10);
                    }

                    mainFrame.frames 
= 1;
                    
break;
                
case 1:
                    
while (mainFrame.frames == 1{
                        
if (mainFrame.tankStatus == 0{
                            mainFrame.tankStatus 
= 1;
                        }
 else {
                            mainFrame.tankStatus 
= 0;
                        }

                        Thread.sleep(
100);
                    }

                    
break;
                }

            }

        }
 catch (Exception e) {
            System.out.println(e.getMessage());
        }

    }

}

这样添加了键盘事件后,游戏初始画面从下网上移动,然后现实坦克,按G健进行选择,选择单人游戏,多人游戏,地图编辑。

就这些了,写写再说…………

需要完成的难点:键盘控制配置,敌人坦克AI,地图文件txt,战场初始化及处理,音频(不知道去哪录那些音效,FC中还不能导出,郁闷)。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值