目录

小游戏介绍

小游戏cocos creator场景图

小游戏部分JS代码

开发中碰到的问题

工程及说明


小游戏介绍

贪吃蛇小游戏:贪吃蛇试玩(首次加载比较慢),类似贪吃蛇大作战的小游戏。当玩家的蛇头碰到另一条蛇蛇身时死亡,游戏结束。

小游戏cocos creator场景图

小游戏的cocos creator节点结构如下图,Canvas上面的节点是单例(DataManager SoundManager Global  WeiXinPlatform)

贪吃蛇大作战

贪吃蛇大作战

贪吃蛇大作战大厅
​​

cocos creator 层级

小游戏部分JS代码

小游戏操控摇杆的JS代码参考github上的,https://github.com/dreeye/Joystick

一个全局变量节点Global.js,保存了其它单例的指针,游戏中通过GameGlobal调用其它单例的接口

cc.Class({extends: cc.Component,properties: {//数据管理器DataManager:{default: null,type: cc.Component,},//声音管理器SoundManager:{default: null,type: cc.Component,   },//UI管理器UIManager:{default: null,type: cc.Component,      },//GameGame:{default: null,type: cc.Component,    },//Net:{default: null,type: cc.Component,        },//WeiXinPlatform:{default: null,type: cc.Component,           },NameList:[],//单机测试版IsSingleMode: true,//统一为微信QQ的localStoragelocalStorage: null,//版本号:GameVersion: '1.0.0'},// LIFE-CYCLE CALLBACKS:onLoad () {this.DataManager = cc.find('DataManager').getComponent('DataManager');this.SoundManager = cc.find('SoundManager').getComponent('SoundManager');this.UIManager = cc.find('Canvas/UIManager').getComponent('UIManager');this.Game = cc.find('Game').getComponent('Game');this.Net = cc.find('Net').getComponent('Net');this.WeiXinPlatform = cc.find('WeiXinPlatform').getComponent('WeiXinPlatform');this.localStorage = {getItem(itemKey){if(cc.sys.platform == cc.sys.WECHAT_GAME){}else if(cc.sys.platform == cc.sys.QQ_PLAY){//return BK.localStorage.getItem(itemKey);}else{return cc.sys.localStorage.getItem(itemKey);}} ,setItem(itemKey, item){if(cc.sys.platform == cc.sys.WECHAT_GAME){}else if(cc.sys.platform == cc.sys.QQ_PLAY){//return BK.localStorage.setItem(itemKey, item);}else{return cc.sys.localStorage.setItem(itemKey, item);}            }};window.GameGlobal = this;},start () {   },// update (dt) {},});

UIManager.JS UI的管理类

//UI管理类(处理打开与关闭, TODO: 管理UI层级, UI的打开方式)var UIType = require("UIType");cc.Class({extends: cc.Component,properties: {//UIList:{default: [],type: [cc.Node],        },//通用遮罩BgMaskSprite:{default: null,type: cc.Sprite,},},// LIFE-CYCLE CALLBACKS:// onLoad () {},onEnable(){this.BgMaskSprite.node.active = false;    },start () {},//获取UI对应的脚本getUIScriptName(uiType){var scriptList = ['UIHall', 'UIGame', 'UIGameOver', 'UILoading', 'UIGameEnd', 'UIShare', 'UIMessageTip','UIKeFu', 'UIInviteFriend', 'UIQianDao', 'UISkin', 'UISetting', 'UIZSAd'];return scriptList[uiType];},//是否二级弹窗UIisPopUI(uiType){if(uiType == UIType.UIType_HallInvite || uiType == UIType.UIType_KeFu|| uiType == UIType.UIType_InviteFriend|| uiType == UIType.UIType_QianDao|| uiType == UIType.UIType_Setting|| uiType == UIType.UIType_RankQQ|| uiType == UIType.UIType_GameOver|| uiType == UIType.UIType_GameEnd){return true;}return false;},//showMask(isShow){this.BgMaskSprite.node.active = isShow;  },//打开UIopenUI(uiType){if(uiType >= this.UIList.length){cc.log("openUI invalid uiType, please check UIList");return;} if(this.UIList[uiType] == null || this.UIList[uiType] == undefined){cc.log("openUI invalid uiType, object null");return;   }this.UIList[uiType].active = true;//二级弹窗UI,显示遮罩if(this.isPopUI(uiType)){this.BgMaskSprite.node.active = true;  var actNode = this.UIList[uiType];actNode.scale = 0;actNode.runAction(cc.scaleTo(0.1, 1).easing(cc.easeSineIn()))}if(this.isPopUI(uiType) || uiType == UIType.UIType_Skin){//关闭大厅广告的处理var uihall = this.getUI(UIType.UIType_Hall);if(uihall != null && uihall.node.active){uihall.pauseAdShow();    }}},//关闭UIcloseUI(uiType){if(uiType >= this.UIList.length){cc.log("closeUI invalid uiType, please check UIList");return;} //二级弹窗UI,关闭遮罩if(this.isPopUI(uiType)){this.BgMaskSprite.node.active = false;   this.UIList[uiType].active = false;//var actNode = this.UIList[uiType];//actNode.scale = 1;// var callbackClose = cc.callFunc(this.onCloseUI, this, uiType);// var seq = cc.sequence(cc.scaleTo(0.2, 0).easing(cc.easeBounceOut(3) ), callbackClose)// actNode.runAction(seq)}else{this.UIList[uiType].active = false;}if(this.isPopUI(uiType) || uiType == UIType.UIType_Skin){//QQ广告恢复展示var uihall = this.getUI(UIType.UIType_Hall);if(uihall != null && uihall.node.active){uihall.resumeAdShow();    }}},//关闭UIonCloseUI(node, uiType){this.UIList[uiType].active = false;},//获取某个UI getUI(uiType){if(uiType >= this.UIList.length){cc.log("closeUI invalid uiType, please check UIList");return;} return this.UIList[uiType].getComponent(this.getUIScriptName(uiType)); },//显示某个消息showMessage(msg){var uiMessageTip = this.getUI(UIType.UIType_ShowMessage); if(uiMessageTip){uiMessageTip.showMessage(msg);                              }                                },//刷新货币RefreshCoin(){var hallUI = this.getUI(UIType.UIType_Hall)hallUI.updateGoldNum()hallUI.updateDiamondNum()},// update (dt) {},
});

Snake.js 游戏中的蛇 小部分代码

var SnakeBody = require('SnakeBody');
var SnakeHead = require('SnakeHead');cc.Class({//蛇头properties: {_SnakeIndex: 0,_HeadType: -1,_BodyTypeList: [],_SnakeHead: cc.Node,_HeadBodyList: [cc.Node],_Game: null,_LastMoveVec: cc.v2(1, 0),_MoveVec: cc.v2(1, 0),_MoveSpeed: 0,_BodyWidth: 0,//增加的重量_GrowingWeight: 0,_Camera: null,_PlayerSelf: false,_PlayerName: "",_MapWidth: 0, _MapHeight: 0,_BodyTypeList:[],//击杀_KillCount: 0,//更新时间_PosUpdateTime: 0,_HeadPrePositon: cc.v2(1, 0),//AI 类型_CurAIType: 1,_CurAITimer: 2,_CurAIMoveCount: 0,_CurTargetDestDir: cc.v2(1, 0),_CurTargetChangeDir: cc.v2(0, 0),_CurAITurnSpeed: 3.14,_State: 0,_StateTimer: 3,_AttachLabel: null,//大厅展示用_CurShowMoveDistance: 0,_CurShowMoveStartPos: cc.v2(0, 0),_ShowMovePosList:[],_CurMoveIndex: 0,//躲避概率//蛇移动路径列表_MovePath: [],_BodySpace: 30,//保护罩_GodSprite: null,},init(headType, bodyTypeList, parent, bornPos, camera, isSelf, mapWidth, mapHeight, index){this._SnakeIndex = index;this._State = 0;this._KillCount = 0;this._Game = GameGlobal.Game;this._Camera = camera;this._PlayerSelf = isSelf;this._MapWidth = mapWidth;this._MapHeight = mapHeight;this._HeadType = headType;this._BodyTypeList = bodyTypeList;//蛇头this._SnakeHead =  this._Game.GetFreeHead();this._SnakeHead.parent = parent;this._SnakeHead.position = bornPos;this._SnakeHead.setLocalZOrder(1);var snakeHead = this._SnakeHead.getComponent(SnakeHead);snakeHead.setSnake(this);snakeHead.setType(headType);if(camera){camera.addTarget(this._SnakeHead)}this._CurTargetChangeDir = cc.v2(0.996, 0.0871); //蛇身for(var i = 0; i < 5; ++i){var body = this._Game.GetFreeBody();if(body){this._HeadBodyList.push(body);  body.parent = parent;var snakeBody = body.getComponent(SnakeBody);snakeBody.setSnake(this);snakeBody.setBodyIndex(i);body.setLocalZOrder(-i);if(camera){camera.addTarget(body);}var typeIndex = (Math.floor(i / 3)) % 2;snakeBody.setType(bodyTypeList[typeIndex]);this._BodyWidth = body.width;}}if(index < 10){this._GodSprite = GameGlobal.Game.GetFreeGodSprite();this._GodSprite.parent = parent;this._GodSprite.active = false;camera.addTarget(this._GodSprite)}},setName(name, parentNode){this._PlayerName = name;this._AttachLabel = this._Game.GetFreeNameLabel();this._AttachLabel.getComponent(cc.Label).string = name;this._AttachLabel.parent = parentNode;this._AttachLabel.position = this._SnakeHead.position;if(this._Camera){this._Camera.addTarget(this._AttachLabel);}},addKillCount(){this._KillCount += 1;},//0:普通状态 1:无敌状态 (死亡刚复活时,给予2秒的无敌,不参与碰撞检测)setState(state){this._State = state;if(state == 1){this._StateTimer = 3;// this._GodSprite.active = true;this.updateGodSpritePos();//console.log("first ", this._GodSprite.width, this._SnakeIndex);}else{this._GodSprite.active = false;}},//死亡重置deadReset(){//将头与身体返回到对象池中,并重置数据this._Game.DelUseHead(this._SnakeHead);this._Game.DelGodSprite(this._GodSprite);//TODO:待优化var len = this._HeadBodyList.length;for(var i = 0; i < len; ++i){this._Game.DelUseBody(this._HeadBodyList[i]);}this._HeadBodyList.splice(0, len);this._SnakeHead = null;this._Game.DelUseNameLabel(this._AttachLabel);},//resetPos(bornPos){this._SnakeHead.position = bornPos;     },initMoveDir(moveDir){moveDir.normalizeSelf(); var len = this._HeadBodyList.length;var body;var snakeBody;for(var i = 0; i < len; ++i){body = this._HeadBodyList[i];var bodyWidth = body.getContentSize().width;//cc.log('bodyWidth ', bodyWidth);snakeBody = body.getComponent(SnakeBody);snakeBody.setInitMoveDir(moveDir);if(i == 0){var interval = bodyWidth / 3; //this._SnakeHead.width / 2 + body.width / 2;// body.position = cc.pAdd(this._SnakeHead.position, cc.pMult(moveDir, interval)); //this._SnakeHead.position; }else{var interval = - bodyWidth;//body.position =  cc.pAdd(this._HeadBodyList[i - 1].position, cc.pMult(moveDir, interval));   }}this._LastMoveVec = moveDir;this._MoveVec = moveDir;//头的方向var curAngle = Math.atan2(moveDir.y, moveDir.x) * (180/Math.PI);this._SnakeHead.rotation = -curAngle - 90;var startPos = this._SnakeHead.position;//初始化paththis._MovePath = [];for(let i = 0; i < len * this._BodySpace; ++i){this._MovePath.push(cc.pAdd(startPos, cc.pMult(moveDir, -(i + 1) + 15)));                        }},//主角的 移动方向 angle:角度 由操作驱动setMoveDir(offX, offY, delta, angle){if(offX == 0 && offY == 0){return;}this._MoveVec.x = offX;this._MoveVec.y = offY;this._SnakeHead.rotation = -angle - 90;//cc.log("setMoveDirangle", angle);},//其它玩家的setOtherMoveDir(x, y){if(x == 0 && y == 0){x = 1;}this._MoveVec.x = x;this._MoveVec.y = y;    this._MoveVec.normalizeSelf();//头的方向var curAngle = Math.atan2(y, x) * (180/Math.PI);this._SnakeHead.rotation = -curAngle - 90;//cc.log("setOtherMoveDir ", this._MoveVec.x, this._MoveVec.y,  this._SnakeHead.rotation);},FixDir(dir){if(dir.x == 0 && dir.y == 0){dir.x = 0.001;}return dir;},//帧更新update1(delta){if(delta == 0){delta = 0.017;}if(this._SnakeHead == null){return false;}//状态重置this._StateTimer -= delta;if(this._State == 1){if(this._StateTimer < 0){this._StateTimer = 0;this._State = 0;}}//边界位置判定if(this._PlayerSelf){if(Math.abs(this._SnakeHead.x) > this._MapWidth / 2 || Math.abs(this._SnakeHead.y) > this._MapHeight / 2){var eventObj = new cc.Event.EventCustom('meBound', true);this._SnakeHead.dispatchEvent(eventObj);return false;}}else{//其它玩家if(Math.abs(this._SnakeHead.x) > this._MapWidth / 2 - 200){if(Math.abs(this._SnakeHead.y) > this._MapHeight / 2 - 200){this.changeAI(10, cc.v2(-this._MoveVec.x, -this._MoveVec.y));    }else{this.changeAI(10, cc.v2(-this._MoveVec.x, this._MoveVec.y));}} else if(Math.abs(this._SnakeHead.y) > this._MapHeight / 2 - 200){this.changeAI(10, cc.v2(this._MoveVec.x, -this._MoveVec.y));    }this.aiUpdate(delta);}this._PosUpdateTime -= delta;var needUpdateBody = false;if(this._PosUpdateTime <= 0){// this._PosUpdateTime = 0.1;//记录上次位置this._LastMoveVec = this._MoveVec;this._HeadPrePositon = this._SnakeHead.position;needUpdateBody = true;}//更新头位置var moveVec = cc.pMult(this._MoveVec,  this._MoveSpeed *  delta); this._SnakeHead.position = this._SnakeHead.position.addSelf(moveVec); // cc.pAdd(this._SnakeHead.position, moveVec);this._AttachLabel.x = this._SnakeHead.x  /* * (moveVec.x >= 0 ? -1 : 1)*/;this._AttachLabel.y = this._SnakeHead.y + 80  /** (moveVec.y >= 0 ? -1 : 1) */;//更新身体位置var bodyLen = this._HeadBodyList.length;for(var i = 0; i < bodyLen; ++i){var snakeBody = this._HeadBodyList[i].getComponent(SnakeBody); snakeBody.updateBody(delta, this._SnakeHead, this._HeadBodyList, this._LastMoveVec, this._SnakeHead.position /*this._HeadPrePositon*/, needUpdateBody);}return true;},//新的更新update(delta){if(delta == 0){delta = 0.017;}if(this._SnakeHead == null){return false;}//边界位置判定if(this._PlayerSelf){if(Math.abs(this._SnakeHead.x) > this._MapWidth / 2 || Math.abs(this._SnakeHead.y) > this._MapHeight / 2){var eventObj = new cc.Event.EventCustom('meBound', true);this._SnakeHead.dispatchEvent(eventObj);return false;}}else{if(Math.abs(this._SnakeHead.x) > this._MapWidth / 2 - 200 || Math.abs(this._SnakeHead.y) > this._MapHeight / 2 - 200){if( this._SnakeHead.x > this._MapWidth / 2 - 200 ){this._SnakeHead.x =  this._MapWidth / 2 - 200 - 10;       }else if( this._SnakeHead.x < -(this._MapWidth / 2 - 200) ){this._SnakeHead.x =  -(this._MapWidth / 2 - 200) + 10;                      }if(this._SnakeHead.y > this._MapHeight / 2 - 200){this._SnakeHead.y =   this._MapHeight / 2 - 200 - 10;     }else if(this._SnakeHead.y < -( this._MapHeight / 2 - 200) ){this._SnakeHead.y =   -(this._MapHeight / 2 - 200) + 10;    }this.changeAI(10, cc.v2(-this._MoveVec.x, -this._MoveVec.y));    } this.aiUpdate(delta);}this._PosUpdateTime -= delta;//更新头位置var moveDis = this._MoveSpeed *  delta;var oldPos = this._SnakeHead.position;var moveVec = cc.pMult(this._MoveVec,  moveDis); this._SnakeHead.position = this._SnakeHead.position.addSelf(moveVec); // cc.pAdd(this._SnakeHead.position, moveVec);this._AttachLabel.x = this._SnakeHead.x  /* * (moveVec.x >= 0 ? -1 : 1)*/;this._AttachLabel.y = this._SnakeHead.y + 80  /** (moveVec.y >= 0 ? -1 : 1) */;var newPos ;//更新身体位置for(let i = 0; i < moveDis; ++i){newPos = cc.pAdd(oldPos, cc.pMult(this._MoveVec,  i));this._MovePath.unshift(newPos);}var bodyLen = this._HeadBodyList.length;for(var i = 0; i < bodyLen; ++i){var snakeBody = this._HeadBodyList[i].getComponent(SnakeBody); if((i + 1) * this._BodySpace < this._MovePath.length){snakeBody.node.position = this._MovePath[(i + 1) * this._BodySpace];}if(this._MovePath.length > bodyLen * (1 + this._BodySpace)){this._MovePath.pop();            }// snakeBody.updateBody(delta, this._SnakeHead, this._HeadBodyList, this._MoveVec, this._SnakeHead.position /*this._HeadPrePositon*/, needUpdateBody);}//状态重置this._StateTimer -= delta;if(this._State == 1){//更新保护罩位置this.updateGodSpritePos();if(this._GodSprite.active == false){this._GodSprite.active = true;    //console.log("second ", this._GodSprite.width, this._SnakeIndex);}if(this._StateTimer < 0 ){this._StateTimer = 0;this.setState(0);}}return true;                 },})

开发中碰到的问题

游戏工程加子域工程后,包体超过了4M,导致没法提交到微信后台。解决办法:裁剪引擎代码与压缩图片(tiny png)。裁剪代码通过 cocos creator 项目--->项目设置中去掉不用的功能模块,如下图所示,特别是子域的工程

cocos creator裁剪引擎代码

微信小游戏子域工程效率问题。如果可以的话,尽量让排行榜作为二级弹窗UI。作为主UI的话,可以降低主工程中的刷新频率。最彻底的解决办法就是不使用cocos creator提供的子域方案(主工程从自己服务器取排行榜数据或者子域使用微信原生开发)。

微信子域数据只能在子域获取,无法传递给主工程 。 主工程可以传递消息与数据给子域。 子域中有些函数也无法使用,比如本地存储等

cocos creator中的碰撞检测(collider)效率问题。当游戏中的collider数量比较多时,会出现帧率降低明显,在PC浏览器不太明显,但发布到微信后,特别是在低端安卓机上特别明显。后期可以考虑使用四叉树优化一下碰撞检测。

工程及说明

cocos creator v1.9.3版本下开发,工程中附带QQ玩一玩相关代码(使用玩一玩 vscode下的插件 qqextension 0.5.5及对应的qqplaycore)。完整工程在 "我的资源" 里下载  贪吃蛇大作战creator工程源码

cocos creator开发微信小游戏(五)贪吃蛇大作战相关推荐

  1. Cocos Creator发布微信小游戏包内体积过大问题

    1.初识 设置微信开发工具和js编辑器 3.5.2 :Cocos Creator perferences 2.Cocos Creator发布微信小游戏包内体积过大问题 2.1 已不可取:搭建本机服务器 ...

  2. Cocos Creator之微信小游戏的游戏圈

    Cocos Creator之微信小游戏的游戏圈 1.官方文档游戏圈使用指南 · 小游戏: 2.需要将游戏圈放到指定地方(比如下图,坐标为x:160,y:850,因为游戏圈图标的锚点在左上角,所在层的锚 ...

  3. Cocos creator导出微信小游戏, 转发给朋友,分享到朋友圈 灰色不能点击

    Cocos creator导出微信小游戏, 转发给朋友,分享到朋友圈 灰色不能点击 解决方法如下: onLoad(){ wx.showShareMenu({withShareTicket: true, ...

  4. python贪吃蛇论文_爆款游戏《贪吃蛇大作战》的 Python 实现

    感觉游戏审核新政实施后,国内手游市场略冷清,是不是各家的新游戏都在排队等审核.媒体们除了之前竞相追捧<Pokemon Go>热闹了一把,似乎也听不到什么声音了.直到最近几天,突然听见好几人 ...

  5. 【经典游戏】贪吃蛇大作战java游戏代码讲解

    <贪吃蛇大作战>一个简单到不行的游戏,也不知道怎么就火了.反正一款游戏火了,各路媒体.专家总能说出种种套路来,所以我就不发表意见了.不过这实在是一个挺好实现的游戏,于是一时技痒,拿 jav ...

  6. Cocos Creator Erro 4916,Failed to load scene的问题找到了!---cocos creator打包微信小游戏的坑

    首先我们来回顾一下问题 当我在用cocos微信小游戏开发的时候,发现你加上开放数据域居然不能超过8M ,wtf? 于是我把自己打包后的res文件夹放在服务器上并且删了本地的res文件.结果问题来了 这 ...

  7. JavaScript+ Canvas开发趣味小游戏《贪吃蛇》

    一.效果展示 二.<贪吃蛇>基本实现思路 蛇头部分+蛇身体部分:采用对象形式来存储坐标,并将每个坐标对象放到一个snake数组中,方便使用.设置每个方格宽度30px,高度30px,画布高度 ...

  8. 超魔性的国民游戏,贪吃蛇大作战,老板出4000元现金悬赏谁是贪吃蛇之神:这不是我嘛?

    导语​ 哈喽哈喽!每天都要开心吖

  9. Unity3d C# 开发微信小游戏分享图片、朋友圈等功能实现(含源码)

    广告 通过一段时间的基于minigame-unity-webgl-transform插件的开发,算是稍微完整的一小个游戏已经制作完成,具体大家可以扫码体验一下: 感谢支持!! 前言 之前编写了一篇u3 ...

最新文章

  1. python可视化多个机器学习模型在独立测试集(test data set)上面的AUC值、可视化模型效能
  2. php 分页类使用,php 分页类
  3. 如何避免面试中薪水要的太高或太低?
  4. ubuntu虚拟机apt报错:No module named ‘uaclient‘(替换所有的python3为/usr/bin/python3)xftp、xshell不能连接
  5. mac终端修改默认python_Mac 修改默认python的版本
  6. 检索数据_20_按照字符串数字组合的排序
  7. 就业模拟试题2_答案
  8. Intellij 14快捷键
  9. php的符号的排序大小
  10. wikioi 1034 家 实时动态的网络流量(费用流)
  11. 【树状数组】CF961E Tufurama
  12. 双拼输入法键位图_你知道双拼输入法吗?
  13. 关于360笔试部分题目小结
  14. 简单行人疏散 Java版
  15. windows update 无法启动 报错87:参数错误的解决方法
  16. HIVE 多个相同属性字段元素合并到一列中
  17. Qlik view 连接数据库
  18. 关于解决Android studio:The emulator process for AVD Pixel_4_XL_API_30 has terminated 以及改变AVD存放位置
  19. excel粘贴 粘贴值 使用VBA宏匹配目标格式
  20. 图片镜像翻转 Java

热门文章

  1. jenkin+maven+git构建项目
  2. NVidia 3060/1650S 独显笔记本 HDMI外接屏幕有输出,笔记本屏幕无输出/ubuntu 更改显卡驱动后无法进入图形界面的处理方法 以及禁止内核自动更新
  3. 操作系统资源分配管理
  4. linux 查看系统命令
  5. 鹰硕区域智慧教育云平台 AI助力搭建线上教学平台
  6. Oracle VirtualBox备份、恢复虚拟机
  7. android开源项目---View篇
  8. python预测模型
  9. 域名会到期吗?到期的域名会怎么处理呢?
  10. Linux c 目录操作函数scandir