Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
MingSnake_241120
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
SparkProjects
MingSnake_241120
Commits
29f47b46
Commit
29f47b46
authored
Nov 20, 2024
by
haiyoucuv
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
init
parent
b193474d
Changes
23
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
1611 additions
and
451 deletions
+1611
-451
MainGame.scene
assets/Bundles/MainGame/MainGame.scene
+303
-134
AISnake.prefab
assets/Bundles/MainGame/prefab/AISnake.prefab
+496
-0
AISnake.prefab.meta
assets/Bundles/MainGame/prefab/AISnake.prefab.meta
+13
-0
Animal.prefab
assets/Bundles/MainGame/prefab/Animal.prefab
+1
-1
body.prefab
assets/Bundles/MainGame/prefab/body.prefab
+1
-1
food.prefab
assets/Bundles/MainGame/prefab/food.prefab
+22
-22
AISnake.ts
assets/Scripts/Scenes/MainGame/AISnake.ts
+228
-0
AISnake.ts.meta
assets/Scripts/Scenes/MainGame/AISnake.ts.meta
+1
-1
Buff.meta
assets/Scripts/Scenes/MainGame/Buff.meta
+9
-0
BaseBuff.ts
assets/Scripts/Scenes/MainGame/Buff/BaseBuff.ts
+75
-0
BaseBuff.ts.meta
assets/Scripts/Scenes/MainGame/Buff/BaseBuff.ts.meta
+9
-0
BuffManager.ts
assets/Scripts/Scenes/MainGame/Buff/BuffManager.ts
+83
-0
BuffManager.ts.meta
assets/Scripts/Scenes/MainGame/Buff/BuffManager.ts.meta
+9
-0
BuffType.ts
assets/Scripts/Scenes/MainGame/Buff/BuffType.ts
+17
-0
BuffType.ts.meta
assets/Scripts/Scenes/MainGame/Buff/BuffType.ts.meta
+9
-0
Buffs.ts
assets/Scripts/Scenes/MainGame/Buff/Buffs.ts
+44
-0
Buffs.ts.meta
assets/Scripts/Scenes/MainGame/Buff/Buffs.ts.meta
+9
-0
FlagSystem.ts
assets/Scripts/Scenes/MainGame/FlagSystem.ts
+0
-81
FondManger.ts
assets/Scripts/Scenes/MainGame/FondManger.ts
+83
-69
MainGame.ts
assets/Scripts/Scenes/MainGame/MainGame.ts
+24
-96
Player.ts
assets/Scripts/Scenes/MainGame/Player.ts
+86
-0
Player.ts.meta
assets/Scripts/Scenes/MainGame/Player.ts.meta
+9
-0
Snake.ts
assets/Scripts/Scenes/MainGame/Snake.ts
+80
-46
No files found.
assets/Bundles/MainGame/MainGame.scene
View file @
29f47b46
...
...
@@ -26,7 +26,7 @@
"_active": true,
"_components": [],
"_prefab": {
"__id__": 6
1
"__id__": 6
5
},
"_lpos": {
"__type__": "cc.Vec3",
...
...
@@ -57,7 +57,7 @@
},
"autoReleaseAssets": false,
"_globals": {
"__id__": 6
2
"__id__": 6
9
},
"_id": "53947ca7-3484-4b53-800d-509405063d68"
},
...
...
@@ -89,16 +89,16 @@
"_active": true,
"_components": [
{
"__id__":
34
"__id__":
61
},
{
"__id__":
35
"__id__":
62
},
{
"__id__":
36
"__id__":
63
},
{
"__id__":
37
"__id__":
64
}
],
"_prefab": null,
...
...
@@ -948,7 +948,7 @@
},
{
"__type__": "cc.Node",
"_name": "
Snake
",
"_name": "
Player
",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
...
...
@@ -962,10 +962,10 @@
"_active": true,
"_components": [
{
"__id__": 3
2
"__id__": 3
6
},
{
"__id__": 3
3
"__id__": 3
7
}
],
"_prefab": null,
...
...
@@ -996,7 +996,7 @@
"y": 0,
"z": 0
},
"_id": "
ee8O/qSSVCI71mLCUiPZ14
"
"_id": "
8aQC0/qANLh6sa4pnah5ME
"
},
{
"__type__": "cc.Node",
...
...
@@ -1006,12 +1006,67 @@
"_parent": {
"__id__": 26
},
"_children": [],
"_children": [
{
"__id__": 28
}
],
"_active": true,
"_components": [
{
"__id__": 28
"__id__": 32
},
{
"__id__": 33
},
{
"__id__": 34
},
{
"__id__": 35
}
],
"_prefab": null,
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": "c71CjBcLpDGZbiUkJjXlQB"
},
{
"__type__": "cc.Node",
"_name": "范围",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 27
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 29
},
...
...
@@ -1050,7 +1105,81 @@
"y": 0,
"z": 0
},
"_id": "4bNFrHrqRFnLipvvtR3IxW"
"_id": "f6HRncHkdAyLMZ5F96R79v"
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 28
},
"_enabled": true,
"__prefab": null,
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": "1cP5Gc6eZC2rh545zjbGs2"
},
{
"__type__": "cc.RigidBody2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 28
},
"_enabled": true,
"__prefab": null,
"enabledContactListener": true,
"bullet": false,
"awakeOnLoad": true,
"_group": 2,
"_type": 1,
"_allowSleep": true,
"_gravityScale": 1,
"_linearDamping": 0,
"_angularDamping": 0,
"_linearVelocity": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_angularVelocity": 0,
"_fixedRotation": false,
"_id": "2eWaMwWa5P3be1EIHKykS3"
},
{
"__type__": "cc.CircleCollider2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 28
},
"_enabled": true,
"__prefab": null,
"tag": 0,
"_group": 2,
"_density": 1,
"_sensor": true,
"_friction": 0.2,
"_restitution": 0,
"_offset": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_radius": 100,
"_id": "9by37rfdJJYqBz5rmVuKgY"
},
{
"__type__": "cc.UITransform",
...
...
@@ -1072,7 +1201,7 @@
"x": 0.5,
"y": 0.5
},
"_id": "9
3szTjc/FGALN4nlwUdbOL
"
"_id": "9
4J0P8OvZCBaaRPtZvEaER
"
},
{
"__type__": "cc.Sprite",
...
...
@@ -1108,7 +1237,7 @@
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": "
611y7OvalMk6WKsBgpqsQe
"
"_id": "
1a9MwOnctHyZhKaI79NTjc
"
},
{
"__type__": "cc.RigidBody2D",
...
...
@@ -1124,7 +1253,7 @@
"bullet": false,
"awakeOnLoad": true,
"_group": 2,
"_type":
2
,
"_type":
1
,
"_allowSleep": true,
"_gravityScale": 1,
"_linearDamping": 0,
...
...
@@ -1136,7 +1265,7 @@
},
"_angularVelocity": 0,
"_fixedRotation": false,
"_id": "
ba/Z9k48lFjKggly+uiLPQ
"
"_id": "
97l7VKphhOLKHUoyq2j8wl
"
},
{
"__type__": "cc.CircleCollider2D",
...
...
@@ -1160,7 +1289,7 @@
"y": 0
},
"_radius": 50,
"_id": "
35XBcgL4hOhYpj8xmXzP8l
"
"_id": "
924VsngudKurMYw/x9IwfW
"
},
{
"__type__": "cc.UITransform",
...
...
@@ -1182,10 +1311,10 @@
"x": 0.5,
"y": 0.5
},
"_id": "
f4NXIEHRxHb42L3h6JeOws
"
"_id": "
dep3lTRQZHBKusQNwSgYav
"
},
{
"__type__": "
5c1d7QKgk1JsaoI0kPfkdM9
",
"__type__": "
3d364IehElNW4a6vUPQ4G1C
",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
...
...
@@ -1201,117 +1330,13 @@
"__uuid__": "8c4f22c7-20c7-4868-88ea-dedb8004999f",
"__expectedType__": "cc.Prefab"
},
"_id": "5fBUl8qiFBzbPmQ/o4D604"
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": null,
"_contentSize": {
"__type__": "cc.Size",
"width": 1624,
"height": 750
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": "bacPL97PpF2bL6DkBZU0aV"
},
{
"__type__": "cc.Canvas",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": null,
"_cameraComponent": {
"__id__": 4
},
"_alignCanvasWithScreen": true,
"_id": "62LdbkMj9H0aoMZiMqeOXB"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": null,
"_alignFlags": 45,
"_target": null,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 0,
"_originalHeight": 0,
"_alignMode": 2,
"_lockFlags": 0,
"_id": "4b4n24QAlBAJTbqsXR4lUh"
},
{
"__type__": "82c44Ork3tL+o56WmoE8TcQ",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": null,
"animalPrefab": {
"__uuid__": "37f1dd8d-17a4-406d-9382-91b0969cf75d",
"__expectedType__": "cc.Prefab"
},
"maxFood": 200,
"maxAnimal": 20,
"joystick": {
"__id__": 38
},
"fastBtn": {
"__id__": 46
},
"uiBg": {
"__id__": 18
},
"snake": {
"__id__": 33
},
"fondManger": {
"__id__": 22
},
"animalNode": {
"__id__": 24
},
"LTips": {
"__id__": 50
},
"camera": {
"__id__": 4
},
"_id": "212vDeP7dNBZXi0fJjPuCy"
"_id": "2dUcPvKs9AvZqQZfZoDIZT"
},
{
"__type__": "4552b9T1AJHJ4xMNlpYdqL/",
...
...
@@ -2134,39 +2159,183 @@
"_lockFlags": 0,
"_id": "35Jp/KTfNHbqtc+8xUyurH"
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": null,
"_contentSize": {
"__type__": "cc.Size",
"width": 1624,
"height": 750
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": "bacPL97PpF2bL6DkBZU0aV"
},
{
"__type__": "cc.Canvas",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": null,
"_cameraComponent": {
"__id__": 4
},
"_alignCanvasWithScreen": true,
"_id": "62LdbkMj9H0aoMZiMqeOXB"
},
{
"__type__": "cc.Widget",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": null,
"_alignFlags": 45,
"_target": null,
"_left": 0,
"_right": 0,
"_top": 0,
"_bottom": 0,
"_horizontalCenter": 0,
"_verticalCenter": 0,
"_isAbsLeft": true,
"_isAbsRight": true,
"_isAbsTop": true,
"_isAbsBottom": true,
"_isAbsHorizontalCenter": true,
"_isAbsVerticalCenter": true,
"_originalWidth": 0,
"_originalHeight": 0,
"_alignMode": 2,
"_lockFlags": 0,
"_id": "4b4n24QAlBAJTbqsXR4lUh"
},
{
"__type__": "82c44Ork3tL+o56WmoE8TcQ",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": null,
"animalPrefab": {
"__uuid__": "f7e4cff9-e50b-4028-b58e-f258871093ca",
"__expectedType__": "cc.Prefab"
},
"maxFood": 200,
"maxAnimal": 20,
"joystick": {
"__id__": 38
},
"fastBtn": {
"__id__": 46
},
"uiBg": {
"__id__": 18
},
"player": {
"__id__": 37
},
"fondManger": {
"__id__": 22
},
"animalNode": {
"__id__": 24
},
"LTips": {
"__id__": 50
},
"camera": {
"__id__": 4
},
"_id": "212vDeP7dNBZXi0fJjPuCy"
},
{
"__type__": "cc.PrefabInfo",
"root": null,
"asset": null,
"fileId": "53947ca7-3484-4b53-800d-509405063d68",
"instance": null,
"targetOverrides": []
"targetOverrides": [
{
"__id__": 66
}
]
},
{
"__type__": "cc.TargetOverrideInfo",
"source": {
"__id__": 26
},
"sourceInfo": {
"__id__": 67
},
"propertyPath": [
"head"
],
"target": {
"__id__": 26
},
"targetInfo": {
"__id__": 68
}
},
{
"__type__": "cc.TargetInfo",
"localID": [
"c35xsYWzJJs6m1l1Hndf6x"
]
},
{
"__type__": "cc.TargetInfo",
"localID": [
"99DwWvaTlMx7bgFz0iHbqY"
]
},
{
"__type__": "cc.SceneGlobals",
"ambient": {
"__id__":
63
"__id__":
70
},
"shadows": {
"__id__":
64
"__id__":
71
},
"_skybox": {
"__id__":
65
"__id__":
72
},
"fog": {
"__id__":
66
"__id__":
73
},
"octree": {
"__id__":
67
"__id__":
74
},
"skin": {
"__id__":
68
"__id__":
75
},
"lightProbeInfo": {
"__id__":
69
"__id__":
76
},
"postSettings": {
"__id__": 7
0
"__id__": 7
7
},
"bakedWithStationaryMainLight": false,
"bakedWithHighpLightmap": false
...
...
assets/Bundles/MainGame/prefab/AISnake.prefab
0 → 100644
View file @
29f47b46
[
{
"__type__": "cc.Prefab",
"_name": "AISnake",
"_objFlags": 0,
"__editorExtras__": {},
"_native": "",
"data": {
"__id__": 1
},
"optimizationPolicy": 0,
"persistent": false
},
{
"__type__": "cc.Node",
"_name": "AISnake",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": null,
"_children": [
{
"__id__": 2
}
],
"_active": true,
"_components": [
{
"__id__": 20
},
{
"__id__": 22
}
],
"_prefab": {
"__id__": 24
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "Head",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 1
},
"_children": [
{
"__id__": 3
}
],
"_active": true,
"_components": [
{
"__id__": 11
},
{
"__id__": 13
},
{
"__id__": 15
},
{
"__id__": 17
}
],
"_prefab": {
"__id__": 19
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.Node",
"_name": "范围",
"_objFlags": 0,
"__editorExtras__": {},
"_parent": {
"__id__": 2
},
"_children": [],
"_active": true,
"_components": [
{
"__id__": 4
},
{
"__id__": 6
},
{
"__id__": 8
}
],
"_prefab": {
"__id__": 10
},
"_lpos": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_lrot": {
"__type__": "cc.Quat",
"x": 0,
"y": 0,
"z": 0,
"w": 1
},
"_lscale": {
"__type__": "cc.Vec3",
"x": 1,
"y": 1,
"z": 1
},
"_mobility": 0,
"_layer": 1,
"_euler": {
"__type__": "cc.Vec3",
"x": 0,
"y": 0,
"z": 0
},
"_id": ""
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 3
},
"_enabled": true,
"__prefab": {
"__id__": 5
},
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "0fac9VpfVO24GEVbqN0rDr"
},
{
"__type__": "cc.RigidBody2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 3
},
"_enabled": true,
"__prefab": {
"__id__": 7
},
"enabledContactListener": true,
"bullet": false,
"awakeOnLoad": true,
"_group": 2,
"_type": 1,
"_allowSleep": true,
"_gravityScale": 1,
"_linearDamping": 0,
"_angularDamping": 0,
"_linearVelocity": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_angularVelocity": 0,
"_fixedRotation": false,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "06tgmn5lJOSrxGT9RzZ/yH"
},
{
"__type__": "cc.CircleCollider2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 3
},
"_enabled": true,
"__prefab": {
"__id__": 9
},
"tag": 0,
"_group": 2,
"_density": 1,
"_sensor": true,
"_friction": 0.2,
"_restitution": 0,
"_offset": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_radius": 100,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "01JFesoj9K0ZY+F0UNJzML"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "11XLaTdr5Np4aokfvlatgx",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": {
"__id__": 12
},
"_contentSize": {
"__type__": "cc.Size",
"width": 100,
"height": 100
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "5deDNWrJxPhZTvijInr7WK"
},
{
"__type__": "cc.Sprite",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": {
"__id__": 14
},
"_customMaterial": null,
"_srcBlendFactor": 2,
"_dstBlendFactor": 4,
"_color": {
"__type__": "cc.Color",
"r": 255,
"g": 255,
"b": 255,
"a": 255
},
"_spriteFrame": null,
"_type": 0,
"_fillType": 0,
"_sizeMode": 1,
"_fillCenter": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_fillStart": 0,
"_fillRange": 0,
"_isTrimmedMode": true,
"_useGrayscale": false,
"_atlas": null,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "a9l0+kQJxKPZS/WlExP1lc"
},
{
"__type__": "cc.RigidBody2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": {
"__id__": 16
},
"enabledContactListener": true,
"bullet": false,
"awakeOnLoad": true,
"_group": 2,
"_type": 1,
"_allowSleep": true,
"_gravityScale": 1,
"_linearDamping": 0,
"_angularDamping": 0,
"_linearVelocity": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_angularVelocity": 0,
"_fixedRotation": false,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "58PN+1WP9JUYhjArC/UslP"
},
{
"__type__": "cc.CircleCollider2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 2
},
"_enabled": true,
"__prefab": {
"__id__": 18
},
"tag": 0,
"_group": 2,
"_density": 1,
"_sensor": true,
"_friction": 0.2,
"_restitution": 0,
"_offset": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_radius": 50,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "bdxTN8nPZA/q7Zd4BUQkQm"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "99DwWvaTlMx7bgFz0iHbqY",
"instance": null,
"targetOverrides": null,
"nestedPrefabInstanceRoots": null
},
{
"__type__": "cc.UITransform",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 21
},
"_contentSize": {
"__type__": "cc.Size",
"width": 0,
"height": 0
},
"_anchorPoint": {
"__type__": "cc.Vec2",
"x": 0.5,
"y": 0.5
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "a7ATZENxxM9opDu0hsckS7"
},
{
"__type__": "9a4204/Rl9HW5pomKW0LWdO",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
"node": {
"__id__": 1
},
"_enabled": true,
"__prefab": {
"__id__": 23
},
"head": {
"__id__": 2
},
"bodyPrefab": {
"__uuid__": "8c4f22c7-20c7-4868-88ea-dedb8004999f",
"__expectedType__": "cc.Prefab"
},
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "85va8m2SpDPq8Fj2dbJkmE"
},
{
"__type__": "cc.PrefabInfo",
"root": {
"__id__": 1
},
"asset": {
"__id__": 0
},
"fileId": "ee8O/qSSVCI71mLCUiPZ14",
"instance": null,
"targetOverrides": null
}
]
\ No newline at end of file
assets/Bundles/MainGame/prefab/AISnake.prefab.meta
0 → 100644
View file @
29f47b46
{
"ver": "1.1.50",
"importer": "prefab",
"imported": true,
"uuid": "f7e4cff9-e50b-4028-b58e-f258871093ca",
"files": [
".json"
],
"subMetas": {},
"userData": {
"syncNodeName": "AISnake"
}
}
assets/Bundles/MainGame/prefab/Animal.prefab
View file @
29f47b46
...
...
@@ -205,7 +205,7 @@
"bullet": false,
"awakeOnLoad": true,
"_group": 8,
"_type":
2
,
"_type":
1
,
"_allowSleep": true,
"_gravityScale": 1,
"_linearDamping": 0,
...
...
assets/Bundles/MainGame/prefab/body.prefab
View file @
29f47b46
...
...
@@ -151,7 +151,7 @@
"bullet": false,
"awakeOnLoad": true,
"_group": 16,
"_type":
2
,
"_type":
1
,
"_allowSleep": true,
"_gravityScale": 1,
"_linearDamping": 0,
...
...
assets/Bundles/MainGame/prefab/food.prefab
View file @
29f47b46
...
...
@@ -136,7 +136,7 @@
"fileId": "00ZbcQtopI2JWAiMHxJkn+"
},
{
"__type__": "cc.
CircleCollider
2D",
"__type__": "cc.
RigidBody
2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
...
...
@@ -147,26 +147,30 @@
"__prefab": {
"__id__": 7
},
"tag": 0,
"enabledContactListener": true,
"bullet": false,
"awakeOnLoad": true,
"_group": 4,
"_density": 1,
"_sensor": true,
"_friction": 0.2,
"_restitution": 0,
"_offset": {
"_type": 1,
"_allowSleep": true,
"_gravityScale": 1,
"_linearDamping": 0,
"_angularDamping": 0,
"_linearVelocity": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_radius": 15,
"_angularVelocity": 0,
"_fixedRotation": false,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "
bbd/hzdzVJ1rG0lXtNgF7s
"
"fileId": "
2d/O9bV5VIyqWQb88vJlpL
"
},
{
"__type__": "cc.
RigidBody
2D",
"__type__": "cc.
CircleCollider
2D",
"_name": "",
"_objFlags": 0,
"__editorExtras__": {},
...
...
@@ -177,27 +181,23 @@
"__prefab": {
"__id__": 9
},
"enabledContactListener": true,
"bullet": false,
"awakeOnLoad": true,
"tag": 0,
"_group": 4,
"_type": 2,
"_allowSleep": true,
"_gravityScale": 1,
"_linearDamping": 0,
"_angularDamping": 0,
"_linearVelocity": {
"_density": 1,
"_sensor": true,
"_friction": 0.2,
"_restitution": 0,
"_offset": {
"__type__": "cc.Vec2",
"x": 0,
"y": 0
},
"_angularVelocity": 0,
"_fixedRotation": false,
"_radius": 15,
"_id": ""
},
{
"__type__": "cc.CompPrefabInfo",
"fileId": "
2d/O9bV5VIyqWQb88vJlpL
"
"fileId": "
bbd/hzdzVJ1rG0lXtNgF7s
"
},
{
"__type__": "cc.PrefabInfo",
...
...
assets/Scripts/Scenes/MainGame/AISnake.ts
0 → 100644
View file @
29f47b46
import
{
_decorator
,
math
,
v3
,
Vec3
}
from
"cc"
;
import
{
Snake
}
from
"./Snake"
;
import
{
DirectionType
}
from
"./Enums"
;
import
{
Global
}
from
"./Global"
;
import
{
MainGame
}
from
"./MainGame"
;
const
{
ccclass
,
property
}
=
_decorator
;
@
ccclass
(
"AISnake"
)
export
class
AISnake
extends
Snake
{
// AI难度等级
@
property
({
range
:
[
1
,
5
],
tooltip
:
"AI难度(1-5)"
})
private
difficulty
:
number
=
5
;
private
v
=
v3
();
private
direction
:
DirectionType
=
DirectionType
.
DEFAULT
;
private
directionSpeed
:
number
=
0
;
// AI行为相关参数
private
readonly
VIEW_DISTANCE
:
number
=
300
;
// 视野范围
private
readonly
AVOID_DISTANCE
:
number
=
100
;
// 躲避距离
private
targetFood
:
Vec3
=
null
;
private
dangerSnake
:
Snake
=
null
;
private
behaviorTimer
:
number
=
0
;
private
readonly
BEHAVIOR_UPDATE_TIME
=
0.5
;
// 行为更新间隔
// 难度相关参数
private
get
difficultyParams
()
{
return
{
reactionTime
:
math
.
lerp
(
0.8
,
0.2
,
(
this
.
difficulty
-
1
)
/
4
),
viewDistance
:
math
.
lerp
(
200
,
400
,
(
this
.
difficulty
-
1
)
/
4
),
decisionAccuracy
:
math
.
lerp
(
0.4
,
0.9
,
(
this
.
difficulty
-
1
)
/
4
),
aggressiveness
:
math
.
lerp
(
0.2
,
0.8
,
(
this
.
difficulty
-
1
)
/
4
)
};
}
onUpdate
(
dt
:
number
)
{
if
(
!
this
.
isLife
)
return
;
this
.
behaviorTimer
+=
dt
;
if
(
this
.
behaviorTimer
>=
this
.
difficultyParams
.
reactionTime
)
{
this
.
behaviorTimer
=
0
;
this
.
updateAIBehavior
();
}
// 预判断位置
this
.
v
=
this
.
getNewPos
(
this
.
head
.
angle
,
dt
,
this
.
head
.
getPosition
(),
this
.
speed
*
20
);
this
.
handleBoundaryAvoidance
();
this
.
executeCurrentBehavior
(
dt
);
super
.
onUpdate
(
dt
);
}
private
updateAIBehavior
()
{
const
params
=
this
.
difficultyParams
;
// 检测危险
this
.
detectThreats
();
// 如果检测到危险,优先躲避
if
(
this
.
dangerSnake
&&
math
.
random
()
<
params
.
decisionAccuracy
)
{
this
.
avoidThreat
();
return
;
}
// 寻找最近的食物
this
.
findNearestFood
();
// 根据难度决定是否追逐食物
if
(
this
.
targetFood
&&
math
.
random
()
<
params
.
decisionAccuracy
)
{
this
.
chaseFood
();
}
else
{
this
.
randomMove
();
}
// 根据难度决定是否加速
if
(
this
.
shouldSpeedUp
())
{
this
.
isFast
=
true
;
}
else
{
this
.
isFast
=
false
;
}
}
private
detectThreats
()
{
const
params
=
this
.
difficultyParams
;
const
myPos
=
this
.
head
.
getPosition
();
let
nearestDanger
=
null
;
let
minDistance
=
params
.
viewDistance
;
// 检测其他蛇
const
allSnakes
=
[...
MainGame
.
ins
.
animalNode
.
children
];
allSnakes
.
push
(
MainGame
.
ins
.
player
.
node
);
for
(
const
snakeNode
of
allSnakes
)
{
const
snake
=
snakeNode
.
getComponent
(
Snake
);
if
(
snake
===
this
)
continue
;
const
distance
=
Vec3
.
distance
(
myPos
,
snake
.
head
.
getPosition
());
if
(
distance
<
minDistance
&&
snake
.
getSnakeLen
()
>=
this
.
getSnakeLen
())
{
minDistance
=
distance
;
nearestDanger
=
snake
;
}
}
this
.
dangerSnake
=
nearestDanger
;
}
private
findNearestFood
()
{
const
params
=
this
.
difficultyParams
;
const
myPos
=
this
.
head
.
getPosition
();
let
nearestFood
=
null
;
let
minDistance
=
params
.
viewDistance
;
// 获取视野范围内的食物
MainGame
.
ins
.
fondManger
.
node
.
children
.
forEach
(
food
=>
{
const
distance
=
Vec3
.
distance
(
myPos
,
food
.
getPosition
());
if
(
distance
<
minDistance
)
{
minDistance
=
distance
;
nearestFood
=
food
.
getPosition
();
}
});
this
.
targetFood
=
nearestFood
;
}
private
avoidThreat
()
{
const
myPos
=
this
.
head
.
getPosition
();
const
dangerPos
=
this
.
dangerSnake
.
head
.
getPosition
();
// 计算逃离角度
const
angle
=
math
.
toDegree
(
Math
.
atan2
(
myPos
.
y
-
dangerPos
.
y
,
myPos
.
x
-
dangerPos
.
x
));
this
.
head
.
angle
=
angle
;
this
.
isFast
=
true
;
}
private
chaseFood
()
{
const
myPos
=
this
.
head
.
getPosition
();
// 计算追逐角度
const
angle
=
math
.
toDegree
(
Math
.
atan2
(
this
.
targetFood
.
y
-
myPos
.
y
,
this
.
targetFood
.
x
-
myPos
.
x
));
// 平滑转向
const
angleDiff
=
this
.
head
.
angle
-
angle
;
this
.
head
.
angle
+=
math
.
clamp
(
angleDiff
,
-
3
,
3
);
}
private
handleBoundaryAvoidance
()
{
const
halfWidth
=
Global
.
MAP_WIDTH
/
2
;
const
halfHeight
=
Global
.
MAP_HIGHT
/
2
;
if
(
this
.
v
.
x
<=
-
halfWidth
||
this
.
v
.
x
>=
halfWidth
||
this
.
v
.
y
<=
-
halfHeight
||
this
.
v
.
y
>=
halfHeight
)
{
const
angleAbs
=
Math
.
abs
(
this
.
head
.
angle
%
180
);
this
.
direction
=
DirectionType
.
DEFAULT
;
// 根据难度调整转向的精确度
const
turnAngle
=
math
.
lerp
(
math
.
randomRangeInt
(
90
,
180
),
135
,
this
.
difficultyParams
.
decisionAccuracy
);
if
(
angleAbs
>
90
)
{
this
.
head
.
angle
+=
turnAngle
;
}
else
{
this
.
head
.
angle
-=
turnAngle
;
}
}
}
private
randomMove
()
{
if
(
math
.
randomRangeInt
(
0
,
11
)
==
0
)
{
this
.
direction
=
math
.
randomRangeInt
(
0
,
3
);
this
.
directionSpeed
=
math
.
randomRangeInt
(
0
,
6
);
}
if
(
this
.
direction
==
DirectionType
.
LEFT
)
{
this
.
head
.
angle
+=
this
.
directionSpeed
;
}
else
if
(
this
.
direction
==
DirectionType
.
RIGHT
)
{
this
.
head
.
angle
-=
this
.
directionSpeed
;
}
}
private
shouldSpeedUp
():
boolean
{
const
params
=
this
.
difficultyParams
;
// 在以下情况下加速:
// 1. 追逐食物且距离适中
// 2. 逃离危险
// 3. 随机因素(基于激进度)
if
(
this
.
dangerSnake
)
return
true
;
if
(
this
.
targetFood
)
{
const
distance
=
Vec3
.
distance
(
this
.
head
.
getPosition
(),
this
.
targetFood
);
if
(
distance
<
this
.
VIEW_DISTANCE
/
2
)
return
true
;
}
return
math
.
random
()
<
params
.
aggressiveness
;
}
private
executeCurrentBehavior
(
dt
:
number
)
{
// 可以在这里添加更多行为逻辑
// 比如:追逐较小的蛇、与同类保持距离等
}
// 设置AI难度
setDifficulty
(
level
:
number
)
{
this
.
difficulty
=
math
.
clamp
(
level
,
1
,
5
);
}
}
\ No newline at end of file
assets/Scripts/Scenes/MainGame/
FlagSystem
.ts.meta
→
assets/Scripts/Scenes/MainGame/
AISnake
.ts.meta
View file @
29f47b46
...
...
@@ -2,7 +2,7 @@
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "
c9d3c00d-0519-4dc0-9e9f-103327cfcc08
",
"uuid": "
9a420e3f-465f-475b-9a68-98a5b42d674e
",
"files": [],
"subMetas": {},
"userData": {}
...
...
assets/Scripts/Scenes/MainGame/Buff.meta
0 → 100644
View file @
29f47b46
{
"ver": "1.2.0",
"importer": "directory",
"imported": true,
"uuid": "4fa63f7f-07d2-4949-b7aa-3f9827a3e8ce",
"files": [],
"subMetas": {},
"userData": {}
}
assets/Scripts/Scenes/MainGame/Buff/BaseBuff.ts
0 → 100644
View file @
29f47b46
import
{
_decorator
}
from
"cc"
;
import
{
BuffType
,
BuffState
}
from
"./BuffType"
;
import
{
Snake
}
from
"../Snake"
;
const
{
ccclass
,
property
}
=
_decorator
;
@
ccclass
(
"BaseBuff"
)
export
class
BaseBuff
{
protected
type
:
BuffType
=
BuffType
.
NONE
;
protected
duration
:
number
=
0
;
protected
remainTime
:
number
=
0
;
protected
value
:
number
=
0
;
protected
state
:
BuffState
=
BuffState
.
INACTIVE
;
protected
target
:
Snake
=
null
;
constructor
(
type
:
BuffType
,
duration
:
number
,
value
:
number
)
{
this
.
type
=
type
;
this
.
duration
=
duration
;
this
.
remainTime
=
duration
;
this
.
value
=
value
;
}
// 激活Buff
activate
(
target
:
Snake
):
void
{
this
.
target
=
target
;
this
.
state
=
BuffState
.
ACTIVE
;
this
.
onActivate
();
}
// 更新Buff状态
update
(
dt
:
number
):
boolean
{
if
(
this
.
state
!==
BuffState
.
ACTIVE
)
return
false
;
this
.
remainTime
-=
dt
;
this
.
onUpdate
(
dt
);
if
(
this
.
remainTime
<=
0
)
{
this
.
deactivate
();
return
false
;
}
return
true
;
}
// 停用Buff
deactivate
():
void
{
this
.
state
=
BuffState
.
FINISHED
;
this
.
onDeactivate
();
}
// 获取剩余时间
getRemainTime
():
number
{
return
Math
.
max
(
0
,
this
.
remainTime
);
}
// 获取Buff类型
getType
():
BuffType
{
return
this
.
type
;
}
// 获取Buff状态
getState
():
BuffState
{
return
this
.
state
;
}
// 获取Buff值
getValue
():
number
{
return
this
.
value
;
}
// 以下是子类需要实现的方法
protected
onActivate
():
void
{
}
protected
onUpdate
(
dt
:
number
):
void
{
}
protected
onDeactivate
():
void
{
}
}
\ No newline at end of file
assets/Scripts/Scenes/MainGame/Buff/BaseBuff.ts.meta
0 → 100644
View file @
29f47b46
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "448e8ec0-47bb-488e-b80b-e52e93c7136f",
"files": [],
"subMetas": {},
"userData": {}
}
assets/Scripts/Scenes/MainGame/Buff/BuffManager.ts
0 → 100644
View file @
29f47b46
import
{
_decorator
}
from
"cc"
;
import
{
BaseBuff
}
from
"./BaseBuff"
;
import
{
BuffType
}
from
"./BuffType"
;
import
{
Snake
}
from
"../Snake"
;
import
{
ShieldBuff
,
SpeedUpBuff
,
MagnetBuff
}
from
"./Buffs"
;
const
{
ccclass
}
=
_decorator
;
@
ccclass
(
"BuffManager"
)
export
class
BuffManager
{
private
buffs
:
Map
<
BuffType
,
BaseBuff
>
=
new
Map
();
private
target
:
Snake
=
null
;
constructor
(
target
:
Snake
)
{
this
.
target
=
target
;
}
// 添加Buff
addBuff
(
buff
:
BaseBuff
):
void
{
const
type
=
buff
.
getType
();
// 如果已存在同类型Buff,先移除
if
(
this
.
buffs
.
has
(
type
))
{
this
.
removeBuff
(
type
);
}
this
.
buffs
.
set
(
type
,
buff
);
buff
.
activate
(
this
.
target
);
}
// 移除指定类型的Buff
removeBuff
(
type
:
BuffType
):
void
{
const
buff
=
this
.
buffs
.
get
(
type
);
if
(
buff
)
{
buff
.
deactivate
();
this
.
buffs
.
delete
(
type
);
}
}
// 更新所有Buff
update
(
dt
:
number
):
void
{
this
.
buffs
.
forEach
((
buff
,
type
)
=>
{
if
(
!
buff
.
update
(
dt
))
{
this
.
buffs
.
delete
(
type
);
}
});
}
// 检查是否有某个Buff
hasBuff
(
type
:
BuffType
):
boolean
{
return
this
.
buffs
.
has
(
type
);
}
// 获取Buff
getBuff
(
type
:
BuffType
):
BaseBuff
|
null
{
return
this
.
buffs
.
get
(
type
)
||
null
;
}
// 清除所有Buff
clearAll
():
void
{
this
.
buffs
.
forEach
(
buff
=>
buff
.
deactivate
());
this
.
buffs
.
clear
();
}
// 获取所有激活的Buff
getActiveBuffs
():
BaseBuff
[]
{
return
Array
.
from
(
this
.
buffs
.
values
());
}
// 创建Buff的便捷方法
createBuff
(
type
:
BuffType
,
duration
?:
number
,
value
?:
number
):
BaseBuff
{
switch
(
type
)
{
case
BuffType
.
SHIELD
:
return
new
ShieldBuff
(
duration
);
case
BuffType
.
SPEED_UP
:
return
new
SpeedUpBuff
(
duration
,
value
);
case
BuffType
.
MAGNET
:
return
new
MagnetBuff
(
duration
,
value
);
default
:
return
null
;
}
}
}
\ No newline at end of file
assets/Scripts/Scenes/MainGame/Buff/BuffManager.ts.meta
0 → 100644
View file @
29f47b46
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "1224d146-f247-4925-ba1c-eb35147e5b8f",
"files": [],
"subMetas": {},
"userData": {}
}
assets/Scripts/Scenes/MainGame/Buff/BuffType.ts
0 → 100644
View file @
29f47b46
export
enum
BuffType
{
NONE
=
0
,
SHIELD
=
1
,
// 护盾
MAGNET
=
2
,
// 磁铁
SPEED_UP
=
3
,
// 加速
DOUBLE_SCORE
=
4
,
// 双倍积分
INVINCIBLE
=
5
,
// 无敌
FROZEN
=
6
,
// 冰冻
// ... 可以继续添加更多类型
}
// Buff的一些通用状态
export
enum
BuffState
{
INACTIVE
=
0
,
// 未激活
ACTIVE
=
1
,
// 激活中
FINISHED
=
2
// 已结束
}
\ No newline at end of file
assets/Scripts/Scenes/MainGame/Buff/BuffType.ts.meta
0 → 100644
View file @
29f47b46
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "de21d110-11a6-4935-a4b4-1898a9fe6101",
"files": [],
"subMetas": {},
"userData": {}
}
assets/Scripts/Scenes/MainGame/Buff/Buffs.ts
0 → 100644
View file @
29f47b46
import
{
BaseBuff
}
from
"./BaseBuff"
;
import
{
BuffType
}
from
"./BuffType"
;
// 护盾Buff
export
class
ShieldBuff
extends
BaseBuff
{
constructor
(
duration
:
number
=
10
)
{
super
(
BuffType
.
SHIELD
,
duration
,
1
);
}
protected
onActivate
():
void
{
this
.
target
.
setInvincible
(
true
);
}
protected
onDeactivate
():
void
{
this
.
target
.
setInvincible
(
false
);
}
}
// 加速Buff
export
class
SpeedUpBuff
extends
BaseBuff
{
constructor
(
duration
:
number
=
8
,
accPercent
:
number
=
1.5
)
{
super
(
BuffType
.
SPEED_UP
,
duration
,
accPercent
);
}
protected
onActivate
():
void
{
this
.
target
.
setSpeedMultiplier
(
this
.
value
);
}
protected
onDeactivate
():
void
{
this
.
target
.
setSpeedMultiplier
(
1
);
}
}
// 磁铁Buff
export
class
MagnetBuff
extends
BaseBuff
{
constructor
(
duration
:
number
=
15
,
range
:
number
=
100
)
{
super
(
BuffType
.
MAGNET
,
duration
,
range
);
}
protected
onUpdate
(
dt
:
number
):
void
{
// 在这里实现磁铁效果的逻辑
// 例如:吸引范围内的食物
}
}
\ No newline at end of file
assets/Scripts/Scenes/MainGame/Buff/Buffs.ts.meta
0 → 100644
View file @
29f47b46
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "aa216ae1-29cc-4cdc-bb17-86f9e1701160",
"files": [],
"subMetas": {},
"userData": {}
}
assets/Scripts/Scenes/MainGame/FlagSystem.ts
deleted
100644 → 0
View file @
b193474d
import
{
_decorator
}
from
"cc"
;
import
{
FlagType
}
from
"./Enums"
;
const
{
ccclass
}
=
_decorator
;
interface
FlagInfo
{
type
:
FlagType
;
duration
:
number
;
// 持续时间
remainTime
:
number
;
// 剩余时间
value
:
number
;
// 效果值
}
@
ccclass
(
"FlagSystem"
)
export
class
FlagSystem
{
private
flags
:
Map
<
FlagType
,
FlagInfo
>
=
new
Map
();
// Flag 默认配置
private
static
readonly
DEFAULT_CONFIG
:
{
[
key
in
FlagType
]?:
{
duration
:
number
,
value
:
number
}
}
=
{
[
FlagType
.
SHIELD
]:
{
duration
:
10
,
value
:
1
},
// 护盾10秒
[
FlagType
.
MAGNET
]:
{
duration
:
15
,
value
:
100
},
// 磁铁15秒,吸收范围100
[
FlagType
.
SPEED_UP
]:
{
duration
:
8
,
value
:
1.5
},
// 加速8秒,速度1.5倍
[
FlagType
.
DOUBLE_SCORE
]:
{
duration
:
12
,
value
:
2
},
// 双倍积分12秒
};
// 添加一个Flag
addFlag
(
type
:
FlagType
,
duration
?:
number
,
value
?:
number
)
{
const
config
=
FlagSystem
.
DEFAULT_CONFIG
[
type
];
if
(
!
config
)
return
;
const
flagInfo
:
FlagInfo
=
{
type
,
duration
:
duration
||
config
.
duration
,
remainTime
:
duration
||
config
.
duration
,
value
:
value
||
config
.
value
};
this
.
flags
.
set
(
type
,
flagInfo
);
}
// 移除一个Flag
removeFlag
(
type
:
FlagType
)
{
this
.
flags
.
delete
(
type
);
}
// 检查Flag是否存在且有效
hasFlag
(
type
:
FlagType
):
boolean
{
return
this
.
flags
.
has
(
type
)
&&
this
.
flags
.
get
(
type
).
remainTime
>
0
;
}
// 获取Flag的值
getFlagValue
(
type
:
FlagType
):
number
{
const
flag
=
this
.
flags
.
get
(
type
);
return
flag
&&
flag
.
remainTime
>
0
?
flag
.
value
:
0
;
}
// 获取Flag的剩余时间
getFlagRemainTime
(
type
:
FlagType
):
number
{
const
flag
=
this
.
flags
.
get
(
type
);
return
flag
?
flag
.
remainTime
:
0
;
}
// 更新所有Flag状态
update
(
dt
:
number
)
{
this
.
flags
.
forEach
((
flag
,
type
)
=>
{
flag
.
remainTime
-=
dt
;
if
(
flag
.
remainTime
<=
0
)
{
this
.
flags
.
delete
(
type
);
}
});
}
// 清除所有Flag
clearAll
()
{
this
.
flags
.
clear
();
}
// 获取所有活动的Flag
getActiveFlags
():
FlagInfo
[]
{
return
Array
.
from
(
this
.
flags
.
values
()).
filter
(
flag
=>
flag
.
remainTime
>
0
);
}
}
\ No newline at end of file
assets/Scripts/Scenes/MainGame/FondManger.ts
View file @
29f47b46
...
...
@@ -2,7 +2,6 @@ import { _decorator, Enum, SpriteFrame, math, v3, Sprite, Collider2D, Component,
import
{
PoolManager
}
from
"./PoolManager"
;
import
{
FoodType
}
from
"./Enums"
;
import
{
Global
}
from
"./Global"
;
import
{
MainGame
}
from
"./MainGame"
;
import
{
executePreFrame
,
getItemGenerator
}
from
"../../Utils/ExecutePreFrame"
;
const
{
ccclass
,
property
}
=
_decorator
;
...
...
@@ -31,6 +30,8 @@ export class FondManger extends Component {
@
property
(
Prefab
)
private
foodPrefab
:
Prefab
=
null
;
maxFood
:
number
=
100
;
/**
* 获取当前食物数量
*/
...
...
@@ -41,8 +42,21 @@ export class FondManger extends Component {
/**
* 初始化食物
*/
async
init
(
count
:
number
=
100
)
{
await
this
.
initFond
(
count
);
async
init
(
maxFood
:
number
=
100
)
{
this
.
maxFood
=
maxFood
;
await
this
.
initFond
(
maxFood
);
this
.
schedule
(
this
.
checkFood
,
1
);
}
/**
* 检查食物
*/
checkFood
()
{
for
(
let
i
=
this
.
getFoodSum
();
i
<
this
.
maxFood
;
i
++
)
{
this
.
addFood
();
}
}
/**
...
...
@@ -90,7 +104,7 @@ export class FondManger extends Component {
const
y
=
math
.
randomRangeInt
(
-
(
Global
.
MAP_HIGHT
/
2
-
50
),
Global
.
MAP_HIGHT
/
2
-
50
);
this
.
addFood
(
x
,
y
);
}
};
/**
* 初始化食物
...
...
assets/Scripts/Scenes/MainGame/MainGame.ts
View file @
29f47b46
...
...
@@ -2,10 +2,6 @@ import {
_decorator
,
Camera
,
director
,
EventKeyboard
,
input
,
Input
,
KeyCode
,
Label
,
math
,
Node
,
...
...
@@ -14,17 +10,18 @@ import {
UITransform
,
}
from
"cc"
;
import
{
Joystick
}
from
"./Joystick"
;
import
{
Snake
}
from
"./Snake"
;
import
{
FastBtn
}
from
"./FastBtn"
;
import
{
Animal
}
from
"./Animal"
;
import
{
FondManger
}
from
"./FondManger"
;
import
{
Config
}
from
"./Config"
;
import
{
Global
}
from
"./Global"
;
import
{
E
BodyTag
,
E
vents
,
GameState
}
from
"./Enums"
;
import
{
Events
,
GameState
}
from
"./Enums"
;
import
{
PoolManager
}
from
"./PoolManager"
;
import
{
showToast
}
from
"../../../Module/UIFast"
;
import
Scene
from
"../../../Module/Scene"
;
import
{
executePreFrame
,
getItemGenerator
}
from
"../../Utils/ExecutePreFrame"
;
import
{
Player
}
from
"./Player"
;
import
{
AISnake
}
from
"./AISnake"
;
const
{
ccclass
,
property
}
=
_decorator
;
...
...
@@ -61,14 +58,14 @@ export class MainGame extends Scene {
@
property
(
UITransform
)
private
uiBg
:
UITransform
=
null
;
@
property
(
Snake
)
p
rivate
snake
:
Snake
=
null
;
@
property
(
Player
)
p
layer
:
Player
=
null
;
@
property
(
FondManger
)
fondManger
:
FondManger
=
null
;
@
property
(
Node
)
private
animalNode
:
Node
=
null
;
animalNode
:
Node
=
null
;
@
property
(
Label
)
private
LTips
:
Label
=
null
;
...
...
@@ -90,6 +87,12 @@ export class MainGame extends Scene {
MainGame
.
_ins
=
this
;
PhysicsSystem2D
.
instance
.
enable
=
true
;
// PhysicsSystem2D.instance.gravity = math.Vec2.ZERO;
// PhysicsSystem2D.instance.debugDrawFlags = EPhysics2DDrawFlags.Aabb |
// EPhysics2DDrawFlags.Pair |
// EPhysics2DDrawFlags.CenterOfMass |
// EPhysics2DDrawFlags.Joint |
// EPhysics2DDrawFlags.Shape;
Global
.
MAP_WIDTH
=
this
.
uiBg
.
contentSize
.
x
;
Global
.
MAP_HIGHT
=
this
.
uiBg
.
contentSize
.
y
;
...
...
@@ -111,7 +114,7 @@ export class MainGame extends Scene {
wallRight
.
setPosition
(
Global
.
MAP_WIDTH
/
2
,
0
);
wallRight
.
getComponent
(
UITransform
).
height
=
Global
.
MAP_HIGHT
;
this
.
snake
.
init
();
this
.
player
.
init
();
// 初始化食物和NPC
this
.
fondManger
.
init
(
this
.
maxFood
);
...
...
@@ -123,86 +126,29 @@ export class MainGame extends Scene {
// 注册事件
director
.
on
(
Events
.
showGOver
,
this
.
showGOver
,
this
);
director
.
on
(
Events
.
setGameState
,
this
.
setGameState
,
this
);
// 仅在调试模式下添加键盘控制
if
(
this
.
DEBUG
)
{
input
.
on
(
Input
.
EventType
.
KEY_DOWN
,
this
.
onKeyDown
,
this
);
input
.
on
(
Input
.
EventType
.
KEY_UP
,
this
.
onKeyUp
,
this
);
}
}
onDestroy
()
{
MainGame
.
_ins
=
null
;
// 仅在调试模式下移除键盘事件监听
if
(
this
.
DEBUG
)
{
input
.
off
(
Input
.
EventType
.
KEY_DOWN
,
this
.
onKeyDown
,
this
);
input
.
off
(
Input
.
EventType
.
KEY_UP
,
this
.
onKeyUp
,
this
);
}
}
keyArr
:
number
[]
=
[];
onKeyDown
(
event
:
EventKeyboard
)
{
const
keyArr
=
[
KeyCode
.
KEY_W
,
KeyCode
.
KEY_S
,
KeyCode
.
KEY_A
,
KeyCode
.
KEY_D
,];
if
(
keyArr
.
indexOf
(
event
.
keyCode
)
>
-
1
)
{
this
.
keyArr
.
push
(
event
.
keyCode
);
}
if
(
event
.
keyCode
==
KeyCode
.
SPACE
)
{
this
.
fastBtn
.
isFast
=
true
;
}
this
.
setDir
();
}
onKeyUp
(
event
:
EventKeyboard
)
{
const
index
=
this
.
keyArr
.
indexOf
(
event
.
keyCode
);
if
(
index
>
-
1
)
{
this
.
keyArr
.
splice
(
index
,
1
);
}
if
(
event
.
keyCode
==
KeyCode
.
SPACE
)
{
this
.
fastBtn
.
isFast
=
false
;
}
this
.
setDir
();
}
setDir
()
{
if
(
!
this
.
keyArr
.
length
)
return
;
this
.
joystick
.
angle
=
{
[
KeyCode
.
KEY_W
]:
270
,
[
KeyCode
.
KEY_S
]:
90
,
[
KeyCode
.
KEY_A
]:
180
,
[
KeyCode
.
KEY_D
]:
0
,
}[
this
.
keyArr
[
this
.
keyArr
.
length
-
1
]];
}
update
(
dt
:
number
)
{
if
(
this
.
state
==
GameState
.
READY
)
return
;
// 更新UI提示
this
.
LTips
.
string
=
`长度:
${
this
.
snake
.
getSnakeLen
()}
}`
;
this
.
LTips
.
string
=
`长度:
${
this
.
player
.
getSnakeLen
()}
}`
;
this
.
snake
.
setAngle
((
360
-
this
.
joystick
.
angle
)
%
360
);
this
.
player
.
onUpdate
(
dt
);
const
speedFlagArr
=
[];
if
(
this
.
fastBtn
.
isFast
)
speedFlagArr
.
push
(
1
);
const
speedPlus
=
speedFlagArr
.
reduce
((
sum
,
item
)
=>
sum
+
item
,
1
);
this
.
snake
.
onUpdate
(
dt
*
speedPlus
);
// 更新相机位置
this
.
camera
.
node
.
setPosition
(
this
.
player
.
head
.
getPosition
());
// 更新NPC移动
this
.
animalNode
.
children
.
forEach
(
child
=>
{
child
.
getComponent
(
A
nimal
)?.
autoMov
e
(
dt
);
child
.
getComponent
(
A
ISnake
)?.
onUpdat
e
(
dt
);
});
}
onPause
()
{
this
.
setGameState
(
GameState
.
PAUSE
);
console
.
log
(
"pause"
);
...
...
@@ -226,7 +172,7 @@ export class MainGame extends Scene {
break
;
case
GameState
.
WIN
:
director
.
pause
();
console
.
log
(
"win"
,
this
.
snake
.
getSnakeLen
());
console
.
log
(
"win"
,
this
.
player
.
getSnakeLen
());
break
;
case
GameState
.
QUIT
:
director
.
resume
();
...
...
@@ -237,38 +183,20 @@ export class MainGame extends Scene {
}
}
play
()
{
if
(
this
.
state
==
GameState
.
OVER
)
{
showToast
(
"你已复活!"
);
this
.
state
=
GameState
.
PLAY
;
this
.
snake
.
reInit
(
math
.
randomRangeInt
(
-
(
Global
.
MAP_WIDTH
/
2
-
50
),
Global
.
MAP_WIDTH
/
2
-
50
),
math
.
randomRangeInt
(
-
(
Global
.
MAP_HIGHT
/
2
-
50
),
Global
.
MAP_HIGHT
/
2
-
50
)
);
// this.showGOver();
}
}
showGOver
()
{
console
.
log
(
"showGOver"
,
this
.
snake
.
getSnakeLen
());
console
.
log
(
"showGOver"
,
this
.
player
.
getSnakeLen
());
}
initItem
=
(
index
:
number
)
=>
{
const
node
=
PoolManager
.
instance
.
getNode
(
this
.
animalPrefab
);
const
x
=
math
.
randomRangeInt
(
-
(
Global
.
MAP_WIDTH
/
2
-
50
),
Global
.
MAP_WIDTH
/
2
-
50
);
const
y
=
math
.
randomRangeInt
(
-
(
Global
.
MAP_HIGHT
/
2
-
50
),
Global
.
MAP_HIGHT
/
2
-
50
);
// const skinId = math.randomRangeInt(0, Config.SKIN_STYLE.length);
const
skinId
=
0
;
node
.
getComponent
(
A
nimal
)?.
init
(
node
.
getComponent
(
A
ISnake
)?.
init
({
x
,
y
,
math
.
randomRangeInt
(
0
,
360
),
skinId
,
0.2
,
Config
.
SKIN_STYLE
[
skinId
].
len
,
Config
.
SKIN_STYLE
[
skinId
].
taitLen
,
index
+
1
);
angle
:
math
.
randomRangeInt
(
0
,
360
),
skinName
:
"default"
,
});
this
.
animalNode
.
addChild
(
node
);
};
...
...
assets/Scripts/Scenes/MainGame/Player.ts
0 → 100644
View file @
29f47b46
import
{
_decorator
,
EventKeyboard
,
Input
,
input
,
KeyCode
,
director
,
}
from
"cc"
;
import
{
Snake
}
from
"./Snake"
;
import
{
Joystick
}
from
"./Joystick"
;
import
{
FastBtn
}
from
"./FastBtn"
;
import
{
Events
,
GameState
}
from
"./Enums"
;
const
{
ccclass
,
property
}
=
_decorator
;
@
ccclass
(
"Player"
)
export
class
Player
extends
Snake
{
@
property
(
Joystick
)
joystick
:
Joystick
=
null
;
@
property
(
FastBtn
)
fastBtn
:
FastBtn
=
null
;
onLoad
()
{
super
.
onLoad
();
input
.
on
(
Input
.
EventType
.
KEY_DOWN
,
this
.
onKeyDown
,
this
);
input
.
on
(
Input
.
EventType
.
KEY_UP
,
this
.
onKeyUp
,
this
);
}
onDestroy
()
{
input
.
off
(
Input
.
EventType
.
KEY_DOWN
,
this
.
onKeyDown
,
this
);
input
.
off
(
Input
.
EventType
.
KEY_UP
,
this
.
onKeyUp
,
this
);
}
death
()
{
super
.
death
();
// 发送游戏结束事件
director
.
emit
(
Events
.
setGameState
,
GameState
.
OVER
);
}
keyArr
:
number
[]
=
[];
onKeyDown
(
event
:
EventKeyboard
)
{
const
keyArr
=
[
KeyCode
.
KEY_W
,
KeyCode
.
KEY_S
,
KeyCode
.
KEY_A
,
KeyCode
.
KEY_D
,];
if
(
keyArr
.
indexOf
(
event
.
keyCode
)
>
-
1
)
{
this
.
keyArr
.
push
(
event
.
keyCode
);
}
if
(
event
.
keyCode
==
KeyCode
.
SPACE
)
{
this
.
fastBtn
.
isFast
=
true
;
}
this
.
setDir
();
}
onKeyUp
(
event
:
EventKeyboard
)
{
const
index
=
this
.
keyArr
.
indexOf
(
event
.
keyCode
);
if
(
index
>
-
1
)
{
this
.
keyArr
.
splice
(
index
,
1
);
}
if
(
event
.
keyCode
==
KeyCode
.
SPACE
)
{
this
.
fastBtn
.
isFast
=
false
;
}
this
.
setDir
();
}
setDir
()
{
if
(
!
this
.
keyArr
.
length
)
return
;
this
.
joystick
.
angle
=
{
[
KeyCode
.
KEY_W
]:
270
,
[
KeyCode
.
KEY_S
]:
90
,
[
KeyCode
.
KEY_A
]:
180
,
[
KeyCode
.
KEY_D
]:
0
,
}[
this
.
keyArr
[
this
.
keyArr
.
length
-
1
]];
}
onUpdate
(
dt
:
number
)
{
this
.
setAngle
((
360
-
this
.
joystick
.
angle
)
%
360
);
this
.
isFast
=
this
.
fastBtn
.
isFast
;
super
.
onUpdate
(
dt
);
}
}
assets/Scripts/Scenes/MainGame/Player.ts.meta
0 → 100644
View file @
29f47b46
{
"ver": "4.0.24",
"importer": "typescript",
"imported": true,
"uuid": "3d36421e-8449-4d5b-86ba-bd43d0e06d42",
"files": [],
"subMetas": {},
"userData": {}
}
assets/Scripts/Scenes/MainGame/Snake.ts
View file @
29f47b46
import
{
_decorator
,
assetManager
,
Collider2D
,
Component
,
Contact2DType
,
director
,
ImageAsset
,
math
,
Node
,
PhysicsGroup
,
Prefab
,
Sprite
,
SpriteAtlas
,
SpriteFrame
,
TextAsset
,
SpriteFrame
,
tween
,
v2
,
v3
,
Vec3
,
}
from
"cc"
;
import
{
Events
,
FoodType
,
GameStat
e
}
from
"./Enums"
;
import
{
FoodTyp
e
}
from
"./Enums"
;
import
{
Global
}
from
"./Global"
;
import
{
PoolManager
}
from
"./PoolManager"
;
import
{
isIntersect
,
loadSkin
}
from
"./uitl"
;
import
{
MainGame
}
from
"./MainGame"
;
import
{
executePreFrame
,
getItemGenerator
}
from
"../../Utils/ExecutePreFrame"
;
import
{
BuffManager
}
from
"./Buff/BuffManager"
;
import
{
BuffType
}
from
"./Buff/BuffType"
;
const
{
ccclass
,
property
}
=
_decorator
;
...
...
@@ -51,9 +52,9 @@ export class Snake extends Component {
private
imgBody2
:
SpriteFrame
=
null
;
// 蛇的状态
pr
ivate
isLife
:
boolean
=
false
;
pr
otected
isLife
:
boolean
=
false
;
private
scale
:
number
=
0.2
;
pr
ivate
speed
:
number
=
600
;
pr
otected
speed
:
number
=
600
;
private
energy
:
number
=
0
;
private
tag
:
number
=
0
;
...
...
@@ -66,10 +67,8 @@ export class Snake extends Component {
public
async
init
(
config
:
IInitConfig
=
{})
{
const
{
x
=
0
,
y
=
0
,
angle
=
0
,
skinName
=
"default"
,
scale
=
0.2
,
bodyCount
=
5
,
x
=
0
,
y
=
0
,
angle
=
0
,
scale
=
0.2
,
skinName
=
"default"
,
bodyCount
=
5
,
}
=
config
;
await
this
.
setSkin
(
skinName
);
...
...
@@ -118,13 +117,17 @@ export class Snake extends Component {
onEnable
()
{
const
collider
=
this
.
head
.
getComponent
(
Collider2D
);
collider
.
on
(
Contact2DType
.
BEGIN_CONTACT
,
this
.
onBeginHead
,
this
);
collider
.
on
(
Contact2DType
.
BEGIN_CONTACT
,
this
.
onBeginEye
,
this
);
const
eye
=
this
.
head
.
getChildByName
(
"范围"
).
getComponent
(
Collider2D
);
eye
.
on
(
Contact2DType
.
BEGIN_CONTACT
,
this
.
onBeginEye
,
this
);
}
onDisable
()
{
const
collider
=
this
.
head
.
getComponent
(
Collider2D
);
collider
.
off
(
Contact2DType
.
BEGIN_CONTACT
,
this
.
onBeginHead
,
this
);
collider
.
off
(
Contact2DType
.
BEGIN_CONTACT
,
this
.
onBeginEye
,
this
);
const
eye
=
this
.
head
.
getChildByName
(
"范围"
).
getComponent
(
Collider2D
);
eye
.
off
(
Contact2DType
.
BEGIN_CONTACT
,
this
.
onBeginEye
,
this
);
}
// 碰撞检测
...
...
@@ -150,11 +153,6 @@ export class Snake extends Component {
if
(
foodType
==
FoodType
.
FOOD
)
{
this
.
addEnergy
(
1
);
}
// 生成新的食物
if
(
MainGame
.
ins
.
fondManger
.
getFoodSum
()
<
MainGame
.
ins
.
maxFood
)
{
MainGame
.
ins
.
fondManger
.
addFood
();
}
})
.
start
();
}
...
...
@@ -197,11 +195,11 @@ export class Snake extends Component {
this
.
bodyArr
.
splice
(
len
,
0
,
newBody
);
}
setAngle
(
e
)
{
this
.
isLife
&&
(
this
.
head
.
angle
=
e
);
setAngle
(
angle
:
number
)
{
this
.
isLife
&&
(
this
.
head
.
angle
=
angl
e
);
}
isFast
=
false
;
private
positions
:
Vec3
[]
=
[];
// 存储历史位置点
private
readonly
HISTORY_LENGTH
=
100
;
// 增加历史点数量
private
readonly
SEGMENT_SPACING
=
5
;
// 增加节点间距
...
...
@@ -210,14 +208,22 @@ export class Snake extends Component {
totalTime
=
0
;
onUpdate
(
dt
:
number
)
{
this
.
totalTime
+=
dt
;
this
.
buffManager
.
update
(
dt
);
let
speedScale
=
1
;
if
(
this
.
isFast
)
{
speedScale
+=
1
;
}
this
.
totalTime
+=
dt
*
speedScale
;
while
(
this
.
totalTime
>=
this
.
moveTime
)
{
this
.
totalTime
-=
this
.
moveTime
;
this
.
move
(
this
.
moveTime
);
}
}
move
(
dt
:
number
)
{
protected
move
(
dt
:
number
)
{
if
(
!
this
.
ready
||
!
this
.
isLife
)
{
return
;
}
...
...
@@ -282,47 +288,75 @@ export class Snake extends Component {
this
.
death
();
}
// 更新相机位置
MainGame
.
ins
.
camera
.
node
.
setPosition
(
this
.
head
.
getPosition
());
}
getSnakeLen
()
{
return
this
.
bodyArr
.
length
;
}
reInit
(
e
,
t
)
{
this
.
head
.
angle
=
0
;
this
.
head
.
setPosition
(
e
,
t
);
this
.
node
.
active
=
true
;
this
.
isLife
=
true
;
}
// 死亡处理
public
death
()
{
if
(
!
this
.
isLife
)
return
;
// 隐藏所有身体节点
for
(
let
i
=
0
;
i
<
this
.
bodyArr
.
length
;
i
++
)
{
this
.
bodyArr
[
i
].
setPosition
(
-
9999
,
-
9999
);
this
.
bodyArr
[
i
].
active
=
false
;
}
this
.
isLife
=
false
;
this
.
node
.
active
=
false
;
// 发送游戏结束事件
director
.
emit
(
Events
.
setGameState
,
GameState
.
OVER
);
this
.
initFond
(
this
.
bodyArr
.
length
);
}
// 工具方法 - 计算新位置
private
getNewPos
(
angle
:
number
,
dt
:
number
,
currentPos
:
Vec3
,
speed
:
number
=
this
.
speed
):
Vec3
{
protected
getNewPos
(
angle
:
number
,
dt
:
number
,
currentPos
:
Vec3
,
speed
:
number
=
this
.
speed
):
Vec3
{
const
radian
=
angle
/
180
*
Math
.
PI
;
const
direction
=
v2
(
Math
.
cos
(
radian
),
Math
.
sin
(
radian
));
return
v3
(
currentPos
.
x
+
dt
*
direction
.
x
*
speed
,
currentPos
.
y
+
dt
*
direction
.
y
*
speed
,
0
return
v3
(
currentPos
.
x
+
dt
*
direction
.
x
*
speed
,
currentPos
.
y
+
dt
*
direction
.
y
*
speed
,
0
);
}
/**
* 初始化食物
*/
initItem
=
(
index
:
number
)
=>
{
const
bp
=
this
.
bodyArr
[
index
].
getPosition
();
MainGame
.
ins
.
fondManger
.
addFood
(
math
.
randomRangeInt
(
bp
.
x
-
10
,
bp
.
x
+
11
),
math
.
randomRangeInt
(
bp
.
y
-
20
,
bp
.
y
+
21
)
);
this
.
bodyArr
[
index
].
setPosition
(
9999
,
9999
);
this
.
bodyArr
[
index
].
active
=
false
;
};
/**
* 初始化食物
*/
async
initFond
(
count
:
number
)
{
await
executePreFrame
(
getItemGenerator
(
count
,
this
.
initItem
),
1
,
this
);
this
.
ready
=
true
;
}
private
buffManager
:
BuffManager
=
new
BuffManager
(
this
);
private
isInvincible
:
boolean
=
false
;
private
speedMultiplier
:
number
=
1
;
onLoad
()
{
// ... 其他初始化代码 ...
this
.
buffManager
=
new
BuffManager
(
this
);
}
// 添加Buff的便捷方法
addBuff
(
type
:
BuffType
,
duration
?:
number
,
value
?:
number
)
{
const
buff
=
this
.
buffManager
.
createBuff
(
type
,
duration
,
value
);
if
(
buff
)
{
this
.
buffManager
.
addBuff
(
buff
);
}
}
// 提供给Buff使用的方法
setInvincible
(
value
:
boolean
)
{
this
.
isInvincible
=
value
;
}
setSpeedMultiplier
(
value
:
number
)
{
this
.
speedMultiplier
=
value
;
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment