mirror of
				https://github.com/genxium/DelayNoMore
				synced 2025-10-31 03:17:20 +00:00 
			
		
		
		
	Minor update to floating number precision.
This commit is contained in:
		| @@ -128,11 +128,12 @@ func calRoomScore(inRoomPlayerCount int32, roomPlayerCnt int, currentRoomBattleS | |||||||
| } | } | ||||||
|  |  | ||||||
| type Room struct { | type Room struct { | ||||||
| 	Id              int32 | 	Id                   int32 | ||||||
| 	Capacity        int | 	Capacity             int | ||||||
| 	Players         map[int32]*Player | 	playerColliderRadius float64 | ||||||
| 	PlayersArr      []*Player // ordered by joinIndex | 	Players              map[int32]*Player | ||||||
| 	CollisionSysMap map[int32]*resolv.Object | 	PlayersArr           []*Player // ordered by joinIndex | ||||||
|  | 	CollisionSysMap      map[int32]*resolv.Object | ||||||
| 	/** | 	/** | ||||||
| 		 * The following `PlayerDownsyncSessionDict` is NOT individually put | 		 * The following `PlayerDownsyncSessionDict` is NOT individually put | ||||||
| 		 * under `type Player struct` for a reason. | 		 * under `type Player struct` for a reason. | ||||||
| @@ -415,7 +416,12 @@ func (pR *Room) StartBattle() { | |||||||
| 	pR.RenderFrameBuffer.Put(kickoffFrame) | 	pR.RenderFrameBuffer.Put(kickoffFrame) | ||||||
|  |  | ||||||
| 	// Refresh "Colliders" | 	// Refresh "Colliders" | ||||||
| 	pR.refreshColliders() | 	spaceW := pR.StageDiscreteW * pR.StageTileW | ||||||
|  | 	spaceH := pR.StageDiscreteH * pR.StageTileH | ||||||
|  |  | ||||||
|  | 	spaceOffsetX := float64(spaceW) * 0.5 | ||||||
|  | 	spaceOffsetY := float64(spaceH) * 0.5 | ||||||
|  | 	pR.refreshColliders(spaceW, spaceH, spaceOffsetX, spaceOffsetY) | ||||||
|  |  | ||||||
| 	/** | 	/** | ||||||
| 	 * Will be triggered from a goroutine which executes the critical `Room.AddPlayerIfPossible`, thus the `battleMainLoop` should be detached. | 	 * Will be triggered from a goroutine which executes the critical `Room.AddPlayerIfPossible`, thus the `battleMainLoop` should be detached. | ||||||
| @@ -488,7 +494,7 @@ func (pR *Room) StartBattle() { | |||||||
| 					// Apply "all-confirmed inputFrames" to move forward "pR.CurDynamicsRenderFrameId" | 					// Apply "all-confirmed inputFrames" to move forward "pR.CurDynamicsRenderFrameId" | ||||||
| 					nextDynamicsRenderFrameId := pR.ConvertToLastUsedRenderFrameId(pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames) | 					nextDynamicsRenderFrameId := pR.ConvertToLastUsedRenderFrameId(pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames) | ||||||
| 					Logger.Debug(fmt.Sprintf("roomId=%v, room.RenderFrameId=%v, LastAllConfirmedInputFrameId=%v, InputDelayFrames=%v, nextDynamicsRenderFrameId=%v", pR.Id, pR.RenderFrameId, pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames, nextDynamicsRenderFrameId)) | 					Logger.Debug(fmt.Sprintf("roomId=%v, room.RenderFrameId=%v, LastAllConfirmedInputFrameId=%v, InputDelayFrames=%v, nextDynamicsRenderFrameId=%v", pR.Id, pR.RenderFrameId, pR.LastAllConfirmedInputFrameId, pR.InputDelayFrames, nextDynamicsRenderFrameId)) | ||||||
| 					pR.applyInputFrameDownsyncDynamics(pR.CurDynamicsRenderFrameId, nextDynamicsRenderFrameId) | 					pR.applyInputFrameDownsyncDynamics(pR.CurDynamicsRenderFrameId, nextDynamicsRenderFrameId, spaceOffsetX, spaceOffsetY) | ||||||
| 					dynamicsDuration = utils.UnixtimeNano() - dynamicsStartedAt | 					dynamicsDuration = utils.UnixtimeNano() - dynamicsStartedAt | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| @@ -792,6 +798,7 @@ func (pR *Room) Dismiss() { | |||||||
| func (pR *Room) OnDismissed() { | func (pR *Room) OnDismissed() { | ||||||
|  |  | ||||||
| 	// Always instantiates new HeapRAM blocks and let the old blocks die out due to not being retained by any root reference. | 	// Always instantiates new HeapRAM blocks and let the old blocks die out due to not being retained by any root reference. | ||||||
|  | 	pR.playerColliderRadius = float64(12) // hardcoded | ||||||
| 	pR.Players = make(map[int32]*Player) | 	pR.Players = make(map[int32]*Player) | ||||||
| 	pR.PlayersArr = make([]*Player, pR.Capacity) | 	pR.PlayersArr = make([]*Player, pR.Capacity) | ||||||
| 	pR.CollisionSysMap = make(map[int32]*resolv.Object) | 	pR.CollisionSysMap = make(map[int32]*resolv.Object) | ||||||
| @@ -1175,7 +1182,7 @@ func (pR *Room) forceConfirmationIfApplicable() uint64 { | |||||||
| 	return unconfirmedMask | 	return unconfirmedMask | ||||||
| } | } | ||||||
|  |  | ||||||
| func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRenderFrameId int32) { | func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRenderFrameId int32, spaceOffsetX, spaceOffsetY float64) { | ||||||
| 	if fromRenderFrameId >= toRenderFrameId { | 	if fromRenderFrameId >= toRenderFrameId { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| @@ -1216,26 +1223,27 @@ func (pR *Room) applyInputFrameDownsyncDynamics(fromRenderFrameId int32, toRende | |||||||
| 				playerCollider := pR.CollisionSysMap[collisionPlayerIndex] | 				playerCollider := pR.CollisionSysMap[collisionPlayerIndex] | ||||||
| 				if collision := playerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil { | 				if collision := playerCollider.Check(oldDx, oldDy, "Barrier"); collision != nil { | ||||||
| 					playerShape := playerCollider.Shape.(*resolv.ConvexPolygon) | 					playerShape := playerCollider.Shape.(*resolv.ConvexPolygon) | ||||||
|                     for _, obj := range collision.Objects { | 					for _, obj := range collision.Objects { | ||||||
|                         barrierShape := obj.Shape.(*resolv.ConvexPolygon) | 						barrierShape := obj.Shape.(*resolv.ConvexPolygon) | ||||||
|                         if overlapped, pushbackX, pushbackY := CalcPushbacks(oldDx, oldDy, playerShape, barrierShape); overlapped { | 						if overlapped, pushbackX, pushbackY := CalcPushbacks(oldDx, oldDy, playerShape, barrierShape); overlapped { | ||||||
|                             Logger.Debug(fmt.Sprintf("Collided & overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v, pushbackX=%v, pushbackY=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), pushbackX, pushbackY)) | 							Logger.Debug(fmt.Sprintf("Collided & overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v, pushbackX=%v, pushbackY=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape), pushbackX, pushbackY)) | ||||||
|                             dx -= pushbackX | 							dx -= pushbackX | ||||||
|                             dy -= pushbackY | 							dy -= pushbackY | ||||||
|                         } else { | 						} else { | ||||||
|                             Logger.Debug(fmt.Sprintf("Collided BUT not overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape))) | 							Logger.Debug(fmt.Sprintf("Collided BUT not overlapped: player.X=%v, player.Y=%v, oldDx=%v, oldDy=%v, playerShape=%v, toCheckBarrier=%v", playerCollider.X, playerCollider.Y, oldDx, oldDy, ConvexPolygonStr(playerShape), ConvexPolygonStr(barrierShape))) | ||||||
|                         } | 						} | ||||||
|                     }  | 					} | ||||||
| 				} | 				} | ||||||
| 				playerCollider.X += dx | 				playerCollider.X += dx | ||||||
| 				playerCollider.Y += dy | 				playerCollider.Y += dy | ||||||
|  |  | ||||||
| 				// Update in "collision space" | 				// Update in "collision space" | ||||||
| 				playerCollider.Update() | 				playerCollider.Update() | ||||||
|  |  | ||||||
| 				player.Dir.Dx = decodedInput[0] | 				player.Dir.Dx = decodedInput[0] | ||||||
| 				player.Dir.Dy = decodedInput[1] | 				player.Dir.Dy = decodedInput[1] | ||||||
| 				player.X += dx | 				player.X = playerCollider.X + pR.playerColliderRadius - spaceOffsetX | ||||||
| 				player.Y += dy | 				player.Y = playerCollider.Y + pR.playerColliderRadius - spaceOffsetY | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| @@ -1253,19 +1261,13 @@ func (pR *Room) inputFrameIdDebuggable(inputFrameId int32) bool { | |||||||
| 	return 0 == (inputFrameId % 10) | 	return 0 == (inputFrameId % 10) | ||||||
| } | } | ||||||
|  |  | ||||||
| func (pR *Room) refreshColliders() { | func (pR *Room) refreshColliders(spaceW, spaceH int32, spaceOffsetX, spaceOffsetY float64) { | ||||||
| 	playerColliderRadius := float64(12) // hardcoded |  | ||||||
| 	// Kindly note that by now, we've already got all the shapes in the tmx file into "pR.(Players | Barriers)" from "ParseTmxLayersAndGroups" | 	// Kindly note that by now, we've already got all the shapes in the tmx file into "pR.(Players | Barriers)" from "ParseTmxLayersAndGroups" | ||||||
| 	spaceW := pR.StageDiscreteW * pR.StageTileW |  | ||||||
| 	spaceH := pR.StageDiscreteH * pR.StageTileH |  | ||||||
|  |  | ||||||
| 	spaceOffsetX := float64(spaceW) * 0.5 |  | ||||||
| 	spaceOffsetY := float64(spaceH) * 0.5 |  | ||||||
|  |  | ||||||
| 	minStep := int(3)                                                    // the approx minimum distance a player can move per frame | 	minStep := int(3)                                                    // the approx minimum distance a player can move per frame | ||||||
| 	space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) // allocate a new collision space everytime after a battle is settled | 	space := resolv.NewSpace(int(spaceW), int(spaceH), minStep, minStep) // allocate a new collision space everytime after a battle is settled | ||||||
| 	for _, player := range pR.Players { | 	for _, player := range pR.Players { | ||||||
| 		playerCollider := GenerateRectCollider(player.X, player.Y, playerColliderRadius*2, playerColliderRadius*2, spaceOffsetX, spaceOffsetY, "Player") | 		playerCollider := GenerateRectCollider(player.X, player.Y, pR.playerColliderRadius*2, pR.playerColliderRadius*2, spaceOffsetX, spaceOffsetY, "Player") | ||||||
| 		space.Add(playerCollider) | 		space.Add(playerCollider) | ||||||
| 		// Keep track of the collider in "pR.CollisionSysMap" | 		// Keep track of the collider in "pR.CollisionSysMap" | ||||||
| 		joinIndex := player.JoinIndex | 		joinIndex := player.JoinIndex | ||||||
|   | |||||||
| @@ -121,13 +121,19 @@ cc.Class({ | |||||||
|     return (0 == inputFrameId % 10); |     return (0 == inputFrameId % 10); | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
|   dumpToRenderCache: function(roomDownsyncFrame) { |   dumpToRenderCache: function(rdf) { | ||||||
|     const self = this; |     const self = this; | ||||||
|  |     // round player position to lower precision | ||||||
|  |     for (let playerId in rdf.players) { | ||||||
|  |       const immediatePlayerInfo = rdf.players[playerId]; | ||||||
|  |       rdf.players[playerId].x = parseFloat(parseInt(immediatePlayerInfo.x * 100)) / 100.0; | ||||||
|  |       rdf.players[playerId].y = parseFloat(parseInt(immediatePlayerInfo.y * 100)) / 100.0; | ||||||
|  |     } | ||||||
|     const minToKeepRenderFrameId = self.lastAllConfirmedRenderFrameId; |     const minToKeepRenderFrameId = self.lastAllConfirmedRenderFrameId; | ||||||
|     while (0 < self.recentRenderCache.cnt && self.recentRenderCache.stFrameId < minToKeepRenderFrameId) { |     while (0 < self.recentRenderCache.cnt && self.recentRenderCache.stFrameId < minToKeepRenderFrameId) { | ||||||
|       self.recentRenderCache.pop(); |       self.recentRenderCache.pop(); | ||||||
|     } |     } | ||||||
|     const ret = self.recentRenderCache.setByFrameId(roomDownsyncFrame, roomDownsyncFrame.id); |     const ret = self.recentRenderCache.setByFrameId(rdf, rdf.id); | ||||||
|     return ret; |     return ret; | ||||||
|   }, |   }, | ||||||
|  |  | ||||||
| @@ -382,8 +388,7 @@ cc.Class({ | |||||||
|       window.clearBoundRoomIdInBothVolatileAndPersistentStorage(); |       window.clearBoundRoomIdInBothVolatileAndPersistentStorage(); | ||||||
|       window.initPersistentSessionClient(self.initAfterWSConnected, null /* Deliberately NOT passing in any `expectedRoomId`. -- YFLu */ ); |       window.initPersistentSessionClient(self.initAfterWSConnected, null /* Deliberately NOT passing in any `expectedRoomId`. -- YFLu */ ); | ||||||
|     }; |     }; | ||||||
|     resultPanelScriptIns.onCloseDelegate = () => { |     resultPanelScriptIns.onCloseDelegate = () => {}; | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     self.gameRuleNode = cc.instantiate(self.gameRulePrefab); |     self.gameRuleNode = cc.instantiate(self.gameRulePrefab); | ||||||
|     self.gameRuleNode.width = self.canvasNode.width; |     self.gameRuleNode.width = self.canvasNode.width; | ||||||
| @@ -575,6 +580,7 @@ cc.Class({ | |||||||
|     if (rdf.id < self.lastAllConfirmedRenderFrameId) { |     if (rdf.id < self.lastAllConfirmedRenderFrameId) { | ||||||
|       return window.RING_BUFF_FAILED_TO_SET; |       return window.RING_BUFF_FAILED_TO_SET; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const dumpRenderCacheRet = self.dumpToRenderCache(rdf); |     const dumpRenderCacheRet = self.dumpToRenderCache(rdf); | ||||||
|     if (window.RING_BUFF_FAILED_TO_SET == dumpRenderCacheRet) { |     if (window.RING_BUFF_FAILED_TO_SET == dumpRenderCacheRet) { | ||||||
|       console.error("Something is wrong while setting the RingBuffer by frameId!"); |       console.error("Something is wrong while setting the RingBuffer by frameId!"); | ||||||
| @@ -589,8 +595,12 @@ cc.Class({ | |||||||
|       return dumpRenderCacheRet; |       return dumpRenderCacheRet; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // The logic below applies to (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START == rdf.id || window.RING_BUFF_NON_CONSECUTIVE_SET == dumpRenderCacheRet) |     // The logic below applies to ( || window.RING_BUFF_NON_CONSECUTIVE_SET == dumpRenderCacheRet) | ||||||
|     console.log('On battle started or resynced! renderFrameId=', rdf.id); |     if (window.MAGIC_ROOM_DOWNSYNC_FRAME_ID.BATTLE_START == rdf.id) { | ||||||
|  |       console.log('On battle resynced! renderFrameId=', rdf.id); | ||||||
|  |     } else { | ||||||
|  |       console.log('On battle resynced! renderFrameId=', rdf.id); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     self.renderFrameId = rdf.id; |     self.renderFrameId = rdf.id; | ||||||
|     self.lastRenderFrameIdTriggeredAt = performance.now(); |     self.lastRenderFrameIdTriggeredAt = performance.now(); | ||||||
| @@ -973,12 +983,14 @@ cc.Class({ | |||||||
|     if ( |     if ( | ||||||
|       null != inputFrameAppliedOnPrevRenderFrame && self._allConfirmed(inputFrameAppliedOnPrevRenderFrame.confirmedList) |       null != inputFrameAppliedOnPrevRenderFrame && self._allConfirmed(inputFrameAppliedOnPrevRenderFrame.confirmedList) | ||||||
|       && |       && | ||||||
|       self.lastAllConfirmedRenderFrameId >= prevRenderFrameId |  | ||||||
|       && |  | ||||||
|       rdf.id > self.lastAllConfirmedRenderFrameId |       rdf.id > self.lastAllConfirmedRenderFrameId | ||||||
|     ) { |     ) { | ||||||
|  |       // We got a more up-to-date "all-confirmed-render-frame". | ||||||
|       self.lastAllConfirmedRenderFrameId = rdf.id; |       self.lastAllConfirmedRenderFrameId = rdf.id; | ||||||
|       self.chaserRenderFrameId = rdf.id; // it must be true that "chaserRenderFrameId >= lastAllConfirmedRenderFrameId"   |       if (rdf.id > self.chaserRenderFrameId) { | ||||||
|  |         // it must be true that "chaserRenderFrameId >= lastAllConfirmedRenderFrameId" | ||||||
|  |         self.chaserRenderFrameId = rdf.id; | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|     self.dumpToRenderCache(rdf); |     self.dumpToRenderCache(rdf); | ||||||
|     return rdf; |     return rdf; | ||||||
| @@ -991,11 +1003,10 @@ cc.Class({ | |||||||
|       const immediatePlayerInfo = rdf.players[playerId]; |       const immediatePlayerInfo = rdf.players[playerId]; | ||||||
|       const dx = (immediatePlayerInfo.x - playerRichInfo.node.x); |       const dx = (immediatePlayerInfo.x - playerRichInfo.node.x); | ||||||
|       const dy = (immediatePlayerInfo.y - playerRichInfo.node.y); |       const dy = (immediatePlayerInfo.y - playerRichInfo.node.y); | ||||||
|       const selfJiggling = (playerId == self.selfPlayerInfo.playerId && (0 != dx && self.teleportEps1D >= Math.abs(dx) && 0 != dy && self.teleportEps1D >= Math.abs(dy))); |       const justJiggling = (self.teleportEps1D >= Math.abs(dx) && self.teleportEps1D >= Math.abs(dy)); | ||||||
|       if (!selfJiggling) { |       if (!justJiggling) { | ||||||
|  |         console.log("@renderFrameId=" + self.renderFrameId + ", teleporting playerId=" + playerId + ": '(" + playerRichInfo.node.x + ", " + playerRichInfo.node.y, ")' to '(" + immediatePlayerInfo.x + ", " + immediatePlayerInfo.y + ")'"); | ||||||
|         playerRichInfo.node.setPosition(immediatePlayerInfo.x, immediatePlayerInfo.y); |         playerRichInfo.node.setPosition(immediatePlayerInfo.x, immediatePlayerInfo.y); | ||||||
|       } else { |  | ||||||
|         console.log("selfJiggling: dx = ", dx, ", dy = ", dy); |  | ||||||
|       } |       } | ||||||
|       playerRichInfo.scriptIns.scheduleNewDirection(immediatePlayerInfo.dir, false); |       playerRichInfo.scriptIns.scheduleNewDirection(immediatePlayerInfo.dir, false); | ||||||
|       playerRichInfo.scriptIns.updateSpeed(immediatePlayerInfo.speed); |       playerRichInfo.scriptIns.updateSpeed(immediatePlayerInfo.speed); | ||||||
| @@ -1074,9 +1085,9 @@ cc.Class({ | |||||||
|         const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex; |         const collisionPlayerIndex = self.collisionPlayerIndexPrefix + joinIndex; | ||||||
|         const playerCollider = collisionSysMap.get(collisionPlayerIndex); |         const playerCollider = collisionSysMap.get(collisionPlayerIndex); | ||||||
|         const potentials = playerCollider.potentials(); |         const potentials = playerCollider.potentials(); | ||||||
|         for (const barrier of potentials) { |         for (const potential of potentials) { | ||||||
|           // Test if the player collides with the wall |           // Test if the player collides with the wall | ||||||
|           if (!playerCollider.collides(barrier, result)) continue; |           if (!playerCollider.collides(potential, result)) continue; | ||||||
|           // Push the player out of the wall |           // Push the player out of the wall | ||||||
|           playerCollider.x -= result.overlap * result.overlap_x; |           playerCollider.x -= result.overlap * result.overlap_x; | ||||||
|           playerCollider.y -= result.overlap * result.overlap_y; |           playerCollider.y -= result.overlap * result.overlap_y; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user