mirror of
https://github.com/genxium/DelayNoMore
synced 2024-12-25 11:18:55 +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)
|
||||
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
|
||||
|
@ -1,11 +1,11 @@
|
||||
<?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="65" source="tiles1.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">
|
||||
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>
|
||||
</layer>
|
||||
<objectgroup id="1" name="PlayerStartingPos">
|
||||
@ -84,12 +84,12 @@
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="84" x="640" y="224" width="16" height="800">
|
||||
<object id="84" x="640" y="224" width="16" height="416">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="85" x="1680" y="224" width="16" height="800">
|
||||
<object id="85" x="1680" y="224" width="16" height="416">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
@ -149,17 +149,12 @@
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
</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">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="119" x="656" y="592" width="1024" height="416">
|
||||
<object id="119" x="656" y="592" width="512" height="48">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
@ -169,5 +164,10 @@
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
</object>
|
||||
<object id="137" x="1168" y="592" width="512" height="48">
|
||||
<properties>
|
||||
<property name="boundary_type" value="barrier"/>
|
||||
</properties>
|
||||
</object>
|
||||
</objectgroup>
|
||||
</map>
|
||||
|
@ -461,7 +461,7 @@
|
||||
"array": [
|
||||
0,
|
||||
0,
|
||||
216.50635094610968,
|
||||
217.52040535921228,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -72,11 +72,14 @@
|
||||
"__id__": 3
|
||||
},
|
||||
{
|
||||
"__id__": 10
|
||||
"__id__": 9
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 50
|
||||
},
|
||||
{
|
||||
"__id__": 51
|
||||
},
|
||||
@ -88,9 +91,6 @@
|
||||
},
|
||||
{
|
||||
"__id__": 54
|
||||
},
|
||||
{
|
||||
"__id__": 55
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -156,9 +156,6 @@
|
||||
},
|
||||
{
|
||||
"__id__": 5
|
||||
},
|
||||
{
|
||||
"__id__": 6
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -220,34 +217,6 @@
|
||||
"_tmxFile": null,
|
||||
"_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",
|
||||
"_name": "",
|
||||
@ -266,7 +235,7 @@
|
||||
"__uuid__": "d92d4831-cd65-4eb5-90bd-b77021aec35b"
|
||||
},
|
||||
"joystickInputControllerNode": {
|
||||
"__id__": 7
|
||||
"__id__": 6
|
||||
},
|
||||
"confirmLogoutPrefab": null,
|
||||
"simplePressToGoDialogPrefab": null,
|
||||
@ -279,19 +248,19 @@
|
||||
"forceBigEndianFloatingNumDecoding": false,
|
||||
"renderFrameIdLagTolerance": 4,
|
||||
"inputFrameFrontLabel": {
|
||||
"__id__": 14
|
||||
"__id__": 13
|
||||
},
|
||||
"sendingQLabel": {
|
||||
"__id__": 16
|
||||
"__id__": 15
|
||||
},
|
||||
"inputFrameDownsyncQLabel": {
|
||||
"__id__": 18
|
||||
"__id__": 17
|
||||
},
|
||||
"peerInputFrameUpsyncQLabel": {
|
||||
"__id__": 20
|
||||
"__id__": 19
|
||||
},
|
||||
"rollbackFramesLabel": {
|
||||
"__id__": 22
|
||||
"__id__": 21
|
||||
},
|
||||
"skippedRenderFrameCntLabel": null,
|
||||
"_id": "e5xQdv12xLoIRr0b36Pie+"
|
||||
@ -301,17 +270,17 @@
|
||||
"_name": "JoystickContainer",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 8
|
||||
"__id__": 7
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 45
|
||||
"__id__": 44
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 50
|
||||
"__id__": 49
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -367,26 +336,26 @@
|
||||
"_name": "Interactive",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 9
|
||||
"__id__": 8
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 7
|
||||
"__id__": 6
|
||||
},
|
||||
{
|
||||
"__id__": 34
|
||||
"__id__": 33
|
||||
},
|
||||
{
|
||||
"__id__": 36
|
||||
"__id__": 35
|
||||
},
|
||||
{
|
||||
"__id__": 40
|
||||
"__id__": 39
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 44
|
||||
"__id__": 43
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -442,20 +411,20 @@
|
||||
"_name": "WidgetsAboveAll",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 10
|
||||
"__id__": 9
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 12
|
||||
"__id__": 11
|
||||
},
|
||||
{
|
||||
"__id__": 8
|
||||
"__id__": 7
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 33
|
||||
"__id__": 32
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -515,13 +484,13 @@
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 9
|
||||
"__id__": 8
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 11
|
||||
"__id__": 10
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -549,7 +518,7 @@
|
||||
"array": [
|
||||
0,
|
||||
0,
|
||||
216.50635094610968,
|
||||
210.4441731196186,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
@ -577,7 +546,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 10
|
||||
"__id__": 9
|
||||
},
|
||||
"_enabled": true,
|
||||
"_cullingMask": 4294967295,
|
||||
@ -613,35 +582,35 @@
|
||||
"_name": "DebugInfo",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 9
|
||||
"__id__": 8
|
||||
},
|
||||
"_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,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 32
|
||||
"__id__": 31
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -697,13 +666,13 @@
|
||||
"_name": "inputFrameFront",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 12
|
||||
"__id__": 11
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 14
|
||||
"__id__": 13
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -759,7 +728,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 13
|
||||
"__id__": 12
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -789,13 +758,13 @@
|
||||
"_name": "sendingQ",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 12
|
||||
"__id__": 11
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 16
|
||||
"__id__": 15
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -851,7 +820,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 15
|
||||
"__id__": 14
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -881,13 +850,13 @@
|
||||
"_name": "inputFrameDownsyncQ",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 12
|
||||
"__id__": 11
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 18
|
||||
"__id__": 17
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -943,7 +912,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 17
|
||||
"__id__": 16
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -973,13 +942,13 @@
|
||||
"_name": "peerInputFrameUpsyncQ",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 12
|
||||
"__id__": 11
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 20
|
||||
"__id__": 19
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -1035,7 +1004,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 19
|
||||
"__id__": 18
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -1065,13 +1034,13 @@
|
||||
"_name": "rollbackFrames",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 12
|
||||
"__id__": 11
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 22
|
||||
"__id__": 21
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -1127,7 +1096,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 21
|
||||
"__id__": 20
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -1157,13 +1126,13 @@
|
||||
"_name": "skippedCnt",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 12
|
||||
"__id__": 11
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 24
|
||||
"__id__": 23
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -1219,7 +1188,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 23
|
||||
"__id__": 22
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -1251,23 +1220,23 @@
|
||||
"_name": "RoomIdIndicator",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 12
|
||||
"__id__": 11
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 26
|
||||
"__id__": 25
|
||||
},
|
||||
{
|
||||
"__id__": 28
|
||||
"__id__": 27
|
||||
}
|
||||
],
|
||||
"_active": false,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 30
|
||||
"__id__": 29
|
||||
},
|
||||
{
|
||||
"__id__": 31
|
||||
"__id__": 30
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -1323,13 +1292,13 @@
|
||||
"_name": "label",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 25
|
||||
"__id__": 24
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 27
|
||||
"__id__": 26
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -1385,7 +1354,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 26
|
||||
"__id__": 25
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [],
|
||||
@ -1413,13 +1382,13 @@
|
||||
"_name": "BoundRoomIdLabel",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 25
|
||||
"__id__": 24
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 29
|
||||
"__id__": 28
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -1475,7 +1444,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 28
|
||||
"__id__": 27
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [],
|
||||
@ -1503,7 +1472,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 25
|
||||
"__id__": 24
|
||||
},
|
||||
"_enabled": true,
|
||||
"_layoutSize": {
|
||||
@ -1536,7 +1505,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 25
|
||||
"__id__": 24
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [],
|
||||
@ -1566,7 +1535,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 12
|
||||
"__id__": 11
|
||||
},
|
||||
"_enabled": true,
|
||||
"_layoutSize": {
|
||||
@ -1599,7 +1568,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 9
|
||||
"__id__": 8
|
||||
},
|
||||
"_enabled": true,
|
||||
"alignMode": 1,
|
||||
@ -1626,13 +1595,13 @@
|
||||
"_name": "CountdownSeconds",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 8
|
||||
"__id__": 7
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 35
|
||||
"__id__": 34
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -1688,7 +1657,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 34
|
||||
"__id__": 33
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -1718,11 +1687,11 @@
|
||||
"_name": "BtnA",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 8
|
||||
"__id__": 7
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 37
|
||||
"__id__": 36
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
@ -1780,16 +1749,16 @@
|
||||
"_name": "Background",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 36
|
||||
"__id__": 35
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 38
|
||||
"__id__": 37
|
||||
},
|
||||
{
|
||||
"__id__": 39
|
||||
"__id__": 38
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -1845,7 +1814,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 37
|
||||
"__id__": 36
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -1879,7 +1848,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 37
|
||||
"__id__": 36
|
||||
},
|
||||
"_enabled": true,
|
||||
"alignMode": 0,
|
||||
@ -1906,11 +1875,11 @@
|
||||
"_name": "BtnB",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 8
|
||||
"__id__": 7
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 41
|
||||
"__id__": 40
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
@ -1968,16 +1937,16 @@
|
||||
"_name": "Background",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 40
|
||||
"__id__": 39
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 42
|
||||
"__id__": 41
|
||||
},
|
||||
{
|
||||
"__id__": 43
|
||||
"__id__": 42
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -2033,7 +2002,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 41
|
||||
"__id__": 40
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -2067,7 +2036,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 41
|
||||
"__id__": 40
|
||||
},
|
||||
"_enabled": true,
|
||||
"alignMode": 0,
|
||||
@ -2094,7 +2063,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 8
|
||||
"__id__": 7
|
||||
},
|
||||
"_enabled": true,
|
||||
"alignMode": 1,
|
||||
@ -2121,20 +2090,20 @@
|
||||
"_name": "JoystickBG",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 7
|
||||
"__id__": 6
|
||||
},
|
||||
"_children": [
|
||||
{
|
||||
"__id__": 46
|
||||
"__id__": 45
|
||||
}
|
||||
],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 48
|
||||
"__id__": 47
|
||||
},
|
||||
{
|
||||
"__id__": 49
|
||||
"__id__": 48
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -2190,13 +2159,13 @@
|
||||
"_name": "Joystick",
|
||||
"_objFlags": 0,
|
||||
"_parent": {
|
||||
"__id__": 45
|
||||
"__id__": 44
|
||||
},
|
||||
"_children": [],
|
||||
"_active": true,
|
||||
"_components": [
|
||||
{
|
||||
"__id__": 47
|
||||
"__id__": 46
|
||||
}
|
||||
],
|
||||
"_prefab": null,
|
||||
@ -2252,7 +2221,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 46
|
||||
"__id__": 45
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -2286,7 +2255,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 45
|
||||
"__id__": 44
|
||||
},
|
||||
"_enabled": true,
|
||||
"_materials": [
|
||||
@ -2320,7 +2289,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 45
|
||||
"__id__": 44
|
||||
},
|
||||
"_enabled": true,
|
||||
"alignMode": 0,
|
||||
@ -2347,7 +2316,7 @@
|
||||
"_name": "",
|
||||
"_objFlags": 0,
|
||||
"node": {
|
||||
"__id__": 7
|
||||
"__id__": 6
|
||||
},
|
||||
"_enabled": true,
|
||||
"alignMode": 0,
|
||||
@ -2449,16 +2418,16 @@
|
||||
},
|
||||
"_enabled": true,
|
||||
"translationListenerNode": {
|
||||
"__id__": 7
|
||||
"__id__": 6
|
||||
},
|
||||
"zoomingListenerNode": {
|
||||
"__id__": 3
|
||||
},
|
||||
"stickhead": {
|
||||
"__id__": 46
|
||||
"__id__": 45
|
||||
},
|
||||
"base": {
|
||||
"__id__": 45
|
||||
"__id__": 44
|
||||
},
|
||||
"joyStickEps": 0.1,
|
||||
"magicLeanLowerBound": 0.414,
|
||||
@ -2479,10 +2448,10 @@
|
||||
"linearMovingEps": 0.1,
|
||||
"scaleByEps": 0.0375,
|
||||
"btnA": {
|
||||
"__id__": 36
|
||||
"__id__": 35
|
||||
},
|
||||
"btnB": {
|
||||
"__id__": 40
|
||||
"__id__": 39
|
||||
},
|
||||
"_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. */
|
||||
|
||||
self.inputFrameUpsyncDelayTolerance = 2;
|
||||
self.collisionMinStep = 2;
|
||||
self.collisionMinStep = 8;
|
||||
|
||||
self.renderCacheSize = 1024;
|
||||
self.serverFps = 60;
|
||||
@ -98,7 +98,7 @@ cc.Class({
|
||||
const p2Vpos = gopkgs.WorldToVirtualGridPos(boundaryObjs.playerStartingPositions[1].x, boundaryObjs.playerStartingPositions[1].y);
|
||||
const colliderRadiusV = gopkgs.WorldToVirtualGridPos(12.0, 0);
|
||||
|
||||
const speciesIdList = [4096, 0];
|
||||
const speciesIdList = [1, 0];
|
||||
const chConfigsOrderedByJoinIndex = gopkgs.GetCharacterConfigsOrderedByJoinIndex(speciesIdList);
|
||||
|
||||
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:usesCleartextTraffic="true"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:launchMode="singleTask"
|
||||
android:taskAffinity="" >
|
||||
android:launchMode="singleTask">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
@ -17,7 +17,8 @@
|
||||
},
|
||||
"encryptJs": false,
|
||||
"excludeScenes": [
|
||||
"8491a86c-bec9-4813-968a-128ca01639e0"
|
||||
"2ff474d9-0c9e-4fe3-87ec-fbff7cae85b4",
|
||||
"92160186-3e0d-4e0a-ae20-97286170ba58"
|
||||
],
|
||||
"fb-instant-games": {},
|
||||
"includeSDKBox": false,
|
||||
@ -37,7 +38,7 @@
|
||||
"REMOTE_SERVER_ROOT": "",
|
||||
"orientation": "portrait"
|
||||
},
|
||||
"startScene": "2ff474d9-0c9e-4fe3-87ec-fbff7cae85b4",
|
||||
"startScene": "8491a86c-bec9-4813-968a-128ca01639e0",
|
||||
"title": "DelayNoMore",
|
||||
"webOrientation": "landscape",
|
||||
"wechatgame": {
|
||||
|
@ -16,7 +16,7 @@ const (
|
||||
PATTERN_ID_UNABLE_TO_OP = -2
|
||||
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
|
||||
|
||||
GRAVITY_X = int32(0)
|
||||
@ -226,16 +226,31 @@ func isPolygonPairOverlapped(a, b *resolv.ConvexPolygon, result *SatResult) bool
|
||||
}
|
||||
|
||||
if 1 < aCnt {
|
||||
for _, axis := range a.SATAxes() {
|
||||
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
|
||||
// Deliberately using "Points" instead of "SATAxes" to avoid unnecessary heap memory alloc
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if 1 < bCnt {
|
||||
for _, axis := range b.SATAxes() {
|
||||
if isPolygonPairSeparatedByDir(a, b, axis.Unit(), result) {
|
||||
for i, _ := range b.Points {
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -411,8 +426,7 @@ func VirtualGridToPolygonColliderBLPos(vx, vy int32, halfBoundingW, halfBounding
|
||||
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 {
|
||||
ret := make([]Vec2D, 0, 10) // no one would simultaneously have more than 5 hardPushbacks
|
||||
func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNextFrame *PlayerDownsync, playerCollider *resolv.Object, playerShape *resolv.ConvexPolygon, snapIntoPlatformOverlap float64, pEffPushback *Vec2D, pHardPushback *[]Vec2D, collision *resolv.Collision) int {
|
||||
virtualGripToWall := float64(0)
|
||||
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
|
||||
}
|
||||
collision := playerCollider.Check(virtualGripToWall, 0)
|
||||
if nil == collision {
|
||||
return &ret
|
||||
retCnt := 0
|
||||
collided := playerCollider.CheckAllWithHolder(virtualGripToWall, 0, collision)
|
||||
if !collided {
|
||||
return retCnt
|
||||
}
|
||||
|
||||
//playerColliderCenterX, playerColliderCenterY := playerCollider.Center()
|
||||
//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
|
||||
switch obj.Data.(type) {
|
||||
case *PlayerDownsync, *MeleeBullet, *FireballBullet:
|
||||
@ -456,15 +475,16 @@ func calcHardPushbacksNorms(joinIndex int32, currPlayerDownsync, thatPlayerInNex
|
||||
// ALWAY snap into hardPushbacks!
|
||||
// [OverlapX, OverlapY] is the unit vector that points into the platform
|
||||
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.Y += pushbackY
|
||||
retCnt++
|
||||
//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)
|
||||
delayedInputFrameId := ConvertToDelayedInputFrameId(currRenderFrame.Id)
|
||||
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.
|
||||
*/
|
||||
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!
|
||||
roomCapacity := len(currRenderFrame.PlayersArr)
|
||||
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?
|
||||
nextRenderFrameFireballBullets := make([]*FireballBullet, 0, len(currRenderFrame.FireballBullets))
|
||||
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)
|
||||
|
||||
bulletLocalId := currRenderFrame.BulletLocalIdCounter
|
||||
@ -813,7 +838,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
||||
playerColliders[i] = playerCollider
|
||||
|
||||
// Add to collision system
|
||||
collisionSys.Add(playerCollider)
|
||||
collisionSys.AddSingle(playerCollider)
|
||||
|
||||
if currPlayerDownsync.InAir {
|
||||
if ATK_CHARACTER_STATE_ONWALL == currPlayerDownsync.CharacterState && !jumpedOrNotList[i] {
|
||||
@ -850,7 +875,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
||||
bulletWx, bulletWy := VirtualGridToWorldPos(fireballBullet.VirtualGridX, fireballBullet.VirtualGridY)
|
||||
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")
|
||||
collisionSys.Add(newBulletCollider)
|
||||
collisionSys.AddSingle(newBulletCollider)
|
||||
bulletColliders = append(bulletColliders, newBulletCollider)
|
||||
fireballBullet.BlState = BULLET_ACTIVE
|
||||
if fireballBullet.BlState != prevFireball.BlState {
|
||||
@ -891,7 +916,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
||||
bulletWx, bulletWy := VirtualGridToWorldPos(offender.VirtualGridX+xfac*meleeBullet.Bullet.HitboxOffsetX, offender.VirtualGridY)
|
||||
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")
|
||||
collisionSys.Add(newBulletCollider)
|
||||
collisionSys.AddSingle(newBulletCollider)
|
||||
bulletColliders = append(bulletColliders, newBulletCollider)
|
||||
meleeBullet.BlState = BULLET_ACTIVE
|
||||
if meleeBullet.BlState != prevMelee.BlState {
|
||||
@ -908,12 +933,16 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
||||
playerCollider := playerColliders[i]
|
||||
playerShape := playerCollider.Shape.(*resolv.ConvexPolygon)
|
||||
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]
|
||||
landedOnGravityPushback := false
|
||||
|
||||
if collision := playerCollider.Check(0, 0); nil != collision {
|
||||
for _, obj := range collision.Objects {
|
||||
if collided := playerCollider.CheckAllWithHolder(0, 0, collision); collided {
|
||||
for true {
|
||||
obj := collision.FirstCollidedObject()
|
||||
if nil == obj {
|
||||
break
|
||||
}
|
||||
isBarrier, isAnotherPlayer, isBullet := false, false, false
|
||||
switch v := obj.Data.(type) {
|
||||
case *PlayerDownsync:
|
||||
@ -943,11 +972,14 @@ 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.
|
||||
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] {
|
||||
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
||||
if isBarrier || (isAnotherPlayer && 0 > projectedMagnitude) {
|
||||
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
||||
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
||||
if 0 < hardPushbackCnt {
|
||||
for i := 0; i < hardPushbackCnt; i++ {
|
||||
hardPushbackNorm := hardPushbackNorms[joinIndex-1][i]
|
||||
projectedMagnitude := pushbackX*hardPushbackNorm.X + pushbackY*hardPushbackNorm.Y
|
||||
if isBarrier || (isAnotherPlayer && 0 > projectedMagnitude) {
|
||||
pushbackX -= projectedMagnitude * hardPushbackNorm.X
|
||||
pushbackY -= projectedMagnitude * hardPushbackNorm.Y
|
||||
}
|
||||
}
|
||||
}
|
||||
effPushbacks[joinIndex-1].X += pushbackX
|
||||
@ -956,10 +988,11 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
||||
if SNAP_INTO_PLATFORM_THRESHOLD < normAlignmentWithGravity {
|
||||
landedOnGravityPushback = true
|
||||
//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 {
|
||||
thatPlayerInNextFrame.InAir = false
|
||||
fallStopping := (currPlayerDownsync.InAir && 0 >= currPlayerDownsync.VelY)
|
||||
@ -1004,9 +1037,10 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
||||
if chConfig.OnWallEnabled {
|
||||
if thatPlayerInNextFrame.InAir {
|
||||
// [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
|
||||
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))
|
||||
normAlignmentWithHorizon2 := (hardPushbackNorm.X*float64(-1.0) + hardPushbackNorm.Y*float64(0.0))
|
||||
if VERTICAL_PLATFORM_THRESHOLD < normAlignmentWithHorizon1 {
|
||||
@ -1031,14 +1065,15 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
||||
|
||||
// 5. Check bullet-anything collisions
|
||||
for _, bulletCollider := range bulletColliders {
|
||||
collision := bulletCollider.Check(0, 0)
|
||||
bulletCollider.Space.Remove(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame
|
||||
exploded := false
|
||||
explodedOnAnotherPlayer := false
|
||||
if nil == collision {
|
||||
collided := bulletCollider.CheckAllWithHolder(0, 0, collision)
|
||||
bulletCollider.Space.RemoveSingle(bulletCollider) // Make sure that the bulletCollider is always removed for each renderFrame
|
||||
if !collided {
|
||||
continue
|
||||
}
|
||||
|
||||
exploded := false
|
||||
explodedOnAnotherPlayer := false
|
||||
|
||||
var bulletStaticAttr *BulletConfig = nil
|
||||
var bulletBattleAttr *BulletBattleAttr = nil
|
||||
switch v := bulletCollider.Data.(type) {
|
||||
@ -1052,7 +1087,11 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
||||
|
||||
bulletShape := bulletCollider.Shape.(*resolv.ConvexPolygon)
|
||||
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)
|
||||
switch t := obj.Data.(type) {
|
||||
case *PlayerDownsync:
|
||||
@ -1170,7 +1209,7 @@ func ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer *RingBuffer
|
||||
}
|
||||
|
||||
for _, playerCollider := range playerColliders {
|
||||
playerCollider.Space.Remove(playerCollider)
|
||||
playerCollider.Space.RemoveSingle(playerCollider)
|
||||
}
|
||||
|
||||
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 {
|
||||
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)
|
||||
collider.SetShape(shape)
|
||||
collider.Data = data
|
||||
|
@ -107,7 +107,7 @@ var Characters = map[int]*CharacterConfig{
|
||||
GetUpInvinsibleFrames: int32(10),
|
||||
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),
|
||||
JumpingFramesToRecover: int32(2),
|
||||
|
||||
@ -234,7 +234,7 @@ var skills = map[int]*Skill{
|
||||
HitStunFrames: int32(13),
|
||||
BlockStunFrames: int32(9),
|
||||
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,
|
||||
PushbackVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||
PushbackVelY: int32(0),
|
||||
@ -332,7 +332,7 @@ var skills = map[int]*Skill{
|
||||
HitStunFrames: int32(13),
|
||||
BlockStunFrames: int32(9),
|
||||
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,
|
||||
PushbackVelX: int32(float64(0.5) * WORLD_TO_VIRTUAL_GRID_RATIO),
|
||||
PushbackVelY: int32(0),
|
||||
|
@ -15,7 +15,7 @@ func NewInputFrameDownsync(inputFrameId int32, inputList []uint64, confirmedList
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -113,7 +113,7 @@ func GetCharacterConfigsOrderedByJoinIndex(speciesIdList []int) []*js.Object {
|
||||
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
|
||||
return js.MakeFullWrapper(ApplyInputFrameDownsyncDynamicsOnSingleRenderFrame(inputsBuffer, currRenderFrame, collisionSys, collisionSysMap, collisionSpaceOffsetX, collisionSpaceOffsetY, chConfigsOrderedByJoinIndex))
|
||||
}
|
||||
|
@ -2,8 +2,8 @@ package resolv
|
||||
|
||||
// Cell is used to contain and organize Object information.
|
||||
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.
|
||||
Objects []*Object // The Objects that a Cell contains.
|
||||
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 *RingBuffer // The Objects that a Cell contains.
|
||||
}
|
||||
|
||||
// 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{
|
||||
X: x,
|
||||
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.
|
||||
func (cell *Cell) register(obj *Object) {
|
||||
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.
|
||||
func (cell *Cell) unregister(obj *Object) {
|
||||
|
||||
for i, o := range cell.Objects {
|
||||
|
||||
rb := cell.Objects
|
||||
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||
o := rb.GetByFrameId(i).(*Object)
|
||||
if o == obj {
|
||||
cell.Objects[i] = cell.Objects[len(cell.Objects)-1]
|
||||
cell.Objects = cell.Objects[:len(cell.Objects)-1]
|
||||
// swap with the st element
|
||||
rb.SetByFrameId(rb.GetByFrameId(rb.StFrameId), i)
|
||||
// pop the current st element
|
||||
rb.Pop()
|
||||
break
|
||||
}
|
||||
|
||||
@ -39,7 +41,9 @@ func (cell *Cell) unregister(obj *Object) {
|
||||
|
||||
// Contains returns whether a Cell contains the specified Object at its position.
|
||||
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 {
|
||||
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.
|
||||
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...) {
|
||||
return true
|
||||
}
|
||||
@ -59,5 +65,5 @@ func (cell *Cell) ContainsTags(tags ...string) bool {
|
||||
|
||||
// Occupied returns whether a Cell contains any Objects at all.
|
||||
func (cell *Cell) Occupied() bool {
|
||||
return len(cell.Objects) > 0
|
||||
return 0 < cell.Objects.Cnt
|
||||
}
|
||||
|
@ -3,23 +3,39 @@ package resolv
|
||||
// Collision contains the results of an Object.Check() call, and represents a collision between an Object and cells that contain other Objects.
|
||||
// The Objects array indicate the Objects collided with.
|
||||
type Collision struct {
|
||||
checkingObject *Object // The checking object
|
||||
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.
|
||||
Cells []*Cell // Slice of cells that were collided with; sorted according to distance to calling Object.
|
||||
checkingObject *Object // The checking object
|
||||
dx, dy float64 // The delta the checking object was moving on that caused this collision
|
||||
Objects *RingBuffer // Slice of objects 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 {
|
||||
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().
|
||||
func (cc *Collision) HasTags(tags ...string) bool {
|
||||
|
||||
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 {
|
||||
continue
|
||||
}
|
||||
@ -38,8 +54,9 @@ func (cc *Collision) ObjectsByTags(tags ...string) []*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 {
|
||||
continue
|
||||
}
|
||||
@ -105,7 +122,7 @@ func (cc *Collision) SlideAgainstCell(cell *Cell, avoidTags ...string) Vector {
|
||||
|
||||
sp := cc.checkingObject.Space
|
||||
|
||||
collidingCell := cc.Cells[0]
|
||||
collidingCell := cc.Cells.GetByFrameId(cc.Cells.StFrameId).(*Cell)
|
||||
ccX, ccY := sp.SpaceToWorld(collidingCell.X, collidingCell.Y)
|
||||
hX := float64(sp.CellWidth) / 2.0
|
||||
hY := float64(sp.CellHeight) / 2.0
|
||||
|
@ -2,7 +2,6 @@ package resolv
|
||||
|
||||
import (
|
||||
"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.
|
||||
@ -10,21 +9,36 @@ type Object struct {
|
||||
Shape Shape // A shape for more specific collision-checking.
|
||||
Space *Space // Reference to the Space the Object exists within
|
||||
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
|
||||
ignoreList map[*Object]bool // Set of Objects to ignore when checking for collisions
|
||||
tags []string // A list of tags the Object has
|
||||
}
|
||||
|
||||
// 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 {
|
||||
o := &Object{
|
||||
X: x,
|
||||
Y: y,
|
||||
W: w,
|
||||
H: h,
|
||||
tags: []string{},
|
||||
ignoreList: map[*Object]bool{},
|
||||
X: x,
|
||||
Y: y,
|
||||
W: w,
|
||||
H: h,
|
||||
TouchingCells: NewRingBuffer(512),
|
||||
tags: []string{},
|
||||
ignoreList: map[*Object]bool{},
|
||||
}
|
||||
|
||||
if len(tags) > 0 {
|
||||
@ -59,7 +73,7 @@ func (obj *Object) Update() {
|
||||
|
||||
space := obj.Space
|
||||
|
||||
obj.Space.Remove(obj)
|
||||
obj.Space.RemoveSingle(obj)
|
||||
|
||||
obj.Space = space
|
||||
|
||||
@ -73,7 +87,7 @@ func (obj *Object) Update() {
|
||||
|
||||
if c != nil {
|
||||
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.
|
||||
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) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SharesCellsTags returns if the Cells the Object occupies have an object with the specified tags.
|
||||
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...) {
|
||||
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
|
||||
// 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.
|
||||
func (obj *Object) Check(dx, dy float64, tags ...string) *Collision {
|
||||
func (obj *Object) CheckAllWithHolder(dx, dy float64, cc *Collision) bool {
|
||||
|
||||
if obj.Space == nil {
|
||||
return nil
|
||||
return false
|
||||
}
|
||||
|
||||
cc := NewCollision()
|
||||
cc.checkingObject = obj
|
||||
|
||||
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 {
|
||||
|
||||
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.
|
||||
if ignored := obj.ignoreList[o]; o == obj || ignored {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, added := objectsAdded[o]; (len(tags) == 0 || o.HasTags(tags...)) && !added {
|
||||
|
||||
cc.Objects = append(cc.Objects, o)
|
||||
if _, added := objectsAdded[o]; !added {
|
||||
cc.Objects.Put(o)
|
||||
objectsAdded[o] = true
|
||||
if _, added := cellsAdded[c]; !added {
|
||||
cc.Cells = append(cc.Cells, c)
|
||||
cc.Cells.Put(c)
|
||||
cellsAdded[c] = true
|
||||
}
|
||||
continue
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(cc.Objects) == 0 {
|
||||
return nil
|
||||
if 0 >= cc.Objects.Cnt {
|
||||
return false
|
||||
}
|
||||
|
||||
/*
|
||||
// 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
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Overlaps returns if an Object overlaps another Object.
|
||||
|
@ -1,4 +1,4 @@
|
||||
package battle
|
||||
package resolv
|
||||
|
||||
const (
|
||||
RING_BUFF_CONSECUTIVE_SET = int32(0)
|
||||
@ -18,11 +18,13 @@ type RingBuffer struct {
|
||||
|
||||
func NewRingBuffer(n int32) *RingBuffer {
|
||||
return &RingBuffer{
|
||||
Ed: 0,
|
||||
St: 0,
|
||||
N: n,
|
||||
Cnt: 0,
|
||||
Eles: make([]interface{}, n),
|
||||
Ed: 0,
|
||||
St: 0,
|
||||
EdFrameId: 0,
|
||||
StFrameId: 0,
|
||||
N: n,
|
||||
Cnt: 0,
|
||||
Eles: make([]interface{}, n),
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,3 +124,13 @@ func (rb *RingBuffer) SetByFrameId(pItem interface{}, frameId int32) (int32, int
|
||||
|
||||
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 {
|
||||
v := line.Vector()
|
||||
return Vector{v[1], -v[0]}.Unit()
|
||||
dy := line.End[1] - line.Start[1]
|
||||
dx := line.End[0] - line.Start[0]
|
||||
return Vector{dy, -dx}.Unit()
|
||||
}
|
||||
|
||||
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.
|
||||
func (cp *ConvexPolygon) Lines() []*Line {
|
||||
|
||||
lines := []*Line{}
|
||||
|
||||
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]
|
||||
|
||||
if i < len(vertices)-1 {
|
||||
end = vertices[i+1]
|
||||
} else if !cp.Closed {
|
||||
break
|
||||
}
|
||||
|
||||
line := NewLine(start[0], start[1], end[0], end[1])
|
||||
|
||||
lines = append(lines, line)
|
||||
|
||||
lines[i] = line
|
||||
}
|
||||
|
||||
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.
|
||||
func (cp *ConvexPolygon) Transformed() []Vector {
|
||||
transformed := []Vector{}
|
||||
for _, point := range cp.Points {
|
||||
transformed = append(transformed, Vector{point[0] + cp.X, point[1] + cp.Y})
|
||||
transformed := make([]Vector, len(cp.Points))
|
||||
for i, point := range cp.Points {
|
||||
transformed[i] = Vector{point[0] + cp.X, point[1] + cp.Y}
|
||||
}
|
||||
return transformed
|
||||
}
|
||||
@ -275,12 +272,14 @@ func (cp *ConvexPolygon) Center() Vector {
|
||||
|
||||
pos := Vector{0, 0}
|
||||
|
||||
for _, v := range cp.Transformed() {
|
||||
vertices := cp.Transformed()
|
||||
for _, v := range vertices {
|
||||
pos.Add(v)
|
||||
}
|
||||
|
||||
pos[0] /= float64(len(cp.Transformed()))
|
||||
pos[1] /= float64(len(cp.Transformed()))
|
||||
denom := float64(len(vertices))
|
||||
pos[0] /= denom
|
||||
pos[1] /= denom
|
||||
|
||||
return pos
|
||||
|
||||
@ -305,10 +304,10 @@ func (cp *ConvexPolygon) Project(axis Vector) Projection {
|
||||
|
||||
// SATAxes returns the axes of the ConvexPolygon for SAT intersection testing.
|
||||
func (cp *ConvexPolygon) SATAxes() []Vector {
|
||||
|
||||
axes := []Vector{}
|
||||
for _, line := range cp.Lines() {
|
||||
axes = append(axes, line.Normal())
|
||||
lines := cp.Lines()
|
||||
axes := make([]Vector, len(lines))
|
||||
for i, line := range lines {
|
||||
axes[i] = line.Normal()
|
||||
}
|
||||
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.
|
||||
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) {
|
||||
|
||||
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
|
||||
// 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) {
|
||||
|
||||
if sp == nil {
|
||||
@ -57,13 +84,11 @@ func (sp *Space) Remove(objects ...*Object) {
|
||||
}
|
||||
|
||||
for _, obj := range objects {
|
||||
|
||||
for _, cell := range obj.TouchingCells {
|
||||
for 0 < obj.TouchingCells.Cnt {
|
||||
cell := obj.TouchingCells.Pop().(*Cell)
|
||||
cell.unregister(obj)
|
||||
}
|
||||
|
||||
obj.TouchingCells = []*Cell{}
|
||||
|
||||
obj.Space = nil
|
||||
|
||||
}
|
||||
@ -80,16 +105,14 @@ func (sp *Space) Objects() []*Object {
|
||||
for cy := range sp.Cells {
|
||||
|
||||
for cx := range sp.Cells[cy] {
|
||||
|
||||
for _, o := range sp.Cells[cy][cx].Objects {
|
||||
|
||||
rb := sp.Cells[cy][cx].Objects
|
||||
for i := rb.StFrameId; i < rb.EdFrameId; i++ {
|
||||
o := rb.GetByFrameId(i).(*Object)
|
||||
if _, added := objectsAdded[o]; !added {
|
||||
objects = append(objects, o)
|
||||
objectsAdded[o] = true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -100,19 +123,13 @@ func (sp *Space) Objects() []*Object {
|
||||
|
||||
// Resize resizes the internal Cells array.
|
||||
func (sp *Space) Resize(width, height int) {
|
||||
|
||||
sp.Cells = [][]*Cell{}
|
||||
|
||||
sp.Cells = make([][]*Cell, height)
|
||||
for y := 0; y < height; y++ {
|
||||
|
||||
sp.Cells = append(sp.Cells, []*Cell{})
|
||||
|
||||
sp.Cells[y] = make([]*Cell, width)
|
||||
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
|
||||
@ -137,25 +154,23 @@ func (sp *Space) CheckCells(x, y, w, h int, tags ...string) *Object {
|
||||
cell := sp.Cell(ix, iy)
|
||||
|
||||
if cell != nil {
|
||||
|
||||
rb := cell.Objects
|
||||
if len(tags) > 0 {
|
||||
|
||||
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...) {
|
||||
return obj
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if cell.Occupied() {
|
||||
return cell.Objects[0]
|
||||
return rb.GetByFrameId(rb.StFrameId).(*Object)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -178,10 +193,13 @@ func (sp *Space) CheckCellsWorld(x, y, w, h float64, tags ...string) *Object {
|
||||
func (sp *Space) UnregisterAllObjects() {
|
||||
|
||||
for y := 0; y < len(sp.Cells); y++ {
|
||||
|
||||
for x := 0; x < len(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