• jQuery版坦克游戏,缺陷面向对象重构版!


     一款jQuery版tank游戏,画面美观、逼真,可双人游戏,其效果堪与flash媲美。支持浏览器:ie6+,firefox,opera,safari,在ie9或其他非ie浏览器,可获得更加流畅的游戏速度。
        下载地址:http://jtankwar.googlecode.com/files/tank%20war%203.0.zip
        诚邀各位志士组团(HTML5+ANDROID):38155026(欢迎入群)
        此文精辟点在第七页“fch415”大哥的回复里面!

        此版本经过精心重构,面向接口设计,模仿类式继承和多继承(掺元类),多处使用闭包优化实现,使用单体工厂模式降低代码间耦合,添加图片及地图的预加载等等;重构版用新算法替代了大量DOM相关的操作,大大提高了游戏性能,即使在ie6下玩,效果也差强人意。

    源码说明:
    1.tank.main.js 定义了基本的接口及其实现,如图:

    Javascript代码  
    1. // Interfaces.   
    2. var Tank = new Interface('Tank', ['explode','clear','die','fire','isShot','move','stopMoving','isBlocked','attachEvents','init']);   
    3. var Bullet = new Interface('Bullet',['explode','clear','die','fire','init']);   
    4. var Block = new Interface('Block', ['explode','clear','die','isShot','display']);   
    5.   
    6. // Abstract tank, impl base methods.   
    7. var AbstractTank = function(opt) { // Constructor   
    8.     this.id = opt.id;   
    9.     this.isAlive = true;   
    10.     this.speed = opt.speed;   
    11.     this.top = opt.pos.y;   
    12.     this.left = opt.pos.x;   
    13.     this.movingToward = 'up';   
    14.     this.init();   
    15.     this.attachEvents();   
    16. };   
    17.   
    18. AbstractTank.prototype = { // Public methods   
    19.     move: function(_d) {   
    20.        ...   
    21.         },   
    22.     stopMoving: function() {   
    23.         var _d = this.movingToward, thisTank = $('div#' + this.id);   
    24.         clearInterval(this.moveTimr);   
    25.         thisTank.removeClass('moving' + _d);   
    26.     },   
    27.     isBlocked: function() {   
    28.             ...   
    29.     },   
    30.     die: function() {   
    31.         this.isAlive = false;   
    32.         this.explode('mapbomb', 11);   
    33.     },   
    34.     fire: function() {   
    35.         TankWarFactory.createBullet(this);   
    36.         return this;   
    37.     },   
    38.     isShot: function() {   
    39.         throw new Error('isShot function is undefined.');   
    40.     },   
    41.     clear: function() {   
    42.         throw new Error('clear function is undefined.');   
    43.     },   
    44.     attachEvents: function() {   
    45.         throw new Error('attachEvents function is undefined.');   
    46.     },   
    47.     init: function() {   
    48.         throw new Error('init function is undefined.');   
    49.     }   
    50. };  

    2.tank.factory.js 实例化坦克、block、子弹等。
    Javascript代码  
    1. var TankWarFactory = {   
    2.     createPlayerTank: function() {   
    3.         var tank = new PlayerTank();   
    4.         Interface.ensureImplements(tank, Tank);   
    5.         TankWar.barrier.players.push(tank);   
    6.         TankWarMng.setTankCount(tank.id, --tank.lives);   
    7.         TankWarMng.setScore(tank, 0);   
    8.     },   
    9.     createEnemyTank: (function() {   
    10.         // Private static check type of enemies.   
    11.         function checkType(type) {   
    12.             var types = TankWar.enemies.types.clone();   
    13.             if (!type) type = 'r';   
    14.             if (TankWar.enemies[type].leftNum > 0) return type;   
    15.             types.remove(type);   
    16.             for (var i = 0, len = types.length; i < len; i++) {   
    17.                 if (TankWar.enemies[types[0]].leftNum === 0) {   
    18.                     types.remove(types[0]);   
    19.                 } else {   
    20.                     return types[0];   
    21.                 }   
    22.             }   
    23.             return false;   
    24.         }   
    25.         return function(type) { // return constructor   
    26.             var tank;   
    27.             type = checkType(type);   
    28.             if (!type) throw new Error('No enemies alive.');   
    29.             switch(type) {   
    30.                 case 'r': tank = new EnemyRTank(); break;   
    31.                 case 'b': tank = new EnemyBTank(); break;   
    32.                 case 'y': tank = new EnemyYTank(); break;   
    33.                 case 'g': tank = new EnemyGTank(); break;   
    34.             }   
    35.             Interface.ensureImplements(tank, Tank);   
    36.             TankWar.barrier.enemies.push(tank);   
    37.             TankWarMng.setTankCount(tank.id, --TankWar.enemies[type].leftNum);   
    38.         }   
    39.     })(),   
    40.     createBullet: function(tank) {   
    41.         var bullet;   
    42.         if (tank instanceof PlayerTank) {   
    43.             bullet = new PlayerBullet(tank);   
    44.         } else {   
    45.             bullet = new EnemyBullet(tank);   
    46.         }   
    47.         Interface.ensureImplements(bullet, Bullet);   
    48.     },   
    49.     createBlock: function(param) {   
    50.         var block;   
    51.         switch(param.type) {   
    52.             case 'e': block = new BrickBlock(param); TankWar.barrier.normalBlocks.push(block);break;   
    53.             case 'h': block = new StoneBlock(param); TankWar.barrier.normalBlocks.push(block);break;   
    54.             case 'k': block = new KingBlock(param); TankWar.barrier.normalBlocks.push(block);break;   
    55.             case 'w': block = new WaterBlock(param); TankWar.barrier.waterBlocks.push(block);break;   
    56.             case 'b': block = new BornBlock(param); TankWar.enemies.posBorn.push({x:block.left,y:block.top,avaliable:true});break;   
    57.             case 'l': block = new LawnBlock(param);break;   
    58.         }   
    59.         Interface.ensureImplements(block, Block);   
    60.     }   
    61. };  

    3.tankwar.js 将页面切换、游戏初始化、事件绑定等封装为TankWarMng对象的方法。
    4.tank.progress.js 图片及地图预加载。
    Javascript代码  
    1. var PreLoad = (function() {   
    2.     // 私有静态方法   
    3.     function obj2array(givenObj) {   
    4.         var urllist = [], patrn = /1-\d{1,2}\.(png|json)$/, level = 0, levelArr = [];   
    5.         if (TankWar.mySite) levelArr[level++] = TankWar.mySite;   
    6.         (function(obj) { // 解析对象,将结果填进urllist数组   
    7.             for (var prop in obj) {   
    8.                 if (prop === 'urls') {   
    9.                     for (var i = 0, n = obj[prop].length; i < n; i++) {   
    10.                         if (patrn.test(obj[prop][i])) {   
    11.                             var tmp = obj[prop][i].split('.')[0].split('-'), suffix = patrn.exec(obj[prop][i])[1];   
    12.                             for (var j = tmp[0], m = tmp[1]; j <= m; j++) {   
    13.                                 urllist.push(levelArr.join('/') + '/' + j + '.' + suffix);   
    14.                             }   
    15.                         } else {   
    16.                             urllist.push(levelArr.join('/') + '/' + obj[prop][i]);   
    17.                         }   
    18.                     }   
    19.                     levelArr.splice(--level, 1);   
    20.                 } else {   
    21.                     levelArr[level++] = prop;   
    22.                     arguments.callee(obj[prop]);   
    23.                 }   
    24.             }   
    25.         })(givenObj);   
    26.         return urllist;   
    27.     };   
    28.     // 构造器   
    29.     return function(urlObj, callback) {   
    30.         this.callback = callback;   
    31.         if (!TankWar.mySite) { // 如果没有启动预加载,直接进入回调   
    32.             this.progressBar(100);   
    33.             return;   
    34.         }   
    35.         this.urlList = obj2array(urlObj);   
    36.         this.total = this.urlList.length;   
    37.         this.succeedcount = 0;   
    38.         this.errorcount = 0;   
    39.         this.init();   
    40.     }   
    41. })();   
    42.   
    43. PreLoad.prototype = {   
    44.     loadImg: function(url) {   
    45.         var img = new Image(), that = this;   
    46.         img.onload = function() {   
    47.             that.complete(url, '图片');   
    48.         }   
    49.         img.onerror = function() {   
    50.             that.error(url);   
    51.         }   
    52.         img.src = url;   
    53.     },   
    54.     loadMap: function(url) {   
    55.         var that = this;   
    56.         $.getJSON(url, function(map) {   
    57.             TankWar.maps.push(map);   
    58.             that.complete(url, '地图');   
    59.         });   
    60.     },   
    61.     complete: function(url, type) {   
    62.         this.progressBar(Math.round(++this.succeedcount*100/this.total), url, type);   
    63.     },   
    64.     error: function(url) {   
    65.         throw new Error('load '+ url +' failed.');   
    66.     },   
    67.     progressBar: function(percent, url, type) {   
    68.         if (url && type) {   
    69.             $('#percent span').text(percent);   
    70.             $('#loading span').text(type + ': ' + url.substr(url.lastIndexOf('/') + 1, url.length));   
    71.         }   
    72.         $('#bar').stop().animate({left: 550 - 550*percent/100}, 200);   
    73.         if (percent === 100) this.over();   
    74.     },   
    75.     over: function() {   
    76.         var that = this;   
    77.         setTimeout(function() {   
    78.             that.callback();   
    79.         }, 500);   
    80.     },   
    81.     init: function() {   
    82.         $('#percent, #loading').show();   
    83.         for (var i = 0; i < this.total; i++) {   
    84.             if (/\.json$/.test(this.urlList[i]))   
    85.                 this.loadMap(this.urlList[i]);   
    86.             else  
    87.                 this.loadImg(this.urlList[i]);   
    88.         }   
    89.     }   
    90. };  

    5.util.js 接口、接口检查、继承等的实现。
    6.tank.namespace.js & tank.config.js 命名空间及常用参数。
    Javascript代码  
    1. var config = {};   
    2. config.my_site = ''// 如果将此游戏放在您网站上,请配置网址如:config.my_site = 'http://www.mysite.com/tank',将会自动启用预加载技术,以获得更好的游戏体验   
    3.   
    4. config.develop_model = 'product'// develop|test|product 如果是product,将不进行接口检查,以提高游戏速度   
    5.   
    6. config.enemy_number_of_level = [{r:5,b:3,y:2,g:1},{r:10,b:5,y:3,g:2},{r:15,b:5,y:5,g:5}]; // 每一关的敌方坦克数量,目前有三关   
    7.   
    8. config.default_scene = 'lawn'// 默认场景   
    9.   
    10. // 游戏参数   
    11. config.player1_lives = 4;   
    12. config.player1_speed = 2;   
    13. config.player1_move_keys = { 37: 'left', 38: 'up', 39: 'right', 40: 'down'};   
    14. config.player1_fire_key = 32;   
    15.   
    16. config.player2_lives = 4;   
    17. config.player2_speed = 2;   
    18. config.player2_move_keys = { 65: 'left', 87: 'up', 68: 'right', 83: 'down'};   
    19. config.player2_fire_key = 71;   
    20.   
    21. config.enemy_red_speed = 1;   
    22. config.enemy_blue_speed = 1.5;   
    23. config.enemy_yellow_speed = 2;   
    24. config.enemy_green_speed = 2.5;   
    25. config.bullet_speed = 10;  

    7.1-3.json 地图
    Javascript代码  
    1. [{   
    2.     "type""b"// b为敌方坦克出生地,你可以添加/减少b的个数,调节敌方坦克数量   
    3.     "y": 10,   
    4.     "x": 9   
    5. }, {   
    6.     "type""b",   
    7.     "y": 9,   
    8.     "x": 332   
    9. }, {   
    10.     "type""b",   
    11.     "y": 9,   
    12.     "x": 653   
    13. },   
    14.   
    15. {   
    16.     "type""h"// 子弹打不破的石头   
    17.     "y": 172,   
    18.     "x": 10   
    19. },   
    20.   
    21. {   
    22.     "type""l"// 草地   
    23.     "y": 212,   
    24.     "x": 43   
    25. }, {   
    26.     "type""e"// 子弹两次可以打破的砖头   
    27.     "y": 212,   
    28.     "x": 79   
    29. }]  
    更多精彩,请下载源码:http://jtankwar.googlecode.com/files/tank%20war%203.0.zip

    游戏效果截图:

    主页--游戏设置

    游戏中..

    暂停/退出

    任务结束

    此文供大家交流,共同学习,可以随便转载!
  • 相关阅读:
    axios取消请求
    echarts常用图表配置
    Vue指令限制输入框输入整数小数
    小程序商品飞入购物车组件
    webpack按测试和生产环境进行编译
    地图画线添加标签
    vue-element-admin 动态侧边栏
    html2canvas 和浏览器打印
    echarts 指定某段曲线颜色
    列出表结构
  • 原文地址:https://www.cnblogs.com/luoyaoquan/p/2046158.html
Copyright © 2020-2023  润新知