Compare commits
80 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
70ae4a4c92 | ||
|
6f561bea87 | ||
|
70a86c27b0 | ||
|
b0f37d2237 | ||
|
09376b827d | ||
|
d560392c79 | ||
|
c75f642011 | ||
|
5cfcac6cf6 | ||
|
d37ebd4c33 | ||
|
1d138b17c3 | ||
|
851678e2f3 | ||
|
2fb6fd6bea | ||
|
e3440a2a06 | ||
|
8de2d6e4e7 | ||
|
ba2dd0b22e | ||
|
754610d31b | ||
|
a35de9b83c | ||
|
2b6cb57050 | ||
|
677e76179c | ||
|
c65c122f45 | ||
|
b5530b352b | ||
|
4e638fb2ec | ||
|
7c454130db | ||
|
5863f88435 | ||
|
bbf07fe518 | ||
|
26660d75d2 | ||
|
76cdbc8f1f | ||
|
4097a8da75 | ||
|
e7bf6ec16b | ||
|
7ab983949c | ||
|
2028f8277d | ||
|
60bb74169e | ||
|
8536521136 | ||
|
5df545e168 | ||
|
6bc3feab58 | ||
|
e21e1b840f | ||
|
ef345e0e48 | ||
|
0168e2182e | ||
|
58b06f6a10 | ||
|
58e60a789f | ||
|
b5b43bb596 | ||
|
59767c1ed5 | ||
|
1c6ad5c8f8 | ||
|
34e0893eb8 | ||
|
cc7524becd | ||
|
d06cb18a08 | ||
|
00816fb636 | ||
|
ff24bea055 | ||
|
56d66a128a | ||
|
2f097dfec5 | ||
|
ff48b47ecc | ||
|
7a0127b17d | ||
|
59c8427c70 | ||
|
c357ebad3b | ||
|
b2e1f7c2a6 | ||
|
9a8c32197e | ||
|
a82a238ce9 | ||
|
5b76c5bbfb | ||
|
b81c470135 | ||
|
48074d48af | ||
|
342efc623c | ||
|
b8e757064d | ||
|
71b9e72592 | ||
|
21b48b7c0d | ||
|
fbfca965e6 | ||
|
b27b567c77 | ||
|
e9119530f1 | ||
|
e6a4295773 | ||
|
aa14529bf8 | ||
|
84af0d1572 | ||
|
16fb23c376 | ||
|
d1f8a58154 | ||
|
89c31e8944 | ||
|
45380d170f | ||
|
dd9c03404e | ||
|
29e402ea71 | ||
|
b1e3d6525c | ||
|
845282db50 | ||
|
71a5a7b727 | ||
|
934a495d47 |
2
.gitignore
vendored
@@ -1,3 +1,5 @@
|
|||||||
|
.vs
|
||||||
|
**/.vs
|
||||||
battle_srv/test_cases/test_cases
|
battle_srv/test_cases/test_cases
|
||||||
battle_srv/test_cases/tests
|
battle_srv/test_cases/tests
|
||||||
*.pid
|
*.pid
|
||||||
|
@@ -47,3 +47,32 @@ renderFrameId | toApplyInputFrameId
|
|||||||
..., ..., ..., 368 | 90
|
..., ..., ..., 368 | 90
|
||||||
369, 370, 371, 372 | 91
|
369, 370, 371, 372 | 91
|
||||||
373, 374, 375, ... | 92
|
373, 374, 375, ... | 92
|
||||||
|
|
||||||
|
# Would using UDP instead of TCP yield better synchronization performance?
|
||||||
|
Yes, but with non-trivial efforts.
|
||||||
|
|
||||||
|
## Neat advantage using UDP
|
||||||
|
Let's check an actual use case. As soon as an inputFrame becomes all-confirmed, the server should downsync it to all active players -- and upon reception loss of the packet containing this "all-confirmed downsync inputFrame" to a certain player, the server MUST retransmit another packet containing the same inputFrame to that player.
|
||||||
|
|
||||||
|
To apply UDP on this use case, additional `ack & retransmission mechanism` would be required, which is a moderately difficult task -- don't just pick a 3rd party lib using TCP flow-control alike `sliding window mechanism`, e.g. [RUDP](https://www.geeksforgeeks.org/reliable-user-datagram-protocol-rudp/)! Here's why.
|
||||||
|
|
||||||
|
Assume that the server is downsyncing `sequence of packets[#1, #2, #3, #4, #5, #6, #7, #8, #9, #10]`, when using TCP we get the advantage that each active player is guaranteed to receive that same sequence in the same order -- however in a bad, lossy network when `packet#2` got lost several times for a certain player whose reception window size is just 5, it has to wait for the arrival of `packet#2` at `[_, #3, #4, #5, #6]`, thus unable to process `[#7, #8, #9, #10]` which could contain `unpredictable inputFrame` while `#2` being `correct prediction` for that player.
|
||||||
|
|
||||||
|
That's so neat but still an advantage for using UDP! Yet if the TCP flow-control alike `sliding window mechanism` is employed on UDP, such advantage'd be compromised.
|
||||||
|
|
||||||
|
To summarize, if UDP is used we need
|
||||||
|
- an `ack & retransmission mechanism` built on top of it to guarantee reception of critical packets for active players, and
|
||||||
|
- reception order is not necessary to be reserved (mimic [markConfirmationIfApplicable](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L1085) to maintain `lastAllConfirmedInputFrameId`), but
|
||||||
|
- TCP flow-control alike `sliding window mechanism` should be avoided to gain advantage over TCP.
|
||||||
|
|
||||||
|
## Additional hassles to care about using UDP
|
||||||
|
When using UDP, it's also necessary to verify authorization of each incoming packet, e.g. by simple time limited symmetric key, due to being connectionless.
|
||||||
|
|
||||||
|
## Why not hybrid?
|
||||||
|
Instead of replacing all use of TCP by UDP, it's more reasonable to keep using TCP for login and the "all-confirmed downsync inputFrames" from server to players (and possibly "upsync inputFrames" from player to server, but tradeoff on that remains to be discussed), while using a `UDP secondary session` for broadcasting inputFrames of each individual player asap (either using p2p or not) just for **better prediction performance**!
|
||||||
|
|
||||||
|
## How do you actually implement the `UDP secondary session`?
|
||||||
|
It's not a global consensus, but in practice many UDP communications are platform specific due to their paired asynchronous I/O choices, e.g. epoll in Linux and kqueue in BSD-ish. Of course there're many 3rd party higher level encapsulated tools for cross-platform use but that introduces extra debugging when things go wrong.
|
||||||
|
|
||||||
|
Therefore, the following plan doesn't assume use of any specific 3rd party encapsulation of UDP communication.
|
||||||
|

|
77
README.md
@@ -2,16 +2,26 @@
|
|||||||
|
|
||||||
This project is a demo for a websocket-based rollback netcode inspired by [GGPO](https://github.com/pond3r/ggpo/blob/master/doc/README.md).
|
This project is a demo for a websocket-based rollback netcode inspired by [GGPO](https://github.com/pond3r/ggpo/blob/master/doc/README.md).
|
||||||
|
|
||||||
_(the following gif is sped up to ~1.5x for file size reduction, kindly note that animations are resumed from a partial progress)_
|
As lots of feedbacks ask for a discussion on using UDP instead, I tried to summarize my personal opinion about it in [ConcerningEdgeCases](./ConcerningEdgeCases.md) -- **since v0.9.25, the project is actually equipped with UDP capabilities as follows**.
|
||||||
|
- When using the so called `native apps` on `Android` and `Windows` (I'm working casually hard to support `iOS` next), the frontends will try to use UDP hole-punching w/ the help of backend as a registry. If UDP hole-punching is working, the rollback is often less than `turn-around frames to recover` and thus not noticeable, being much better than using websocket alone.
|
||||||
|
- If UDP hole-punching is not working, e.g. for Symmetric NAT like in 4G/5G cellular network, the frontends will use backend as a UDP tunnel (or relay, whatever you like to call it). This video shows how the UDP tunnel performs for a [Phone-4G v.s. PC-Wifi (viewed by PC side)](https://pan.baidu.com/s/1IZVa5wVgAdeH6D-xsZYFUw?pwd=dgkj).
|
||||||
|
- Browser vs `native app` is possible but in that case only websocket is used.
|
||||||
|
|
||||||

|
The following video is recorded over INTERNET using an input delay of 4 frames and it feels SMOOTH when playing! Please also checkout these demo videos
|
||||||
|
- [source video of the first gif (earlier version)](https://pan.baidu.com/s/1ML6hNupaPHPJRd5rcTvQvw?pwd=8ruc)
|
||||||
|
- [source video of the second gif (added turn-around optimization & dashing)](https://pan.baidu.com/s/1isMcLvxax4NNkDgitV_FDg?pwd=s1i6)
|
||||||
|
|
||||||
Please also checkout [this demo video](https://pan.baidu.com/s/1Lmot9cb0pYylfUvC8G4fDg?pwd=ia97) to see how this demo carries out a full 60fps synchronization with the help of _batched input upsync/downsync_ for satisfying network I/O performance.
|
to see how this demo carries out a full 60fps synchronization with the help of _batched input upsync/downsync_ for satisfying network I/O performance.
|
||||||
|
|
||||||
The video mainly shows the following features.
|

|
||||||
- The backend receives inputs from frontend peers and broadcasts back for synchronization.
|
|
||||||
- The game is recovered for a player upon reconnection.
|

|
||||||
- Both backend(Golang) and frontend(JavaScript) execute collision detection and handle collision contacts by the same algorithm. The backend dynamics is togglable by [Room.BackendDynamicsEnabled](https://github.com/genxium/DelayNoMore/blob/v0.5.2/battle_srv/models/room.go#L813), but **when turned off the game couldn't support recovery upon reconnection**.
|
|
||||||
|
# Notable Features
|
||||||
|
- Backend dynamics toggle via [Room.BackendDynamicsEnabled](https://github.com/genxium/DelayNoMore/blob/v0.9.14/battle_srv/models/room.go#L786)
|
||||||
|
- Recovery upon reconnection (only if backend dynamics is ON)
|
||||||
|
- Automatically correction for "slow ticker", especially "active slow ticker" which is well-known to be a headache for input synchronization
|
||||||
|
- Frame data logging toggle for both frontend & backend, useful for debugging out of sync entities when developing new features
|
||||||
|
|
||||||
_(how input delay roughly works)_
|
_(how input delay roughly works)_
|
||||||
|
|
||||||
@@ -19,7 +29,10 @@ _(how input delay roughly works)_
|
|||||||
|
|
||||||
_(how rollback-and-chase in this project roughly works)_
|
_(how rollback-and-chase in this project roughly works)_
|
||||||
|
|
||||||
|

|
||||||

|

|
||||||
|
|
||||||
|
(By use of [GopherJs](https://github.com/gopherjs/gopherjs), the frontend codes for dynamics are now automatically generated)
|
||||||

|

|
||||||
|
|
||||||
# 1. Building & running
|
# 1. Building & running
|
||||||
@@ -27,7 +40,8 @@ _(how rollback-and-chase in this project roughly works)_
|
|||||||
## 1.1 Tools to install
|
## 1.1 Tools to install
|
||||||
### Backend
|
### Backend
|
||||||
- [Command Line Tools for Xcode](https://developer.apple.com/download/all/?q=command%20line%20tools) (on OSX) or [TDM-GCC](https://jmeubank.github.io/tdm-gcc/download/) (on Windows) (a `make` executable mandatory)
|
- [Command Line Tools for Xcode](https://developer.apple.com/download/all/?q=command%20line%20tools) (on OSX) or [TDM-GCC](https://jmeubank.github.io/tdm-gcc/download/) (on Windows) (a `make` executable mandatory)
|
||||||
- [Golang1.18.6](https://golang.org/dl/) (brought down to 1.18 for GopherJs support, mandatory, in China please try a mirror site like [that of ustc](https://mirrors.ustc.edu.cn/golang/))
|
- [Golang1.18.6](https://golang.org/dl/) (brought down to 1.18 for _GopherJs_ support, mandatory, in China please try a mirror site like [that of ustc](https://mirrors.ustc.edu.cn/golang/))
|
||||||
|
- [GopherJs1.18.0-beta1](https://github.com/gopherjs/gopherjs/tree/v1.18.0-beta1) (optional, only for developemnt)
|
||||||
- [MySQL 5.7](https://dev.mysql.com/downloads/windows/installer/5.7.html) (mandatory, for OSX not all versions of 5.7 can be found thus 5.7.24 is recommended)
|
- [MySQL 5.7](https://dev.mysql.com/downloads/windows/installer/5.7.html) (mandatory, for OSX not all versions of 5.7 can be found thus 5.7.24 is recommended)
|
||||||
- [Redis 3.0.503 or above](https://redis.io/download/) (mandatory)
|
- [Redis 3.0.503 or above](https://redis.io/download/) (mandatory)
|
||||||
- [skeema](https://www.skeema.io/) (optional, only for convenient MySQL schema provisioning)
|
- [skeema](https://www.skeema.io/) (optional, only for convenient MySQL schema provisioning)
|
||||||
@@ -60,7 +74,7 @@ user@proj-root/battle_srv/configs> cp -r ./configs.template ./configs
|
|||||||
user@proj-root/frontend/assets/plugin_scripts> cp ./conf.js.template ./conf.js
|
user@proj-root/frontend/assets/plugin_scripts> cp ./conf.js.template ./conf.js
|
||||||
```
|
```
|
||||||
|
|
||||||
## 1.2 Actual building & running
|
## 1.3 Actual building & running
|
||||||
### Backend
|
### Backend
|
||||||
```
|
```
|
||||||
### The following command runs mysql-server in foreground, it's almost NEVER run in such a way, please find a proper way to run it for yourself
|
### The following command runs mysql-server in foreground, it's almost NEVER run in such a way, please find a proper way to run it for yourself
|
||||||
@@ -89,3 +103,48 @@ ErrFatal {"err": "MISCONF Redis is configured to save RDB snapshots, but
|
|||||||
```
|
```
|
||||||
|
|
||||||
Just restart your `redis-server` process.
|
Just restart your `redis-server` process.
|
||||||
|
|
||||||
|
### 2.2 Why not show "PING value" on frontend display?
|
||||||
|
The most important reason for not showing "PING value" is simple: in most games the "PING value" is collected by a dedicated kernel thread which doesn't interfere the UI thread or the primary networking thread. As this demo primarily runs on browser by far, I don't have this capability easily.
|
||||||
|
|
||||||
|
Moreover, in practice I found that to spot sync anomalies, the following tools are much more useful than the "PING VALUE".
|
||||||
|
- Detection of [prediction mismatch on the frontend](https://github.com/genxium/DelayNoMore/blob/v0.9.19/frontend/assets/scripts/Map.js#L842).
|
||||||
|
- Detection of [type#1 forceConfirmation on the backend](https://github.com/genxium/DelayNoMore/blob/v0.9.19/battle_srv/models/room.go#L1246).
|
||||||
|
- Detection of [type#2 forceConfirmation on the backend](https://github.com/genxium/DelayNoMore/blob/v0.9.19/battle_srv/models/room.go#L1259).
|
||||||
|
|
||||||
|
There's also some useful information displayed on the frontend when `true == Map.showNetworkDoctorInfo`.
|
||||||
|

|
||||||
|
|
||||||
|
### 2.3 WIN32 platform tool versioning
|
||||||
|

|
||||||
|
When building for native platforms, it's much more convenient to trigger the CocosCreator project forming frmo CLI, e.g.
|
||||||
|
```
|
||||||
|
shell> cd <proj-root>
|
||||||
|
shell> /path/to/CocosCreator.exe --path ./frontend --build "platform=win32;debug=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.4 CococCreator native build reloading
|
||||||
|
CocosCreator doesn't have perfect file cache management during native project building, use "Developer Tools > Reload" to reset the IDE status upon mysterious errors.
|
||||||
|

|
||||||
|
|
||||||
|
Another issue is with the package name, see the screenshot below, kindly note that after successfully building with a blank package name, you can then re-fill the desired package name and build again!
|
||||||
|

|
||||||
|
|
||||||
|
### 2.5 Checking UDP port binding result
|
||||||
|
__*nix__
|
||||||
|
```
|
||||||
|
netstat -anp | grep <your_port>
|
||||||
|
```
|
||||||
|
|
||||||
|
__Windows__
|
||||||
|
```
|
||||||
|
netstat -ano | grep <your_port>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2.6 Checking native code crash on non-rooted Android phone
|
||||||
|
```
|
||||||
|
DeveloperOs> adb bugreport ./logs.zip
|
||||||
|
# The file "logs.zip" will be automatically pulled to current folder of the DeveloperOS, copy "logs/FS/data/tomestones" out of the zip, then use the binary "$NDK_ROOT/ndk-stack" to analyze whichever tombstone you're interested in, for example, I often use the following
|
||||||
|
DeveloperOs> ${NDK_ROOT}/ndk-stack.cmd -sym \path\to\DelayNoMore\frontend\build\jsb-link\frameworks\runtime-src\proj.android-studio\app\build\intermediates\ndkBuild\debug\obj\local\arm64-v8a -dump \path\to\tombstones\tombstone_03
|
||||||
|
# The param "-sym \path\to\objs" tells "ndk-stack" to decode "tombstone_03" with symbols provided by all the files inside that "\path\to\objs".
|
||||||
|
```
|
||||||
|
@@ -37,6 +37,8 @@ type mysqlConf struct {
|
|||||||
|
|
||||||
type sioConf struct {
|
type sioConf struct {
|
||||||
HostAndPort string `json:"hostAndPort"`
|
HostAndPort string `json:"hostAndPort"`
|
||||||
|
UdpHost string `json:"udpHost"`
|
||||||
|
UdpPort int `json:"udpPort"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type botServerConf struct {
|
type botServerConf struct {
|
||||||
|
@@ -1,3 +1,5 @@
|
|||||||
{
|
{
|
||||||
"hostAndPort": "0.0.0.0:9992"
|
"hostAndPort": "0.0.0.0:9992",
|
||||||
|
"udpHost": "0.0.0.0",
|
||||||
|
"udpPort": 3000
|
||||||
}
|
}
|
||||||
|
@@ -23,6 +23,8 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/robfig/cron"
|
"github.com/robfig/cron"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -34,7 +36,7 @@ func main() {
|
|||||||
env_tools.MergeTestPlayerAccounts()
|
env_tools.MergeTestPlayerAccounts()
|
||||||
}
|
}
|
||||||
models.InitRoomHeapManager()
|
models.InitRoomHeapManager()
|
||||||
startScheduler()
|
// startScheduler()
|
||||||
router := gin.Default()
|
router := gin.Default()
|
||||||
setRouter(router)
|
setRouter(router)
|
||||||
|
|
||||||
@@ -54,6 +56,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
Logger.Info("Listening and serving HTTP on", zap.Any("Conf.Sio.HostAndPort", Conf.Sio.HostAndPort))
|
Logger.Info("Listening and serving HTTP on", zap.Any("Conf.Sio.HostAndPort", Conf.Sio.HostAndPort))
|
||||||
}()
|
}()
|
||||||
|
go startGrandUdpServer()
|
||||||
var gracefulStop = make(chan os.Signal)
|
var gracefulStop = make(chan os.Signal)
|
||||||
signal.Notify(gracefulStop, syscall.SIGTERM)
|
signal.Notify(gracefulStop, syscall.SIGTERM)
|
||||||
signal.Notify(gracefulStop, syscall.SIGINT)
|
signal.Notify(gracefulStop, syscall.SIGINT)
|
||||||
@@ -89,6 +92,7 @@ func setRouter(router *gin.Engine) {
|
|||||||
router.StaticFS("/asset", http.Dir(filepath.Join(Conf.General.AppRoot, "asset")))
|
router.StaticFS("/asset", http.Dir(filepath.Join(Conf.General.AppRoot, "asset")))
|
||||||
router.GET("/ping", f)
|
router.GET("/ping", f)
|
||||||
router.GET("/tsrht", ws.Serve)
|
router.GET("/tsrht", ws.Serve)
|
||||||
|
router.GET("/tsrhtSecondary", ws.HandleSecondaryWsSessionForPlayer)
|
||||||
|
|
||||||
apiRouter := router.Group("/api")
|
apiRouter := router.Group("/api")
|
||||||
{
|
{
|
||||||
@@ -113,3 +117,33 @@ func startScheduler() {
|
|||||||
//c.AddFunc("*/1 * * * * *", FuncName)
|
//c.AddFunc("*/1 * * * * *", FuncName)
|
||||||
c.Start()
|
c.Start()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func startGrandUdpServer() {
|
||||||
|
conn, err := net.ListenUDP("udp", &net.UDPAddr{
|
||||||
|
Port: Conf.Sio.UdpPort,
|
||||||
|
IP: net.ParseIP(Conf.Sio.UdpHost),
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
conn.Close()
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
Logger.Error("`GrandUdpServer`, recovery spot#1, recovered from: ", zap.Any("panic", r))
|
||||||
|
}
|
||||||
|
Logger.Info(fmt.Sprintf("The `GrandUdpServer` is stopped"))
|
||||||
|
}()
|
||||||
|
|
||||||
|
Logger.Info(fmt.Sprintf("`GrandUdpServer` started at %s", conn.LocalAddr().String()))
|
||||||
|
|
||||||
|
for {
|
||||||
|
message := make([]byte, 2046)
|
||||||
|
rlen, remote, err := conn.ReadFromUDP(message[:])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
Logger.Info(fmt.Sprintf("`GrandUdpServer` received: %d bytes from %s\n", rlen, remote))
|
||||||
|
ws.HandleUdpHolePunchingForPlayer(message[0:rlen], remote)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -38,6 +38,10 @@ func toPbRoomDownsyncFrame(rdf *battle.RoomDownsyncFrame) *pb.RoomDownsyncFrame
|
|||||||
BattleState: last.BattleState,
|
BattleState: last.BattleState,
|
||||||
CharacterState: last.CharacterState,
|
CharacterState: last.CharacterState,
|
||||||
InAir: last.InAir,
|
InAir: last.InAir,
|
||||||
|
OnWall: last.OnWall,
|
||||||
|
OnWallNormX: last.OnWallNormX,
|
||||||
|
OnWallNormY: last.OnWallNormY,
|
||||||
|
CapturedByInertia: last.CapturedByInertia,
|
||||||
JoinIndex: last.JoinIndex,
|
JoinIndex: last.JoinIndex,
|
||||||
BulletTeamId: last.BulletTeamId,
|
BulletTeamId: last.BulletTeamId,
|
||||||
ChCollisionTeamId: last.ChCollisionTeamId,
|
ChCollisionTeamId: last.ChCollisionTeamId,
|
||||||
@@ -52,62 +56,74 @@ func toPbRoomDownsyncFrame(rdf *battle.RoomDownsyncFrame) *pb.RoomDownsyncFrame
|
|||||||
|
|
||||||
for i, last := range rdf.MeleeBullets {
|
for i, last := range rdf.MeleeBullets {
|
||||||
pbBullet := &pb.MeleeBullet{
|
pbBullet := &pb.MeleeBullet{
|
||||||
BulletLocalId: last.BulletLocalId,
|
BulletLocalId: last.BattleAttr.BulletLocalId,
|
||||||
OriginatedRenderFrameId: last.OriginatedRenderFrameId,
|
OriginatedRenderFrameId: last.BattleAttr.OriginatedRenderFrameId,
|
||||||
OffenderJoinIndex: last.OffenderJoinIndex,
|
OffenderJoinIndex: last.BattleAttr.OffenderJoinIndex,
|
||||||
|
TeamId: last.BattleAttr.TeamId,
|
||||||
|
|
||||||
StartupFrames: last.StartupFrames,
|
StartupFrames: last.Bullet.StartupFrames,
|
||||||
CancellableStFrame: last.CancellableStFrame,
|
CancellableStFrame: last.Bullet.CancellableStFrame,
|
||||||
CancellableEdFrame: last.CancellableEdFrame,
|
CancellableEdFrame: last.Bullet.CancellableEdFrame,
|
||||||
ActiveFrames: last.ActiveFrames,
|
ActiveFrames: last.Bullet.ActiveFrames,
|
||||||
|
|
||||||
HitStunFrames: last.HitStunFrames,
|
HitStunFrames: last.Bullet.HitStunFrames,
|
||||||
BlockStunFrames: last.BlockStunFrames,
|
BlockStunFrames: last.Bullet.BlockStunFrames,
|
||||||
PushbackVelX: last.PushbackVelX,
|
PushbackVelX: last.Bullet.PushbackVelX,
|
||||||
PushbackVelY: last.PushbackVelY,
|
PushbackVelY: last.Bullet.PushbackVelY,
|
||||||
Damage: last.Damage,
|
Damage: last.Bullet.Damage,
|
||||||
|
|
||||||
SelfLockVelX: last.SelfLockVelX,
|
SelfLockVelX: last.Bullet.SelfLockVelX,
|
||||||
SelfLockVelY: last.SelfLockVelY,
|
SelfLockVelY: last.Bullet.SelfLockVelY,
|
||||||
|
|
||||||
HitboxOffsetX: last.HitboxOffsetX,
|
HitboxOffsetX: last.Bullet.HitboxOffsetX,
|
||||||
HitboxOffsetY: last.HitboxOffsetY,
|
HitboxOffsetY: last.Bullet.HitboxOffsetY,
|
||||||
HitboxSizeX: last.HitboxSizeX,
|
HitboxSizeX: last.Bullet.HitboxSizeX,
|
||||||
HitboxSizeY: last.HitboxSizeY,
|
HitboxSizeY: last.Bullet.HitboxSizeY,
|
||||||
|
|
||||||
BlowUp: last.BlowUp,
|
BlowUp: last.Bullet.BlowUp,
|
||||||
TeamId: last.TeamId,
|
|
||||||
|
SpeciesId: last.Bullet.SpeciesId,
|
||||||
|
ExplosionFrames: last.Bullet.ExplosionFrames,
|
||||||
|
|
||||||
|
BlState: last.BlState,
|
||||||
|
FramesInBlState: last.FramesInBlState,
|
||||||
}
|
}
|
||||||
ret.MeleeBullets[i] = pbBullet
|
ret.MeleeBullets[i] = pbBullet
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, last := range rdf.FireballBullets {
|
for i, last := range rdf.FireballBullets {
|
||||||
pbBullet := &pb.FireballBullet{
|
pbBullet := &pb.FireballBullet{
|
||||||
BulletLocalId: last.BulletLocalId,
|
BulletLocalId: last.BattleAttr.BulletLocalId,
|
||||||
OriginatedRenderFrameId: last.OriginatedRenderFrameId,
|
OriginatedRenderFrameId: last.BattleAttr.OriginatedRenderFrameId,
|
||||||
OffenderJoinIndex: last.OffenderJoinIndex,
|
OffenderJoinIndex: last.BattleAttr.OffenderJoinIndex,
|
||||||
|
TeamId: last.BattleAttr.TeamId,
|
||||||
|
|
||||||
StartupFrames: last.StartupFrames,
|
StartupFrames: last.Bullet.StartupFrames,
|
||||||
CancellableStFrame: last.CancellableStFrame,
|
CancellableStFrame: last.Bullet.CancellableStFrame,
|
||||||
CancellableEdFrame: last.CancellableEdFrame,
|
CancellableEdFrame: last.Bullet.CancellableEdFrame,
|
||||||
ActiveFrames: last.ActiveFrames,
|
ActiveFrames: last.Bullet.ActiveFrames,
|
||||||
|
|
||||||
HitStunFrames: last.HitStunFrames,
|
HitStunFrames: last.Bullet.HitStunFrames,
|
||||||
BlockStunFrames: last.BlockStunFrames,
|
BlockStunFrames: last.Bullet.BlockStunFrames,
|
||||||
PushbackVelX: last.PushbackVelX,
|
PushbackVelX: last.Bullet.PushbackVelX,
|
||||||
PushbackVelY: last.PushbackVelY,
|
PushbackVelY: last.Bullet.PushbackVelY,
|
||||||
Damage: last.Damage,
|
Damage: last.Bullet.Damage,
|
||||||
|
|
||||||
SelfLockVelX: last.SelfLockVelX,
|
SelfLockVelX: last.Bullet.SelfLockVelX,
|
||||||
SelfLockVelY: last.SelfLockVelY,
|
SelfLockVelY: last.Bullet.SelfLockVelY,
|
||||||
|
|
||||||
HitboxOffsetX: last.HitboxOffsetX,
|
HitboxOffsetX: last.Bullet.HitboxOffsetX,
|
||||||
HitboxOffsetY: last.HitboxOffsetY,
|
HitboxOffsetY: last.Bullet.HitboxOffsetY,
|
||||||
HitboxSizeX: last.HitboxSizeX,
|
HitboxSizeX: last.Bullet.HitboxSizeX,
|
||||||
HitboxSizeY: last.HitboxSizeY,
|
HitboxSizeY: last.Bullet.HitboxSizeY,
|
||||||
|
|
||||||
BlowUp: last.BlowUp,
|
BlowUp: last.Bullet.BlowUp,
|
||||||
TeamId: last.TeamId,
|
|
||||||
|
SpeciesId: last.Bullet.SpeciesId,
|
||||||
|
ExplosionFrames: last.Bullet.ExplosionFrames,
|
||||||
|
|
||||||
|
BlState: last.BlState,
|
||||||
|
FramesInBlState: last.FramesInBlState,
|
||||||
|
|
||||||
VirtualGridX: last.VirtualGridX,
|
VirtualGridX: last.VirtualGridX,
|
||||||
VirtualGridY: last.VirtualGridY,
|
VirtualGridY: last.VirtualGridY,
|
||||||
@@ -147,6 +163,10 @@ func toPbPlayers(modelInstances map[int32]*Player, withMetaInfo bool) []*pb.Play
|
|||||||
BattleState: last.BattleState,
|
BattleState: last.BattleState,
|
||||||
CharacterState: last.CharacterState,
|
CharacterState: last.CharacterState,
|
||||||
InAir: last.InAir,
|
InAir: last.InAir,
|
||||||
|
OnWall: last.OnWall,
|
||||||
|
OnWallNormX: last.OnWallNormX,
|
||||||
|
OnWallNormY: last.OnWallNormY,
|
||||||
|
CapturedByInertia: last.CapturedByInertia,
|
||||||
JoinIndex: last.JoinIndex,
|
JoinIndex: last.JoinIndex,
|
||||||
BulletTeamId: last.BulletTeamId,
|
BulletTeamId: last.BulletTeamId,
|
||||||
ChCollisionTeamId: last.ChCollisionTeamId,
|
ChCollisionTeamId: last.ChCollisionTeamId,
|
||||||
@@ -195,6 +215,10 @@ func toJsPlayers(modelInstances map[int32]*Player) []*battle.PlayerDownsync {
|
|||||||
MaxHp: last.MaxHp,
|
MaxHp: last.MaxHp,
|
||||||
ColliderRadius: last.ColliderRadius,
|
ColliderRadius: last.ColliderRadius,
|
||||||
InAir: last.InAir,
|
InAir: last.InAir,
|
||||||
|
OnWall: last.OnWall,
|
||||||
|
OnWallNormX: last.OnWallNormX,
|
||||||
|
OnWallNormY: last.OnWallNormY,
|
||||||
|
CapturedByInertia: last.CapturedByInertia,
|
||||||
Score: last.Score,
|
Score: last.Score,
|
||||||
Removed: last.Removed,
|
Removed: last.Removed,
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
sq "github.com/Masterminds/squirrel"
|
sq "github.com/Masterminds/squirrel"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PlayerBattleState struct {
|
type PlayerBattleState struct {
|
||||||
@@ -47,9 +48,14 @@ type Player struct {
|
|||||||
|
|
||||||
// other in-battle info fields
|
// other in-battle info fields
|
||||||
LastReceivedInputFrameId int32
|
LastReceivedInputFrameId int32
|
||||||
|
LastUdpReceivedInputFrameId int32
|
||||||
LastSentInputFrameId int32
|
LastSentInputFrameId int32
|
||||||
AckingFrameId int32
|
AckingFrameId int32
|
||||||
AckingInputFrameId int32
|
AckingInputFrameId int32
|
||||||
|
|
||||||
|
UdpAddr *PeerUdpAddr
|
||||||
|
BattleUdpTunnelAddr *net.UDPAddr // This addr is used by backend only, not visible to frontend
|
||||||
|
BattleUdpTunnelAuthKey int32
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExistPlayerByName(name string) (bool, error) {
|
func ExistPlayerByName(name string) (bool, error) {
|
||||||
|
@@ -13,6 +13,7 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"jsexport/battle"
|
"jsexport/battle"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"resolv"
|
"resolv"
|
||||||
@@ -31,6 +32,8 @@ const (
|
|||||||
DOWNSYNC_MSG_ACT_INPUT_BATCH = int32(2)
|
DOWNSYNC_MSG_ACT_INPUT_BATCH = int32(2)
|
||||||
DOWNSYNC_MSG_ACT_BATTLE_STOPPED = int32(3)
|
DOWNSYNC_MSG_ACT_BATTLE_STOPPED = int32(3)
|
||||||
DOWNSYNC_MSG_ACT_FORCED_RESYNC = int32(4)
|
DOWNSYNC_MSG_ACT_FORCED_RESYNC = int32(4)
|
||||||
|
DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH = int32(5)
|
||||||
|
DOWNSYNC_MSG_ACT_PEER_UDP_ADDR = int32(6)
|
||||||
|
|
||||||
DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START = int32(-1)
|
DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START = int32(-1)
|
||||||
DOWNSYNC_MSG_ACT_BATTLE_START = int32(0)
|
DOWNSYNC_MSG_ACT_BATTLE_START = int32(0)
|
||||||
@@ -117,9 +120,14 @@ type Room struct {
|
|||||||
* Moreover, during the invocation of `PlayerSignalToCloseDict`, the `Player` instance is supposed to be deallocated (though not synchronously).
|
* Moreover, during the invocation of `PlayerSignalToCloseDict`, the `Player` instance is supposed to be deallocated (though not synchronously).
|
||||||
*/
|
*/
|
||||||
PlayerDownsyncSessionDict map[int32]*websocket.Conn
|
PlayerDownsyncSessionDict map[int32]*websocket.Conn
|
||||||
PlayerDownsyncChanDict map[int32](chan pb.InputsBufferSnapshot)
|
|
||||||
PlayerActiveWatchdogDict map[int32](*Watchdog)
|
|
||||||
PlayerSignalToCloseDict map[int32]SignalToCloseConnCbType
|
PlayerSignalToCloseDict map[int32]SignalToCloseConnCbType
|
||||||
|
PlayerDownsyncChanDict map[int32](chan pb.InputsBufferSnapshot)
|
||||||
|
|
||||||
|
PlayerSecondaryDownsyncSessionDict map[int32]*websocket.Conn
|
||||||
|
PlayerSecondarySignalToCloseDict map[int32]SignalToCloseConnCbType
|
||||||
|
PlayerSecondaryDownsyncChanDict map[int32](chan pb.InputsBufferSnapshot)
|
||||||
|
|
||||||
|
PlayerActiveWatchdogDict map[int32](*Watchdog)
|
||||||
Score float32
|
Score float32
|
||||||
State int32
|
State int32
|
||||||
Index int
|
Index int
|
||||||
@@ -128,7 +136,7 @@ type Room struct {
|
|||||||
EffectivePlayerCount int32
|
EffectivePlayerCount int32
|
||||||
DismissalWaitGroup sync.WaitGroup
|
DismissalWaitGroup sync.WaitGroup
|
||||||
InputsBuffer *battle.RingBuffer // Indices are STRICTLY consecutive
|
InputsBuffer *battle.RingBuffer // Indices are STRICTLY consecutive
|
||||||
InputsBufferLock sync.Mutex // Guards [InputsBuffer, LatestPlayerUpsyncedInputFrameId, LastAllConfirmedInputFrameId, LastAllConfirmedInputList, LastAllConfirmedInputFrameIdWithChange, LastIndividuallyConfirmedInputList, player.LastReceivedInputFrameId]
|
InputsBufferLock sync.Mutex // Guards [InputsBuffer, LatestPlayerUpsyncedInputFrameId, LastAllConfirmedInputFrameId, LastAllConfirmedInputList, LastAllConfirmedInputFrameIdWithChange, LastIndividuallyConfirmedInputList, player.LastReceivedInputFrameId, player.LastUdpReceivedInputFrameId]
|
||||||
RenderFrameBuffer *battle.RingBuffer // Indices are STRICTLY consecutive
|
RenderFrameBuffer *battle.RingBuffer // Indices are STRICTLY consecutive
|
||||||
LatestPlayerUpsyncedInputFrameId int32
|
LatestPlayerUpsyncedInputFrameId int32
|
||||||
LastAllConfirmedInputFrameId int32
|
LastAllConfirmedInputFrameId int32
|
||||||
@@ -150,6 +158,10 @@ type Room struct {
|
|||||||
|
|
||||||
rdfIdToActuallyUsedInput map[int32]*pb.InputFrameDownsync
|
rdfIdToActuallyUsedInput map[int32]*pb.InputFrameDownsync
|
||||||
LastIndividuallyConfirmedInputList []uint64
|
LastIndividuallyConfirmedInputList []uint64
|
||||||
|
|
||||||
|
BattleUdpTunnelLock sync.Mutex
|
||||||
|
BattleUdpTunnelAddr *pb.PeerUdpAddr
|
||||||
|
BattleUdpTunnel *net.UDPConn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) updateScore() {
|
func (pR *Room) updateScore() {
|
||||||
@@ -170,10 +182,14 @@ func (pR *Room) AddPlayerIfPossible(pPlayerFromDbInit *Player, session *websocke
|
|||||||
|
|
||||||
defer pR.onPlayerAdded(playerId)
|
defer pR.onPlayerAdded(playerId)
|
||||||
|
|
||||||
|
pPlayerFromDbInit.UdpAddr = nil
|
||||||
|
pPlayerFromDbInit.BattleUdpTunnelAddr = nil
|
||||||
|
pPlayerFromDbInit.BattleUdpTunnelAuthKey = rand.Int31()
|
||||||
pPlayerFromDbInit.AckingFrameId = -1
|
pPlayerFromDbInit.AckingFrameId = -1
|
||||||
pPlayerFromDbInit.AckingInputFrameId = -1
|
pPlayerFromDbInit.AckingInputFrameId = -1
|
||||||
pPlayerFromDbInit.LastSentInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_NORMAL_ADDED
|
pPlayerFromDbInit.LastSentInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_NORMAL_ADDED
|
||||||
pPlayerFromDbInit.LastReceivedInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_NORMAL_ADDED
|
pPlayerFromDbInit.LastReceivedInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_NORMAL_ADDED
|
||||||
|
pPlayerFromDbInit.LastUdpReceivedInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_NORMAL_ADDED
|
||||||
pPlayerFromDbInit.BattleState = PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK
|
pPlayerFromDbInit.BattleState = PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK
|
||||||
|
|
||||||
pPlayerFromDbInit.ColliderRadius = DEFAULT_PLAYER_RADIUS // Hardcoded
|
pPlayerFromDbInit.ColliderRadius = DEFAULT_PLAYER_RADIUS // Hardcoded
|
||||||
@@ -184,7 +200,7 @@ func (pR *Room) AddPlayerIfPossible(pPlayerFromDbInit *Player, session *websocke
|
|||||||
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
|
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
|
||||||
newWatchdog := NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
|
newWatchdog := NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
|
||||||
Logger.Warn("Conn inactive watchdog triggered#1:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
|
Logger.Warn("Conn inactive watchdog triggered#1:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
|
||||||
signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "")
|
pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.ActiveWatchdog)
|
||||||
})
|
})
|
||||||
newWatchdog.Stop()
|
newWatchdog.Stop()
|
||||||
pR.PlayerActiveWatchdogDict[playerId] = newWatchdog
|
pR.PlayerActiveWatchdogDict[playerId] = newWatchdog
|
||||||
@@ -209,9 +225,13 @@ func (pR *Room) ReAddPlayerIfPossible(pTmpPlayerInstance *Player, session *webso
|
|||||||
*/
|
*/
|
||||||
defer pR.onPlayerReAdded(playerId)
|
defer pR.onPlayerReAdded(playerId)
|
||||||
pEffectiveInRoomPlayerInstance := pR.Players[playerId]
|
pEffectiveInRoomPlayerInstance := pR.Players[playerId]
|
||||||
|
pEffectiveInRoomPlayerInstance.UdpAddr = nil
|
||||||
|
pEffectiveInRoomPlayerInstance.BattleUdpTunnelAddr = nil
|
||||||
|
pEffectiveInRoomPlayerInstance.BattleUdpTunnelAuthKey = rand.Int31()
|
||||||
pEffectiveInRoomPlayerInstance.AckingFrameId = -1
|
pEffectiveInRoomPlayerInstance.AckingFrameId = -1
|
||||||
pEffectiveInRoomPlayerInstance.AckingInputFrameId = -1
|
pEffectiveInRoomPlayerInstance.AckingInputFrameId = -1
|
||||||
pEffectiveInRoomPlayerInstance.LastSentInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED
|
pEffectiveInRoomPlayerInstance.LastSentInputFrameId = MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED
|
||||||
|
// [WARNING] DON'T reset "player.LastReceivedInputFrameId" & "player.LastUdpReceivedInputFrameId" upon reconnection!
|
||||||
pEffectiveInRoomPlayerInstance.BattleState = PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK
|
pEffectiveInRoomPlayerInstance.BattleState = PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK
|
||||||
|
|
||||||
pEffectiveInRoomPlayerInstance.ColliderRadius = DEFAULT_PLAYER_RADIUS // Hardcoded
|
pEffectiveInRoomPlayerInstance.ColliderRadius = DEFAULT_PLAYER_RADIUS // Hardcoded
|
||||||
@@ -221,7 +241,7 @@ func (pR *Room) ReAddPlayerIfPossible(pTmpPlayerInstance *Player, session *webso
|
|||||||
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
|
pR.PlayerSignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
|
||||||
pR.PlayerActiveWatchdogDict[playerId] = NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
|
pR.PlayerActiveWatchdogDict[playerId] = NewWatchdog(ConstVals.Ws.WillKickIfInactiveFor, func() {
|
||||||
Logger.Warn("Conn inactive watchdog triggered#2:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
|
Logger.Warn("Conn inactive watchdog triggered#2:", zap.Any("playerId", playerId), zap.Any("roomId", pR.Id), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount))
|
||||||
signalToCloseConnOfThisPlayer(Constants.RetCode.ActiveWatchdog, "")
|
pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.ActiveWatchdog)
|
||||||
}) // For ReAdded player the new watchdog starts immediately
|
}) // For ReAdded player the new watchdog starts immediately
|
||||||
|
|
||||||
Logger.Warn("ReAddPlayerIfPossible finished.", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("joinIndex", pEffectiveInRoomPlayerInstance.JoinIndex), zap.Any("playerBattleState", pEffectiveInRoomPlayerInstance.BattleState), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount), zap.Any("AckingFrameId", pEffectiveInRoomPlayerInstance.AckingFrameId), zap.Any("AckingInputFrameId", pEffectiveInRoomPlayerInstance.AckingInputFrameId), zap.Any("LastSentInputFrameId", pEffectiveInRoomPlayerInstance.LastSentInputFrameId))
|
Logger.Warn("ReAddPlayerIfPossible finished.", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("joinIndex", pEffectiveInRoomPlayerInstance.JoinIndex), zap.Any("playerBattleState", pEffectiveInRoomPlayerInstance.BattleState), zap.Any("roomState", pR.State), zap.Any("roomEffectivePlayerCount", pR.EffectivePlayerCount), zap.Any("AckingFrameId", pEffectiveInRoomPlayerInstance.AckingFrameId), zap.Any("AckingInputFrameId", pEffectiveInRoomPlayerInstance.AckingInputFrameId), zap.Any("LastSentInputFrameId", pEffectiveInRoomPlayerInstance.LastSentInputFrameId))
|
||||||
@@ -309,8 +329,8 @@ func (pR *Room) InputsBufferString(allDetails bool) string {
|
|||||||
// Appending of the array of strings can be very SLOW due to on-demand heap allocation! Use this printing with caution.
|
// Appending of the array of strings can be very SLOW due to on-demand heap allocation! Use this printing with caution.
|
||||||
s := make([]string, 0)
|
s := make([]string, 0)
|
||||||
s = append(s, fmt.Sprintf("{renderFrameId: %v, stInputFrameId: %v, edInputFrameId: %v, lastAllConfirmedInputFrameIdWithChange: %v, lastAllConfirmedInputFrameId: %v}", pR.RenderFrameId, pR.InputsBuffer.StFrameId, pR.InputsBuffer.EdFrameId, pR.LastAllConfirmedInputFrameIdWithChange, pR.LastAllConfirmedInputFrameId))
|
s = append(s, fmt.Sprintf("{renderFrameId: %v, stInputFrameId: %v, edInputFrameId: %v, lastAllConfirmedInputFrameIdWithChange: %v, lastAllConfirmedInputFrameId: %v}", pR.RenderFrameId, pR.InputsBuffer.StFrameId, pR.InputsBuffer.EdFrameId, pR.LastAllConfirmedInputFrameIdWithChange, pR.LastAllConfirmedInputFrameId))
|
||||||
for playerId, player := range pR.PlayersArr {
|
for _, player := range pR.PlayersArr {
|
||||||
s = append(s, fmt.Sprintf("{playerId: %v, ackingFrameId: %v, ackingInputFrameId: %v, lastSentInputFrameId: %v}", playerId, player.AckingFrameId, player.AckingInputFrameId, player.LastSentInputFrameId))
|
s = append(s, fmt.Sprintf("{playerId: %v, ackingFrameId: %v, ackingInputFrameId: %v, lastSentInputFrameId: %v}", player.Id, player.AckingFrameId, player.AckingInputFrameId, player.LastSentInputFrameId))
|
||||||
}
|
}
|
||||||
for i := pR.InputsBuffer.StFrameId; i < pR.InputsBuffer.EdFrameId; i++ {
|
for i := pR.InputsBuffer.StFrameId; i < pR.InputsBuffer.EdFrameId; i++ {
|
||||||
tmp := pR.InputsBuffer.GetByFrameId(i)
|
tmp := pR.InputsBuffer.GetByFrameId(i)
|
||||||
@@ -335,7 +355,20 @@ func (pR *Room) playerDownsyncStr(player *battle.PlayerDownsync) string {
|
|||||||
if player.InAir {
|
if player.InAir {
|
||||||
inAirInt = 1
|
inAirInt = 1
|
||||||
}
|
}
|
||||||
s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d,%d}", player.JoinIndex, player.VirtualGridX, player.VirtualGridY, player.VelX, player.VelY, player.FramesToRecover, inAirInt)
|
onWallInt := 0
|
||||||
|
if player.OnWall {
|
||||||
|
onWallInt = 1
|
||||||
|
}
|
||||||
|
s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d,%d,%d}", player.JoinIndex, player.VirtualGridX, player.VirtualGridY, player.VelX, player.VelY, player.FramesToRecover, inAirInt, onWallInt)
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pR *Room) fireballDownsyncStr(fireball *battle.FireballBullet) string {
|
||||||
|
if nil == fireball {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
s := fmt.Sprintf("{%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d}", fireball.BattleAttr.BulletLocalId, fireball.BattleAttr.OriginatedRenderFrameId, fireball.BattleAttr.OffenderJoinIndex, fireball.VirtualGridX, fireball.VirtualGridY, fireball.VelX, fireball.VelY, fireball.DirX, fireball.DirY, fireball.Bullet.HitboxSizeX, fireball.Bullet.HitboxSizeY)
|
||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
@@ -365,7 +398,11 @@ func (pR *Room) rdfIdToActuallyUsedInputString() string {
|
|||||||
for _, player := range rdf.PlayersArr {
|
for _, player := range rdf.PlayersArr {
|
||||||
playersStrBldr = append(playersStrBldr, pR.playerDownsyncStr(player))
|
playersStrBldr = append(playersStrBldr, pR.playerDownsyncStr(player))
|
||||||
}
|
}
|
||||||
s = append(s, fmt.Sprintf("rdfId:%d\nplayers:[%v]\nactuallyUsedinputList:{%v}", rdfId, strings.Join(playersStrBldr, ","), pR.inputFrameDownsyncStr(pR.rdfIdToActuallyUsedInput[rdfId])))
|
fireballsStrBldr := make([]string, 0, len(rdf.FireballBullets))
|
||||||
|
for _, fireball := range rdf.FireballBullets {
|
||||||
|
fireballsStrBldr = append(fireballsStrBldr, pR.fireballDownsyncStr(fireball))
|
||||||
|
}
|
||||||
|
s = append(s, fmt.Sprintf("rdfId:%d\nplayers:[%v]\nfireballs:[%v]\nactuallyUsedinputList:{%v}", rdfId, strings.Join(playersStrBldr, ","), strings.Join(fireballsStrBldr, ","), pR.inputFrameDownsyncStr(pR.rdfIdToActuallyUsedInput[rdfId])))
|
||||||
}
|
}
|
||||||
|
|
||||||
return strings.Join(s, "\n")
|
return strings.Join(s, "\n")
|
||||||
@@ -381,7 +418,7 @@ func (pR *Room) StartBattle() {
|
|||||||
|
|
||||||
for _, player := range pR.Players {
|
for _, player := range pR.Players {
|
||||||
speciesId := int(player.JoinIndex - 1) // FIXME: Hardcoded the values for now
|
speciesId := int(player.JoinIndex - 1) // FIXME: Hardcoded the values for now
|
||||||
if player.JoinIndex == 2 {
|
if player.JoinIndex == 1 {
|
||||||
speciesId = 4096
|
speciesId = 4096
|
||||||
}
|
}
|
||||||
chosenCh := battle.Characters[speciesId]
|
chosenCh := battle.Characters[speciesId]
|
||||||
@@ -465,7 +502,7 @@ func (pR *Room) StartBattle() {
|
|||||||
kickoffFrameJs := pR.RenderFrameBuffer.GetByFrameId(0).(*battle.RoomDownsyncFrame)
|
kickoffFrameJs := pR.RenderFrameBuffer.GetByFrameId(0).(*battle.RoomDownsyncFrame)
|
||||||
pbKickOffRenderFrame := toPbRoomDownsyncFrame(kickoffFrameJs)
|
pbKickOffRenderFrame := toPbRoomDownsyncFrame(kickoffFrameJs)
|
||||||
pbKickOffRenderFrame.SpeciesIdList = pR.SpeciesIdList
|
pbKickOffRenderFrame.SpeciesIdList = pR.SpeciesIdList
|
||||||
pR.sendSafely(pbKickOffRenderFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_START, playerId, true)
|
pR.sendSafely(pbKickOffRenderFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_START, playerId, true, MAGIC_JOIN_INDEX_DEFAULT)
|
||||||
}
|
}
|
||||||
Logger.Info(fmt.Sprintf("In `battleMainLoop` for roomId=%v sent out kickoffFrame", pR.Id))
|
Logger.Info(fmt.Sprintf("In `battleMainLoop` for roomId=%v sent out kickoffFrame", pR.Id))
|
||||||
}
|
}
|
||||||
@@ -492,7 +529,7 @@ func (pR *Room) StartBattle() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
downsyncLoop := func(playerId int32, player *Player, playerDownsyncChan chan pb.InputsBufferSnapshot) {
|
downsyncLoop := func(playerId int32, player *Player, playerDownsyncChan chan pb.InputsBufferSnapshot, playerSecondaryDownsyncChan chan pb.InputsBufferSnapshot) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
Logger.Error("downsyncLoop, recovery spot#1, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r))
|
Logger.Error("downsyncLoop, recovery spot#1, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r))
|
||||||
@@ -500,19 +537,23 @@ func (pR *Room) StartBattle() {
|
|||||||
Logger.Info(fmt.Sprintf("The `downsyncLoop` for (roomId=%v, playerId=%v) is stopped@renderFrameId=%v", pR.Id, playerId, pR.RenderFrameId))
|
Logger.Info(fmt.Sprintf("The `downsyncLoop` for (roomId=%v, playerId=%v) is stopped@renderFrameId=%v", pR.Id, playerId, pR.RenderFrameId))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
Logger.Debug(fmt.Sprintf("Started downsyncLoop for (roomId: %d, playerId:%d, playerDownsyncChan:%p)", pR.Id, playerId, playerDownsyncChan))
|
//Logger.Info(fmt.Sprintf("Started downsyncLoop for (roomId: %d, playerId:%d, playerDownsyncChan:%p)", pR.Id, playerId, playerDownsyncChan))
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
|
||||||
case inputsBufferSnapshot := <-playerDownsyncChan:
|
|
||||||
nowBattleState := atomic.LoadInt32(&pR.State)
|
nowBattleState := atomic.LoadInt32(&pR.State)
|
||||||
switch nowBattleState {
|
switch nowBattleState {
|
||||||
case RoomBattleStateIns.IDLE, RoomBattleStateIns.STOPPING_BATTLE_FOR_SETTLEMENT, RoomBattleStateIns.IN_SETTLEMENT, RoomBattleStateIns.IN_DISMISSAL:
|
case RoomBattleStateIns.IDLE, RoomBattleStateIns.STOPPING_BATTLE_FOR_SETTLEMENT, RoomBattleStateIns.IN_SETTLEMENT, RoomBattleStateIns.IN_DISMISSAL:
|
||||||
Logger.Warn(fmt.Sprintf("Battle is not waiting/preparing/active for playerDownsyncChan for (roomId: %d, playerId:%d)", pR.Id, playerId))
|
Logger.Warn(fmt.Sprintf("Battle is not waiting/preparing/active for playerDownsyncChan for (roomId: %d, playerId:%d)", pR.Id, playerId))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case inputsBufferSnapshot := <-playerDownsyncChan:
|
||||||
pR.downsyncToSinglePlayer(playerId, player, inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, inputsBufferSnapshot.ToSendInputFrameDownsyncs, inputsBufferSnapshot.ShouldForceResync)
|
pR.downsyncToSinglePlayer(playerId, player, inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, inputsBufferSnapshot.ToSendInputFrameDownsyncs, inputsBufferSnapshot.ShouldForceResync)
|
||||||
//Logger.Info(fmt.Sprintf("Sent inputsBufferSnapshot(refRenderFrameId:%d, unconfirmedMask:%v) to for (roomId: %d, playerId:%d)#2", inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, pR.Id, playerId))
|
//Logger.Info(fmt.Sprintf("Sent inputsBufferSnapshot(refRenderFrameId:%d, unconfirmedMask:%v) to for (roomId: %d, playerId:%d)#2", inputsBufferSnapshot.RefRenderFrameId, inputsBufferSnapshot.UnconfirmedMask, pR.Id, playerId))
|
||||||
|
case inputsBufferSnapshot2 := <-playerSecondaryDownsyncChan:
|
||||||
|
pR.downsyncPeerInputFrameUpsyncToSinglePlayer(playerId, player, inputsBufferSnapshot2.ToSendInputFrameDownsyncs, inputsBufferSnapshot2.PeerJoinIndex)
|
||||||
|
//Logger.Info(fmt.Sprintf("Sent secondary inputsBufferSnapshot to for (roomId: %d, playerId:%d)#2", pR.Id, playerId))
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -525,7 +566,8 @@ func (pR *Room) StartBattle() {
|
|||||||
Each "playerDownsyncChan" stays alive through out the lifecycle of room instead of each "playerDownsyncSession", i.e. not closed or dereferenced upon disconnection.
|
Each "playerDownsyncChan" stays alive through out the lifecycle of room instead of each "playerDownsyncSession", i.e. not closed or dereferenced upon disconnection.
|
||||||
*/
|
*/
|
||||||
pR.PlayerDownsyncChanDict[playerId] = make(chan pb.InputsBufferSnapshot, pR.InputsBuffer.N)
|
pR.PlayerDownsyncChanDict[playerId] = make(chan pb.InputsBufferSnapshot, pR.InputsBuffer.N)
|
||||||
go downsyncLoop(playerId, player, pR.PlayerDownsyncChanDict[playerId])
|
pR.PlayerSecondaryDownsyncChanDict[playerId] = make(chan pb.InputsBufferSnapshot, pR.InputsBuffer.N)
|
||||||
|
go downsyncLoop(playerId, player, pR.PlayerDownsyncChanDict[playerId], pR.PlayerSecondaryDownsyncChanDict[playerId])
|
||||||
}
|
}
|
||||||
|
|
||||||
pR.onBattlePrepare(func() {
|
pR.onBattlePrepare(func() {
|
||||||
@@ -534,7 +576,7 @@ func (pR *Room) StartBattle() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) {
|
func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq, fromUDP bool) {
|
||||||
/*
|
/*
|
||||||
[WARNING] This function "OnBattleCmdReceived" could be called by different ws sessions and thus from different threads!
|
[WARNING] This function "OnBattleCmdReceived" could be called by different ws sessions and thus from different threads!
|
||||||
|
|
||||||
@@ -579,10 +621,21 @@ func (pR *Room) OnBattleCmdReceived(pReq *pb.WsReq) {
|
|||||||
//Logger.Debug(fmt.Sprintf("OnBattleCmdReceived-InputsBufferLock unlocked: roomId=%v, fromPlayerId=%v", pR.Id, playerId))
|
//Logger.Debug(fmt.Sprintf("OnBattleCmdReceived-InputsBufferLock unlocked: roomId=%v, fromPlayerId=%v", pR.Id, playerId))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
inputsBufferSnapshot := pR.markConfirmationIfApplicable(inputFrameUpsyncBatch, playerId, player)
|
inputsBufferSnapshot := pR.markConfirmationIfApplicable(inputFrameUpsyncBatch, playerId, player, fromUDP)
|
||||||
if nil != inputsBufferSnapshot {
|
if nil != inputsBufferSnapshot {
|
||||||
pR.downsyncToAllPlayers(inputsBufferSnapshot)
|
pR.downsyncToAllPlayers(inputsBufferSnapshot)
|
||||||
|
} /*else {
|
||||||
|
// FIXME: Enable this block after we can proactively detect whether there's any "secondary ws session player" in the battle to avoid waste of resource in creating the snapshot
|
||||||
|
// no new all-confirmed
|
||||||
|
toSendInputFrameDownsyncs := pR.cloneInputsBuffer(inputFrameUpsyncBatch[0].InputFrameId, inputFrameUpsyncBatch[len(inputFrameUpsyncBatch)-1].InputFrameId+1)
|
||||||
|
|
||||||
|
inputsBufferSnapshot = &pb.InputsBufferSnapshot{
|
||||||
|
ToSendInputFrameDownsyncs: toSendInputFrameDownsyncs,
|
||||||
|
PeerJoinIndex: player.JoinIndex,
|
||||||
}
|
}
|
||||||
|
//Logger.Info(fmt.Sprintf("OnBattleCmdReceived no new all-confirmed: roomId=%v, fromPlayerId=%v, forming peer broadcasting snapshot=%v", pR.Id, playerId, inputsBufferSnapshot))
|
||||||
|
pR.broadcastPeerUpsyncForBetterPrediction(inputsBufferSnapshot)
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *battle.InputFrameDownsync, playerId int32) {
|
func (pR *Room) onInputFrameDownsyncAllConfirmed(inputFrameDownsync *battle.InputFrameDownsync, playerId int32) {
|
||||||
@@ -624,6 +677,10 @@ func (pR *Room) StopBattleForSettlement() {
|
|||||||
if RoomBattleStateIns.IN_BATTLE != pR.State {
|
if RoomBattleStateIns.IN_BATTLE != pR.State {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
pR.BattleUdpTunnelLock.Lock()
|
||||||
|
pR.BattleUdpTunnel.Close()
|
||||||
|
pR.BattleUdpTunnelLock.Unlock()
|
||||||
|
|
||||||
pR.State = RoomBattleStateIns.STOPPING_BATTLE_FOR_SETTLEMENT
|
pR.State = RoomBattleStateIns.STOPPING_BATTLE_FOR_SETTLEMENT
|
||||||
Logger.Info("Stopping the `battleMainLoop` for:", zap.Any("roomId", pR.Id))
|
Logger.Info("Stopping the `battleMainLoop` for:", zap.Any("roomId", pR.Id))
|
||||||
pR.RenderFrameId++
|
pR.RenderFrameId++
|
||||||
@@ -633,7 +690,7 @@ func (pR *Room) StopBattleForSettlement() {
|
|||||||
PlayersArr: toPbPlayers(pR.Players, false),
|
PlayersArr: toPbPlayers(pR.Players, false),
|
||||||
CountdownNanos: -1, // TODO: Replace this magic constant!
|
CountdownNanos: -1, // TODO: Replace this magic constant!
|
||||||
}
|
}
|
||||||
pR.sendSafely(&assembledFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_STOPPED, playerId, true)
|
pR.sendSafely(&assembledFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_STOPPED, playerId, true, MAGIC_JOIN_INDEX_DEFAULT)
|
||||||
}
|
}
|
||||||
// Note that `pR.onBattleStoppedForSettlement` will be called by `battleMainLoop`.
|
// Note that `pR.onBattleStoppedForSettlement` will be called by `battleMainLoop`.
|
||||||
}
|
}
|
||||||
@@ -662,7 +719,7 @@ func (pR *Room) onBattlePrepare(cb BattleStartCbType) {
|
|||||||
|
|
||||||
Logger.Info("Sending out frame for RoomBattleState.PREPARE:", zap.Any("battleReadyToStartFrame", battleReadyToStartFrame))
|
Logger.Info("Sending out frame for RoomBattleState.PREPARE:", zap.Any("battleReadyToStartFrame", battleReadyToStartFrame))
|
||||||
for _, player := range pR.Players {
|
for _, player := range pR.Players {
|
||||||
pR.sendSafely(battleReadyToStartFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START, player.Id, true)
|
pR.sendSafely(battleReadyToStartFrame, nil, DOWNSYNC_MSG_ACT_BATTLE_READY_TO_START, player.Id, true, MAGIC_JOIN_INDEX_DEFAULT)
|
||||||
}
|
}
|
||||||
|
|
||||||
battlePreparationNanos := int64(6000000000)
|
battlePreparationNanos := int64(6000000000)
|
||||||
@@ -731,6 +788,7 @@ func (pR *Room) OnDismissed() {
|
|||||||
pR.CharacterConfigsArr = make([]*battle.CharacterConfig, pR.Capacity)
|
pR.CharacterConfigsArr = make([]*battle.CharacterConfig, pR.Capacity)
|
||||||
pR.CollisionSysMap = make(map[int32]*resolv.Object)
|
pR.CollisionSysMap = make(map[int32]*resolv.Object)
|
||||||
pR.PlayerDownsyncSessionDict = make(map[int32]*websocket.Conn)
|
pR.PlayerDownsyncSessionDict = make(map[int32]*websocket.Conn)
|
||||||
|
pR.PlayerSecondaryDownsyncSessionDict = make(map[int32]*websocket.Conn)
|
||||||
for _, oldWatchdog := range pR.PlayerActiveWatchdogDict {
|
for _, oldWatchdog := range pR.PlayerActiveWatchdogDict {
|
||||||
oldWatchdog.Stop()
|
oldWatchdog.Stop()
|
||||||
}
|
}
|
||||||
@@ -739,7 +797,12 @@ func (pR *Room) OnDismissed() {
|
|||||||
close(oldChan)
|
close(oldChan)
|
||||||
}
|
}
|
||||||
pR.PlayerDownsyncChanDict = make(map[int32](chan pb.InputsBufferSnapshot))
|
pR.PlayerDownsyncChanDict = make(map[int32](chan pb.InputsBufferSnapshot))
|
||||||
|
for _, oldChan := range pR.PlayerSecondaryDownsyncChanDict {
|
||||||
|
close(oldChan)
|
||||||
|
}
|
||||||
|
pR.PlayerSecondaryDownsyncChanDict = make(map[int32](chan pb.InputsBufferSnapshot))
|
||||||
pR.PlayerSignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
|
pR.PlayerSignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
|
||||||
|
pR.PlayerSecondarySignalToCloseDict = make(map[int32]SignalToCloseConnCbType)
|
||||||
pR.JoinIndexBooleanArr = make([]bool, pR.Capacity)
|
pR.JoinIndexBooleanArr = make([]bool, pR.Capacity)
|
||||||
pR.RenderCacheSize = 1024
|
pR.RenderCacheSize = 1024
|
||||||
pR.RenderFrameBuffer = battle.NewRingBuffer(pR.RenderCacheSize)
|
pR.RenderFrameBuffer = battle.NewRingBuffer(pR.RenderCacheSize)
|
||||||
@@ -754,7 +817,7 @@ func (pR *Room) OnDismissed() {
|
|||||||
|
|
||||||
pR.RenderFrameId = 0
|
pR.RenderFrameId = 0
|
||||||
pR.CurDynamicsRenderFrameId = 0
|
pR.CurDynamicsRenderFrameId = 0
|
||||||
pR.NstDelayFrames = 16
|
pR.NstDelayFrames = 24
|
||||||
|
|
||||||
serverFps := 60
|
serverFps := 60
|
||||||
pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
|
pR.RollbackEstimatedDtMillis = 16.667 // Use fixed-and-low-precision to mitigate the inconsistent floating-point-number issue between Golang and JavaScript
|
||||||
@@ -762,39 +825,50 @@ func (pR *Room) OnDismissed() {
|
|||||||
dilutedServerFps := float64(58.0) // Don't set this value too small, otherwise we might miss force confirmation needs for slow tickers!
|
dilutedServerFps := float64(58.0) // Don't set this value too small, otherwise we might miss force confirmation needs for slow tickers!
|
||||||
pR.dilutedRollbackEstimatedDtNanos = int64(float64(pR.RollbackEstimatedDtNanos) * float64(serverFps) / dilutedServerFps)
|
pR.dilutedRollbackEstimatedDtNanos = int64(float64(pR.RollbackEstimatedDtNanos) * float64(serverFps) / dilutedServerFps)
|
||||||
pR.BattleDurationFrames = int32(60 * serverFps)
|
pR.BattleDurationFrames = int32(60 * serverFps)
|
||||||
|
//pR.BattleDurationFrames = int32(20 * serverFps)
|
||||||
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
|
pR.BattleDurationNanos = int64(pR.BattleDurationFrames) * (pR.RollbackEstimatedDtNanos + 1)
|
||||||
pR.InputFrameUpsyncDelayTolerance = battle.ConvertToNoDelayInputFrameId(pR.NstDelayFrames) - 1 // this value should be strictly smaller than (NstDelayFrames >> InputScaleFrames), otherwise "type#1 forceConfirmation" might become a lag avalanche
|
pR.InputFrameUpsyncDelayTolerance = battle.ConvertToNoDelayInputFrameId(pR.NstDelayFrames) - 1 // this value should be strictly smaller than (NstDelayFrames >> InputScaleFrames), otherwise "type#1 forceConfirmation" might become a lag avalanche
|
||||||
pR.MaxChasingRenderFramesPerUpdate = 12 // Don't set this value too high to avoid exhausting frontend CPU within a single frame
|
pR.MaxChasingRenderFramesPerUpdate = 9 // Don't set this value too high to avoid exhausting frontend CPU within a single frame, roughly as the "turn-around frames to recover" is empirically OK
|
||||||
|
|
||||||
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
|
pR.BackendDynamicsEnabled = true // [WARNING] When "false", recovery upon reconnection wouldn't work!
|
||||||
pR.ForceAllResyncOnAnyActiveSlowTicker = true // See tradeoff discussion in "downsyncToAllPlayers"
|
pR.ForceAllResyncOnAnyActiveSlowTicker = true // See tradeoff discussion in "downsyncToAllPlayers"
|
||||||
|
|
||||||
pR.FrameDataLoggingEnabled = false // [WARNING] DON'T ENABLE ON LONG BATTLE DURATION! It consumes A LOT OF MEMORY!
|
pR.FrameDataLoggingEnabled = false // [WARNING] DON'T ENABLE ON LONG BATTLE DURATION! It consumes A LOT OF MEMORY!
|
||||||
|
pR.BattleUdpTunnelLock.Lock()
|
||||||
|
pR.BattleUdpTunnel = nil
|
||||||
|
pR.BattleUdpTunnelAddr = nil
|
||||||
|
pR.BattleUdpTunnelLock.Unlock()
|
||||||
|
|
||||||
pR.ChooseStage()
|
pR.ChooseStage()
|
||||||
pR.EffectivePlayerCount = 0
|
pR.EffectivePlayerCount = 0
|
||||||
|
|
||||||
// [WARNING] It's deliberately ordered such that "pR.State = RoomBattleStateIns.IDLE" is put AFTER all the refreshing operations above.
|
// [WARNING] It's deliberately ordered such that "pR.State = RoomBattleStateIns.IDLE" is put AFTER all the refreshing operations above.
|
||||||
pR.State = RoomBattleStateIns.IDLE
|
pR.State = RoomBattleStateIns.IDLE
|
||||||
|
go pR.startBattleUdpTunnel() // Would reassign "pR.BattleUdpTunnel"
|
||||||
pR.updateScore()
|
pR.updateScore()
|
||||||
|
|
||||||
Logger.Info("The room is completely dismissed(all playerDownsyncChan closed):", zap.Any("roomId", pR.Id))
|
Logger.Info("The room is completely dismissed(all playerDownsyncChan closed):", zap.Any("roomId", pR.Id))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) expelPlayerDuringGame(playerId int32) {
|
func (pR *Room) expelPlayerDuringGame(playerId int32) {
|
||||||
if signalToCloseConnOfThisPlayer, existent := pR.PlayerSignalToCloseDict[playerId]; existent {
|
pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.UnknownError)
|
||||||
signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") // TODO: Specify an error code
|
|
||||||
}
|
|
||||||
pR.onPlayerExpelledDuringGame(playerId)
|
pR.onPlayerExpelledDuringGame(playerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) expelPlayerForDismissal(playerId int32) {
|
func (pR *Room) expelPlayerForDismissal(playerId int32) {
|
||||||
if signalToCloseConnOfThisPlayer, existent := pR.PlayerSignalToCloseDict[playerId]; existent {
|
pR.signalToCloseAllSessionsOfPlayer(playerId, Constants.RetCode.UnknownError)
|
||||||
signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") // TODO: Specify an error code
|
|
||||||
}
|
|
||||||
pR.onPlayerExpelledForDismissal(playerId)
|
pR.onPlayerExpelledForDismissal(playerId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pR *Room) signalToCloseAllSessionsOfPlayer(playerId int32, retCode int) {
|
||||||
|
if signalToCloseConnOfThisPlayer, existent := pR.PlayerSignalToCloseDict[playerId]; existent {
|
||||||
|
signalToCloseConnOfThisPlayer(retCode, "") // TODO: Specify an error code
|
||||||
|
}
|
||||||
|
if signalToCloseConnOfThisPlayer2, existent2 := pR.PlayerSecondarySignalToCloseDict[playerId]; existent2 {
|
||||||
|
signalToCloseConnOfThisPlayer2(retCode, "") // TODO: Specify an error code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (pR *Room) onPlayerExpelledDuringGame(playerId int32) {
|
func (pR *Room) onPlayerExpelledDuringGame(playerId int32) {
|
||||||
pR.onPlayerLost(playerId)
|
pR.onPlayerLost(playerId)
|
||||||
}
|
}
|
||||||
@@ -812,6 +886,10 @@ func (pR *Room) OnPlayerDisconnected(playerId int32) {
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
if signalToCloseConnOfThisPlayer2, existent2 := pR.PlayerSecondarySignalToCloseDict[playerId]; existent2 {
|
||||||
|
signalToCloseConnOfThisPlayer2(Constants.RetCode.UnknownError, "") // TODO: Specify an error code
|
||||||
|
}
|
||||||
|
|
||||||
if player, existent := pR.Players[playerId]; existent {
|
if player, existent := pR.Players[playerId]; existent {
|
||||||
thatPlayerBattleState := atomic.LoadInt32(&(player.BattleState))
|
thatPlayerBattleState := atomic.LoadInt32(&(player.BattleState))
|
||||||
switch thatPlayerBattleState {
|
switch thatPlayerBattleState {
|
||||||
@@ -871,6 +949,8 @@ func (pR *Room) clearPlayerNetworkSession(playerId int32) {
|
|||||||
delete(pR.PlayerActiveWatchdogDict, playerId)
|
delete(pR.PlayerActiveWatchdogDict, playerId)
|
||||||
delete(pR.PlayerDownsyncSessionDict, playerId)
|
delete(pR.PlayerDownsyncSessionDict, playerId)
|
||||||
delete(pR.PlayerSignalToCloseDict, playerId)
|
delete(pR.PlayerSignalToCloseDict, playerId)
|
||||||
|
delete(pR.PlayerSecondaryDownsyncSessionDict, playerId)
|
||||||
|
delete(pR.PlayerSecondarySignalToCloseDict, playerId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -960,7 +1040,7 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
|
|||||||
Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-middle: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, thatPlayerId=%v, thatPlayerBattleState=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, thatPlayer.Id, thatPlayerBattleState))
|
Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-middle: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, thatPlayerId=%v, thatPlayerBattleState=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, thatPlayer.Id, thatPlayerBattleState))
|
||||||
if thatPlayerId == targetPlayer.Id || (PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK == thatPlayerBattleState || PlayerBattleStateIns.ACTIVE == thatPlayerBattleState) {
|
if thatPlayerId == targetPlayer.Id || (PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK == thatPlayerBattleState || PlayerBattleStateIns.ACTIVE == thatPlayerBattleState) {
|
||||||
Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-sending DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, capacity=%v, EffectivePlayerCount=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, pR.Capacity, pR.EffectivePlayerCount))
|
Logger.Debug(fmt.Sprintf("OnPlayerBattleColliderAcked-sending DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED: roomId=%v, roomState=%v, targetPlayerId=%v, targetPlayerBattleState=%v, capacity=%v, EffectivePlayerCount=%v", pR.Id, pR.State, targetPlayer.Id, targetPlayer.BattleState, pR.Capacity, pR.EffectivePlayerCount))
|
||||||
pR.sendSafely(playerAckedFrame, nil, DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED, thatPlayer.Id, true)
|
pR.sendSafely(playerAckedFrame, nil, DOWNSYNC_MSG_ACT_PLAYER_ADDED_AND_ACKED, thatPlayer.Id, true, MAGIC_JOIN_INDEX_DEFAULT)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
atomic.StoreInt32(&(targetPlayer.BattleState), PlayerBattleStateIns.ACTIVE)
|
atomic.StoreInt32(&(targetPlayer.BattleState), PlayerBattleStateIns.ACTIVE)
|
||||||
@@ -993,19 +1073,19 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) sendSafely(roomDownsyncFrame *pb.RoomDownsyncFrame, toSendInputFrameDownsyncs []*pb.InputFrameDownsync, act int32, playerId int32, needLockExplicitly bool) {
|
func (pR *Room) sendSafely(roomDownsyncFrame *pb.RoomDownsyncFrame, toSendInputFrameDownsyncs []*pb.InputFrameDownsync, act int32, playerId int32, needLockExplicitly bool, peerJoinIndex int32) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
Logger.Error("sendSafely, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r))
|
Logger.Error("sendSafely, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("playerId", playerId), zap.Any("panic", r))
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if playerDownsyncSession, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
|
|
||||||
pResp := &pb.WsResp{
|
pResp := &pb.WsResp{
|
||||||
Ret: int32(Constants.RetCode.Ok),
|
Ret: int32(Constants.RetCode.Ok),
|
||||||
Act: act,
|
Act: act,
|
||||||
Rdf: roomDownsyncFrame,
|
Rdf: roomDownsyncFrame,
|
||||||
InputFrameDownsyncBatch: toSendInputFrameDownsyncs,
|
InputFrameDownsyncBatch: toSendInputFrameDownsyncs,
|
||||||
|
PeerJoinIndex: peerJoinIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
theBytes, marshalErr := proto.Marshal(pResp)
|
theBytes, marshalErr := proto.Marshal(pResp)
|
||||||
@@ -1013,8 +1093,25 @@ func (pR *Room) sendSafely(roomDownsyncFrame *pb.RoomDownsyncFrame, toSendInputF
|
|||||||
panic(fmt.Sprintf("Error marshaling downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount))
|
panic(fmt.Sprintf("Error marshaling downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shouldUseSecondaryWsSession := (MAGIC_JOIN_INDEX_DEFAULT != peerJoinIndex && DOWNSYNC_MSG_ACT_INPUT_BATCH == act) // FIXME: Simplify the condition
|
||||||
|
//Logger.Info(fmt.Sprintf("shouldUseSecondaryWsSession=%v: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v", shouldUseSecondaryWsSession, pR.Id, playerId, pR.State, pR.EffectivePlayerCount))
|
||||||
|
if !shouldUseSecondaryWsSession {
|
||||||
|
if playerDownsyncSession, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
|
||||||
if err := playerDownsyncSession.WriteMessage(websocket.BinaryMessage, theBytes); nil != err {
|
if err := playerDownsyncSession.WriteMessage(websocket.BinaryMessage, theBytes); nil != err {
|
||||||
panic(fmt.Sprintf("Error sending downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v, err=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount, err))
|
panic(fmt.Sprintf("Error sending primary downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v, err=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
[FIXME]
|
||||||
|
This branch is preferred to use an additional session of each player for sending, and the session is preferrably UDP instead of any TCP-based protocol, but I'm being lazy here.
|
||||||
|
|
||||||
|
See `<proj-root>/ConcerningEdgeCases.md` for the advantage of using UDP as a supplement.
|
||||||
|
*/
|
||||||
|
if playerSecondaryDownsyncSession, existent := pR.PlayerSecondaryDownsyncSessionDict[playerId]; existent {
|
||||||
|
if err := playerSecondaryDownsyncSession.WriteMessage(websocket.BinaryMessage, theBytes); nil != err {
|
||||||
|
panic(fmt.Sprintf("Error sending secondary downsync message: roomId=%v, playerId=%v, roomState=%v, roomEffectivePlayerCount=%v, err=%v", pR.Id, playerId, pR.State, pR.EffectivePlayerCount, err))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1065,7 +1162,7 @@ func (pR *Room) getOrPrefabInputFrameDownsync(inputFrameId int32) *battle.InputF
|
|||||||
return currInputFrameDownsync
|
return currInputFrameDownsync
|
||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*pb.InputFrameUpsync, playerId int32, player *Player) *pb.InputsBufferSnapshot {
|
func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*pb.InputFrameUpsync, playerId int32, player *Player, fromUDP bool) *pb.InputsBufferSnapshot {
|
||||||
// [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked!
|
// [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked!
|
||||||
// Step#1, put the received "inputFrameUpsyncBatch" into "pR.InputsBuffer"
|
// Step#1, put the received "inputFrameUpsyncBatch" into "pR.InputsBuffer"
|
||||||
for _, inputFrameUpsync := range inputFrameUpsyncBatch {
|
for _, inputFrameUpsync := range inputFrameUpsyncBatch {
|
||||||
@@ -1076,6 +1173,7 @@ func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*pb.InputFr
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if clientInputFrameId < player.LastReceivedInputFrameId {
|
if clientInputFrameId < player.LastReceivedInputFrameId {
|
||||||
|
// [WARNING] It's important for correctness that we use "player.LastReceivedInputFrameId" instead of "player.LastUdpReceivedInputFrameId" here!
|
||||||
Logger.Debug(fmt.Sprintf("Omitting obsolete inputFrameUpsync#2: roomId=%v, playerId=%v, clientInputFrameId=%v, playerLastReceivedInputFrameId=%v, InputsBuffer=%v", pR.Id, playerId, clientInputFrameId, player.LastReceivedInputFrameId, pR.InputsBufferString(false)))
|
Logger.Debug(fmt.Sprintf("Omitting obsolete inputFrameUpsync#2: roomId=%v, playerId=%v, clientInputFrameId=%v, playerLastReceivedInputFrameId=%v, InputsBuffer=%v", pR.Id, playerId, clientInputFrameId, player.LastReceivedInputFrameId, pR.InputsBufferString(false)))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -1088,14 +1186,28 @@ func (pR *Room) markConfirmationIfApplicable(inputFrameUpsyncBatch []*pb.InputFr
|
|||||||
targetInputFrameDownsync.InputList[player.JoinIndex-1] = inputFrameUpsync.Encoded
|
targetInputFrameDownsync.InputList[player.JoinIndex-1] = inputFrameUpsync.Encoded
|
||||||
targetInputFrameDownsync.ConfirmedList |= uint64(1 << uint32(player.JoinIndex-1))
|
targetInputFrameDownsync.ConfirmedList |= uint64(1 << uint32(player.JoinIndex-1))
|
||||||
|
|
||||||
player.LastReceivedInputFrameId = clientInputFrameId
|
if false == fromUDP {
|
||||||
pR.LastIndividuallyConfirmedInputList[player.JoinIndex-1] = inputFrameUpsync.Encoded
|
/*
|
||||||
|
[WARNING] We have to distinguish whether or not the incoming batch is from UDP here, otherwise "pR.LatestPlayerUpsyncedInputFrameId - pR.LastAllConfirmedInputFrameId" might become unexpectedly large in case of "UDP packet loss + slow ws session"!
|
||||||
|
|
||||||
|
Moreover, only ws session upsyncs should advance "player.LastReceivedInputFrameId" & "pR.LatestPlayerUpsyncedInputFrameId".
|
||||||
|
|
||||||
|
Kindly note that the updates of "player.LastReceivedInputFrameId" could be discrete before and after reconnection.
|
||||||
|
*/
|
||||||
|
player.LastReceivedInputFrameId = clientInputFrameId
|
||||||
if clientInputFrameId > pR.LatestPlayerUpsyncedInputFrameId {
|
if clientInputFrameId > pR.LatestPlayerUpsyncedInputFrameId {
|
||||||
pR.LatestPlayerUpsyncedInputFrameId = clientInputFrameId
|
pR.LatestPlayerUpsyncedInputFrameId = clientInputFrameId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if clientInputFrameId > player.LastUdpReceivedInputFrameId {
|
||||||
|
// No need to update "player.LastUdpReceivedInputFrameId" only when "true == fromUDP", we should keep "player.LastUdpReceivedInputFrameId >= player.LastReceivedInputFrameId" at any moment.
|
||||||
|
player.LastUdpReceivedInputFrameId = clientInputFrameId
|
||||||
|
// It's safe (in terms of getting an eventually correct "RenderFrameBuffer") to put the following update of "pR.LastIndividuallyConfirmedInputList" which is ONLY used for prediction in "InputsBuffer" out of "false == fromUDP" block.
|
||||||
|
pR.LastIndividuallyConfirmedInputList[player.JoinIndex-1] = inputFrameUpsync.Encoded
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Step#2, mark confirmation without forcing
|
// Step#2, mark confirmation without forcing
|
||||||
newAllConfirmedCount := int32(0)
|
newAllConfirmedCount := int32(0)
|
||||||
inputFrameId1 := pR.LastAllConfirmedInputFrameId + 1
|
inputFrameId1 := pR.LastAllConfirmedInputFrameId + 1
|
||||||
@@ -1159,6 +1271,7 @@ func (pR *Room) forceConfirmationIfApplicable(prevRenderFrameId int32) uint64 {
|
|||||||
totPlayerCnt := uint32(pR.Capacity)
|
totPlayerCnt := uint32(pR.Capacity)
|
||||||
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
|
allConfirmedMask := uint64((1 << totPlayerCnt) - 1)
|
||||||
unconfirmedMask := uint64(0)
|
unconfirmedMask := uint64(0)
|
||||||
|
// As "pR.LastAllConfirmedInputFrameId" can be advanced by UDP but "pR.LatestPlayerUpsyncedInputFrameId" could only be advanced by ws session, when the following condition is met we know that the slow ticker is really in trouble!
|
||||||
if pR.LatestPlayerUpsyncedInputFrameId > (pR.LastAllConfirmedInputFrameId + pR.InputFrameUpsyncDelayTolerance + 1) {
|
if pR.LatestPlayerUpsyncedInputFrameId > (pR.LastAllConfirmedInputFrameId + pR.InputFrameUpsyncDelayTolerance + 1) {
|
||||||
// Type#1 check whether there's a significantly slow ticker among players
|
// Type#1 check whether there's a significantly slow ticker among players
|
||||||
oldLastAllConfirmedInputFrameId := pR.LastAllConfirmedInputFrameId
|
oldLastAllConfirmedInputFrameId := pR.LastAllConfirmedInputFrameId
|
||||||
@@ -1280,13 +1393,13 @@ func (pR *Room) printBarrier(barrierCollider *resolv.Object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (pR *Room) doBattleMainLoopPerTickBackendDynamicsWithProperLocking(prevRenderFrameId int32, pDynamicsDuration *int64) {
|
func (pR *Room) doBattleMainLoopPerTickBackendDynamicsWithProperLocking(prevRenderFrameId int32, pDynamicsDuration *int64) {
|
||||||
Logger.Debug(fmt.Sprintf("doBattleMainLoopPerTickBackendDynamicsWithProperLocking-InputsBufferLock to about lock: roomId=%v", pR.Id))
|
//Logger.Debug(fmt.Sprintf("doBattleMainLoopPerTickBackendDynamicsWithProperLocking-InputsBufferLock to about lock: roomId=%v", pR.Id))
|
||||||
pR.InputsBufferLock.Lock()
|
pR.InputsBufferLock.Lock()
|
||||||
Logger.Debug(fmt.Sprintf("doBattleMainLoopPerTickBackendDynamicsWithProperLocking-InputsBufferLock locked: roomId=%v", pR.Id))
|
//Logger.Debug(fmt.Sprintf("doBattleMainLoopPerTickBackendDynamicsWithProperLocking-InputsBufferLock locked: roomId=%v", pR.Id))
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
pR.InputsBufferLock.Unlock()
|
pR.InputsBufferLock.Unlock()
|
||||||
Logger.Debug(fmt.Sprintf("doBattleMainLoopPerTickBackendDynamicsWithProperLocking-InputsBufferLock unlocked: roomId=%v", pR.Id))
|
//Logger.Debug(fmt.Sprintf("doBattleMainLoopPerTickBackendDynamicsWithProperLocking-InputsBufferLock unlocked: roomId=%v", pR.Id))
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if ok, thatRenderFrameId := battle.ShouldPrefabInputFrameDownsync(prevRenderFrameId, pR.RenderFrameId); ok {
|
if ok, thatRenderFrameId := battle.ShouldPrefabInputFrameDownsync(prevRenderFrameId, pR.RenderFrameId); ok {
|
||||||
@@ -1325,11 +1438,35 @@ func (pR *Room) doBattleMainLoopPerTickBackendDynamicsWithProperLocking(prevRend
|
|||||||
snapshotStFrameId = refSnapshotStFrameId
|
snapshotStFrameId = refSnapshotStFrameId
|
||||||
}
|
}
|
||||||
inputsBufferSnapshot := pR.produceInputsBufferSnapshotWithCurDynamicsRenderFrameAsRef(unconfirmedMask, snapshotStFrameId, pR.LastAllConfirmedInputFrameId+1)
|
inputsBufferSnapshot := pR.produceInputsBufferSnapshotWithCurDynamicsRenderFrameAsRef(unconfirmedMask, snapshotStFrameId, pR.LastAllConfirmedInputFrameId+1)
|
||||||
Logger.Debug(fmt.Sprintf("[forceConfirmation] roomId=%v, room.RenderFrameId=%v, room.CurDynamicsRenderFrameId=%v, room.LastAllConfirmedInputFrameId=%v, unconfirmedMask=%v", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LastAllConfirmedInputFrameId, unconfirmedMask))
|
//Logger.Warn(fmt.Sprintf("[forceConfirmation] roomId=%v, room.RenderFrameId=%v, room.CurDynamicsRenderFrameId=%v, room.LastAllConfirmedInputFrameId=%v, unconfirmedMask=%v", pR.Id, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, pR.LastAllConfirmedInputFrameId, unconfirmedMask))
|
||||||
pR.downsyncToAllPlayers(inputsBufferSnapshot)
|
pR.downsyncToAllPlayers(inputsBufferSnapshot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pR *Room) broadcastPeerUpsyncForBetterPrediction(inputsBufferSnapshot *pb.InputsBufferSnapshot) {
|
||||||
|
// See `<proj-root>/ConcerningEdgeCases.md` for why this method exists.
|
||||||
|
for _, player := range pR.PlayersArr {
|
||||||
|
playerBattleState := atomic.LoadInt32(&(player.BattleState))
|
||||||
|
switch playerBattleState {
|
||||||
|
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL, PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if player.JoinIndex == inputsBufferSnapshot.PeerJoinIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if playerSecondaryDownsyncChan, existent := pR.PlayerSecondaryDownsyncChanDict[player.Id]; existent {
|
||||||
|
/*
|
||||||
|
[FIXME]
|
||||||
|
This function is preferred to use an additional go-channel of each player for sending, see "downsyncLoop" & "Room.sendSafely" for more information!
|
||||||
|
*/
|
||||||
|
playerSecondaryDownsyncChan <- (*inputsBufferSnapshot)
|
||||||
|
} else {
|
||||||
|
Logger.Warn(fmt.Sprintf("playerDownsyncChan for (roomId: %d, playerId:%d) is gone", pR.Id, player.Id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *pb.InputsBufferSnapshot) {
|
func (pR *Room) downsyncToAllPlayers(inputsBufferSnapshot *pb.InputsBufferSnapshot) {
|
||||||
/*
|
/*
|
||||||
[WARNING] This function MUST BE called while "pR.InputsBufferLock" is LOCKED to **preserve the order of generation of "inputsBufferSnapshot" for sending** -- see comments in "OnBattleCmdReceived" and [this issue](https://github.com/genxium/DelayNoMore/issues/12).
|
[WARNING] This function MUST BE called while "pR.InputsBufferLock" is LOCKED to **preserve the order of generation of "inputsBufferSnapshot" for sending** -- see comments in "OnBattleCmdReceived" and [this issue](https://github.com/genxium/DelayNoMore/issues/12).
|
||||||
@@ -1406,14 +1543,14 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
|
|||||||
We hereby assume that Golang runtime allocates & frees small amount of RAM quickly enough compared to either network I/O blocking in worst cases or the high frequency "per inputFrameDownsync*player" locking (though "OnBattleCmdReceived" locks at the same frequency but it's inevitable).
|
We hereby assume that Golang runtime allocates & frees small amount of RAM quickly enough compared to either network I/O blocking in worst cases or the high frequency "per inputFrameDownsync*player" locking (though "OnBattleCmdReceived" locks at the same frequency but it's inevitable).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
playerJoinIndex := player.JoinIndex - 1
|
playerJoinIndexInBooleanArr := player.JoinIndex - 1
|
||||||
playerBattleState := atomic.LoadInt32(&(player.BattleState))
|
playerBattleState := atomic.LoadInt32(&(player.BattleState))
|
||||||
switch playerBattleState {
|
switch playerBattleState {
|
||||||
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL, PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
|
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL, PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
isSlowTicker := (0 < (unconfirmedMask & uint64(1<<uint32(playerJoinIndex))))
|
isSlowTicker := (0 < (unconfirmedMask & uint64(1<<uint32(playerJoinIndexInBooleanArr))))
|
||||||
shouldResync1 := (PlayerBattleStateIns.READDED_BATTLE_COLLIDER_ACKED == playerBattleState) // i.e. implies that "MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId"
|
shouldResync1 := (PlayerBattleStateIns.READDED_BATTLE_COLLIDER_ACKED == playerBattleState) // i.e. implies that "MAGIC_LAST_SENT_INPUT_FRAME_ID_READDED == player.LastSentInputFrameId"
|
||||||
shouldResync2 := isSlowTicker // This condition is critical, if we don't send resync upon this condition, the "reconnected or slowly-clocking player" might never get its input synced
|
shouldResync2 := isSlowTicker // This condition is critical, if we don't send resync upon this condition, the "reconnected or slowly-clocking player" might never get its input synced
|
||||||
shouldResync3 := shouldForceResync
|
shouldResync3 := shouldForceResync
|
||||||
@@ -1438,13 +1575,13 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
|
|||||||
refRenderFrame.BackendUnconfirmedMask = unconfirmedMask
|
refRenderFrame.BackendUnconfirmedMask = unconfirmedMask
|
||||||
pbRefRenderFrame := toPbRoomDownsyncFrame(refRenderFrame)
|
pbRefRenderFrame := toPbRoomDownsyncFrame(refRenderFrame)
|
||||||
pbRefRenderFrame.SpeciesIdList = pR.SpeciesIdList
|
pbRefRenderFrame.SpeciesIdList = pR.SpeciesIdList
|
||||||
pR.sendSafely(pbRefRenderFrame, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_FORCED_RESYNC, playerId, false)
|
pR.sendSafely(pbRefRenderFrame, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_FORCED_RESYNC, playerId, false, MAGIC_JOIN_INDEX_DEFAULT)
|
||||||
//Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: InputsBuffer=%v", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, pR.InputsBufferString(false)))
|
//Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: InputsBuffer=%v", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, pR.InputsBufferString(false)))
|
||||||
if shouldResync1 {
|
if shouldResync1 || shouldResync3 {
|
||||||
Logger.Warn(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: shouldResync1=%v, shouldResync2=%v, shouldResync3=%v, playerBattleState=%d", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, shouldResync1, shouldResync2, shouldResync3, playerBattleState))
|
Logger.Debug(fmt.Sprintf("Sent refRenderFrameId=%v & inputFrameIds [%d, %d), for roomId=%v, playerId=%d, playerJoinIndex=%d, renderFrameId=%d, curDynamicsRenderFrameId=%d, playerLastSentInputFrameId=%d: shouldResync1=%v, shouldResync2=%v, shouldResync3=%v, playerBattleState=%d", refRenderFrameId, toSendInputFrameIdSt, toSendInputFrameIdEd, pR.Id, playerId, player.JoinIndex, pR.RenderFrameId, pR.CurDynamicsRenderFrameId, player.LastSentInputFrameId, shouldResync1, shouldResync2, shouldResync3, playerBattleState))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId, false)
|
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_INPUT_BATCH, playerId, false, MAGIC_JOIN_INDEX_DEFAULT)
|
||||||
}
|
}
|
||||||
player.LastSentInputFrameId = toSendInputFrameIdEd - 1
|
player.LastSentInputFrameId = toSendInputFrameIdEd - 1
|
||||||
if shouldResync1 {
|
if shouldResync1 {
|
||||||
@@ -1452,6 +1589,16 @@ func (pR *Room) downsyncToSinglePlayer(playerId int32, player *Player, refRender
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pR *Room) downsyncPeerInputFrameUpsyncToSinglePlayer(playerId int32, player *Player, toSendInputFrameDownsyncsSnapshot []*pb.InputFrameDownsync, peerJoinIndex int32) {
|
||||||
|
playerBattleState := atomic.LoadInt32(&(player.BattleState))
|
||||||
|
switch playerBattleState {
|
||||||
|
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL, PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
pR.sendSafely(nil, toSendInputFrameDownsyncsSnapshot, DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH, playerId, false, peerJoinIndex)
|
||||||
|
}
|
||||||
|
|
||||||
func (pR *Room) cloneInputsBuffer(stFrameId, edFrameId int32) []*pb.InputFrameDownsync {
|
func (pR *Room) cloneInputsBuffer(stFrameId, edFrameId int32) []*pb.InputFrameDownsync {
|
||||||
// [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked!
|
// [WARNING] This function MUST BE called while "pR.InputsBufferLock" is locked!
|
||||||
cloned := make([]*pb.InputFrameDownsync, 0, edFrameId-stFrameId)
|
cloned := make([]*pb.InputFrameDownsync, 0, edFrameId-stFrameId)
|
||||||
@@ -1484,3 +1631,163 @@ func (pR *Room) cloneInputsBuffer(stFrameId, edFrameId int32) []*pb.InputFrameDo
|
|||||||
|
|
||||||
return cloned
|
return cloned
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (pR *Room) SetSecondarySession(playerId int32, session *websocket.Conn, signalToCloseConnOfThisPlayer SignalToCloseConnCbType) {
|
||||||
|
// TODO: Use a dedicated lock
|
||||||
|
if player, ok := pR.Players[playerId]; ok {
|
||||||
|
playerBattleState := atomic.LoadInt32(&(player.BattleState))
|
||||||
|
switch playerBattleState {
|
||||||
|
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
|
||||||
|
// Kindly note that "PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK" are allowed
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
|
||||||
|
if _, existent2 := pR.PlayerSecondaryDownsyncSessionDict[playerId]; !existent2 {
|
||||||
|
Logger.Info(fmt.Sprintf("SetSecondarySession for roomId=%v, playerId=%d, pR.Players=%v", pR.Id, playerId, pR.Players))
|
||||||
|
pR.PlayerSecondaryDownsyncSessionDict[playerId] = session
|
||||||
|
pR.PlayerSecondarySignalToCloseDict[playerId] = signalToCloseConnOfThisPlayer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pR *Room) UpdatePeerUdpAddrList(playerId int32, peerAddr *net.UDPAddr, pReq *pb.HolePunchUpsync) {
|
||||||
|
// TODO: There's a chance that by now "player.JoinIndex" is not yet determined, use a lock to sync
|
||||||
|
if player, ok := pR.Players[playerId]; ok && MAGIC_JOIN_INDEX_DEFAULT != player.JoinIndex {
|
||||||
|
playerBattleState := atomic.LoadInt32(&(player.BattleState))
|
||||||
|
switch playerBattleState {
|
||||||
|
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
|
||||||
|
// Kindly note that "PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK, PlayerBattleStateIns.READDED_PENDING_BATTLE_COLLIDER_ACK" are allowed
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if _, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
|
||||||
|
player.UdpAddr = &pb.PeerUdpAddr{
|
||||||
|
Ip: peerAddr.IP.String(),
|
||||||
|
Port: int32(peerAddr.Port),
|
||||||
|
AuthKey: pReq.AuthKey,
|
||||||
|
}
|
||||||
|
Logger.Info(fmt.Sprintf("UpdatePeerUdpAddrList done for roomId=%v, playerId=%d, peerAddr=%s", pR.Id, playerId, peerAddr))
|
||||||
|
|
||||||
|
peerJoinIndex := player.JoinIndex
|
||||||
|
peerUdpAddrList := make([]*pb.PeerUdpAddr, pR.Capacity, pR.Capacity)
|
||||||
|
|
||||||
|
for _, otherPlayer := range pR.Players {
|
||||||
|
if MAGIC_JOIN_INDEX_DEFAULT == otherPlayer.JoinIndex {
|
||||||
|
// TODO: Again this shouldn't happen, apply proper locking
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// In case of highly concurrent update that might occur while later marshalling, use the ptr of a copy
|
||||||
|
peerUdpAddrList[otherPlayer.JoinIndex-1] = &pb.PeerUdpAddr{
|
||||||
|
Ip: otherPlayer.UdpAddr.Ip,
|
||||||
|
Port: otherPlayer.UdpAddr.Port,
|
||||||
|
AuthKey: otherPlayer.UdpAddr.AuthKey,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Broadcast this new UDP addr to all the existing players
|
||||||
|
for otherPlayerId, otherPlayer := range pR.Players {
|
||||||
|
otherPlayerBattleState := atomic.LoadInt32(&(otherPlayer.BattleState))
|
||||||
|
switch otherPlayerBattleState {
|
||||||
|
case PlayerBattleStateIns.DISCONNECTED, PlayerBattleStateIns.LOST, PlayerBattleStateIns.EXPELLED_DURING_GAME, PlayerBattleStateIns.EXPELLED_IN_DISMISSAL:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Info(fmt.Sprintf("Downsyncing peerUdpAddrList for roomId=%v, playerId=%d", pR.Id, otherPlayerId))
|
||||||
|
pR.sendSafely(&pb.RoomDownsyncFrame{
|
||||||
|
PeerUdpAddrList: peerUdpAddrList,
|
||||||
|
}, nil, DOWNSYNC_MSG_ACT_PEER_UDP_ADDR, otherPlayerId, false, peerJoinIndex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pR *Room) startBattleUdpTunnel() {
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
Logger.Error("`BattleUdpTunnel` recovery spot#1, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("panic", r))
|
||||||
|
}
|
||||||
|
Logger.Info(fmt.Sprintf("`BattleUdpTunnel` stopped for (roomId=%d)@renderFrameId=%v", pR.Id, pR.RenderFrameId))
|
||||||
|
}()
|
||||||
|
|
||||||
|
pR.BattleUdpTunnelLock.Lock()
|
||||||
|
conn, err := net.ListenUDP("udp", &net.UDPAddr{
|
||||||
|
Port: 0,
|
||||||
|
IP: net.ParseIP(Conf.Sio.UdpHost),
|
||||||
|
})
|
||||||
|
if nil != err {
|
||||||
|
// No need to close the "conn" upon error here
|
||||||
|
pR.BattleUdpTunnelLock.Unlock()
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pR.BattleUdpTunnel = conn
|
||||||
|
switch v := conn.LocalAddr().(type) {
|
||||||
|
case (*net.UDPAddr):
|
||||||
|
pR.BattleUdpTunnelAddr = &pb.PeerUdpAddr{
|
||||||
|
Ip: Conf.Sio.UdpHost,
|
||||||
|
Port: int32(v.Port),
|
||||||
|
AuthKey: 0, // To be determined for each specific player upon joining and sent to it by BattleColliderInfo
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pR.BattleUdpTunnelLock.Unlock()
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
Logger.Warn("`BattleUdpTunnel` recovery spot#2, recovered from: ", zap.Any("roomId", pR.Id), zap.Any("panic", r))
|
||||||
|
}
|
||||||
|
Logger.Info(fmt.Sprintf("`BattleUdpTunnel` closed for (roomId=%d)@renderFrameId=%v", pR.Id, pR.RenderFrameId))
|
||||||
|
}()
|
||||||
|
Logger.Info(fmt.Sprintf("`BattleUdpTunnel` started for roomId=%d at %s", pR.Id, conn.LocalAddr().String()))
|
||||||
|
for {
|
||||||
|
message := make([]byte, 128)
|
||||||
|
rlen, remote, err := conn.ReadFromUDP(message[:]) // Would be unblocked when "conn.Close()" is called from another thread/goroutine, reference https://pkg.go.dev/net@go1.18.6#PacketConn
|
||||||
|
if nil != err {
|
||||||
|
// Should proceed to close the "conn" upon error here, if "conn" is already closed it'd just throw another error to be catched by "spot#2"
|
||||||
|
conn.Close()
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
pReq := new(pb.WsReq)
|
||||||
|
bytes := message[0:rlen]
|
||||||
|
if unmarshalErr := proto.Unmarshal(bytes, pReq); nil != unmarshalErr {
|
||||||
|
Logger.Warn(fmt.Sprintf("`BattleUdpTunnel` for roomId=%d failed to unmarshal %d bytes", pR.Id, rlen), zap.Error(unmarshalErr))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
playerId := pReq.PlayerId
|
||||||
|
//Logger.Info(fmt.Sprintf("`BattleUdpTunnel` for roomId=%d received decoded WsReq:", pR.Id), zap.Any("pReq", pReq))
|
||||||
|
if player, exists1 := pR.Players[playerId]; exists1 {
|
||||||
|
authKey := pReq.AuthKey
|
||||||
|
if authKey != player.BattleUdpTunnelAuthKey {
|
||||||
|
Logger.Warn(fmt.Sprintf("`BattleUdpTunnel` for roomId=%d received %d bytes for playerId=%d from %s, but (incomingAuthKey:%d != playerBattleUdpTunnelAuthKey:%d)\n", pR.Id, rlen, playerId, remote, authKey, player.BattleUdpTunnelAuthKey))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, existent := pR.PlayerDownsyncSessionDict[playerId]; existent {
|
||||||
|
player.BattleUdpTunnelAddr = remote
|
||||||
|
//Logger.Info(fmt.Sprintf("`BattleUdpTunnel` for roomId=%d updated battleUdpAddr for playerId=%d to be %s\n", pR.Id, playerId, remote))
|
||||||
|
|
||||||
|
nowBattleState := atomic.LoadInt32(&pR.State)
|
||||||
|
if RoomBattleStateIns.IN_BATTLE == nowBattleState {
|
||||||
|
batch := pReq.InputFrameUpsyncBatch
|
||||||
|
if nil != batch && 0 < len(batch) {
|
||||||
|
peerJoinIndex := pReq.JoinIndex
|
||||||
|
// Broadcast to every other player in the same room/battle
|
||||||
|
for _, otherPlayer := range pR.PlayersArr {
|
||||||
|
if otherPlayer.JoinIndex == peerJoinIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
_, wrerr := conn.WriteTo(bytes, otherPlayer.BattleUdpTunnelAddr)
|
||||||
|
if nil != wrerr {
|
||||||
|
Logger.Warn(fmt.Sprintf("`BattleUdpTunnel` for roomId=%d failed to forward upsync from (playerId:%d, joinIndex:%d, addr:%s) to (otherPlayerId:%d, otherPlayerJoinIndex:%d, otherPlayerAddr:%s)\n", pR.Id, playerId, peerJoinIndex, remote, otherPlayer.Id, otherPlayer.JoinIndex, otherPlayer.BattleUdpTunnelAddr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pR.OnBattleCmdReceived(pReq, true) // To help advance "pR.LastAllConfirmedInputFrameId" asap, and even if "pR.LastAllConfirmedInputFrameId" is not advanced due to packet loss, these UDP packets would help prefill the "InputsBuffer" with correct player "future inputs (compared to ws session)" such that when "forceConfirmation" occurs we have as many correct predictions as possible
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger.Warn(fmt.Sprintf("`BattleUdpTunnel` for roomId=%d received validated %d bytes for playerId=%d from %s, but primary downsync session for it doesn't exist\n", pR.Id, rlen, playerId, remote))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger.Warn(fmt.Sprintf("`BattleUdpTunnel` for roomId=%d received invalid %d bytes for playerId=%d from %s, but it doesn't belong to this room!\n", pR.Id, rlen, playerId, remote))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@@ -46,6 +47,7 @@ func Serve(c *gin.Context) {
|
|||||||
c.AbortWithStatus(http.StatusBadRequest)
|
c.AbortWithStatus(http.StatusBadRequest)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
boundRoomId := 0
|
boundRoomId := 0
|
||||||
expectedRoomId := 0
|
expectedRoomId := 0
|
||||||
var err error
|
var err error
|
||||||
@@ -257,6 +259,13 @@ func Serve(c *gin.Context) {
|
|||||||
|
|
||||||
RenderCacheSize: pRoom.RenderCacheSize,
|
RenderCacheSize: pRoom.RenderCacheSize,
|
||||||
CollisionMinStep: pRoom.CollisionMinStep,
|
CollisionMinStep: pRoom.CollisionMinStep,
|
||||||
|
BoundRoomCapacity: int32(pRoom.Capacity),
|
||||||
|
|
||||||
|
BattleUdpTunnel: &pb.PeerUdpAddr{
|
||||||
|
Ip: pRoom.BattleUdpTunnelAddr.Ip,
|
||||||
|
Port: pRoom.BattleUdpTunnelAddr.Port,
|
||||||
|
AuthKey: pThePlayer.BattleUdpTunnelAuthKey,
|
||||||
|
},
|
||||||
|
|
||||||
FrameDataLoggingEnabled: pRoom.FrameDataLoggingEnabled,
|
FrameDataLoggingEnabled: pRoom.FrameDataLoggingEnabled,
|
||||||
}
|
}
|
||||||
@@ -266,6 +275,7 @@ func Serve(c *gin.Context) {
|
|||||||
EchoedMsgId: int32(0),
|
EchoedMsgId: int32(0),
|
||||||
Act: models.DOWNSYNC_MSG_ACT_HB_REQ,
|
Act: models.DOWNSYNC_MSG_ACT_HB_REQ,
|
||||||
BciFrame: bciFrame,
|
BciFrame: bciFrame,
|
||||||
|
PeerJoinIndex: pThePlayer.JoinIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.Debug("Sending downsync HeartbeatRequirements:", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Any("resp", resp))
|
Logger.Debug("Sending downsync HeartbeatRequirements:", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Any("resp", resp))
|
||||||
@@ -378,7 +388,7 @@ func Serve(c *gin.Context) {
|
|||||||
startOrFeedHeartbeatWatchdog(conn)
|
startOrFeedHeartbeatWatchdog(conn)
|
||||||
case models.UPSYNC_MSG_ACT_PLAYER_CMD:
|
case models.UPSYNC_MSG_ACT_PLAYER_CMD:
|
||||||
startOrFeedHeartbeatWatchdog(conn)
|
startOrFeedHeartbeatWatchdog(conn)
|
||||||
pRoom.OnBattleCmdReceived(pReq)
|
pRoom.OnBattleCmdReceived(pReq, false)
|
||||||
case models.UPSYNC_MSG_ACT_PLAYER_COLLIDER_ACK:
|
case models.UPSYNC_MSG_ACT_PLAYER_COLLIDER_ACK:
|
||||||
res := pRoom.OnPlayerBattleColliderAcked(int32(playerId))
|
res := pRoom.OnPlayerBattleColliderAcked(int32(playerId))
|
||||||
if false == res {
|
if false == res {
|
||||||
@@ -395,3 +405,118 @@ func Serve(c *gin.Context) {
|
|||||||
startOrFeedHeartbeatWatchdog(conn)
|
startOrFeedHeartbeatWatchdog(conn)
|
||||||
go receivingLoopAgainstPlayer()
|
go receivingLoopAgainstPlayer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func HandleSecondaryWsSessionForPlayer(c *gin.Context) {
|
||||||
|
token, ok := c.GetQuery("intAuthToken")
|
||||||
|
if !ok {
|
||||||
|
Logger.Warn("Secondary ws session req must have intAuthToken param!")
|
||||||
|
c.AbortWithStatus(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
boundRoomId := 0
|
||||||
|
var err error = nil
|
||||||
|
if boundRoomIdStr, hasBoundRoomId := c.GetQuery("boundRoomId"); hasBoundRoomId {
|
||||||
|
boundRoomId, err = strconv.Atoi(boundRoomIdStr)
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithStatus(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger.Warn("Secondary ws session req must have boundRoomId param:", zap.Any("intAuthToken", token))
|
||||||
|
c.AbortWithStatus(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var pRoom *models.Room = nil
|
||||||
|
// Deliberately querying playerId after querying room, because the former is against persistent storage and could be slow!
|
||||||
|
if tmpPRoom, existent := (*models.RoomMapManagerIns)[int32(boundRoomId)]; !existent {
|
||||||
|
Logger.Warn("Secondary ws session failed to get:\n", zap.Any("intAuthToken", token), zap.Any("forBoundRoomId", boundRoomId))
|
||||||
|
c.AbortWithStatus(http.StatusBadRequest)
|
||||||
|
} else {
|
||||||
|
pRoom = tmpPRoom
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Wrap the following 2 stmts by sql transaction!
|
||||||
|
playerId, err := models.GetPlayerIdByToken(token)
|
||||||
|
if err != nil || playerId == 0 {
|
||||||
|
// TODO: Abort with specific message.
|
||||||
|
Logger.Warn("Secondary ws session playerLogin record not found:", zap.Any("intAuthToken", token))
|
||||||
|
c.AbortWithStatus(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Info("Secondary ws session playerLogin record has been found:", zap.Any("playerId", playerId), zap.Any("intAuthToken", token), zap.Any("boundRoomId", boundRoomId))
|
||||||
|
|
||||||
|
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
|
||||||
|
if err != nil {
|
||||||
|
Logger.Error("Secondary ws session upgrade:", zap.Error(err), zap.Any("playerId", playerId))
|
||||||
|
c.AbortWithStatus(http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connHasBeenSignaledToClose := int32(0)
|
||||||
|
pConnHasBeenSignaledToClose := &connHasBeenSignaledToClose
|
||||||
|
|
||||||
|
signalToCloseConnOfThisPlayer := func(customRetCode int, customRetMsg string) {
|
||||||
|
if swapped := atomic.CompareAndSwapInt32(pConnHasBeenSignaledToClose, 0, 1); !swapped {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Logger.Warn("Secondary ws session signalToCloseConnOfThisPlayer:", zap.Any("playerId", playerId), zap.Any("customRetCode", customRetCode), zap.Any("customRetMsg", customRetMsg))
|
||||||
|
defer func() {
|
||||||
|
if r := recover(); r != nil {
|
||||||
|
Logger.Error("Secondary ws session recovered from: ", zap.Any("panic", r))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
closeMessage := websocket.FormatCloseMessage(customRetCode, customRetMsg)
|
||||||
|
err := conn.WriteControl(websocket.CloseMessage, closeMessage, time.Now().Add(time.Millisecond*(ConstVals.Ws.WillKickIfInactiveFor)))
|
||||||
|
if err != nil {
|
||||||
|
Logger.Error("Secondary ws session unable to send the CloseFrame control message to player(client-side):", zap.Any("playerId", playerId), zap.Error(err))
|
||||||
|
}
|
||||||
|
|
||||||
|
time.AfterFunc(3*time.Second, func() {
|
||||||
|
// To actually terminates the underlying TCP connection which might be in `CLOSE_WAIT` state if inspected by `netstat`.
|
||||||
|
conn.Close()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onReceivedCloseMessageFromClient := func(code int, text string) error {
|
||||||
|
Logger.Warn("Secondary ws session triggered `onReceivedCloseMessageFromClient`:", zap.Any("code", code), zap.Any("playerId", playerId), zap.Any("message", text))
|
||||||
|
signalToCloseConnOfThisPlayer(code, text)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.SetCloseHandler(onReceivedCloseMessageFromClient)
|
||||||
|
|
||||||
|
pRoom.SetSecondarySession(int32(playerId), conn, signalToCloseConnOfThisPlayer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleUdpHolePunchingForPlayer(message []byte, peerAddr *net.UDPAddr) {
|
||||||
|
pReq := new(pb.HolePunchUpsync)
|
||||||
|
if unmarshalErr := proto.Unmarshal(message, pReq); nil != unmarshalErr {
|
||||||
|
Logger.Error("`GrandUdpServer` failed to unmarshal", zap.Error(unmarshalErr))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
token := pReq.IntAuthToken
|
||||||
|
boundRoomId := pReq.BoundRoomId
|
||||||
|
|
||||||
|
pRoom, existent := (*models.RoomMapManagerIns)[int32(boundRoomId)]
|
||||||
|
// Deliberately querying playerId after querying room, because the former is against persistent storage and could be slow!
|
||||||
|
if !existent {
|
||||||
|
Logger.Warn("`GrandUdpServer` failed to get:\n", zap.Any("intAuthToken", token), zap.Any("forBoundRoomId", boundRoomId))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Wrap the following 2 stmts by sql transaction!
|
||||||
|
playerId, err := models.GetPlayerIdByToken(token)
|
||||||
|
if err != nil || playerId == 0 {
|
||||||
|
// TODO: Abort with specific message.
|
||||||
|
Logger.Warn("`GrandUdpServer` playerLogin record not found for:", zap.Any("intAuthToken", token))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.Info("`GrandUdpServer` playerLogin record has been found:", zap.Any("playerId", playerId), zap.Any("intAuthToken", token), zap.Any("boundRoomId", boundRoomId), zap.Any("peerAddr", peerAddr))
|
||||||
|
pRoom.UpdatePeerUdpAddrList(int32(playerId), peerAddr, pReq)
|
||||||
|
}
|
||||||
|
BIN
charts/NativeBuildReload.png
Normal file
After Width: | Height: | Size: 118 KiB |
BIN
charts/PackageNameIssueInCcc.png
Normal file
After Width: | Height: | Size: 135 KiB |
BIN
charts/ServerClients.jpg
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
charts/UDPEssentials.jpg
Normal file
After Width: | Height: | Size: 472 KiB |
BIN
charts/VisualStudioSetup.png
Normal file
After Width: | Height: | Size: 191 KiB |
BIN
charts/internet_dash_turnaround_cut_spedup.gif
Normal file
After Width: | Height: | Size: 6.7 MiB |
BIN
charts/internet_fireball_explosion_wallmove_spedup.gif
Normal file
After Width: | Height: | Size: 3.7 MiB |
Before Width: | Height: | Size: 11 MiB |
BIN
charts/networkstats.png
Normal file
After Width: | Height: | Size: 2.2 MiB |
@@ -1,66 +0,0 @@
|
|||||||
function NetworkDoctor(serverFps, clientUpsyncFps) {
|
|
||||||
this.serverFps = serverFps;
|
|
||||||
this.clientUpsyncFps = clientUpsyncFps;
|
|
||||||
this.millisPerServerFrame = parseInt(1000 / this.serverFps);
|
|
||||||
this._tooLongSinceLastFrameDiffReceivedThreshold = (this.millisPerServerFrame << 6);
|
|
||||||
|
|
||||||
this.setupFps = function(fps) {
|
|
||||||
this.serverFps = this.clientUpsyncFps = fps;
|
|
||||||
this.millisPerServerFrame = parseInt(1000 / this.serverFps);
|
|
||||||
this._tooLongSinceLastFrameDiffReceivedThreshold = (this.millisPerServerFrame << 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
this._lastFrameDiffRecvTime = null;
|
|
||||||
this._tooLongSinceLastFrameDiffReceived = function() {
|
|
||||||
if (undefined === this._lastFrameDiffRecvTime || null === this._lastFrameDiffRecvTime) return false;
|
|
||||||
return (this._tooLongSinceLastFrameDiffReceivedThreshold <= (Date.now() - this._lastFrameDiffRecvTime));
|
|
||||||
};
|
|
||||||
|
|
||||||
this._consecutiveALittleLongFrameDiffReceivedIntervalCount = 0;
|
|
||||||
this._consecutiveALittleLongFrameDiffReceivedIntervalCountThreshold = 120;
|
|
||||||
|
|
||||||
this.onNewFrameDiffReceived = function(frameDiff) {
|
|
||||||
var now = Date.now();
|
|
||||||
if (undefined !== this._lastFrameDiffRecvTime && null !== this._lastFrameDiffRecvTime) {
|
|
||||||
var intervalFromLastFrameDiff = (now - this._lastFrameDiffRecvTime);
|
|
||||||
if ((this.millisPerServerFrame << 5) < intervalFromLastFrameDiff) {
|
|
||||||
++this._consecutiveALittleLongFrameDiffReceivedIntervalCount;
|
|
||||||
console.log('Medium delay, intervalFromLastFrameDiff is', intervalFromLastFrameDiff);
|
|
||||||
} else {
|
|
||||||
this._consecutiveALittleLongFrameDiffReceivedIntervalCount = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._lastFrameDiffRecvTime = now;
|
|
||||||
};
|
|
||||||
|
|
||||||
this._networkComplaintPrefix = "\nNetwork is not good >_<\n";
|
|
||||||
|
|
||||||
this.generateNetworkComplaint = function(excludeTypeConstantALittleLongFrameDiffReceivedInterval, excludeTypeTooLongSinceLastFrameDiffReceived) {
|
|
||||||
if (this.hasBattleStopped) return null;
|
|
||||||
var shouldComplain = false;
|
|
||||||
var ret = this._networkComplaintPrefix;
|
|
||||||
if (true != excludeTypeConstantALittleLongFrameDiffReceivedInterval && this._consecutiveALittleLongFrameDiffReceivedIntervalCountThreshold <= this._consecutiveALittleLongFrameDiffReceivedIntervalCount) {
|
|
||||||
this._consecutiveALittleLongFrameDiffReceivedIntervalCount = 0;
|
|
||||||
ret += "\nConstantly having a little long recv interval.\n";
|
|
||||||
shouldComplain = true;
|
|
||||||
}
|
|
||||||
if (true != excludeTypeTooLongSinceLastFrameDiffReceived && this._tooLongSinceLastFrameDiffReceived()) {
|
|
||||||
ret += "\nToo long since last received frameDiff.\n";
|
|
||||||
shouldComplain = true;
|
|
||||||
}
|
|
||||||
return (shouldComplain ? ret : null);
|
|
||||||
};
|
|
||||||
|
|
||||||
this.hasBattleStopped = false;
|
|
||||||
this.onBattleStopped = function() {
|
|
||||||
this.hasBattleStopped = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
this.isClientSessionConnected = function() {
|
|
||||||
if (!window.game) return false;
|
|
||||||
if (!window.game.clientSession) return false;
|
|
||||||
return window.game.clientSession.connected;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
window.NetworkDoctor = NetworkDoctor;
|
|
@@ -198,3 +198,6 @@ window.getOrCreateAnimationClipForGid = function(gid, tiledMapInfo, tilesElListU
|
|||||||
animationClip: animClip,
|
animationClip: animClip,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Node.js, this is a workaround to avoid accessing the non-existent "TextDecoder class" from "jsexport.js".
|
||||||
|
window.fs = function() {};
|
||||||
|
7
frontend/assets/resources/animation/Explosion.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.1",
|
||||||
|
"uuid": "c7c2ac6e-f1ea-4233-b6a4-aa5b96b61e17",
|
||||||
|
"isSubpackage": false,
|
||||||
|
"subpackageName": "",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "Fireball1Explosion",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.26666666666666666,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "f4ad4f9f-4890-450b-9334-68fe6b903893"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.05,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "c6a5994f-251d-4191-a550-dfef979bab59"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.11666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "417e58d9-e364-47f7-9364-f31ad3452adc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.15,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "8b566f26-b34d-4da6-bdaa-078358a5b685"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.2,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "6ec5f75d-307e-4292-b667-cbbb5a52c2f6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.25,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "d89977f1-d927-4a08-9591-9feb1daf68c8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "7941215a-2b8c-4798-954b-4f1b16d5f6f5",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "MeleeExplosion1",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.16666666666666666,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "ab4866e8-ce52-4bc1-be19-b03687acf0d6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.016666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "67cc8a51-0ebe-49db-a941-7aabc5655ecf"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.03333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "367592d0-3566-4b6a-8707-01d6a8dbe34a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.05,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "cc336b1e-b5d8-4a89-96fc-7ada0e232389"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.06666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "a457cc63-08bd-4cfa-b84a-7287d0343ecf"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.08333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "89697d35-cde3-4392-a231-db91d4ede29b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.1,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "3815bf7a-0a48-40e0-b791-0a0be9ec0da6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.11666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "20e691ee-a0c0-4710-8981-8dee1911e819"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.13333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "94e678c5-0780-4f2b-bf3b-86c6c0a75c23"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.15,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "af4f9c62-4c7e-43a4-b9b3-dd3effbbbafb"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "954a2924-89df-4df4-93fc-36d2b22e7619",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "MeleeExplosion2",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.26666666666666666,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "89e54317-7835-4d4c-9c04-579da8b33c54"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.016666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "2a186e00-a0c5-4c8a-b0ab-c84d56dcee7c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.05,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "083168e3-6ccc-4c5b-a800-2554bffc67d4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.08333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "d4b12ec9-6f04-493c-91e5-22b1a212262a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.13333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "13038788-b0f9-4714-960b-c98619a0d0ce"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.16666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "94c21ed7-94a2-47a4-9537-fe5d9c51d7b0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.2,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "d5340298-923c-4bd7-9fd7-7a2e029a2b44"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.21666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "c4b145c0-0145-4e09-8559-9ef508d95be8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.23333333333333334,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "79398d4d-305e-4987-b199-d9d9649cf490"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.25,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "c032eb65-fdf3-41e6-b868-d95df34168df"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "5bd304eb-c8ba-426f-a9ab-5698ac62de85",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -0,0 +1,79 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "MeleeExplosion3",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.26666666666666666,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "20d9ce6b-d9ab-4402-8c59-770ad0adf570"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.016666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "0654601f-6788-4a2c-aed4-8dfbe1c5fdd0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.03333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "0913e11a-c796-4b58-94cf-f70b3869deff"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.06666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "d6b58622-2cc3-4ee6-a34f-1a18deb73700"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.08333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "b83c6261-b86f-4323-ad11-7375cac02a2b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.11666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "b458c047-b7b5-4476-996e-d4c1ca85ef9c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.15,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "3971256a-8120-448e-8adf-de8d67dedfd3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.18333333333333332,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "0e548d92-36c8-4795-b3dc-2bc2cfcd7170"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.21666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "25f94245-87b0-4954-abab-c817c80fed37"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.25,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "20d9ce6b-d9ab-4402-8c59-770ad0adf570"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "5054633c-a588-4506-b4ac-eef29b1d8511",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -0,0 +1,476 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>frames</key>
|
||||||
|
<dict>
|
||||||
|
<key>Explosion1_1.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{0,506},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion1_10.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{0,577},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion1_2.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{67,506},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion1_3.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{67,577},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion1_4.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{134,506},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion1_5.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{134,577},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion1_6.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{355,503},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion1_7.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{426,503},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion1_8.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{355,570},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion1_9.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{71,67}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{422,570},{71,67}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_1.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{462,0},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_10.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{462,88},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_2.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{462,176},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_3.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{462,264},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_4.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{0,304},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_5.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{88,304},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_6.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{176,304},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_7.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{264,304},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_8.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{352,304},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion2_9.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{88,45}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{456,352},{88,45}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_1.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{0,0},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_10.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{154,0},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_2.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{308,0},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_3.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{0,152},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_4.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{154,152},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_5.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{308,152},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_6.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{0,352},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_7.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{152,349},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_8.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{201,503},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Explosion3_9.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{154,152}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{304,349},{154,152}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
<key>metadata</key>
|
||||||
|
<dict>
|
||||||
|
<key>format</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>pixelFormat</key>
|
||||||
|
<string>RGBA8888</string>
|
||||||
|
<key>premultiplyAlpha</key>
|
||||||
|
<false/>
|
||||||
|
<key>realTextureFileName</key>
|
||||||
|
<string>MeleeExplosions.png</string>
|
||||||
|
<key>size</key>
|
||||||
|
<string>{507,655}</string>
|
||||||
|
<key>smartupdate</key>
|
||||||
|
<string>$TexturePacker:SmartUpdate:6c1498ee6f30bdad4abeb6a9f6af8367:4c81e1a1720f2ad3535ac93f1b42991f:d9b184ec81b83b14db5cf31d298727df$</string>
|
||||||
|
<key>textureFileName</key>
|
||||||
|
<string>MeleeExplosions.png</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
@@ -0,0 +1,672 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.4",
|
||||||
|
"uuid": "1c4c1dcb-54af-485b-9119-abd6d6d84526",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"size": {
|
||||||
|
"width": 507,
|
||||||
|
"height": 655
|
||||||
|
},
|
||||||
|
"type": "Texture Packer",
|
||||||
|
"subMetas": {
|
||||||
|
"Explosion1_1.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "ab4866e8-ce52-4bc1-be19-b03687acf0d6",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 506,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion1_10.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "af4f9c62-4c7e-43a4-b9b3-dd3effbbbafb",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 577,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion1_2.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "67cc8a51-0ebe-49db-a941-7aabc5655ecf",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 67,
|
||||||
|
"trimY": 506,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion1_3.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "367592d0-3566-4b6a-8707-01d6a8dbe34a",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 67,
|
||||||
|
"trimY": 577,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion1_4.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "cc336b1e-b5d8-4a89-96fc-7ada0e232389",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 134,
|
||||||
|
"trimY": 506,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion1_5.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "a457cc63-08bd-4cfa-b84a-7287d0343ecf",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 134,
|
||||||
|
"trimY": 577,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion1_6.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "89697d35-cde3-4392-a231-db91d4ede29b",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 355,
|
||||||
|
"trimY": 503,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion1_7.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "3815bf7a-0a48-40e0-b791-0a0be9ec0da6",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 426,
|
||||||
|
"trimY": 503,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion1_8.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "20e691ee-a0c0-4710-8981-8dee1911e819",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 355,
|
||||||
|
"trimY": 570,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion1_9.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "94e678c5-0780-4f2b-bf3b-86c6c0a75c23",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 422,
|
||||||
|
"trimY": 570,
|
||||||
|
"width": 71,
|
||||||
|
"height": 67,
|
||||||
|
"rawWidth": 71,
|
||||||
|
"rawHeight": 67,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_1.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "89e54317-7835-4d4c-9c04-579da8b33c54",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 462,
|
||||||
|
"trimY": 0,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_10.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "c032eb65-fdf3-41e6-b868-d95df34168df",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 462,
|
||||||
|
"trimY": 88,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_2.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "2a186e00-a0c5-4c8a-b0ab-c84d56dcee7c",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 462,
|
||||||
|
"trimY": 176,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_3.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "083168e3-6ccc-4c5b-a800-2554bffc67d4",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 462,
|
||||||
|
"trimY": 264,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_4.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "d4b12ec9-6f04-493c-91e5-22b1a212262a",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 304,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_5.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "13038788-b0f9-4714-960b-c98619a0d0ce",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 88,
|
||||||
|
"trimY": 304,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_6.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "94c21ed7-94a2-47a4-9537-fe5d9c51d7b0",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 176,
|
||||||
|
"trimY": 304,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_7.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "d5340298-923c-4bd7-9fd7-7a2e029a2b44",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 264,
|
||||||
|
"trimY": 304,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_8.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "c4b145c0-0145-4e09-8559-9ef508d95be8",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 352,
|
||||||
|
"trimY": 304,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion2_9.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "79398d4d-305e-4987-b199-d9d9649cf490",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 456,
|
||||||
|
"trimY": 352,
|
||||||
|
"width": 88,
|
||||||
|
"height": 45,
|
||||||
|
"rawWidth": 88,
|
||||||
|
"rawHeight": 45,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_1.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "84e28787-c6cb-435b-8f59-20d9afe6bf3a",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 0,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_10.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "20d9ce6b-d9ab-4402-8c59-770ad0adf570",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 154,
|
||||||
|
"trimY": 0,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_2.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "0654601f-6788-4a2c-aed4-8dfbe1c5fdd0",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 308,
|
||||||
|
"trimY": 0,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_3.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "0913e11a-c796-4b58-94cf-f70b3869deff",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 152,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_4.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "d6b58622-2cc3-4ee6-a34f-1a18deb73700",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 154,
|
||||||
|
"trimY": 152,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_5.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "b83c6261-b86f-4323-ad11-7375cac02a2b",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 308,
|
||||||
|
"trimY": 152,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_6.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "b458c047-b7b5-4476-996e-d4c1ca85ef9c",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 0,
|
||||||
|
"trimY": 352,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_7.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "3971256a-8120-448e-8adf-de8d67dedfd3",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 152,
|
||||||
|
"trimY": 349,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_8.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "0e548d92-36c8-4795-b3dc-2bc2cfcd7170",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": false,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 201,
|
||||||
|
"trimY": 503,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
},
|
||||||
|
"Explosion3_9.png": {
|
||||||
|
"ver": "1.0.4",
|
||||||
|
"uuid": "25f94245-87b0-4954-abab-c817c80fed37",
|
||||||
|
"rawTextureUuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"trimType": "auto",
|
||||||
|
"trimThreshold": 1,
|
||||||
|
"rotated": true,
|
||||||
|
"offsetX": 0,
|
||||||
|
"offsetY": 0,
|
||||||
|
"trimX": 304,
|
||||||
|
"trimY": 349,
|
||||||
|
"width": 154,
|
||||||
|
"height": 152,
|
||||||
|
"rawWidth": 154,
|
||||||
|
"rawHeight": 152,
|
||||||
|
"borderTop": 0,
|
||||||
|
"borderBottom": 0,
|
||||||
|
"borderLeft": 0,
|
||||||
|
"borderRight": 0,
|
||||||
|
"spriteType": "normal",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.3.3",
|
||||||
|
"uuid": "b11569aa-2e43-4084-a3e5-42eec243c4eb",
|
||||||
|
"type": "raw",
|
||||||
|
"wrapMode": "clamp",
|
||||||
|
"filterMode": "bilinear",
|
||||||
|
"premultiplyAlpha": false,
|
||||||
|
"genMipmaps": false,
|
||||||
|
"packable": true,
|
||||||
|
"platformSettings": {},
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
7
frontend/assets/resources/animation/Fireball.meta
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.1",
|
||||||
|
"uuid": "b07a911d-2d61-486d-9edc-1b3ba53c9911",
|
||||||
|
"isSubpackage": false,
|
||||||
|
"subpackageName": "",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
145
frontend/assets/resources/animation/Fireball/Fireball1.anim
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "Fireball1",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.35,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 2,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "dbe67025-9878-4e13-8f3d-81e04734810a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.016666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "e92702d5-d5fd-49e6-ab6b-2296b43fa6d6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.03333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "e1a89340-0b92-4e6b-93f2-e983302d70ce"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.05,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "b0bb4a7a-4ae3-48fc-9913-3b6d1d36c56f"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.06666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "b44d585b-8e18-4767-b263-ed3a53cd3250"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.08333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "a87a9ea8-2d84-4a3b-83e3-a4d7b8ac96b8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.1,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "a1604f9d-c0ea-4f92-b09b-3608245bda8e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.11666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "4372818f-1e44-4180-a0ce-4a34cee4fc5b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.13333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "dbe67025-9878-4e13-8f3d-81e04734810a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.15,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "5d867617-7f50-4fa8-804d-ce28c47ea407"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.16666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "824c9bee-42b7-4a94-86f8-6356f11aee16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.18333333333333332,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "6389164e-93bb-4d4d-9740-5e2d5cdb1029"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.2,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "d184a083-6043-4ca6-bd14-8db1b6be1d2e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.21666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "361b1722-e362-46e5-939e-e2d1666df374"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.23333333333333334,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "662fbe4f-a1f4-46f7-83e4-eafd021432da"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.25,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "5e509118-a44b-4e7f-9686-c6bb0b30f0b0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.26666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "bc1110c7-4423-4c43-965c-0cb3dd8e31ff"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.2833333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "33cc8d11-1568-47a7-b4f1-cef4888302e5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.3,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "83bb5dd3-510c-4fce-b393-840f14efb8cd"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.31666666666666665,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "1db706f5-366a-421c-843f-a4bb016f80ec"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.3333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "41a4f35a-01c0-4a22-b5cc-7bfe25ed4501"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "ba12416b-eec3-4260-8402-7fc25b125624",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -18,61 +18,43 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.06666666666666667,
|
"frame": 0.05,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "dd9a00aa-ddbc-4b01-a7cb-3c43c3a655b6"
|
"__uuid__": "dd9a00aa-ddbc-4b01-a7cb-3c43c3a655b6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.11666666666666667,
|
"frame": 0.08333333333333333,
|
||||||
"value": {
|
|
||||||
"__uuid__": "f66e83bd-1afc-4957-bb16-488d70566ed1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"frame": 0.16666666666666666,
|
|
||||||
"value": {
|
|
||||||
"__uuid__": "bd682c41-dc62-49ff-a96a-18b33e50a6de"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"frame": 0.23333333333333334,
|
|
||||||
"value": {
|
|
||||||
"__uuid__": "94ccab85-e32f-4e13-b0e5-72c798f78ad1"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"frame": 0.3,
|
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "e80d3a01-5048-42b7-a280-cb6aa01602c2"
|
"__uuid__": "e80d3a01-5048-42b7-a280-cb6aa01602c2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.36666666666666664,
|
"frame": 0.11666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "d899088c-be62-47b4-9ebf-0a89a2261565"
|
"__uuid__": "d899088c-be62-47b4-9ebf-0a89a2261565"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.4166666666666667,
|
"frame": 0.15,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "5b1e5aa7-fd82-47ae-a5b2-6d4983d848ed"
|
"__uuid__": "5b1e5aa7-fd82-47ae-a5b2-6d4983d848ed"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.48333333333333334,
|
"frame": 0.18333333333333332,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "c2945988-b4bb-4583-a5ef-2fa02b23a347"
|
"__uuid__": "c2945988-b4bb-4583-a5ef-2fa02b23a347"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.5666666666666667,
|
"frame": 0.23333333333333334,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "070ea1e3-9c07-4735-8b94-515ef70216ad"
|
"__uuid__": "070ea1e3-9c07-4735-8b94-515ef70216ad"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.6666666666666666,
|
"frame": 0.2833333333333333,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "3b8bc5c0-26df-4218-b7dc-134a36080a35"
|
"__uuid__": "3b8bc5c0-26df-4218-b7dc-134a36080a35"
|
||||||
}
|
}
|
||||||
|
61
frontend/assets/resources/animation/KnifeGirl/Dashing.anim
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "Dashing",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.35,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "cf396dac-50c9-4389-90c0-55f49fd3276d"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.05,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "b9e4b5d5-c296-48c8-aa60-d22db0e5a632"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.11666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "e456c710-69f5-4dcc-9f5d-dd486a9198a1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.16666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "ec6df76f-0004-4216-9b83-449487fe0cda"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.23333333333333334,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "26032d0f-845c-4b96-89a6-d88113ed7827"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.2833333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "e3e0169c-3c56-4206-a20e-35e4d0471873"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.3333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "80b98036-c5de-492b-b0e8-f1703f3a7d20"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "38b2c892-347b-4009-93f8-65b2ab1614f0",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -15,9 +15,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{112,128}</string>
|
<string>{112,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{824,544},{112,128}}</string>
|
<string>{{384,989},{112,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk1_1.png</key>
|
<key>Atk1_1.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -30,9 +30,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{112,128}</string>
|
<string>{112,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{0,1200},{112,128}}</string>
|
<string>{{256,990},{112,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk1_10.png</key>
|
<key>Atk1_10.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -90,9 +90,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{112,128}</string>
|
<string>{112,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{0,964},{112,128}}</string>
|
<string>{{128,1082},{112,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk1_4.png</key>
|
<key>Atk1_4.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -105,9 +105,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{112,128}</string>
|
<string>{112,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{112,964},{112,128}}</string>
|
<string>{{0,1188},{112,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk1_5.png</key>
|
<key>Atk1_5.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,128}</string>
|
<string>{96,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{840,288},{96,128}}</string>
|
<string>{{512,643},{96,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,128}</string>
|
<string>{96,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{840,416},{96,128}}</string>
|
<string>{{512,771},{96,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -165,7 +165,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,128}</string>
|
<string>{80,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{936,384},{80,128}}</string>
|
<string>{{937,384},{80,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -180,7 +180,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,128}</string>
|
<string>{80,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{936,512},{80,128}}</string>
|
<string>{{528,515},{80,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,128}</string>
|
<string>{80,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{936,640},{80,128}}</string>
|
<string>{{936,512},{80,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -210,7 +210,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,128}</string>
|
<string>{96,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{582,531},{96,128}}</string>
|
<string>{{512,899},{96,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -225,7 +225,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{128,112}</string>
|
<string>{128,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{326,871},{128,112}}</string>
|
<string>{{0,1076},{128,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -240,7 +240,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,96}</string>
|
<string>{96,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{696,1200},{96,96}}</string>
|
<string>{{688,1357},{96,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -255,7 +255,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,112}</string>
|
<string>{96,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{416,983},{96,112}}</string>
|
<string>{{240,1360},{96,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -270,7 +270,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,112}</string>
|
<string>{96,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{656,1092},{96,112}}</string>
|
<string>{{352,1358},{96,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -285,9 +285,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,112}</string>
|
<string>{96,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{528,1113},{96,112}}</string>
|
<string>{{920,1072},{96,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk2_5.png</key>
|
<key>Atk2_5.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -300,9 +300,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,112}</string>
|
<string>{96,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{392,1207},{96,112}}</string>
|
<string>{{914,1184},{96,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk2_6.png</key>
|
<key>Atk2_6.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -330,7 +330,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{128,112}</string>
|
<string>{128,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{454,871},{128,112}}</string>
|
<string>{{806,631},{128,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -525,7 +525,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,128}</string>
|
<string>{96,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{582,659},{96,128}}</string>
|
<string>{{512,1027},{96,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -540,7 +540,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{112,112}</string>
|
<string>{112,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{240,1081},{112,112}}</string>
|
<string>{{802,1149},{112,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -555,9 +555,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,112}</string>
|
<string>{96,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{504,1209},{96,112}}</string>
|
<string>{{800,1261},{96,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atked1_3.png</key>
|
<key>Atked1_3.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -570,7 +570,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{128,112}</string>
|
<string>{128,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{678,980},{128,112}}</string>
|
<string>{{806,743},{128,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -634,37 +634,112 @@
|
|||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>Dashing_1.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{806,1037},{114,112}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>Dashing_2.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{384,1213},{114,112}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Dashing_3.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{464,1327},{114,112}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Dashing_4.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{496,1213},{114,112}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Dashing_5.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{464,1327},{114,112}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Dashing_6.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{576,1327},{114,112}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>Dashing_7.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{114,112}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{688,1043},{114,112}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
<key>GetUp1_1.png</key>
|
<key>GetUp1_1.png</key>
|
||||||
<dict>
|
|
||||||
<key>aliases</key>
|
|
||||||
<array/>
|
|
||||||
<key>spriteOffset</key>
|
|
||||||
<string>{0,0}</string>
|
|
||||||
<key>spriteSize</key>
|
|
||||||
<string>{128,118}</string>
|
|
||||||
<key>spriteSourceSize</key>
|
|
||||||
<string>{128,118}</string>
|
|
||||||
<key>textureRect</key>
|
|
||||||
<string>{{806,791},{128,118}}</string>
|
|
||||||
<key>textureRotated</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
<key>GetUp1_2.png</key>
|
|
||||||
<dict>
|
|
||||||
<key>aliases</key>
|
|
||||||
<array/>
|
|
||||||
<key>spriteOffset</key>
|
|
||||||
<string>{0,0}</string>
|
|
||||||
<key>spriteSize</key>
|
|
||||||
<string>{128,118}</string>
|
|
||||||
<key>spriteSourceSize</key>
|
|
||||||
<string>{128,118}</string>
|
|
||||||
<key>textureRect</key>
|
|
||||||
<string>{{0,846},{128,118}}</string>
|
|
||||||
<key>textureRotated</key>
|
|
||||||
<false/>
|
|
||||||
</dict>
|
|
||||||
<key>GetUp1_3.png</key>
|
|
||||||
<dict>
|
<dict>
|
||||||
<key>aliases</key>
|
<key>aliases</key>
|
||||||
<array/>
|
<array/>
|
||||||
@@ -679,6 +754,36 @@
|
|||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>GetUp1_2.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{128,118}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{128,118}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{0,958},{128,118}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>GetUp1_3.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{128,118}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{128,118}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{384,753},{128,118}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
<key>GetUp1_4.png</key>
|
<key>GetUp1_4.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>aliases</key>
|
<key>aliases</key>
|
||||||
@@ -690,7 +795,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{128,118}</string>
|
<string>{128,118}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{326,753},{128,118}}</string>
|
<string>{{678,631},{128,118}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -705,7 +810,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{128,118}</string>
|
<string>{128,118}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{454,753},{128,118}}</string>
|
<string>{{384,871},{128,118}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -720,7 +825,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{128,118}</string>
|
<string>{128,118}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{678,862},{128,118}}</string>
|
<string>{{256,872},{128,118}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -735,7 +840,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{128,118}</string>
|
<string>{128,118}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{806,909},{128,118}}</string>
|
<string>{{128,964},{128,118}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -750,7 +855,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{256,489},{70,128}}</string>
|
<string>{{608,531},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -765,7 +870,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{256,617},{70,128}}</string>
|
<string>{{608,659},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -780,7 +885,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{256,745},{70,128}}</string>
|
<string>{{608,787},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -795,7 +900,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{256,873},{70,128}}</string>
|
<string>{{608,915},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -810,9 +915,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{112,1200},{70,128}}</string>
|
<string>{{128,1290},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Idle1_14.png</key>
|
<key>Idle1_14.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -825,9 +930,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{182,1200},{70,128}}</string>
|
<string>{{0,1300},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Idle1_15.png</key>
|
<key>Idle1_15.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -840,9 +945,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{252,1200},{70,128}}</string>
|
<string>{{0,1370},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Idle1_2.png</key>
|
<key>Idle1_2.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -855,9 +960,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{252,1200},{70,128}}</string>
|
<string>{{0,1370},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Idle1_3.png</key>
|
<key>Idle1_3.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -870,9 +975,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{182,1200},{70,128}}</string>
|
<string>{{0,1300},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Idle1_4.png</key>
|
<key>Idle1_4.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -885,9 +990,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{112,1200},{70,128}}</string>
|
<string>{{128,1290},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Idle1_5.png</key>
|
<key>Idle1_5.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -900,7 +1005,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{256,873},{70,128}}</string>
|
<string>{{608,915},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -915,7 +1020,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{256,745},{70,128}}</string>
|
<string>{{608,787},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -930,7 +1035,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{256,617},{70,128}}</string>
|
<string>{{608,659},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -945,9 +1050,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{322,1200},{70,128}}</string>
|
<string>{{806,967},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Idle1_9.png</key>
|
<key>Idle1_9.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -960,7 +1065,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{70,128}</string>
|
<string>{70,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{528,1043},{70,128}}</string>
|
<string>{{678,973},{70,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -975,7 +1080,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{112,96}</string>
|
<string>{112,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{128,1092},{112,96}}</string>
|
<string>{{128,1360},{112,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1005,7 +1110,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{144,112}</string>
|
<string>{144,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{680,512},{144,112}}</string>
|
<string>{{0,489},{144,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1020,7 +1125,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{128,112}</string>
|
<string>{128,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{806,1027},{128,112}}</string>
|
<string>{{678,749},{128,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1035,7 +1140,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,96}</string>
|
<string>{96,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{792,1139},{96,96}}</string>
|
<string>{{784,1357},{96,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1050,7 +1155,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,96}</string>
|
<string>{80,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{934,1104},{80,96}}</string>
|
<string>{{934,976},{80,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1065,7 +1170,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{112,112}</string>
|
<string>{112,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{352,1081},{112,112}}</string>
|
<string>{{688,1155},{112,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1080,7 +1185,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{128,96}</string>
|
<string>{128,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{0,1092},{128,96}}</string>
|
<string>{{256,1102},{128,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1095,7 +1200,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,112}</string>
|
<string>{80,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{934,768},{80,112}}</string>
|
<string>{{934,640},{80,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1110,7 +1215,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,112}</string>
|
<string>{80,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{934,880},{80,112}}</string>
|
<string>{{934,752},{80,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1125,9 +1230,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{64,128}</string>
|
<string>{64,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{464,1079},{64,128}}</string>
|
<string>{{256,1294},{64,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirIdle1_3.png</key>
|
<key>InAirIdle1_3.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1140,7 +1245,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,112}</string>
|
<string>{80,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{934,992},{80,112}}</string>
|
<string>{{934,864},{80,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1155,9 +1260,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,96}</string>
|
<string>{80,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{224,1001},{80,96}}</string>
|
<string>{{608,1043},{80,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirIdle1_5.png</key>
|
<key>InAirIdle1_5.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1170,9 +1275,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,96}</string>
|
<string>{80,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{320,1001},{80,96}}</string>
|
<string>{{608,1139},{80,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirIdle1_6.png</key>
|
<key>InAirIdle1_6.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1185,9 +1290,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,96}</string>
|
<string>{80,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{792,1235},{80,96}}</string>
|
<string>{{688,1267},{80,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirIdle1_7.png</key>
|
<key>InAirIdle1_7.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1200,9 +1305,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,112}</string>
|
<string>{96,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{600,1209},{96,112}}</string>
|
<string>{{912,1296},{96,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirIdle1_8.png</key>
|
<key>InAirIdle1_8.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1215,9 +1320,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,128}</string>
|
<string>{96,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{582,787},{96,128}}</string>
|
<string>{{128,1194},{96,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirIdle1_9.png</key>
|
<key>InAirIdle1_9.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1230,9 +1335,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,128}</string>
|
<string>{96,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{582,915},{96,128}}</string>
|
<string>{{256,1198},{96,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>LayDown1_1.png</key>
|
<key>LayDown1_1.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1264,6 +1369,96 @@
|
|||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>OnWall1_1.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{112,97}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{112,97}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{840,288},{112,97}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>OnWall1_2.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{112,97}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{112,97}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{840,400},{112,97}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>OnWall1_3.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{112,97}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{112,97}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{840,400},{112,97}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>TurnAround1_1.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{112,128}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{112,128}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{806,855},{112,128}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>TurnAround1_2.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{112,128}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{112,128}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{678,861},{112,128}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>TurnAround1_3.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{112,128}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{112,128}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{384,1101},{112,128}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
<key>Walking_1.png</key>
|
<key>Walking_1.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>aliases</key>
|
<key>aliases</key>
|
||||||
@@ -1275,7 +1470,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{0,489},{119,128}}</string>
|
<string>{{144,489},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1290,7 +1485,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{128,489},{119,128}}</string>
|
<string>{{0,601},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1305,7 +1500,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{0,608},{119,128}}</string>
|
<string>{{272,515},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1335,7 +1530,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{326,515},{119,128}}</string>
|
<string>{{0,720},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1350,7 +1545,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{454,515},{119,128}}</string>
|
<string>{{400,515},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1365,7 +1560,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{678,624},{119,128}}</string>
|
<string>{{256,634},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1380,7 +1575,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{806,672},{119,128}}</string>
|
<string>{{128,727},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1395,7 +1590,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{0,727},{119,128}}</string>
|
<string>{{0,839},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1410,7 +1605,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{128,727},{119,128}}</string>
|
<string>{{384,634},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1425,7 +1620,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{326,634},{119,128}}</string>
|
<string>{{680,512},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1440,7 +1635,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{454,634},{119,128}}</string>
|
<string>{{808,512},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1455,7 +1650,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{119,128}</string>
|
<string>{119,128}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{678,743},{119,128}}</string>
|
<string>{{256,753},{119,128}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1471,9 +1666,9 @@
|
|||||||
<key>realTextureFileName</key>
|
<key>realTextureFileName</key>
|
||||||
<string>KnifeGirl.png</string>
|
<string>KnifeGirl.png</string>
|
||||||
<key>size</key>
|
<key>size</key>
|
||||||
<string>{1020,1331}</string>
|
<string>{1024,1456}</string>
|
||||||
<key>smartupdate</key>
|
<key>smartupdate</key>
|
||||||
<string>$TexturePacker:SmartUpdate:9514b6b35473e14baf98f68515bcb817:1aae9dd4a8024ce783fdab093a39672a:1ae107e0c6667a1ecb5ed98687517e0e$</string>
|
<string>$TexturePacker:SmartUpdate:8fd7507b5e24a1de6da5e4a6c568fcd3:d861e924a13180a640774a9c85662e57:1ae107e0c6667a1ecb5ed98687517e0e$</string>
|
||||||
<key>textureFileName</key>
|
<key>textureFileName</key>
|
||||||
<string>KnifeGirl.png</string>
|
<string>KnifeGirl.png</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 119 KiB |
37
frontend/assets/resources/animation/KnifeGirl/OnWall.anim
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "OnWall",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.26666666666666666,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "c18886db-8116-4602-84f2-51652a90269a"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.13333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "0d81cbf0-dff8-4672-99b3-2ec8055c6931"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.25,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "a183e740-3c2d-4890-8430-39a00f55f446"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "411f964a-4dd8-424c-b2e2-d92b10474ce2",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "TurnAround1",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.15,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "28ee1f29-e538-4d36-bb5c-275f9e3b392b"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.03333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "211a73bb-31d7-4e6c-901e-f6939d9214e0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.08333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "048c41dc-fc00-4bc4-8041-6003e7c2b6e4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.13333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "9435195e-4560-495e-b1ae-083c0c87e8a0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "e906322d-a08b-4477-a2e9-98acd42fa034",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
"_name": "Walking",
|
"_name": "Walking",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_native": "",
|
"_native": "",
|
||||||
"_duration": 1.5166666666666666,
|
"_duration": 0.6333333333333333,
|
||||||
"sample": 60,
|
"sample": 60,
|
||||||
"speed": 1.2,
|
"speed": 1.2,
|
||||||
"wrapMode": 2,
|
"wrapMode": 2,
|
||||||
@@ -13,78 +13,78 @@
|
|||||||
"spriteFrame": [
|
"spriteFrame": [
|
||||||
{
|
{
|
||||||
"frame": 0,
|
"frame": 0,
|
||||||
"value": {
|
|
||||||
"__uuid__": "c3b14ecc-a6d9-4cb3-8637-ca7b407a0f5c"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"frame": 0.08333333333333333,
|
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "9435195e-4560-495e-b1ae-083c0c87e8a0"
|
"__uuid__": "9435195e-4560-495e-b1ae-083c0c87e8a0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.18333333333333332,
|
"frame": 0.06666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "ec048360-7a17-4f22-ba52-eb86ec1acae8"
|
"__uuid__": "ec048360-7a17-4f22-ba52-eb86ec1acae8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.2833333333333333,
|
"frame": 0.11666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "82bb81e3-667c-4280-8710-211f4904ef2f"
|
"__uuid__": "82bb81e3-667c-4280-8710-211f4904ef2f"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.4,
|
"frame": 0.16666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "c3b14ecc-a6d9-4cb3-8637-ca7b407a0f5c"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.21666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "f958fb7f-ef5a-4918-81f3-564004572f45"
|
"__uuid__": "f958fb7f-ef5a-4918-81f3-564004572f45"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.5333333333333333,
|
"frame": 0.26666666666666666,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "8a0ecf92-db26-4206-9a80-20e749055def"
|
"__uuid__": "8a0ecf92-db26-4206-9a80-20e749055def"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.65,
|
"frame": 0.31666666666666665,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "942f2e02-a700-4fbf-877e-08c93e4d4010"
|
"__uuid__": "942f2e02-a700-4fbf-877e-08c93e4d4010"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.7666666666666667,
|
"frame": 0.36666666666666664,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "30546064-1a11-499e-8523-a82c83951c73"
|
"__uuid__": "30546064-1a11-499e-8523-a82c83951c73"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.9,
|
"frame": 0.4166666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "515bb75f-7a1f-4500-8aa9-c895915ce19f"
|
"__uuid__": "515bb75f-7a1f-4500-8aa9-c895915ce19f"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 1.0333333333333334,
|
"frame": 0.4666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "9100da6b-7582-4afb-9698-3d67d3b2012d"
|
"__uuid__": "9100da6b-7582-4afb-9698-3d67d3b2012d"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 1.2166666666666666,
|
"frame": 0.5166666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "1257f72d-0cb3-4750-ae70-13c2d8eb2269"
|
"__uuid__": "1257f72d-0cb3-4750-ae70-13c2d8eb2269"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 1.3833333333333333,
|
"frame": 0.5666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "1d34b6db-27ba-4e26-864d-0f00d501765e"
|
"__uuid__": "1d34b6db-27ba-4e26-864d-0f00d501765e"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 1.5,
|
"frame": 0.6166666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "c317a75a-52c0-4c38-9300-a064cbf4efb3"
|
"__uuid__": "c317a75a-52c0-4c38-9300-a064cbf4efb3"
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
"_name": "Atk3",
|
"_name": "Atk3",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_native": "",
|
"_native": "",
|
||||||
"_duration": 0.6333333333333333,
|
"_duration": 0.5333333333333333,
|
||||||
"sample": 60,
|
"sample": 60,
|
||||||
"speed": 1,
|
"speed": 1,
|
||||||
"wrapMode": 1,
|
"wrapMode": 1,
|
||||||
@@ -13,84 +13,72 @@
|
|||||||
"spriteFrame": [
|
"spriteFrame": [
|
||||||
{
|
{
|
||||||
"frame": 0,
|
"frame": 0,
|
||||||
"value": {
|
|
||||||
"__uuid__": "318745eb-06b1-4e7f-88d1-e23e02d99e67"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"frame": 0.06666666666666667,
|
|
||||||
"value": {
|
|
||||||
"__uuid__": "a64b6f59-fa72-4f5d-89dc-81a469244ea5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"frame": 0.11666666666666667,
|
|
||||||
"value": {
|
|
||||||
"__uuid__": "f800d4a1-2396-4aa5-a578-11481db1d8bf"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"frame": 0.16666666666666666,
|
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "d97f6a5f-8e63-40d7-bd14-9dc71e15e5db"
|
"__uuid__": "d97f6a5f-8e63-40d7-bd14-9dc71e15e5db"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.23333333333333334,
|
"frame": 0.03333333333333333,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "196bcbf9-e89f-4b26-b736-73e2fa787e50"
|
"__uuid__": "196bcbf9-e89f-4b26-b736-73e2fa787e50"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.3,
|
"frame": 0.08333333333333333,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "3229e023-e63d-4a4e-af72-2b1409ea43c5"
|
"__uuid__": "3229e023-e63d-4a4e-af72-2b1409ea43c5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.36666666666666664,
|
"frame": 0.11666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "e2d6e8b8-b468-4edb-b8c3-860bd85ebeae"
|
"__uuid__": "e2d6e8b8-b468-4edb-b8c3-860bd85ebeae"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.4166666666666667,
|
"frame": 0.16666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "318745eb-06b1-4e7f-88d1-e23e02d99e67"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.21666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "bba6f088-0e1f-4a12-9872-41670be1152a"
|
"__uuid__": "bba6f088-0e1f-4a12-9872-41670be1152a"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.45,
|
"frame": 0.26666666666666666,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "2c5de5b2-9009-48fa-bef4-ae34cc94f876"
|
"__uuid__": "2c5de5b2-9009-48fa-bef4-ae34cc94f876"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.48333333333333334,
|
"frame": 0.31666666666666665,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "6f27b252-6eaf-4b4b-9c5a-46ba899e4845"
|
"__uuid__": "6f27b252-6eaf-4b4b-9c5a-46ba899e4845"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.5166666666666667,
|
"frame": 0.36666666666666664,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "4ebd5c60-efa6-4950-a4c8-74a7a8517333"
|
"__uuid__": "4ebd5c60-efa6-4950-a4c8-74a7a8517333"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.55,
|
"frame": 0.4166666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "a207290f-4556-4adb-8a11-e1d5ba342550"
|
"__uuid__": "a207290f-4556-4adb-8a11-e1d5ba342550"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.5833333333333334,
|
"frame": 0.4666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "e9d442d2-981d-437d-87c0-085162017de7"
|
"__uuid__": "e9d442d2-981d-437d-87c0-085162017de7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.6166666666666667,
|
"frame": 0.5166666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "9b4d5c8c-5ec0-4fd7-a45e-6b0bc8ff9119"
|
"__uuid__": "9b4d5c8c-5ec0-4fd7-a45e-6b0bc8ff9119"
|
||||||
}
|
}
|
||||||
|
85
frontend/assets/resources/animation/Monk/Atk5.anim
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "Atk5",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 1.0166666666666666,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "6aa88bb9-0427-496f-ae7d-dc06410e904e"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.08333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "cdc65f83-c526-48b6-8a96-758b098568fe"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.16666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "927636af-2d1d-4801-a546-857f5eeb256d"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.26666666666666666,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "2aeeb833-9151-4160-9775-9e08a376fd63"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.36666666666666664,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "2bd1de9e-30e5-4bc5-b6c3-5c286754b0b7"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.4666666666666667,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "15a6ebb3-289a-46fb-ac94-f6efa0d90510"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.5833333333333334,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "6ca922c0-cb62-4b1b-8773-79685a58bbd6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.7,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "d60ceb6f-3a45-47dd-8d3f-bcfe8c919d85"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.8,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "c313f6a1-e0fa-4321-8336-c32f471b2592"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.9,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "bb886d03-7f3e-45c8-acfd-393091f09adb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 1,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "1be255c3-f8c9-43ae-be68-2e500e7f1125"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
5
frontend/assets/resources/animation/Monk/Atk5.anim.meta
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "0abbd156-980e-475e-9994-3c958bd913fc",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -3,7 +3,7 @@
|
|||||||
"_name": "InAirIdle1ByJump",
|
"_name": "InAirIdle1ByJump",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_native": "",
|
"_native": "",
|
||||||
"_duration": 0.7833333333333333,
|
"_duration": 0.5833333333333334,
|
||||||
"sample": 60,
|
"sample": 60,
|
||||||
"speed": 1,
|
"speed": 1,
|
||||||
"wrapMode": 1,
|
"wrapMode": 1,
|
||||||
@@ -18,67 +18,67 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.05,
|
"frame": 0.03333333333333333,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "06d18871-0cb6-41eb-a484-5c6a4c04d5d5"
|
"__uuid__": "06d18871-0cb6-41eb-a484-5c6a4c04d5d5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.11666666666666667,
|
"frame": 0.06666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "f298ff82-ad9d-4945-ab19-14c3e3d54c95"
|
"__uuid__": "f298ff82-ad9d-4945-ab19-14c3e3d54c95"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.18333333333333332,
|
"frame": 0.11666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "bb5924a6-40cf-4e43-8c94-e51b27861656"
|
"__uuid__": "bb5924a6-40cf-4e43-8c94-e51b27861656"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.25,
|
"frame": 0.16666666666666666,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "fc4b5181-77af-44ec-836e-c14eec8d20c4"
|
"__uuid__": "fc4b5181-77af-44ec-836e-c14eec8d20c4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.3333333333333333,
|
"frame": 0.21666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "5ddd3db3-79b2-4f0c-bb76-2446801ff665"
|
"__uuid__": "5ddd3db3-79b2-4f0c-bb76-2446801ff665"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.4166666666666667,
|
"frame": 0.26666666666666666,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "032785ce-c911-479b-be1c-2e0899a586d0"
|
"__uuid__": "032785ce-c911-479b-be1c-2e0899a586d0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.48333333333333334,
|
"frame": 0.31666666666666665,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "d651269d-1c08-49f8-bc38-d301bf26b0e1"
|
"__uuid__": "d651269d-1c08-49f8-bc38-d301bf26b0e1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.5666666666666667,
|
"frame": 0.36666666666666664,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "e270563e-d98d-4a80-82db-837183053ae3"
|
"__uuid__": "e270563e-d98d-4a80-82db-837183053ae3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.6333333333333333,
|
"frame": 0.43333333333333335,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "aec31ef8-46dc-4f0e-9cba-18f6c96c5c33"
|
"__uuid__": "aec31ef8-46dc-4f0e-9cba-18f6c96c5c33"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.7,
|
"frame": 0.5,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "e64b3a8d-41a9-45f6-9aeb-9e49b6317080"
|
"__uuid__": "e64b3a8d-41a9-45f6-9aeb-9e49b6317080"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"frame": 0.7666666666666667,
|
"frame": 0.5666666666666667,
|
||||||
"value": {
|
"value": {
|
||||||
"__uuid__": "cf886091-24a9-4cfb-8cb9-e3db977035ab"
|
"__uuid__": "cf886091-24a9-4cfb-8cb9-e3db977035ab"
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 217 KiB After Width: | Height: | Size: 269 KiB |
43
frontend/assets/resources/animation/Monk/TurnAround1.anim
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "TurnAround1",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.15,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "ee5e05fa-b515-470f-bc3c-43544f02cb92"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.03333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "ffa521b6-118e-46e8-be1c-51cc54381ec8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.08333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "0b27d2c9-c5a3-4020-adbe-0297c1ba3aeb"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.13333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "a47f518e-62fb-4549-8897-4f2d387bd145"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "edd23b2f-1caa-4836-88a7-e4af1f26743e",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -15,7 +15,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{62,92}</string>
|
<string>{62,92}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1277,188},{62,92}}</string>
|
<string>{{1307,188},{62,92}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{77,99}</string>
|
<string>{77,99}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{748,0},{77,99}}</string>
|
<string>{{782,101},{77,99}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{112,99}</string>
|
<string>{112,99}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{408,348},{112,99}}</string>
|
<string>{{381,360},{112,99}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -60,7 +60,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{96,100}</string>
|
<string>{96,100}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{664,315},{96,100}}</string>
|
<string>{{704,312},{96,100}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{62,92}</string>
|
<string>{62,92}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1277,188},{62,92}}</string>
|
<string>{{1307,188},{62,92}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -90,7 +90,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{58,97}</string>
|
<string>{58,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1023,194},{58,97}}</string>
|
<string>{{983,388},{58,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -105,9 +105,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{60,90}</string>
|
<string>{60,90}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1393,141},{60,90}}</string>
|
<string>{{1424,0},{60,90}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk2_2.png</key>
|
<key>Atk2_2.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -120,7 +120,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{84,96}</string>
|
<string>{84,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1087,97},{84,96}}</string>
|
<string>{{1082,291},{84,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -135,7 +135,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{55,100}</string>
|
<string>{55,100}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{731,101},{55,100}}</string>
|
<string>{{738,206},{55,100}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -150,9 +150,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{63,100}</string>
|
<string>{63,100}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{717,206},{63,100}}</string>
|
<string>{{0,437},{63,100}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk2_5.png</key>
|
<key>Atk2_5.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -165,7 +165,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{66,101}</string>
|
<string>{66,101}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{682,0},{66,101}}</string>
|
<string>{{755,0},{66,101}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -180,7 +180,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,95}</string>
|
<string>{80,95}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1126,0},{80,95}}</string>
|
<string>{{1099,387},{80,95}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{116,109}</string>
|
<string>{116,109}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{315,119},{116,109}}</string>
|
<string>{{336,244},{116,109}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -210,7 +210,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{102,96}</string>
|
<string>{102,96}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{621,213},{102,96}}</string>
|
<string>{{608,325},{102,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -225,9 +225,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{75,102}</string>
|
<string>{75,102}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{139,421},{75,102}}</string>
|
<string>{{663,210},{75,102}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk3_0.png</key>
|
<key>Atk3_0.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -240,7 +240,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{66,109}</string>
|
<string>{66,109}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{469,110},{66,109}}</string>
|
<string>{{480,339},{66,109}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -255,7 +255,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{66,113}</string>
|
<string>{66,113}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{355,235},{66,113}}</string>
|
<string>{{403,114},{66,113}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -330,7 +330,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{78,131}</string>
|
<string>{78,131}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{137,290},{78,131}}</string>
|
<string>{{78,0},{78,131}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -345,9 +345,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{59,139}</string>
|
<string>{59,139}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{0,437},{59,139}}</string>
|
<string>{{78,290},{59,139}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atk3_8.png</key>
|
<key>Atk3_8.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -360,7 +360,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{59,139}</string>
|
<string>{59,139}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{78,290},{59,139}}</string>
|
<string>{{137,290},{59,139}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -375,9 +375,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{62,97}</string>
|
<string>{62,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{507,434},{62,97}}</string>
|
<string>{{962,291},{62,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atked1_1.png</key>
|
<key>Atked1_1.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -390,9 +390,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{73,95}</string>
|
<string>{73,95}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1171,95},{73,95}}</string>
|
<string>{{641,427},{73,95}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Atked1_2.png</key>
|
<key>Atked1_2.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -405,7 +405,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{90,89}</string>
|
<string>{90,89}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1324,0},{90,89}}</string>
|
<string>{{1335,0},{90,89}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -420,7 +420,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{95,80}</string>
|
<string>{95,80}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1084,291},{95,80}}</string>
|
<string>{{1168,193},{95,80}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -435,7 +435,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,95}</string>
|
<string>{80,95}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1010,388},{80,95}}</string>
|
<string>{{1166,290},{80,95}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -450,7 +450,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{83,92}</string>
|
<string>{83,92}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1208,382},{83,92}}</string>
|
<string>{{1299,382},{83,92}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -465,7 +465,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{92,83}</string>
|
<string>{92,83}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1224,284},{92,83}}</string>
|
<string>{{1306,284},{92,83}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -480,7 +480,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{112,45}</string>
|
<string>{112,45}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{424,115},{112,45}}</string>
|
<string>{{469,112},{112,45}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -495,7 +495,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{88,69}</string>
|
<string>{88,69}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{604,427},{88,69}}</string>
|
<string>{{1443,222},{88,69}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -510,7 +510,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{91,90}</string>
|
<string>{91,90}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1303,93},{91,90}}</string>
|
<string>{{1313,93},{91,90}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -525,7 +525,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{120,93}</string>
|
<string>{120,93}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{222,123},{120,93}}</string>
|
<string>{{254,124},{120,93}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -540,9 +540,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{100,112}</string>
|
<string>{100,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{241,396},{100,112}}</string>
|
<string>{{408,0},{100,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>GetUp1_5.png</key>
|
<key>GetUp1_5.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -555,7 +555,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{106,93}</string>
|
<string>{106,93}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{507,328},{106,93}}</string>
|
<string>{{570,219},{106,93}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -570,7 +570,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{106,79}</string>
|
<string>{106,79}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{542,217},{106,79}}</string>
|
<string>{{571,108},{106,79}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -585,7 +585,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{73,87}</string>
|
<string>{73,87}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1307,280},{73,87}}</string>
|
<string>{{1382,376},{73,87}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -600,9 +600,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{67,90}</string>
|
<string>{67,90}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1413,74},{67,90}}</string>
|
<string>{{1403,90},{67,90}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>GetUp1_9.png</key>
|
<key>GetUp1_9.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -615,7 +615,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{58,97}</string>
|
<string>{58,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1023,194},{58,97}}</string>
|
<string>{{983,388},{58,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -630,7 +630,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{58,95}</string>
|
<string>{58,95}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1090,386},{58,95}}</string>
|
<string>{{1219,0},{58,95}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -645,7 +645,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{58,97}</string>
|
<string>{58,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1029,97},{58,97}}</string>
|
<string>{{1024,291},{58,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -660,7 +660,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{60,94}</string>
|
<string>{60,94}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1148,386},{60,94}}</string>
|
<string>{{1179,385},{60,94}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -675,7 +675,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{58,97}</string>
|
<string>{58,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1081,194},{58,97}}</string>
|
<string>{{1036,194},{58,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -690,7 +690,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{58,97}</string>
|
<string>{58,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1068,0},{58,97}}</string>
|
<string>{{1041,388},{58,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -705,9 +705,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{60,95}</string>
|
<string>{60,95}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1206,0},{60,95}}</string>
|
<string>{{546,440},{60,95}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Idle1_5.png</key>
|
<key>Idle1_5.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -720,7 +720,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{60,94}</string>
|
<string>{60,94}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1164,288},{60,94}}</string>
|
<string>{{1239,385},{60,94}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -735,7 +735,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{59,93}</string>
|
<string>{59,93}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{789,403},{59,93}}</string>
|
<string>{{1248,191},{59,93}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -750,7 +750,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{58,93}</string>
|
<string>{58,93}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1266,0},{58,93}}</string>
|
<string>{{1277,0},{58,93}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -765,7 +765,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{59,93}</string>
|
<string>{59,93}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1244,95},{59,93}}</string>
|
<string>{{1254,95},{59,93}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -780,7 +780,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{60,94}</string>
|
<string>{60,94}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1217,190},{60,94}}</string>
|
<string>{{1246,288},{60,94}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -795,7 +795,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{77,68}</string>
|
<string>{77,68}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1437,417},{77,68}}</string>
|
<string>{{1473,291},{77,68}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -810,7 +810,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{118,76}</string>
|
<string>{118,76}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{215,278},{118,76}}</string>
|
<string>{{196,284},{118,76}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -825,7 +825,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{104,65}</string>
|
<string>{104,65}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{617,0},{104,65}}</string>
|
<string>{{650,106},{104,65}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -840,9 +840,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{80,66}</string>
|
<string>{80,66}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1380,285},{80,66}}</string>
|
<string>{{1473,368},{80,66}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirAtk1_12.png</key>
|
<key>InAirAtk1_12.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -855,7 +855,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{102,67}</string>
|
<string>{102,67}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{664,104},{102,67}}</string>
|
<string>{{715,104},{102,67}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -870,9 +870,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{79,66}</string>
|
<string>{79,66}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1339,201},{79,66}}</string>
|
<string>{{1470,90},{79,66}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirAtk1_3.png</key>
|
<key>InAirAtk1_3.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -885,7 +885,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{124,64}</string>
|
<string>{124,64}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{78,0},{124,64}}</string>
|
<string>{{156,0},{124,64}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -900,7 +900,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{104,64}</string>
|
<string>{104,64}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{600,323},{104,64}}</string>
|
<string>{{691,0},{104,64}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -915,7 +915,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{79,61}</string>
|
<string>{79,61}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1376,417},{79,61}}</string>
|
<string>{{1484,0},{79,61}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -930,7 +930,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{124,64}</string>
|
<string>{124,64}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{142,0},{124,64}}</string>
|
<string>{{160,124},{124,64}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -945,7 +945,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{106,67}</string>
|
<string>{106,67}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{597,107},{106,67}}</string>
|
<string>{{624,0},{106,67}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -960,7 +960,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{79,66}</string>
|
<string>{79,66}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1380,351},{79,66}}</string>
|
<string>{{1470,156},{79,66}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -975,7 +975,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{118,64}</string>
|
<string>{118,64}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{291,243},{118,64}}</string>
|
<string>{{272,284},{118,64}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -990,9 +990,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{71,119}</string>
|
<string>{71,119}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{242,0},{71,119}}</string>
|
<string>{{100,429},{71,119}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirIdle1_1.png</key>
|
<key>InAirIdle1_1.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1005,7 +1005,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{71,119}</string>
|
<string>{71,119}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{313,0},{71,119}}</string>
|
<string>{{282,0},{71,119}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1020,7 +1020,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{55,114}</string>
|
<string>{55,114}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{353,361},{55,114}}</string>
|
<string>{{353,0},{55,114}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1035,7 +1035,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{62,124}</string>
|
<string>{62,124}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{160,124},{62,124}}</string>
|
<string>{{220,0},{62,124}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1050,9 +1050,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{74,90}</string>
|
<string>{74,90}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1413,0},{74,90}}</string>
|
<string>{{1369,184},{74,90}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirIdle1_3.png</key>
|
<key>InAirIdle1_3.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1065,7 +1065,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{110,54}</string>
|
<string>{110,54}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{440,0},{110,54}}</string>
|
<string>{{508,0},{110,54}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1080,7 +1080,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{85,88}</string>
|
<string>{85,88}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1291,376},{85,88}}</string>
|
<string>{{736,412},{85,88}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1095,7 +1095,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{64,112}</string>
|
<string>{64,112}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{421,235},{64,112}}</string>
|
<string>{{445,227},{64,112}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1110,7 +1110,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{62,107}</string>
|
<string>{62,107}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{555,0},{62,107}}</string>
|
<string>{{546,333},{62,107}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1125,9 +1125,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{85,84}</string>
|
<string>{85,84}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1405,201},{85,84}}</string>
|
<string>{{1389,291},{85,84}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>InAirIdle1_8.png</key>
|
<key>InAirIdle1_8.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1140,7 +1140,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{109,61}</string>
|
<string>{109,61}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{494,0},{109,61}}</string>
|
<string>{{509,224},{109,61}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1155,7 +1155,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{78,95}</string>
|
<string>{78,95}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1139,193},{78,95}}</string>
|
<string>{{1176,96},{78,95}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1170,7 +1170,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{115,56}</string>
|
<string>{115,56}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{384,0},{115,56}}</string>
|
<string>{{347,119},{115,56}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1185,7 +1185,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{109,57}</string>
|
<string>{109,57}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{485,219},{109,57}}</string>
|
<string>{{514,110},{109,57}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1200,7 +1200,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{108,62}</string>
|
<string>{108,62}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{535,109},{108,62}}</string>
|
<string>{{562,0},{108,62}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1215,9 +1215,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{123,36}</string>
|
<string>{123,36}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{206,0},{123,36}}</string>
|
<string>{{160,248},{123,36}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>LayDown1_4.png</key>
|
<key>LayDown1_4.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1230,7 +1230,52 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{123,30}</string>
|
<string>{123,30}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{160,248},{123,30}}</string>
|
<string>{{224,124},{123,30}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>TurnAround1_1.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{74,96}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{74,96}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{1094,194},{74,96}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>TurnAround1_2.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{74,96}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{74,96}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{1102,97},{74,96}}</string>
|
||||||
|
<key>textureRotated</key>
|
||||||
|
<false/>
|
||||||
|
</dict>
|
||||||
|
<key>TurnAround1_3.png</key>
|
||||||
|
<dict>
|
||||||
|
<key>aliases</key>
|
||||||
|
<array/>
|
||||||
|
<key>spriteOffset</key>
|
||||||
|
<string>{0,0}</string>
|
||||||
|
<key>spriteSize</key>
|
||||||
|
<string>{74,96}</string>
|
||||||
|
<key>spriteSourceSize</key>
|
||||||
|
<string>{74,96}</string>
|
||||||
|
<key>textureRect</key>
|
||||||
|
<string>{{1145,0},{74,96}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1245,9 +1290,9 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{692,415},{81,97}}</string>
|
<string>{{219,402},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<true/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>Walking_10.png</key>
|
<key>Walking_10.png</key>
|
||||||
<dict>
|
<dict>
|
||||||
@@ -1260,7 +1305,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{760,306},{81,97}}</string>
|
<string>{{300,402},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1275,7 +1320,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{780,201},{81,97}}</string>
|
<string>{{821,0},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1290,7 +1335,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{786,99},{81,97}}</string>
|
<string>{{793,200},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1305,7 +1350,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{825,0},{81,97}}</string>
|
<string>{{859,97},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1320,7 +1365,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{841,298},{81,97}}</string>
|
<string>{{902,0},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1335,7 +1380,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{848,395},{81,97}}</string>
|
<string>{{800,297},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1350,7 +1395,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{861,196},{81,97}}</string>
|
<string>{{874,194},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1365,7 +1410,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{867,97},{81,97}}</string>
|
<string>{{940,97},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1380,7 +1425,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{906,0},{81,97}}</string>
|
<string>{{983,0},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1395,7 +1440,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{922,293},{81,97}}</string>
|
<string>{{821,394},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1410,7 +1455,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{942,194},{81,97}}</string>
|
<string>{{881,291},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1425,7 +1470,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{948,97},{81,97}}</string>
|
<string>{{955,194},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1440,7 +1485,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{987,0},{81,97}}</string>
|
<string>{{1021,97},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1455,7 +1500,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{929,390},{81,97}}</string>
|
<string>{{1064,0},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1470,7 +1515,7 @@
|
|||||||
<key>spriteSourceSize</key>
|
<key>spriteSourceSize</key>
|
||||||
<string>{81,97}</string>
|
<string>{81,97}</string>
|
||||||
<key>textureRect</key>
|
<key>textureRect</key>
|
||||||
<string>{{1003,291},{81,97}}</string>
|
<string>{{902,388},{81,97}}</string>
|
||||||
<key>textureRotated</key>
|
<key>textureRotated</key>
|
||||||
<false/>
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
@@ -1486,9 +1531,9 @@
|
|||||||
<key>realTextureFileName</key>
|
<key>realTextureFileName</key>
|
||||||
<string>MonkGirl.png</string>
|
<string>MonkGirl.png</string>
|
||||||
<key>size</key>
|
<key>size</key>
|
||||||
<string>{1505,496}</string>
|
<string>{1549,500}</string>
|
||||||
<key>smartupdate</key>
|
<key>smartupdate</key>
|
||||||
<string>$TexturePacker:SmartUpdate:8383576ddc6ed0fb9e6adcbc98ec9c07:b0caf27c9f592741053365a3d87b3473:7b088363a1f16e4f4ff313aecc52227b$</string>
|
<string>$TexturePacker:SmartUpdate:f2fd96a7a4bba5a2e1c4622dcb63e1f2:17c698372c46bf0be82704dd808cd6f4:7b088363a1f16e4f4ff313aecc52227b$</string>
|
||||||
<key>textureFileName</key>
|
<key>textureFileName</key>
|
||||||
<string>MonkGirl.png</string>
|
<string>MonkGirl.png</string>
|
||||||
</dict>
|
</dict>
|
||||||
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 98 KiB |
@@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"__type__": "cc.AnimationClip",
|
||||||
|
"_name": "TurnAround1",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"_duration": 0.15,
|
||||||
|
"sample": 60,
|
||||||
|
"speed": 1,
|
||||||
|
"wrapMode": 1,
|
||||||
|
"curveData": {
|
||||||
|
"comps": {
|
||||||
|
"cc.Sprite": {
|
||||||
|
"spriteFrame": [
|
||||||
|
{
|
||||||
|
"frame": 0,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "c1a00209-f74d-41b5-a5da-df5720ac34b4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.03333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "2b52c0f1-2360-4a2b-9233-bf5662de09a5"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.08333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "e3f9dfe7-ed91-4dc3-b68b-a3a3c2637074"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"frame": 0.13333333333333333,
|
||||||
|
"value": {
|
||||||
|
"__uuid__": "7515ef50-3a14-4e58-8811-a0c890fc40f3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"events": []
|
||||||
|
}
|
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"ver": "2.1.0",
|
||||||
|
"uuid": "6e1139d4-03dd-4bd4-9510-606e94f629fe",
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -1,23 +1,23 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="128" height="128" tilewidth="16" tileheight="16" infinite="0" nextlayerid="6" nextobjectid="113">
|
<map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="128" height="64" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="137">
|
||||||
<tileset firstgid="1" source="tiles0.tsx"/>
|
<tileset firstgid="1" source="tiles0.tsx"/>
|
||||||
<tileset firstgid="65" source="tiles1.tsx"/>
|
<tileset firstgid="65" source="tiles1.tsx"/>
|
||||||
<tileset firstgid="129" source="tiles2.tsx"/>
|
<tileset firstgid="129" source="tiles2.tsx"/>
|
||||||
<layer id="2" name="Ground" width="128" height="128">
|
<layer id="6" name="Ground" width="128" height="64">
|
||||||
<data encoding="base64" compression="zlib">
|
<data encoding="base64" compression="zlib">
|
||||||
eJzt3LFu00AcwOEoFUuHigqBBANTByRegrlTWWBj6gsgWGBCqngAFgZ23hNHsiXj5mLncs6dfd/wSVUbWa1/f199VpSLzWZzAQAAAAAAAAAAAAAAAAAAES5buX8Pzue+p+t/X6HcHXL237a6/p8atwHbFdL///4h+q9Pv//tSP/LAlrpP1//ffRft93f/ry179wM14TcrfQ/b/8a6K9/7g45+z+LkLuZ/nn7r2kG9Nc/d4cl9i+J/nX2d/3X3T/FDOi/XK5//fWvt3+KGdA//bntnik+nGjua19//fVfRv+XLf3r6d/v3f9af/31z9f/6YiU/fv0z9t/rPu+/r8bH47U9Xf/V07/qe3vNu7/l2Jq/6ntt/ovylj/fY3fNq4C7Yf9h+6OpH++/vvaX/UMu8/R/0XjRv9i+h9a9/v9U9O/3P4x94jH0v/8/afMwPBcpuw7JmX/bQEtSuyf6hwfEtNe//X0P2ZG5ji2/qfPwN9ELVIdR/90/afMgP7LpL/+JXXL1T93B/31X3L/Xwnpv7z+S6Z/3fSvm/51079u+tdN/7rpXzf966Z/3fSvm/51079u+pfrJkD/MvrP9X7RUPc55kD/cvpfj3gSoP86+uegf3xv/Zet9Ps//dfXP/S/vfv5+4T6xwytT97/Pe5ja7jed9/PfQ2fev3rf9ih//nD/q8LaBqyb43QP2zXMrTn2hnbr12PHD93+65/7g6l9u86vznBqfvzOdvr/3i9Tr1+p3hGM1d7/dM/Twv1zzEDU/YItfefu8Fwts71nGjqHlH/8/bvZmDOz3s55hmB/o+lvJ8/tH8I+REhpr3+4/1OnYOY/jEz8DOS/tPEzsGrTVz/3WcBfA207nxvfG5fq/+8/WM1/d/F9t/5sgn3/9Z73a7ln5b+0/uTvwMAAAAAAAAAAAAAAABwfv8AQJoGWw==
|
eJzt201uwjAQhuEIxCY7KugeqTepumHXC/T+xyCqYimy4sQ4E2bE9y6eDf+e1w4bOHZddwQAAAAAAAAAAACAF/jBP+8Onv29P4M35Rkor50ZaK+dGWivnRlor50ZtK39UmnL5/owegz94/X/on8Ykfsv9V27n/72a0/drPqfBucZeeMSjxm8m5b+W1m9Dv3fv//c9eG88f3p397fytr1vNR9j31A/1hq21vtg4gziNz/ZvQY+vubrr0fefdv3QOt+0O9/3cm3ZffntwqlZ4fTZqBdwuv/odROv9/g3vBwUDpjFq8dst7q5//vP/0O2B6m1V/T/Qv979nvedY9/jcwTPXHPov9+lXZldjrb/1fqL/c/2vo6W5bTn/S3tg7/Nfsz/pX+5v+Z1L/3i8f3cdhXcHz/6/4uivjf7a6K+N/tror43+2uivjf7a6K+N/tror43+2uivjf7a6K+N/tror43+2uivjf7a6K+N/trSf6C8W9Cf/vSn/6v7Y7/+Dyz1uAA=
|
||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
<objectgroup id="1" name="PlayerStartingPos">
|
<objectgroup id="1" name="PlayerStartingPos">
|
||||||
<object id="135" x="1040.33" y="1081">
|
<object id="135" x="1400" y="580">
|
||||||
<point/>
|
<point/>
|
||||||
</object>
|
</object>
|
||||||
<object id="137" x="1134.67" y="1081.67">
|
<object id="137" x="1500" y="580">
|
||||||
<point/>
|
<point/>
|
||||||
</object>
|
</object>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
<objectgroup id="4" name="NpcStartingPos">
|
<objectgroup id="4" name="NpcStartingPos">
|
||||||
<object id="108" x="926" y="1447">
|
<object id="108" x="927.333" y="535">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="dirX" value="-2"/>
|
<property name="dirX" value="-2"/>
|
||||||
<property name="speciesId" value="4196"/>
|
<property name="speciesId" value="4196"/>
|
||||||
@@ -26,28 +26,28 @@
|
|||||||
</object>
|
</object>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
<objectgroup id="5" name="NpcPatrolCue">
|
<objectgroup id="5" name="NpcPatrolCue">
|
||||||
<object id="109" x="773.337" y="1468.67">
|
<object id="109" x="774.67" y="556.67">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="flAct" value="36"/>
|
<property name="flAct" value="36"/>
|
||||||
<property name="frAct" value="35"/>
|
<property name="frAct" value="35"/>
|
||||||
</properties>
|
</properties>
|
||||||
<point/>
|
<point/>
|
||||||
</object>
|
</object>
|
||||||
<object id="110" x="728" y="1500">
|
<object id="110" x="729.333" y="588">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="flAct" value="4"/>
|
<property name="flAct" value="4"/>
|
||||||
<property name="frAct" value="35"/>
|
<property name="frAct" value="35"/>
|
||||||
</properties>
|
</properties>
|
||||||
<point/>
|
<point/>
|
||||||
</object>
|
</object>
|
||||||
<object id="111" x="668" y="1500">
|
<object id="111" x="669.333" y="588">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="flAct" value="3"/>
|
<property name="flAct" value="3"/>
|
||||||
<property name="frAct" value="3"/>
|
<property name="frAct" value="3"/>
|
||||||
</properties>
|
</properties>
|
||||||
<point/>
|
<point/>
|
||||||
</object>
|
</object>
|
||||||
<object id="112" x="984" y="1447">
|
<object id="112" x="985.333" y="535">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="flAct" value="4"/>
|
<property name="flAct" value="4"/>
|
||||||
<property name="frAct" value="4"/>
|
<property name="frAct" value="4"/>
|
||||||
@@ -59,197 +59,112 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<property name="type" value="barrier_and_shelter"/>
|
<property name="type" value="barrier_and_shelter"/>
|
||||||
</properties>
|
</properties>
|
||||||
<object id="54" x="656" y="1504" width="80" height="16">
|
<object id="57" x="768" y="560" width="32" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="55" x="736" y="1552" width="112" height="16">
|
<object id="60" x="1232" y="448" width="208" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="57" x="768" y="1472" width="32" height="16">
|
<object id="65" x="1040" y="576" width="32" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="58" x="1040" y="1536" width="80" height="16">
|
<object id="66" x="1040" y="560" width="16" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="59" x="1040" y="1568" width="224" height="48">
|
<object id="67" x="784" y="544" width="256" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="60" x="1216" y="1344" width="224" height="16">
|
<object id="84" x="640" y="224" width="16" height="800">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="62" x="1040" y="1552" width="208" height="16">
|
<object id="85" x="1680" y="224" width="16" height="800">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="63" x="1040" y="1504" width="48" height="16">
|
<object id="86" x="1104" y="496" width="96" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="64" x="1040" y="1520" width="64" height="16">
|
<object id="90" x="1248" y="464" width="320" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="65" x="1040" y="1488" width="32" height="16">
|
<object id="97" x="1248" y="416" width="158" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="66" x="1040" y="1472" width="16" height="16">
|
<object id="98" x="1280" y="400" width="96" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="67" x="784" y="1456" width="256" height="16">
|
<object id="100" x="1538" y="560" width="144" height="32">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="73" x="784" y="1568" width="96" height="16">
|
<object id="101" x="1568" y="528" width="112" height="32">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="74" x="816" y="1584" width="96" height="16">
|
<object id="102" x="1136" y="368" width="96" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="79" x="640" y="1616" width="1056" height="16">
|
<object id="103" x="1600" y="496" width="80" height="32">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="83" x="640" y="480" width="1056" height="16">
|
<object id="104" x="816" y="414" width="304" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="84" x="640" y="480" width="16" height="1152">
|
<object id="105" x="816" y="366" width="16" height="64">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="85" x="1680" y="480" width="16" height="1152">
|
<object id="106" x="1104" y="334" width="16" height="96">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="86" x="1104" y="1408" width="96" height="16">
|
<object id="113" x="640" y="1008" width="1056" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="87" x="1456" y="1568" width="224" height="48">
|
<object id="114" x="640" y="224" width="1056" height="16">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="88" x="1264" y="1584" width="16" height="32">
|
<object id="119" x="656" y="592" width="1024" height="416">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="89" x="1280" y="1600" width="16" height="16">
|
<object id="136" x="1232" y="432" width="208" height="16">
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="90" x="1232" y="1408" width="304" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="91" x="1440" y="1584" width="16" height="32">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="92" x="1424" y="1600" width="16" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="93" x="1488" y="1552" width="192" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="94" x="1504" y="1536" width="176" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="95" x="1520" y="1520" width="160" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="96" x="1568" y="1408" width="16" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="97" x="1248" y="1328" width="158" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="98" x="1280" y="1312" width="96" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="99" x="1536" y="1504" width="144" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="100" x="1552" y="1488" width="128" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="101" x="1568" y="1472" width="112" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="102" x="1584" y="1456" width="96" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="103" x="1600" y="1440" width="80" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="104" x="928" y="1088" width="304" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="105" x="928" y="1008" width="16" height="96">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="106" x="1216" y="1008" width="16" height="96">
|
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
|
@@ -9,9 +9,9 @@ message PlayerDownsync {
|
|||||||
int32 virtualGridX = 2;
|
int32 virtualGridX = 2;
|
||||||
int32 virtualGridY = 3;
|
int32 virtualGridY = 3;
|
||||||
int32 dirX = 4;
|
int32 dirX = 4;
|
||||||
int32 dirY = 5; // "dirX" and "dirY" determines character facing
|
int32 dirY = 5;
|
||||||
int32 velX = 6;
|
int32 velX = 6;
|
||||||
int32 velY = 7; // "velX" and "velY" is used to record the accumulated effect by accelerations (including gravity)
|
int32 velY = 7; // "velX" and "velY" is used to record the accumulated effect by inertia and accelerations (including gravity)
|
||||||
int32 speed = 8; // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY"
|
int32 speed = 8; // this is the instantaneous scalar attribute of a character, different from but will be accounted in "velX" and "velY"
|
||||||
int32 battleState = 9;
|
int32 battleState = 9;
|
||||||
int32 joinIndex = 10;
|
int32 joinIndex = 10;
|
||||||
@@ -32,6 +32,12 @@ message PlayerDownsync {
|
|||||||
int32 bulletTeamId = 24;
|
int32 bulletTeamId = 24;
|
||||||
int32 chCollisionTeamId = 25;
|
int32 chCollisionTeamId = 25;
|
||||||
|
|
||||||
|
bool onWall = 26; // like "inAir", it’s by design a standalone field only inferred by the collision result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState", because we need check the transition for "characterState" from this field, i.e. "onWall (prev -> curr)"
|
||||||
|
int32 onWallNormX = 27;
|
||||||
|
int32 onWallNormY = 28;
|
||||||
|
|
||||||
|
bool capturedByInertia = 29; // like "inAir", it’s by design a standalone field only inferred by the calc result of "applyInputFrameDownsyncDynamicsOnSingleRenderFrame" instead of "characterState"
|
||||||
|
|
||||||
string name = 997;
|
string name = 997;
|
||||||
string displayName = 998;
|
string displayName = 998;
|
||||||
string avatar = 999;
|
string avatar = 999;
|
||||||
@@ -47,6 +53,7 @@ message InputFrameDecoded {
|
|||||||
message InputFrameUpsync {
|
message InputFrameUpsync {
|
||||||
int32 inputFrameId = 1;
|
int32 inputFrameId = 1;
|
||||||
uint64 encoded = 2;
|
uint64 encoded = 2;
|
||||||
|
int32 joinIndex = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
message InputFrameDownsync {
|
message InputFrameDownsync {
|
||||||
@@ -66,17 +73,9 @@ message WsReq {
|
|||||||
int32 joinIndex = 4;
|
int32 joinIndex = 4;
|
||||||
int32 ackingFrameId = 5;
|
int32 ackingFrameId = 5;
|
||||||
int32 ackingInputFrameId = 6;
|
int32 ackingInputFrameId = 6;
|
||||||
repeated InputFrameUpsync inputFrameUpsyncBatch = 7;
|
int32 authKey = 7;
|
||||||
HeartbeatUpsync hb = 8;
|
repeated InputFrameUpsync inputFrameUpsyncBatch = 8;
|
||||||
}
|
HeartbeatUpsync hb = 9;
|
||||||
|
|
||||||
message WsResp {
|
|
||||||
int32 ret = 1;
|
|
||||||
int32 echoedMsgId = 2;
|
|
||||||
int32 act = 3;
|
|
||||||
RoomDownsyncFrame rdf = 4;
|
|
||||||
repeated InputFrameDownsync inputFrameDownsyncBatch = 5;
|
|
||||||
BattleColliderInfo bciFrame = 6;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
message InputsBufferSnapshot {
|
message InputsBufferSnapshot {
|
||||||
@@ -84,6 +83,7 @@ message InputsBufferSnapshot {
|
|||||||
uint64 unconfirmedMask = 2;
|
uint64 unconfirmedMask = 2;
|
||||||
repeated InputFrameDownsync toSendInputFrameDownsyncs = 3;
|
repeated InputFrameDownsync toSendInputFrameDownsyncs = 3;
|
||||||
bool shouldForceResync = 4;
|
bool shouldForceResync = 4;
|
||||||
|
int32 peerJoinIndex = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message MeleeBullet {
|
message MeleeBullet {
|
||||||
@@ -117,6 +117,11 @@ message MeleeBullet {
|
|||||||
int32 teamId = 19;
|
int32 teamId = 19;
|
||||||
|
|
||||||
int32 bulletLocalId = 20;
|
int32 bulletLocalId = 20;
|
||||||
|
int32 speciesId = 21;
|
||||||
|
int32 explosionFrames = 22;
|
||||||
|
|
||||||
|
int32 blState = 23;
|
||||||
|
int32 framesInBlState = 24;
|
||||||
}
|
}
|
||||||
|
|
||||||
message FireballBullet {
|
message FireballBullet {
|
||||||
@@ -146,6 +151,11 @@ message FireballBullet {
|
|||||||
int32 teamId = 19;
|
int32 teamId = 19;
|
||||||
|
|
||||||
int32 bulletLocalId = 20;
|
int32 bulletLocalId = 20;
|
||||||
|
int32 speciesId = 21;
|
||||||
|
int32 explosionFrames = 22;
|
||||||
|
|
||||||
|
int32 blState = 23;
|
||||||
|
int32 framesInBlState = 24;
|
||||||
|
|
||||||
int32 virtualGridX = 999;
|
int32 virtualGridX = 999;
|
||||||
int32 virtualGridY = 1000;
|
int32 virtualGridY = 1000;
|
||||||
@@ -156,6 +166,18 @@ message FireballBullet {
|
|||||||
int32 speed = 1005;
|
int32 speed = 1005;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message HolePunchUpsync {
|
||||||
|
string intAuthToken = 1;
|
||||||
|
int32 boundRoomId = 2;
|
||||||
|
int32 authKey = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message PeerUdpAddr {
|
||||||
|
string ip = 1;
|
||||||
|
int32 port = 2;
|
||||||
|
int32 authKey = 3;
|
||||||
|
}
|
||||||
|
|
||||||
message BattleColliderInfo {
|
message BattleColliderInfo {
|
||||||
string stageName = 1;
|
string stageName = 1;
|
||||||
|
|
||||||
@@ -172,6 +194,8 @@ message BattleColliderInfo {
|
|||||||
double spaceOffsetX = 11;
|
double spaceOffsetX = 11;
|
||||||
double spaceOffsetY = 12;
|
double spaceOffsetY = 12;
|
||||||
int32 collisionMinStep = 13;
|
int32 collisionMinStep = 13;
|
||||||
|
int32 boundRoomCapacity = 14;
|
||||||
|
PeerUdpAddr battleUdpTunnel = 15;
|
||||||
|
|
||||||
bool frameDataLoggingEnabled = 1024;
|
bool frameDataLoggingEnabled = 1024;
|
||||||
}
|
}
|
||||||
@@ -188,4 +212,15 @@ message RoomDownsyncFrame {
|
|||||||
repeated int32 speciesIdList = 1026;
|
repeated int32 speciesIdList = 1026;
|
||||||
|
|
||||||
int32 bulletLocalIdCounter = 1027;
|
int32 bulletLocalIdCounter = 1027;
|
||||||
|
repeated PeerUdpAddr peerUdpAddrList = 1028;
|
||||||
|
}
|
||||||
|
|
||||||
|
message WsResp {
|
||||||
|
int32 ret = 1;
|
||||||
|
int32 echoedMsgId = 2;
|
||||||
|
int32 act = 3;
|
||||||
|
RoomDownsyncFrame rdf = 4;
|
||||||
|
repeated InputFrameDownsync inputFrameDownsyncBatch = 5;
|
||||||
|
BattleColliderInfo bciFrame = 6;
|
||||||
|
int32 peerJoinIndex = 7;
|
||||||
}
|
}
|
||||||
|
@@ -31,13 +31,10 @@
|
|||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 22
|
"__id__": 22
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 23
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 24
|
"__id__": 23
|
||||||
},
|
},
|
||||||
"_opacity": 255,
|
"_opacity": 255,
|
||||||
"_color": {
|
"_color": {
|
||||||
@@ -485,6 +482,13 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__uuid__": "e8247e2a-1b5b-4618-86f8-224b25246b55"
|
"__uuid__": "e8247e2a-1b5b-4618-86f8-224b25246b55"
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
"__uuid__": "6e1139d4-03dd-4bd4-9510-606e94f629fe"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"playOnLoad": false,
|
"playOnLoad": false,
|
||||||
@@ -648,6 +652,17 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__uuid__": "9b500cb0-8048-4715-81db-cc975c914225"
|
"__uuid__": "9b500cb0-8048-4715-81db-cc975c914225"
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
"__uuid__": "38b2c892-347b-4009-93f8-65b2ab1614f0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__uuid__": "411f964a-4dd8-424c-b2e2-d92b10474ce2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__uuid__": "e906322d-a08b-4477-a2e9-98acd42fa034"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"playOnLoad": false,
|
"playOnLoad": false,
|
||||||
@@ -814,6 +829,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__uuid__": "7e0a1e98-ee5a-446f-bec2-7d72b6916503"
|
"__uuid__": "7e0a1e98-ee5a-446f-bec2-7d72b6916503"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__uuid__": "0abbd156-980e-475e-9994-3c958bd913fc"
|
||||||
|
},
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
{
|
||||||
|
"__uuid__": "edd23b2f-1caa-4836-88a7-e4af1f26743e"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"playOnLoad": false,
|
"playOnLoad": false,
|
||||||
@@ -869,32 +892,6 @@
|
|||||||
"fileId": "7aN7Gcc/tBw5EGlTJVBj2+",
|
"fileId": "7aN7Gcc/tBw5EGlTJVBj2+",
|
||||||
"sync": false
|
"sync": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"__type__": "cc.Sprite",
|
|
||||||
"_name": "",
|
|
||||||
"_objFlags": 0,
|
|
||||||
"node": {
|
|
||||||
"__id__": 1
|
|
||||||
},
|
|
||||||
"_enabled": true,
|
|
||||||
"_materials": [],
|
|
||||||
"_srcBlendFactor": 770,
|
|
||||||
"_dstBlendFactor": 771,
|
|
||||||
"_spriteFrame": null,
|
|
||||||
"_type": 0,
|
|
||||||
"_sizeMode": 0,
|
|
||||||
"_fillType": 0,
|
|
||||||
"_fillCenter": {
|
|
||||||
"__type__": "cc.Vec2",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"_fillStart": 0,
|
|
||||||
"_fillRange": 0,
|
|
||||||
"_isTrimmedMode": true,
|
|
||||||
"_atlas": null,
|
|
||||||
"_id": ""
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__type__": "b74b05YDqZFRo4OkZRFZX8k",
|
"__type__": "b74b05YDqZFRo4OkZRFZX8k",
|
||||||
"_name": "",
|
"_name": "",
|
||||||
|
@@ -8,7 +8,8 @@
|
|||||||
"__id__": 1
|
"__id__": 1
|
||||||
},
|
},
|
||||||
"optimizationPolicy": 0,
|
"optimizationPolicy": 0,
|
||||||
"asyncLoadAssets": false
|
"asyncLoadAssets": false,
|
||||||
|
"readonly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Node",
|
"__type__": "cc.Node",
|
||||||
@@ -27,20 +28,19 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 11
|
"__id__": 11
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 14
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_level": 1,
|
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 14
|
"__id__": 17
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 15
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 16
|
"__id__": 18
|
||||||
},
|
},
|
||||||
"_opacity": 255,
|
"_opacity": 255,
|
||||||
"_color": {
|
"_color": {
|
||||||
@@ -52,25 +52,14 @@
|
|||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
"width": 1024,
|
"width": 960,
|
||||||
"height": 1920
|
"height": 640
|
||||||
},
|
},
|
||||||
"_anchorPoint": {
|
"_anchorPoint": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
"x": 0.5,
|
"x": 0.5,
|
||||||
"y": 0.5
|
"y": 0.5
|
||||||
},
|
},
|
||||||
"_quat": {
|
|
||||||
"__type__": "cc.Quat",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"z": 0,
|
|
||||||
"w": 1
|
|
||||||
},
|
|
||||||
"_skewX": 0,
|
|
||||||
"_skewY": 0,
|
|
||||||
"groupIndex": 0,
|
|
||||||
"_id": "",
|
|
||||||
"_trs": {
|
"_trs": {
|
||||||
"__type__": "TypedArray",
|
"__type__": "TypedArray",
|
||||||
"ctor": "Float64Array",
|
"ctor": "Float64Array",
|
||||||
@@ -86,18 +75,29 @@
|
|||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Node",
|
"__type__": "cc.Node",
|
||||||
"_name": "WhiteStars",
|
"_name": "Background",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 1
|
"__id__": 1
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_level": 2,
|
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 3
|
"__id__": 3
|
||||||
@@ -109,37 +109,26 @@
|
|||||||
"_opacity": 255,
|
"_opacity": 255,
|
||||||
"_color": {
|
"_color": {
|
||||||
"__type__": "cc.Color",
|
"__type__": "cc.Color",
|
||||||
"r": 255,
|
"r": 0,
|
||||||
"g": 255,
|
"g": 163,
|
||||||
"b": 255,
|
"b": 255,
|
||||||
"a": 255
|
"a": 255
|
||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
"width": 268,
|
"width": 1920,
|
||||||
"height": 112
|
"height": 1280
|
||||||
},
|
},
|
||||||
"_anchorPoint": {
|
"_anchorPoint": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
"x": 0.5,
|
"x": 0.5,
|
||||||
"y": 0.5
|
"y": 0.5
|
||||||
},
|
},
|
||||||
"_quat": {
|
|
||||||
"__type__": "cc.Quat",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"z": 0,
|
|
||||||
"w": 1
|
|
||||||
},
|
|
||||||
"_skewX": 0,
|
|
||||||
"_skewY": 0,
|
|
||||||
"groupIndex": 0,
|
|
||||||
"_id": "",
|
|
||||||
"_trs": {
|
"_trs": {
|
||||||
"__type__": "TypedArray",
|
"__type__": "TypedArray",
|
||||||
"ctor": "Float64Array",
|
"ctor": "Float64Array",
|
||||||
"array": [
|
"array": [
|
||||||
-16,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -150,7 +139,19 @@
|
|||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Sprite",
|
"__type__": "cc.Sprite",
|
||||||
@@ -160,11 +161,18 @@
|
|||||||
"__id__": 2
|
"__id__": 2
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
|
"_materials": [
|
||||||
|
{
|
||||||
|
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_srcBlendFactor": 770,
|
||||||
|
"_dstBlendFactor": 771,
|
||||||
"_spriteFrame": {
|
"_spriteFrame": {
|
||||||
"__uuid__": "1a2d934e-9d6d-45bf-83c6-564586cc8400"
|
"__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
|
||||||
},
|
},
|
||||||
"_type": 0,
|
"_type": 0,
|
||||||
"_sizeMode": 1,
|
"_sizeMode": 0,
|
||||||
"_fillType": 0,
|
"_fillType": 0,
|
||||||
"_fillCenter": {
|
"_fillCenter": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
@@ -174,12 +182,9 @@
|
|||||||
"_fillStart": 0,
|
"_fillStart": 0,
|
||||||
"_fillRange": 0,
|
"_fillRange": 0,
|
||||||
"_isTrimmedMode": true,
|
"_isTrimmedMode": true,
|
||||||
"_state": 0,
|
|
||||||
"_atlas": {
|
"_atlas": {
|
||||||
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
|
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
|
||||||
},
|
},
|
||||||
"_srcBlendFactor": 770,
|
|
||||||
"_dstBlendFactor": 771,
|
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -190,7 +195,7 @@
|
|||||||
"asset": {
|
"asset": {
|
||||||
"__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e"
|
"__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e"
|
||||||
},
|
},
|
||||||
"fileId": "50Mjaee6xFXLrZ/mSBD3P5",
|
"fileId": "83iQr+5XNNF5E2qjV+WUp0",
|
||||||
"sync": false
|
"sync": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -202,7 +207,6 @@
|
|||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_level": 3,
|
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 6
|
"__id__": 6
|
||||||
@@ -229,17 +233,6 @@
|
|||||||
"x": 0.5,
|
"x": 0.5,
|
||||||
"y": 0.5
|
"y": 0.5
|
||||||
},
|
},
|
||||||
"_quat": {
|
|
||||||
"__type__": "cc.Quat",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"z": 0,
|
|
||||||
"w": 1
|
|
||||||
},
|
|
||||||
"_skewX": 0,
|
|
||||||
"_skewY": 0,
|
|
||||||
"groupIndex": 0,
|
|
||||||
"_id": "",
|
|
||||||
"_trs": {
|
"_trs": {
|
||||||
"__type__": "TypedArray",
|
"__type__": "TypedArray",
|
||||||
"ctor": "Float64Array",
|
"ctor": "Float64Array",
|
||||||
@@ -255,7 +248,19 @@
|
|||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Sprite",
|
"__type__": "cc.Sprite",
|
||||||
@@ -265,6 +270,13 @@
|
|||||||
"__id__": 5
|
"__id__": 5
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
|
"_materials": [
|
||||||
|
{
|
||||||
|
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_srcBlendFactor": 770,
|
||||||
|
"_dstBlendFactor": 771,
|
||||||
"_spriteFrame": {
|
"_spriteFrame": {
|
||||||
"__uuid__": "75a2c1e3-2c22-480c-9572-eb65f4a554e1"
|
"__uuid__": "75a2c1e3-2c22-480c-9572-eb65f4a554e1"
|
||||||
},
|
},
|
||||||
@@ -279,12 +291,9 @@
|
|||||||
"_fillStart": 0,
|
"_fillStart": 0,
|
||||||
"_fillRange": 0,
|
"_fillRange": 0,
|
||||||
"_isTrimmedMode": true,
|
"_isTrimmedMode": true,
|
||||||
"_state": 0,
|
|
||||||
"_atlas": {
|
"_atlas": {
|
||||||
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
|
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
|
||||||
},
|
},
|
||||||
"_srcBlendFactor": 770,
|
|
||||||
"_dstBlendFactor": 771,
|
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -307,7 +316,6 @@
|
|||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_level": 2,
|
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 9
|
"__id__": 9
|
||||||
@@ -327,24 +335,13 @@
|
|||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
"width": 111.23,
|
"width": 111.23,
|
||||||
"height": 200
|
"height": 252
|
||||||
},
|
},
|
||||||
"_anchorPoint": {
|
"_anchorPoint": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
"x": 0.5,
|
"x": 0.5,
|
||||||
"y": 0.5
|
"y": 0.5
|
||||||
},
|
},
|
||||||
"_quat": {
|
|
||||||
"__type__": "cc.Quat",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"z": 0,
|
|
||||||
"w": 1
|
|
||||||
},
|
|
||||||
"_skewX": 0,
|
|
||||||
"_skewY": 0,
|
|
||||||
"groupIndex": 0,
|
|
||||||
"_id": "",
|
|
||||||
"_trs": {
|
"_trs": {
|
||||||
"__type__": "TypedArray",
|
"__type__": "TypedArray",
|
||||||
"ctor": "Float64Array",
|
"ctor": "Float64Array",
|
||||||
@@ -360,7 +357,19 @@
|
|||||||
0.66667,
|
0.66667,
|
||||||
0.66667
|
0.66667
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Label",
|
"__type__": "cc.Label",
|
||||||
@@ -370,6 +379,11 @@
|
|||||||
"__id__": 8
|
"__id__": 8
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
|
"_materials": [
|
||||||
|
{
|
||||||
|
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
||||||
|
}
|
||||||
|
],
|
||||||
"_useOriginalSize": false,
|
"_useOriginalSize": false,
|
||||||
"_string": "3",
|
"_string": "3",
|
||||||
"_N$string": "3",
|
"_N$string": "3",
|
||||||
@@ -407,7 +421,6 @@
|
|||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_level": 2,
|
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 12
|
"__id__": 12
|
||||||
@@ -434,17 +447,6 @@
|
|||||||
"x": 0.5,
|
"x": 0.5,
|
||||||
"y": 0.5
|
"y": 0.5
|
||||||
},
|
},
|
||||||
"_quat": {
|
|
||||||
"__type__": "cc.Quat",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"z": 0,
|
|
||||||
"w": 1
|
|
||||||
},
|
|
||||||
"_skewX": 0,
|
|
||||||
"_skewY": 0,
|
|
||||||
"groupIndex": 0,
|
|
||||||
"_id": "",
|
|
||||||
"_trs": {
|
"_trs": {
|
||||||
"__type__": "TypedArray",
|
"__type__": "TypedArray",
|
||||||
"ctor": "Float64Array",
|
"ctor": "Float64Array",
|
||||||
@@ -460,7 +462,19 @@
|
|||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Sprite",
|
"__type__": "cc.Sprite",
|
||||||
@@ -470,6 +484,13 @@
|
|||||||
"__id__": 11
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
|
"_materials": [
|
||||||
|
{
|
||||||
|
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_srcBlendFactor": 770,
|
||||||
|
"_dstBlendFactor": 771,
|
||||||
"_spriteFrame": {
|
"_spriteFrame": {
|
||||||
"__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
|
"__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
|
||||||
},
|
},
|
||||||
@@ -484,12 +505,9 @@
|
|||||||
"_fillStart": 0,
|
"_fillStart": 0,
|
||||||
"_fillRange": 0,
|
"_fillRange": 0,
|
||||||
"_isTrimmedMode": true,
|
"_isTrimmedMode": true,
|
||||||
"_state": 0,
|
|
||||||
"_atlas": {
|
"_atlas": {
|
||||||
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
|
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
|
||||||
},
|
},
|
||||||
"_srcBlendFactor": 770,
|
|
||||||
"_dstBlendFactor": 771,
|
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -503,6 +521,115 @@
|
|||||||
"fileId": "21dxpL7zlKIIDhUt+GIMbg",
|
"fileId": "21dxpL7zlKIIDhUt+GIMbg",
|
||||||
"sync": false
|
"sync": false
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Node",
|
||||||
|
"_name": "WhiteStars",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_parent": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"_children": [],
|
||||||
|
"_active": true,
|
||||||
|
"_components": [
|
||||||
|
{
|
||||||
|
"__id__": 15
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_prefab": {
|
||||||
|
"__id__": 16
|
||||||
|
},
|
||||||
|
"_opacity": 255,
|
||||||
|
"_color": {
|
||||||
|
"__type__": "cc.Color",
|
||||||
|
"r": 255,
|
||||||
|
"g": 255,
|
||||||
|
"b": 255,
|
||||||
|
"a": 255
|
||||||
|
},
|
||||||
|
"_contentSize": {
|
||||||
|
"__type__": "cc.Size",
|
||||||
|
"width": 268,
|
||||||
|
"height": 112
|
||||||
|
},
|
||||||
|
"_anchorPoint": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0.5,
|
||||||
|
"y": 0.5
|
||||||
|
},
|
||||||
|
"_trs": {
|
||||||
|
"__type__": "TypedArray",
|
||||||
|
"ctor": "Float64Array",
|
||||||
|
"array": [
|
||||||
|
-16,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Sprite",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"node": {
|
||||||
|
"__id__": 14
|
||||||
|
},
|
||||||
|
"_enabled": true,
|
||||||
|
"_materials": [
|
||||||
|
{
|
||||||
|
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_srcBlendFactor": 770,
|
||||||
|
"_dstBlendFactor": 771,
|
||||||
|
"_spriteFrame": {
|
||||||
|
"__uuid__": "1a2d934e-9d6d-45bf-83c6-564586cc8400"
|
||||||
|
},
|
||||||
|
"_type": 0,
|
||||||
|
"_sizeMode": 1,
|
||||||
|
"_fillType": 0,
|
||||||
|
"_fillCenter": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"_fillStart": 0,
|
||||||
|
"_fillRange": 0,
|
||||||
|
"_isTrimmedMode": true,
|
||||||
|
"_atlas": {
|
||||||
|
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
|
||||||
|
},
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.PrefabInfo",
|
||||||
|
"root": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"__uuid__": "230eeb1f-e0f9-4a41-ab6c-05b3771cbf3e"
|
||||||
|
},
|
||||||
|
"fileId": "50Mjaee6xFXLrZ/mSBD3P5",
|
||||||
|
"sync": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"__type__": "6a3d6Y6Ki1BiqAVSKIRdwRl",
|
"__type__": "6a3d6Y6Ki1BiqAVSKIRdwRl",
|
||||||
"_name": "",
|
"_name": "",
|
||||||
@@ -516,34 +643,6 @@
|
|||||||
},
|
},
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"__type__": "cc.Sprite",
|
|
||||||
"_name": "",
|
|
||||||
"_objFlags": 0,
|
|
||||||
"node": {
|
|
||||||
"__id__": 1
|
|
||||||
},
|
|
||||||
"_enabled": true,
|
|
||||||
"_spriteFrame": {
|
|
||||||
"__uuid__": "334d4f93-b007-49e8-9268-35891d4f4ebb"
|
|
||||||
},
|
|
||||||
"_type": 0,
|
|
||||||
"_sizeMode": 1,
|
|
||||||
"_fillType": 0,
|
|
||||||
"_fillCenter": {
|
|
||||||
"__type__": "cc.Vec2",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"_fillStart": 0,
|
|
||||||
"_fillRange": 0,
|
|
||||||
"_isTrimmedMode": true,
|
|
||||||
"_state": 0,
|
|
||||||
"_atlas": null,
|
|
||||||
"_srcBlendFactor": 770,
|
|
||||||
"_dstBlendFactor": 771,
|
|
||||||
"_id": ""
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__type__": "cc.PrefabInfo",
|
"__type__": "cc.PrefabInfo",
|
||||||
"root": {
|
"root": {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ver": "1.2.5",
|
"ver": "1.2.5",
|
||||||
"uuid": "3ed4c7bc-79d0-4075-a563-d5a58ae798f9",
|
"uuid": "dc804c5c-ff76-445e-ac69-52269055c3c5",
|
||||||
"optimizationPolicy": "AUTO",
|
"optimizationPolicy": "AUTO",
|
||||||
"asyncLoadAssets": false,
|
"asyncLoadAssets": false,
|
||||||
"readonly": false,
|
"readonly": false,
|
||||||
|
443
frontend/assets/resources/prefabs/Fireball.prefab
Normal file
@@ -0,0 +1,443 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"__type__": "cc.Prefab",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_native": "",
|
||||||
|
"data": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"optimizationPolicy": 0,
|
||||||
|
"asyncLoadAssets": false,
|
||||||
|
"readonly": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Node",
|
||||||
|
"_name": "Root",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_parent": null,
|
||||||
|
"_children": [
|
||||||
|
{
|
||||||
|
"__id__": 2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_active": true,
|
||||||
|
"_components": [
|
||||||
|
{
|
||||||
|
"__id__": 12
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_prefab": {
|
||||||
|
"__id__": 13
|
||||||
|
},
|
||||||
|
"_opacity": 255,
|
||||||
|
"_color": {
|
||||||
|
"__type__": "cc.Color",
|
||||||
|
"r": 255,
|
||||||
|
"g": 255,
|
||||||
|
"b": 255,
|
||||||
|
"a": 255
|
||||||
|
},
|
||||||
|
"_contentSize": {
|
||||||
|
"__type__": "cc.Size",
|
||||||
|
"width": 120,
|
||||||
|
"height": 120
|
||||||
|
},
|
||||||
|
"_anchorPoint": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0.5,
|
||||||
|
"y": 0.5
|
||||||
|
},
|
||||||
|
"_trs": {
|
||||||
|
"__type__": "TypedArray",
|
||||||
|
"ctor": "Float64Array",
|
||||||
|
"array": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 2,
|
||||||
|
"groupIndex": 2,
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Node",
|
||||||
|
"_name": "animNode",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_parent": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"_children": [
|
||||||
|
{
|
||||||
|
"__id__": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 7
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_active": true,
|
||||||
|
"_components": [],
|
||||||
|
"_prefab": {
|
||||||
|
"__id__": 11
|
||||||
|
},
|
||||||
|
"_opacity": 255,
|
||||||
|
"_color": {
|
||||||
|
"__type__": "cc.Color",
|
||||||
|
"r": 255,
|
||||||
|
"g": 255,
|
||||||
|
"b": 255,
|
||||||
|
"a": 255
|
||||||
|
},
|
||||||
|
"_contentSize": {
|
||||||
|
"__type__": "cc.Size",
|
||||||
|
"width": 0,
|
||||||
|
"height": 0
|
||||||
|
},
|
||||||
|
"_anchorPoint": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0.5,
|
||||||
|
"y": 0.5
|
||||||
|
},
|
||||||
|
"_trs": {
|
||||||
|
"__type__": "TypedArray",
|
||||||
|
"ctor": "Float64Array",
|
||||||
|
"array": [
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Node",
|
||||||
|
"_name": "Fireball1",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_parent": {
|
||||||
|
"__id__": 2
|
||||||
|
},
|
||||||
|
"_children": [],
|
||||||
|
"_active": false,
|
||||||
|
"_components": [
|
||||||
|
{
|
||||||
|
"__id__": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_prefab": {
|
||||||
|
"__id__": 6
|
||||||
|
},
|
||||||
|
"_opacity": 255,
|
||||||
|
"_color": {
|
||||||
|
"__type__": "cc.Color",
|
||||||
|
"r": 255,
|
||||||
|
"g": 255,
|
||||||
|
"b": 255,
|
||||||
|
"a": 255
|
||||||
|
},
|
||||||
|
"_contentSize": {
|
||||||
|
"__type__": "cc.Size",
|
||||||
|
"width": 117,
|
||||||
|
"height": 55
|
||||||
|
},
|
||||||
|
"_anchorPoint": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0.5,
|
||||||
|
"y": 0.5
|
||||||
|
},
|
||||||
|
"_trs": {
|
||||||
|
"__type__": "TypedArray",
|
||||||
|
"ctor": "Float64Array",
|
||||||
|
"array": [
|
||||||
|
-32,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Sprite",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"node": {
|
||||||
|
"__id__": 3
|
||||||
|
},
|
||||||
|
"_enabled": true,
|
||||||
|
"_materials": [
|
||||||
|
{
|
||||||
|
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_srcBlendFactor": 770,
|
||||||
|
"_dstBlendFactor": 771,
|
||||||
|
"_spriteFrame": null,
|
||||||
|
"_type": 0,
|
||||||
|
"_sizeMode": 1,
|
||||||
|
"_fillType": 0,
|
||||||
|
"_fillCenter": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"_fillStart": 0,
|
||||||
|
"_fillRange": 0,
|
||||||
|
"_isTrimmedMode": true,
|
||||||
|
"_atlas": {
|
||||||
|
"__uuid__": "6dcd5722-8ef9-47fd-9520-861d2713e274"
|
||||||
|
},
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Animation",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"node": {
|
||||||
|
"__id__": 3
|
||||||
|
},
|
||||||
|
"_enabled": true,
|
||||||
|
"_defaultClip": {
|
||||||
|
"__uuid__": "ba12416b-eec3-4260-8402-7fc25b125624"
|
||||||
|
},
|
||||||
|
"_clips": [
|
||||||
|
{
|
||||||
|
"__uuid__": "ba12416b-eec3-4260-8402-7fc25b125624"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__uuid__": "7941215a-2b8c-4798-954b-4f1b16d5f6f5"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"playOnLoad": false,
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.PrefabInfo",
|
||||||
|
"root": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
|
||||||
|
},
|
||||||
|
"fileId": "5f1s6pDt5F3rknJTu0gQW7",
|
||||||
|
"sync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Node",
|
||||||
|
"_name": "MeleeExplosion",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_parent": {
|
||||||
|
"__id__": 2
|
||||||
|
},
|
||||||
|
"_children": [],
|
||||||
|
"_active": false,
|
||||||
|
"_components": [
|
||||||
|
{
|
||||||
|
"__id__": 8
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__id__": 9
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_prefab": {
|
||||||
|
"__id__": 10
|
||||||
|
},
|
||||||
|
"_opacity": 255,
|
||||||
|
"_color": {
|
||||||
|
"__type__": "cc.Color",
|
||||||
|
"r": 255,
|
||||||
|
"g": 255,
|
||||||
|
"b": 255,
|
||||||
|
"a": 255
|
||||||
|
},
|
||||||
|
"_contentSize": {
|
||||||
|
"__type__": "cc.Size",
|
||||||
|
"width": 0,
|
||||||
|
"height": 0
|
||||||
|
},
|
||||||
|
"_anchorPoint": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0.5,
|
||||||
|
"y": 0.5
|
||||||
|
},
|
||||||
|
"_trs": {
|
||||||
|
"__type__": "TypedArray",
|
||||||
|
"ctor": "Float64Array",
|
||||||
|
"array": [
|
||||||
|
24,
|
||||||
|
8,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Animation",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"node": {
|
||||||
|
"__id__": 7
|
||||||
|
},
|
||||||
|
"_enabled": true,
|
||||||
|
"_defaultClip": null,
|
||||||
|
"_clips": [
|
||||||
|
{
|
||||||
|
"__uuid__": "954a2924-89df-4df4-93fc-36d2b22e7619"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__uuid__": "5bd304eb-c8ba-426f-a9ab-5698ac62de85"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__uuid__": "5054633c-a588-4506-b4ac-eef29b1d8511"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"playOnLoad": false,
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Sprite",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"node": {
|
||||||
|
"__id__": 7
|
||||||
|
},
|
||||||
|
"_enabled": true,
|
||||||
|
"_materials": [],
|
||||||
|
"_srcBlendFactor": 770,
|
||||||
|
"_dstBlendFactor": 771,
|
||||||
|
"_spriteFrame": null,
|
||||||
|
"_type": 0,
|
||||||
|
"_sizeMode": 1,
|
||||||
|
"_fillType": 0,
|
||||||
|
"_fillCenter": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"_fillStart": 0,
|
||||||
|
"_fillRange": 0,
|
||||||
|
"_isTrimmedMode": true,
|
||||||
|
"_atlas": {
|
||||||
|
"__uuid__": "1c4c1dcb-54af-485b-9119-abd6d6d84526"
|
||||||
|
},
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.PrefabInfo",
|
||||||
|
"root": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
|
||||||
|
},
|
||||||
|
"fileId": "fd9jQiClRJSI00917fifB8",
|
||||||
|
"sync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.PrefabInfo",
|
||||||
|
"root": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
|
||||||
|
},
|
||||||
|
"fileId": "3824oBeVVL1KOAQ6Zd9CC5",
|
||||||
|
"sync": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "e66a2qRmRZGnqSyVMwLy6Pw",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"node": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"_enabled": true,
|
||||||
|
"animNode": {
|
||||||
|
"__id__": 2
|
||||||
|
},
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.PrefabInfo",
|
||||||
|
"root": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
|
||||||
|
},
|
||||||
|
"fileId": "4cx75uwJJFa7U8QL187QCL",
|
||||||
|
"sync": false
|
||||||
|
}
|
||||||
|
]
|
8
frontend/assets/resources/prefabs/Fireball.prefab.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.2.5",
|
||||||
|
"uuid": "d92d4831-cd65-4eb5-90bd-b77021aec35b",
|
||||||
|
"optimizationPolicy": "AUTO",
|
||||||
|
"asyncLoadAssets": false,
|
||||||
|
"readonly": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -21,20 +21,20 @@
|
|||||||
"__id__": 2
|
"__id__": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 10
|
"__id__": 5
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 13
|
"__id__": 12
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 14
|
"__id__": 13
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 15
|
"__id__": 14
|
||||||
},
|
},
|
||||||
"_opacity": 255,
|
"_opacity": 255,
|
||||||
"_color": {
|
"_color": {
|
||||||
@@ -46,8 +46,72 @@
|
|||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
"width": 1024,
|
"width": 960,
|
||||||
"height": 1920
|
"height": 640
|
||||||
|
},
|
||||||
|
"_anchorPoint": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0.5,
|
||||||
|
"y": 0.5
|
||||||
|
},
|
||||||
|
"_trs": {
|
||||||
|
"__type__": "TypedArray",
|
||||||
|
"ctor": "Float64Array",
|
||||||
|
"array": [
|
||||||
|
480,
|
||||||
|
320,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Node",
|
||||||
|
"_name": "Background",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"_parent": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"_children": [],
|
||||||
|
"_active": true,
|
||||||
|
"_components": [
|
||||||
|
{
|
||||||
|
"__id__": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_prefab": {
|
||||||
|
"__id__": 4
|
||||||
|
},
|
||||||
|
"_opacity": 255,
|
||||||
|
"_color": {
|
||||||
|
"__type__": "cc.Color",
|
||||||
|
"r": 255,
|
||||||
|
"g": 255,
|
||||||
|
"b": 255,
|
||||||
|
"a": 255
|
||||||
|
},
|
||||||
|
"_contentSize": {
|
||||||
|
"__type__": "cc.Size",
|
||||||
|
"width": 1920,
|
||||||
|
"height": 1280
|
||||||
},
|
},
|
||||||
"_anchorPoint": {
|
"_anchorPoint": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
@@ -83,6 +147,51 @@
|
|||||||
"groupIndex": 0,
|
"groupIndex": 0,
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.Sprite",
|
||||||
|
"_name": "",
|
||||||
|
"_objFlags": 0,
|
||||||
|
"node": {
|
||||||
|
"__id__": 2
|
||||||
|
},
|
||||||
|
"_enabled": true,
|
||||||
|
"_materials": [
|
||||||
|
{
|
||||||
|
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"_srcBlendFactor": 770,
|
||||||
|
"_dstBlendFactor": 771,
|
||||||
|
"_spriteFrame": {
|
||||||
|
"__uuid__": "637f31c2-c53e-4dec-ae11-d56c0c6177ad"
|
||||||
|
},
|
||||||
|
"_type": 0,
|
||||||
|
"_sizeMode": 0,
|
||||||
|
"_fillType": 0,
|
||||||
|
"_fillCenter": {
|
||||||
|
"__type__": "cc.Vec2",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0
|
||||||
|
},
|
||||||
|
"_fillStart": 0,
|
||||||
|
"_fillRange": 0,
|
||||||
|
"_isTrimmedMode": true,
|
||||||
|
"_atlas": {
|
||||||
|
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
|
||||||
|
},
|
||||||
|
"_id": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"__type__": "cc.PrefabInfo",
|
||||||
|
"root": {
|
||||||
|
"__id__": 1
|
||||||
|
},
|
||||||
|
"asset": {
|
||||||
|
"__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109"
|
||||||
|
},
|
||||||
|
"fileId": "a7oR1cZvVO/pp9QJgLnJyt",
|
||||||
|
"sync": false
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Node",
|
"__type__": "cc.Node",
|
||||||
"_name": "modeButton",
|
"_name": "modeButton",
|
||||||
@@ -92,20 +201,20 @@
|
|||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 3
|
"__id__": 6
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 7
|
"__id__": 9
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 8
|
"__id__": 10
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 9
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_opacity": 255,
|
"_opacity": 255,
|
||||||
"_color": {
|
"_color": {
|
||||||
@@ -117,8 +226,8 @@
|
|||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
"width": 280,
|
"width": 240,
|
||||||
"height": 130
|
"height": 100
|
||||||
},
|
},
|
||||||
"_anchorPoint": {
|
"_anchorPoint": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
@@ -130,7 +239,7 @@
|
|||||||
"ctor": "Float64Array",
|
"ctor": "Float64Array",
|
||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
-564,
|
-90.495,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -159,20 +268,17 @@
|
|||||||
"_name": "Label",
|
"_name": "Label",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 2
|
"__id__": 5
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 4
|
"__id__": 7
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 5
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 6
|
"__id__": 8
|
||||||
},
|
},
|
||||||
"_opacity": 255,
|
"_opacity": 255,
|
||||||
"_color": {
|
"_color": {
|
||||||
@@ -226,7 +332,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 3
|
"__id__": 6
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@@ -235,8 +341,8 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_useOriginalSize": false,
|
"_useOriginalSize": false,
|
||||||
"_string": "gameRule.mode",
|
"_string": "1 v 1",
|
||||||
"_N$string": "gameRule.mode",
|
"_N$string": "1 v 1",
|
||||||
"_fontSize": 55,
|
"_fontSize": 55,
|
||||||
"_lineHeight": 50,
|
"_lineHeight": 50,
|
||||||
"_enableWrapText": false,
|
"_enableWrapText": false,
|
||||||
@@ -251,17 +357,6 @@
|
|||||||
"_N$cacheMode": 0,
|
"_N$cacheMode": 0,
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"__type__": "744dcs4DCdNprNhG0xwq6FK",
|
|
||||||
"_name": "",
|
|
||||||
"_objFlags": 0,
|
|
||||||
"node": {
|
|
||||||
"__id__": 3
|
|
||||||
},
|
|
||||||
"_enabled": true,
|
|
||||||
"_dataID": "gameRule.mode",
|
|
||||||
"_id": ""
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__type__": "cc.PrefabInfo",
|
"__type__": "cc.PrefabInfo",
|
||||||
"root": {
|
"root": {
|
||||||
@@ -278,7 +373,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 2
|
"__id__": 5
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@@ -312,7 +407,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 2
|
"__id__": 5
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_normalMaterial": null,
|
"_normalMaterial": null,
|
||||||
@@ -375,7 +470,7 @@
|
|||||||
"hoverSprite": null,
|
"hoverSprite": null,
|
||||||
"_N$disabledSprite": null,
|
"_N$disabledSprite": null,
|
||||||
"_N$target": {
|
"_N$target": {
|
||||||
"__id__": 2
|
"__id__": 5
|
||||||
},
|
},
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
@@ -390,115 +485,6 @@
|
|||||||
"fileId": "c54lqSflFD8ogSYAhsAkKh",
|
"fileId": "c54lqSflFD8ogSYAhsAkKh",
|
||||||
"sync": false
|
"sync": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"__type__": "cc.Node",
|
|
||||||
"_name": "decoration",
|
|
||||||
"_objFlags": 0,
|
|
||||||
"_parent": {
|
|
||||||
"__id__": 1
|
|
||||||
},
|
|
||||||
"_children": [],
|
|
||||||
"_active": true,
|
|
||||||
"_components": [
|
|
||||||
{
|
|
||||||
"__id__": 11
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"_prefab": {
|
|
||||||
"__id__": 12
|
|
||||||
},
|
|
||||||
"_opacity": 255,
|
|
||||||
"_color": {
|
|
||||||
"__type__": "cc.Color",
|
|
||||||
"r": 255,
|
|
||||||
"g": 255,
|
|
||||||
"b": 255,
|
|
||||||
"a": 255
|
|
||||||
},
|
|
||||||
"_contentSize": {
|
|
||||||
"__type__": "cc.Size",
|
|
||||||
"width": 543,
|
|
||||||
"height": 117
|
|
||||||
},
|
|
||||||
"_anchorPoint": {
|
|
||||||
"__type__": "cc.Vec2",
|
|
||||||
"x": 0.5,
|
|
||||||
"y": 0.5
|
|
||||||
},
|
|
||||||
"_trs": {
|
|
||||||
"__type__": "TypedArray",
|
|
||||||
"ctor": "Float64Array",
|
|
||||||
"array": [
|
|
||||||
0,
|
|
||||||
-312,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"_eulerAngles": {
|
|
||||||
"__type__": "cc.Vec3",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"z": 0
|
|
||||||
},
|
|
||||||
"_skewX": 0,
|
|
||||||
"_skewY": 0,
|
|
||||||
"_is3DNode": false,
|
|
||||||
"_groupIndex": 0,
|
|
||||||
"groupIndex": 0,
|
|
||||||
"_id": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__type__": "cc.Sprite",
|
|
||||||
"_name": "",
|
|
||||||
"_objFlags": 0,
|
|
||||||
"node": {
|
|
||||||
"__id__": 10
|
|
||||||
},
|
|
||||||
"_enabled": true,
|
|
||||||
"_materials": [
|
|
||||||
{
|
|
||||||
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"_srcBlendFactor": 770,
|
|
||||||
"_dstBlendFactor": 771,
|
|
||||||
"_spriteFrame": {
|
|
||||||
"__uuid__": "153d890a-fc37-4d59-8779-93a8fb19fa85"
|
|
||||||
},
|
|
||||||
"_type": 0,
|
|
||||||
"_sizeMode": 1,
|
|
||||||
"_fillType": 0,
|
|
||||||
"_fillCenter": {
|
|
||||||
"__type__": "cc.Vec2",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0
|
|
||||||
},
|
|
||||||
"_fillStart": 0,
|
|
||||||
"_fillRange": 0,
|
|
||||||
"_isTrimmedMode": true,
|
|
||||||
"_atlas": {
|
|
||||||
"__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4"
|
|
||||||
},
|
|
||||||
"_id": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"__type__": "cc.PrefabInfo",
|
|
||||||
"root": {
|
|
||||||
"__id__": 1
|
|
||||||
},
|
|
||||||
"asset": {
|
|
||||||
"__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109"
|
|
||||||
},
|
|
||||||
"fileId": "1bbMLAzntHZpEudL8lM/Lx",
|
|
||||||
"sync": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__type__": "dd92bKVy8FJY7uq3ieoNZCZ",
|
"__type__": "dd92bKVy8FJY7uq3ieoNZCZ",
|
||||||
"_name": "",
|
"_name": "",
|
||||||
@@ -508,41 +494,36 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"modeButton": {
|
"modeButton": {
|
||||||
"__id__": 8
|
"__id__": 10
|
||||||
},
|
},
|
||||||
"mapNode": null,
|
"mapNode": null,
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Sprite",
|
"__type__": "cc.Widget",
|
||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 1
|
"__id__": 1
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"alignMode": 1,
|
||||||
{
|
"_target": null,
|
||||||
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
"_alignFlags": 18,
|
||||||
}
|
"_left": 0,
|
||||||
],
|
"_right": 0,
|
||||||
"_srcBlendFactor": 770,
|
"_top": 0,
|
||||||
"_dstBlendFactor": 771,
|
"_bottom": 0,
|
||||||
"_spriteFrame": {
|
"_verticalCenter": 0,
|
||||||
"__uuid__": "7838f276-ab48-445a-b858-937dd27d9520"
|
"_horizontalCenter": 0,
|
||||||
},
|
"_isAbsLeft": true,
|
||||||
"_type": 0,
|
"_isAbsRight": true,
|
||||||
"_sizeMode": 0,
|
"_isAbsTop": true,
|
||||||
"_fillType": 0,
|
"_isAbsBottom": true,
|
||||||
"_fillCenter": {
|
"_isAbsHorizontalCenter": true,
|
||||||
"__type__": "cc.Vec2",
|
"_isAbsVerticalCenter": true,
|
||||||
"x": 0,
|
"_originalWidth": 0,
|
||||||
"y": 0
|
"_originalHeight": 0,
|
||||||
},
|
|
||||||
"_fillStart": 0,
|
|
||||||
"_fillRange": 0,
|
|
||||||
"_isTrimmedMode": true,
|
|
||||||
"_atlas": null,
|
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@@ -8,7 +8,8 @@
|
|||||||
"__id__": 1
|
"__id__": 1
|
||||||
},
|
},
|
||||||
"optimizationPolicy": 0,
|
"optimizationPolicy": 0,
|
||||||
"asyncLoadAssets": false
|
"asyncLoadAssets": false,
|
||||||
|
"readonly": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Node",
|
"__type__": "cc.Node",
|
||||||
@@ -20,18 +21,17 @@
|
|||||||
"__id__": 2
|
"__id__": 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 6
|
"__id__": 5
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_level": 1,
|
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 9
|
"__id__": 8
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 10
|
"__id__": 9
|
||||||
},
|
},
|
||||||
"_opacity": 255,
|
"_opacity": 255,
|
||||||
"_color": {
|
"_color": {
|
||||||
@@ -51,24 +51,12 @@
|
|||||||
"x": 0.5,
|
"x": 0.5,
|
||||||
"y": 0.5
|
"y": 0.5
|
||||||
},
|
},
|
||||||
"_quat": {
|
|
||||||
"__type__": "cc.Quat",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"z": 0,
|
|
||||||
"w": 1
|
|
||||||
},
|
|
||||||
"_skewX": 0,
|
|
||||||
"_skewY": 0,
|
|
||||||
"_zIndex": 0,
|
|
||||||
"groupIndex": 0,
|
|
||||||
"_id": "",
|
|
||||||
"_trs": {
|
"_trs": {
|
||||||
"__type__": "TypedArray",
|
"__type__": "TypedArray",
|
||||||
"ctor": "Float64Array",
|
"ctor": "Float64Array",
|
||||||
"array": [
|
"array": [
|
||||||
512,
|
480,
|
||||||
0,
|
480,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -78,7 +66,19 @@
|
|||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Node",
|
"__type__": "cc.Node",
|
||||||
@@ -89,17 +89,13 @@
|
|||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_level": 0,
|
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 3
|
"__id__": 3
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 4
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 5
|
"__id__": 4
|
||||||
},
|
},
|
||||||
"_opacity": 255,
|
"_opacity": 255,
|
||||||
"_color": {
|
"_color": {
|
||||||
@@ -111,32 +107,20 @@
|
|||||||
},
|
},
|
||||||
"_contentSize": {
|
"_contentSize": {
|
||||||
"__type__": "cc.Size",
|
"__type__": "cc.Size",
|
||||||
"width": 303.5,
|
"width": 805.7,
|
||||||
"height": 30
|
"height": 35.28
|
||||||
},
|
},
|
||||||
"_anchorPoint": {
|
"_anchorPoint": {
|
||||||
"__type__": "cc.Vec2",
|
"__type__": "cc.Vec2",
|
||||||
"x": 0.5,
|
"x": 0.5,
|
||||||
"y": 0.5
|
"y": 0.5
|
||||||
},
|
},
|
||||||
"_quat": {
|
|
||||||
"__type__": "cc.Quat",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"z": 0,
|
|
||||||
"w": 1
|
|
||||||
},
|
|
||||||
"_skewX": 0,
|
|
||||||
"_skewY": 0,
|
|
||||||
"_zIndex": 0,
|
|
||||||
"groupIndex": 0,
|
|
||||||
"_id": "",
|
|
||||||
"_trs": {
|
"_trs": {
|
||||||
"__type__": "TypedArray",
|
"__type__": "TypedArray",
|
||||||
"ctor": "Float64Array",
|
"ctor": "Float64Array",
|
||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
210,
|
-150,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -146,7 +130,19 @@
|
|||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Label",
|
"__type__": "cc.Label",
|
||||||
@@ -156,32 +152,26 @@
|
|||||||
"__id__": 2
|
"__id__": 2
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_srcBlendFactor": 1,
|
"_materials": [
|
||||||
"_dstBlendFactor": 771,
|
{
|
||||||
|
"__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432"
|
||||||
|
}
|
||||||
|
],
|
||||||
"_useOriginalSize": false,
|
"_useOriginalSize": false,
|
||||||
"_string": "login.tips.loginSuccess",
|
"_string": "Logged in successfully, loading game resources...",
|
||||||
"_N$string": "login.tips.loginSuccess",
|
"_N$string": "Logged in successfully, loading game resources...",
|
||||||
"_fontSize": 30,
|
"_fontSize": 28,
|
||||||
"_lineHeight": 30,
|
"_lineHeight": 28,
|
||||||
"_enableWrapText": true,
|
"_enableWrapText": true,
|
||||||
"_N$file": null,
|
"_N$file": null,
|
||||||
"_isSystemFontUsed": true,
|
"_isSystemFontUsed": true,
|
||||||
"_spacingX": 0,
|
"_spacingX": 0,
|
||||||
|
"_batchAsBitmap": false,
|
||||||
"_N$horizontalAlign": 1,
|
"_N$horizontalAlign": 1,
|
||||||
"_N$verticalAlign": 1,
|
"_N$verticalAlign": 1,
|
||||||
"_N$fontFamily": "Arial",
|
"_N$fontFamily": "Arial",
|
||||||
"_N$overflow": 0,
|
"_N$overflow": 3,
|
||||||
"_id": ""
|
"_N$cacheMode": 0,
|
||||||
},
|
|
||||||
{
|
|
||||||
"__type__": "744dcs4DCdNprNhG0xwq6FK",
|
|
||||||
"_name": "",
|
|
||||||
"_objFlags": 0,
|
|
||||||
"node": {
|
|
||||||
"__id__": 2
|
|
||||||
},
|
|
||||||
"_enabled": true,
|
|
||||||
"_dataID": "login.tips.loginSuccess",
|
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -204,14 +194,13 @@
|
|||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_level": 0,
|
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 7
|
"__id__": 6
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": {
|
"_prefab": {
|
||||||
"__id__": 8
|
"__id__": 7
|
||||||
},
|
},
|
||||||
"_opacity": 255,
|
"_opacity": 255,
|
||||||
"_color": {
|
"_color": {
|
||||||
@@ -231,24 +220,12 @@
|
|||||||
"x": 0.5,
|
"x": 0.5,
|
||||||
"y": 0.5
|
"y": 0.5
|
||||||
},
|
},
|
||||||
"_quat": {
|
|
||||||
"__type__": "cc.Quat",
|
|
||||||
"x": 0,
|
|
||||||
"y": 0,
|
|
||||||
"z": 0,
|
|
||||||
"w": 1
|
|
||||||
},
|
|
||||||
"_skewX": 0,
|
|
||||||
"_skewY": 0,
|
|
||||||
"_zIndex": 0,
|
|
||||||
"groupIndex": 0,
|
|
||||||
"_id": "",
|
|
||||||
"_trs": {
|
"_trs": {
|
||||||
"__type__": "TypedArray",
|
"__type__": "TypedArray",
|
||||||
"ctor": "Float64Array",
|
"ctor": "Float64Array",
|
||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
333,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@@ -258,16 +235,29 @@
|
|||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"_eulerAngles": {
|
||||||
|
"__type__": "cc.Vec3",
|
||||||
|
"x": 0,
|
||||||
|
"y": 0,
|
||||||
|
"z": 0
|
||||||
|
},
|
||||||
|
"_skewX": 0,
|
||||||
|
"_skewY": 0,
|
||||||
|
"_is3DNode": false,
|
||||||
|
"_groupIndex": 0,
|
||||||
|
"groupIndex": 0,
|
||||||
|
"_id": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__type__": "cc.Sprite",
|
"__type__": "cc.Sprite",
|
||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 6
|
"__id__": 5
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
|
"_materials": [],
|
||||||
"_srcBlendFactor": 770,
|
"_srcBlendFactor": 770,
|
||||||
"_dstBlendFactor": 771,
|
"_dstBlendFactor": 771,
|
||||||
"_spriteFrame": null,
|
"_spriteFrame": null,
|
||||||
@@ -282,7 +272,6 @@
|
|||||||
"_fillStart": 0,
|
"_fillStart": 0,
|
||||||
"_fillRange": 0,
|
"_fillRange": 0,
|
||||||
"_isTrimmedMode": true,
|
"_isTrimmedMode": true,
|
||||||
"_state": 0,
|
|
||||||
"_atlas": null,
|
"_atlas": null,
|
||||||
"_id": ""
|
"_id": ""
|
||||||
},
|
},
|
||||||
@@ -307,7 +296,7 @@
|
|||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"alignMode": 0,
|
"alignMode": 0,
|
||||||
"_target": null,
|
"_target": null,
|
||||||
"_alignFlags": 20,
|
"_alignFlags": 18,
|
||||||
"_left": 0,
|
"_left": 0,
|
||||||
"_right": 0,
|
"_right": 0,
|
||||||
"_top": 0,
|
"_top": 0,
|
||||||
|
Before Width: | Height: | Size: 121 KiB |
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"ver": "2.3.3",
|
|
||||||
"uuid": "825df908-a4cb-449d-9731-8ef53f3fd44f",
|
|
||||||
"type": "sprite",
|
|
||||||
"wrapMode": "clamp",
|
|
||||||
"filterMode": "bilinear",
|
|
||||||
"premultiplyAlpha": false,
|
|
||||||
"genMipmaps": false,
|
|
||||||
"packable": true,
|
|
||||||
"platformSettings": {},
|
|
||||||
"subMetas": {
|
|
||||||
"MiniGame_Background": {
|
|
||||||
"ver": "1.0.4",
|
|
||||||
"uuid": "7838f276-ab48-445a-b858-937dd27d9520",
|
|
||||||
"rawTextureUuid": "825df908-a4cb-449d-9731-8ef53f3fd44f",
|
|
||||||
"trimType": "auto",
|
|
||||||
"trimThreshold": 1,
|
|
||||||
"rotated": false,
|
|
||||||
"offsetX": 0,
|
|
||||||
"offsetY": 0,
|
|
||||||
"trimX": 0,
|
|
||||||
"trimY": 0,
|
|
||||||
"width": 750,
|
|
||||||
"height": 1624,
|
|
||||||
"rawWidth": 750,
|
|
||||||
"rawHeight": 1624,
|
|
||||||
"borderTop": 0,
|
|
||||||
"borderBottom": 0,
|
|
||||||
"borderLeft": 0,
|
|
||||||
"borderRight": 0,
|
|
||||||
"subMetas": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Before Width: | Height: | Size: 95 KiB |
@@ -1,34 +0,0 @@
|
|||||||
{
|
|
||||||
"ver": "2.3.3",
|
|
||||||
"uuid": "94b8bb09-e8ac-4402-a933-b79f01b5a813",
|
|
||||||
"type": "sprite",
|
|
||||||
"wrapMode": "clamp",
|
|
||||||
"filterMode": "bilinear",
|
|
||||||
"premultiplyAlpha": false,
|
|
||||||
"genMipmaps": false,
|
|
||||||
"packable": true,
|
|
||||||
"platformSettings": {},
|
|
||||||
"subMetas": {
|
|
||||||
"MiniGame_Blackboard": {
|
|
||||||
"ver": "1.0.4",
|
|
||||||
"uuid": "334d4f93-b007-49e8-9268-35891d4f4ebb",
|
|
||||||
"rawTextureUuid": "94b8bb09-e8ac-4402-a933-b79f01b5a813",
|
|
||||||
"trimType": "auto",
|
|
||||||
"trimThreshold": 1,
|
|
||||||
"rotated": false,
|
|
||||||
"offsetX": 0,
|
|
||||||
"offsetY": 0,
|
|
||||||
"trimX": 0,
|
|
||||||
"trimY": 0,
|
|
||||||
"width": 1024,
|
|
||||||
"height": 1920,
|
|
||||||
"rawWidth": 1024,
|
|
||||||
"rawHeight": 1920,
|
|
||||||
"borderTop": 0,
|
|
||||||
"borderBottom": 0,
|
|
||||||
"borderLeft": 0,
|
|
||||||
"borderRight": 0,
|
|
||||||
"subMetas": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -15,6 +15,10 @@ window.ATK_CHARACTER_STATE = {
|
|||||||
Atk2: [11, "Atk2"],
|
Atk2: [11, "Atk2"],
|
||||||
Atk3: [12, "Atk3"],
|
Atk3: [12, "Atk3"],
|
||||||
Atk4: [13, "Atk4"],
|
Atk4: [13, "Atk4"],
|
||||||
|
Atk5: [14, "Atk5"],
|
||||||
|
Dashing: [15, "Dashing"],
|
||||||
|
OnWall: [16, "OnWall"],
|
||||||
|
TurnAround1: [17, "TurnAround1"],
|
||||||
};
|
};
|
||||||
|
|
||||||
window.ATK_CHARACTER_STATE_ARR = [];
|
window.ATK_CHARACTER_STATE_ARR = [];
|
||||||
@@ -30,6 +34,8 @@ window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.In
|
|||||||
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]);
|
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]);
|
||||||
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.LayDown1[0]);
|
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.LayDown1[0]);
|
||||||
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.GetUp1[0]);
|
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.GetUp1[0]);
|
||||||
|
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.Dashing[0]);
|
||||||
|
window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.add(window.ATK_CHARACTER_STATE.OnWall[0]);
|
||||||
|
|
||||||
window.ATK_CHARACTER_STATE_IN_AIR_SET = new Set();
|
window.ATK_CHARACTER_STATE_IN_AIR_SET = new Set();
|
||||||
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0]);
|
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0]);
|
||||||
@@ -37,6 +43,7 @@ window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirIdle1B
|
|||||||
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtk1[0]);
|
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtk1[0]);
|
||||||
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtked1[0]);
|
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.InAirAtked1[0]);
|
||||||
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]);
|
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.BlownUp1[0]);
|
||||||
|
window.ATK_CHARACTER_STATE_IN_AIR_SET.add(window.ATK_CHARACTER_STATE.OnWall[0]);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Kindly note that the use of dragonBones anim is an informed choice for the feasibility of "gotoAndPlayByFrame", which is a required feature by "Map.rollbackAndChase". You might find that "cc.Animation" -- the traditional frame anim -- can also suffice this requirement, yet if we want to develop 3D frontend in the future, working with skeletal anim will make a smoother transition.
|
Kindly note that the use of dragonBones anim is an informed choice for the feasibility of "gotoAndPlayByFrame", which is a required feature by "Map.rollbackAndChase". You might find that "cc.Animation" -- the traditional frame anim -- can also suffice this requirement, yet if we want to develop 3D frontend in the future, working with skeletal anim will make a smoother transition.
|
||||||
@@ -68,37 +75,45 @@ cc.Class({
|
|||||||
onLoad() {
|
onLoad() {
|
||||||
BaseCharacter.prototype.onLoad.call(this);
|
BaseCharacter.prototype.onLoad.call(this);
|
||||||
this.effAnimNode = this.animNode.getChildByName(this.speciesName);
|
this.effAnimNode = this.animNode.getChildByName(this.speciesName);
|
||||||
this.animComp = this.effAnimNode.getComponent(dragonBones.ArmatureDisplay);
|
//this.animComp = this.effAnimNode.getComponent(dragonBones.ArmatureDisplay);
|
||||||
if (!this.animComp) {
|
//if (!this.animComp) {
|
||||||
this.animComp = this.effAnimNode.getComponent(cc.Animation);
|
this.animComp = this.effAnimNode.getComponent(cc.Animation);
|
||||||
}
|
//}
|
||||||
this.effAnimNode.active = true;
|
this.effAnimNode.active = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
updateCharacterAnim(rdfPlayer, prevRdfPlayer, forceAnimSwitch, chConfig) {
|
updateCharacterAnim(rdfPlayer, prevRdfPlayer, forceAnimSwitch, chConfig) {
|
||||||
// As this function might be called after many frames of a rollback, it's possible that the playing animation was predicted, different from "prevRdfPlayer.CharacterState" but same as "newCharacterState". More granular checks are needed to determine whether we should interrupt the playing animation.
|
// As this function might be called after many frames of a rollback, it's possible that the playing animation was predicted, different from "prevRdfPlayer.CharacterState" but same as "newCharacterState". More granular checks are needed to determine whether we should interrupt the playing animation.
|
||||||
|
|
||||||
|
let newCharacterState = rdfPlayer.CharacterState;
|
||||||
|
|
||||||
// Update directions
|
// Update directions
|
||||||
if (this.animComp && this.animComp.node) {
|
if (this.animComp && this.animComp.node) {
|
||||||
if (0 > rdfPlayer.DirX) {
|
if (0 > rdfPlayer.DirX) {
|
||||||
this.animNode.scaleX = (-1.0);
|
this.animNode.scaleX = (-1.0);
|
||||||
} else if (0 < rdfPlayer.DirX) {
|
} else if (0 < rdfPlayer.DirX) {
|
||||||
this.animNode.scaleX = (1.0);
|
this.animNode.scaleX = (+1.0);
|
||||||
|
}
|
||||||
|
if (ATK_CHARACTER_STATE.OnWall[0] == newCharacterState || ATK_CHARACTER_STATE.TurnAround1[0] == newCharacterState) {
|
||||||
|
if (0 < rdfPlayer.OnWallNormX) {
|
||||||
|
this.animNode.scaleX = (-1.0);
|
||||||
|
} else {
|
||||||
|
this.animNode.scaleX = (+1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let newCharacterState = rdfPlayer.CharacterState;
|
|
||||||
let newAnimName = window.ATK_CHARACTER_STATE_ARR[newCharacterState][1];
|
let newAnimName = window.ATK_CHARACTER_STATE_ARR[newCharacterState][1];
|
||||||
let playingAnimName = null;
|
let playingAnimName = null;
|
||||||
let underlyingAnimationCtrl = null;
|
let underlyingAnimationCtrl = null;
|
||||||
|
|
||||||
if (this.animComp instanceof dragonBones.ArmatureDisplay) {
|
//if (this.animComp instanceof dragonBones.ArmatureDisplay) {
|
||||||
underlyingAnimationCtrl = this.animComp._armature.animation; // ALWAYS use the dragonBones api instead of ccc's wrapper!
|
// underlyingAnimationCtrl = this.animComp._armature.animation; // ALWAYS use the dragonBones api instead of ccc's wrapper!
|
||||||
playingAnimName = underlyingAnimationCtrl.lastAnimationName;
|
// playingAnimName = underlyingAnimationCtrl.lastAnimationName;
|
||||||
} else {
|
//} else {
|
||||||
underlyingAnimationCtrl = this.animComp.currentClip;
|
underlyingAnimationCtrl = this.animComp.currentClip;
|
||||||
playingAnimName = (!underlyingAnimationCtrl ? null : underlyingAnimationCtrl.name);
|
playingAnimName = (!underlyingAnimationCtrl ? null : underlyingAnimationCtrl.name);
|
||||||
}
|
//}
|
||||||
|
|
||||||
// It turns out that "prevRdfPlayer.CharacterState" is not useful in this function :)
|
// It turns out that "prevRdfPlayer.CharacterState" is not useful in this function :)
|
||||||
if (newAnimName == playingAnimName && window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.has(newCharacterState)) {
|
if (newAnimName == playingAnimName && window.ATK_CHARACTER_STATE_INTERRUPT_WAIVE_SET.has(newCharacterState)) {
|
||||||
@@ -107,11 +122,11 @@ cc.Class({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.animComp instanceof dragonBones.ArmatureDisplay) {
|
//if (this.animComp instanceof dragonBones.ArmatureDisplay) {
|
||||||
this._interruptPlayingAnimAndPlayNewAnimDragonBones(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, underlyingAnimationCtrl, playingAnimName, chConfig);
|
// this._interruptPlayingAnimAndPlayNewAnimDragonBones(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, underlyingAnimationCtrl, playingAnimName, chConfig);
|
||||||
} else {
|
//} else {
|
||||||
this._interruptPlayingAnimAndPlayNewAnimFrameAnim(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, playingAnimName, chConfig);
|
this._interruptPlayingAnimAndPlayNewAnimFrameAnim(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, playingAnimName, chConfig);
|
||||||
}
|
//}
|
||||||
},
|
},
|
||||||
|
|
||||||
_interruptPlayingAnimAndPlayNewAnimDragonBones(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, underlyingAnimationCtrl, playingAnimName, chConfig) {
|
_interruptPlayingAnimAndPlayNewAnimDragonBones(rdfPlayer, prevRdfPlayer, newCharacterState, newAnimName, underlyingAnimationCtrl, playingAnimName, chConfig) {
|
||||||
|
36
frontend/assets/scripts/Bullet.js
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
window.BULLET_STATE = {
|
||||||
|
Startup: 0,
|
||||||
|
Active: 1,
|
||||||
|
Exploding: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
cc.Class({
|
||||||
|
extends: cc.Component,
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
animNode: {
|
||||||
|
type: cc.Node,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
updateAnim(newAnimName, frameIdxInAnim, dirX, spontaneousLooping, rdf, newAnimIdx) {
|
||||||
|
this.animComp = this.effAnimNode.getComponent(cc.Animation);
|
||||||
|
// Update directions
|
||||||
|
if (this.animComp && this.animComp.node) {
|
||||||
|
if (0 > dirX) {
|
||||||
|
this.animNode.scaleX = (-1.0);
|
||||||
|
} else if (0 < dirX) {
|
||||||
|
this.animNode.scaleX = (1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentClip = this.animComp.currentClip;
|
||||||
|
if (true == spontaneousLooping && (null != currentClip && currentClip.name == newAnimName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const targetClip = this.animComp.getClips()[newAnimIdx];
|
||||||
|
let fromTime = (frameIdxInAnim / targetClip.sample); // TODO: Anyway to avoid using division here?
|
||||||
|
this.animComp.play(newAnimName, fromTime);
|
||||||
|
},
|
||||||
|
});
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ver": "1.0.5",
|
"ver": "1.0.5",
|
||||||
"uuid": "247b7613-6c6e-4f01-b1d6-5f8f041b5688",
|
"uuid": "a4b909c4-56a8-4b70-b6ea-b7f928077747",
|
||||||
"isPlugin": false,
|
"isPlugin": false,
|
||||||
"loadPluginInWeb": true,
|
"loadPluginInWeb": true,
|
||||||
"loadPluginInNative": true,
|
"loadPluginInNative": true,
|
@@ -12,7 +12,7 @@ cc.Class({
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
onLoad () {
|
onLoad() {
|
||||||
this.mainCamera = this.mapNode.parent.getChildByName("Main Camera").getComponent(cc.Camera);
|
this.mainCamera = this.mapNode.parent.getChildByName("Main Camera").getComponent(cc.Camera);
|
||||||
this.mapScriptIns = this.mapNode.getComponent("Map");
|
this.mapScriptIns = this.mapNode.getComponent("Map");
|
||||||
},
|
},
|
||||||
@@ -29,9 +29,15 @@ cc.Class({
|
|||||||
if (!selfPlayerRichInfo) return;
|
if (!selfPlayerRichInfo) return;
|
||||||
const selfPlayerNode = selfPlayerRichInfo.node;
|
const selfPlayerNode = selfPlayerRichInfo.node;
|
||||||
if (!selfPlayerNode) return;
|
if (!selfPlayerNode) return;
|
||||||
const pDiff = selfPlayerNode.position.sub(self.mainCamera.node.position);
|
const dst = cc.v2().sub(selfPlayerNode.position);
|
||||||
|
const pDiff = dst.sub(self.mapNode.position);
|
||||||
|
const stepLength = dt * self.speed;
|
||||||
|
if (stepLength > pDiff.mag()) {
|
||||||
|
self.mapNode.setPosition(dst);
|
||||||
|
} else {
|
||||||
pDiff.normalizeSelf();
|
pDiff.normalizeSelf();
|
||||||
const newCamPos = self.mainCamera.node.position.add(pDiff.mul(dt*self.speed));
|
const newMapPos = self.mapNode.position.add(pDiff.mul(dt * self.speed));
|
||||||
self.mainCamera.node.setPosition(newCamPos);
|
self.mapNode.setPosition(newMapPos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -14,10 +14,6 @@ cc.Class({
|
|||||||
type: cc.Node,
|
type: cc.Node,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
myAvatarNode: {
|
|
||||||
type: cc.Node,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
exitBtnNode: {
|
exitBtnNode: {
|
||||||
type: cc.Node,
|
type: cc.Node,
|
||||||
default: null
|
default: null
|
||||||
@@ -25,10 +21,10 @@ cc.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
// LIFE-CYCLE CALLBACKS:
|
// LIFE-CYCLE CALLBACKS:
|
||||||
onLoad() {
|
onLoad() {},
|
||||||
},
|
|
||||||
|
|
||||||
init() {
|
init(mapIns) {
|
||||||
|
this.mapIns = mapIns;
|
||||||
if (null != this.firstPlayerInfoNode) {
|
if (null != this.firstPlayerInfoNode) {
|
||||||
this.firstPlayerInfoNode.active = false;
|
this.firstPlayerInfoNode.active = false;
|
||||||
}
|
}
|
||||||
@@ -58,9 +54,10 @@ cc.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
exitBtnOnClick(evt) {
|
exitBtnOnClick(evt) {
|
||||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
this.mapIns.hideFindingPlayersGUI();
|
||||||
window.closeWSConnection();
|
cc.log(`FindingPlayers.exitBtnOnClick`);
|
||||||
cc.director.loadScene('login');
|
window.closeWSConnection(constants.RET_CODE.BATTLE_STOPPED, "");
|
||||||
|
window.clearLocalStorageAndBackToLoginScene(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
updatePlayersInfo(playerMetas) {
|
updatePlayersInfo(playerMetas) {
|
||||||
@@ -79,20 +76,11 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//显示自己的头像名称以及他人的头像名称
|
|
||||||
for (let i in playerMetas) {
|
for (let i in playerMetas) {
|
||||||
const playerMeta = playerMetas[i];
|
const playerMeta = playerMetas[i];
|
||||||
console.log("Showing playerMeta:", playerMeta);
|
console.log("Showing playerMeta:", playerMeta);
|
||||||
const playerInfoNode = this.playersInfoNode[playerMeta.joinIndex];
|
const playerInfoNode = this.playersInfoNode[playerMeta.joinIndex];
|
||||||
|
|
||||||
(() => { //远程加载头像
|
|
||||||
let remoteUrl = playerMeta.avatar;
|
|
||||||
if (remoteUrl == null || remoteUrl == '') {
|
|
||||||
cc.log(`No avatar to show for :`);
|
|
||||||
cc.log(playerMeta);
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
function isEmptyString(str) {
|
function isEmptyString(str) {
|
||||||
return str == null || str == ''
|
return str == null || str == ''
|
||||||
}
|
}
|
||||||
|
29
frontend/assets/scripts/Fireball.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
const Bullet = require("./Bullet");
|
||||||
|
|
||||||
|
cc.Class({
|
||||||
|
extends: Bullet,
|
||||||
|
|
||||||
|
ctor() {
|
||||||
|
this.lastUsed = -1;
|
||||||
|
this.bulletLocalId = -1;
|
||||||
|
this.speciesName = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
setSpecies(speciesName, fireballBullet, rdf) {
|
||||||
|
if (speciesName == this.speciesName) return;
|
||||||
|
if (null != this.speciesName) {
|
||||||
|
for (let k in this.animNode.children) {
|
||||||
|
const child = this.children[k];
|
||||||
|
if (!child.active) continue;
|
||||||
|
if (child == effAnimNode || child.name == speciesName) continue;
|
||||||
|
child.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.speciesName = speciesName;
|
||||||
|
this.effAnimNode = this.animNode.getChildByName(this.speciesName);
|
||||||
|
this.effAnimNode.active = true;
|
||||||
|
},
|
||||||
|
|
||||||
|
onLoad() {},
|
||||||
|
|
||||||
|
});
|
9
frontend/assets/scripts/Fireball.js.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.5",
|
||||||
|
"uuid": "e66a2a91-9916-469e-a4b2-54cc0bcba3f0",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -68,6 +68,8 @@ cc.Class({
|
|||||||
// LIFE-CYCLE CALLBACKS:
|
// LIFE-CYCLE CALLBACKS:
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
|
cc.view.setOrientation(cc.macro.ORIENTATION_AUTO);
|
||||||
|
cc.view.enableAutoFullScreen(true);
|
||||||
|
|
||||||
window.atFirstLocationHref = window.location.href.split('#')[0];
|
window.atFirstLocationHref = window.location.href.split('#')[0];
|
||||||
const self = this;
|
const self = this;
|
||||||
|
@@ -2,6 +2,8 @@ const i18n = require('LanguageData');
|
|||||||
i18n.init(window.language); // languageID should be equal to the one we input in New Language ID input field
|
i18n.init(window.language); // languageID should be equal to the one we input in New Language ID input field
|
||||||
|
|
||||||
const RingBuffer = require('./RingBuffer');
|
const RingBuffer = require('./RingBuffer');
|
||||||
|
const NetworkDoctor = require('./NetworkDoctor');
|
||||||
|
const PriorityQueue = require("./PriorityQueue");
|
||||||
|
|
||||||
window.ALL_MAP_STATES = {
|
window.ALL_MAP_STATES = {
|
||||||
VISUAL: 0, // For free dragging & zooming.
|
VISUAL: 0, // For free dragging & zooming.
|
||||||
@@ -32,6 +34,23 @@ window.PlayerBattleState = {
|
|||||||
EXPELLED_IN_DISMISSAL: 6
|
EXPELLED_IN_DISMISSAL: 6
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.onUdpMessage = (args) => {
|
||||||
|
const self = window.mapIns;
|
||||||
|
const ui8Arr = args;
|
||||||
|
//cc.log(`#1 Js called back by CPP: onUdpMessage: args=${args}, typeof(args)=${typeof (args)}, argslen=${args.length}, ui8Arr=${ui8Arr}`);
|
||||||
|
const req = window.pb.protos.WsReq.decode(ui8Arr);
|
||||||
|
if (req) {
|
||||||
|
//cc.log(`#2 Js called back by CPP for upsync: onUdpMessage: ${JSON.stringify(req)}`);
|
||||||
|
if (req.act && window.UPSYNC_MSG_ACT_PLAYER_CMD == req.act) {
|
||||||
|
let effCnt = 0;
|
||||||
|
const peerJoinIndex = req.joinIndex;
|
||||||
|
if (peerJoinIndex == self.selfPlayerInfo.JoinIndex) return;
|
||||||
|
const batch = req.inputFrameUpsyncBatch;
|
||||||
|
self.onPeerInputFrameUpsync(peerJoinIndex, batch, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
cc.Class({
|
cc.Class({
|
||||||
extends: cc.Component,
|
extends: cc.Component,
|
||||||
|
|
||||||
@@ -44,6 +63,10 @@ cc.Class({
|
|||||||
type: cc.Prefab,
|
type: cc.Prefab,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
|
fireballPrefab: {
|
||||||
|
type: cc.Prefab,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
joystickInputControllerNode: {
|
joystickInputControllerNode: {
|
||||||
type: cc.Node,
|
type: cc.Node,
|
||||||
default: null
|
default: null
|
||||||
@@ -91,16 +114,26 @@ cc.Class({
|
|||||||
type: cc.Integer,
|
type: cc.Integer,
|
||||||
default: 4 // implies (renderFrameIdLagTolerance >> inputScaleFrames) count of inputFrameIds
|
default: 4 // implies (renderFrameIdLagTolerance >> inputScaleFrames) count of inputFrameIds
|
||||||
},
|
},
|
||||||
jigglingEps1D: {
|
sendingQLabel: {
|
||||||
type: cc.Float,
|
type: cc.Label,
|
||||||
default: 1e-3
|
default: null
|
||||||
},
|
},
|
||||||
bulletTriggerEnabled: {
|
inputFrameDownsyncQLabel: {
|
||||||
default: false
|
type: cc.Label,
|
||||||
|
default: null
|
||||||
},
|
},
|
||||||
closeOnForcedtoResyncNotSelf: {
|
peerInputFrameUpsyncQLabel: {
|
||||||
default: true
|
type: cc.Label,
|
||||||
|
default: null
|
||||||
},
|
},
|
||||||
|
rollbackFramesLabel: {
|
||||||
|
type: cc.Label,
|
||||||
|
default: null
|
||||||
|
},
|
||||||
|
skippedRenderFrameCntLabel: {
|
||||||
|
type: cc.Label,
|
||||||
|
default: null
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_inputFrameIdDebuggable(inputFrameId) {
|
_inputFrameIdDebuggable(inputFrameId) {
|
||||||
@@ -111,7 +144,7 @@ cc.Class({
|
|||||||
return (confirmedList + 1) == (1 << this.playerRichInfoDict.size);
|
return (confirmedList + 1) == (1 << this.playerRichInfoDict.size);
|
||||||
},
|
},
|
||||||
|
|
||||||
getOrPrefabInputFrameUpsync(inputFrameId) {
|
getOrPrefabInputFrameUpsync(inputFrameId, canConfirmSelf) {
|
||||||
// TODO: find some kind of synchronization mechanism against "onInputFrameDownsyncBatch"!
|
// TODO: find some kind of synchronization mechanism against "onInputFrameDownsyncBatch"!
|
||||||
const self = this;
|
const self = this;
|
||||||
if (
|
if (
|
||||||
@@ -124,33 +157,48 @@ cc.Class({
|
|||||||
let previousSelfInput = null,
|
let previousSelfInput = null,
|
||||||
currSelfInput = null;
|
currSelfInput = null;
|
||||||
const joinIndex = self.selfPlayerInfo.JoinIndex;
|
const joinIndex = self.selfPlayerInfo.JoinIndex;
|
||||||
|
const selfJoinIndexMask = (1 << (joinIndex - 1));
|
||||||
const existingInputFrame = self.recentInputCache.GetByFrameId(inputFrameId);
|
const existingInputFrame = self.recentInputCache.GetByFrameId(inputFrameId);
|
||||||
const previousInputFrameDownsync = self.recentInputCache.GetByFrameId(inputFrameId - 1);
|
const previousInputFrameDownsync = self.recentInputCache.GetByFrameId(inputFrameId - 1);
|
||||||
previousSelfInput = (null == previousInputFrameDownsync ? null : previousInputFrameDownsync.InputList[joinIndex - 1]);
|
previousSelfInput = (null == previousInputFrameDownsync ? null : previousInputFrameDownsync.InputList[joinIndex - 1]);
|
||||||
if (null != existingInputFrame) {
|
if (
|
||||||
|
null != existingInputFrame
|
||||||
|
&&
|
||||||
|
(true != canConfirmSelf)
|
||||||
|
) {
|
||||||
// This could happen upon either [type#1] or [type#2] forceConfirmation, where "refRenderFrame" is accompanied by some "inputFrameDownsyncs". The check here also guarantees that we don't override history
|
// This could happen upon either [type#1] or [type#2] forceConfirmation, where "refRenderFrame" is accompanied by some "inputFrameDownsyncs". The check here also guarantees that we don't override history
|
||||||
console.log(`noDelayInputFrameId=${inputFrameId} already exists in recentInputCache: recentInputCache=${self._stringifyRecentInputCache(false)}`);
|
//console.log(`noDelayInputFrameId=${inputFrameId} already exists in recentInputCache: recentInputCache=${self._stringifyRecentInputCache(false)}`);
|
||||||
return [previousSelfInput, existingInputFrame.InputList[joinIndex - 1]];
|
return [previousSelfInput, existingInputFrame.InputList[joinIndex - 1]];
|
||||||
}
|
}
|
||||||
|
|
||||||
const lastAllConfirmedInputFrame = self.recentInputCache.GetByFrameId(self.lastAllConfirmedInputFrameId);
|
|
||||||
const prefabbedInputList = new Array(self.playerRichInfoDict.size).fill(0);
|
const prefabbedInputList = new Array(self.playerRichInfoDict.size).fill(0);
|
||||||
// the returned "gopkgs.NewInputFrameDownsync.InputList" is immutable, thus we can only modify the values in "prefabbedInputList"
|
// the returned "gopkgs.NewInputFrameDownsync.InputList" is immutable, thus we can only modify the values in "prefabbedInputList"
|
||||||
for (let k in prefabbedInputList) {
|
for (let k = 0; k < window.boundRoomCapacity; ++k) {
|
||||||
if (null != previousInputFrameDownsync) {
|
if (null != existingInputFrame) {
|
||||||
prefabbedInputList[k] = previousInputFrameDownsync.InputList[k];
|
// When "null != existingInputFrame", it implies that "true == canConfirmSelf" here, we just have to assign "prefabbedInputList[(joinIndex-1)]" specifically and copy all others
|
||||||
}
|
prefabbedInputList[k] = existingInputFrame.InputList[k];
|
||||||
if (0 <= self.lastAllConfirmedInputFrameId && inputFrameId - 1 > self.lastAllConfirmedInputFrameId) {
|
} else if (self.lastIndividuallyConfirmedInputFrameId[k] <= inputFrameId) {
|
||||||
prefabbedInputList[k] = lastAllConfirmedInputFrame.InputList[k];
|
prefabbedInputList[k] = self.lastIndividuallyConfirmedInputList[k];
|
||||||
}
|
|
||||||
// Don't predict "btnA & btnB"!
|
// Don't predict "btnA & btnB"!
|
||||||
prefabbedInputList[k] = (prefabbedInputList[k] & 15);
|
prefabbedInputList[k] = (prefabbedInputList[k] & 15);
|
||||||
|
} else if (null != previousInputFrameDownsync) {
|
||||||
|
// When "self.lastIndividuallyConfirmedInputFrameId[k] > inputFrameId", don't use it to predict a historical input!
|
||||||
|
prefabbedInputList[k] = previousInputFrameDownsync.InputList[k];
|
||||||
|
// Don't predict "btnA & btnB"!
|
||||||
|
prefabbedInputList[k] = (prefabbedInputList[k] & 15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let initConfirmedList = 0;
|
||||||
|
if (null != existingInputFrame) {
|
||||||
|
// When "null != existingInputFrame", it implies that "true == canConfirmSelf" here
|
||||||
|
initConfirmedList = (existingInputFrame.ConfirmedList | selfJoinIndexMask);
|
||||||
}
|
}
|
||||||
currSelfInput = self.ctrl.getEncodedInput(); // When "null == existingInputFrame", it'd be safe to say that the realtime "self.ctrl.getEncodedInput()" is for the requested "inputFrameId"
|
currSelfInput = self.ctrl.getEncodedInput(); // When "null == existingInputFrame", it'd be safe to say that the realtime "self.ctrl.getEncodedInput()" is for the requested "inputFrameId"
|
||||||
prefabbedInputList[(joinIndex - 1)] = currSelfInput;
|
prefabbedInputList[(joinIndex - 1)] = currSelfInput;
|
||||||
while (self.recentInputCache.EdFrameId <= inputFrameId) {
|
while (self.recentInputCache.EdFrameId <= inputFrameId) {
|
||||||
// Fill the gap
|
// Fill the gap
|
||||||
const prefabbedInputFrameDownsync = gopkgs.NewInputFrameDownsync(self.recentInputCache.EdFrameId, prefabbedInputList.slice(), (1 << (joinIndex - 1)));
|
// [WARNING] Do not blindly use "selfJoinIndexMask" here, as the "actuallyUsedInput for self" couldn't be confirmed while prefabbing, otherwise we'd have confirmed a wrong self input by "_markConfirmationIfApplicable()"!
|
||||||
|
const prefabbedInputFrameDownsync = gopkgs.NewInputFrameDownsync(self.recentInputCache.EdFrameId, prefabbedInputList.slice(), initConfirmedList);
|
||||||
// console.log(`Prefabbed inputFrameId=${prefabbedInputFrameDownsync.InputFrameId}`);
|
// console.log(`Prefabbed inputFrameId=${prefabbedInputFrameDownsync.InputFrameId}`);
|
||||||
self.recentInputCache.Put(prefabbedInputFrameDownsync);
|
self.recentInputCache.Put(prefabbedInputFrameDownsync);
|
||||||
}
|
}
|
||||||
@@ -179,6 +227,7 @@ cc.Class({
|
|||||||
// Upon resync, "self.lastUpsyncInputFrameId" might not have been updated properly.
|
// Upon resync, "self.lastUpsyncInputFrameId" might not have been updated properly.
|
||||||
batchInputFrameIdSt = self.recentInputCache.StFrameId;
|
batchInputFrameIdSt = self.recentInputCache.StFrameId;
|
||||||
}
|
}
|
||||||
|
self.networkDoctor.logSending(batchInputFrameIdSt, latestLocalInputFrameId);
|
||||||
for (let i = batchInputFrameIdSt; i <= latestLocalInputFrameId; ++i) {
|
for (let i = batchInputFrameIdSt; i <= latestLocalInputFrameId; ++i) {
|
||||||
const inputFrameDownsync = self.recentInputCache.GetByFrameId(i);
|
const inputFrameDownsync = self.recentInputCache.GetByFrameId(i);
|
||||||
if (null == inputFrameDownsync) {
|
if (null == inputFrameDownsync) {
|
||||||
@@ -200,7 +249,11 @@ cc.Class({
|
|||||||
joinIndex: self.selfPlayerInfo.JoinIndex,
|
joinIndex: self.selfPlayerInfo.JoinIndex,
|
||||||
ackingInputFrameId: self.lastAllConfirmedInputFrameId,
|
ackingInputFrameId: self.lastAllConfirmedInputFrameId,
|
||||||
inputFrameUpsyncBatch: inputFrameUpsyncBatch,
|
inputFrameUpsyncBatch: inputFrameUpsyncBatch,
|
||||||
|
authKey: self.selfPlayerInfo.udpTunnelAuthKey,
|
||||||
}).finish();
|
}).finish();
|
||||||
|
if (cc.sys.isNative) {
|
||||||
|
DelayNoMore.UdpSession.broadcastInputFrameUpsync(reqData, window.boundRoomCapacity, self.selfPlayerInfo.JoinIndex);
|
||||||
|
}
|
||||||
window.sendSafely(reqData);
|
window.sendSafely(reqData);
|
||||||
self.lastUpsyncInputFrameId = latestLocalInputFrameId;
|
self.lastUpsyncInputFrameId = latestLocalInputFrameId;
|
||||||
if (self.lastUpsyncInputFrameId >= self.recentInputCache.EdFrameId) {
|
if (self.lastUpsyncInputFrameId >= self.recentInputCache.EdFrameId) {
|
||||||
@@ -287,15 +340,40 @@ cc.Class({
|
|||||||
self.playerRichInfoDict = new Map();
|
self.playerRichInfoDict = new Map();
|
||||||
// Clearing previous info of all players. [ENDS]
|
// Clearing previous info of all players. [ENDS]
|
||||||
|
|
||||||
|
// Clearing cached fireball rendering nodes [BEGINS]
|
||||||
|
if (null != self.cachedFireballs) {
|
||||||
|
while (!self.cachedFireballs.isEmpty()) {
|
||||||
|
const v = self.cachedFireballs.pop();
|
||||||
|
if (v && v.node && v.node.parent) {
|
||||||
|
v.node.parent.removeChild(v.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.cachedFireballs = new PriorityQueue();
|
||||||
|
}
|
||||||
|
for (let k = 0; k < 1000; k++) {
|
||||||
|
const newFireballNode = cc.instantiate(self.fireballPrefab);
|
||||||
|
const newFireball = newFireballNode.getComponent("Fireball");
|
||||||
|
newFireballNode.setPosition(cc.v2(Number.MAX_VALUE, Number.MAX_VALUE));
|
||||||
|
safelyAddChild(self.node, newFireballNode);
|
||||||
|
setLocalZOrder(newFireballNode, 10);
|
||||||
|
newFireball.lastUsed = -1;
|
||||||
|
newFireball.bulletLocalId = -1;
|
||||||
|
const initLookupKey = -(k + 1); // there's definitely no suck "bulletLocalId"
|
||||||
|
self.cachedFireballs.push(newFireball.lastUsed, newFireball, initLookupKey);
|
||||||
|
}
|
||||||
|
// Clearing cached fireball rendering nodes [ENDS]
|
||||||
|
|
||||||
self.renderFrameId = 0; // After battle started
|
self.renderFrameId = 0; // After battle started
|
||||||
self.bulletBattleLocalIdCounter = 0;
|
self.bulletBattleLocalIdCounter = 0;
|
||||||
self.lastAllConfirmedInputFrameId = -1;
|
self.lastAllConfirmedInputFrameId = -1;
|
||||||
self.lastUpsyncInputFrameId = -1;
|
self.lastUpsyncInputFrameId = -1;
|
||||||
self.chaserRenderFrameId = -1; // at any moment, "chaserRenderFrameId <= renderFrameId", but "chaserRenderFrameId" would fluctuate according to "onInputFrameDownsyncBatch"
|
self.chaserRenderFrameId = -1; // at any moment, "chaserRenderFrameId <= renderFrameId", but "chaserRenderFrameId" would fluctuate according to "onInputFrameDownsyncBatch"
|
||||||
|
|
||||||
|
self.lastIndividuallyConfirmedInputFrameId = new Array(window.boundRoomCapacity).fill(-1);
|
||||||
|
self.lastIndividuallyConfirmedInputList = new Array(window.boundRoomCapacity).fill(0);
|
||||||
self.recentRenderCache = new RingBuffer(self.renderCacheSize);
|
self.recentRenderCache = new RingBuffer(self.renderCacheSize);
|
||||||
|
|
||||||
self.selfPlayerInfo = null; // This field is kept for distinguishing "self" and "others".
|
|
||||||
self.recentInputCache = gopkgs.NewRingBufferJs((self.renderCacheSize >> 1) + 1);
|
self.recentInputCache = gopkgs.NewRingBufferJs((self.renderCacheSize >> 1) + 1);
|
||||||
|
|
||||||
self.gopkgsCollisionSys = gopkgs.NewCollisionSpaceJs((self.spaceOffsetX << 1), (self.spaceOffsetY << 1), self.collisionMinStep, self.collisionMinStep);
|
self.gopkgsCollisionSys = gopkgs.NewCollisionSpaceJs((self.spaceOffsetX << 1), (self.spaceOffsetY << 1), self.collisionMinStep, self.collisionMinStep);
|
||||||
@@ -313,14 +391,13 @@ cc.Class({
|
|||||||
self.othersForcedDownsyncRenderFrameDict = new Map();
|
self.othersForcedDownsyncRenderFrameDict = new Map();
|
||||||
self.rdfIdToActuallyUsedInput = new Map();
|
self.rdfIdToActuallyUsedInput = new Map();
|
||||||
|
|
||||||
|
self.networkDoctor = new NetworkDoctor(20);
|
||||||
|
self.skipRenderFrameFlag = false;
|
||||||
|
|
||||||
self.countdownNanos = null;
|
self.countdownNanos = null;
|
||||||
if (self.countdownLabel) {
|
if (self.countdownLabel) {
|
||||||
self.countdownLabel.string = "";
|
self.countdownLabel.string = "";
|
||||||
}
|
}
|
||||||
if (self.findingPlayerNode) {
|
|
||||||
const findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
|
|
||||||
findingPlayerScriptIns.init();
|
|
||||||
}
|
|
||||||
if (self.playersInfoNode) {
|
if (self.playersInfoNode) {
|
||||||
safelyAddChild(self.widgetsAboveAllNode, self.playersInfoNode);
|
safelyAddChild(self.widgetsAboveAllNode, self.playersInfoNode);
|
||||||
}
|
}
|
||||||
@@ -380,11 +457,16 @@ cc.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
|
cc.game.setFrameRate(60);
|
||||||
|
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
|
||||||
|
cc.view.enableAutoFullScreen(true);
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
window.mapIns = self;
|
window.mapIns = self;
|
||||||
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
|
window.forceBigEndianFloatingNumDecoding = self.forceBigEndianFloatingNumDecoding;
|
||||||
|
|
||||||
self.showCriticalCoordinateLabels = true;
|
self.showCriticalCoordinateLabels = false;
|
||||||
|
self.showNetworkDoctorInfo = true;
|
||||||
|
|
||||||
console.warn("+++++++ Map onLoad()");
|
console.warn("+++++++ Map onLoad()");
|
||||||
|
|
||||||
@@ -422,7 +504,7 @@ cc.Class({
|
|||||||
self.findingPlayerNode.width = self.canvasNode.width;
|
self.findingPlayerNode.width = self.canvasNode.width;
|
||||||
self.findingPlayerNode.height = self.canvasNode.height;
|
self.findingPlayerNode.height = self.canvasNode.height;
|
||||||
const findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
|
const findingPlayerScriptIns = self.findingPlayerNode.getComponent("FindingPlayer");
|
||||||
findingPlayerScriptIns.init();
|
findingPlayerScriptIns.init(self);
|
||||||
|
|
||||||
self.playersInfoNode = cc.instantiate(self.playersInfoPrefab);
|
self.playersInfoNode = cc.instantiate(self.playersInfoPrefab);
|
||||||
|
|
||||||
@@ -444,7 +526,7 @@ cc.Class({
|
|||||||
console.log(`Received parsedBattleColliderInfo via ws`);
|
console.log(`Received parsedBattleColliderInfo via ws`);
|
||||||
// TODO: Upon reconnection, the backend might have already been sending down data that'd trigger "onRoomDownsyncFrame & onInputFrameDownsyncBatch", but frontend could reject those data due to "battleState != PlayerBattleState.ACTIVE".
|
// TODO: Upon reconnection, the backend might have already been sending down data that'd trigger "onRoomDownsyncFrame & onInputFrameDownsyncBatch", but frontend could reject those data due to "battleState != PlayerBattleState.ACTIVE".
|
||||||
Object.assign(self, parsedBattleColliderInfo);
|
Object.assign(self, parsedBattleColliderInfo);
|
||||||
self.tooFastDtIntervalMillis = 0.5 * self.rollbackEstimatedDtMillis;
|
self.inputFrameUpsyncDelayTolerance = parsedBattleColliderInfo.inputFrameUpsyncDelayTolerance;
|
||||||
|
|
||||||
const tiledMapIns = self.node.getComponent(cc.TiledMap);
|
const tiledMapIns = self.node.getComponent(cc.TiledMap);
|
||||||
|
|
||||||
@@ -452,7 +534,7 @@ cc.Class({
|
|||||||
const fullPathOfTmxFile = cc.js.formatStr("map/%s/map", parsedBattleColliderInfo.stageName);
|
const fullPathOfTmxFile = cc.js.formatStr("map/%s/map", parsedBattleColliderInfo.stageName);
|
||||||
cc.loader.loadRes(fullPathOfTmxFile, cc.TiledMapAsset, (err, tmxAsset) => {
|
cc.loader.loadRes(fullPathOfTmxFile, cc.TiledMapAsset, (err, tmxAsset) => {
|
||||||
if (null != err) {
|
if (null != err) {
|
||||||
console.error(err);
|
console.error(`Error occurred when loading tiled stage ${parsedBattleColliderInfo.stageName}`, err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,10 +583,6 @@ cc.Class({
|
|||||||
const collisionBarrierIndex = (self.collisionBarrierIndexPrefix + barrierIdCounter);
|
const collisionBarrierIndex = (self.collisionBarrierIndexPrefix + barrierIdCounter);
|
||||||
self.gopkgsCollisionSysMap[collisionBarrierIndex] = newBarrierCollider;
|
self.gopkgsCollisionSysMap[collisionBarrierIndex] = newBarrierCollider;
|
||||||
}
|
}
|
||||||
self.selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
|
|
||||||
Object.assign(self.selfPlayerInfo, {
|
|
||||||
Id: self.selfPlayerInfo.playerId
|
|
||||||
});
|
|
||||||
self.initDebugDrawers();
|
self.initDebugDrawers();
|
||||||
const reqData = window.pb.protos.WsReq.encode({
|
const reqData = window.pb.protos.WsReq.encode({
|
||||||
msgId: Date.now(),
|
msgId: Date.now(),
|
||||||
@@ -578,19 +656,19 @@ cc.Class({
|
|||||||
const jsPlayersArr = new Array(pbRdf.playersArr.length).fill(null);
|
const jsPlayersArr = new Array(pbRdf.playersArr.length).fill(null);
|
||||||
for (let k = 0; k < pbRdf.playersArr.length; ++k) {
|
for (let k = 0; k < pbRdf.playersArr.length; ++k) {
|
||||||
const pbPlayer = pbRdf.playersArr[k];
|
const pbPlayer = pbRdf.playersArr[k];
|
||||||
const jsPlayer = gopkgs.NewPlayerDownsyncJs(pbPlayer.id, pbPlayer.virtualGridX, pbPlayer.virtualGridY, pbPlayer.dirX, pbPlayer.dirY, pbPlayer.velX, pbPlayer.velY, pbPlayer.framesToRecover, pbPlayer.framesInChState, pbPlayer.activeSkillId, pbPlayer.activeSkillHit, pbPlayer.framesInvinsible, pbPlayer.speed, pbPlayer.battleState, pbPlayer.characterState, pbPlayer.joinIndex, pbPlayer.hp, pbPlayer.maxHp, pbPlayer.colliderRadius, pbPlayer.inAir);
|
const jsPlayer = gopkgs.NewPlayerDownsyncJs(pbPlayer.id, pbPlayer.virtualGridX, pbPlayer.virtualGridY, pbPlayer.dirX, pbPlayer.dirY, pbPlayer.velX, pbPlayer.velY, pbPlayer.framesToRecover, pbPlayer.framesInChState, pbPlayer.activeSkillId, pbPlayer.activeSkillHit, pbPlayer.framesInvinsible, pbPlayer.speed, pbPlayer.battleState, pbPlayer.characterState, pbPlayer.joinIndex, pbPlayer.hp, pbPlayer.maxHp, pbPlayer.colliderRadius, pbPlayer.inAir, pbPlayer.onWall, pbPlayer.onWallNormX, pbPlayer.onWallNormY, pbPlayer.capturedByInertia, pbPlayer.bulletTeamId, pbPlayer.chCollisionTeamId);
|
||||||
jsPlayersArr[k] = jsPlayer;
|
jsPlayersArr[k] = jsPlayer;
|
||||||
}
|
}
|
||||||
const jsMeleeBulletsArr = new Array(pbRdf.meleeBullets.length).fill(null);
|
const jsMeleeBulletsArr = new Array(pbRdf.meleeBullets.length).fill(null);
|
||||||
for (let k = 0; k < pbRdf.meleeBullets.length; ++k) {
|
for (let k = 0; k < pbRdf.meleeBullets.length; ++k) {
|
||||||
const pbBullet = pbRdf.meleeBullets[k];
|
const pbBullet = pbRdf.meleeBullets[k];
|
||||||
const jsMeleeBullet = gopkgs.NewMeleeBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp);
|
const jsMeleeBullet = gopkgs.NewMeleeBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp, pbBullet.teamId, pbBullet.blState, pbBullet.framesInBlState, pbBullet.explosionFrames, pbBullet.speciesId);
|
||||||
jsMeleeBulletsArr[k] = jsMeleeBullet;
|
jsMeleeBulletsArr[k] = jsMeleeBullet;
|
||||||
}
|
}
|
||||||
const jsFireballBulletsArr = new Array(pbRdf.fireballBullets.length).fill(null);
|
const jsFireballBulletsArr = new Array(pbRdf.fireballBullets.length).fill(null);
|
||||||
for (let k = 0; k < pbRdf.fireballBullets.length; ++k) {
|
for (let k = 0; k < pbRdf.fireballBullets.length; ++k) {
|
||||||
const pbBullet = pbRdf.fireballBullets[k];
|
const pbBullet = pbRdf.fireballBullets[k];
|
||||||
const jsFireballBullet = gopkgs.NewFireballBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp, pbBullet.teamId, pbBullet.virtualGridX, pbBullet.virtualGridY, pbBullet.dirX, pbBullet.dirY, pbBullet.velX, pbBullet.velY, pbBullet.speed);
|
const jsFireballBullet = gopkgs.NewFireballBulletJs(pbBullet.bulletLocalId, pbBullet.originatedRenderFrameId, pbBullet.offenderJoinIndex, pbBullet.startupFrames, pbBullet.cancellableStFrame, pbBullet.cancellableEdFrame, pbBullet.activeFrames, pbBullet.hitStunFrames, pbBullet.blockStunFrames, pbBullet.pushbackVelX, pbBullet.pushbackVelY, pbBullet.damage, pbBullet.selfLockVelX, pbBullet.selfLockVelY, pbBullet.hitboxOffsetX, pbBullet.hitboxOffsetY, pbBullet.hitboxSizeX, pbBullet.hitboxSizeY, pbBullet.blowUp, pbBullet.teamId, pbBullet.virtualGridX, pbBullet.virtualGridY, pbBullet.dirX, pbBullet.dirY, pbBullet.velX, pbBullet.velY, pbBullet.speed, pbBullet.blState, pbBullet.framesInBlState, pbBullet.explosionFrames, pbBullet.speciesId);
|
||||||
jsFireballBulletsArr[k] = jsFireballBullet;
|
jsFireballBulletsArr[k] = jsFireballBullet;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,6 +737,7 @@ cc.Class({
|
|||||||
self.lastRenderFrameIdTriggeredAt = performance.now();
|
self.lastRenderFrameIdTriggeredAt = performance.now();
|
||||||
// In this case it must be true that "rdf.id > chaserRenderFrameId".
|
// In this case it must be true that "rdf.id > chaserRenderFrameId".
|
||||||
self.chaserRenderFrameId = rdf.Id;
|
self.chaserRenderFrameId = rdf.Id;
|
||||||
|
self.networkDoctor.logRollbackFrames(0);
|
||||||
|
|
||||||
const canvasNode = self.canvasNode;
|
const canvasNode = self.canvasNode;
|
||||||
self.ctrl = canvasNode.getComponent("TouchEventsManager");
|
self.ctrl = canvasNode.getComponent("TouchEventsManager");
|
||||||
@@ -691,6 +770,8 @@ cc.Class({
|
|||||||
|
|
||||||
equalPlayers(lhs, rhs) {
|
equalPlayers(lhs, rhs) {
|
||||||
if (null == lhs || null == rhs) return false;
|
if (null == lhs || null == rhs) return false;
|
||||||
|
if (null == lhs && null != rhs) return false;
|
||||||
|
if (null != lhs && null == rhs) return false;
|
||||||
if (lhs.VirtualGridX != rhs.VirtualGridX) return false;
|
if (lhs.VirtualGridX != rhs.VirtualGridX) return false;
|
||||||
if (lhs.VirtualGridY != rhs.VirtualGridY) return false;
|
if (lhs.VirtualGridY != rhs.VirtualGridY) return false;
|
||||||
if (lhs.DirX != rhs.DirX) return false;
|
if (lhs.DirX != rhs.DirX) return false;
|
||||||
@@ -709,24 +790,60 @@ cc.Class({
|
|||||||
|
|
||||||
equalMeleeBullets(lhs, rhs) {
|
equalMeleeBullets(lhs, rhs) {
|
||||||
if (null == lhs || null == rhs) return false;
|
if (null == lhs || null == rhs) return false;
|
||||||
if (lhs.battleLocalId != rhs.battleLocalId) return false;
|
if (null == lhs && null != rhs) return false;
|
||||||
if (lhs.offenderPlayerId != rhs.offenderPlayerId) return false;
|
if (null != lhs && null == rhs) return false;
|
||||||
if (lhs.offenderJoinIndex != rhs.offenderJoinIndex) return false;
|
if (lhs.BattleAttr.BulletLocalId != rhs.BattleAttr.BulletLocalId) return false;
|
||||||
if (lhs.originatedRenderFrameId != rhs.originatedRenderFrameId) return false;
|
if (lhs.BattleAttr.OffenderJoinIndex != rhs.BattleAttr.OffenderJoinIndex) return false;
|
||||||
|
if (lhs.BattleAttr.OriginatedRenderFrameId != rhs.BattleAttr.OriginatedRenderFrameId) return false;
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
|
equalFireballBullets(lhs, rhs) {
|
||||||
|
if (null == lhs || null == rhs) return false;
|
||||||
|
if (null == lhs && null != rhs) return false;
|
||||||
|
if (null != lhs && null == rhs) return false;
|
||||||
|
if (lhs.BattleAttr.BulletLocalId != rhs.BattleAttr.BulletLocalId) return false;
|
||||||
|
if (lhs.BattleAttr.OffenderJoinIndex != rhs.BattleAttr.OffenderJoinIndex) return false;
|
||||||
|
if (lhs.BattleAttr.OriginatedRenderFrameId != rhs.BattleAttr.OriginatedRenderFrameId) return false;
|
||||||
|
|
||||||
|
if (lhs.VirtualGridX != rhs.Bullet.VirtualGridX) return false;
|
||||||
|
if (lhs.VirtualGridY != rhs.Bullet.VirtualGridY) return false;
|
||||||
|
if (lhs.DirX != rhs.DirX) return false;
|
||||||
|
if (lhs.DirY != rhs.DirY) return false;
|
||||||
|
if (lhs.VelX != rhs.VelX) return false;
|
||||||
|
if (lhs.VelY != rhs.VelY) return false;
|
||||||
|
if (lhs.Speed != rhs.Speed) return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
equalRoomDownsyncFrames(lhs, rhs) {
|
equalRoomDownsyncFrames(lhs, rhs) {
|
||||||
if (null == lhs || null == rhs) return false;
|
if (null == lhs || null == rhs) return false;
|
||||||
for (let k in lhs.players) {
|
for (let k in lhs.PlayersArr) {
|
||||||
if (!this.equalPlayers(lhs.players[k], rhs.players[k])) return false;
|
if (!this.equalPlayers(lhs.PlayersArr[k], rhs.PlayersArr[k])) return false;
|
||||||
}
|
}
|
||||||
for (let k in lhs.meleeBullets) {
|
for (let k in lhs.MeleeBullets) {
|
||||||
if (!this.equalMeleeBullets(lhs.meleeBullets[k], rhs.meleeBullets[k])) return false;
|
if (!this.equalMeleeBullets(lhs.MeleeBullets[k], rhs.MeleeBullets[k])) return false;
|
||||||
|
}
|
||||||
|
for (let k in lhs.fireballBullet) {
|
||||||
|
if (!this.equalFireballBullets(lhs.FireballBullets[k], rhs.FireballBullets[k])) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_markConfirmationIfApplicable() {
|
||||||
|
const self = this;
|
||||||
|
let newAllConfirmedCnt = 0;
|
||||||
|
while (self.recentInputCache.StFrameId <= self.lastAllConfirmedInputFrameId && self.lastAllConfirmedInputFrameId < self.recentInputCache.EdFrameId) {
|
||||||
|
const inputFrameDownsync = self.recentInputCache.GetByFrameId(self.lastAllConfirmedInputFrameId);
|
||||||
|
if (null == inputFrameDownsync) break;
|
||||||
|
if (self._allConfirmed(inputFrameDownsync.ConfirmedList)) break;
|
||||||
|
++self.lastAllConfirmedInputFrameId;
|
||||||
|
++newAllConfirmedCnt;
|
||||||
|
}
|
||||||
|
return newAllConfirmedCnt;
|
||||||
|
},
|
||||||
|
|
||||||
onInputFrameDownsyncBatch(batch /* []*pb.InputFrameDownsync */ ) {
|
onInputFrameDownsyncBatch(batch /* []*pb.InputFrameDownsync */ ) {
|
||||||
// TODO: find some kind of synchronization mechanism against "getOrPrefabInputFrameUpsync"!
|
// TODO: find some kind of synchronization mechanism against "getOrPrefabInputFrameUpsync"!
|
||||||
if (null == batch) {
|
if (null == batch) {
|
||||||
@@ -740,6 +857,7 @@ cc.Class({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.networkDoctor.logInputFrameDownsync(batch[0].inputFrameId, batch[batch.length - 1].inputFrameId);
|
||||||
let firstPredictedYetIncorrectInputFrameId = null;
|
let firstPredictedYetIncorrectInputFrameId = null;
|
||||||
for (let k in batch) {
|
for (let k in batch) {
|
||||||
const inputFrameDownsync = batch[k];
|
const inputFrameDownsync = batch[k];
|
||||||
@@ -747,8 +865,9 @@ cc.Class({
|
|||||||
if (inputFrameDownsyncId <= self.lastAllConfirmedInputFrameId) {
|
if (inputFrameDownsyncId <= self.lastAllConfirmedInputFrameId) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// [WARNING] Take all "inputFrameDownsync" from backend as all-confirmed, it'll be later checked by "rollbackAndChase".
|
// [WARNING] Now that "inputFrameDownsyncId > self.lastAllConfirmedInputFrameId", we should make an update immediately because unlike its backend counterpart "Room.LastAllConfirmedInputFrameId", the frontend "mapIns.lastAllConfirmedInputFrameId" might inevitably get gaps among discrete values due to "either type#1 or type#2 forceConfirmation" -- and only "onInputFrameDownsyncBatch" can catch this!
|
||||||
self.lastAllConfirmedInputFrameId = inputFrameDownsyncId;
|
self.lastAllConfirmedInputFrameId = inputFrameDownsyncId;
|
||||||
|
|
||||||
const localInputFrame = self.recentInputCache.GetByFrameId(inputFrameDownsyncId);
|
const localInputFrame = self.recentInputCache.GetByFrameId(inputFrameDownsyncId);
|
||||||
if (null != localInputFrame
|
if (null != localInputFrame
|
||||||
&&
|
&&
|
||||||
@@ -758,16 +877,29 @@ cc.Class({
|
|||||||
) {
|
) {
|
||||||
firstPredictedYetIncorrectInputFrameId = inputFrameDownsyncId;
|
firstPredictedYetIncorrectInputFrameId = inputFrameDownsyncId;
|
||||||
}
|
}
|
||||||
|
// [WARNING] Take all "inputFrameDownsync" from backend as all-confirmed, it'll be later checked by "rollbackAndChase".
|
||||||
inputFrameDownsync.confirmedList = (1 << self.playerRichInfoDict.size) - 1;
|
inputFrameDownsync.confirmedList = (1 << self.playerRichInfoDict.size) - 1;
|
||||||
const inputFrameDownsyncLocal = gopkgs.NewInputFrameDownsync(inputFrameDownsync.inputFrameId, inputFrameDownsync.inputList, inputFrameDownsync.confirmedList); // "battle.InputFrameDownsync" in "jsexport"
|
const inputFrameDownsyncLocal = gopkgs.NewInputFrameDownsync(inputFrameDownsync.inputFrameId, inputFrameDownsync.inputList, inputFrameDownsync.confirmedList); // "battle.InputFrameDownsync" in "jsexport"
|
||||||
|
for (let j in self.playerRichInfoArr) {
|
||||||
|
const jj = parseInt(j);
|
||||||
|
if (inputFrameDownsync.inputFrameId > self.lastIndividuallyConfirmedInputFrameId[jj]) {
|
||||||
|
self.lastIndividuallyConfirmedInputFrameId[jj] = inputFrameDownsync.inputFrameId;
|
||||||
|
self.lastIndividuallyConfirmedInputList[jj] = inputFrameDownsync.inputList[jj];
|
||||||
|
}
|
||||||
|
}
|
||||||
//console.log(`Confirmed inputFrameId=${inputFrameDownsync.inputFrameId}`);
|
//console.log(`Confirmed inputFrameId=${inputFrameDownsync.inputFrameId}`);
|
||||||
const [ret, oldStFrameId, oldEdFrameId] = self.recentInputCache.SetByFrameId(inputFrameDownsyncLocal, inputFrameDownsync.inputFrameId);
|
const [ret, oldStFrameId, oldEdFrameId] = self.recentInputCache.SetByFrameId(inputFrameDownsyncLocal, inputFrameDownsync.inputFrameId);
|
||||||
if (window.RING_BUFF_FAILED_TO_SET == ret) {
|
if (window.RING_BUFF_FAILED_TO_SET == ret) {
|
||||||
throw `Failed to dump input cache (maybe recentInputCache too small)! inputFrameDownsync.inputFrameId=${inputFrameDownsync.inputFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}; recentRenderCache=${self._stringifyRecentRenderCache(false)}, recentInputCache=${self._stringifyRecentInputCache(false)}`;
|
throw `Failed to dump input cache (maybe recentInputCache too small)! inputFrameDownsync.inputFrameId=${inputFrameDownsync.inputFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}; recentRenderCache=${self._stringifyRecentRenderCache(false)}, recentInputCache=${self._stringifyRecentInputCache(false)}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
self._markConfirmationIfApplicable();
|
||||||
|
self._handleIncorrectlyRenderedPrediction(firstPredictedYetIncorrectInputFrameId, batch, false);
|
||||||
|
},
|
||||||
|
|
||||||
|
_handleIncorrectlyRenderedPrediction(firstPredictedYetIncorrectInputFrameId, batch, fromUDP) {
|
||||||
if (null == firstPredictedYetIncorrectInputFrameId) return;
|
if (null == firstPredictedYetIncorrectInputFrameId) return;
|
||||||
|
const self = this;
|
||||||
const renderFrameId1 = gopkgs.ConvertToFirstUsedRenderFrameId(firstPredictedYetIncorrectInputFrameId) - 1;
|
const renderFrameId1 = gopkgs.ConvertToFirstUsedRenderFrameId(firstPredictedYetIncorrectInputFrameId) - 1;
|
||||||
if (renderFrameId1 >= self.chaserRenderFrameId) return;
|
if (renderFrameId1 >= self.chaserRenderFrameId) return;
|
||||||
|
|
||||||
@@ -783,11 +915,83 @@ cc.Class({
|
|||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
// The actual rollback-and-chase would later be executed in update(dt).
|
// The actual rollback-and-chase would later be executed in update(dt).
|
||||||
console.warn(`Mismatched input detected, resetting chaserRenderFrameId: ${self.chaserRenderFrameId}->${renderFrameId1} by firstPredictedYetIncorrectInputFrameId: ${firstPredictedYetIncorrectInputFrameId}
|
console.log(`Mismatched input detected, resetting chaserRenderFrameId: ${self.chaserRenderFrameId}->${renderFrameId1} by
|
||||||
|
firstPredictedYetIncorrectInputFrameId: ${firstPredictedYetIncorrectInputFrameId}
|
||||||
lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}
|
lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}
|
||||||
recentInputCache=${self._stringifyRecentInputCache(false)}
|
recentInputCache=${self._stringifyRecentInputCache(false)}
|
||||||
batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}]`);
|
batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}]
|
||||||
|
fromUDP=${fromUDP}`);
|
||||||
self.chaserRenderFrameId = renderFrameId1;
|
self.chaserRenderFrameId = renderFrameId1;
|
||||||
|
let rollbackFrames = (self.renderFrameId - self.chaserRenderFrameId);
|
||||||
|
if (0 > rollbackFrames)
|
||||||
|
rollbackFrames = 0;
|
||||||
|
self.networkDoctor.logRollbackFrames(rollbackFrames);
|
||||||
|
},
|
||||||
|
|
||||||
|
onPeerInputFrameUpsync(peerJoinIndex, batch, fromUDP) {
|
||||||
|
// TODO: find some kind of synchronization mechanism against "getOrPrefabInputFrameUpsync"!
|
||||||
|
// See `<proj-root>/ConcerningEdgeCases.md` for why this method exists.
|
||||||
|
if (null == batch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const self = this;
|
||||||
|
if (!self.recentInputCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (ALL_BATTLE_STATES.IN_BATTLE != self.battleState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let effCnt = 0;
|
||||||
|
//console.log(`Received peer inputFrameUpsync batch w/ inputFrameId in [${batch[0].inputFrameId}, ${batch[batch.length - 1].inputFrameId}] for prediction assistance`);
|
||||||
|
let firstPredictedYetIncorrectInputFrameId = null;
|
||||||
|
const renderedInputFrameIdUpper = gopkgs.ConvertToDelayedInputFrameId(self.renderFrameId);
|
||||||
|
for (let k in batch) {
|
||||||
|
const inputFrame = batch[k]; // could be either "pb.InputFrameDownsync" or "pb.InputFrameUpsync", depending on "fromUDP"
|
||||||
|
const inputFrameId = inputFrame.inputFrameId;
|
||||||
|
const peerEncodedInput = (true == fromUDP ? inputFrame.encoded : inputFrame.inputList[peerJoinIndex - 1]);
|
||||||
|
if (inputFrameId <= renderedInputFrameIdUpper) {
|
||||||
|
// [WARNING] Avoid obfuscating already rendered history, even at "inputFrameId == renderedInputFrameIdUpper", due to the use of "INPUT_SCALE_FRAMES" some previous render frames might already be rendered with "inputFrameId"!
|
||||||
|
// TODO: Shall we update the "chaserRenderFrameId" if the rendered history was wrong? It doesn't seem to impact eventual correctness if we allow the update of "chaserRenderFrameId" upon "inputFrameId <= renderedInputFrameIdUpper" here, however UDP upsync doesn't reserve order from a same sender and there might be multiple other senders, hence it might result in unnecessarily frequent chasing.
|
||||||
|
const localInputFrame = self.recentInputCache.GetByFrameId(inputFrameId);
|
||||||
|
if (null != localInputFrame
|
||||||
|
&&
|
||||||
|
null == firstPredictedYetIncorrectInputFrameId
|
||||||
|
&&
|
||||||
|
localInputFrame.InputList[peerJoinIndex - 1] != peerEncodedInput
|
||||||
|
) {
|
||||||
|
firstPredictedYetIncorrectInputFrameId = inputFrameId;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inputFrameId <= self.lastAllConfirmedInputFrameId) {
|
||||||
|
// [WARNING] Don't reject it by "inputFrameId <= self.lastIndividuallyConfirmedInputFrameId[peerJoinIndex-1]", the arrival of UDP packets might not reserve their sending order!
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const peerJoinIndexMask = (1 << (peerJoinIndex - 1));
|
||||||
|
self.getOrPrefabInputFrameUpsync(inputFrameId, false); // Make sure that inputFrame exists locally
|
||||||
|
const existingInputFrame = self.recentInputCache.GetByFrameId(inputFrameId);
|
||||||
|
if (0 < (existingInputFrame.ConfirmedList & peerJoinIndexMask)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (inputFrameId > self.lastIndividuallyConfirmedInputFrameId[peerJoinIndex - 1]) {
|
||||||
|
self.lastIndividuallyConfirmedInputFrameId[peerJoinIndex - 1] = inputFrameId;
|
||||||
|
self.lastIndividuallyConfirmedInputList[peerJoinIndex - 1] = peerEncodedInput;
|
||||||
|
}
|
||||||
|
effCnt += 1;
|
||||||
|
// the returned "gopkgs.NewInputFrameDownsync.InputList" is immutable, thus we can only modify the values in "newInputList" and "newConfirmedList"!
|
||||||
|
let newInputList = existingInputFrame.InputList.slice();
|
||||||
|
newInputList[peerJoinIndex - 1] = peerEncodedInput;
|
||||||
|
let newConfirmedList = (existingInputFrame.ConfirmedList | peerJoinIndex);
|
||||||
|
const newInputFrameDownsyncLocal = gopkgs.NewInputFrameDownsync(inputFrameId, newInputList, newConfirmedList);
|
||||||
|
//console.log(`Updated encoded input of peerJoinIndex=${peerJoinIndex} to ${peerEncodedInput} for inputFrameId=${inputFrameId}/renderedInputFrameIdUpper=${renderedInputFrameIdUpper} from ${JSON.stringify(inputFrame)}; newInputFrameDownsyncLocal=${self.gopkgsInputFrameDownsyncStr(newInputFrameDownsyncLocal)}; existingInputFrame=${self.gopkgsInputFrameDownsyncStr(existingInputFrame)}`);
|
||||||
|
self.recentInputCache.SetByFrameId(newInputFrameDownsyncLocal, inputFrameId);
|
||||||
|
}
|
||||||
|
if (0 < effCnt) {
|
||||||
|
//self._markConfirmationIfApplicable();
|
||||||
|
self.networkDoctor.logPeerInputFrameUpsync(batch[0].inputFrameId, batch[batch.length - 1].inputFrameId);
|
||||||
|
}
|
||||||
|
self._handleIncorrectlyRenderedPrediction(firstPredictedYetIncorrectInputFrameId, batch, fromUDP);
|
||||||
},
|
},
|
||||||
|
|
||||||
onPlayerAdded(rdf /* pb.RoomDownsyncFrame */ ) {
|
onPlayerAdded(rdf /* pb.RoomDownsyncFrame */ ) {
|
||||||
@@ -805,8 +1009,7 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
|||||||
if (ALL_BATTLE_STATES.IN_BATTLE != self.battleState) {
|
if (ALL_BATTLE_STATES.IN_BATTLE != self.battleState) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
self._stringifyRdfIdToActuallyUsedInput();
|
window.closeWSConnection(constants.RET_CODE.BATTLE_STOPPED, "");
|
||||||
window.closeWSConnection(constants.RET_CODE.BATTLE_STOPPED);
|
|
||||||
self.battleState = ALL_BATTLE_STATES.IN_SETTLEMENT;
|
self.battleState = ALL_BATTLE_STATES.IN_SETTLEMENT;
|
||||||
self.countdownNanos = null;
|
self.countdownNanos = null;
|
||||||
if (self.musicEffectManagerScriptIns) {
|
if (self.musicEffectManagerScriptIns) {
|
||||||
@@ -854,19 +1057,31 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
|||||||
update(dt) {
|
update(dt) {
|
||||||
const self = this;
|
const self = this;
|
||||||
if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) {
|
if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) {
|
||||||
const elapsedMillisSinceLastFrameIdTriggered = performance.now() - self.lastRenderFrameIdTriggeredAt;
|
/*
|
||||||
if (elapsedMillisSinceLastFrameIdTriggered < self.tooFastDtIntervalMillis) {
|
[WARNING] Different devices might differ in the rate of calling "update(dt)", and the game engine is responsible of keeping this rate statistically constant.
|
||||||
// [WARNING] We should avoid a frontend ticking too fast to prevent cheating, as well as ticking too slow to cause a "resync avalanche" that impacts user experience!
|
|
||||||
// console.debug("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": elapsedMillisSinceLastFrameIdTriggered=", elapsedMillisSinceLastFrameIdTriggered);
|
Significantly different rates of calling "update(dt)" among players in a same battle would result in frequent [type#1 forceConfirmation], if you have any doubt on troubles caused by this, sample the FPS curve from all players in that battle.
|
||||||
|
|
||||||
|
Kindly note that Significantly different network bandwidths or delay fluctuations would result in frequent [type#1 forceConfirmation] too, but CAUSE FROM DIFFERENT LOCAL "update(dt)" RATE SHOULD BE THE FIRST TO INVESTIGATE AND ELIMINATE -- because we have control on it, but no one has control on the internet.
|
||||||
|
*/
|
||||||
|
if (self.skipRenderFrameFlag) {
|
||||||
|
self.networkDoctor.logSkippedRenderFrameCnt();
|
||||||
|
self.skipRenderFrameFlag = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
let st = performance.now();
|
let st = performance.now();
|
||||||
|
const noDelayInputFrameId = gopkgs.ConvertToNoDelayInputFrameId(self.renderFrameId);
|
||||||
let prevSelfInput = null,
|
let prevSelfInput = null,
|
||||||
currSelfInput = null;
|
currSelfInput = null;
|
||||||
const noDelayInputFrameId = gopkgs.ConvertToNoDelayInputFrameId(self.renderFrameId);
|
|
||||||
if (gopkgs.ShouldGenerateInputFrameUpsync(self.renderFrameId)) {
|
if (gopkgs.ShouldGenerateInputFrameUpsync(self.renderFrameId)) {
|
||||||
[prevSelfInput, currSelfInput] = self.getOrPrefabInputFrameUpsync(noDelayInputFrameId);
|
[prevSelfInput, currSelfInput] = self.getOrPrefabInputFrameUpsync(noDelayInputFrameId, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(self.renderFrameId);
|
||||||
|
if (null == self.recentInputCache.GetByFrameId(delayedInputFrameId)) {
|
||||||
|
// Possible edge case after resync, kindly note that it's OK to prefab a "future inputFrame" here, because "sendInputFrameUpsyncBatch" would be capped by "noDelayInputFrameId from self.renderFrameId".
|
||||||
|
self.getOrPrefabInputFrameUpsync(delayedInputFrameId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
let t0 = performance.now();
|
let t0 = performance.now();
|
||||||
@@ -890,6 +1105,7 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
|||||||
|
|
||||||
// Inside the following "self.rollbackAndChase" actually ROLLS FORWARD w.r.t. the corresponding delayedInputFrame, REGARDLESS OF whether or not "self.chaserRenderFrameId == self.renderFrameId" now.
|
// Inside the following "self.rollbackAndChase" actually ROLLS FORWARD w.r.t. the corresponding delayedInputFrame, REGARDLESS OF whether or not "self.chaserRenderFrameId == self.renderFrameId" now.
|
||||||
const latestRdfResults = self.rollbackAndChase(self.renderFrameId, self.renderFrameId + 1, self.gopkgsCollisionSys, self.gopkgsCollisionSysMap, false);
|
const latestRdfResults = self.rollbackAndChase(self.renderFrameId, self.renderFrameId + 1, self.gopkgsCollisionSys, self.gopkgsCollisionSysMap, false);
|
||||||
|
self.networkDoctor.logRollbackFrames(self.renderFrameId - self.chaserRenderFrameId);
|
||||||
let prevRdf = latestRdfResults[0],
|
let prevRdf = latestRdfResults[0],
|
||||||
rdf = latestRdfResults[1];
|
rdf = latestRdfResults[1];
|
||||||
/*
|
/*
|
||||||
@@ -899,24 +1115,28 @@ batchInputFrameIdRange=[${batch[0].inputFrameId}, ${batch[batch.length - 1].inpu
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
// [WARNING] Don't try to get "prevRdf(i.e. renderFrameId == latest-1)" by "self.recentRenderCache.getByFrameId(...)" here, as the cache might have been updated by asynchronous "onRoomDownsyncFrame(...)" calls!
|
// [WARNING] Don't try to get "prevRdf(i.e. renderFrameId == latest-1)" by "self.recentRenderCache.getByFrameId(...)" here, as the cache might have been updated by asynchronous "onRoomDownsyncFrame(...)" calls!
|
||||||
if (self.othersForcedDownsyncRenderFrameDict.has(rdf.id)) {
|
if (self.othersForcedDownsyncRenderFrameDict.has(rdf.Id)) {
|
||||||
const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(rdf.id);
|
const delayedInputFrameId = gopkgs.ConvertToDelayedInputFrameId(rdf.Id);
|
||||||
const othersForcedDownsyncRenderFrame = self.othersForcedDownsyncRenderFrameDict.get(rdf.id);
|
const othersForcedDownsyncRenderFrame = self.othersForcedDownsyncRenderFrameDict.get(rdf.Id);
|
||||||
if (self.lastAllConfirmedInputFrameId >= delayedInputFrameId && !self.equalRoomDownsyncFrames(othersForcedDownsyncRenderFrame, rdf)) {
|
if (self.lastAllConfirmedInputFrameId >= delayedInputFrameId && !self.equalRoomDownsyncFrames(othersForcedDownsyncRenderFrame, rdf)) {
|
||||||
console.warn(`Mismatched render frame@rdf.id=${rdf.id} w/ inputFrameId=${delayedInputFrameId}:
|
console.warn(`Mismatched render frame@rdf.id=${rdf.Id} w/ inputFrameId=${delayedInputFrameId}:
|
||||||
rdf=${JSON.stringify(rdf)}
|
rdf=${JSON.stringify(rdf)}
|
||||||
othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame)}`);
|
othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame)}`);
|
||||||
// closeWSConnection(constants.RET_CODE.CLIENT_MISMATCHED_RENDER_FRAME, "");
|
// closeWSConnection(constants.RET_CODE.CLIENT_MISMATCHED_RENDER_FRAME, "");
|
||||||
// self.onManualRejoinRequired("[DEBUG] CLIENT_MISMATCHED_RENDER_FRAME");
|
// self.onManualRejoinRequired("[DEBUG] CLIENT_MISMATCHED_RENDER_FRAME");
|
||||||
rdf = othersForcedDownsyncRenderFrame;
|
rdf = othersForcedDownsyncRenderFrame;
|
||||||
self.othersForcedDownsyncRenderFrameDict.delete(rdf.id);
|
self.othersForcedDownsyncRenderFrameDict.delete(rdf.Id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.applyRoomDownsyncFrameDynamics(rdf, prevRdf);
|
self.applyRoomDownsyncFrameDynamics(rdf, prevRdf);
|
||||||
self.showDebugBoundaries(rdf);
|
self.showDebugBoundaries(rdf);
|
||||||
|
if (self.showNetworkDoctorInfo) {
|
||||||
|
self.showNetworkDoctorLabels();
|
||||||
|
}
|
||||||
++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!!
|
++self.renderFrameId; // [WARNING] It's important to increment the renderFrameId AFTER all the operations above!!!
|
||||||
self.lastRenderFrameIdTriggeredAt = performance.now();
|
self.lastRenderFrameIdTriggeredAt = performance.now();
|
||||||
let t3 = performance.now();
|
let t3 = performance.now();
|
||||||
|
self.skipRenderFrameFlag = self.networkDoctor.isTooFast(self);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error during Map.update", err);
|
console.error("Error during Map.update", err);
|
||||||
self.onBattleStopped(); // TODO: Popup to ask player to refresh browser
|
self.onBattleStopped(); // TODO: Popup to ask player to refresh browser
|
||||||
@@ -940,6 +1160,7 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
logout(byClick /* The case where this param is "true" will be triggered within `ConfirmLogout.js`.*/ , shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage) {
|
logout(byClick /* The case where this param is "true" will be triggered within `ConfirmLogout.js`.*/ , shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage) {
|
||||||
const self = this;
|
const self = this;
|
||||||
const localClearance = () => {
|
const localClearance = () => {
|
||||||
|
window.closeWSConnection(constants.RET_CODE.BATTLE_STOPPED, "");
|
||||||
window.clearLocalStorageAndBackToLoginScene(shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage);
|
window.clearLocalStorageAndBackToLoginScene(shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1053,6 +1274,77 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
playerRichInfo.scriptIns.updateCharacterAnim(currPlayerDownsync, prevRdfPlayer, false, chConfig);
|
playerRichInfo.scriptIns.updateCharacterAnim(currPlayerDownsync, prevRdfPlayer, false, chConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Move all to infinitely far away first
|
||||||
|
for (let k in self.cachedFireballs.list) {
|
||||||
|
const pqNode = self.cachedFireballs.list[k];
|
||||||
|
const fireball = pqNode.value;
|
||||||
|
fireball.node.setPosition(cc.v2(Number.MAX_VALUE, Number.MAX_VALUE));
|
||||||
|
}
|
||||||
|
for (let k in rdf.MeleeBullets) {
|
||||||
|
const meleeBullet = rdf.MeleeBullets[k];
|
||||||
|
const isExploding = (window.BULLET_STATE.Exploding == meleeBullet.BlState);
|
||||||
|
if (isExploding) {
|
||||||
|
let pqNode = self.cachedFireballs.popAny(meleeBullet.BattleAttr.BulletLocalId);
|
||||||
|
let speciesName = `MeleeExplosion`;
|
||||||
|
let animName = `MeleeExplosion${meleeBullet.Bullet.SpeciesId}`;
|
||||||
|
|
||||||
|
const offender = rdf.PlayersArr[meleeBullet.BattleAttr.OffenderJoinIndex - 1];
|
||||||
|
let xfac = 1; // By now, straight Punch offset doesn't respect "y-axis"
|
||||||
|
if (0 > offender.DirX) {
|
||||||
|
xfac = -1;
|
||||||
|
}
|
||||||
|
const [wx, wy] = gopkgs.VirtualGridToWorldPos(offender.VirtualGridX + xfac * meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY);
|
||||||
|
|
||||||
|
if (null == pqNode) {
|
||||||
|
pqNode = self.cachedFireballs.pop();
|
||||||
|
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${meleeBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${meleeBullet.Bullet.StartupFrames}, using a new fireball node for rendering for bulletLocalId=${meleeBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
|
||||||
|
} else {
|
||||||
|
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${meleeBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${meleeBullet.Bullet.StartupFrames}, using a cached fireball node for rendering for bulletLocalId=${meleeBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
|
||||||
|
}
|
||||||
|
const cachedFireball = pqNode.value;
|
||||||
|
cachedFireball.setSpecies(speciesName, meleeBullet, rdf);
|
||||||
|
const newAnimIdx = meleeBullet.Bullet.SpeciesId - 1;
|
||||||
|
cachedFireball.updateAnim(animName, meleeBullet.FramesInBlState, offender.DirX, false, rdf, newAnimIdx);
|
||||||
|
cachedFireball.lastUsed = self.renderFrameId;
|
||||||
|
cachedFireball.bulletLocalId = meleeBullet.BattleAttr.BulletLocalId;
|
||||||
|
cachedFireball.node.setPosition(cc.v2(wx, wy));
|
||||||
|
|
||||||
|
self.cachedFireballs.push(cachedFireball.lastUsed, cachedFireball, meleeBullet.BattleAttr.BulletLocalId);
|
||||||
|
} else {
|
||||||
|
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${meleeBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${meleeBullet.Bullet.StartupFrames}, activeFrames=${meleeBullet.Bullet.ActiveFrames}, not rendering melee node for bulletLocalId=${meleeBullet.BattleAttr.BulletLocalId}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let k in rdf.FireballBullets) {
|
||||||
|
const fireballBullet = rdf.FireballBullets[k];
|
||||||
|
const isExploding = (window.BULLET_STATE.Exploding == fireballBullet.BlState);
|
||||||
|
if (gopkgs.IsFireballBulletActive(fireballBullet, rdf) || isExploding) {
|
||||||
|
let pqNode = self.cachedFireballs.popAny(fireballBullet.BattleAttr.BulletLocalId);
|
||||||
|
let speciesName = `Fireball${fireballBullet.Bullet.SpeciesId}`;
|
||||||
|
let animName = (BULLET_STATE.Exploding == fireballBullet.BlState ? `Fireball${fireballBullet.Bullet.SpeciesId}Explosion` : speciesName);
|
||||||
|
|
||||||
|
const [wx, wy] = gopkgs.VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY);
|
||||||
|
|
||||||
|
if (null == pqNode) {
|
||||||
|
pqNode = self.cachedFireballs.pop();
|
||||||
|
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, using a new fireball node for rendering for bulletLocalId=${fireballBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
|
||||||
|
} else {
|
||||||
|
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, using a cached fireball node for rendering for bulletLocalId=${fireballBullet.BattleAttr.BulletLocalId} at wpos=(${wx},${wy})`);
|
||||||
|
}
|
||||||
|
const cachedFireball = pqNode.value;
|
||||||
|
cachedFireball.setSpecies(speciesName, fireballBullet, rdf);
|
||||||
|
const spontaneousLooping = !isExploding;
|
||||||
|
const newAnimIdx = (spontaneousLooping ? 0 : 1);
|
||||||
|
cachedFireball.updateAnim(animName, fireballBullet.FramesInBlState, fireballBullet.DirX, spontaneousLooping, rdf, newAnimIdx);
|
||||||
|
cachedFireball.lastUsed = self.renderFrameId;
|
||||||
|
cachedFireball.bulletLocalId = fireballBullet.BattleAttr.BulletLocalId;
|
||||||
|
cachedFireball.node.setPosition(cc.v2(wx, wy));
|
||||||
|
|
||||||
|
self.cachedFireballs.push(cachedFireball.lastUsed, cachedFireball, fireballBullet.BattleAttr.BulletLocalId);
|
||||||
|
} else {
|
||||||
|
//console.log(`@rdf.Id=${rdf.Id}, origRdfId=${fireballBullet.BattleAttr.OriginatedRenderFrameId}, startupFrames=${fireballBullet.Bullet.StartupFrames}, activeFrames=${fireballBullet.Bullet.ActiveFrames}, not rendering fireball node for bulletLocalId=${fireballBullet.BattleAttr.BulletLocalId}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update countdown
|
// Update countdown
|
||||||
self.countdownNanos = self.battleDurationNanos - self.renderFrameId * self.rollbackEstimatedDtNanos;
|
self.countdownNanos = self.battleDurationNanos - self.renderFrameId * self.rollbackEstimatedDtNanos;
|
||||||
if (self.countdownNanos <= 0) {
|
if (self.countdownNanos <= 0) {
|
||||||
@@ -1070,13 +1362,8 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
throw `Couldn't find renderFrame for i=${i} to rollback (are you using Firefox?), self.renderFrameId=${self.renderFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, might've been interruptted by onRoomDownsyncFrame`;
|
throw `Couldn't find renderFrame for i=${i} to rollback (are you using Firefox?), self.renderFrameId=${self.renderFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, might've been interruptted by onRoomDownsyncFrame`;
|
||||||
}
|
}
|
||||||
const j = gopkgs.ConvertToDelayedInputFrameId(i);
|
const j = gopkgs.ConvertToDelayedInputFrameId(i);
|
||||||
const delayedInputFrame = self.recentInputCache.GetByFrameId(j); // Don't make prediction here, the inputFrameDownsyncs in recentInputCache was already predicted while prefabbing
|
const delayedInputFrame = self.recentInputCache.GetByFrameId(j);
|
||||||
if (null == delayedInputFrame) {
|
|
||||||
// Shouldn't happen!
|
|
||||||
throw `Failed to get cached delayedInputFrame for i=${i}, j=${j}, renderFrameId=${self.renderFrameId}, lastUpsyncInputFrameId=${self.lastUpsyncInputFrameId}, lastAllConfirmedInputFrameId=${self.lastAllConfirmedInputFrameId}, chaserRenderFrameId=${self.chaserRenderFrameId}; recentRenderCache=${self._stringifyRecentRenderCache(false)}, recentInputCache=${self._stringifyRecentInputCache(false)}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const jPrev = gopkgs.ConvertToDelayedInputFrameId(i - 1);
|
|
||||||
if (self.frameDataLoggingEnabled) {
|
if (self.frameDataLoggingEnabled) {
|
||||||
const actuallyUsedInputClone = delayedInputFrame.InputList.slice();
|
const actuallyUsedInputClone = delayedInputFrame.InputList.slice();
|
||||||
const inputFrameDownsyncClone = {
|
const inputFrameDownsyncClone = {
|
||||||
@@ -1121,7 +1408,7 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
|
|
||||||
const selfPlayerId = self.selfPlayerInfo.Id;
|
const selfPlayerId = self.selfPlayerInfo.Id;
|
||||||
if (selfPlayerId == playerId) {
|
if (selfPlayerId == playerId) {
|
||||||
self.selfPlayerInfo.JoinIndex = immediatePlayerInfo.JoinIndex;
|
self.selfPlayerInfo.JoinIndex = immediatePlayerInfo.JoinIndex; // Update here in case of any change during WAITING phase
|
||||||
nodeAndScriptIns[1].showArrowTipNode();
|
nodeAndScriptIns[1].showArrowTipNode();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1174,7 +1461,12 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
|
|
||||||
playerDownsyncStr(playerDownsync) {
|
playerDownsyncStr(playerDownsync) {
|
||||||
if (null == playerDownsync) return "";
|
if (null == playerDownsync) return "";
|
||||||
return `{${playerDownsync.JoinIndex},${playerDownsync.VirtualGridX},${playerDownsync.VirtualGridY},${playerDownsync.VelX},${playerDownsync.VelY},${playerDownsync.FramesToRecover},${playerDownsync.InAir ? 1 : 0}}`;
|
return `{${playerDownsync.JoinIndex},${playerDownsync.VirtualGridX},${playerDownsync.VirtualGridY},${playerDownsync.VelX},${playerDownsync.VelY},${playerDownsync.FramesToRecover},${playerDownsync.InAir ? 1 : 0},${playerDownsync.OnWall ? 1 : 0}}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
fireballDownsyncStr(fireball) {
|
||||||
|
if (null == fireball) return "";
|
||||||
|
return `{${fireball.BattleAttr.BulletLocalId},${fireball.BattleAttr.OriginatedRenderFrameId},${fireball.BattleAttr.OffenderJoinIndex},${fireball.VirtualGridX},${fireball.VirtualGridY},${fireball.VelX},${fireball.VelY},${fireball.DirX},${fireball.DirY},${fireball.Bullet.HitboxSizeX},${fireball.Bullet.HitboxSizeY}}`;
|
||||||
},
|
},
|
||||||
|
|
||||||
inputFrameDownsyncStr(inputFrameDownsync) {
|
inputFrameDownsyncStr(inputFrameDownsync) {
|
||||||
@@ -1193,6 +1485,21 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
return s.join(',');
|
return s.join(',');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
gopkgsInputFrameDownsyncStr(inputFrameDownsync) {
|
||||||
|
if (null == inputFrameDownsync) return "{}";
|
||||||
|
const self = this;
|
||||||
|
let s = [];
|
||||||
|
s.push(`InputFrameId:${inputFrameDownsync.InputFrameId}`);
|
||||||
|
let ss = [];
|
||||||
|
for (let k = 0; k < window.boundRoomCapacity; ++k) {
|
||||||
|
ss.push(`"${inputFrameDownsync.InputList[k]}"`);
|
||||||
|
}
|
||||||
|
s.push(`InputList:[${ss.join(',')}]`);
|
||||||
|
s.push(`ConfirmedList:${inputFrameDownsync.ConfirmedList}`);
|
||||||
|
|
||||||
|
return `{${s.join(',')}}`;
|
||||||
|
},
|
||||||
|
|
||||||
_stringifyRdfIdToActuallyUsedInput() {
|
_stringifyRdfIdToActuallyUsedInput() {
|
||||||
const self = this;
|
const self = this;
|
||||||
let s = [];
|
let s = [];
|
||||||
@@ -1203,8 +1510,13 @@ othersForcedDownsyncRenderFrame=${JSON.stringify(othersForcedDownsyncRenderFrame
|
|||||||
for (let k in rdf.PlayersArr) {
|
for (let k in rdf.PlayersArr) {
|
||||||
playersStrBldr.push(self.playerDownsyncStr(rdf.PlayersArr[k]));
|
playersStrBldr.push(self.playerDownsyncStr(rdf.PlayersArr[k]));
|
||||||
}
|
}
|
||||||
|
const fireballsStrBldr = [];
|
||||||
|
for (let k in rdf.FireballBullets) {
|
||||||
|
fireballsStrBldr.push(self.fireballDownsyncStr(rdf.FireballBullets[k]));
|
||||||
|
}
|
||||||
s.push(`rdfId:${i}
|
s.push(`rdfId:${i}
|
||||||
players:[${playersStrBldr.join(',')}]
|
players:[${playersStrBldr.join(',')}]
|
||||||
|
fireballs:[${fireballsStrBldr.join(',')}]
|
||||||
actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
|
actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1242,6 +1554,7 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
|
|||||||
case ATK_CHARACTER_STATE.BlownUp1[0]:
|
case ATK_CHARACTER_STATE.BlownUp1[0]:
|
||||||
case ATK_CHARACTER_STATE.InAirIdle1NoJump[0]:
|
case ATK_CHARACTER_STATE.InAirIdle1NoJump[0]:
|
||||||
case ATK_CHARACTER_STATE.InAirIdle1ByJump[0]:
|
case ATK_CHARACTER_STATE.InAirIdle1ByJump[0]:
|
||||||
|
case ATK_CHARACTER_STATE.OnWall[0]:
|
||||||
[colliderWidth, colliderHeight] = [player.ColliderRadius * 2, player.ColliderRadius * 2];
|
[colliderWidth, colliderHeight] = [player.ColliderRadius * 2, player.ColliderRadius * 2];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1262,12 +1575,8 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
|
|||||||
|
|
||||||
for (let k in rdf.MeleeBullets) {
|
for (let k in rdf.MeleeBullets) {
|
||||||
const meleeBullet = rdf.MeleeBullets[k];
|
const meleeBullet = rdf.MeleeBullets[k];
|
||||||
if (
|
if (gopkgs.IsMeleeBulletActive(meleeBullet, rdf)) {
|
||||||
meleeBullet.Bullet.OriginatedRenderFrameId + meleeBullet.Bullet.StartupFrames <= rdf.Id
|
const offender = rdf.PlayersArr[meleeBullet.BattleAttr.OffenderJoinIndex - 1];
|
||||||
&&
|
|
||||||
meleeBullet.Bullet.OriginatedRenderFrameId + meleeBullet.Bullet.StartupFrames + meleeBullet.Bullet.ActiveFrames > rdf.Id
|
|
||||||
) {
|
|
||||||
const offender = rdf.PlayersArr[meleeBullet.Bullet.OffenderJoinIndex - 1];
|
|
||||||
if (1 == offender.JoinIndex) {
|
if (1 == offender.JoinIndex) {
|
||||||
g2.strokeColor = cc.Color.BLUE;
|
g2.strokeColor = cc.Color.BLUE;
|
||||||
} else {
|
} else {
|
||||||
@@ -1294,12 +1603,8 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
|
|||||||
|
|
||||||
for (let k in rdf.FireballBullets) {
|
for (let k in rdf.FireballBullets) {
|
||||||
const fireballBullet = rdf.FireballBullets[k];
|
const fireballBullet = rdf.FireballBullets[k];
|
||||||
if (
|
if (gopkgs.IsFireballBulletActive(fireballBullet, rdf)) {
|
||||||
fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames <= rdf.Id
|
const offender = rdf.PlayersArr[fireballBullet.BattleAttr.OffenderJoinIndex - 1];
|
||||||
&&
|
|
||||||
fireballBullet.Bullet.OriginatedRenderFrameId + fireballBullet.Bullet.StartupFrames + fireballBullet.Bullet.ActiveFrames > rdf.Id
|
|
||||||
) {
|
|
||||||
const offender = rdf.PlayersArr[fireballBullet.Bullet.OffenderJoinIndex - 1];
|
|
||||||
if (1 == offender.JoinIndex) {
|
if (1 == offender.JoinIndex) {
|
||||||
g2.strokeColor = cc.Color.BLUE;
|
g2.strokeColor = cc.Color.BLUE;
|
||||||
} else {
|
} else {
|
||||||
@@ -1321,4 +1626,44 @@ actuallyUsedinputList:{${self.inputFrameDownsyncStr(actuallyUsedInputClone)}}`);
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
showNetworkDoctorLabels() {
|
||||||
|
const self = this;
|
||||||
|
const [sendingFps, srvDownsyncFps, peerUpsyncFps, rollbackFrames, skippedRenderFrameCnt] = self.networkDoctor.stats();
|
||||||
|
if (self.sendingQLabel) {
|
||||||
|
self.sendingQLabel.string = `${sendingFps} fps sending`;
|
||||||
|
if (sendingFps < self.networkDoctor.inputRateThreshold) {
|
||||||
|
self.sendingQLabel.node.color = cc.Color.RED;
|
||||||
|
} else {
|
||||||
|
self.sendingQLabel.node.color = cc.Color.WHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self.inputFrameDownsyncQLabel) {
|
||||||
|
self.inputFrameDownsyncQLabel.string = `${srvDownsyncFps} fps srv-downsync`;
|
||||||
|
if (srvDownsyncFps < self.networkDoctor.inputRateThreshold) {
|
||||||
|
self.inputFrameDownsyncQLabel.node.color = cc.Color.RED;
|
||||||
|
} else {
|
||||||
|
self.inputFrameDownsyncQLabel.node.color = cc.Color.WHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self.peerInputFrameUpsyncQLabel) {
|
||||||
|
self.peerInputFrameUpsyncQLabel.string = `${peerUpsyncFps} fps peer-upsync`;
|
||||||
|
if (peerUpsyncFps > self.networkDoctor.peerUpsyncFps) {
|
||||||
|
self.peerInputFrameUpsyncQLabel.node.color = cc.Color.RED;
|
||||||
|
} else {
|
||||||
|
self.peerInputFrameUpsyncQLabel.node.color = cc.Color.WHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self.rollbackFramesLabel) {
|
||||||
|
self.rollbackFramesLabel.string = `rollbackFrames: ${rollbackFrames}`
|
||||||
|
if (rollbackFrames > self.networkDoctor.rollbackFramesThreshold) {
|
||||||
|
self.rollbackFramesLabel.node.color = cc.Color.RED;
|
||||||
|
} else {
|
||||||
|
self.rollbackFramesLabel.node.color = cc.Color.WHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (self.skippedRenderFrameCntLabel) {
|
||||||
|
self.skippedRenderFrameCntLabel.string = `${skippedRenderFrameCnt} frames skipped`
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
110
frontend/assets/scripts/NetworkDoctor.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
const RingBuffer = require('./RingBuffer');
|
||||||
|
|
||||||
|
var NetworkDoctor = function(capacity) {
|
||||||
|
this.reset(capacity);
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkDoctor.prototype.reset = function(capacity) {
|
||||||
|
this.sendingQ = new RingBuffer(capacity);
|
||||||
|
this.inputFrameDownsyncQ = new RingBuffer(capacity);
|
||||||
|
this.peerInputFrameUpsyncQ = new RingBuffer(capacity);
|
||||||
|
this.peerInputFrameUpsyncCnt = 0;
|
||||||
|
this.immediateRollbackFrames = 0;
|
||||||
|
this.skippedRenderFrameCnt = 0;
|
||||||
|
|
||||||
|
this.inputRateThreshold = gopkgs.ConvertToNoDelayInputFrameId(60);
|
||||||
|
this.peerUpsyncThreshold = 8;
|
||||||
|
this.rollbackFramesThreshold = 8; // Roughly the minimum "TurnAroundFramesToRecover".
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkDoctor.prototype.logSending = function(stFrameId, edFrameId) {
|
||||||
|
this.sendingQ.put({
|
||||||
|
i: stFrameId,
|
||||||
|
j: edFrameId,
|
||||||
|
t: Date.now()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkDoctor.prototype.logInputFrameDownsync = function(stFrameId, edFrameId) {
|
||||||
|
this.inputFrameDownsyncQ.put({
|
||||||
|
i: stFrameId,
|
||||||
|
j: edFrameId,
|
||||||
|
t: Date.now()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkDoctor.prototype.logPeerInputFrameUpsync = function(stFrameId, edFrameId) {
|
||||||
|
const firstPopped = this.peerInputFrameUpsyncQ.put({
|
||||||
|
i: stFrameId,
|
||||||
|
j: edFrameId,
|
||||||
|
t: Date.now()
|
||||||
|
});
|
||||||
|
if (null != firstPopped) {
|
||||||
|
this.peerInputFrameUpsyncCnt -= (firstPopped.j - firstPopped.i + 1);
|
||||||
|
}
|
||||||
|
this.peerInputFrameUpsyncCnt += (edFrameId - stFrameId + 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkDoctor.prototype.logRollbackFrames = function(x) {
|
||||||
|
this.immediateRollbackFrames = x;
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkDoctor.prototype.stats = function() {
|
||||||
|
let sendingFps = 0,
|
||||||
|
srvDownsyncFps = 0,
|
||||||
|
peerUpsyncFps = 0,
|
||||||
|
rollbackFrames = this.immediateRollbackFrames;
|
||||||
|
if (1 < this.sendingQ.cnt) {
|
||||||
|
const st = this.sendingQ.getByFrameId(this.sendingQ.stFrameId);
|
||||||
|
const ed = this.sendingQ.getByFrameId(this.sendingQ.edFrameId - 1);
|
||||||
|
const elapsedMillis = ed.t - st.t;
|
||||||
|
sendingFps = Math.round((ed.j - st.i) * 1000 / elapsedMillis);
|
||||||
|
}
|
||||||
|
if (1 < this.inputFrameDownsyncQ.cnt) {
|
||||||
|
const st = this.inputFrameDownsyncQ.getByFrameId(this.inputFrameDownsyncQ.stFrameId);
|
||||||
|
const ed = this.inputFrameDownsyncQ.getByFrameId(this.inputFrameDownsyncQ.edFrameId - 1);
|
||||||
|
const elapsedMillis = ed.t - st.t;
|
||||||
|
srvDownsyncFps = Math.round((ed.j - st.i) * 1000 / elapsedMillis);
|
||||||
|
}
|
||||||
|
if (1 < this.peerInputFrameUpsyncQ.cnt) {
|
||||||
|
const st = this.peerInputFrameUpsyncQ.getByFrameId(this.peerInputFrameUpsyncQ.stFrameId);
|
||||||
|
const ed = this.peerInputFrameUpsyncQ.getByFrameId(this.peerInputFrameUpsyncQ.edFrameId - 1);
|
||||||
|
const elapsedMillis = ed.t - st.t;
|
||||||
|
peerUpsyncFps = Math.round(this.peerInputFrameUpsyncCnt * 1000 / elapsedMillis);
|
||||||
|
}
|
||||||
|
return [sendingFps, srvDownsyncFps, peerUpsyncFps, rollbackFrames, this.skippedRenderFrameCnt];
|
||||||
|
};
|
||||||
|
|
||||||
|
NetworkDoctor.prototype.logSkippedRenderFrameCnt = function() {
|
||||||
|
this.skippedRenderFrameCnt += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
NetworkDoctor.prototype.isTooFast = function(mapIns) {
|
||||||
|
const [sendingFps, srvDownsyncFps, peerUpsyncFps, rollbackFrames, skippedRenderFrameCnt] = this.stats();
|
||||||
|
if (sendingFps >= this.inputRateThreshold + 3) {
|
||||||
|
// Don't send too fast
|
||||||
|
console.log(`Sending too fast, sendingFps=${sendingFps}`);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
const sendingFpsNormal = (sendingFps >= this.inputRateThreshold);
|
||||||
|
// An outstanding lag within the "inputFrameDownsyncQ" will reduce "srvDownsyncFps", HOWEVER, a constant lag wouldn't impact "srvDownsyncFps"! In native platforms we might use PING value might help as a supplement information to confirm that the "selfPlayer" is not lagged within the time accounted by "inputFrameDownsyncQ".
|
||||||
|
const recvFpsNormal = (srvDownsyncFps >= this.inputRateThreshold || peerUpsyncFps >= this.inputRateThreshold * (window.boundRoomCapacity - 1));
|
||||||
|
if (sendingFpsNormal && recvFpsNormal) {
|
||||||
|
let selfInputFrameIdFront = gopkgs.ConvertToNoDelayInputFrameId(mapIns.renderFrameId);
|
||||||
|
let minInputFrameIdFront = Number.MAX_VALUE;
|
||||||
|
for (let k = 0; k < window.boundRoomCapacity; ++k) {
|
||||||
|
if (k + 1 == mapIns.selfPlayerInfo.JoinIndex) continue;
|
||||||
|
if (mapIns.lastIndividuallyConfirmedInputFrameId[k] >= minInputFrameIdFront) continue;
|
||||||
|
minInputFrameIdFront = mapIns.lastIndividuallyConfirmedInputFrameId[k];
|
||||||
|
}
|
||||||
|
if ((selfInputFrameIdFront > minInputFrameIdFront) && ((selfInputFrameIdFront - minInputFrameIdFront) > (mapIns.inputFrameUpsyncDelayTolerance + 1))) {
|
||||||
|
// first comparison condition is to avoid numeric overflow
|
||||||
|
console.log(`Game logic ticking too fast, selfInputFrameIdFront=${selfInputFrameIdFront}, minInputFrameIdFront=${minInputFrameIdFront}, inputFrameUpsyncDelayTolerance=${mapIns.inputFrameUpsyncDelayTolerance}`);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = NetworkDoctor;
|
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"ver": "1.0.5",
|
"ver": "1.0.5",
|
||||||
"uuid": "477c07c3-0d50-4d55-96f0-6eaf9f25e2da",
|
"uuid": "affd726a-02f0-4079-aace-39fe525d7478",
|
||||||
"isPlugin": false,
|
"isPlugin": false,
|
||||||
"loadPluginInWeb": true,
|
"loadPluginInWeb": true,
|
||||||
"loadPluginInNative": true,
|
"loadPluginInNative": true,
|
@@ -11,9 +11,13 @@ cc.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
onLoad() {
|
onLoad() {
|
||||||
|
cc.game.setFrameRate(60);
|
||||||
|
cc.view.setOrientation(cc.macro.ORIENTATION_LANDSCAPE);
|
||||||
|
cc.view.enableAutoFullScreen(true);
|
||||||
const self = this;
|
const self = this;
|
||||||
window.mapIns = self;
|
window.mapIns = self;
|
||||||
self.showCriticalCoordinateLabels = true;
|
self.showCriticalCoordinateLabels = false;
|
||||||
|
self.showNetworkDoctorInfo = true;
|
||||||
|
|
||||||
const mapNode = self.node;
|
const mapNode = self.node;
|
||||||
const canvasNode = mapNode.parent;
|
const canvasNode = mapNode.parent;
|
||||||
@@ -29,7 +33,7 @@ cc.Class({
|
|||||||
/** Init required prefab ended. */
|
/** Init required prefab ended. */
|
||||||
|
|
||||||
self.inputFrameUpsyncDelayTolerance = 2;
|
self.inputFrameUpsyncDelayTolerance = 2;
|
||||||
self.collisionMinStep = 8;
|
self.collisionMinStep = 2;
|
||||||
|
|
||||||
self.renderCacheSize = 1024;
|
self.renderCacheSize = 1024;
|
||||||
self.serverFps = 60;
|
self.serverFps = 60;
|
||||||
@@ -92,9 +96,11 @@ cc.Class({
|
|||||||
|
|
||||||
const p1Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[0].x, boundaryObjs.playerStartingPositions[0].y);
|
const p1Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[0].x, boundaryObjs.playerStartingPositions[0].y);
|
||||||
const p2Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y);
|
const p2Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y);
|
||||||
const speedV = gopkgs.WorldToVirtualGridPos(1.0, 0);
|
|
||||||
const colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0);
|
const colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0);
|
||||||
|
|
||||||
|
const speciesIdList = [1, 4096];
|
||||||
|
const chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(speciesIdList);
|
||||||
|
|
||||||
const startRdf = window.pb.protos.RoomDownsyncFrame.create({
|
const startRdf = window.pb.protos.RoomDownsyncFrame.create({
|
||||||
id: window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START,
|
id: window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START,
|
||||||
playersArr: [
|
playersArr: [
|
||||||
@@ -103,7 +109,7 @@ cc.Class({
|
|||||||
joinIndex: 1,
|
joinIndex: 1,
|
||||||
virtualGridX: p1Vpos[0],
|
virtualGridX: p1Vpos[0],
|
||||||
virtualGridY: p1Vpos[1],
|
virtualGridY: p1Vpos[1],
|
||||||
speed: speedV[0],
|
speed: chConfigsOrderedByJoinIndex[0].Speed,
|
||||||
colliderRadius: colliderRadiusV[0],
|
colliderRadius: colliderRadiusV[0],
|
||||||
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
|
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
|
||||||
framesToRecover: 0,
|
framesToRecover: 0,
|
||||||
@@ -112,13 +118,14 @@ cc.Class({
|
|||||||
velX: 0,
|
velX: 0,
|
||||||
velY: 0,
|
velY: 0,
|
||||||
inAir: true,
|
inAir: true,
|
||||||
|
onWall: false,
|
||||||
}),
|
}),
|
||||||
window.pb.protos.PlayerDownsync.create({
|
window.pb.protos.PlayerDownsync.create({
|
||||||
id: 11,
|
id: 11,
|
||||||
joinIndex: 2,
|
joinIndex: 2,
|
||||||
virtualGridX: p2Vpos[0],
|
virtualGridX: p2Vpos[0],
|
||||||
virtualGridY: p2Vpos[1],
|
virtualGridY: p2Vpos[1],
|
||||||
speed: speedV[0],
|
speed: chConfigsOrderedByJoinIndex[1].Speed,
|
||||||
colliderRadius: colliderRadiusV[0],
|
colliderRadius: colliderRadiusV[0],
|
||||||
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
|
characterState: window.ATK_CHARACTER_STATE.InAirIdle1NoJump[0],
|
||||||
framesToRecover: 0,
|
framesToRecover: 0,
|
||||||
@@ -127,15 +134,45 @@ cc.Class({
|
|||||||
velX: 0,
|
velX: 0,
|
||||||
velY: 0,
|
velY: 0,
|
||||||
inAir: true,
|
inAir: true,
|
||||||
|
onWall: false,
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
speciesIdList: [4096, 0],
|
speciesIdList: speciesIdList,
|
||||||
});
|
});
|
||||||
|
|
||||||
self.selfPlayerInfo = {
|
self.selfPlayerInfo = {
|
||||||
Id: 10,
|
Id: 10,
|
||||||
JoinIndex: 1,
|
JoinIndex: 1,
|
||||||
};
|
};
|
||||||
|
if (cc.sys.isNative) {
|
||||||
|
window.onUdpMessage = (args) => {
|
||||||
|
const len = args.length;
|
||||||
|
const ui8Arr = new Uint8Array(len);
|
||||||
|
for (let i = 0; i < len; i++) {
|
||||||
|
ui8Arr[i] = args.charCodeAt(i);
|
||||||
|
}
|
||||||
|
cc.log(`#1 Js called back by CPP: onUdpMessage: args=${args}, typeof(args)=${typeof (args)}, argslen=${args.length}, ui8Arr=${ui8Arr}`);
|
||||||
|
const echoed = window.pb.protos.HolePunchUpsync.decode(ui8Arr);
|
||||||
|
cc.log(`#2 Js called back by CPP: onUdpMessage: ${JSON.stringify(echoed)}`);
|
||||||
|
};
|
||||||
|
const res1 = DelayNoMore.UdpSession.openUdpSession(8888 + self.selfPlayerInfo.JoinIndex);
|
||||||
|
const holePunchData = window.pb.protos.HolePunchUpsync.encode({
|
||||||
|
boundRoomId: 22,
|
||||||
|
intAuthToken: "foobar",
|
||||||
|
authKey: Math.floor(Math.random() * 65535),
|
||||||
|
}).finish()
|
||||||
|
//const res2 = DelayNoMore.UdpSession.punchToServer("127.0.0.1", 3000, holePunchData, 19999, holePunchData);
|
||||||
|
const res3 = DelayNoMore.UdpSession.upsertPeerUdpAddr([window.pb.protos.PeerUdpAddr.create({
|
||||||
|
ip: "192.168.31.194",
|
||||||
|
port: 6789,
|
||||||
|
authKey: 123456,
|
||||||
|
}), window.pb.protos.PeerUdpAddr.create({
|
||||||
|
ip: "192.168.1.101",
|
||||||
|
port: 8771,
|
||||||
|
authKey: 654321,
|
||||||
|
})], 2, self.selfPlayerInfo.JoinIndex);
|
||||||
|
//const res4 = DelayNoMore.UdpSession.closeUdpSession();
|
||||||
|
}
|
||||||
self.onRoomDownsyncFrame(startRdf);
|
self.onRoomDownsyncFrame(startRdf);
|
||||||
|
|
||||||
self.battleState = ALL_BATTLE_STATES.IN_BATTLE;
|
self.battleState = ALL_BATTLE_STATES.IN_BATTLE;
|
||||||
@@ -146,19 +183,13 @@ cc.Class({
|
|||||||
update(dt) {
|
update(dt) {
|
||||||
const self = this;
|
const self = this;
|
||||||
if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) {
|
if (ALL_BATTLE_STATES.IN_BATTLE == self.battleState) {
|
||||||
const elapsedMillisSinceLastFrameIdTriggered = performance.now() - self.lastRenderFrameIdTriggeredAt;
|
|
||||||
if (elapsedMillisSinceLastFrameIdTriggered < self.tooFastDtIntervalMillis) {
|
|
||||||
// [WARNING] We should avoid a frontend ticking too fast to prevent cheating, as well as ticking too slow to cause a "resync avalanche" that impacts user experience!
|
|
||||||
// console.debug("Avoiding too fast frame@renderFrameId=", self.renderFrameId, ": elapsedMillisSinceLastFrameIdTriggered=", elapsedMillisSinceLastFrameIdTriggered);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
let st = performance.now();
|
let st = performance.now();
|
||||||
let prevSelfInput = null,
|
let prevSelfInput = null,
|
||||||
currSelfInput = null;
|
currSelfInput = null;
|
||||||
const noDelayInputFrameId = gopkgs.ConvertToNoDelayInputFrameId(self.renderFrameId); // It's important that "inputDelayFrames == 0" here
|
const noDelayInputFrameId = gopkgs.ConvertToNoDelayInputFrameId(self.renderFrameId); // It's important that "inputDelayFrames == 0" here
|
||||||
if (gopkgs.ShouldGenerateInputFrameUpsync(self.renderFrameId)) {
|
if (gopkgs.ShouldGenerateInputFrameUpsync(self.renderFrameId)) {
|
||||||
const prevAndCurrInputs = self.getOrPrefabInputFrameUpsync(noDelayInputFrameId);
|
const prevAndCurrInputs = self.getOrPrefabInputFrameUpsync(noDelayInputFrameId, true);
|
||||||
prevSelfInput = prevAndCurrInputs[0];
|
prevSelfInput = prevAndCurrInputs[0];
|
||||||
currSelfInput = prevAndCurrInputs[1];
|
currSelfInput = prevAndCurrInputs[1];
|
||||||
}
|
}
|
||||||
|
@@ -12,32 +12,15 @@ var BinaryHeap = function (customCompare) {
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
this.list = [];
|
this.list = [];
|
||||||
|
this.lookupKeyToIndex = {};
|
||||||
|
|
||||||
if (customCompare) {
|
if (customCompare) {
|
||||||
this.compare = customCompare;
|
this.compare = customCompare;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
BinaryHeap.prototype.contains = function (lookupKey) {
|
||||||
* Builds a heap with the provided keys and values, this will discard the
|
return null != this.lookupKeyToIndex[lookupKey];
|
||||||
* heap's current data.
|
|
||||||
*
|
|
||||||
* @param {Array} keys An array of keys.
|
|
||||||
* @param {Array} values An array of values. This must be the same size as the
|
|
||||||
* key array.
|
|
||||||
*/
|
|
||||||
BinaryHeap.prototype.buildHeap = function (keys, values) {
|
|
||||||
if (typeof values !== 'undefined' && values.length !== keys.length) {
|
|
||||||
throw new Error('Key array must be the same length as value array');
|
|
||||||
}
|
|
||||||
|
|
||||||
var nodeArray = [];
|
|
||||||
|
|
||||||
for (var i = 0; i < keys.length; i++) {
|
|
||||||
nodeArray.push(new Node(keys[i], values ? values[i] : undefined));
|
|
||||||
}
|
|
||||||
|
|
||||||
buildHeapFromNodeArray(this, nodeArray);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,6 +28,7 @@ BinaryHeap.prototype.buildHeap = function (keys, values) {
|
|||||||
*/
|
*/
|
||||||
BinaryHeap.prototype.clear = function () {
|
BinaryHeap.prototype.clear = function () {
|
||||||
this.list.length = 0;
|
this.list.length = 0;
|
||||||
|
this.lookupKeyToIndex = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,15 +37,20 @@ BinaryHeap.prototype.clear = function () {
|
|||||||
* @return {Node} node The heap's minimum node or undefined if the heap is
|
* @return {Node} node The heap's minimum node or undefined if the heap is
|
||||||
* empty.
|
* empty.
|
||||||
*/
|
*/
|
||||||
BinaryHeap.prototype.extractMinimum = function () {
|
BinaryHeap.prototype.pop = function () {
|
||||||
if (!this.list.length) {
|
if (0 == this.list.length) {
|
||||||
return undefined;
|
return null;
|
||||||
}
|
}
|
||||||
if (this.list.length === 1) {
|
if (1 == this.list.length) {
|
||||||
|
delete this.lookupKeyToIndex[Object.keys(this.lookupKeyToIndex)[0]];
|
||||||
return this.list.shift();
|
return this.list.shift();
|
||||||
}
|
}
|
||||||
var min = this.list[0];
|
var min = this.list[0];
|
||||||
|
delete this.lookupKeyToIndex[min.lookupKey];
|
||||||
|
|
||||||
this.list[0] = this.list.pop();
|
this.list[0] = this.list.pop();
|
||||||
|
this.lookupKeyToIndex[this.list[0].lookupKey] = 0;
|
||||||
|
|
||||||
heapify(this, 0);
|
heapify(this, 0);
|
||||||
return min;
|
return min;
|
||||||
};
|
};
|
||||||
@@ -72,8 +61,8 @@ BinaryHeap.prototype.extractMinimum = function () {
|
|||||||
* @return {Node} node The heap's minimum node or undefined if the heap is
|
* @return {Node} node The heap's minimum node or undefined if the heap is
|
||||||
* empty.
|
* empty.
|
||||||
*/
|
*/
|
||||||
BinaryHeap.prototype.findMinimum = function () {
|
BinaryHeap.prototype.top = function () {
|
||||||
return this.isEmpty() ? undefined : this.list[0];
|
return this.isEmpty() ? null : this.list[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -83,25 +72,79 @@ BinaryHeap.prototype.findMinimum = function () {
|
|||||||
* @param {Object} value The value to insert.
|
* @param {Object} value The value to insert.
|
||||||
* @return {Node} node The inserted node.
|
* @return {Node} node The inserted node.
|
||||||
*/
|
*/
|
||||||
BinaryHeap.prototype.insert = function (key, value) {
|
BinaryHeap.prototype.push = function (key, value, lookupKey) {
|
||||||
var i = this.list.length;
|
var i = this.list.length;
|
||||||
var node = new Node(key, value);
|
var node = new Node(key, value, lookupKey);
|
||||||
this.list.push(node);
|
this.list.push(node);
|
||||||
var parent = getParent(i);
|
this.lookupKeyToIndex[lookupKey] = i;
|
||||||
while (typeof parent !== 'undefined' &&
|
let u = getParent(i);
|
||||||
this.compare(this.list[i], this.list[parent]) < 0) {
|
while (null != u && this.compare(this.list[i], this.list[u]) < 0) {
|
||||||
swap(this.list, i, parent);
|
swap(this.list, i, u, this.lookupKeyToIndex);
|
||||||
i = parent;
|
i = u;
|
||||||
parent = getParent(i);
|
u = getParent(i);
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
BinaryHeap.prototype.update = function (lookupKey, newKey, newValue) {
|
||||||
|
if (null == this.lookupKeyToIndex[lookupKey]) return null;
|
||||||
|
var i = this.lookupKeyToIndex[lookupKey];
|
||||||
|
|
||||||
|
this.list[i].key = newKey;
|
||||||
|
this.list[i].value = newValue;
|
||||||
|
|
||||||
|
let u = getParent(i);
|
||||||
|
if (null != u && this.compare(this.list[i], this.list[u]) < 0) {
|
||||||
|
while (null != u && this.compare(this.list[i], this.list[u]) < 0) {
|
||||||
|
swap(this.list, i, u, this.lookupKeyToIndex);
|
||||||
|
i = u;
|
||||||
|
u = getParent(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
heapify(this, i);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BinaryHeap.prototype.popAny = function (lookupKey) {
|
||||||
|
if (null == this.lookupKeyToIndex[lookupKey]) return null;
|
||||||
|
|
||||||
|
if (0 == this.list.length) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (1 == this.list.length) {
|
||||||
|
delete this.lookupKeyToIndex[Object.keys(this.lookupKeyToIndex)[0]];
|
||||||
|
return this.list.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
var i = this.lookupKeyToIndex[lookupKey];
|
||||||
|
|
||||||
|
|
||||||
|
var old = this.list[i];
|
||||||
|
delete this.lookupKeyToIndex[old.lookupKey];
|
||||||
|
|
||||||
|
this.list[i] = this.list.pop();
|
||||||
|
this.lookupKeyToIndex[this.list[i].lookupKey] = i;
|
||||||
|
|
||||||
|
let u = getParent(i);
|
||||||
|
if (null != u && this.compare(this.list[i], this.list[u]) < 0) {
|
||||||
|
while (null != u && this.compare(this.list[i], this.list[u]) < 0) {
|
||||||
|
swap(this.list, i, u, this.lookupKeyToIndex);
|
||||||
|
i = u;
|
||||||
|
u = getParent(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
heapify(this, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return old;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {boolean} Whether the heap is empty.
|
* @return {boolean} Whether the heap is empty.
|
||||||
*/
|
*/
|
||||||
BinaryHeap.prototype.isEmpty = function () {
|
BinaryHeap.prototype.isEmpty = function () {
|
||||||
return !this.list.length;
|
return 0 == this.list.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,16 +154,6 @@ BinaryHeap.prototype.size = function () {
|
|||||||
return this.list.length;
|
return this.list.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Joins another heap to this one.
|
|
||||||
*
|
|
||||||
* @param {BinaryHeap} otherHeap The other heap.
|
|
||||||
*/
|
|
||||||
BinaryHeap.prototype.union = function (otherHeap) {
|
|
||||||
var array = this.list.concat(otherHeap.list);
|
|
||||||
buildHeapFromNodeArray(this, array);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares two nodes with each other.
|
* Compares two nodes with each other.
|
||||||
*
|
*
|
||||||
@@ -147,34 +180,27 @@ BinaryHeap.prototype.compare = function (a, b) {
|
|||||||
* @param {number} i The index of the node to heapify.
|
* @param {number} i The index of the node to heapify.
|
||||||
*/
|
*/
|
||||||
function heapify(heap, i) {
|
function heapify(heap, i) {
|
||||||
var l = getLeft(i);
|
let cur = i;
|
||||||
var r = getRight(i);
|
let smallest = -1;
|
||||||
var smallest = i;
|
while (cur != smallest) {
|
||||||
|
const l = getLeft(cur);
|
||||||
|
const r = getRight(cur);
|
||||||
|
|
||||||
|
smallest = cur;
|
||||||
if (l < heap.list.length &&
|
if (l < heap.list.length &&
|
||||||
heap.compare(heap.list[l], heap.list[i]) < 0) {
|
heap.compare(heap.list[l], heap.list[smallest]) < 0) {
|
||||||
smallest = l;
|
smallest = l;
|
||||||
}
|
}
|
||||||
if (r < heap.list.length &&
|
if (r < heap.list.length &&
|
||||||
heap.compare(heap.list[r], heap.list[smallest]) < 0) {
|
heap.compare(heap.list[r], heap.list[smallest]) < 0) {
|
||||||
smallest = r;
|
smallest = r;
|
||||||
}
|
}
|
||||||
if (smallest !== i) {
|
|
||||||
swap(heap.list, i, smallest);
|
|
||||||
heapify(heap, smallest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (smallest !== cur) {
|
||||||
* Builds a heap from a node array, this will discard the heap's current data.
|
swap(heap.list, cur, smallest, heap.lookupKeyToIndex);
|
||||||
*
|
cur = smallest;
|
||||||
* @private
|
smallest = -1;
|
||||||
* @param {BinaryHeap} heap The heap to override.
|
}
|
||||||
* @param {Node[]} nodeArray The array of nodes for the new heap.
|
|
||||||
*/
|
|
||||||
function buildHeapFromNodeArray(heap, nodeArray) {
|
|
||||||
heap.list = nodeArray;
|
|
||||||
for (var i = Math.floor(heap.list.length / 2); i >= 0; i--) {
|
|
||||||
heapify(heap, i);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,10 +212,16 @@ function buildHeapFromNodeArray(heap, nodeArray) {
|
|||||||
* @param {number} a The index of the first element.
|
* @param {number} a The index of the first element.
|
||||||
* @param {number} b The index of the second element.
|
* @param {number} b The index of the second element.
|
||||||
*/
|
*/
|
||||||
function swap(array, a, b) {
|
function swap(array, a, b, lookupKeyToIndex) {
|
||||||
|
var aLookupKey = array[a].lookupKey;
|
||||||
|
var bLookupKey = array[b].lookupKey;
|
||||||
|
|
||||||
var temp = array[a];
|
var temp = array[a];
|
||||||
array[a] = array[b];
|
array[a] = array[b];
|
||||||
array[b] = temp;
|
array[b] = temp;
|
||||||
|
|
||||||
|
lookupKeyToIndex[aLookupKey] = b;
|
||||||
|
lookupKeyToIndex[bLookupKey] = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -200,8 +232,8 @@ function swap(array, a, b) {
|
|||||||
* @return {number} The index of the node's parent.
|
* @return {number} The index of the node's parent.
|
||||||
*/
|
*/
|
||||||
function getParent(i) {
|
function getParent(i) {
|
||||||
if (i === 0) {
|
if (0 == i) {
|
||||||
return undefined;
|
return null;
|
||||||
}
|
}
|
||||||
return Math.floor((i - 1) / 2);
|
return Math.floor((i - 1) / 2);
|
||||||
}
|
}
|
||||||
@@ -235,9 +267,10 @@ function getRight(i) {
|
|||||||
* @param {Object} key The key of the new node.
|
* @param {Object} key The key of the new node.
|
||||||
* @param {Object} value The value of the new node.
|
* @param {Object} value The value of the new node.
|
||||||
*/
|
*/
|
||||||
function Node(key, value) {
|
function Node(key, value, lookupKey) {
|
||||||
this.key = key;
|
this.key = key;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
|
this.lookupKey = lookupKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = BinaryHeap;
|
module.exports = BinaryHeap;
|
9
frontend/assets/scripts/PriorityQueue.js.meta
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"ver": "1.0.5",
|
||||||
|
"uuid": "20a75b4a-e220-42cd-bab4-9fc63a289b3f",
|
||||||
|
"isPlugin": false,
|
||||||
|
"loadPluginInWeb": true,
|
||||||
|
"loadPluginInNative": true,
|
||||||
|
"loadPluginInEditor": false,
|
||||||
|
"subMetas": {}
|
||||||
|
}
|
@@ -11,14 +11,6 @@ cc.Class({
|
|||||||
type: cc.Object,
|
type: cc.Object,
|
||||||
default: null
|
default: null
|
||||||
},
|
},
|
||||||
myAvatarNode: {
|
|
||||||
type: cc.Node,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
myNameNode: {
|
|
||||||
type: cc.Node,
|
|
||||||
default: null,
|
|
||||||
},
|
|
||||||
rankingNodes: {
|
rankingNodes: {
|
||||||
type: [cc.Node],
|
type: [cc.Node],
|
||||||
default: [],
|
default: [],
|
||||||
@@ -46,22 +38,6 @@ cc.Class({
|
|||||||
|
|
||||||
showPlayerInfo(playerRichInfoDict) {
|
showPlayerInfo(playerRichInfoDict) {
|
||||||
this.showRanking(playerRichInfoDict);
|
this.showRanking(playerRichInfoDict);
|
||||||
this.showMyAvatar();
|
|
||||||
this.showMyName();
|
|
||||||
},
|
|
||||||
|
|
||||||
showMyName() {
|
|
||||||
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
|
|
||||||
let name = 'No name';
|
|
||||||
if (null == selfPlayerInfo.displayName || "" == selfPlayerInfo.displayName) {
|
|
||||||
name = selfPlayerInfo.name;
|
|
||||||
} else {
|
|
||||||
name = selfPlayerInfo.displayName;
|
|
||||||
}
|
|
||||||
if (!this.myNameNode) return;
|
|
||||||
const myNameNodeLabel = this.myNameNode.getComponent(cc.Label);
|
|
||||||
if (!myNameNodeLabel || null == name) return;
|
|
||||||
myNameNodeLabel.string = name;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
showRanking(playerRichInfoDict) {
|
showRanking(playerRichInfoDict) {
|
||||||
@@ -115,42 +91,6 @@ cc.Class({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
showMyAvatar() {
|
|
||||||
const self = this;
|
|
||||||
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
|
|
||||||
let remoteUrl = selfPlayerInfo.avatar;
|
|
||||||
if (remoteUrl == null || remoteUrl == '') {
|
|
||||||
cc.log(`No avatar to show for myself, check storage.`);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
cc.loader.load({
|
|
||||||
url: remoteUrl,
|
|
||||||
type: 'jpg'
|
|
||||||
}, function(err, texture) {
|
|
||||||
if (err != null || texture == null) {
|
|
||||||
console.log(err);
|
|
||||||
} else {
|
|
||||||
const sf = new cc.SpriteFrame();
|
|
||||||
sf.setTexture(texture);
|
|
||||||
self.myAvatarNode.getComponent(cc.Sprite).spriteFrame = sf;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
showRibbon(winnerInfo, ribbonNode) {
|
|
||||||
const selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer'));
|
|
||||||
const texture = (selfPlayerInfo.playerId == winnerInfo.id) ? "textures/resultPanel/WinRibbon" : "textures/resultPanel/loseRibbon";
|
|
||||||
cc.loader.loadRes(texture, cc.SpriteFrame, function(err, spriteFrame) {
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ribbonNode.getComponent(cc.Sprite).spriteFrame = spriteFrame;
|
|
||||||
});
|
|
||||||
|
|
||||||
},
|
|
||||||
|
|
||||||
onClose(evt) {
|
onClose(evt) {
|
||||||
if (this.node.parent) {
|
if (this.node.parent) {
|
||||||
this.node.parent.removeChild(this.node);
|
this.node.parent.removeChild(this.node);
|
||||||
|
@@ -13,9 +13,12 @@ var RingBuffer = function(capacity) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
RingBuffer.prototype.put = function(item) {
|
RingBuffer.prototype.put = function(item) {
|
||||||
|
let firstPopped = null;
|
||||||
while (0 < this.cnt && this.cnt >= this.n) {
|
while (0 < this.cnt && this.cnt >= this.n) {
|
||||||
// Make room for the new element
|
// Make room for the new element
|
||||||
this.pop();
|
const popped = this.pop();
|
||||||
|
if (null == firstPopped)
|
||||||
|
firstPopped = popped;
|
||||||
}
|
}
|
||||||
this.eles[this.ed] = item
|
this.eles[this.ed] = item
|
||||||
this.edFrameId++;
|
this.edFrameId++;
|
||||||
@@ -24,6 +27,7 @@ RingBuffer.prototype.put = function(item) {
|
|||||||
if (this.ed >= this.n) {
|
if (this.ed >= this.n) {
|
||||||
this.ed -= this.n; // Deliberately not using "%" operator for performance concern
|
this.ed -= this.n; // Deliberately not using "%" operator for performance concern
|
||||||
}
|
}
|
||||||
|
return firstPopped;
|
||||||
};
|
};
|
||||||
|
|
||||||
RingBuffer.prototype.pop = function() {
|
RingBuffer.prototype.pop = function() {
|
||||||
|
@@ -106,8 +106,13 @@ cc.Class({
|
|||||||
this.cachedBtnDownLevel = 0;
|
this.cachedBtnDownLevel = 0;
|
||||||
this.cachedBtnLeftLevel = 0;
|
this.cachedBtnLeftLevel = 0;
|
||||||
this.cachedBtnRightLevel = 0;
|
this.cachedBtnRightLevel = 0;
|
||||||
|
|
||||||
|
this.realtimeBtnALevel = 0;
|
||||||
this.cachedBtnALevel = 0;
|
this.cachedBtnALevel = 0;
|
||||||
|
this.btnAEdgeTriggerLock = false;
|
||||||
|
this.realtimeBtnBLevel = 0;
|
||||||
this.cachedBtnBLevel = 0;
|
this.cachedBtnBLevel = 0;
|
||||||
|
this.btnBEdgeTriggerLock = false;
|
||||||
|
|
||||||
this.canvasNode = this.mapNode.parent;
|
this.canvasNode = this.mapNode.parent;
|
||||||
this.mainCameraNode = this.canvasNode.getChildByName("Main Camera"); // Cannot drag and assign the `mainCameraNode` from CocosCreator EDITOR directly, otherwise it'll cause an infinite loading time, till v2.1.0.
|
this.mainCameraNode = this.canvasNode.getChildByName("Main Camera"); // Cannot drag and assign the `mainCameraNode` from CocosCreator EDITOR directly, otherwise it'll cause an infinite loading time, till v2.1.0.
|
||||||
@@ -163,31 +168,25 @@ cc.Class({
|
|||||||
|
|
||||||
if (self.btnA) {
|
if (self.btnA) {
|
||||||
self.btnA.on(cc.Node.EventType.TOUCH_START, function(evt) {
|
self.btnA.on(cc.Node.EventType.TOUCH_START, function(evt) {
|
||||||
self.cachedBtnALevel = 1;
|
self._triggerEdgeBtnA(true);
|
||||||
evt.target.runAction(cc.scaleTo(0.1, 0.3));
|
|
||||||
});
|
});
|
||||||
self.btnA.on(cc.Node.EventType.TOUCH_END, function(evt) {
|
self.btnA.on(cc.Node.EventType.TOUCH_END, function(evt) {
|
||||||
self.cachedBtnALevel = 0;
|
self._triggerEdgeBtnA(false);
|
||||||
evt.target.runAction(cc.scaleTo(0.1, 1.0));
|
|
||||||
});
|
});
|
||||||
self.btnA.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
|
self.btnA.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
|
||||||
self.cachedBtnALevel = 0;
|
self._triggerEdgeBtnA(false);
|
||||||
evt.target.runAction(cc.scaleTo(0.1, 1.0));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self.btnB) {
|
if (self.btnB) {
|
||||||
self.btnB.on(cc.Node.EventType.TOUCH_START, function(evt) {
|
self.btnB.on(cc.Node.EventType.TOUCH_START, function(evt) {
|
||||||
self.cachedBtnBLevel = 1;
|
self._triggerEdgeBtnB(true);
|
||||||
evt.target.runAction(cc.scaleTo(0.1, 0.3));
|
|
||||||
});
|
});
|
||||||
self.btnB.on(cc.Node.EventType.TOUCH_END, function(evt) {
|
self.btnB.on(cc.Node.EventType.TOUCH_END, function(evt) {
|
||||||
self.cachedBtnBLevel = 0;
|
self._triggerEdgeBtnB(false);
|
||||||
evt.target.runAction(cc.scaleTo(0.1, 1.0));
|
|
||||||
});
|
});
|
||||||
self.btnB.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
|
self.btnB.on(cc.Node.EventType.TOUCH_CANCEL, function(evt) {
|
||||||
self.cachedBtnBLevel = 0;
|
self._triggerEdgeBtnB(false);
|
||||||
evt.target.runAction(cc.scaleTo(0.1, 1.0));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,22 +194,38 @@ cc.Class({
|
|||||||
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function(evt) {
|
cc.systemEvent.on(cc.SystemEvent.EventType.KEY_DOWN, function(evt) {
|
||||||
switch (evt.keyCode) {
|
switch (evt.keyCode) {
|
||||||
case cc.macro.KEY.w:
|
case cc.macro.KEY.w:
|
||||||
|
self.cachedBtnUpLevel = 0;
|
||||||
|
self.cachedBtnDownLevel = 0;
|
||||||
|
self.cachedBtnLeftLevel = 0;
|
||||||
|
self.cachedBtnRightLevel = 0;
|
||||||
self.cachedBtnUpLevel = 1;
|
self.cachedBtnUpLevel = 1;
|
||||||
break;
|
break;
|
||||||
case cc.macro.KEY.s:
|
case cc.macro.KEY.s:
|
||||||
|
self.cachedBtnUpLevel = 0;
|
||||||
|
self.cachedBtnDownLevel = 0;
|
||||||
|
self.cachedBtnLeftLevel = 0;
|
||||||
|
self.cachedBtnRightLevel = 0;
|
||||||
self.cachedBtnDownLevel = 1;
|
self.cachedBtnDownLevel = 1;
|
||||||
break;
|
break;
|
||||||
case cc.macro.KEY.a:
|
case cc.macro.KEY.a:
|
||||||
|
self.cachedBtnUpLevel = 0;
|
||||||
|
self.cachedBtnDownLevel = 0;
|
||||||
|
self.cachedBtnLeftLevel = 0;
|
||||||
|
self.cachedBtnRightLevel = 0;
|
||||||
self.cachedBtnLeftLevel = 1;
|
self.cachedBtnLeftLevel = 1;
|
||||||
break;
|
break;
|
||||||
case cc.macro.KEY.d:
|
case cc.macro.KEY.d:
|
||||||
|
self.cachedBtnUpLevel = 0;
|
||||||
|
self.cachedBtnDownLevel = 0;
|
||||||
|
self.cachedBtnLeftLevel = 0;
|
||||||
|
self.cachedBtnRightLevel = 0;
|
||||||
self.cachedBtnRightLevel = 1;
|
self.cachedBtnRightLevel = 1;
|
||||||
break;
|
break;
|
||||||
case cc.macro.KEY.h:
|
case cc.macro.KEY.h:
|
||||||
self.cachedBtnALevel = 1;
|
self._triggerEdgeBtnA(true);
|
||||||
break;
|
break;
|
||||||
case cc.macro.KEY.j:
|
case cc.macro.KEY.j:
|
||||||
self.cachedBtnBLevel = 1;
|
self._triggerEdgeBtnB(true);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -232,10 +247,10 @@ cc.Class({
|
|||||||
self.cachedBtnRightLevel = 0;
|
self.cachedBtnRightLevel = 0;
|
||||||
break;
|
break;
|
||||||
case cc.macro.KEY.h:
|
case cc.macro.KEY.h:
|
||||||
self.cachedBtnALevel = 0;
|
self._triggerEdgeBtnA(false);
|
||||||
break;
|
break;
|
||||||
case cc.macro.KEY.j:
|
case cc.macro.KEY.j:
|
||||||
self.cachedBtnBLevel = 0;
|
self._triggerEdgeBtnB(false);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -448,6 +463,12 @@ cc.Class({
|
|||||||
const discretizedDir = this.discretizeDirection(this.stickhead.x, this.stickhead.y, this.joyStickEps).encodedIdx; // There're only 9 dirs, thus using only the lower 4-bits
|
const discretizedDir = this.discretizeDirection(this.stickhead.x, this.stickhead.y, this.joyStickEps).encodedIdx; // There're only 9 dirs, thus using only the lower 4-bits
|
||||||
const btnALevel = (this.cachedBtnALevel << 4);
|
const btnALevel = (this.cachedBtnALevel << 4);
|
||||||
const btnBLevel = (this.cachedBtnBLevel << 5);
|
const btnBLevel = (this.cachedBtnBLevel << 5);
|
||||||
|
|
||||||
|
this.cachedBtnALevel = this.realtimeBtnALevel;
|
||||||
|
this.cachedBtnBLevel = this.realtimeBtnBLevel;
|
||||||
|
|
||||||
|
this.btnAEdgeTriggerLock = false;
|
||||||
|
this.btnBEdgeTriggerLock = false;
|
||||||
return (btnBLevel + btnALevel + discretizedDir);
|
return (btnBLevel + btnALevel + discretizedDir);
|
||||||
},
|
},
|
||||||
|
|
||||||
@@ -466,4 +487,30 @@ cc.Class({
|
|||||||
btnBLevel: btnBLevel,
|
btnBLevel: btnBLevel,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_triggerEdgeBtnA(rising) {
|
||||||
|
this.realtimeBtnALevel = (rising ? 1 : 0);
|
||||||
|
if (!this.btnAEdgeTriggerLock && (1 - this.realtimeBtnALevel) == this.cachedBtnALevel) {
|
||||||
|
this.cachedBtnALevel = this.realtimeBtnALevel;
|
||||||
|
this.btnAEdgeTriggerLock = true;
|
||||||
|
}
|
||||||
|
if (rising) {
|
||||||
|
this.btnA.runAction(cc.scaleTo(0.1, 0.3));
|
||||||
|
} else {
|
||||||
|
this.btnA.runAction(cc.scaleTo(0.1, 0.5));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
_triggerEdgeBtnB(rising, evt) {
|
||||||
|
this.realtimeBtnBLevel = (rising ? 1 : 0);
|
||||||
|
if (!this.btnBEdgeTriggerLock && (1 - this.realtimeBtnBLevel) == this.cachedBtnBLevel) {
|
||||||
|
this.cachedBtnBLevel = this.realtimeBtnBLevel;
|
||||||
|
this.btnBEdgeTriggerLock = true;
|
||||||
|
}
|
||||||
|
if (rising) {
|
||||||
|
this.btnB.runAction(cc.scaleTo(0.1, 0.3));
|
||||||
|
} else {
|
||||||
|
this.btnB.runAction(cc.scaleTo(0.1, 0.5));
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
@@ -11,6 +11,8 @@ window.DOWNSYNC_MSG_ACT_HB_REQ = 1;
|
|||||||
window.DOWNSYNC_MSG_ACT_INPUT_BATCH = 2;
|
window.DOWNSYNC_MSG_ACT_INPUT_BATCH = 2;
|
||||||
window.DOWNSYNC_MSG_ACT_BATTLE_STOPPED = 3;
|
window.DOWNSYNC_MSG_ACT_BATTLE_STOPPED = 3;
|
||||||
window.DOWNSYNC_MSG_ACT_FORCED_RESYNC = 4;
|
window.DOWNSYNC_MSG_ACT_FORCED_RESYNC = 4;
|
||||||
|
window.DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH = 5;
|
||||||
|
window.DOWNSYNC_MSG_ACT_PEER_UDP_ADDR = 6;
|
||||||
|
|
||||||
window.sendSafely = function(msgStr) {
|
window.sendSafely = function(msgStr) {
|
||||||
/**
|
/**
|
||||||
@@ -32,7 +34,7 @@ window.closeWSConnection = function(code, reason) {
|
|||||||
console.log(`"window.clientSession" is already closed or destroyed.`);
|
console.log(`"window.clientSession" is already closed or destroyed.`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log(`Closing "window.clientSession" from the client-side.`);
|
console.log(`Closing "window.clientSession" from the client-side with code=${code}.`);
|
||||||
window.clientSession.close(code, reason);
|
window.clientSession.close(code, reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,12 +44,24 @@ window.getBoundRoomIdFromPersistentStorage = function() {
|
|||||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return cc.sys.localStorage.getItem("boundRoomId");
|
const boundRoomIdStr = cc.sys.localStorage.getItem("boundRoomId");
|
||||||
|
return (null == boundRoomIdStr ? null : parseInt(boundRoomIdStr));
|
||||||
|
};
|
||||||
|
|
||||||
|
window.getBoundRoomCapacityFromPersistentStorage = function() {
|
||||||
|
const boundRoomIdExpiresAt = parseInt(cc.sys.localStorage.getItem("boundRoomIdExpiresAt"));
|
||||||
|
if (!boundRoomIdExpiresAt || Date.now() >= boundRoomIdExpiresAt) {
|
||||||
|
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const boundRoomCapacityStr = cc.sys.localStorage.getItem("boundRoomCapacity");
|
||||||
|
return (null == boundRoomCapacityStr ? null : parseInt(boundRoomCapacityStr));
|
||||||
};
|
};
|
||||||
|
|
||||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage = function() {
|
window.clearBoundRoomIdInBothVolatileAndPersistentStorage = function() {
|
||||||
window.boundRoomId = null;
|
window.boundRoomId = null;
|
||||||
cc.sys.localStorage.removeItem("boundRoomId");
|
cc.sys.localStorage.removeItem("boundRoomId");
|
||||||
|
cc.sys.localStorage.removeItem("boundRoomCapacity");
|
||||||
cc.sys.localStorage.removeItem("boundRoomIdExpiresAt");
|
cc.sys.localStorage.removeItem("boundRoomIdExpiresAt");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,17 +70,51 @@ window.clearSelfPlayer = function() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
window.boundRoomId = getBoundRoomIdFromPersistentStorage();
|
window.boundRoomId = getBoundRoomIdFromPersistentStorage();
|
||||||
|
window.boundRoomCapacity = getBoundRoomCapacityFromPersistentStorage();
|
||||||
window.handleHbRequirements = function(resp) {
|
window.handleHbRequirements = function(resp) {
|
||||||
|
console.log(`Handle hb requirements #1`);
|
||||||
if (constants.RET_CODE.OK != resp.ret) return;
|
if (constants.RET_CODE.OK != resp.ret) return;
|
||||||
if (null == window.boundRoomId) {
|
// The assignment of "window.mapIns" is inside "Map.onLoad", which precedes "initPersistentSessionClient".
|
||||||
|
window.mapIns.selfPlayerInfo = JSON.parse(cc.sys.localStorage.getItem('selfPlayer')); // This field is kept for distinguishing "self" and "others".
|
||||||
|
window.mapIns.selfPlayerInfo.Id = window.mapIns.selfPlayerInfo.playerId;
|
||||||
|
window.mapIns.selfPlayerInfo.JoinIndex = resp.peerJoinIndex;
|
||||||
|
console.log(`Handle hb requirements #2`);
|
||||||
|
if (null == window.boundRoomId || null == window.boundRoomCapacity) {
|
||||||
window.boundRoomId = resp.bciFrame.boundRoomId;
|
window.boundRoomId = resp.bciFrame.boundRoomId;
|
||||||
|
window.boundRoomCapacity = resp.bciFrame.boundRoomCapacity;
|
||||||
cc.sys.localStorage.setItem('boundRoomId', window.boundRoomId);
|
cc.sys.localStorage.setItem('boundRoomId', window.boundRoomId);
|
||||||
|
cc.sys.localStorage.setItem('boundRoomCapacity', window.boundRoomCapacity);
|
||||||
cc.sys.localStorage.setItem('boundRoomIdExpiresAt', Date.now() + 10 * 60 * 1000); // Temporarily hardcoded, for `boundRoomId` only.
|
cc.sys.localStorage.setItem('boundRoomIdExpiresAt', Date.now() + 10 * 60 * 1000); // Temporarily hardcoded, for `boundRoomId` only.
|
||||||
}
|
}
|
||||||
|
console.log(`Handle hb requirements #3`);
|
||||||
if (window.handleBattleColliderInfo) {
|
if (window.handleBattleColliderInfo) {
|
||||||
window.handleBattleColliderInfo(resp.bciFrame);
|
window.handleBattleColliderInfo(resp.bciFrame);
|
||||||
}
|
}
|
||||||
|
console.log(`Handle hb requirements #4`);
|
||||||
|
|
||||||
|
if (!cc.sys.isNative) {
|
||||||
|
console.log(`Handle hb requirements #5, web`);
|
||||||
|
window.initSecondarySession(null, window.boundRoomId);
|
||||||
|
} else {
|
||||||
|
console.log(`Handle hb requirements #5, native, bciFrame.battleUdpTunnel=${resp.bciFrame.battleUdpTunnel}, selfPlayerInfo=${JSON.stringify(window.mapIns.selfPlayerInfo)}`);
|
||||||
|
const res1 = DelayNoMore.UdpSession.openUdpSession(8888 + window.mapIns.selfPlayerInfo.JoinIndex);
|
||||||
|
window.mapIns.selfPlayerInfo.udpTunnelAuthKey = resp.bciFrame.battleUdpTunnel.authKey;
|
||||||
|
const intAuthToken = window.mapIns.selfPlayerInfo.intAuthToken;
|
||||||
|
const authKey = Math.floor(Math.random() * 65535);
|
||||||
|
window.mapIns.selfPlayerInfo.authKey = authKey;
|
||||||
|
const holePunchData = window.pb.protos.HolePunchUpsync.encode({
|
||||||
|
boundRoomId: window.boundRoomId,
|
||||||
|
intAuthToken: intAuthToken,
|
||||||
|
authKey: authKey,
|
||||||
|
}).finish();
|
||||||
|
const udpTunnelHolePunchData = window.pb.protos.WsReq.encode({
|
||||||
|
msgId: Date.now(),
|
||||||
|
playerId: window.mapIns.selfPlayerInfo.Id,
|
||||||
|
act: window.UPSYNC_MSG_ACT_PLAYER_CMD,
|
||||||
|
authKey: resp.bciFrame.battleUdpTunnel.authKey,
|
||||||
|
}).finish();
|
||||||
|
const res2 = DelayNoMore.UdpSession.punchToServer(backendAddress.HOST, 3000, holePunchData, resp.bciFrame.battleUdpTunnel.port, udpTunnelHolePunchData);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
function _uint8ToBase64(uint8Arr) {
|
function _uint8ToBase64(uint8Arr) {
|
||||||
@@ -124,14 +172,13 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
|||||||
urlToConnect = urlToConnect + "&expectedRoomId=" + expectedRoomId;
|
urlToConnect = urlToConnect + "&expectedRoomId=" + expectedRoomId;
|
||||||
} else {
|
} else {
|
||||||
window.boundRoomId = getBoundRoomIdFromPersistentStorage();
|
window.boundRoomId = getBoundRoomIdFromPersistentStorage();
|
||||||
|
window.boundRoomCapacity = getBoundRoomCapacityFromPersistentStorage();
|
||||||
if (null != window.boundRoomId) {
|
if (null != window.boundRoomId) {
|
||||||
console.log("initPersistentSessionClient with boundRoomId == " + boundRoomId);
|
console.log("initPersistentSessionClient with boundRoomId == " + boundRoomId);
|
||||||
urlToConnect = urlToConnect + "&boundRoomId=" + window.boundRoomId;
|
urlToConnect = urlToConnect + "&boundRoomId=" + window.boundRoomId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentHistoryState = window.history && window.history.state ? window.history.state : {};
|
|
||||||
|
|
||||||
const clientSession = new WebSocket(urlToConnect);
|
const clientSession = new WebSocket(urlToConnect);
|
||||||
clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob"
|
clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob"
|
||||||
|
|
||||||
@@ -176,6 +223,19 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
|||||||
}
|
}
|
||||||
mapIns.onRoomDownsyncFrame(resp.rdf, resp.inputFrameDownsyncBatch);
|
mapIns.onRoomDownsyncFrame(resp.rdf, resp.inputFrameDownsyncBatch);
|
||||||
break;
|
break;
|
||||||
|
case window.DOWNSYNC_MSG_ACT_PEER_UDP_ADDR:
|
||||||
|
console.warn(`Got DOWNSYNC_MSG_ACT_PEER_UDP_ADDR resp=${JSON.stringify(resp, null, 2)}`);
|
||||||
|
if (cc.sys.isNative) {
|
||||||
|
const peerJoinIndex = resp.peerJoinIndex;
|
||||||
|
const peerAddrList = resp.rdf.peerUdpAddrList;
|
||||||
|
console.log(`Got DOWNSYNC_MSG_ACT_PEER_UDP_ADDR peerAddrList=${JSON.stringify(peerAddrList)}; boundRoomCapacity=${window.boundRoomCapacity}`);
|
||||||
|
for (let j = 0; j < 3; ++j) {
|
||||||
|
setTimeout(()=> {
|
||||||
|
DelayNoMore.UdpSession.upsertPeerUdpAddr(peerAddrList, window.boundRoomCapacity, window.mapIns.selfPlayerInfo.JoinIndex); // In C++ impl it actually broadcasts the peer-punching message to all known peers within "window.boundRoomCapacity"
|
||||||
|
}, j*500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -192,13 +252,21 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
|||||||
clientSession.onclose = function(evt) {
|
clientSession.onclose = function(evt) {
|
||||||
// [WARNING] The callback "onclose" might be called AFTER the webpage is refreshed with "1001 == evt.code".
|
// [WARNING] The callback "onclose" might be called AFTER the webpage is refreshed with "1001 == evt.code".
|
||||||
console.warn(`The WS clientSession is closed: evt=${JSON.stringify(evt)}, evt.code=${evt.code}`);
|
console.warn(`The WS clientSession is closed: evt=${JSON.stringify(evt)}, evt.code=${evt.code}`);
|
||||||
|
if (cc.sys.isNative) {
|
||||||
|
if (mapIns.frameDataLoggingEnabled) {
|
||||||
|
console.warn(`${mapIns._stringifyRdfIdToActuallyUsedInput()}
|
||||||
|
`);
|
||||||
|
}
|
||||||
|
DelayNoMore.UdpSession.closeUdpSession();
|
||||||
|
}
|
||||||
switch (evt.code) {
|
switch (evt.code) {
|
||||||
case constants.RET_CODE.CLIENT_MISMATCHED_RENDER_FRAME:
|
case constants.RET_CODE.CLIENT_MISMATCHED_RENDER_FRAME:
|
||||||
break;
|
break;
|
||||||
case constants.RET_CODE.BATTLE_STOPPED:
|
case constants.RET_CODE.BATTLE_STOPPED:
|
||||||
// deliberately do nothing
|
// deliberately do nothing
|
||||||
if (mapIns.frameDataLoggingEnabled) {
|
if (mapIns.frameDataLoggingEnabled) {
|
||||||
console.warn(`${mapIns._stringifyRdfIdToActuallyUsedInput()}`);
|
console.warn(`${mapIns._stringifyRdfIdToActuallyUsedInput()}
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case constants.RET_CODE.PLAYER_NOT_ADDABLE_TO_ROOM:
|
case constants.RET_CODE.PLAYER_NOT_ADDABLE_TO_ROOM:
|
||||||
@@ -213,9 +281,10 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
|||||||
case constants.RET_CODE.MYSQL_ERROR:
|
case constants.RET_CODE.MYSQL_ERROR:
|
||||||
case constants.RET_CODE.PLAYER_NOT_FOUND:
|
case constants.RET_CODE.PLAYER_NOT_FOUND:
|
||||||
case constants.RET_CODE.PLAYER_CHEATING:
|
case constants.RET_CODE.PLAYER_CHEATING:
|
||||||
case 1006: // Peer(i.e. the backend) gone unexpectedly
|
case 1006: // Peer(i.e. the backend) gone unexpectedly, but not working for "cc.sys.isNative"
|
||||||
if (mapIns.frameDataLoggingEnabled) {
|
if (mapIns.frameDataLoggingEnabled) {
|
||||||
console.warn(`${mapIns._stringifyRdfIdToActuallyUsedInput()}`);
|
console.warn(`${mapIns._stringifyRdfIdToActuallyUsedInput()}
|
||||||
|
`);
|
||||||
}
|
}
|
||||||
window.clearLocalStorageAndBackToLoginScene(true);
|
window.clearLocalStorageAndBackToLoginScene(true);
|
||||||
break;
|
break;
|
||||||
@@ -227,16 +296,68 @@ window.initPersistentSessionClient = function(onopenCb, expectedRoomId) {
|
|||||||
|
|
||||||
window.clearLocalStorageAndBackToLoginScene = function(shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage) {
|
window.clearLocalStorageAndBackToLoginScene = function(shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage) {
|
||||||
console.warn("+++++++ Calling `clearLocalStorageAndBackToLoginScene`");
|
console.warn("+++++++ Calling `clearLocalStorageAndBackToLoginScene`");
|
||||||
|
window.clearSelfPlayer();
|
||||||
|
if (true != shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage) {
|
||||||
|
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
||||||
|
}
|
||||||
|
|
||||||
if (window.mapIns && window.mapIns.musicEffectManagerScriptIns) {
|
if (window.mapIns && window.mapIns.musicEffectManagerScriptIns) {
|
||||||
window.mapIns.musicEffectManagerScriptIns.stopAllMusic();
|
window.mapIns.musicEffectManagerScriptIns.stopAllMusic();
|
||||||
}
|
}
|
||||||
|
|
||||||
window.closeWSConnection();
|
|
||||||
window.clearSelfPlayer();
|
|
||||||
if (true != shouldRetainBoundRoomIdInBothVolatileAndPersistentStorage) {
|
|
||||||
window.clearBoundRoomIdInBothVolatileAndPersistentStorage();
|
|
||||||
}
|
|
||||||
cc.director.loadScene('login');
|
cc.director.loadScene('login');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// For secondary ws session
|
||||||
|
window.initSecondarySession = function(onopenCb, boundRoomId) {
|
||||||
|
if (window.secondarySession && window.secondarySession.readyState == WebSocket.OPEN) {
|
||||||
|
if (null != onopenCb) {
|
||||||
|
onopenCb();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selfPlayerStr = cc.sys.localStorage.getItem("selfPlayer");
|
||||||
|
const selfPlayer = null == selfPlayerStr ? null : JSON.parse(selfPlayerStr);
|
||||||
|
const intAuthToken = null == selfPlayer ? "" : selfPlayer.intAuthToken;
|
||||||
|
|
||||||
|
let urlToConnect = backendAddress.PROTOCOL.replace('http', 'ws') + '://' + backendAddress.HOST + ":" + backendAddress.PORT + "/tsrhtSecondary?isSecondary=true&intAuthToken=" + intAuthToken + "&boundRoomId=" + boundRoomId;
|
||||||
|
|
||||||
|
const clientSession = new WebSocket(urlToConnect);
|
||||||
|
clientSession.binaryType = 'arraybuffer'; // Make 'event.data' of 'onmessage' an "ArrayBuffer" instead of a "Blob"
|
||||||
|
|
||||||
|
clientSession.onopen = function(evt) {
|
||||||
|
console.warn("The secondary WS clientSession is opened.");
|
||||||
|
window.secondarySession = clientSession;
|
||||||
|
if (null == onopenCb) return;
|
||||||
|
onopenCb();
|
||||||
|
};
|
||||||
|
|
||||||
|
clientSession.onmessage = function(evt) {
|
||||||
|
if (null == evt || null == evt.data) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const resp = window.pb.protos.WsResp.decode(new Uint8Array(evt.data));
|
||||||
|
//console.log(`Got non-empty onmessage decoded: resp.act=${resp.act}`);
|
||||||
|
switch (resp.act) {
|
||||||
|
case window.DOWNSYNC_MSG_ACT_PEER_INPUT_BATCH:
|
||||||
|
mapIns.onPeerInputFrameUpsync(resp.peerJoinIndex, resp.inputFrameDownsyncBatch, false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Secondary ws session, unexpected error when parsing data of:", evt.data, e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
clientSession.onerror = function(evt) {
|
||||||
|
console.error("Secondary ws session, error caught on the WS clientSession: ", evt);
|
||||||
|
};
|
||||||
|
|
||||||
|
clientSession.onclose = function(evt) {
|
||||||
|
// [WARNING] The callback "onclose" might be called AFTER the webpage is refreshed with "1001 == evt.code".
|
||||||
|
console.warn(`Secondary ws session is closed: evt=${JSON.stringify(evt)}, evt.code=${evt.code}`);
|
||||||
|
};
|
||||||
|
};
|
||||||
|