【腾讯云的1001种玩法】从一个云服务器到一款十年后的游戏之第一年

背景

累觉不爱,追求流浪,只信猫咪与游戏。与QQ三国结缘多年,却因为对物理的愧疚大学没有读计算机而选了物理系。因此丢失了几年对QQ三国未来发展的憧憬,没事,我们还有青春去幻想去设计去定义这游戏的未来,希望多年之后,游戏未倒,焕发二春,又有怀着梦想的少年进入了这个有爱的三国世界。我有满腔对这游戏未来发展的热情,希望十年后该游戏的策划组愿意倾听。

十年计划

  1. 在你好棒棒啊的腾讯云服务器(参赛就是来拿优惠券续费的,这个广告应打)建设一个帮助某游戏新玩家快速熟悉游戏,让老玩家重新热爱起游戏的社区网站QQ三国爱
  2. 开发与该游戏相关的在线攻略功能,运营网站期间收集玩家们的偏好、问题、建议、如何良好体验游戏等。
  3. 学习怎么制作游戏,从一个玩家体验友好的角度来策划新游戏。
  4. 开发一个个实现小功能的框架,最终整合成自己的游戏引擎。
  5. 做一款页游版本的游戏,把策划和源码送到QQ三国工作室,也许其中某个观点和建议可以被接纳,被相信这游戏还有未来,告诉策划组我爱QQ三国,谢谢它陪我度过的青春,希望你们别放弃这游戏,我们选择相信在等着。

接入服务器

不想说搭建的细节,因为老手不需要教,而新手让自己去摸索会更有趣,毕竟腾讯云管理中心的指引后详细了,简单说下会遇到的一些问题,新手遇到时可以查看。

问题基于的环境:IIS、windows、php

  1. 遇到json、jpeg等“新”扩展名文件,无法访问,去添加mime类型。
  2. 某非关键进程cpu利用率太大,但不确定是否可以关闭,而且是系统程序无法删除,去强行限制该帐号的权限。
  3. 网站随着访问数量增多,崩溃概率增大,排查后发现问题只可能在云服务器上,去设置IIS应用池回收时间,在更短周期内回收。
  4. 从一开始就养成用绝对路径的习惯,以后代码就可以少修改。
  5. 定期访问云主机检查有无中毒或异常进程。
  6. 网站设置单入口,权限页面可设置session,避免被非法访问。
  7. 多思考运用或不运用缓存。

网站设计

背景

不知从哪一年起,大概是最高等级开放到100+开始吧,享受玩三国乐趣的玩家,要么就是已经坚持很多年了的,所以有一定装备和等级基础,要么就是冲堆钱进来的。而达不到这两个要求的新玩家,甚至这几年挂机的老玩家,都跟不上一直新出的副本、道具、市场等,打开官网,又发现官网的资料一直停滞不前,论坛和三国吧的精品资料不错,可惜好帖很容易匿贴,新手也不知道该怎么搜索出想要的资料。

因为对三国九年的热爱,想搭个三国非官方玩家交流平台,帮助新手玩家去快速上手和融入三国这个可爱的世界中。

整体框架

部分功能展示

分别选取一个前端、后台和游戏例子。

副职产品计算器

网站上线后最受欢迎的单页面,利用ag的数据双向绑定计算副职产品成本和利润。

物品交易平台

访客查看发布+访客发布(图一)+统计搜索记录(图二)+后台管理(图三)

实现关键:

获取用户当前搜索所在的大区、物品类型,合理用好该游戏的特色分类。

拼图游戏

模拟客户端该游戏,帮助不熟悉的玩家训练出游戏技巧。

源码(另需引入jq和bootcss):

<style>
    *{
        padding: 0;
        margin: 0;
    }
    #main{
        width: 900px;
        margin: auto;
    }
    #twoboxes{
        position: relative;
    }
    .box{
        width: 420px;
        height: 420px;
        position: relative;
        float: left;
        margin-left: 30px;
    }
    .msg{
        width: 420px;
        margin: auto;
        position: absolute;
    }
    #leftmsg{
        top:420px;
        left: 30px;
    }
    #rightmsg{
        top:420px;
        left: 480px;
    }
    .each{
        position: absolute;
        border: 2px solid gray;
        /*background: url(images/1.jpg);*/
    }
    #emptyl,#emptyr{
        background: gray;
        z-index: 10;
    }
    #rule{
        width: 500px;
        margin: auto;
    }
</style>
<script>
    $(function(){
        $("#ruletoggle").click(function(){
            $("#rule").toggle();
        });
    });
    var stepsl=0;
    var stepsr=0;
    var isl=0;
    var isr=0;
    var secsObj=new Date();
    var secs=secsObj.getTime();
    var sort="";

    function calc(size){
        //清空元素,还有计时器,名次
        $("#rule").hide();
        stepsl=0;
        stepsr=0;
        isl=0;
        isr=0;
        $("#leftbox").empty();
        $("#rightbox").empty();
        $("#leftmsg p").empty();
        $("#rightmsg p").empty();
        sort="";
        //size取值:3,4,5
        //正方形的长宽后缀用大写X,count
        var picName=(Math.floor(Math.random()*16)+1)+".jpg";
        var X=420/size;
        var count=size*size;
        var boxArray=[];
        for(var i=0;i<count;i++){
            boxArray.push(i);
        }
        //记录初始顺序,之后判断是否胜利
        //循环,格子越多,交换次数越多,得到交换后的一个数组
        var times=0;
        while(times<(size*4)){
            var i=times%(count-1)+1;
            var randNum=Math.floor(Math.random()*(count-1))+1;
            if(randNum!=i){
                var tempArray=boxArray[i-1];
                boxArray[i-1]= boxArray[randNum-1];
                boxArray[randNum-1]=tempArray;
                times++;
            }
        }
        sort=boxArray.join("");
        //创建格子元素,左盒子的id是数字+l,右是数字+r
        for(var j=0;j<count-1;j++){
            var tempL=$('<div class="each" id="'+j+'l"></div>');
            tempL.attr({
                "numTop":Math.floor(j/size),
                "numLeft":Math.floor(j%size)
            });
            var eachTop=Math.floor(j/size)*X;
            var eachLeft=Math.floor(j%size)*X;
            var eachY=Math.floor((boxArray[j])/size)*X;
            var eachX=Math.floor((boxArray[j])%size)*X;
//            console.log(j,obj[j],eachTop,eachLeft);
            tempL.css({
                width:X+"px",
                height:X+"px",
                top:eachTop+"px",
                left:eachLeft+"px",
                "background":"url(http://www.qqsg2.com/application/views/community/pintu/images/"+picName+")",
                backgroundPositionX:-eachX+"px",
                backgroundPositionY:-eachY+"px"
            });
            $("#leftbox").append(tempL);
        }
        var tempEmptyL=$('<div class="each" id="emptyl"></div>');
        tempEmptyL.attr({
            "numTop":size-1,
            "numLeft":size-1
        });
        tempEmptyL.css({
            width:X+"px",
            height:X+"px",
            top:X*(size-1)+"px",
            left:X*(size-1)+"px",
        });
        $("#leftbox").append(tempEmptyL);

        for(var j=0;j<count-1;j++){
            var tempR=$('<div class="each" id="'+j+'r"></div>');
            tempR.attr({
                "numTop":Math.floor(j/size),
                "numLeft":Math.floor(j%size)
            });
            var eachTop=Math.floor(j/size)*X;
            var eachLeft=Math.floor(j%size)*X;
            var eachY=Math.floor((boxArray[j])/size)*X;
            var eachX=Math.floor((boxArray[j])%size)*X;
//            console.log(j,obj[j],eachTop,eachLeft);
            tempR.css({
                width:X+"px",
                height:X+"px",
                top:eachTop+"px",
                left:eachLeft+"px",
                "background":"url(http://www.qqsg2.com/application/views/community/pintu/images/"+picName+")",
                backgroundPositionX:-eachX+"px",
                backgroundPositionY:-eachY+"px"
            });
            $("#rightbox").append(tempR);
        }
        var tempEmptyR=$('<div class="each" id="emptyr"></div>');
        tempEmptyR.attr({
            "numTop":size-1,
            "numLeft":size-1
        });
        tempEmptyR.css({
            width:X+"px",
            height:X+"px",
            top:X*(size-1)+"px",
            left:X*(size-1)+"px",
        });
        $("#rightbox").append(tempEmptyR);
        //计时器
        secsObj=new Date();
        secs=secsObj.getTime();
        //捕获键盘按下事件
        document.onkeyup = function (event) {
            var e = event || window.event;
            var keyCode = e.keyCode || e.which;
            var el=$("#emptyl");
            var elTop=parseInt(el.attr("numTop"));
            var elLeft=parseInt(el.attr("numLeft"));
            var er=$("#emptyr");
            var erTop=parseInt(er.attr("numTop"));
            var erLeft=parseInt(er.attr("numLeft"));
            switch (keyCode) {
                case 37:
//                    console.log("左");
                    if(erLeft<size-1){
                        var changeId=erTop*size+erLeft+1;
                        var changeObj=$("#"+changeId+"r");
                        changeObj.css("left",erLeft*X+"px");
                        changeObj.attr("numLeft",erLeft);
                        changeObj.attr("id",erTop*size+erLeft+"r");
                        er.css("left",(erLeft+1)*X+"px");
                        er.attr("numLeft",erLeft+1);
                        isWinr(size);
                    }
                    break;
                case 38:
//                    console.log("上");
                    if(erTop<size-1){
                        var changeId=(erTop+1)*size+erLeft;
                        var changeObj=$("#"+changeId+"r");
                        changeObj.css("top",erTop*X+"px");
                        changeObj.attr("numTop",erTop);
                        changeObj.attr("id",erTop*size+erLeft+"r");
                        er.css("top",(erTop+1)*X+"px");
                        er.attr("numTop",erTop+1);
                        isWinr(size);
                    }
                    break;
                case 39:
//                    console.log("右");
                    if(erLeft>0){
                        var changeId=erTop*size+erLeft-1;
                        var changeObj=$("#"+changeId+"r");
                        changeObj.css("left",erLeft*X+"px");
                        changeObj.attr("numLeft",erLeft);
                        changeObj.attr("id",erTop*size+erLeft+"r");
                        er.css("left",(erLeft-1)*X+"px");
                        er.attr("numLeft",erLeft-1);
                        isWinr(size);
                    }
                    break;
                case 40:
//                    console.log("下");
                    if(erTop>0){
                        var changeId=(erTop-1)*size+erLeft;
                        var changeObj=$("#"+changeId+"r");
                        changeObj.css("top",erTop*X+"px");
                        changeObj.attr("numTop",erTop);
                        changeObj.attr("id",erTop*size+erLeft+"r");
                        er.css("top",(erTop-1)*X+"px");
                        er.attr("numTop",erTop-1);
                        isWinr(size);
                    }
                    break;
                case 65:
//                    console.log("a");
                    if(elLeft<size-1){
                        var changeId=elTop*size+elLeft+1;
                        var changeObj=$("#"+changeId+"l");
                        changeObj.css("left",elLeft*X+"px");
                        changeObj.attr("numLeft",elLeft);
                        changeObj.attr("id",elTop*size+elLeft+"l");
                        el.css("left",(elLeft+1)*X+"px");
                        el.attr("numLeft",elLeft+1);
                        isWinl(size);
                    }
                    break;
                case 87:
//                    console.log("w");
                    if(elTop<size-1){
                        var changeId=(elTop+1)*size+elLeft;
                        var changeObj=$("#"+changeId+"l");
                        changeObj.css("top",elTop*X+"px");
                        changeObj.attr("numTop",elTop);
                        changeObj.attr("id",elTop*size+elLeft+"l");
                        el.css("top",(elTop+1)*X+"px");
                        el.attr("numTop",elTop+1);
                        isWinl(size);
                    }
                    break;
                case 68:
//                    console.log("d");
                    if(elLeft>0){
                        var changeId=elTop*size+elLeft-1;
                        var changeObj=$("#"+changeId+"l");
                        changeObj.css("left",elLeft*X+"px");
                        changeObj.attr("numLeft",elLeft);
                        changeObj.attr("id",elTop*size+elLeft+"l");
                        el.css("left",(elLeft-1)*X+"px");
                        el.attr("numLeft",elLeft-1);
                        isWinl(size);
                    }
                    break;
                case 83:
//                    console.log("s");
                    if(elTop>0){
                        var changeId=(elTop-1)*size+elLeft;
                        var changeObj=$("#"+changeId+"l");
                        changeObj.css("top",elTop*X+"px");
                        changeObj.attr("numTop",elTop);
                        changeObj.attr("id",elTop*size+elLeft+"l");
                        el.css("top",(elTop-1)*X+"px");
                        el.attr("numTop",elTop-1);
                        isWinl(size);
                    }
                    break;
                default:
                    break;
            }
        }

    };
    function isWinl(size){
        stepsl++;
        var sort2=[];
        for(var i=0;i<size*size-1;i++){
            sort2.push(parseInt($("#leftbox .each:eq("+i+")").attr("id")));
        }
        var sort3=sort2.join("");
        sort3+=size*size-1;
        if(sort3==sort){
            var secsObj2=new Date();
            var secs2=secsObj2.getTime();
            if(isr==0&&isl==0){
                $("#leftmsg p").html("恭喜你第一名!通过"+(secs2-secs)/1000+"秒,"+stepsl+"步完成!");
            }else if(isr==1&&isl==0){
                $("#leftmsg p").html("恭喜你第二名!通过"+(secs2-secs)/1000+"秒,"+stepsl+"步完成!");
            }
            isl=1;
        }
    }
    function isWinr(size){
        stepsr++;
        var sort2=[];
        for(var i=0;i<size*size-1;i++){
            sort2.push(parseInt($("#rightbox .each:eq("+i+")").attr("id")));
        }
        var sort3=sort2.join("");
        sort3+=size*size-1;
        if(sort3==sort){
            var secsObj2=new Date();
            var secs2=secsObj2.getTime();
            if(isl==0&&isr==0){
                $("#rightmsg p").html("恭喜你第一名!通过"+(secs2-secs)/1000+"秒,"+stepsr+"步完成!");
            }else if(isl==1&&isr==0){
                $("#rightmsg p").html("恭喜你第二名!通过"+(secs2-secs)/1000+"秒,"+stepsr+"步完成!");
            }
            isr=1;
        }
    }
</script></head>
<body>
<div id="main" class="text-center">
    <div>
        <button class="btn" id="ruletoggle">显示/隐藏游戏规则</button>
        <div id="rule" class="text-left" style="display: none;;">
            <ol>
                <li>仅在有键盘的电脑上可以游戏</li>
                <li>供不熟练华容道拼图的玩家练习</li>
                <li>左手/玩家一按wsad键,右手/玩家二按↑↓←→键</li>
                <li>按下下面几种游戏难度按钮之一,便开始计时游戏</li>
                <li>如果浏览器长宽不够大,游戏时出现滚动条影响体验,建议把浏览器缩放再游戏,一般是按下ctrl加↓缩放</li>
            </ol>
        </div>
    </div>
    <div class="btn-group" role="group">
        <button type="button" class="btn btn-default" onclick="calc(3)">3X3简单</button>
        <button type="button" class="btn btn-default" onclick="calc(4)">4X4一般</button>
        <button type="button" class="btn btn-default" onclick="calc(5)">5X5困难</button>
        <button type="button" class="btn btn-default" onclick="calc(6)">6X6变态</button>
        <button type="button" class="btn btn-default" onclick="calc(7)">7X7神级</button>
    </div>
    <div id="twoboxes">
        <div class="box" id="leftbox"></div>
        <div class="msg" id="leftmsg"><p class="text-success"></p></div>
        <div class="box" id="rightbox"></div>
        <div class="msg" id="rightmsg"><p class="text-success"></p></div>
    </div>
</div>

因为网站不盈利,希望可以中奖获取服务器续费券,多谢!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

张灿树的专栏

1 篇文章1 人订阅

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏小狼的世界

超越按钮,拥抱触摸界面

苹果iPhone手机的发布,可以说带来了一个全新的“触摸”时代。现如今,就连小孩子都能够非常自然的使用一些触摸设备,手机、iPad等等。父母们一定很惊奇孩子们能...

632
来自专栏张善友的专栏

Entity Framework 和NHibernate的区别

今天在Boy's (小气的神) BLOG上看到一篇精彩的文章 Astoria to SQLite to Entity Framework to 建立你的ORM观...

1857
来自专栏PPV课数据科学社区

【学习】什么数据库最适合数据分析师

有奖转发活动 回复“抽奖”参与《2015年数据分析/数据挖掘工具大调查》有奖活动。 文 | 孙镜涛 来源 | InfoQ 数据分析师都想使用数据库作为数据仓库处...

2624
来自专栏即时通讯技术

技术干货:实时视频直播首屏耗时400ms内的优化实践

直播行业的竞争越来越激烈,进过2018年这波洗牌后,已经度过了蛮荒暴力期,剩下的都是在不断追求体验。最近正好在做直播首开优化工作,实践中通过多种方案并行,已经能...

111
来自专栏PPV课数据科学社区

【学习】MySQL入门书籍和方法分享

作者:卢钧轶 出处:CENALULU’S TECH BLOG 本文罗列了一些适用于MySQL及运维入门和进阶使用的书籍。 背景:各大论坛上总是有很多同学咨询想学...

2854
来自专栏Albert陈凯

flink与Spark的对比分析

我们是否还需要另外一个新的数据处理引擎?当我第一次听到flink的时候这是我是非常怀疑的。 在大数据领域,现在已经不缺少数据处理框架了,但是没有一个框架能够完...

6584
来自专栏程序人生

是时候想想该怎么删代码了

武林外传里秀才怼上姬无命,来了一段关于「我是谁」的精彩逼问。 我是谁?我生从何来,死往何处,我为何要出现在这个世界上?我的出现对这个世界来说意味着什么,是世界选...

34311
来自专栏CSDN技术头条

你被复制了吗?大数据带你看中国人的名字 重名TOP榜

名字是一个人的代号,起名字也是一门学问。你想知道中国人重名最多的名字是哪个吗?你想知道中国人重名最多的名都有哪些吗?再看看身边“10后”的娃们,有没有叫子涵、子...

1778
来自专栏PingCAP的专栏

TiDB 助力客如云餐饮 SaaS 服务

客如云成立于 2012 年,是全球领先、 国内最大的 SaaS 系统公司。 目前面向餐饮、 零售等服务业商家, 提供软硬一体的新一代智能化前台、收银等 SaaS...

1704
来自专栏数据和云

PostgreSQL 获评2017 DB-Engines年度DBMS榜首

在 DB-Engines 网站,一年一度的年度数据库已经被评选出来,2017 年的年度数据库花落 PostgreSQL。 ? 百花齐放春光好,各领风骚立潮头,最...

2925

扫码关注云+社区