zoukankan      html  css  js  c++  java
  • HTML5游戏实战(2):90行代码实现捕鱼达人

    捕鱼达人是一款非常流行的游戏,几年里赚取了数以千万的收入,这里借用它来介绍一下用Gamebuilder+CanTK开发游戏的方法。其实赚钱的游戏未必技术就很难,今天我们就仅用90来行代码来实现这个游戏。 

    CanTK(Canvas ToolKit)是一个开源的游戏引擎和APP框架,是开发HTML5游戏和APP的利器,如果你喜欢它,请在github上给它加星,您的支持是我们努力的动力:https://github.com/drawapp8/cantk

    0.先Show一下最终成果:

    在线运行:http://www.tangide.com/apprun.html?appid=previewupyunosgames1-841431856568571

    在线编辑:http://www.tangide.com/gamebuilder.php?appid=previewupyunosgames1-841431856568571

    1,新建一个项目,删除场景里的球和地面,把手机设置成横屏,然后设置场景的物理引擎参数,把X/Y方向的重力设置为0。

    设置场景的背景图片:

    效果如下:

    2,在场景中放一个图片,如下图设置它的属性。

    3,在图片中再放一个帧动画,用来表示大炮,如下图设置它的属性。

    4,在场景中再放一个帧动画,用来表示鱼,如下图设置它的属性。

    通过拷贝&粘贴,创建10条鱼,名称分别命名为ui-fish1到ui-fish10。得到下面的效果:

    5,在场景中再放一个帧动画,用来表示金币,如下图设置它的属性。

    6,在场景中再放一个帧动画,用来表示炮弹,如下图设置它的属性。

    7,在底部的图片中放一个图片字体,用来表示总金币数量,如下图设置它的属性。

    8,在场景中中放一个图片字体,用来表示单次金币数,如下图设置它的属性。

    9,在底部的图片中放两个按钮,用来改变大炮的威力,如下图设置它的属性。

    到此界面基本完成了(后面可能需要做些调整),效果如下:

    10,现在我们开始写代码。

    在场景的onOpen里定义几个函数:

    var win = this;
    function isObjInvisible(obj) {return !obj.visible;}
    //当炮弹和鱼移动到场景之外时,把它们设置为不可见不可用,后面重用这些对象,以减小内存开销。
    function handleOnMoved() {
        var x = this.x, y = this.y, r = x + this.w, b = y + this.h, w = win.w, h = win.h;
        if(x > w || y > h || r < 0 || b < 0) {
            this.setVisible(false).setEnable(false);
        }
    }
    //定时产生鱼
    function makeFish() {
        if(!win.info) return;
        var info = win.info,cannon = info.cannon;
        var fish = info.fishs.find(isObjInvisible);
        if(!fish && info.fishs.length < 20) {
            var index = Math.floor(10 * Math.random())+1;
            fish = win.dupChild("ui-fish"+index);
            
        }
        if(fish) {
            info.fishs.push(fish);
            var y = Math.max(0, Math.floor((win.h - info.bottom.h) * Math.random() - fish.h));
            var x =  y%2 ? -fish.w : win.w;
            var vx = x > 0 ? -1 : 1;
            var rotation = x > 0 ? Math.PI : 0;
            fish.setPosition(x, y).setVisible(true).setEnable(true).setV(vx, 0).setRotation(rotation).play("live");
        }
        setTimeout(makeFish, 500);
    }
    //初始化游戏
    win.initGame = function() {
        var info = {bullets:[], fishs:[], cannonType:1, scoreValue:0};
        var cannon = this.find("ui-cannon", true);
        var p = cannon.getPositionInWindow(); 
        cannon.center ={x: p.x + (cannon.w >> 1), y: p.y + (cannon.h >> 1)};    
        info.cannon = cannon;
    
        info.bottom = this.find("ui-image");
        var totalScore = this.find("ui-total-score", true);
        p = totalScore.getPositionInWindow(); 
        totalScore.center ={x: p.x + (totalScore.w >> 1), y: p.y + (totalScore.h >> 1)};    
        info.totalScore = totalScore;
        
        var bullet = this.find("ui-bullet").setVisible(false).setEnable(false);
        bullet.handleOnMoved = handleOnMoved;
        info.bullets.push(bullet);
        
        info.coin = this.find("ui-coin").setVisible(false);
        info.score = this.find("ui-score").setVisible(false);
        for(var i = 0; i < this.children.length; i++) {
            var iter = this.children[i];
            if(iter.name.indexOf("ui-fish") >= 0) {
                iter.handleOnMoved = handleOnMoved;
                iter.setEnable(false).setVisible(false);
                info.fishs.push(iter);
            }
        }
        info.timerID = setTimeout(makeFish, 1000);
        this.info = info;
    }
    //改变大炮类型
    win.changeCannon = function(delta) {
        var info = this.info,cannon = info.cannon;
        info.cannonType = Math.max(1, Math.min(7, info.cannonType + delta));
        cannon.play("default"+info.cannonType, 100000);
    }
    //炮弹打中鱼时,炮弹变成网,鱼播放die动画,金币从炮弹处移动到总金币处。
    win.onContacted = function(bullet, fish) {
        var info = this.info,cannon = info.cannon;
        bullet.setEnable(false).play("web"+info.cannonType, 1, function() {bullet.setVisible(false);});
        fish.setEnable(false).play("die", 1, function() {fish.setVisible(false)});
        info.scoreValue += 100;
        info.totalScore.setValue(info.scoreValue);
        info.coin.setVisible(true).animate({xStart:bullet.x, yStart:bullet.y, xEnd:info.totalScore.x, yEnd:info.totalScore.y-20});
    }
    //点击场景时,调整大炮位置,发射炮弹,大炮播放射击动画。
    win.handleClick = function(point) {
        var info = this.info,cannon = info.cannon;
        if(this.targetShape != this.info.bottom) {
            var angle = Math.lineAngle(cannon.center, point) - 1.5 * Math.PI;
            cannon.setRotation(angle);
            var bullet = info.bullets.find(isObjInvisible);
            if(!bullet)  {
                bullet = win.dupChild("ui-bullet",0);
                info.bullets.push(bullet);
            }
            var x = cannon.center.x - (bullet.w >> 1), y = cannon.center.y - (bullet.h >> 1);
            bullet.setPosition(x, y).setRotation(angle).setVisible(true).setEnable(true).setV(5*Math.sin(angle),-5*Math.cos(angle));
            bullet.play("bullet"+info.cannonType);
            cannon.play("fire"+info.cannonType, 1);
            console.log(angle);
        }
    }
    
    this.initGame();

    在场景的点击事件中:

    this.handleClick(point);

    在两个按钮中:

    this.getWindow().changeCannon(-1);

    好了,我们的捕鱼达人基本完成了。还有几个地方需要完善:1.射中多条鱼时分数加倍。2.鱼有不同的生命值,炮弹有不同的杀伤力。

    呵河,这些问题留给读者动手去做吧,或许您就是下一个千万级游戏的开发者呢:)

    参考资料:

    https://github.com/drawapp8/gamebuilder/wiki/%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%A3

  • 相关阅读:
    MOSS中的User的Title, LoginName, DisplayName, SID之间的关系
    如何在Network Monitor中高亮间隔时间过长的帧?
    SharePoint服务器如果需要安装杀毒软件, 需要注意什么?
    如何查看SQL Profiler? 如何查看SQL死锁?
    什么是Telnet
    The name or security ID (SID) of the domain specified is inconsistent with the trust information for that domain.
    Windows SharePoint Service 3.0的某个Web Application无搜索结果
    网络连接不上, 有TCP错误, 如果操作系统是Windows Server 2003, 请尝试一下这里
    在WinDBG中查看内存的命令
    The virtual machine could not be started because the hypervisor is not running
  • 原文地址:https://www.cnblogs.com/zhangyunlin/p/6167356.html
Copyright © 2011-2022 走看看