【从零开始学Skynet】实战篇《球球大作战》(十三):场景代码设计(下)
1、主循环
service/scene/init.lua中新增的内容:
function update(frame)food_update()move_update()eat_update()--碰撞略--分裂略
end
现在思考一个问题,怎样开启稳定的定时器?可以开启一个死循环协程,协程中调用update,最后用skynet.sleep让它等待一小段时间。定义服务初始化方法init:
s.init = function()skynet.fork(function()--保持帧率执行local stime = skynet.now()local frame = 0while true doframe = frame + 1local isok, err = pcall(update, frame)if not isok thenskynet.error(err)endlocal etime = skynet.now()local waittime = frame*20 - (etime - stime)if waittime <= 0 thenwaittime = 2endskynet.sleep(waittime)endend)
end
- 它会调用skynet.fork开启一个协程,协程的代码位于匿名函数中。
- pcall是为安全调用update而引入的,它的功能可以参照前面的xpcall。
- waittime 代表每次循环后需等待的时间。
- 由于程序有可能卡住,我们很难保证“ 每隔 0.2 秒调用一次 update” 是精确的。
- update 方法也需要一定的执行时间,等待时间waittime 的实际值应为 0.2减去执行时间,如下左图所示,图中 update 前的竖直黑线代表 update 的执行时间。
- 若某次执行时间超过间隔(如下右图 第 0.2 秒执行的 update ),则程序需要加快执行,只能给很短的间隔时间。使得运行较长时间后,最终会在第N 秒执行 N×5 次 update 。
2、移动逻辑
function move_update()for i, v in pairs(balls) dov.x = v.x + v.speedx * 0.2v.y = v.y + v.speedy * 0.2if v.speedx ~= 0 or v.speedy ~= 0 thenlocal msg = {"move", v.playerid, v.x, v.y}broadcast(msg)endend
end
由于主循环会每隔0.2秒调用一次move_update,因此它只需遍历场景中的所有球,根据“路程 = 速度 × 时间”计算出每个球的新位置,再广播move协议通知所有客户端即可。
3、生成食物
function food_update()if food_count > 50 thenreturnendif math.random( 1,100) < 98 thenreturnendfood_maxid = food_maxid + 1food_count = food_count + 1local f = food()f.id = food_maxidfoods[f.id] = flocal msg = {"addfood", f.id, f.x, f.y}broadcast(msg)
end - 判断食物总量:场景中最多能有50个食物,多了就不再生成;
- 控制生成时间:计算一个 0 到 100 的随机数,只有大于等于 98 才往下执行,即往下执行的概率是1/50 。由于主循环每 0.2 秒调用一次 food_update,因此平均下来每 10 秒会生成一个食物。
- 生成食物:创建 food 类型对象 f ,把它添加到 foods 列表中,并广播addfood 协议。生成食物时,会更新食物总量 food_count 和食物最大标识food_maxid 。
4、吞下食物
function eat_update()for pid, b in pairs(balls) dofor fid, f in pairs(foods) doif (b.x-f.x)^2 + (b.y-f.y)^2 < b.size^2 thenb.size = b.size + 1food_count = food_count - 1local msg = {"eat", b.playerid, fid, b.size}broadcast(msg)foods[fid] = nil --warmendendend
end
代码中变量名的含义如下:
- pid:即playerid,指遍历到的小球对应的玩家id。
- b:遍历到的ball对象。
- fid:遍历到的食物id。
- f :遍历到的 food 对象。
说明:本篇的场景服务代码更多的是为了演示如何使用框架, 没有很多性能考究。比如在eat_update代码中,双重嵌套for循环的计算量较大。在实际项目中,往往会使用一些简化的计算方法(后面会有简单的描述)。
至此,完成了场景服务的所有代码。
5、主服务修改
--scene (sid->sceneid)
for _, sid in pairs(runconfig.scene[mynode] or {}) dolocal srv = skynet.newservice("scene", "scene", sid)skynet.name("scene"..sid, srv)
end 说明: 为简单起见,演示程序会开启固定数量的场景服务。在 实际项目中,可以仿照agent 动态开启场景服务。
完整项目地址:https://gitee.com/frank-yangyu/ball-server
相关文章:
【从零开始学Skynet】实战篇《球球大作战》(十三):场景代码设计(下)
1、主循环 《球球大作战》是一款服务端运算的游戏,一般会使用主循环程序结构,让服务端处理战斗逻辑。如下图所示,图中的 balls 和 foods代表服务端的状态,在循环中执行“ 食物生成”“位置更新”和“碰撞检 测” 等功能࿰…...
2023年虚拟数字人行业研究报告
第一章 行业概况 虚拟数字人指存在于非物理世界中,由计算机图形学、图形渲染、动作捕捉、深度学习、语音合成等计算机手段创造及使用,并具有多种人类特征(外貌特征、人类表演能力、人类交互能力等)的综合产物。虚拟人可分为服务型…...
Oracle 之表的连接类型——舞蹈跳出
嵌套循环(Nested Loops Join) Oracle 中最基本的连接方法,用于处理数据表之间的连接操作。 嵌套循环是通过对其中一个表(外部表)进行全循环操作,然后针对每条记录在另一张表(内部表)…...
深入浅出JS定时器:从setTimeout到setInterval
前言 当谈到 JavaScript 编程语言最基本的概念时,定时器就是一个必须掌握的知识点。在编写网站时,你经常会遇到需要在一定时间间隔内执行一些代码的情况。这时候,JavaScript 定时器就可以派上用场了。 什么是定时器? JS 定时器是…...
CountDownLatch、CyclicBarrier、Semaphore 的原理以及实例总结
文章目录 CountDownLatch、CyclicBarrier、Semaphore 的原理以及实例总结一、CountDownLatch二、CyclicBarrier三、Semaphore总结 CountDownLatch、CyclicBarrier、Semaphore 的原理以及实例总结 在Java多线程编程中,有三种常见的同步工具类:CountDownL…...
企业电子招投标系统源码之了解电子招标投标全流程
随着各级政府部门的大力推进,以及国内互联网的建设,电子招投标已经逐渐成为国内主流的招标投标方式,但是依然有很多人对电子招投标的流程不够了解,在具体操作上存在困难。虽然各个交易平台的招标投标在线操作会略有不同࿰…...
SpringCloud之Gateway组件简介
网关的理解 网关类似于海关或者大门,出入都需要经过这个网关。别人不经过这个网关,永远也看不到里面的东西。可以在网关进行条件过滤,比如大门只有对应的钥匙才能入内。网关和大门一样,永远暴露在最外面 不使用网关 前端需要记住每…...
GoNote第三章 主流框架加对比
GoNote第三章 主流框架加对比 Golang主流框架介绍 自从面市以来,Golang成为了程序员在编写API和开发Web服务时的首选之一。近90%的受访者表示会在自己下一组项目中持续使用Golang。与我们熟悉的C和C类似,Go语言也是现有Golang的“灵魂”。而Golang则是…...
Quartz框架详解分析
文章目录 1 Quartz框架1.1 入门demo1.2 Job 讲解1.2.1 Job简介1.2.2 Job 并发1.2.3 Job 异常1.2.4 Job 中断 1.3 Trigger 触发器1.3.1 SimpleTrigger1.3.2 CornTrigger 1.4 Listener监听器1.5 Jdbc store1.5.1 简介1.5.2 添加pom依赖1.5.3 建表SQL1.5.4 配置文件quartz.propert…...
Nginx专题-基于多网卡的主机配置
文章目录 Nginx 基于多网卡的主机实现一、虚拟机前置环境准备ifcfg-ens32配置文件的内容参考ifcfg-ens33配置文件的内容 二、案例演示修改nginx.conf配置文件解决中文乱码 Nginx 基于多网卡的主机实现 一、虚拟机前置环境准备 点击虚拟机右下角的 红色标框按钮,然后…...
4.2和4.3、MAC地址、IP地址、端口
计算机网络等相关知识可以去小林coding进行巩固(点击前往) 4.2和4.3、MAC地址、IP地址、端口 1.MAC地址的简介2.IP地址①IP地址简介②IP地址编址方式③A类IP地址④B类IP地址⑤C类IP地址⑥D类IP地址⑧子网掩码 3.端口①简介②端口类型 1.MAC地址的简介 …...
放弃 console.log 吧!用 Debugger 你能读懂各种源码
很多同学不知道为什么要用 debugger 来调试,console.log 不行么? 还有,会用 debugger 了,还是有很多代码看不懂,如何调试复杂源码呢? 这篇文章就来讲一下为什么要用这些调试工具: console.lo…...
epoll机制解析
一、epoll实现原理 1、实现原理 epoll通过3个方法来实现对句柄的监控操作,要深刻理解epoll,首先得了解epoll的三大关键要素:mmap、红黑树、链表。下面是epoll的框架图,如下: mmap epoll是通过内核与用户空间mmap同一块…...
基于 SpringBoot + Vue 实现的可视化拖拽编辑的大屏项目
今天给小伙伴们分享一个基于 SpringBoot Vue 实现的可视化拖拽编辑的大屏项目; 一、简介 这个是一个开源的一个BI平台,酷炫大屏展示,能随时随地掌控业务动态,让每个决策都有数据支撑。 多数据源支持,内置mysql、el…...
我们为什么要写作?
为什么要写书是一个很难回答的问题,因为从不同的角度,会有不同的答案。 最近ChatGPT很火!诸事不决,先问问ChatGPT,看看它是怎么回答的。 ChatGPT给出的答案还是比较全,虽然没有“一本正经的胡说八道”&…...
设计模式:创建者模式 - 建造者模式
文章目录 1.概述2.结构3.实例4.优缺点5.使用场景6.模式扩展 1.概述 将一个复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。 分离了部件的构造(由Builder来负责)和装配(由Director负责)。 从而可以构造出复杂的对象。这个模式适用于:某…...
String a = new String(“abc“); 创建了几个对象?String a = “abc“; 呢?
String a new String(“abc”); 创建了几个对象?String a “abc”; 呢? 答案:String a new String(“abc”); 创建了1个或2个对象;String a “abc”; 创建了0个或1个都对象 String a new String(“abc”); 创建过程 首先在…...
keepalived+nginx安装
欢迎使用ShowDoc! 1、安装基础包: yum -y install libnl libnl-devel 2、上传包: tar -zxvf keepalived-2.0.20.tar.gz -C /data/imas/base_soft mkdir -p /data/imas/base_soft/keepalived cd /data/imas/base_soft/keepalived-2.0.20 .…...
硬盘格式化工具,强烈推荐这个!
案例:硬盘格式化工具推荐 【我的电脑已经用了好几年了,硬盘存储容量严重不够了,最近想把它格式化,但却不知道怎么操作,大家有什么比较好的硬盘格式化工具可以推荐吗?】 硬盘作为存储设备,我们…...
Python的异常捕获和处理
程序在运行过程当中,不可避免的会出现一些错误,比如:使用了没有赋值过的变量,使用了不存在的索引,一个数字除以0 …… 这些错误在程序中,我们称其为异常。 程序运行过程中,一旦出现异常将会导致…...
工业安全零事故的智能守护者:一体化AI智能安防平台
前言: 通过AI视觉技术,为船厂提供全面的安全监控解决方案,涵盖交通违规检测、起重机轨道安全、非法入侵检测、盗窃防范、安全规范执行监控等多个方面,能够实现对应负责人反馈机制,并最终实现数据的统计报表。提升船厂…...
页面渲染流程与性能优化
页面渲染流程与性能优化详解(完整版) 一、现代浏览器渲染流程(详细说明) 1. 构建DOM树 浏览器接收到HTML文档后,会逐步解析并构建DOM(Document Object Model)树。具体过程如下: (…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
基于PHP的连锁酒店管理系统
有需要请加文章底部Q哦 可远程调试 基于PHP的连锁酒店管理系统 一 介绍 连锁酒店管理系统基于原生PHP开发,数据库mysql,前端bootstrap。系统角色分为用户和管理员。 技术栈 phpmysqlbootstrapphpstudyvscode 二 功能 用户 1 注册/登录/注销 2 个人中…...
BLEU评分:机器翻译质量评估的黄金标准
BLEU评分:机器翻译质量评估的黄金标准 1. 引言 在自然语言处理(NLP)领域,衡量一个机器翻译模型的性能至关重要。BLEU (Bilingual Evaluation Understudy) 作为一种自动化评估指标,自2002年由IBM的Kishore Papineni等人提出以来,…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...
ubuntu系统文件误删(/lib/x86_64-linux-gnu/libc.so.6)修复方案 [成功解决]
报错信息:libc.so.6: cannot open shared object file: No such file or directory: #ls, ln, sudo...命令都不能用 error while loading shared libraries: libc.so.6: cannot open shared object file: No such file or directory重启后报错信息&…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...
