欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Lua游戏开发教程之时区问题详解

程序员文章站 2022-01-20 06:06:27
前言 什么是lua? lua 是一个小巧的脚本语言,巴西里约热内卢天主教大学里的一个研究小组于1993年开发,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩...

前言

什么是lua?

lua 是一个小巧的脚本语言,巴西里约热内卢天主教大学里的一个研究小组于1993年开发,其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。lua由标准c编写而成,几乎在所有操作系统和平台上都可以编译,运行。一个完整的lua解释器不过200k,在目前所有脚本引擎中,lua的速度是最快的。这一切都决定了lua是作为嵌入式脚本的最佳选择。相比python和per的内核,lua的内核小于120kb,而python的内核大约860kb,perl的内核大约1.1mb。lua语言支持面向对象编程和函数式编程,它提供了一个通用类型的表table,可以实现数组、哈希表、集合、对象的功能。lua支持协同进程机制。作为一门可扩展的语言,lua提供简单而稳定的交互接口,如lua和c程序可通过一个堆栈交换数据,这使得lua语言可以快速地和其它语言实现整合。

总体来说,lua语言具备以下优点:

(1)语言优美、轻巧

(2)性能优良、速度快

(3)可扩展性强。

正因为lua语言具备了这样的特点,使得它能和游戏开发领域的需求完美地结合起来,因为我们需要这样的一门语言,它能够和c/c++进行完美地交互,因为我们需要它对底层进行封装。它需要足够地简单,因为我们需要简单、灵活、快速地编写代码。那么显然lua就是我们一直在寻找地这种语言。

目前大部分游戏都采用了lua语言进行功能开发,在进行多语种发行的时候就会遇到时区显示的问题。以韩国版本为例,场景如下:

1、服务器处于固定的位置,比如放在首尔机房;

2、玩家所处的位置不确定,可能在韩国,或者是出差在其它国家或地区;

需求:

无论在哪个国家或地区,统一显示服务器的当前时间。在pc上查看,即便在国内测试的时候也显示韩国首尔的时间(比北京时间快1个小时)。

实现:

关注是这个方法: os.date("!*t", now),其中以!为关键。

lua 源码, loslib.c line 283 行

从源码可以看到 ! 调用了

gmtime_r 函数是标准的posix函数,它是线程安全的,将日历时间转换为用utc时间表示的时间。

注:utc —— 协调世界时,又称世界统一时间、世界标准时间

也就是说 “!*t” 得到的是一个 utc 时间,为0度的经线(子午线),亦称本初子午线,通常将它与gmt视作等同(但是utc更为科学和精确)。

Lua游戏开发教程之时区问题详解

Lua游戏开发教程之时区问题详解 

首尔位于东9区,所以实际的时间应该是 utc + 9,9就是时区差 —— 9个小时。北京位于东8区,即 utc + 8。

如何保证游戏内全部统一为服务器的时间呢?

服务器需要返回给客户端当前的时区的差值,比如韩国就返回 9,国内就返回 8,越南返回 7,北美返回 –16,记为 servertimezone。

服务端返回当前服务器时间servertime(即首尔当前时间),我们只需要将服务器时间转为 utc 的时间,然后再加上 servertimezone即可。

这样无论在哪个地区或国家,都将显示首尔的时候,与服务器显示的时间就同步上了。

为什么要一直显示服务器的时间呢?

游戏中有很多功能是有时间限制的,比如运营活动,或者功能开启。如果用本地时间就不好控制,统一用服务器时间避免了很多问题。

可是也容易遇到一个坑,运营配置的活动时间都是针对当前服务器的时间,例如某个活动的截止时间是:2018-10-08 00:00:00,游戏需要显示活动截止倒计时。

通常的做法: ployendtime – servertime,得到一个秒数,然后将秒转成:xx天xx小时xx分xx秒

servertime 是固定的,可是ployendtime就容易出错,为什么?

servertime 是在东9区 —— 首尔的时间,而 os.time({year=…}) 是根据本地时间来算时间的,这中间就存在问题。有一个时差的问题,之前计算一直用的是servertimezone —— 一个固定值,而我当前处于地区或国家,它相对于utc的时区不确定的,怎么办?

用 (currtimezone – servertimezone) * 3600 / 秒,os.time()之后再加上这个时区差就是首尔当前的时间戳了。国内东8 - 东9  = -1,也就是要减去一个1时区,最终将得到首尔地区的时间戳,再减去 servertime 就是剩下的秒数了,然后将它转为 xx 天 xx 小时 xx 分 xx 秒。

最后小结一下:

1)os.time({year=xx}),这个时间算出来的是针对当前所处时区的那个时间戳。

2)os.date(“!*t”, 时间戳) 得到的是utc(时区为0)的时间戳。

3)获取当前时区的值,可以通过文章开头的 gettimezone 方法

4)想显示固定时区的时间(例如无论在哪都显示服务器的时间),只需要将(服务器)时间戳(秒),通过第2步的方法,得到 utc 再加上固定的时区差

5)计算倒计时的时候,需要考虑到 os.time 是取当前时区,需要再将当前时区减去目标时区,再计划时间戳

6)夏令时,本身已经拨快了一个小时,当需要显示为固定时区的时间,则需要减去一个小时

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。