【腾讯云的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 条评论
登录 后参与评论

相关文章

来自专栏阮一峰的网络日志

关于BT下载电影

BT下载的一个注意点,就是你必须认清版本。同一部电影,网上往往有几十个、甚至几百个版本,有的版本质量很糟糕,下载它们就是浪费时间和带宽。

1042
来自专栏阮一峰的网络日志

每周分享第 23 期

社会学家按照收入,把所有美国的职业分成100个等级。收入最高的职业为100分,收入最低的职业为1分。在这个体系里面,医生是93分,空姐是53分,擦鞋工是9分。

824
来自专栏程序你好

macOS Mojave 10.14预览

看起来iOS现在很受欢迎。很容易理解为什么。在许多用户的生活中,智能手机一直是占主导地位的设备,而台式机/笔记本电脑则一直在走下坡路。但macOS还有一些生命力...

673
来自专栏互联网杂技

超赞!2016年7月新鲜出炉的设计圈实用干货大合集

又到了新的一轮的设计圈干货大合集发布的时间了!这次的合集也是干货云集,囊括了笔记类工具,营销工具,生产力工具,CSS框架,UIKit,远程协作工具,配色工具,以...

3417
来自专栏BestSDK

Android P DP3发布:SDK/API确定、彩色指纹录入等

3月份,谷歌悄然发布Android P DP1(第一版开发者预览),在上个月的I/O大会上,DP2推送,同时,谷歌宣布一加6、小米MIX 2S、vivo X21...

884
来自专栏人工智能头条

MAC开发利器—开发工程师角度的BenQ PD2710QC显示器测评

862
来自专栏小狼的世界

Segoe Font 介绍

作为微软的官方品牌字体,Segoe Font是一种非常优雅的字体,小到海报大到Logo,Segoe字体应用在微软品牌宣传的各种领域,

732
来自专栏FreeBuf

研究人员找到禁用Intel ME组件的方法(乡村故事版)

本文试图以故事形式还原PositiveTechnologies公司找到禁用IntelME组件方法的消息,祝各位阅读愉快。 (1)清晨鸡鸣响彻天 ? 喔喔喔~喔喔...

3405
来自专栏无原型不设计

4款APP原型设计工具助你搞定移动应用设计!

1544
来自专栏罗超频道

与苹果斗争,可以不优雅,但要有用

原创2015-03-26罗超 苹果一直顽固地控制着iPhone的用户体验,通过封闭的操作系统和中心化的分发机制,还有技术上著名的“沙盒机制”。这个机制下一个Ap...

3187

扫码关注云+社区