mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-26 03:39:00 +00:00
Applied ringbuff to resolv_tailored for reducing memory usage.
This commit is contained in:
parent
2d179d0cdf
commit
5b7f35b874
@ -1771,7 +1771,7 @@ func (pR *Room) startBattleUdpTunnel() {
|
|||||||
}
|
}
|
||||||
_, wrerr := conn.WriteTo(bytes, otherPlayer.BattleUdpTunnelAddr)
|
_, wrerr := conn.WriteTo(bytes, otherPlayer.BattleUdpTunnelAddr)
|
||||||
if nil != wrerr {
|
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))
|
//Logger.Debug(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
|
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
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?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="64" tilewidth="16" tileheight="16" infinite="0" nextlayerid="7" nextobjectid="137">
|
<map version="1.2" tiledversion="1.2.3" orientation="orthogonal" renderorder="right-down" width="128" height="40" tilewidth="16" tileheight="16" infinite="0" nextlayerid="8" nextobjectid="138">
|
||||||
<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="6" name="Ground" width="128" height="64">
|
<layer id="7" name="Ground" width="128" height="40">
|
||||||
<data encoding="base64" compression="zlib">
|
<data encoding="base64" compression="zlib">
|
||||||
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=
|
eJzt2k0OgjAQQGECccMOo+5JvIlx484LeP9jaAxNSEOhlMGZOG/xbfyl81rc2FRV1QAAAAAAAAAAAADAD9zxpd1Bs7/2NWjzPAPPa2cGvtfODHyvnRn4XjszKFv7KdOW6zoKvYb+9vpf6W+G5f5zfZeep7/82kM3qf6Hj25C3DhFYwb/pqT/VlKfQ///7z91f+g2fj/9y/tLWbqfp7rvsQ/ob0tue6l9YHEGlvv3Qq+hv77x2tuBdv/SPVC6P7z3v0XCc/HjQZ8p9X5rwgy0W2j1rwfh/L8+Hgm1gNQZlfjsku/2fv7j/uPfgPFjUv010T/d/xH1niLd47KDNfcc+s/3aRdml2Opv/R+ov+6/ufB3Ny2nP+5PbD3+c/Zn/RP95f8zaW/Pdr/u7ZCu4Nm/6dz9Pdtz/5vZSq2hg==
|
||||||
</data>
|
</data>
|
||||||
</layer>
|
</layer>
|
||||||
<objectgroup id="1" name="PlayerStartingPos">
|
<objectgroup id="1" name="PlayerStartingPos">
|
||||||
@ -84,12 +84,12 @@
|
|||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="84" x="640" y="224" width="16" height="800">
|
<object id="84" x="640" y="224" width="16" height="416">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="85" x="1680" y="224" width="16" height="800">
|
<object id="85" x="1680" y="224" width="16" height="416">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
@ -149,17 +149,12 @@
|
|||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
<object id="113" x="640" y="1008" width="1056" height="16">
|
|
||||||
<properties>
|
|
||||||
<property name="boundary_type" value="barrier"/>
|
|
||||||
</properties>
|
|
||||||
</object>
|
|
||||||
<object id="114" x="640" y="224" width="1056" height="16">
|
<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="119" x="656" y="592" width="1024" height="416">
|
<object id="119" x="656" y="592" width="512" height="48">
|
||||||
<properties>
|
<properties>
|
||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
@ -169,5 +164,10 @@
|
|||||||
<property name="boundary_type" value="barrier"/>
|
<property name="boundary_type" value="barrier"/>
|
||||||
</properties>
|
</properties>
|
||||||
</object>
|
</object>
|
||||||
|
<object id="137" x="1168" y="592" width="512" height="48">
|
||||||
|
<properties>
|
||||||
|
<property name="boundary_type" value="barrier"/>
|
||||||
|
</properties>
|
||||||
|
</object>
|
||||||
</objectgroup>
|
</objectgroup>
|
||||||
</map>
|
</map>
|
||||||
|
@ -461,7 +461,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
216.50635094610968,
|
217.52040535921228,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
|
@ -72,11 +72,14 @@
|
|||||||
"__id__": 3
|
"__id__": 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 10
|
"__id__": 9
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
|
{
|
||||||
|
"__id__": 50
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"__id__": 51
|
"__id__": 51
|
||||||
},
|
},
|
||||||
@ -88,9 +91,6 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 54
|
"__id__": 54
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 55
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -156,9 +156,6 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 5
|
"__id__": 5
|
||||||
},
|
|
||||||
{
|
|
||||||
"__id__": 6
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -220,34 +217,6 @@
|
|||||||
"_tmxFile": null,
|
"_tmxFile": null,
|
||||||
"_id": "c8MqKDLJdKz7VhPwMjScDw"
|
"_id": "c8MqKDLJdKz7VhPwMjScDw"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"__type__": "09e1b/tEy5K2qaPIpqHDbae",
|
|
||||||
"_name": "",
|
|
||||||
"_objFlags": 0,
|
|
||||||
"node": {
|
|
||||||
"__id__": 3
|
|
||||||
},
|
|
||||||
"_enabled": true,
|
|
||||||
"BGMEffect": {
|
|
||||||
"__uuid__": "64a79efa-97de-4cb5-b2a9-01500c60573a"
|
|
||||||
},
|
|
||||||
"crashedByTrapBullet": {
|
|
||||||
"__uuid__": "1d604e42-8cee-466f-884d-e74cae21ce3b"
|
|
||||||
},
|
|
||||||
"highScoreTreasurePicked": {
|
|
||||||
"__uuid__": "0164d22c-d965-461f-867e-b30e2d56cc5c"
|
|
||||||
},
|
|
||||||
"treasurePicked": {
|
|
||||||
"__uuid__": "7704b97e-6367-420c-b7af-d0750a2bbb30"
|
|
||||||
},
|
|
||||||
"countDown10SecToEnd": {
|
|
||||||
"__uuid__": "261d1d7d-a5cc-4cb7-a737-194427055fd4"
|
|
||||||
},
|
|
||||||
"mapNode": {
|
|
||||||
"__id__": 3
|
|
||||||
},
|
|
||||||
"_id": "3crA1nz5xPSLAnCSLQIPOq"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"__type__": "b3810kDSWtD14RhiYzulYVI",
|
"__type__": "b3810kDSWtD14RhiYzulYVI",
|
||||||
"_name": "",
|
"_name": "",
|
||||||
@ -266,7 +235,7 @@
|
|||||||
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
|
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
|
||||||
},
|
},
|
||||||
"joystickInputControllerNode": {
|
"joystickInputControllerNode": {
|
||||||
"__id__": 7
|
"__id__": 6
|
||||||
},
|
},
|
||||||
"confirmLogoutPrefab": null,
|
"confirmLogoutPrefab": null,
|
||||||
"simplePressToGoDialogPrefab": null,
|
"simplePressToGoDialogPrefab": null,
|
||||||
@ -279,19 +248,19 @@
|
|||||||
"forceBigEndianFloatingNumDecoding": false,
|
"forceBigEndianFloatingNumDecoding": false,
|
||||||
"renderFrameIdLagTolerance": 4,
|
"renderFrameIdLagTolerance": 4,
|
||||||
"inputFrameFrontLabel": {
|
"inputFrameFrontLabel": {
|
||||||
"__id__": 14
|
"__id__": 13
|
||||||
},
|
},
|
||||||
"sendingQLabel": {
|
"sendingQLabel": {
|
||||||
"__id__": 16
|
"__id__": 15
|
||||||
},
|
},
|
||||||
"inputFrameDownsyncQLabel": {
|
"inputFrameDownsyncQLabel": {
|
||||||
"__id__": 18
|
"__id__": 17
|
||||||
},
|
},
|
||||||
"peerInputFrameUpsyncQLabel": {
|
"peerInputFrameUpsyncQLabel": {
|
||||||
"__id__": 20
|
"__id__": 19
|
||||||
},
|
},
|
||||||
"rollbackFramesLabel": {
|
"rollbackFramesLabel": {
|
||||||
"__id__": 22
|
"__id__": 21
|
||||||
},
|
},
|
||||||
"skippedRenderFrameCntLabel": null,
|
"skippedRenderFrameCntLabel": null,
|
||||||
"_id": "e5xQdv12xLoIRr0b36Pie+"
|
"_id": "e5xQdv12xLoIRr0b36Pie+"
|
||||||
@ -301,17 +270,17 @@
|
|||||||
"_name": "JoystickContainer",
|
"_name": "JoystickContainer",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 8
|
"__id__": 7
|
||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 45
|
"__id__": 44
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 50
|
"__id__": 49
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -367,26 +336,26 @@
|
|||||||
"_name": "Interactive",
|
"_name": "Interactive",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 9
|
"__id__": 8
|
||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 7
|
"__id__": 6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 34
|
"__id__": 33
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 36
|
"__id__": 35
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 40
|
"__id__": 39
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 44
|
"__id__": 43
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -442,20 +411,20 @@
|
|||||||
"_name": "WidgetsAboveAll",
|
"_name": "WidgetsAboveAll",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 10
|
"__id__": 9
|
||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 12
|
"__id__": 11
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 8
|
"__id__": 7
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 33
|
"__id__": 32
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -515,13 +484,13 @@
|
|||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 9
|
"__id__": 8
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 11
|
"__id__": 10
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -549,7 +518,7 @@
|
|||||||
"array": [
|
"array": [
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
216.50635094610968,
|
210.4441731196186,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
@ -577,7 +546,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 10
|
"__id__": 9
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_cullingMask": 4294967295,
|
"_cullingMask": 4294967295,
|
||||||
@ -613,35 +582,35 @@
|
|||||||
"_name": "DebugInfo",
|
"_name": "DebugInfo",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 9
|
"__id__": 8
|
||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 13
|
"__id__": 12
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 15
|
"__id__": 14
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 17
|
"__id__": 16
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 19
|
"__id__": 18
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 21
|
"__id__": 20
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 23
|
"__id__": 22
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 25
|
"__id__": 24
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 32
|
"__id__": 31
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -697,13 +666,13 @@
|
|||||||
"_name": "inputFrameFront",
|
"_name": "inputFrameFront",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 12
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 14
|
"__id__": 13
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -759,7 +728,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 13
|
"__id__": 12
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -789,13 +758,13 @@
|
|||||||
"_name": "sendingQ",
|
"_name": "sendingQ",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 12
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 16
|
"__id__": 15
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -851,7 +820,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 15
|
"__id__": 14
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -881,13 +850,13 @@
|
|||||||
"_name": "inputFrameDownsyncQ",
|
"_name": "inputFrameDownsyncQ",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 12
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 18
|
"__id__": 17
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -943,7 +912,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 17
|
"__id__": 16
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -973,13 +942,13 @@
|
|||||||
"_name": "peerInputFrameUpsyncQ",
|
"_name": "peerInputFrameUpsyncQ",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 12
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 20
|
"__id__": 19
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -1035,7 +1004,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 19
|
"__id__": 18
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -1065,13 +1034,13 @@
|
|||||||
"_name": "rollbackFrames",
|
"_name": "rollbackFrames",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 12
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 22
|
"__id__": 21
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -1127,7 +1096,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 21
|
"__id__": 20
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -1157,13 +1126,13 @@
|
|||||||
"_name": "skippedCnt",
|
"_name": "skippedCnt",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 12
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 24
|
"__id__": 23
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -1219,7 +1188,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 23
|
"__id__": 22
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -1251,23 +1220,23 @@
|
|||||||
"_name": "RoomIdIndicator",
|
"_name": "RoomIdIndicator",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 12
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 26
|
"__id__": 25
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 28
|
"__id__": 27
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": false,
|
"_active": false,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 30
|
"__id__": 29
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 31
|
"__id__": 30
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -1323,13 +1292,13 @@
|
|||||||
"_name": "label",
|
"_name": "label",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 25
|
"__id__": 24
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 27
|
"__id__": 26
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -1385,7 +1354,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 26
|
"__id__": 25
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [],
|
"_materials": [],
|
||||||
@ -1413,13 +1382,13 @@
|
|||||||
"_name": "BoundRoomIdLabel",
|
"_name": "BoundRoomIdLabel",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 25
|
"__id__": 24
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 29
|
"__id__": 28
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -1475,7 +1444,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 28
|
"__id__": 27
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [],
|
"_materials": [],
|
||||||
@ -1503,7 +1472,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 25
|
"__id__": 24
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_layoutSize": {
|
"_layoutSize": {
|
||||||
@ -1536,7 +1505,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 25
|
"__id__": 24
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [],
|
"_materials": [],
|
||||||
@ -1566,7 +1535,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 12
|
"__id__": 11
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_layoutSize": {
|
"_layoutSize": {
|
||||||
@ -1599,7 +1568,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 9
|
"__id__": 8
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"alignMode": 1,
|
"alignMode": 1,
|
||||||
@ -1626,13 +1595,13 @@
|
|||||||
"_name": "CountdownSeconds",
|
"_name": "CountdownSeconds",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 8
|
"__id__": 7
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 35
|
"__id__": 34
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -1688,7 +1657,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 34
|
"__id__": 33
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -1718,11 +1687,11 @@
|
|||||||
"_name": "BtnA",
|
"_name": "BtnA",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 8
|
"__id__": 7
|
||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 37
|
"__id__": 36
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
@ -1780,16 +1749,16 @@
|
|||||||
"_name": "Background",
|
"_name": "Background",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 36
|
"__id__": 35
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 38
|
"__id__": 37
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 39
|
"__id__": 38
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -1845,7 +1814,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 37
|
"__id__": 36
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -1879,7 +1848,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 37
|
"__id__": 36
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"alignMode": 0,
|
"alignMode": 0,
|
||||||
@ -1906,11 +1875,11 @@
|
|||||||
"_name": "BtnB",
|
"_name": "BtnB",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 8
|
"__id__": 7
|
||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 41
|
"__id__": 40
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
@ -1968,16 +1937,16 @@
|
|||||||
"_name": "Background",
|
"_name": "Background",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 40
|
"__id__": 39
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 42
|
"__id__": 41
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 43
|
"__id__": 42
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -2033,7 +2002,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 41
|
"__id__": 40
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -2067,7 +2036,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 41
|
"__id__": 40
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"alignMode": 0,
|
"alignMode": 0,
|
||||||
@ -2094,7 +2063,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 8
|
"__id__": 7
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"alignMode": 1,
|
"alignMode": 1,
|
||||||
@ -2121,20 +2090,20 @@
|
|||||||
"_name": "JoystickBG",
|
"_name": "JoystickBG",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 7
|
"__id__": 6
|
||||||
},
|
},
|
||||||
"_children": [
|
"_children": [
|
||||||
{
|
{
|
||||||
"__id__": 46
|
"__id__": 45
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 48
|
"__id__": 47
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"__id__": 49
|
"__id__": 48
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -2190,13 +2159,13 @@
|
|||||||
"_name": "Joystick",
|
"_name": "Joystick",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"_parent": {
|
"_parent": {
|
||||||
"__id__": 45
|
"__id__": 44
|
||||||
},
|
},
|
||||||
"_children": [],
|
"_children": [],
|
||||||
"_active": true,
|
"_active": true,
|
||||||
"_components": [
|
"_components": [
|
||||||
{
|
{
|
||||||
"__id__": 47
|
"__id__": 46
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"_prefab": null,
|
"_prefab": null,
|
||||||
@ -2252,7 +2221,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 46
|
"__id__": 45
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -2286,7 +2255,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 45
|
"__id__": 44
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"_materials": [
|
"_materials": [
|
||||||
@ -2320,7 +2289,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 45
|
"__id__": 44
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"alignMode": 0,
|
"alignMode": 0,
|
||||||
@ -2347,7 +2316,7 @@
|
|||||||
"_name": "",
|
"_name": "",
|
||||||
"_objFlags": 0,
|
"_objFlags": 0,
|
||||||
"node": {
|
"node": {
|
||||||
"__id__": 7
|
"__id__": 6
|
||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"alignMode": 0,
|
"alignMode": 0,
|
||||||
@ -2449,16 +2418,16 @@
|
|||||||
},
|
},
|
||||||
"_enabled": true,
|
"_enabled": true,
|
||||||
"translationListenerNode": {
|
"translationListenerNode": {
|
||||||
"__id__": 7
|
"__id__": 6
|
||||||
},
|
},
|
||||||
"zoomingListenerNode": {
|
"zoomingListenerNode": {
|
||||||
"__id__": 3
|
"__id__": 3
|
||||||
},
|
},
|
||||||
"stickhead": {
|
"stickhead": {
|
||||||
"__id__": 46
|
"__id__": 45
|
||||||
},
|
},
|
||||||
"base": {
|
"base": {
|
||||||
"__id__": 45
|
"__id__": 44
|
||||||
},
|
},
|
||||||
"joyStickEps": 0.1,
|
"joyStickEps": 0.1,
|
||||||
"magicLeanLowerBound": 0.414,
|
"magicLeanLowerBound": 0.414,
|
||||||
@ -2479,10 +2448,10 @@
|
|||||||
"linearMovingEps": 0.1,
|
"linearMovingEps": 0.1,
|
||||||
"scaleByEps": 0.0375,
|
"scaleByEps": 0.0375,
|
||||||
"btnA": {
|
"btnA": {
|
||||||
"__id__": 36
|
"__id__": 35
|
||||||
},
|
},
|
||||||
"btnB": {
|
"btnB": {
|
||||||
"__id__": 40
|
"__id__": 39
|
||||||
},
|
},
|
||||||
"_id": "e9oVYTr7ROlpp/IrNjBUmR"
|
"_id": "e9oVYTr7ROlpp/IrNjBUmR"
|
||||||
}
|
}
|
||||||
|
@ -1,66 +0,0 @@
|
|||||||
cc.Class({
|
|
||||||
extends: cc.Component,
|
|
||||||
|
|
||||||
properties: {
|
|
||||||
BGMEffect: {
|
|
||||||
type: cc.AudioClip,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
crashedByTrapBullet: {
|
|
||||||
type: cc.AudioClip,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
highScoreTreasurePicked: {
|
|
||||||
type: cc.AudioClip,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
treasurePicked: {
|
|
||||||
type: cc.AudioClip,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
countDown10SecToEnd: {
|
|
||||||
type: cc.AudioClip,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
mapNode: {
|
|
||||||
type: cc.Node,
|
|
||||||
default: null
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
// LIFE-CYCLE CALLBACKS:
|
|
||||||
|
|
||||||
onLoad() {
|
|
||||||
cc.audioEngine.setEffectsVolume(1);
|
|
||||||
cc.audioEngine.setMusicVolume(0.5);
|
|
||||||
},
|
|
||||||
stopAllMusic() {
|
|
||||||
cc.audioEngine.stopAll();
|
|
||||||
},
|
|
||||||
playBGM() {
|
|
||||||
if(this.BGMEffect) {
|
|
||||||
cc.audioEngine.playMusic(this.BGMEffect, true);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
playCrashedByTrapBullet() {
|
|
||||||
if(this.crashedByTrapBullet) {
|
|
||||||
cc.audioEngine.playEffect(this.crashedByTrapBullet, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
playHighScoreTreasurePicked() {
|
|
||||||
if(this.highScoreTreasurePicked) {
|
|
||||||
cc.audioEngine.playEffect(this.highScoreTreasurePicked, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
playTreasurePicked() {
|
|
||||||
if(this.treasurePicked) {
|
|
||||||
cc.audioEngine.playEffect(this.treasurePicked, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
playCountDown10SecToEnd() {
|
|
||||||
if(this.countDown10SecToEnd) {
|
|
||||||
cc.audioEngine.playEffect(this.countDown10SecToEnd, false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"ver": "1.0.5",
|
|
||||||
"uuid": "09e1bfed-132e-4ada-a68f-229a870db69e",
|
|
||||||
"isPlugin": false,
|
|
||||||
"loadPluginInWeb": true,
|
|
||||||
"loadPluginInNative": true,
|
|
||||||
"loadPluginInEditor": false,
|
|
||||||
"subMetas": {}
|
|
||||||
}
|
|
@ -33,7 +33,7 @@ cc.Class({
|
|||||||
/** Init required prefab ended. */
|
/** Init required prefab ended. */
|
||||||
|
|
||||||
self.inputFrameUpsyncDelayTolerance = 2;
|
self.inputFrameUpsyncDelayTolerance = 2;
|
||||||
self.collisionMinStep = 2;
|
self.collisionMinStep = 8;
|
||||||
|
|
||||||
self.renderCacheSize = 1024;
|
self.renderCacheSize = 1024;
|
||||||
self.serverFps = 60;
|
self.serverFps = 60;
|
||||||
@ -98,7 +98,7 @@ cc.Class({
|
|||||||
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 colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0);
|
const colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0);
|
||||||
|
|
||||||
const speciesIdList = [4096, 0];
|
const speciesIdList = [1, 0];
|
||||||
const chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(speciesIdList);
|
const chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(speciesIdList);
|
||||||
|
|
||||||
const startRdf = window.pb.protos.RoomDownsyncFrame.create({
|
const startRdf = window.pb.protos.RoomDownsyncFrame.create({
|
||||||
|
File diff suppressed because one or more lines are too long
@ -27,8 +27,7 @@
|
|||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:usesCleartextTraffic="true"
|
android:usesCleartextTraffic="true"
|
||||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask">
|
||||||
android:taskAffinity="" >
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
},
|
},
|
||||||
"encryptJs": false,
|
"encryptJs": false,
|
||||||
"excludeScenes": [
|
"excludeScenes": [
|
||||||
"8491a86c-bec9-4813-968a-128ca01639e0"
|
"2ff474d9-0c9e-4fe3-87ec-fbff7cae85b4",
|
||||||
|
"92160186-3e0d-4e0a-ae20-97286170ba58"
|
||||||
],
|
],
|
||||||
"fb-instant-games": {},
|
"fb-instant-games": {},
|
||||||
"includeSDKBox": false,
|
"includeSDKBox": false,
|
||||||
@ -37,7 +38,7 @@
|
|||||||
"REMOTE_SERVER_ROOT": "",
|
"REMOTE_SERVER_ROOT": "",
|
||||||
"orientation": "portrait"
|
"orientation": "portrait"
|
||||||
},
|
},
|
||||||
"startScene": "2ff474d9-0c9e-4fe3-87ec-fbff7cae85b4",
|
"startScene": "8491a86c-bec9-4813-968a-128ca01639e0",
|
||||||
"title": "DelayNoMore",
|
"title": "DelayNoMore",
|
||||||
"webOrientation": "landscape",
|
"webOrientation": "landscape",
|
||||||
"wechatgame": {
|
"wechatgame": {
|
||||||
|
@ -16,7 +16,7 @@ const (
|
|||||||
PATTERN_ID_UNABLE_TO_OP = -2
|
PATTERN_ID_UNABLE_TO_OP = -2
|
||||||
PATTERN_ID_NO_OP = -1
|
PATTERN_ID_NO_OP = -1
|
||||||
|
|
||||||
WORLD_TO_VIRTUAL_GRID_RATIO = float64(100.0)
|
WORLD_TO_VIRTUAL_GRID_RATIO = float64(10.0)
|
||||||
VIRTUAL_GRID_TO_WORLD_RATIO = float64(1.0) / WORLD_TO_VIRTUAL_GRID_RATIO
|
VIRTUAL_GRID_TO_WORLD_RATIO = float64(1.0) / WORLD_TO_VIRTUAL_GRID_RATIO
|
||||||
|
|
||||||
GRAVITY_X = int32(0)
|
GRAVITY_X = int32(0)
|
||||||
@ -226,16 +226,31 @@ func isPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
if 1 < aCnt {
|
if 1 < aCnt {
|
||||||
for _, axis := range a.SATAxes() {
|
// Deliberately using "Points" instead of "SATAxes" to avoid unnecessary heap memory alloc
|
||||||
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
|
for i, _ := range a.Points {
|
||||||
|
u, v := a.Points[i], a.Points[0]
|
||||||
|
if i != len(a.Points)-1 {
|
||||||
|
v = a.Points[i+1]
|
||||||
|
}
|
||||||
|
dy := v[1] - u[1]
|
||||||
|
dx := v[0] - u[0]
|
||||||
|
axis := resolv.Vector{dy, -dx}.Unit()
|
||||||
|
if isPolygonPairSeparatedByDir(a, b, axis, result) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if 1 < bCnt {
|
if 1 < bCnt {
|
||||||
for _, axis := range b.SATAxes() {
|
for i, _ := range b.Points {
|
||||||
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
|
u, v := b.Points[i], b.Points[0]
|
||||||
|
if i != len(b.Points)-1 {
|
||||||
|
v = b.Points[i+1]
|
||||||
|
}
|
||||||
|
dy := v[1] - u[1]
|
||||||
|
dx := v[0] - u[0]
|
||||||
|
axis := resolv.Vector{dy, -dx}.Unit()
|
||||||
|
if isPolygonPairSeparatedByDir(a, b, axis, result) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -411,8 +426,7 @@ func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBounding
|
|||||||
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
|
return WorldToPolygonColliderBLPos(wx, wy, halfBoundingW, halfBoundingH, topPadding, bottomPadding, leftPadding, rightPadding, collisionSpaceOffsetX, collisionSpaceOffsetY)
|
||||||
}
|
}
|
||||||
|
|
||||||
func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D) *[]Vec2D {
|
func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D, pHardPushback *[]Vec2D, collision *resolv.Collision) int {
|
||||||
ret := make([]Vec2D, 0, 10) // no one would simultaneously have more than 5 hardPushbacks
|
|
||||||
virtualGripToWall := float64(0)
|
virtualGripToWall := float64(0)
|
||||||
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && 0 == thatPlayerInNextFrame.VelX && currPlayerDownsync.DirX == thatPlayerInNextFrame.DirX {
|
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && 0 == thatPlayerInNextFrame.VelX && currPlayerDownsync.DirX == thatPlayerInNextFrame.DirX {
|
||||||
/*
|
/*
|
||||||
@ -429,14 +443,19 @@ func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNex
|
|||||||
}
|
}
|
||||||
virtualGripToWall = xfac * float64(currPlayerDownsync.Speed) * VIRTUAL_GRID_TO_WORLD_RATIO
|
virtualGripToWall = xfac * float64(currPlayerDownsync.Speed) * VIRTUAL_GRID_TO_WORLD_RATIO
|
||||||
}
|
}
|
||||||
collision := playerCollider.Check(virtualGripToWall, 0)
|
retCnt := 0
|
||||||
if nil == collision {
|
collided := playerCollider.CheckAllWithHolder(virtualGripToWall, 0, collision)
|
||||||
return &ret
|
if !collided {
|
||||||
|
return retCnt
|
||||||
}
|
}
|
||||||
|
|
||||||
//playerColliderCenterX, playerColliderCenterY := playerCollider.Center()
|
//playerColliderCenterX, playerColliderCenterY := playerCollider.Center()
|
||||||
//fmt.Printf("joinIndex=%d calcHardPushbacksNorms has non-empty collision;playerColliderPos=(%.2f,%.2f)\n", joinIndex, playerColliderCenterX, playerColliderCenterY)
|
//fmt.Printf("joinIndex=%d calcHardPushbacksNorms has non-empty collision;playerColliderPos=(%.2f,%.2f)\n", joinIndex, playerColliderCenterX, playerColliderCenterY)
|
||||||
for _, obj := range collision.Objects {
|
for true {
|
||||||
|
obj := collision.FirstCollidedObject()
|
||||||
|
if nil == obj {
|
||||||
|
break
|
||||||
|
}
|
||||||
isBarrier := false
|
isBarrier := false
|
||||||
switch obj.Data.(type) {
|
switch obj.Data.(type) {
|
||||||
case *PlayerDownsync, *MeleeBullet, *FireballBullet:
|
case *PlayerDownsync, *MeleeBullet, *FireballBullet:
|
||||||
@ -456,15 +475,16 @@ func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNex
|
|||||||
// ALWAY snap into hardPushbacks!
|
// ALWAY snap into hardPushbacks!
|
||||||
// [OverlapX, OverlapY] is the unit vector that points into the platform
|
// [OverlapX, OverlapY] is the unit vector that points into the platform
|
||||||
pushbackX, pushbackY = (overlapResult.Overlap-snapIntoPlatformOverlap)*overlapResult.OverlapX, (overlapResult.Overlap-snapIntoPlatformOverlap)*overlapResult.OverlapY
|
pushbackX, pushbackY = (overlapResult.Overlap-snapIntoPlatformOverlap)*overlapResult.OverlapX, (overlapResult.Overlap-snapIntoPlatformOverlap)*overlapResult.OverlapY
|
||||||
ret = append(ret, Vec2D{X: overlapResult.OverlapX, Y: overlapResult.OverlapY})
|
(*pHardPushback)[retCnt] = Vec2D{X: overlapResult.OverlapX, Y: overlapResult.OverlapY}
|
||||||
pEffPushback.X += pushbackX
|
pEffPushback.X += pushbackX
|
||||||
pEffPushback.Y += pushbackY
|
pEffPushback.Y += pushbackY
|
||||||
|
retCnt++
|
||||||
//fmt.Printf("joinIndex=%d calcHardPushbacksNorms found one hardpushback; immediatePushback=(%.2f,%.2f)\n", joinIndex, pushbackX, pushbackY)
|
//fmt.Printf("joinIndex=%d calcHardPushbacksNorms found one hardpushback; immediatePushback=(%.2f,%.2f)\n", joinIndex, pushbackX, pushbackY)
|
||||||
}
|
}
|
||||||
return &ret
|
return retCnt
|
||||||
}
|
}
|
||||||
|
|
||||||
func deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, currRenderFrame *RoomDownsyncFrame, chConfig *CharacterConfig, inputsBuffer *RingBuffer) (int, bool, int32, int32) {
|
func deriveOpPattern(currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, currRenderFrame *RoomDownsyncFrame, chConfig *CharacterConfig, inputsBuffer *resolv.RingBuffer) (int, bool, int32, int32) {
|
||||||
// returns (patternId, jumpedOrNot, effectiveDx, effectiveDy)
|
// returns (patternId, jumpedOrNot, effectiveDx, effectiveDy)
|
||||||
delayedInputFrameId := ConvertToDelayedInputFrameId(currRenderFrame.Id)
|
delayedInputFrameId := ConvertToDelayedInputFrameId(currRenderFrame.Id)
|
||||||
delayedInputFrameIdForPrevRdf := ConvertToDelayedInputFrameId(currRenderFrame.Id - 1)
|
delayedInputFrameIdForPrevRdf := ConvertToDelayedInputFrameId(currRenderFrame.Id - 1)
|
||||||
@ -558,7 +578,9 @@ then pass in the whole "renderFrameBuffer *SpecificRingBuffer" to this function
|
|||||||
|
|
||||||
However, the enhancement for "playerColliders & bulletColliders" of each room is even more difficult, because the feasibility of doing in-place overwrites depends on the collision library in use.
|
However, the enhancement for "playerColliders & bulletColliders" of each room is even more difficult, because the feasibility of doing in-place overwrites depends on the collision library in use.
|
||||||
*/
|
*/
|
||||||
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig) *RoomDownsyncFrame {
|
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *resolv.RingBuffer, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig) *RoomDownsyncFrame {
|
||||||
|
collision := resolv.NewCollision() // TODO: Pass this holder in from params
|
||||||
|
|
||||||
// [WARNING] On backend this function MUST BE called while "InputsBufferLock" is locked!
|
// [WARNING] On backend this function MUST BE called while "InputsBufferLock" is locked!
|
||||||
roomCapacity := len(currRenderFrame.PlayersArr)
|
roomCapacity := len(currRenderFrame.PlayersArr)
|
||||||
nextRenderFramePlayers := make([]*PlayerDownsync, roomCapacity)
|
nextRenderFramePlayers := make([]*PlayerDownsync, roomCapacity)
|
||||||
@ -607,7 +629,10 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
nextRenderFrameMeleeBullets := make([]*MeleeBullet, 0, len(currRenderFrame.MeleeBullets)) // Is there any better way to reduce malloc/free impact, e.g. smart prediction for fixed memory allocation?
|
nextRenderFrameMeleeBullets := make([]*MeleeBullet, 0, len(currRenderFrame.MeleeBullets)) // Is there any better way to reduce malloc/free impact, e.g. smart prediction for fixed memory allocation?
|
||||||
nextRenderFrameFireballBullets := make([]*FireballBullet, 0, len(currRenderFrame.FireballBullets))
|
nextRenderFrameFireballBullets := make([]*FireballBullet, 0, len(currRenderFrame.FireballBullets))
|
||||||
effPushbacks := make([]Vec2D, roomCapacity)
|
effPushbacks := make([]Vec2D, roomCapacity)
|
||||||
hardPushbackNorms := make([]*[]Vec2D, roomCapacity)
|
hardPushbackNorms := make([][]Vec2D, roomCapacity)
|
||||||
|
for i, _ := range currRenderFrame.PlayersArr {
|
||||||
|
hardPushbackNorms[i] = make([]Vec2D, 5) // In reality no more than 4 simultaneous hard pushbacks
|
||||||
|
}
|
||||||
jumpedOrNotList := make([]bool, roomCapacity)
|
jumpedOrNotList := make([]bool, roomCapacity)
|
||||||
|
|
||||||
bulletLocalId := currRenderFrame.BulletLocalIdCounter
|
bulletLocalId := currRenderFrame.BulletLocalIdCounter
|
||||||
@ -813,7 +838,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
playerColliders[i] = playerCollider
|
playerColliders[i] = playerCollider
|
||||||
|
|
||||||
// Add to collision system
|
// Add to collision system
|
||||||
collisionSys.Add(playerCollider)
|
collisionSys.AddSingle(playerCollider)
|
||||||
|
|
||||||
if currPlayerDownsync.InAir {
|
if currPlayerDownsync.InAir {
|
||||||
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && !jumpedOrNotList[i] {
|
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && !jumpedOrNotList[i] {
|
||||||
@ -850,7 +875,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY)
|
bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY)
|
||||||
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(fireballBullet.Bullet.HitboxSizeX, fireballBullet.Bullet.HitboxSizeY)
|
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(fireballBullet.Bullet.HitboxSizeX, fireballBullet.Bullet.HitboxSizeY)
|
||||||
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, fireballBullet, "FireballBullet")
|
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, fireballBullet, "FireballBullet")
|
||||||
collisionSys.Add(newBulletCollider)
|
collisionSys.AddSingle(newBulletCollider)
|
||||||
bulletColliders = append(bulletColliders, newBulletCollider)
|
bulletColliders = append(bulletColliders, newBulletCollider)
|
||||||
fireballBullet.BlState = BULLET_ACTIVE
|
fireballBullet.BlState = BULLET_ACTIVE
|
||||||
if fireballBullet.BlState != prevFireball.BlState {
|
if fireballBullet.BlState != prevFireball.BlState {
|
||||||
@ -891,7 +916,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY)
|
bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY)
|
||||||
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(meleeBullet.Bullet.HitboxSizeX, meleeBullet.Bullet.HitboxSizeY)
|
hitboxSizeWx, hitboxSizeWy := VirtualGridToWorldPos(meleeBullet.Bullet.HitboxSizeX, meleeBullet.Bullet.HitboxSizeY)
|
||||||
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet")
|
newBulletCollider := GenerateRectCollider(bulletWx, bulletWy, hitboxSizeWx, hitboxSizeWy, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, SNAP_INTO_PLATFORM_OVERLAP, collisionSpaceOffsetX, collisionSpaceOffsetY, meleeBullet, "MeleeBullet")
|
||||||
collisionSys.Add(newBulletCollider)
|
collisionSys.AddSingle(newBulletCollider)
|
||||||
bulletColliders = append(bulletColliders, newBulletCollider)
|
bulletColliders = append(bulletColliders, newBulletCollider)
|
||||||
meleeBullet.BlState = BULLET_ACTIVE
|
meleeBullet.BlState = BULLET_ACTIVE
|
||||||
if meleeBullet.BlState != prevMelee.BlState {
|
if meleeBullet.BlState != prevMelee.BlState {
|
||||||
@ -908,12 +933,16 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
playerCollider := playerColliders[i]
|
playerCollider := playerColliders[i]
|
||||||
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
thatPlayerInNextFrame := nextRenderFramePlayers[i]
|
||||||
hardPushbackNorms[joinIndex-1] = calcHardPushbacksNorms(joinIndex, currPlayerDownsync, thatPlayerInNextFrame, playerCollider, playerShape, SNAP_INTO_PLATFORM_OVERLAP, &(effPushbacks[joinIndex-1]))
|
hardPushbackCnt := calcHardPushbacksNorms(joinIndex, currPlayerDownsync, thatPlayerInNextFrame, playerCollider, playerShape, SNAP_INTO_PLATFORM_OVERLAP, &(effPushbacks[joinIndex-1]), &(hardPushbackNorms[joinIndex-1]), collision)
|
||||||
chConfig := chConfigsOrderedByJoinIndex[i]
|
chConfig := chConfigsOrderedByJoinIndex[i]
|
||||||
landedOnGravityPushback := false
|
landedOnGravityPushback := false
|
||||||
|
|
||||||
if collision := playerCollider.Check(0, 0); nil != collision {
|
if collided := playerCollider.CheckAllWithHolder(0, 0, collision); collided {
|
||||||
for _, obj := range collision.Objects {
|
for true {
|
||||||
|
obj := collision.FirstCollidedObject()
|
||||||
|
if nil == obj {
|
||||||
|
break
|
||||||
|
}
|
||||||
isBarrier, isAnotherPlayer, isBullet := false, false, false
|
isBarrier, isAnotherPlayer, isBullet := false, false, false
|
||||||
switch v := obj.Data.(type) {
|
switch v := obj.Data.(type) {
|
||||||
case *PlayerDownsync:
|
case *PlayerDownsync:
|
||||||
@ -943,23 +972,27 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
// [WARNING] The "zero overlap collision" might be randomly detected/missed on either frontend or backend, to have deterministic result we added paddings to all sides of a playerCollider. As each velocity component of (velX, velY) being a multiple of 0.5 at any renderFrame, each position component of (x, y) can only be a multiple of 0.5 too, thus whenever a 1-dimensional collision happens between players from [player#1: i*0.5, player#2: j*0.5, not collided yet] to [player#1: (i+k)*0.5, player#2: j*0.5, collided], the overlap becomes (i+k-j)*0.5+2*s, and after snapping subtraction the effPushback magnitude for each player is (i+k-j)*0.5, resulting in 0.5-multiples-position for the next renderFrame.
|
// [WARNING] The "zero overlap collision" might be randomly detected/missed on either frontend or backend, to have deterministic result we added paddings to all sides of a playerCollider. As each velocity component of (velX, velY) being a multiple of 0.5 at any renderFrame, each position component of (x, y) can only be a multiple of 0.5 too, thus whenever a 1-dimensional collision happens between players from [player#1: i*0.5, player#2: j*0.5, not collided yet] to [player#1: (i+k)*0.5, player#2: j*0.5, collided], the overlap becomes (i+k-j)*0.5+2*s, and after snapping subtraction the effPushback magnitude for each player is (i+k-j)*0.5, resulting in 0.5-multiples-position for the next renderFrame.
|
||||||
pushbackX, pushbackY = (overlapResult.Overlap-SNAP_INTO_PLATFORM_OVERLAP*2)*overlapResult.OverlapX, (overlapResult.Overlap-SNAP_INTO_PLATFORM_OVERLAP*2)*overlapResult.OverlapY
|
pushbackX, pushbackY = (overlapResult.Overlap-SNAP_INTO_PLATFORM_OVERLAP*2)*overlapResult.OverlapX, (overlapResult.Overlap-SNAP_INTO_PLATFORM_OVERLAP*2)*overlapResult.OverlapY
|
||||||
}
|
}
|
||||||
for _, hardPushbackNorm := range *hardPushbackNorms[joinIndex-1] {
|
if 0 < hardPushbackCnt {
|
||||||
|
for i := 0; i < hardPushbackCnt; i++ {
|
||||||
|
hardPushbackNorm := hardPushbackNorms[joinIndex-1][i]
|
||||||
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
||||||
if isBarrier || (isAnotherPlayer && 0 > projectedMagnitude) {
|
if isBarrier || (isAnotherPlayer && 0 > projectedMagnitude) {
|
||||||
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
||||||
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
effPushbacks[joinIndex-1].X += pushbackX
|
effPushbacks[joinIndex-1].X += pushbackX
|
||||||
effPushbacks[joinIndex-1].Y += pushbackY
|
effPushbacks[joinIndex-1].Y += pushbackY
|
||||||
|
|
||||||
if SNAP_INTO_PLATFORM_THRESHOLD < normAlignmentWithGravity {
|
if SNAP_INTO_PLATFORM_THRESHOLD < normAlignmentWithGravity {
|
||||||
landedOnGravityPushback = true
|
landedOnGravityPushback = true
|
||||||
//playerColliderCenterX, playerColliderCenterY := playerCollider.Center()
|
//playerColliderCenterX, playerColliderCenterY := playerCollider.Center()
|
||||||
//fmt.Printf("joinIndex=%d landedOnGravityPushback\n{renderFrame.id: %d, isBarrier: %v, isAnotherPlayer: %v}\nhardPushbackNormsOfThisPlayer=%v, playerColliderPos=(%.2f,%.2f), immediatePushback={%.3f, %.3f}, effPushback={%.3f, %.3f}, overlapMag=%.4f\n", joinIndex, currRenderFrame.Id, isBarrier, isAnotherPlayer, *hardPushbackNorms[joinIndex-1], playerColliderCenterX, playerColliderCenterY, pushbackX, pushbackY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, overlapResult.Overlap)
|
//fmt.Printf("joinIndex=%d landedOnGravityPushback\n{renderFrame.id: %d, isBarrier: %v, isAnotherPlayer: %v}\nhardPushbackNormsOfThisPlayer=%v, playerColliderPos=(%.2f,%.2f), immediatePushback={%.3f, %.3f}, effPushback={%.3f, %.3f}, overlapMag=%.4f\n", joinIndex, currRenderFrame.Id, isBarrier, isAnotherPlayer, hardPushbackNorms[joinIndex-1], playerColliderCenterX, playerColliderCenterY, pushbackX, pushbackY, effPushbacks[joinIndex-1].X, effPushbacks[joinIndex-1].Y, overlapResult.Overlap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if landedOnGravityPushback {
|
if landedOnGravityPushback {
|
||||||
thatPlayerInNextFrame.InAir = false
|
thatPlayerInNextFrame.InAir = false
|
||||||
fallStopping := (currPlayerDownsync.InAir && 0 >= currPlayerDownsync.VelY)
|
fallStopping := (currPlayerDownsync.InAir && 0 >= currPlayerDownsync.VelY)
|
||||||
@ -1004,9 +1037,10 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
if chConfig.OnWallEnabled {
|
if chConfig.OnWallEnabled {
|
||||||
if thatPlayerInNextFrame.InAir {
|
if thatPlayerInNextFrame.InAir {
|
||||||
// [WARNING] Sticking to wall MUST BE based on "InAir", otherwise we would get gravity reduction from ground up incorrectly!
|
// [WARNING] Sticking to wall MUST BE based on "InAir", otherwise we would get gravity reduction from ground up incorrectly!
|
||||||
if _, existent := noOpSet[currPlayerDownsync.CharacterState]; !existent {
|
if _, existent := noOpSet[currPlayerDownsync.CharacterState]; !existent && 0 < hardPushbackCnt {
|
||||||
// [WARNING] Sticking to wall could only be triggered by proactive player input
|
// [WARNING] Sticking to wall could only be triggered by proactive player input
|
||||||
for _, hardPushbackNorm := range *hardPushbackNorms[joinIndex-1] {
|
for i := 0; i < hardPushbackCnt; i++ {
|
||||||
|
hardPushbackNorm := hardPushbackNorms[joinIndex-1][i]
|
||||||
normAlignmentWithHorizon1 := (hardPushbackNorm.X*float64(1.0) + hardPushbackNorm.Y*float64(0.0))
|
normAlignmentWithHorizon1 := (hardPushbackNorm.X*float64(1.0) + hardPushbackNorm.Y*float64(0.0))
|
||||||
normAlignmentWithHorizon2 := (hardPushbackNorm.X*float64(-1.0) + hardPushbackNorm.Y*float64(0.0))
|
normAlignmentWithHorizon2 := (hardPushbackNorm.X*float64(-1.0) + hardPushbackNorm.Y*float64(0.0))
|
||||||
if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon1 {
|
if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon1 {
|
||||||
@ -1031,14 +1065,15 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
|
|
||||||
// 5. Check bullet-anything collisions
|
// 5. Check bullet-anything collisions
|
||||||
for _, bulletCollider := range bulletColliders {
|
for _, bulletCollider := range bulletColliders {
|
||||||
collision := bulletCollider.Check(0, 0)
|
collided := bulletCollider.CheckAllWithHolder(0, 0, collision)
|
||||||
bulletCollider.Space.Remove(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame
|
bulletCollider.Space.RemoveSingle(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame
|
||||||
exploded := false
|
if !collided {
|
||||||
explodedOnAnotherPlayer := false
|
|
||||||
if nil == collision {
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exploded := false
|
||||||
|
explodedOnAnotherPlayer := false
|
||||||
|
|
||||||
var bulletStaticAttr *BulletConfig = nil
|
var bulletStaticAttr *BulletConfig = nil
|
||||||
var bulletBattleAttr *BulletBattleAttr = nil
|
var bulletBattleAttr *BulletBattleAttr = nil
|
||||||
switch v := bulletCollider.Data.(type) {
|
switch v := bulletCollider.Data.(type) {
|
||||||
@ -1052,7 +1087,11 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
|
|
||||||
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
|
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
|
||||||
offender := currRenderFrame.PlayersArr[bulletBattleAttr.OffenderJoinIndex-1]
|
offender := currRenderFrame.PlayersArr[bulletBattleAttr.OffenderJoinIndex-1]
|
||||||
for _, obj := range collision.Objects {
|
for true {
|
||||||
|
obj := collision.FirstCollidedObject()
|
||||||
|
if nil == obj {
|
||||||
|
break
|
||||||
|
}
|
||||||
defenderShape := obj.Shape.(*resolv.ConvexPolygon)
|
defenderShape := obj.Shape.(*resolv.ConvexPolygon)
|
||||||
switch t := obj.Data.(type) {
|
switch t := obj.Data.(type) {
|
||||||
case *PlayerDownsync:
|
case *PlayerDownsync:
|
||||||
@ -1170,7 +1209,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, playerCollider := range playerColliders {
|
for _, playerCollider := range playerColliders {
|
||||||
playerCollider.Space.Remove(playerCollider)
|
playerCollider.Space.RemoveSingle(playerCollider)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &RoomDownsyncFrame{
|
return &RoomDownsyncFrame{
|
||||||
@ -1188,7 +1227,7 @@ func GenerateRectCollider(wx, wy, w, h, topPadding, bottomPadding, leftPadding,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generateRectColliderInCollisionSpace(blX, blY, w, h float64, data interface{}, tag string) *resolv.Object {
|
func generateRectColliderInCollisionSpace(blX, blY, w, h float64, data interface{}, tag string) *resolv.Object {
|
||||||
collider := resolv.NewObject(blX, blY, w, h, tag) // Unlike its frontend counter part, the position of a "resolv.Object" must be specified by "bottom-left point" because "w" and "h" must be positive, see "resolv.Object.BoundsToSpace" for details
|
collider := resolv.NewObjectSingleTag(blX, blY, w, h, tag) // Unlike its frontend counter part, the position of a "resolv.Object" must be specified by "bottom-left point" because "w" and "h" must be positive, see "resolv.Object.BoundsToSpace" for details
|
||||||
shape := resolv.NewRectangle(0, 0, w, h)
|
shape := resolv.NewRectangle(0, 0, w, h)
|
||||||
collider.SetShape(shape)
|
collider.SetShape(shape)
|
||||||
collider.Data = data
|
collider.Data = data
|
||||||
|
@ -107,7 +107,7 @@ var Characters = map[int]*CharacterConfig{
|
|||||||
GetUpInvinsibleFrames: int32(10),
|
GetUpInvinsibleFrames: int32(10),
|
||||||
GetUpFramesToRecover: int32(27),
|
GetUpFramesToRecover: int32(27),
|
||||||
|
|
||||||
Speed: int32(float64(2.19) * WORLD_TO_VIRTUAL_GRID_RATIO), // I don't know why "2.2" is so special that it throws a compile error
|
Speed: int32(float64(2.2) * WORLD_TO_VIRTUAL_GRID_RATIO), // I don't know why "2.2" is so special that it throws a compile error
|
||||||
JumpingInitVelY: int32(float64(7.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
JumpingInitVelY: int32(float64(7.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
JumpingFramesToRecover: int32(2),
|
JumpingFramesToRecover: int32(2),
|
||||||
|
|
||||||
@ -234,7 +234,7 @@ var skills = map[int]*Skill{
|
|||||||
HitStunFrames: int32(13),
|
HitStunFrames: int32(13),
|
||||||
BlockStunFrames: int32(9),
|
BlockStunFrames: int32(9),
|
||||||
Damage: int32(5),
|
Damage: int32(5),
|
||||||
SelfLockVelX: int32(float64(0.05) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
SelfLockVelX: int32(float64(0.1) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
SelfLockVelY: NO_LOCK_VEL,
|
SelfLockVelY: NO_LOCK_VEL,
|
||||||
PushbackVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
PushbackVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
PushbackVelY: int32(0),
|
PushbackVelY: int32(0),
|
||||||
@ -332,7 +332,7 @@ var skills = map[int]*Skill{
|
|||||||
HitStunFrames: int32(13),
|
HitStunFrames: int32(13),
|
||||||
BlockStunFrames: int32(9),
|
BlockStunFrames: int32(9),
|
||||||
Damage: int32(5),
|
Damage: int32(5),
|
||||||
SelfLockVelX: int32(float64(0.05) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
SelfLockVelX: int32(float64(0.1) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
SelfLockVelY: NO_LOCK_VEL,
|
SelfLockVelY: NO_LOCK_VEL,
|
||||||
PushbackVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
PushbackVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||||
PushbackVelY: int32(0),
|
PushbackVelY: int32(0),
|
||||||
|
@ -15,7 +15,7 @@ func NewInputFrameDownsync(inputFrameId int32, inputList []uint64, confirmedList
|
|||||||
}
|
}
|
||||||
|
|
||||||
func NewRingBufferJs(n int32) *js.Object {
|
func NewRingBufferJs(n int32) *js.Object {
|
||||||
return js.MakeFullWrapper(NewRingBuffer(n))
|
return js.MakeFullWrapper(resolv.NewRingBuffer(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCollisionSpaceJs(spaceW, spaceH, minStepW, minStepH int) *js.Object {
|
func NewCollisionSpaceJs(spaceW, spaceH, minStepW, minStepH int) *js.Object {
|
||||||
@ -113,7 +113,7 @@ func GetCharacterConfigsOrderedByJoinIndex(speciesIdList []int) []*js.Object {
|
|||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(inputsBuffer *RingBuffer, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig) *js.Object {
|
func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrameJs(inputsBuffer *resolv.RingBuffer, currRenderFrame *RoomDownsyncFrame, collisionSys *resolv.Space, collisionSysMap map[int32]*resolv.Object, collisionSpaceOffsetX, collisionSpaceOffsetY float64, chConfigsOrderedByJoinIndex []*CharacterConfig) *js.Object {
|
||||||
// We need access to all fields of RoomDownsyncFrame for displaying in frontend
|
// We need access to all fields of RoomDownsyncFrame for displaying in frontend
|
||||||
return js.MakeFullWrapper(ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer, currRenderFrame, collisionSys, collisionSysMap, collisionSpaceOffsetX, collisionSpaceOffsetY, chConfigsOrderedByJoinIndex))
|
return js.MakeFullWrapper(ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer, currRenderFrame, collisionSys, collisionSysMap, collisionSpaceOffsetX, collisionSpaceOffsetY, chConfigsOrderedByJoinIndex))
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ package resolv
|
|||||||
// Cell is used to contain and organize Object information.
|
// Cell is used to contain and organize Object information.
|
||||||
type Cell struct {
|
type Cell struct {
|
||||||
X, Y int // The X and Y position of the cell in the Space - note that this is in Grid position, not World position.
|
X, Y int // The X and Y position of the cell in the Space - note that this is in Grid position, not World position.
|
||||||
Objects []*Object // The Objects that a Cell contains.
|
Objects *RingBuffer // The Objects that a Cell contains.
|
||||||
}
|
}
|
||||||
|
|
||||||
// newCell creates a new cell at the specified X and Y position. Should not be used directly.
|
// newCell creates a new cell at the specified X and Y position. Should not be used directly.
|
||||||
@ -11,25 +11,27 @@ func newCell(x, y int) *Cell {
|
|||||||
return &Cell{
|
return &Cell{
|
||||||
X: x,
|
X: x,
|
||||||
Y: y,
|
Y: y,
|
||||||
Objects: []*Object{},
|
Objects: NewRingBuffer(16), // A single cell is so small thus wouldn't have many touching objects simultaneously
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// register registers an object with a Cell. Should not be used directly.
|
// register registers an object with a Cell. Should not be used directly.
|
||||||
func (cell *Cell) register(obj *Object) {
|
func (cell *Cell) register(obj *Object) {
|
||||||
if !cell.Contains(obj) {
|
if !cell.Contains(obj) {
|
||||||
cell.Objects = append(cell.Objects, obj)
|
cell.Objects.Put(obj)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// unregister unregisters an object from a Cell. Should not be used directly.
|
// unregister unregisters an object from a Cell. Should not be used directly.
|
||||||
func (cell *Cell) unregister(obj *Object) {
|
func (cell *Cell) unregister(obj *Object) {
|
||||||
|
rb := cell.Objects
|
||||||
for i, o := range cell.Objects {
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
o := rb.GetByFrameId(i).(*Object)
|
||||||
if o == obj {
|
if o == obj {
|
||||||
cell.Objects[i] = cell.Objects[len(cell.Objects)-1]
|
// swap with the st element
|
||||||
cell.Objects = cell.Objects[:len(cell.Objects)-1]
|
rb.SetByFrameId(rb.GetByFrameId(rb.StFrameId), i)
|
||||||
|
// pop the current st element
|
||||||
|
rb.Pop()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,7 +41,9 @@ func (cell *Cell) unregister(obj *Object) {
|
|||||||
|
|
||||||
// Contains returns whether a Cell contains the specified Object at its position.
|
// Contains returns whether a Cell contains the specified Object at its position.
|
||||||
func (cell *Cell) Contains(obj *Object) bool {
|
func (cell *Cell) Contains(obj *Object) bool {
|
||||||
for _, o := range cell.Objects {
|
rb := cell.Objects
|
||||||
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
o := rb.GetByFrameId(i).(*Object)
|
||||||
if o == obj {
|
if o == obj {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -49,7 +53,9 @@ func (cell *Cell) Contains(obj *Object) bool {
|
|||||||
|
|
||||||
// ContainsTags returns whether a Cell contains an Object that has the specified tag at its position.
|
// ContainsTags returns whether a Cell contains an Object that has the specified tag at its position.
|
||||||
func (cell *Cell) ContainsTags(tags ...string) bool {
|
func (cell *Cell) ContainsTags(tags ...string) bool {
|
||||||
for _, o := range cell.Objects {
|
rb := cell.Objects
|
||||||
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
o := rb.GetByFrameId(i).(*Object)
|
||||||
if o.HasTags(tags...) {
|
if o.HasTags(tags...) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -59,5 +65,5 @@ func (cell *Cell) ContainsTags(tags ...string) bool {
|
|||||||
|
|
||||||
// Occupied returns whether a Cell contains any Objects at all.
|
// Occupied returns whether a Cell contains any Objects at all.
|
||||||
func (cell *Cell) Occupied() bool {
|
func (cell *Cell) Occupied() bool {
|
||||||
return len(cell.Objects) > 0
|
return 0 < cell.Objects.Cnt
|
||||||
}
|
}
|
||||||
|
@ -5,21 +5,37 @@ package resolv
|
|||||||
type Collision struct {
|
type Collision struct {
|
||||||
checkingObject *Object // The checking object
|
checkingObject *Object // The checking object
|
||||||
dx, dy float64 // The delta the checking object was moving on that caused this collision
|
dx, dy float64 // The delta the checking object was moving on that caused this collision
|
||||||
Objects []*Object // Slice of objects that were collided with; sorted according to distance to calling Object.
|
Objects *RingBuffer // Slice of objects that were collided with; sorted according to distance to calling Object.
|
||||||
Cells []*Cell // Slice of cells that were collided with; sorted according to distance to calling Object.
|
Cells *RingBuffer // Slice of cells that were collided with; sorted according to distance to calling Object.
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCollision() *Collision {
|
func NewCollision() *Collision {
|
||||||
return &Collision{
|
return &Collision{
|
||||||
Objects: []*Object{},
|
Objects: NewRingBuffer(16), // I don't expect it to exceed 10 actually
|
||||||
|
Cells: NewRingBuffer(16),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cc *Collision) Clear() {
|
||||||
|
cc.checkingObject = nil
|
||||||
|
cc.dx = 0
|
||||||
|
cc.dy = 0
|
||||||
|
cc.Objects.Clear()
|
||||||
|
cc.Cells.Clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cc *Collision) FirstCollidedObject() *Object {
|
||||||
|
if 0 >= cc.Objects.Cnt {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return cc.Objects.Pop().(*Object)
|
||||||
|
}
|
||||||
|
|
||||||
// HasTags returns whether any objects within the Collision have all of the specified tags. This slice does not contain the Object that called Check().
|
// HasTags returns whether any objects within the Collision have all of the specified tags. This slice does not contain the Object that called Check().
|
||||||
func (cc *Collision) HasTags(tags ...string) bool {
|
func (cc *Collision) HasTags(tags ...string) bool {
|
||||||
|
rb := cc.Objects
|
||||||
for _, o := range cc.Objects {
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
o := rb.GetByFrameId(i).(*Object)
|
||||||
if o == cc.checkingObject {
|
if o == cc.checkingObject {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -38,8 +54,9 @@ func (cc *Collision) ObjectsByTags(tags ...string) []*Object {
|
|||||||
|
|
||||||
objects := []*Object{}
|
objects := []*Object{}
|
||||||
|
|
||||||
for _, o := range cc.Objects {
|
rb := cc.Objects
|
||||||
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
o := rb.GetByFrameId(i).(*Object)
|
||||||
if o == cc.checkingObject {
|
if o == cc.checkingObject {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -105,7 +122,7 @@ func (cc *Collision) SlideAgainstCell(cell *Cell, avoidTags ...string) Vector {
|
|||||||
|
|
||||||
sp := cc.checkingObject.Space
|
sp := cc.checkingObject.Space
|
||||||
|
|
||||||
collidingCell := cc.Cells[0]
|
collidingCell := cc.Cells.GetByFrameId(cc.Cells.StFrameId).(*Cell)
|
||||||
ccX, ccY := sp.SpaceToWorld(collidingCell.X, collidingCell.Y)
|
ccX, ccY := sp.SpaceToWorld(collidingCell.X, collidingCell.Y)
|
||||||
hX := float64(sp.CellWidth) / 2.0
|
hX := float64(sp.CellWidth) / 2.0
|
||||||
hY := float64(sp.CellHeight) / 2.0
|
hY := float64(sp.CellHeight) / 2.0
|
||||||
|
@ -2,7 +2,6 @@ package resolv
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
"math"
|
||||||
//"sort"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Object represents an object that can be spread across one or more Cells in a Space. An Object is essentially an AABB (Axis-Aligned Bounding Box) Rectangle.
|
// Object represents an object that can be spread across one or more Cells in a Space. An Object is essentially an AABB (Axis-Aligned Bounding Box) Rectangle.
|
||||||
@ -10,19 +9,34 @@ type Object struct {
|
|||||||
Shape Shape // A shape for more specific collision-checking.
|
Shape Shape // A shape for more specific collision-checking.
|
||||||
Space *Space // Reference to the Space the Object exists within
|
Space *Space // Reference to the Space the Object exists within
|
||||||
X, Y, W, H float64 // Position and size of the Object in the Space
|
X, Y, W, H float64 // Position and size of the Object in the Space
|
||||||
TouchingCells []*Cell // An array of Cells the Object is touching
|
TouchingCells *RingBuffer // An array of Cells the Object is touching
|
||||||
Data interface{} // A pointer to a user-definable object
|
Data interface{} // A pointer to a user-definable object
|
||||||
ignoreList map[*Object]bool // Set of Objects to ignore when checking for collisions
|
ignoreList map[*Object]bool // Set of Objects to ignore when checking for collisions
|
||||||
tags []string // A list of tags the Object has
|
tags []string // A list of tags the Object has
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewObject returns a new Object of the specified position and size.
|
// NewObject returns a new Object of the specified position and size.
|
||||||
|
func NewObjectSingleTag(x, y, w, h float64, tag string) *Object {
|
||||||
|
o := &Object{
|
||||||
|
X: x,
|
||||||
|
Y: y,
|
||||||
|
W: w,
|
||||||
|
H: h,
|
||||||
|
TouchingCells: NewRingBuffer(512), // [WARNING] Should make N large enough to cover all "TouchingCells", otherwise some cells would fail to unregister an object, resulting in memory corruption and incorrect detection result!
|
||||||
|
tags: []string{tag},
|
||||||
|
ignoreList: map[*Object]bool{},
|
||||||
|
}
|
||||||
|
|
||||||
|
return o
|
||||||
|
}
|
||||||
|
|
||||||
func NewObject(x, y, w, h float64, tags ...string) *Object {
|
func NewObject(x, y, w, h float64, tags ...string) *Object {
|
||||||
o := &Object{
|
o := &Object{
|
||||||
X: x,
|
X: x,
|
||||||
Y: y,
|
Y: y,
|
||||||
W: w,
|
W: w,
|
||||||
H: h,
|
H: h,
|
||||||
|
TouchingCells: NewRingBuffer(512),
|
||||||
tags: []string{},
|
tags: []string{},
|
||||||
ignoreList: map[*Object]bool{},
|
ignoreList: map[*Object]bool{},
|
||||||
}
|
}
|
||||||
@ -59,7 +73,7 @@ func (obj *Object) Update() {
|
|||||||
|
|
||||||
space := obj.Space
|
space := obj.Space
|
||||||
|
|
||||||
obj.Space.Remove(obj)
|
obj.Space.RemoveSingle(obj)
|
||||||
|
|
||||||
obj.Space = space
|
obj.Space = space
|
||||||
|
|
||||||
@ -73,7 +87,7 @@ func (obj *Object) Update() {
|
|||||||
|
|
||||||
if c != nil {
|
if c != nil {
|
||||||
c.register(obj)
|
c.register(obj)
|
||||||
obj.TouchingCells = append(obj.TouchingCells, c)
|
obj.TouchingCells.Put(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -154,17 +168,22 @@ func (obj *Object) BoundsToSpace(dx, dy float64) (int, int, int, int) {
|
|||||||
|
|
||||||
// SharesCells returns whether the Object occupies a cell shared by the specified other Object.
|
// SharesCells returns whether the Object occupies a cell shared by the specified other Object.
|
||||||
func (obj *Object) SharesCells(other *Object) bool {
|
func (obj *Object) SharesCells(other *Object) bool {
|
||||||
for _, cell := range obj.TouchingCells {
|
rb := obj.TouchingCells
|
||||||
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
cell := rb.GetByFrameId(i).(*Cell)
|
||||||
if cell.Contains(other) {
|
if cell.Contains(other) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// SharesCellsTags returns if the Cells the Object occupies have an object with the specified tags.
|
// SharesCellsTags returns if the Cells the Object occupies have an object with the specified tags.
|
||||||
func (obj *Object) SharesCellsTags(tags ...string) bool {
|
func (obj *Object) SharesCellsTags(tags ...string) bool {
|
||||||
for _, cell := range obj.TouchingCells {
|
rb := obj.TouchingCells
|
||||||
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
cell := rb.GetByFrameId(i).(*Cell)
|
||||||
if cell.ContainsTags(tags...) {
|
if cell.ContainsTags(tags...) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -218,13 +237,12 @@ func (obj *Object) SetBounds(topLeft, bottomRight Vector) {
|
|||||||
// Check checks the space around the object using the designated delta movement (dx and dy). This is done by querying the containing Space's Cells
|
// Check checks the space around the object using the designated delta movement (dx and dy). This is done by querying the containing Space's Cells
|
||||||
// so that it can see if moving it would coincide with a cell that houses another Object (filtered using the given selection of tag strings). If so,
|
// so that it can see if moving it would coincide with a cell that houses another Object (filtered using the given selection of tag strings). If so,
|
||||||
// Check returns a Collision. If no objects are found or the Object does not exist within a Space, this function returns nil.
|
// Check returns a Collision. If no objects are found or the Object does not exist within a Space, this function returns nil.
|
||||||
func (obj *Object) Check(dx, dy float64, tags ...string) *Collision {
|
func (obj *Object) CheckAllWithHolder(dx, dy float64, cc *Collision) bool {
|
||||||
|
|
||||||
if obj.Space == nil {
|
if obj.Space == nil {
|
||||||
return nil
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
cc := NewCollision()
|
|
||||||
cc.checkingObject = obj
|
cc.checkingObject = obj
|
||||||
|
|
||||||
if dx < 0 {
|
if dx < 0 {
|
||||||
@ -253,63 +271,36 @@ func (obj *Object) Check(dx, dy float64, tags ...string) *Collision {
|
|||||||
|
|
||||||
if c := obj.Space.Cell(x, y); c != nil {
|
if c := obj.Space.Cell(x, y); c != nil {
|
||||||
|
|
||||||
for _, o := range c.Objects {
|
rb := c.Objects
|
||||||
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
o := rb.GetByFrameId(i).(*Object)
|
||||||
// We only want cells that have objects other than the checking object, or that aren't on the ignore list.
|
// We only want cells that have objects other than the checking object, or that aren't on the ignore list.
|
||||||
if ignored := obj.ignoreList[o]; o == obj || ignored {
|
if ignored := obj.ignoreList[o]; o == obj || ignored {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, added := objectsAdded[o]; (len(tags) == 0 || o.HasTags(tags...)) && !added {
|
if _, added := objectsAdded[o]; !added {
|
||||||
|
cc.Objects.Put(o)
|
||||||
cc.Objects = append(cc.Objects, o)
|
|
||||||
objectsAdded[o] = true
|
objectsAdded[o] = true
|
||||||
if _, added := cellsAdded[c]; !added {
|
if _, added := cellsAdded[c]; !added {
|
||||||
cc.Cells = append(cc.Cells, c)
|
cc.Cells.Put(c)
|
||||||
cellsAdded[c] = true
|
cellsAdded[c] = true
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if 0 >= cc.Objects.Cnt {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(cc.Objects) == 0 {
|
return true
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
// In my use case, order of objects within a collision instance is not needed, and this also favors both runtime performance & size reduction of `jsexport.js`.
|
|
||||||
|
|
||||||
ox, oy := cc.checkingObject.Center()
|
|
||||||
oc := Vector{ox, oy}
|
|
||||||
sort.Slice(cc.Objects, func(i, j int) bool {
|
|
||||||
|
|
||||||
ix, iy := cc.Objects[i].Center()
|
|
||||||
jx, jy := cc.Objects[j].Center()
|
|
||||||
return Vector{ix, iy}.Sub(oc).Magnitude2() < Vector{jx, jy}.Sub(oc).Magnitude2()
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
cw := cc.checkingObject.Space.CellWidth
|
|
||||||
ch := cc.checkingObject.Space.CellHeight
|
|
||||||
|
|
||||||
sort.Slice(cc.Cells, func(i, j int) bool {
|
|
||||||
|
|
||||||
return Vector{float64(cc.Cells[i].X*cw + (cw / 2)), float64(cc.Cells[i].Y*ch + (ch / 2))}.Sub(oc).Magnitude2() <
|
|
||||||
Vector{float64(cc.Cells[j].X*cw + (cw / 2)), float64(cc.Cells[j].Y*ch + (ch / 2))}.Sub(oc).Magnitude2()
|
|
||||||
|
|
||||||
})
|
|
||||||
*/
|
|
||||||
|
|
||||||
return cc
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Overlaps returns if an Object overlaps another Object.
|
// Overlaps returns if an Object overlaps another Object.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package battle
|
package resolv
|
||||||
|
|
||||||
const (
|
const (
|
||||||
RING_BUFF_CONSECUTIVE_SET = int32(0)
|
RING_BUFF_CONSECUTIVE_SET = int32(0)
|
||||||
@ -20,6 +20,8 @@ func NewRingBuffer(n int32) *RingBuffer {
|
|||||||
return &RingBuffer{
|
return &RingBuffer{
|
||||||
Ed: 0,
|
Ed: 0,
|
||||||
St: 0,
|
St: 0,
|
||||||
|
EdFrameId: 0,
|
||||||
|
StFrameId: 0,
|
||||||
N: n,
|
N: n,
|
||||||
Cnt: 0,
|
Cnt: 0,
|
||||||
Eles: make([]interface{}, n),
|
Eles: make([]interface{}, n),
|
||||||
@ -122,3 +124,13 @@ func (rb *RingBuffer) SetByFrameId(pItem interface{}, frameId int32) (int32, int
|
|||||||
|
|
||||||
return ret, oldStFrameId, oldEdFrameId
|
return ret, oldStFrameId, oldEdFrameId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rb *RingBuffer) Clear() {
|
||||||
|
for 0 < rb.Cnt {
|
||||||
|
rb.Pop()
|
||||||
|
}
|
||||||
|
rb.St = 0
|
||||||
|
rb.Ed = 0
|
||||||
|
rb.StFrameId = 0
|
||||||
|
rb.EdFrameId = 0
|
||||||
|
}
|
@ -38,8 +38,9 @@ func (line *Line) Project(axis Vector) Vector {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (line *Line) Normal() Vector {
|
func (line *Line) Normal() Vector {
|
||||||
v := line.Vector()
|
dy := line.End[1] - line.Start[1]
|
||||||
return Vector{v[1], -v[0]}.Unit()
|
dx := line.End[0] - line.Start[0]
|
||||||
|
return Vector{dy, -dx}.Unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (line *Line) Vector() Vector {
|
func (line *Line) Vector() Vector {
|
||||||
@ -177,24 +178,20 @@ func (cp *ConvexPolygon) AddPoints(vertexPositions ...float64) {
|
|||||||
// Lines returns a slice of transformed Lines composing the ConvexPolygon.
|
// Lines returns a slice of transformed Lines composing the ConvexPolygon.
|
||||||
func (cp *ConvexPolygon) Lines() []*Line {
|
func (cp *ConvexPolygon) Lines() []*Line {
|
||||||
|
|
||||||
lines := []*Line{}
|
|
||||||
|
|
||||||
vertices := cp.Transformed()
|
vertices := cp.Transformed()
|
||||||
|
linesCnt := len(vertices)
|
||||||
|
if !cp.Closed {
|
||||||
|
linesCnt -= 1
|
||||||
|
}
|
||||||
|
lines := make([]*Line, linesCnt)
|
||||||
|
|
||||||
for i := 0; i < len(vertices); i++ {
|
for i := 0; i < linesCnt; i++ {
|
||||||
|
|
||||||
start, end := vertices[i], vertices[0]
|
start, end := vertices[i], vertices[0]
|
||||||
|
|
||||||
if i < len(vertices)-1 {
|
if i < len(vertices)-1 {
|
||||||
end = vertices[i+1]
|
end = vertices[i+1]
|
||||||
} else if !cp.Closed {
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
line := NewLine(start[0], start[1], end[0], end[1])
|
line := NewLine(start[0], start[1], end[0], end[1])
|
||||||
|
lines[i] = line
|
||||||
lines = append(lines, line)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
@ -203,9 +200,9 @@ func (cp *ConvexPolygon) Lines() []*Line {
|
|||||||
|
|
||||||
// Transformed returns the ConvexPolygon's points / vertices, transformed according to the ConvexPolygon's position.
|
// Transformed returns the ConvexPolygon's points / vertices, transformed according to the ConvexPolygon's position.
|
||||||
func (cp *ConvexPolygon) Transformed() []Vector {
|
func (cp *ConvexPolygon) Transformed() []Vector {
|
||||||
transformed := []Vector{}
|
transformed := make([]Vector, len(cp.Points))
|
||||||
for _, point := range cp.Points {
|
for i, point := range cp.Points {
|
||||||
transformed = append(transformed, Vector{point[0] + cp.X, point[1] + cp.Y})
|
transformed[i] = Vector{point[0] + cp.X, point[1] + cp.Y}
|
||||||
}
|
}
|
||||||
return transformed
|
return transformed
|
||||||
}
|
}
|
||||||
@ -275,12 +272,14 @@ func (cp *ConvexPolygon) Center() Vector {
|
|||||||
|
|
||||||
pos := Vector{0, 0}
|
pos := Vector{0, 0}
|
||||||
|
|
||||||
for _, v := range cp.Transformed() {
|
vertices := cp.Transformed()
|
||||||
|
for _, v := range vertices {
|
||||||
pos.Add(v)
|
pos.Add(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
pos[0] /= float64(len(cp.Transformed()))
|
denom := float64(len(vertices))
|
||||||
pos[1] /= float64(len(cp.Transformed()))
|
pos[0] /= denom
|
||||||
|
pos[1] /= denom
|
||||||
|
|
||||||
return pos
|
return pos
|
||||||
|
|
||||||
@ -305,10 +304,10 @@ func (cp *ConvexPolygon) Project(axis Vector) Projection {
|
|||||||
|
|
||||||
// SATAxes returns the axes of the ConvexPolygon for SAT intersection testing.
|
// SATAxes returns the axes of the ConvexPolygon for SAT intersection testing.
|
||||||
func (cp *ConvexPolygon) SATAxes() []Vector {
|
func (cp *ConvexPolygon) SATAxes() []Vector {
|
||||||
|
lines := cp.Lines()
|
||||||
axes := []Vector{}
|
axes := make([]Vector, len(lines))
|
||||||
for _, line := range cp.Lines() {
|
for i, line := range lines {
|
||||||
axes = append(axes, line.Normal())
|
axes[i] = line.Normal()
|
||||||
}
|
}
|
||||||
return axes
|
return axes
|
||||||
|
|
||||||
|
@ -30,7 +30,20 @@ func NewSpace(spaceWidth, spaceHeight, cellWidth, cellHeight int) *Space {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// [WARNING] The slice type boxing/unboxing is proved by profiling to be heavy after transpiled to JavaScript, thus adding some "XxxSingle" shortcuts here.
|
||||||
// Add adds the specified Objects to the Space, updating the Space's cells to refer to the Object.
|
// Add adds the specified Objects to the Space, updating the Space's cells to refer to the Object.
|
||||||
|
func (sp *Space) AddSingle(obj *Object) {
|
||||||
|
|
||||||
|
if sp == nil {
|
||||||
|
panic("ERROR: space is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.Space = sp
|
||||||
|
|
||||||
|
// We call Update() once to make sure the object gets its cells added.
|
||||||
|
obj.Update()
|
||||||
|
}
|
||||||
|
|
||||||
func (sp *Space) Add(objects ...*Object) {
|
func (sp *Space) Add(objects ...*Object) {
|
||||||
|
|
||||||
if sp == nil {
|
if sp == nil {
|
||||||
@ -50,6 +63,20 @@ func (sp *Space) Add(objects ...*Object) {
|
|||||||
|
|
||||||
// Remove removes the specified Objects from being associated with the Space. This should be done whenever an Object is removed from the
|
// Remove removes the specified Objects from being associated with the Space. This should be done whenever an Object is removed from the
|
||||||
// game.
|
// game.
|
||||||
|
func (sp *Space) RemoveSingle(obj *Object) {
|
||||||
|
|
||||||
|
if sp == nil {
|
||||||
|
panic("ERROR: space is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
for 0 < obj.TouchingCells.Cnt {
|
||||||
|
cell := obj.TouchingCells.Pop().(*Cell)
|
||||||
|
cell.unregister(obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
obj.Space = nil
|
||||||
|
}
|
||||||
|
|
||||||
func (sp *Space) Remove(objects ...*Object) {
|
func (sp *Space) Remove(objects ...*Object) {
|
||||||
|
|
||||||
if sp == nil {
|
if sp == nil {
|
||||||
@ -57,13 +84,11 @@ func (sp *Space) Remove(objects ...*Object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range objects {
|
for _, obj := range objects {
|
||||||
|
for 0 < obj.TouchingCells.Cnt {
|
||||||
for _, cell := range obj.TouchingCells {
|
cell := obj.TouchingCells.Pop().(*Cell)
|
||||||
cell.unregister(obj)
|
cell.unregister(obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
obj.TouchingCells = []*Cell{}
|
|
||||||
|
|
||||||
obj.Space = nil
|
obj.Space = nil
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -80,16 +105,14 @@ func (sp *Space) Objects() []*Object {
|
|||||||
for cy := range sp.Cells {
|
for cy := range sp.Cells {
|
||||||
|
|
||||||
for cx := range sp.Cells[cy] {
|
for cx := range sp.Cells[cy] {
|
||||||
|
rb := sp.Cells[cy][cx].Objects
|
||||||
for _, o := range sp.Cells[cy][cx].Objects {
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
o := rb.GetByFrameId(i).(*Object)
|
||||||
if _, added := objectsAdded[o]; !added {
|
if _, added := objectsAdded[o]; !added {
|
||||||
objects = append(objects, o)
|
objects = append(objects, o)
|
||||||
objectsAdded[o] = true
|
objectsAdded[o] = true
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -100,19 +123,13 @@ func (sp *Space) Objects() []*Object {
|
|||||||
|
|
||||||
// Resize resizes the internal Cells array.
|
// Resize resizes the internal Cells array.
|
||||||
func (sp *Space) Resize(width, height int) {
|
func (sp *Space) Resize(width, height int) {
|
||||||
|
sp.Cells = make([][]*Cell, height)
|
||||||
sp.Cells = [][]*Cell{}
|
|
||||||
|
|
||||||
for y := 0; y < height; y++ {
|
for y := 0; y < height; y++ {
|
||||||
|
sp.Cells[y] = make([]*Cell, width)
|
||||||
sp.Cells = append(sp.Cells, []*Cell{})
|
|
||||||
|
|
||||||
for x := 0; x < width; x++ {
|
for x := 0; x < width; x++ {
|
||||||
sp.Cells[y] = append(sp.Cells[y], newCell(x, y))
|
sp.Cells[y][x] = newCell(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cell returns the Cell at the given cellular / spatial (not world) X and Y position in the Space. If the X and Y position are
|
// Cell returns the Cell at the given cellular / spatial (not world) X and Y position in the Space. If the X and Y position are
|
||||||
@ -137,25 +154,23 @@ func (sp *Space) CheckCells(x, y, w, h int, tags ...string) *Object {
|
|||||||
cell := sp.Cell(ix, iy)
|
cell := sp.Cell(ix, iy)
|
||||||
|
|
||||||
if cell != nil {
|
if cell != nil {
|
||||||
|
rb := cell.Objects
|
||||||
if len(tags) > 0 {
|
if len(tags) > 0 {
|
||||||
|
|
||||||
if cell.ContainsTags(tags...) {
|
if cell.ContainsTags(tags...) {
|
||||||
for _, obj := range cell.Objects {
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
obj := rb.GetByFrameId(i).(*Object)
|
||||||
if obj.HasTags(tags...) {
|
if obj.HasTags(tags...) {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if cell.Occupied() {
|
} else if cell.Occupied() {
|
||||||
return cell.Objects[0]
|
return rb.GetByFrameId(rb.StFrameId).(*Object)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -178,10 +193,13 @@ func (sp *Space) CheckCellsWorld(x, y, w, h float64, tags ...string) *Object {
|
|||||||
func (sp *Space) UnregisterAllObjects() {
|
func (sp *Space) UnregisterAllObjects() {
|
||||||
|
|
||||||
for y := 0; y < len(sp.Cells); y++ {
|
for y := 0; y < len(sp.Cells); y++ {
|
||||||
|
|
||||||
for x := 0; x < len(sp.Cells[y]); x++ {
|
for x := 0; x < len(sp.Cells[y]); x++ {
|
||||||
cell := sp.Cells[y][x]
|
cell := sp.Cells[y][x]
|
||||||
sp.Remove(cell.Objects...)
|
rb := cell.Objects
|
||||||
|
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||||
|
o := rb.GetByFrameId(i).(*Object)
|
||||||
|
sp.RemoveSingle(o)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user