diff --git a/battle_srv/models/player.go b/battle_srv/models/player.go index 12e6648..f84d2cc 100644 --- a/battle_srv/models/player.go +++ b/battle_srv/models/player.go @@ -96,7 +96,7 @@ func getPlayer(cond sq.Eq) (*Player, error) { p.CreatedAt = int64(val.(int64)) } } - Logger.Info("Queried player from db", zap.Any("cond", cond), zap.Any("p", p), zap.Any("pd", pd), zap.Any("cols", cols), zap.Any("rowValues", vals)) + Logger.Debug("Queried player from db", zap.Any("cond", cond), zap.Any("p", p), zap.Any("pd", pd), zap.Any("cols", cols), zap.Any("rowValues", vals)) } p.PlayerDownsync = pd return &p, nil diff --git a/battle_srv/models/room.go b/battle_srv/models/room.go index 9019f2b..773d9d1 100644 --- a/battle_srv/models/room.go +++ b/battle_srv/models/room.go @@ -476,7 +476,7 @@ func (pR *Room) StartBattle() { for playerId, player := range pR.Players { if swapped := atomic.CompareAndSwapInt32(&player.BattleState, PlayerBattleStateIns.ACTIVE, PlayerBattleStateIns.ACTIVE); !swapped { - // [WARNING] DON'T send anything if the player is disconnected, because it could jam the channel and cause significant delay upon "battle recovery for reconnected player". + // [WARNING] DON'T send anything if the player is not yet active, because it could jam the channel and cause significant delay upon "battle recovery for reconnected player". continue } if 0 == pR.RenderFrameId { @@ -995,6 +995,12 @@ func (pR *Room) OnPlayerBattleColliderAcked(playerId int32) bool { This function is triggered by an upsync message via WebSocket, thus downsync sending is also available by now. */ + currPlayerBattleState := atomic.LoadInt32(&(eachPlayer.BattleState)) + if PlayerBattleStateIns.DISCONNECTED == currPlayerBattleState || PlayerBattleStateIns.LOST == currPlayerBattleState { + // [WARNING] DON'T try to send any message to an inactive player! + continue + } + switch targetPlayer.BattleState { case PlayerBattleStateIns.ADDED_PENDING_BATTLE_COLLIDER_ACK: playerAckedFrame := &RoomDownsyncFrame{ @@ -1338,7 +1344,7 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF thatPlayerInNextFrame := nextRenderFramePlayers[playerId] if 0 < thatPlayerInNextFrame.FramesToRecover { // No need to process inputs for this player, but there might be bullet pushbacks on this player - // Also note that in this case we keep "CharacterState" of this player from last render frame + // Also note that in this case we keep "CharacterState" of this player from last render frame playerCollider.X += bulletPushbacks[joinIndex-1].X playerCollider.Y += bulletPushbacks[joinIndex-1].Y // Update in the collision system @@ -1374,7 +1380,7 @@ func (pR *Room) applyInputFrameDownsyncDynamicsOnSingleRenderFrame(delayedInputF Logger.Debug(fmt.Sprintf("roomId=%v, playerId=%v triggered a falling-edge of btnA at currRenderFrame.id=%v, delayedInputFrame.id=%v", pR.Id, playerId, currRenderFrame.Id, delayedInputFrame.InputFrameId)) } else { // No bullet trigger, process movement inputs - // Note that by now "0 == thatPlayerInNextFrame.FramesToRecover", we should change "CharacterState" to "WALKING" or "IDLE" depending on player inputs + // Note that by now "0 == thatPlayerInNextFrame.FramesToRecover", we should change "CharacterState" to "WALKING" or "IDLE" depending on player inputs if 0 != decodedInput.Dx || 0 != decodedInput.Dy { thatPlayerInNextFrame.DirX = decodedInput.Dx thatPlayerInNextFrame.DirY = decodedInput.Dy diff --git a/battle_srv/models/room_heap_manager.go b/battle_srv/models/room_heap_manager.go index 05daa76..ead3f46 100644 --- a/battle_srv/models/room_heap_manager.go +++ b/battle_srv/models/room_heap_manager.go @@ -5,6 +5,7 @@ import ( . "dnmshared" "fmt" "go.uber.org/zap" + "strings" "sync" ) @@ -21,11 +22,13 @@ var ( func (pPq *RoomHeap) PrintInOrder() { pq := *pPq - fmt.Printf("The RoomHeap instance now contains:\n") + s := make([]string, 0) + s = append(s, fmt.Sprintf("The RoomHeap instance now contains:")) for i := 0; i < len(pq); i++ { - fmt.Printf("{index: %d, roomID: %d, score: %.2f} ", i, pq[i].Id, pq[i].Score) + s = append(s, fmt.Sprintf("{index: %d, roomID: %d, score: %.2f} ", i, pq[i].Id, pq[i].Score)) } - fmt.Printf("\n") + + Logger.Debug(strings.Join(s, "\n")) } func (pq RoomHeap) Len() int { return len(pq) } diff --git a/battle_srv/ws/serve.go b/battle_srv/ws/serve.go index 0c2955e..7bcea1b 100644 --- a/battle_srv/ws/serve.go +++ b/battle_srv/ws/serve.go @@ -16,7 +16,6 @@ import ( "time" . "dnmshared" - "runtime/debug" ) const ( @@ -47,9 +46,8 @@ func Serve(c *gin.Context) { c.AbortWithStatus(http.StatusBadRequest) return } - Logger.Info("Finding PlayerLogin record for ws authentication:", zap.Any("intAuthToken", token)) boundRoomId := 0 - expectRoomId := 0 + expectedRoomId := 0 var err error if boundRoomIdStr, hasBoundRoomId := c.GetQuery("boundRoomId"); hasBoundRoomId { boundRoomId, err = strconv.Atoi(boundRoomIdStr) @@ -58,27 +56,28 @@ func Serve(c *gin.Context) { c.AbortWithStatus(http.StatusBadRequest) return } - Logger.Info("Finding PlayerLogin record for ws authentication:", zap.Any("intAuthToken", token), zap.Any("boundRoomId", boundRoomId)) - } - if expectRoomIdStr, hasExpectRoomId := c.GetQuery("expectedRoomId"); hasExpectRoomId { - expectRoomId, err = strconv.Atoi(expectRoomIdStr) + Logger.Debug("Finding PlayerLogin record for ws authentication:", zap.Any("intAuthToken", token), zap.Any("boundRoomId", boundRoomId)) + } else if expectedRoomIdStr, hasExpectRoomId := c.GetQuery("expectedRoomId"); hasExpectRoomId { + expectedRoomId, err = strconv.Atoi(expectedRoomIdStr) if err != nil { c.AbortWithStatus(http.StatusBadRequest) return } - Logger.Info("Finding PlayerLogin record for ws authentication:", zap.Any("intAuthToken", token), zap.Any("expectedRoomId", expectRoomId)) + Logger.Debug("Finding PlayerLogin record for ws authentication:", zap.Any("intAuthToken", token), zap.Any("expectedRoomId", expectedRoomId)) + } else { + Logger.Debug("Finding PlayerLogin record for ws authentication:", zap.Any("intAuthToken", token)) } // 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.Info("PlayerLogin record not found for ws authentication:", zap.Any("intAuthToken", token)) + Logger.Warn("PlayerLogin record not found for ws authentication:", zap.Any("intAuthToken", token)) c.AbortWithStatus(http.StatusBadRequest) return } - Logger.Info("PlayerLogin record has been found for ws authentication:", zap.Any("playerId", playerId)) + Logger.Info("PlayerLogin record has been found for ws authentication:", zap.Any("playerId", playerId), zap.Any("intAuthToken", token), zap.Any("boundRoomId", boundRoomId), zap.Any("expectedRoomId", expectedRoomId)) conn, err := upgrader.Upgrade(c.Writer, c.Request, nil) if err != nil { @@ -160,14 +159,14 @@ func Serve(c *gin.Context) { signalToCloseConnOfThisPlayer(Constants.RetCode.PlayerNotFound, "") } - Logger.Info("Player has logged in and its profile is found from persistent storage:", zap.Any("playerId", playerId), zap.Any("play", pPlayer)) + Logger.Debug("Player has logged in and its profile is found from persistent storage:", zap.Any("playerId", playerId), zap.Any("player", pPlayer)) // Find a room to join. - Logger.Info("About to acquire RoomHeapMux for player:", zap.Any("playerId", playerId)) + Logger.Debug("About to acquire RoomHeapMux for player:", zap.Any("playerId", playerId)) (*(models.RoomHeapMux)).Lock() defer func() { (*(models.RoomHeapMux)).Unlock() - Logger.Info("Released RoomHeapMux for player:", zap.Any("playerId", playerId)) + Logger.Debug("Released RoomHeapMux for player:", zap.Any("playerId", playerId)) }() defer func() { if r := recover(); r != nil { @@ -175,13 +174,12 @@ func Serve(c *gin.Context) { signalToCloseConnOfThisPlayer(Constants.RetCode.UnknownError, "") } }() - Logger.Info("Acquired RoomHeapMux for player:", zap.Any("playerId", playerId)) + Logger.Debug("Acquired RoomHeapMux for player:", zap.Any("playerId", playerId)) // Logger.Info("The RoomHeapManagerIns has:", zap.Any("addr", fmt.Sprintf("%p", models.RoomHeapManagerIns)), zap.Any("size", len(*(models.RoomHeapManagerIns)))) playerSuccessfullyAddedToRoom := false if 0 < boundRoomId { if tmpPRoom, existent := (*models.RoomMapManagerIns)[int32(boundRoomId)]; existent { pRoom = tmpPRoom - Logger.Info("Successfully got:\n", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Any("forBoundRoomId", boundRoomId)) res := pRoom.ReAddPlayerIfPossible(pPlayer, conn, signalToCloseConnOfThisPlayer) if !res { Logger.Warn("Failed to get:\n", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Any("forBoundRoomId", boundRoomId)) @@ -189,19 +187,16 @@ func Serve(c *gin.Context) { playerSuccessfullyAddedToRoom = true } } - } - - if 0 < expectRoomId { - if tmpRoom, existent := (*models.RoomMapManagerIns)[int32(expectRoomId)]; existent { + } else if 0 < expectedRoomId { + if tmpRoom, existent := (*models.RoomMapManagerIns)[int32(expectedRoomId)]; existent { pRoom = tmpRoom - Logger.Info("Successfully got:\n", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Any("forExpectedRoomId", expectRoomId)) if pRoom.ReAddPlayerIfPossible(pPlayer, conn, signalToCloseConnOfThisPlayer) { playerSuccessfullyAddedToRoom = true } else if pRoom.AddPlayerIfPossible(pPlayer, conn, signalToCloseConnOfThisPlayer) { playerSuccessfullyAddedToRoom = true } else { - Logger.Warn("Failed to get:\n", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Any("forExpectedRoomId", expectRoomId)) + Logger.Warn("Failed to get:\n", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId), zap.Any("forExpectedRoomId", expectedRoomId)) playerSuccessfullyAddedToRoom = false } @@ -221,7 +216,7 @@ func Serve(c *gin.Context) { signalToCloseConnOfThisPlayer(Constants.RetCode.LocallyNoAvailableRoom, fmt.Sprintf("Cannot pop a (*Room) for playerId == %v!", playerId)) } else { pRoom = tmpRoom - Logger.Info("Successfully popped:\n", zap.Any("roomId", pRoom.Id), zap.Any("playerId", playerId)) + Logger.Info("Successfully popped:\n", zap.Any("roomId", pRoom.Id), zap.Any("forPlayerId", playerId)) res := pRoom.AddPlayerIfPossible(pPlayer, conn, signalToCloseConnOfThisPlayer) if !res { signalToCloseConnOfThisPlayer(Constants.RetCode.PlayerNotAddableToRoom, fmt.Sprintf("AddPlayerIfPossible returns false for roomId == %v, playerId == %v!", pRoom.Id, playerId)) @@ -361,7 +356,7 @@ func Serve(c *gin.Context) { receivingLoopAgainstPlayer := func() error { defer func() { if r := recover(); r != nil { - Logger.Error("Goroutine `receivingLoopAgainstPlayer`, recovery spot#1, recovered from: ", zap.Any("panic", r), zap.Any("callstack", debug.Stack())) + Logger.Error("Goroutine `receivingLoopAgainstPlayer`, recovery spot#1, recovered from: ", zap.Any("panic", r)) } Logger.Info("Goroutine `receivingLoopAgainstPlayer` is stopped for:", zap.Any("playerId", playerId), zap.Any("roomId", pRoom.Id)) }() diff --git a/frontend/assets/resources/prefabs/GameRule.prefab b/frontend/assets/resources/prefabs/GameRule.prefab index 96adfb4..511a40e 100644 --- a/frontend/assets/resources/prefabs/GameRule.prefab +++ b/frontend/assets/resources/prefabs/GameRule.prefab @@ -8,7 +8,8 @@ "__id__": 1 }, "optimizationPolicy": 0, - "asyncLoadAssets": false + "asyncLoadAssets": false, + "readonly": false }, { "__type__": "cc.Node", @@ -20,24 +21,20 @@ "__id__": 2 }, { - "__id__": 9 - }, - { - "__id__": 17 + "__id__": 10 } ], "_active": true, - "_level": 1, "_components": [ { - "__id__": 20 + "__id__": 13 }, { - "__id__": 21 + "__id__": 14 } ], "_prefab": { - "__id__": 22 + "__id__": 15 }, "_opacity": 255, "_color": { @@ -57,17 +54,6 @@ "x": 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": { "__type__": "TypedArray", "ctor": "Float64Array", @@ -83,231 +69,20 @@ 1, 1 ] - } - }, - { - "__type__": "cc.Node", - "_name": "ruleNode", - "_objFlags": 0, - "_parent": { - "__id__": 1 }, - "_children": [ - { - "__id__": 3 - } - ], - "_active": true, - "_level": 2, - "_components": [ - { - "__id__": 7 - } - ], - "_prefab": { - "__id__": 8 - }, - "_opacity": 255, - "_color": { - "__type__": "cc.Color", - "r": 255, - "g": 255, - "b": 255, - "a": 255 - }, - "_contentSize": { - "__type__": "cc.Size", - "width": 644, - "height": 793 - }, - "_anchorPoint": { - "__type__": "cc.Vec2", - "x": 0.5, - "y": 0.5 - }, - "_quat": { - "__type__": "cc.Quat", + "_eulerAngles": { + "__type__": "cc.Vec3", "x": 0, "y": 0, - "z": 0, - "w": 1 + "z": 0 }, "_skewX": 0, "_skewY": 0, + "_is3DNode": false, + "_groupIndex": 0, "groupIndex": 0, - "_id": "", - "_trs": { - "__type__": "TypedArray", - "ctor": "Float64Array", - "array": [ - 0, - 257, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1 - ] - } - }, - { - "__type__": "cc.Node", - "_name": "rule", - "_objFlags": 0, - "_parent": { - "__id__": 2 - }, - "_children": [], - "_active": true, - "_level": 3, - "_components": [ - { - "__id__": 4 - }, - { - "__id__": 5 - } - ], - "_prefab": { - "__id__": 6 - }, - "_opacity": 255, - "_color": { - "__type__": "cc.Color", - "r": 0, - "g": 0, - "b": 0, - "a": 255 - }, - "_contentSize": { - "__type__": "cc.Size", - "width": 550, - "height": 560 - }, - "_anchorPoint": { - "__type__": "cc.Vec2", - "x": 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": { - "__type__": "TypedArray", - "ctor": "Float64Array", - "array": [ - 48, - 12, - 0, - 0, - 0, - 0, - 1, - 1, - 1, - 1 - ] - } - }, - { - "__type__": "cc.Label", - "_name": "", - "_objFlags": 0, - "node": { - "__id__": 3 - }, - "_enabled": true, - "_useOriginalSize": false, - "_string": "gameRule.tip", - "_N$string": "gameRule.tip", - "_fontSize": 38, - "_lineHeight": 70, - "_enableWrapText": true, - "_N$file": null, - "_isSystemFontUsed": true, - "_spacingX": 0, - "_batchAsBitmap": false, - "_N$horizontalAlign": 1, - "_N$verticalAlign": 1, - "_N$fontFamily": "Arial", - "_N$overflow": 1, - "_N$cacheMode": 0, "_id": "" }, - { - "__type__": "744dcs4DCdNprNhG0xwq6FK", - "_name": "", - "_objFlags": 0, - "node": { - "__id__": 3 - }, - "_enabled": true, - "_dataID": "gameRule.tip", - "_id": "" - }, - { - "__type__": "cc.PrefabInfo", - "root": { - "__id__": 1 - }, - "asset": { - "__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109" - }, - "fileId": "11EBmT5DNNXbQDiC9n1CEy", - "sync": false - }, - { - "__type__": "cc.Sprite", - "_name": "", - "_objFlags": 0, - "node": { - "__id__": 2 - }, - "_enabled": true, - "_spriteFrame": { - "__uuid__": "0fe43223-61fc-4cb8-95bd-bd9e8f01ce8f" - }, - "_type": 0, - "_sizeMode": 1, - "_fillType": 0, - "_fillCenter": { - "__type__": "cc.Vec2", - "x": 0, - "y": 0 - }, - "_fillStart": 0, - "_fillRange": 0, - "_isTrimmedMode": true, - "_state": 0, - "_atlas": { - "__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4" - }, - "_srcBlendFactor": 770, - "_dstBlendFactor": 771, - "_id": "" - }, - { - "__type__": "cc.PrefabInfo", - "root": { - "__id__": 1 - }, - "asset": { - "__uuid__": "32b8e752-8362-4783-a4a6-1160af8b7109" - }, - "fileId": "9exF2/yWJPwK/biWKavf16", - "sync": false - }, { "__type__": "cc.Node", "_name": "modeButton", @@ -317,21 +92,20 @@ }, "_children": [ { - "__id__": 10 + "__id__": 3 } ], "_active": true, - "_level": 2, "_components": [ { - "__id__": 14 + "__id__": 7 }, { - "__id__": 15 + "__id__": 8 } ], "_prefab": { - "__id__": 16 + "__id__": 9 }, "_opacity": 255, "_color": { @@ -351,17 +125,6 @@ "x": 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": { "__type__": "TypedArray", "ctor": "Float64Array", @@ -377,28 +140,39 @@ 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": "Label", "_objFlags": 0, "_parent": { - "__id__": 9 + "__id__": 2 }, "_children": [], "_active": true, - "_level": 0, "_components": [ { - "__id__": 11 + "__id__": 4 }, { - "__id__": 12 + "__id__": 5 } ], "_prefab": { - "__id__": 13 + "__id__": 6 }, "_opacity": 255, "_color": { @@ -418,17 +192,6 @@ "x": 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": { "__type__": "TypedArray", "ctor": "Float64Array", @@ -444,16 +207,33 @@ 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", "_name": "", "_objFlags": 0, "node": { - "__id__": 10 + "__id__": 3 }, "_enabled": true, + "_materials": [ + { + "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" + } + ], "_useOriginalSize": false, "_string": "gameRule.mode", "_N$string": "gameRule.mode", @@ -476,7 +256,7 @@ "_name": "", "_objFlags": 0, "node": { - "__id__": 10 + "__id__": 3 }, "_enabled": true, "_dataID": "gameRule.mode", @@ -498,9 +278,16 @@ "_name": "", "_objFlags": 0, "node": { - "__id__": 9 + "__id__": 2 }, "_enabled": true, + "_materials": [ + { + "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" + } + ], + "_srcBlendFactor": 770, + "_dstBlendFactor": 771, "_spriteFrame": { "__uuid__": "081ad337-20ca-4313-ae3e-bb6dee3547b7" }, @@ -515,12 +302,9 @@ "_fillStart": 0, "_fillRange": 0, "_isTrimmedMode": true, - "_state": 0, "_atlas": { "__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4" }, - "_srcBlendFactor": 770, - "_dstBlendFactor": 771, "_id": "" }, { @@ -528,9 +312,11 @@ "_name": "", "_objFlags": 0, "node": { - "__id__": 9 + "__id__": 2 }, "_enabled": true, + "_normalMaterial": null, + "_grayMaterial": null, "duration": 0.1, "zoomScale": 1.2, "clickEvents": [], @@ -589,7 +375,7 @@ "hoverSprite": null, "_N$disabledSprite": null, "_N$target": { - "__id__": 9 + "__id__": 2 }, "_id": "" }, @@ -613,14 +399,13 @@ }, "_children": [], "_active": true, - "_level": 2, "_components": [ { - "__id__": 18 + "__id__": 11 } ], "_prefab": { - "__id__": 19 + "__id__": 12 }, "_opacity": 255, "_color": { @@ -640,17 +425,6 @@ "x": 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": { "__type__": "TypedArray", "ctor": "Float64Array", @@ -666,16 +440,35 @@ 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__": 17 + "__id__": 10 }, "_enabled": true, + "_materials": [ + { + "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" + } + ], + "_srcBlendFactor": 770, + "_dstBlendFactor": 771, "_spriteFrame": { "__uuid__": "153d890a-fc37-4d59-8779-93a8fb19fa85" }, @@ -690,12 +483,9 @@ "_fillStart": 0, "_fillRange": 0, "_isTrimmedMode": true, - "_state": 0, "_atlas": { "__uuid__": "030d9286-e8a2-40cf-98f8-baf713f0b8c4" }, - "_srcBlendFactor": 770, - "_dstBlendFactor": 771, "_id": "" }, { @@ -718,7 +508,7 @@ }, "_enabled": true, "modeButton": { - "__id__": 15 + "__id__": 8 }, "mapNode": null, "_id": "" @@ -731,6 +521,13 @@ "__id__": 1 }, "_enabled": true, + "_materials": [ + { + "__uuid__": "eca5d2f2-8ef6-41c2-bbe6-f9c79d09c432" + } + ], + "_srcBlendFactor": 770, + "_dstBlendFactor": 771, "_spriteFrame": { "__uuid__": "7838f276-ab48-445a-b858-937dd27d9520" }, @@ -745,10 +542,7 @@ "_fillStart": 0, "_fillRange": 0, "_isTrimmedMode": true, - "_state": 0, "_atlas": null, - "_srcBlendFactor": 770, - "_dstBlendFactor": 771, "_id": "" }, { diff --git a/frontend/assets/scripts/AttackingCharacter.js b/frontend/assets/scripts/AttackingCharacter.js index a396ca0..ee5c553 100644 --- a/frontend/assets/scripts/AttackingCharacter.js +++ b/frontend/assets/scripts/AttackingCharacter.js @@ -12,6 +12,11 @@ for (let k in window.ATK_CHARACTER_STATE) { window.ATK_CHARACTER_STATE_ARR.push(window.ATK_CHARACTER_STATE[k]); } +/* +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 animation -- can also suffice this requirement, yet if we want to develop 3D frontend in the future, working with skeletal animation will make a smoother transition. + +I've also spent sometime in extending "ccc wrapped dragoneBones.ArmatureDisplay" for enabling "gotoAndPlayByFrame" in CACHE mode (in REALTIME mode it's just the same as what's done here), but the debugging is an unexpected brainteaser -- not worth the time. +*/ cc.Class({ extends: BaseCharacter, properties: {