五一放假呆着没事儿,于是乎打算把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(512, 466);
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中还不能导出,郁闷)。
博主在五一假期尝试使用Java实现FC经典游戏BattleCity,首先搭建程序框架,包括主程序和主游戏类,采用双缓冲技术进行画面更新。游戏包含坦克的动画效果和两种类型。另外,创建了一个独立的数据处理类进行状态判断和AI计算。目前实现了游戏启动画面、坦克选择和键盘事件响应,未来挑战包括键盘控制、敌人AI、地图读取、战场初始化和音频处理。
6425

被折叠的 条评论
为什么被折叠?



