源码网,源码论坛,源码之家,商业源码,游戏源码下载,discuz插件,棋牌源码下载,精品源码论坛

 找回密码
 立即注册
楼主: ttx9n

[JavaScript] javascript制作坦克大战全纪录(1)

[复制链接]

7万

主题

861

回帖

32万

积分

论坛元老

Rank: 8Rank: 8

积分
329525
发表于 2018-12-25 05:45:11 | 显示全部楼层 |阅读模式
本文写作的目的是巩固一下自己最近学习的js知识, 这个教程适合熟悉js基本语法和面向对象语法的小伙伴学习。由于自己也是刚学js不久,所以难免出现错误。如果发现希望给予指正。

PS:这个坦克大战是在网上下的一段源码之后,自己进行的重写。本身没有太难的东西,这个案例将js面向对象用的比较好,可以作为js面向对象的入门教程。

1.   创建基本对象,实现坦克简单的移动

1.1    如何在地图中绘制画布

    考虑到浏览器兼容的问题,我们用操作dom的方式来实现游戏对象的绘制和刷新。我们如何存储我们的地图呢? 我们应该把地图用一个二维数组来保存, js中没有二维数组,但是可以通过在一维数组从存储数组来实现。

1.2    代码实现

    我们将画布设计为 13 * 13 的一个二维数组,每个元素在地图中对应的长和宽均为40px,可以把整个地图看成由 40px*40p x大小的单元格组成的一个表格,那么我们整个画布的大小为 520px  *  520px ;
 
   上代码前先给大家来一张对象关系图:

1.2.1    创建顶级对象

html代码:

复制代码 代码如下:
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 <html>
 <head>
     <title>坦克大战</title>
     <link rel=stylesheet href="css/main.css" />
     <script src="js/Common.js"></script>
     <script src="js/TankObject.js"></script>
     <script src="js/Mover.js"></script>
     <script src="js/Tank.js"></script>
     <script src="js/Frame.js"></script>
     <script>
         window.onload = function () {
             // 调用游戏装载对象
             var loader = new GameLoader();
             loader.Begin();
         }
     </script>
 </head>
 
 <body>
     <!--地图容器-->
     <div id="divMap">
     </div>
     <div id="debugInfo">
     </div>
 </body>
 </html>

TankObject.js文件:
 
复制代码 代码如下:
 // 顶级对象
 TankObject = function () {
     this.XPosition = 0; // 对象在地图(13*13)中的X的位置
     this.YPosition = 0;
     this.UI = null; // dom元素
 }
 // 更改UI静态方法
 TankObject.prototype.UpdateUI = function (battlFiled) { }
 // 设置位置,参数是这样:1*40,6*40
 TankObject.prototype.SetPosition = function (leftPosition, topPosition) {
     // 在地图的位置 Math.round四舍五入   
     this.XPosition = Math.round(leftPosition / 40);
     this.YPosition = Math.round(topPosition / 40);
     // 设置在窗体上的位置
     if (this.UI != null && this.UI.style != null) {
         this.UI.style.left = leftPosition + "px";
         this.UI.style.top = topPosition + "px";
     }
 }

 
    这里​我们用X,Y坐标表示对象在地图上的位置。后面我们会将地图中的每个对象都放入二维数组中,这时可以通过X,Y坐标来取得对应的对象。
    然后用css中的left和top来控制我们对象在窗体中的位置。(可以移动的对象:坦克,子弹)
 

1.2.2   创建公用对象

    我们还需要创建一个公共的对象,来写入我们常用的一些方法。
 
Common.js:
 
复制代码 代码如下:
// 坦克移动的四个方向
var EnumDirection = {
    Up: "0",
    Right: "1",
    Down: "2",
    Left: "3"
};
// 通用方法对象
var UtilityClass = {
    // 创建dom元素到parentNode中,可指定id,className
    CreateE: function (type, id, className, parentNode) {
        var J = document.createElement(type);
        if (id) { J.id = id };
        if (className) { J.className = className };
        return parentNode.appendChild(J);
    },  // 移除元素
    RemoveE: function (obj, parentNode) {
        parentNode.removeChild(obj);
    },
    GetFunctionName: function (context, argumentCallee) {
        for (var i in context) {
            if (context == argumentCallee) { return i };
        }
        return "";
    },  // 绑定事件,返回func方法,this为传入的obj
    BindFunction: function (obj,func) {
        return function () {
            func.apply(obj, arguments);
        };
    }
};

1.2.3    创建移动对象

Mover.js
 
复制代码 代码如下:
 // 移动对象,继承自顶层对象
 Mover = function () {
     this.Direction = EnumDirection.Up;
     this.Speed = 1;
 }
 Mover.prototype = new TankObject();
 Mover.prototype.Move = function () {
     if (this.lock) {
         return;/* 停用或者尚在步进中,操作无效 */
     }
     // 根据方向设置坦克的背景图片
     this.UI.style.backgroundPosition = "0 -" + this.Direction * 40 + "px";
     // 如果方向是上和下,vp就是top;如果方向是上和左,val就是-1
     var vp = ["top", "left"][((this.Direction == EnumDirection.Up) || (this.Direction == EnumDirection.Down)) ? 0 : 1];
     var val = ((this.Direction == EnumDirection.Up) || (this.Direction == EnumDirection.Left)) ? -1 : 1;
     this.lock = true;/* 加锁 */
     // 把当前对象保存到This
     var This = this;
     // 记录对象移动起始位置
     var startmoveP = parseInt(This.UI.style[vp]);
     var xp = This.XPosition, yp = This.YPosition;
     var subMove = setInterval(function () {
         // 开始移动,每次移动5px
         This.UI.style[vp] = parseInt(This.UI.style[vp]) + 5 * val + "px";
         // 每次移动一个单元格 40px
         if (Math.abs((parseInt(This.UI.style[vp]) - startmoveP)) >= 40) {
             clearInterval(subMove);
             This.lock = false;/* 解锁,允许再次步进 */
             // 记录对象移动后在表格中的位置
             This.XPosition = Math.round(This.UI.offsetLeft / 40);
             This.YPosition = Math.round(This.UI.offsetTop / 40);
         }
     }, 80 - this.Speed * 10);
 }

 
    这里的移动对象继承自我们的顶级对象 ,这里this就代表调用Move方法的对象。
    Move对象的功能根据对象的方向和速度进行移动,每次移动5px总共移动40px一个单元格。后面这个对象还会进行扩展,会加入碰撞检测等功能。

1.2.4    创建坦克对象
 
Tank.js 文件:

复制代码 代码如下:
//tank对象 继承自Mover
Tank=function(){}
Tank.prototype = new Mover();

// 创建玩家坦克,继承自tank对象
SelfTank = function () {
    this.UI = UtilityClass.CreateE("div", "", "itank", document.getElementById("divMap"));
    this.MovingState = false;
    this.Speed = 4;
}
SelfTank.prototype = new Tank();
// 设置坦克的位置
SelfTank.prototype.UpdateUI = function () {
    this.UI.className = "itank";
    // 顶级对象方法,设置坦克的位置
    this.SetPosition(this.XPosition * 40, this.YPosition * 40);
}

     现在只创建了玩家坦克,后面我们还会往里添加敌人坦克。

1.2.5    创建游戏装载对象(核心)

复制代码 代码如下:
 // 游戏载入对象 整个游戏的核心对象
 GameLoader = function () {
     this.mapContainer = document.getElementById("divMap");  // 存放游戏地图的div
     this._selfTank = null;  // 玩家坦克
     this._gameListener = null; // 游戏主循环计时器id
 }
 GameLoader.prototype = {
     Begin: function () {
         // 初始化玩家坦克
         var selfT = new SelfTank();
         selfT.XPosition = 4;
         selfT.YPosition = 12;
         selfT.UpdateUI();
         this._selfTank = selfT;
         // 添加按键事件
         var warpper = UtilityClass.BindFunction(this, this.OnKeyDown);
         window.onkeydown = document.body.onkeydown = warpper;
         warpper = UtilityClass.BindFunction(this, this.OnKeyUp);
         window.onkeyup = document.body.onkeyup = warpper;
         // 游戏主循环
         warpper = UtilityClass.BindFunction(this, this.Run);
         /*长定时器监听控制键*/
         this._gameListener = setInterval(warpper, 20);
     }
     // 键盘按下玩家坦克开始移动
     , OnKeyDown: function (e) {
         switch ((window.event || e).keyCode) {
             case 37:
                 this._selfTank.Direction = EnumDirection.Left;
                 this._selfTank.MovingState = true;
                 break;        //左
             case 38:
                 this._selfTank.Direction = EnumDirection.Up;
                 this._selfTank.MovingState = true;
                 break;        //上
             case 39:
                 this._selfTank.Direction = EnumDirection.Right;
                 this._selfTank.MovingState = true;
                 break;        //右
             case 40:
                 this._selfTank.Direction = EnumDirection.Down;
                 this._selfTank.MovingState = true;
                 break;        //下
         }
     }
     // 按键弹起停止移动
     , OnKeyUp: function (e) {
         switch ((window.event || e).keyCode) {
             case 37:
             case 38:
             case 39:
             case 40:
                 this._selfTank.MovingState = false;
                 break;
         }
     }
     /*游戏主循环运行函数,游戏的心脏,枢纽*/
     , Run: function () {
         if (this._selfTank.MovingState) {
             this._selfTank.Move();
         }
     }
 };

   游戏装载对象代码看起来很多,其实就做了两件事情:
        1、创建玩家坦克对象。
        2、添加按键监听事件,当玩家按下移动键调用坦克Move方法移动坦克。

总结:到这里我们的坦克可以通过按键自由的移动了。下一步我们需要完善地图和碰撞检测。

回复

使用道具 举报

4

主题

2万

回帖

316

积分

中级会员

Rank: 3Rank: 3

积分
316
发表于 2022-8-8 09:12:13 | 显示全部楼层
儿童服务绯闻绯闻绯闻
回复 支持 反对

使用道具 举报

0

主题

1万

回帖

68

积分

注册会员

Rank: 2

积分
68
发表于 2022-8-13 18:15:39 | 显示全部楼层
哦哦哦哦哦哦哦哦哦
回复 支持 反对

使用道具 举报

16

主题

2万

回帖

174

积分

注册会员

Rank: 2

积分
174
发表于 2022-12-4 15:08:32 | 显示全部楼层
谢谢您的分享!
回复 支持 反对

使用道具 举报

3

主题

2万

回帖

156

积分

注册会员

Rank: 2

积分
156
发表于 2023-8-24 19:08:54 | 显示全部楼层
哈哈哈哈哈哈
回复 支持 反对

使用道具 举报

0

主题

2万

回帖

55

积分

注册会员

Rank: 2

积分
55
发表于 2023-9-2 18:26:27 | 显示全部楼层
有什么好的服务器
回复 支持 反对

使用道具 举报

0

主题

2万

回帖

0

积分

中级会员

Rank: 3Rank: 3

积分
0
发表于 2023-10-17 16:06:55 | 显示全部楼层
额风风风微风微风违法
回复 支持 反对

使用道具 举报

0

主题

1万

回帖

0

积分

中级会员

Rank: 3Rank: 3

积分
0
发表于 2023-11-14 13:30:15 | 显示全部楼层
很不错的玩意
回复 支持 反对

使用道具 举报

0

主题

2万

回帖

0

积分

中级会员

Rank: 3Rank: 3

积分
0
发表于 2024-7-29 13:34:52 | 显示全部楼层
收下来看看怎么样
回复 支持 反对

使用道具 举报

12

主题

2万

回帖

431

积分

中级会员

Rank: 3Rank: 3

积分
431
发表于 2024-8-22 12:48:53 | 显示全部楼层
人都不在了啊 啊
回复 支持 反对

使用道具 举报

高级模式
B Color Image Link Quote Code Smilies

本版积分规则

手机版|小黑屋|网站地图|源码论坛 ( 海外版 )

GMT+8, 2025-2-6 23:18 , Processed in 0.072624 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表