发布时间:2025-06-24 18:54:38  作者:北方职教升学中心  阅读量:066


传说中,这群波拉哩的共同祖先是一只叫“塔坦”的超级波拉哩,塔坦的职责就是守护宇宙瑰宝“荆棘之花”,它拥有强大的能量,会分出分身,变化万物,唯一的弱点就是贪吃。

在这里插入图片描述

游戏以玩家间的实时互动PK为设计宗旨,通过简单的规则将玩家操作直接转化为游戏策略,体验智谋碰撞的战斗乐趣。

运动状态包括:

  • 位置
  • 移动方向
  • 时间戳

模拟步骤:

  • 在收到运动状态改变时,根据运动改变时的位置,方向,以及当前时间戳与运动改变时的时间戳的差值,计算出当前应该所在的位置 p0
  • 玩家节点当前实际所在位置 p1,p0 - p1(向量减法),即为校正后的运动路径
  • 对路径进行模拟,直至下次运动状态改变

球控制器,当前客户端需要添加组件,由用户输入直接移动,并触发移动同步

constBall =require("Ball");constConstants =require("../Constants");constLeanCloud =require("../LeanCloud");const{getClient }=LeanCloud;/** * 球控制器,当前客户端需要添加组件,由用户输入直接移动,并触发移动同步 */cc.Class({extends:cc.Component,properties:{},// LIFE-CYCLE CALLBACKS:onLoad(){cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN,this._onKeyDown,this);cc.systemEvent.on(cc.SystemEvent.EventType.KEY_UP,this._onKeyUp,this);this._ball =this.node.getComponent(Ball);this._direction =cc.Vec2.ZERO;},onDestroy(){cc.systemEvent.off(cc.SystemEvent.EventType.KEY_DOWN,this._onKeyDown,this);cc.systemEvent.off(cc.SystemEvent.EventType.KEY_UP,this._onKeyUp,this);},start(){this._cameraNode =cc.find("Canvas/Main Camera");},update(dt){constspeed =this._ball.getSpeed();constdelta =this._direction.normalize().mul(speed *dt);constposition =this.node.position.add(delta);const{x,y }=position;const{LEFT,RIGHT,TOP,BOTTOM}=Constants;constnewPosition =cc.v2(Math.min(Math.max(x,LEFT),RIGHT),Math.min(Math.max(y,BOTTOM),TOP));this.node.position =newPosition;// 设置摄像机跟随this._cameraNode.position =this.node.position;},_onKeyDown(event){this.running =true;letdir =this._direction.clone();switch(event.keyCode){casecc.macro.KEY.a:casecc.macro.KEY.left:dir.x =-1;break;casecc.macro.KEY.d:casecc.macro.KEY.right:dir.x =1;break;casecc.macro.KEY.w:casecc.macro.KEY.up:dir.y =1;break;casecc.macro.KEY.s:casecc.macro.KEY.down:dir.y =-1;break;default:break;}this._synchMove(dir.normalize());},_onKeyUp(event){letdir =this._direction.clone();switch(event.keyCode){casecc.macro.KEY.a:casecc.macro.KEY.left:casecc.macro.KEY.d:casecc.macro.KEY.right:dir.x =0;break;casecc.macro.KEY.w:casecc.macro.KEY.up:casecc.macro.KEY.s:casecc.macro.KEY.down:dir.y =0;break;default:break;}this._synchMove(dir.normalize());},_synchMove(dir){if(dir.fuzzyEquals(this._direction,0.01)){return;}this._direction =dir;const{x,y }=this.node.position;const{x:dx,y:dy }=this._direction;constclient =getClient();client.player.setCustomProperties({move:{p:{x,y },d:{x:dx,y:dy },t:Date.now()}});}});

项目结构

├── Animation 动画目录├── Prefabs 预制目录,主要存放球,食物预制体├── Scene 场景目录,主菜单场景,战斗场景├── Script 脚本目录│   ├── Battle 战斗相关脚本目录│   │    ├── Ball.js 球节点控制脚本│   │    ├── BallController.js 玩家控制球脚本,生成移动数据同步给其他客户端│   │    ├── BallSimulator.js 玩家运动模拟脚本,根据玩家运动数据,模拟运动行为│   │    ├── Battle.js 战场节点总控制器,用于接收并解析战斗中的自定义事件,驱动场景节点及 UI 节点变化│   │    ├── BattleHelper.js 战场工具脚本│   │    ├── Food.js 食物节点控制脚本│   │    ├── Master.js 游戏逻辑脚本,用于区分 Master 客户端与普通客户端,Master 组件用于生成房间数据及逻辑判断,只有 Master 的客户端才拥有这个组件,包括最初的房间的创建者和切换后的新房主。他们是天生的战斗种族,为战斗而生,为战斗而亡。│   │    ├── PlayerInfoItem.js 玩家信息 UI 节点控制脚本│   │    └── UI.js UI 控制脚本│   ├── Menu主菜单相关脚本目录│   │    └── Menu.js 主菜单脚本│   ├── Constants.js 游戏中用到的常量│   └── LeanCloud.js 全局存放 LeanCloud SDK 对象的脚本├── Texture 素材资源目录└── play.js LeanCloud 实时对战服务 SDK

添加wx/微信公众回复球球大作战获取完整代码

在线体验链接


欢迎评论 💬点赞👍🏻 收藏 📂加关注+



在这里插入图片描述

欢迎添加微信,加入我的核心小队,请备注来意

👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇

而在运动过程中,并不同步移动数据。

其他功能

消息处理控制

由于从主场景加载到战斗场景,存在异步的资源加载过程,所以需要暂停 / 恢复消息队列的处理。在这个球球的世界里,每个人都化身为一颗独特的球球,大球吃小球,努力生存下来就是唯一的目标。

  • 游戏结束:用于返回主菜单场景。

    在这里插入图片描述



    个人名片:

    在这里插入图片描述


    🐼作者简介:一名大三在校生,喜欢AI编程🎋
    🐻‍❄️个人主页🥇:落798.
    🐼个人WeChat:hmmwx53
    🕊️系列专栏:🖼️

    • 零基础学Java——小白入门必备🔥
    • 重识C语言——复习回顾🔥
    • 计算机网络体系———深度详讲
    • HCIP数通工程师-刷题与实战🔥🔥🔥
    • 微信小程序开发——实战开发🔥
    • HarmonyOS 4.0 应用开发实战——实战开发🔥🔥🔥
    • Redis快速入门到精通——实战开发🔥🔥🔥
    • RabbitMQ快速入门🔥
      🐓每日一句:🍭我很忙,但我要忙的有意义!
      欢迎评论 💬点赞👍🏻 收藏 📂加关注+


    文章目录

    • BallBattle
      • 简介
      • 背景设定
      • 玩法
      • 主要功能
        • 匹配对战
        • 属性同步与保存
          • 房间属性
          • 玩家属性
        • 自定义事件
        • 其他功能
          • 消息处理控制
          • 移动同步
      • 项目结构
      • 欢迎添加微信,加入我的核心小队,请备注来意


    BallBattle

    简介

    《球球大作战》是一款由巨人网络Superpop&Lollipop工作室自主研发,并且免费(不包括道具)的手机网络游戏。

    在这里插入图片描述

    玩法

    输入房间 ID,加入房间(如果没有此房间,则创建)。
    用户 ID 随机生成。
    右侧面板显示当前房间的玩家体重排行榜。

    更多关于属性同步文档

    房间属性
    • 房间用时
    • 战场的食物列表
    • 食物最大 ID

    食物:

    /** * 食物 */cc.Class({extends:cc.Component,properties:{id:0,type:0},getProperties(){constid =this.id;consttype =this.type;const{x,y }=this.node.position;return{id,type,x,y      // 可能还会有能量值};}});
    玩家属性
    • 位置
    • 体重
    • 速度

    球:

    constConstants =require("Constants");constFood =require("./Food");/** * 球 */cc.Class({extends:cc.Component,properties:{nameLabel:{type:cc.Label,default:null},infoLabel:{type:cc.Label,default:null}},init(player){this.player =player;},eat(){// 计算尺寸const{weight }=this.player.customProperties;constscale =Math.sqrt(weight)/Constants.BORN_SIZE;this.node.scale =cc.v2(scale,scale);},reborn(){// 计算尺寸const{weight,pos }=this.player.customProperties;constscale =Math.sqrt(weight)/Constants.BORN_SIZE;this.node.scale =cc.v2(scale,scale);// 位置const{x,y }=pos;this.node.position =cc.v2(x,y);},getId(){returnthis.player.actorId;},getSpeed(){const{speed }=this.player.customProperties;returnspeed;},getWeight(){constcollider =this.node.getComponent(cc.CircleCollider);const{radius }=collider;const{scaleX,scaleY }=this.node;returnConstants.PI*Math.pow(radius,2)*scaleX *scaleY;},// LIFE-CYCLE CALLBACKS:start(){this.nameLabel.string =this.player.userId;},update(dt){const{x,y }=this.node;this.infoLabel.string =`(${parseInt(x)}, ${parseInt(y)})`;},// 碰撞onCollisionEnter(other,self){const{group:otherGroup }=other.node;if(otherGroup ===Constants.FOOD_GROUP){this._onCollideFood(other,self);}elseif(otherGroup ===Constants.BALL_GROUP){this._onCollideBall(other,self);}},_onCollideFood(other,self){// 球碰食物,客户端模拟const{node:foodNode }=other;const{x,y }=self.node.position;cc.log(`collide food: (${x}, ${y})`);constfood =foodNode.getComponent(Food);foodNode.active =false;// 交由 Master 处理constevent =newcc.Event.EventCustom(Constants.BALL_AND_FOOD_COLLISION_EVENT,true);event.detail ={ball:this,food    };this.node.dispatchEvent(event);},_onCollideBall(other,self){const{node:b1Node }=other;const{node:b2Node }=self;constevent =newcc.Event.EventCustom(Constants.BALL_AND_BALL_COLLISION_EVENT,true);event.detail ={b1Node,b2Node    };this.node.dispatchEvent(event);}});

    自定义事件

    • 玩家出生:对于当前玩家,执行战场初始化逻辑;对于其他玩家,执行增加玩家逻辑。
    移动同步

    移动同步实现思路是玩家在运动状态改变时,将当前运动状态同步给其他客户端,其他客户端对玩家行为进行模拟。2015年5月27日由巨人网络在中国大陆发行。

    线上体验

    背景设定

    在宇宙深处一片遍布着荆棘之花的神秘星云中,生活着一群名叫“波拉哩”(译名“球球”)的奇特生物。

  • 玩家离开:用于移除场景和 UI 对应节点。

    主要功能

    匹配对战

    最基础的房间 ID 匹配。

    为了那甜蜜的希望,波拉哩们战斗着。从此,波拉哩的族群就受到了贪食的诅咒,只能在这片星云中无休止的战斗,如果停止战斗,生命便会流失,消亡在茫茫的星空之中。流程如下:

    • 加入房间
    • 暂停消息处理
    • 加载战斗场景
    • 初始化战场
    • 恢复消息队列。他们外表萌萌,却有着勇敢的心。在漫漫的历史长河里,只有最强大的波拉哩才能冲过这片黑暗星云,打破命运的枷锁,去寻找那传说中的光明与和平。
    • 吃食物:客户端移除内存中的食物节点,同步玩家体重。

      一天,塔坦终于禁不住诱惑,偷食了“荆棘之花”,结果身体爆裂,成为了数以亿计的小波拉哩。他们必须奋力奔跑,让自己变大变大再变大,才能对抗比自己更强的存在。

    • 杀死玩家:用于同步节点间碰撞事件。
    • 玩家重生:用于重新初始化玩家数据。
      使用 ⬆️⬇️⬅️➡️ 或 WSAD 来控制小球移动,吃掉场景中的食物(三角形,方形,六边形)则会增长体重(并减少速度);遇到其他球(玩家),碰撞之后,体重较大者获胜,较小者将会死亡并重生。

      更多关于房间匹配文档

      属性同步与保存

      这个 demo 使用的是 Master Client 机制,但由于 Master Client 可能存在掉线等异常情况,所以需要将房间和玩家的部分数据保存至 Room Properties 和 Player Properties。

    • 生成食物:同步房间内的食物数据。哪怕经历无数失败也必须重新凝聚力量,直到成为最强壮的那个。