我们提供安全,免费的手游软件下载!
介绍
通过本项目能够更直观地理解应用层和运输层网络协议, 以及继承封装多态的运用. 网络部分是本文叙述的重点, 你将看到如何使用Java建立TCP和UDP连接并交换报文, 你还将看到如何自己定义一个简单的应用层协议来让自己应用进行网络通信。
本项目的Github地址
基础版本 游戏的原理, 图形界面(非重点)
多张图片快速连续地播放, 图片中的东西就能动起来形成视频, 对视频中动起来的东西进行操作就变成游戏了. 在一个坦克对战游戏中, 改变一辆坦克每一帧的位置, 当多帧连续播放的时候, 视觉上就有了控制坦克的感觉. 同理, 改变子弹每一帧的位置, 看起来就像是发射了一发炮弹. 当子弹和坦克的位置重合, 也就是两个图形的边界相碰时, 在碰撞的位置放上一个爆炸的图片, 就完成了子弹击中坦克发生爆炸的效果。
在本项目借助坦克游戏认识网络知识和面向对象思想, 游戏的显示与交互使用到了Java中的图形组件, 如今Java已较少用于图形交互程序开发, 本项目也只是使用了一些简单的图形组件。
在本项目中, 游戏的客户端由TankClient类控制, 游戏的运行和所有的图形操作都包含在这个类中, 下面会介绍一些主要的方法。
//类TankClient, 继承自Frame类
//继承Frame类后所重写的两个方法paint()和update()
//在paint()方法中设置在一张图片中需要画出什么东西.
@Override
public void paint(Graphics g) {
//下面三行画出游戏窗口左上角的游戏参数
g.drawString("missiles count:" + missiles.size(), 10, 50);
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);
if(m.hitTank(myTank)){
TankDeadMsg msg = new TankDeadMsg(myTank.id);
nc.send(msg);
MissileDeadMsg mmsg = new MissileDeadMsg(m.getTankId(), m.getId());
nc.send(mmsg);
m.draw(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.draw(g);
//画出我的坦克
myTank.draw(g);
/*
* update()方法用于写每帧更新时的逻辑.
* 每一帧更新的时候, 我们会把该帧的图片画到屏幕中.
* 但是这样做是有缺陷的, 因为把一副图片画到屏幕上会有延时, 游戏显示不够流畅
* 所以这里用到了一种缓冲技术.
* 先把图像画到一块幕布上, 每帧更新的时候直接把画布推到窗口中显示
*/
@Override
public void update(Graphics g) {
if(offScreenImage == null) {
offScreenImage = this.createImage(800, 600);//创建一张画布
Graphics gOffScreen = offScreenImage.getGraphics();
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);//直接把画布推到窗口
//这是加载游戏窗口的方法
public void launchFrame() {
this.setLocation(400, 300);//设置游戏窗口相对于屏幕的位置
this.setSize(GAME_WIDTH, GAME_HEIGHT);//设置游戏窗口的大小
this.setTitle("TankWar");//设置标题
this.addWindowListener(new WindowAdapter() {//为窗口的关闭按钮添加监听
@Override
public void windowClosing(WindowEvent e) {
System.exit(0);
});
this.setResizable(false);//设置游戏窗口的大小不可改变
this.setBackground(Color.GREEN);//设置背景颜色
this.addKeyListener(new KeyMonitor());//添加键盘监听,
this.setVisible(true);//设置窗口可视化, 也就是显示出来
new Thread(new PaintThread()).start();//开启线程, 把图片画出到窗口中
dialog.setVisible(true);//显示设置服务器IP, 端口号, 自己UDP端口号的对话窗口
//在窗口中画出图像的线程, 定义为每50毫秒画一次.
class PaintThread implements Runnable {
public void run() {
while(true) {
repaint();
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();