child) {
91 | super(child);
92 | this.times = times;
93 | }
94 |
95 | /**
96 | * Draws a value from the distribution that determines how many times the
97 | * wrapped task must be repeated. Any negative value means forever.
98 | *
99 | * This method is called when the task is entered.
100 | */
101 | @Override
102 | public void start() {
103 | count = times;
104 | }
105 |
106 | @Override
107 | public boolean condition() {
108 | return loop && count != 0;
109 | }
110 |
111 | @Override
112 | public void childSuccess(Task runningTask) {
113 | if (count > 0)
114 | count--;
115 | if (count == 0) {
116 | super.childSuccess(runningTask);
117 | loop = false;
118 | } else
119 | loop = true;
120 | }
121 |
122 | @Override
123 | public void childFail(Task runningTask) {
124 | childSuccess(runningTask);
125 | }
126 |
127 | @Override
128 | public void release() {
129 | count = 0;
130 | times = 0;
131 | super.release();
132 | }
133 |
134 | public int getTimes() {
135 | return times;
136 | }
137 |
138 | public void setTimes(int times) {
139 | this.times = times;
140 | }
141 |
142 |
143 | }
144 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/btree/decorator/UntilFail.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.btree.decorator;
18 |
19 |
20 | import com.jzy.ai.btree.LoopDecorator;
21 | import com.jzy.ai.btree.Task;
22 |
23 | /**
24 | * 直到失败
25 | * The {@code UntilFail} decorator will repeat the wrapped task until that task
26 | * fails, which makes the decorator succeed.
27 | *
28 | * Notice that a wrapped task that always succeeds without entering the running
29 | * status will cause an infinite loop in the current frame.
30 | *
31 | * @param
32 | * type of the blackboard object that tasks use to read or modify
33 | * game state
34 | *
35 | * @author implicit-invocation
36 | * @author davebaol
37 | */
38 | public class UntilFail extends LoopDecorator {
39 |
40 | /** Creates an {@code UntilFail} decorator with no child. */
41 | public UntilFail() {
42 | }
43 |
44 | /**
45 | * Creates an {@code UntilFail} decorator with the given child.
46 | *
47 | * @param task
48 | * the child task to wrap
49 | */
50 | public UntilFail(Task task) {
51 | super(task);
52 | }
53 |
54 | @Override
55 | public void childSuccess(Task runningTask) {
56 | loop = true;
57 | }
58 |
59 | @Override
60 | public void childFail(Task runningTask) {
61 | success();
62 | loop = false;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/btree/decorator/UntilSuccess.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.btree.decorator;
18 |
19 |
20 | import com.jzy.ai.btree.LoopDecorator;
21 | import com.jzy.ai.btree.Task;
22 |
23 | /**
24 | * 直到成功
25 | * The {@code UntilSuccess} decorator will repeat the wrapped task until that
26 | * task succeeds, which makes the decorator succeed.
27 | *
28 | * Notice that a wrapped task that always fails without entering the running
29 | * status will cause an infinite loop in the current frame.
30 | *
31 | * @param
32 | * type of the blackboard object that tasks use to read or modify
33 | * game state
34 | *
35 | * @author implicit-invocation
36 | * @author davebaol
37 | */
38 | public class UntilSuccess extends LoopDecorator {
39 |
40 | /** Creates an {@code UntilSuccess} decorator with no child. */
41 | public UntilSuccess() {
42 | }
43 |
44 | /**
45 | * Creates an {@code UntilSuccess} decorator with the given child.
46 | *
47 | * @param task
48 | * the child task to wrap
49 | */
50 | public UntilSuccess(Task task) {
51 | super(task);
52 | }
53 |
54 | @Override
55 | public void childSuccess(Task runningTask) {
56 | success();
57 | loop = false;
58 | }
59 |
60 | @Override
61 | public void childFail(Task runningTask) {
62 | loop = true;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/btree/leaf/Failure.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.btree.leaf;
18 |
19 |
20 | import com.jzy.ai.btree.LeafTask;
21 |
22 | /**失败子节点
23 | * {@code Failure} is a leaf that immediately fails.
24 | *
25 | * @param type of the blackboard object that tasks use to read or modify game state
26 | *
27 | * @author davebaol */
28 | public class Failure extends LeafTask {
29 |
30 | /** Creates a {@code Failure} task. */
31 | public Failure () {
32 | }
33 |
34 | /** Executes this {@code Failure} task.
35 | * @return {@link Status#FAILED}. */
36 | @Override
37 | public Status execute () {
38 | return Status.FAILED;
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/btree/leaf/Success.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.btree.leaf;
18 |
19 |
20 | import com.jzy.ai.btree.LeafTask;
21 |
22 | /**成功
23 | * {@code Success} is a leaf that immediately succeeds.
24 | *
25 | * @param type of the blackboard object that tasks use to read or modify game state
26 | *
27 | * @author davebaol */
28 | public class Success extends LeafTask {
29 |
30 | /** Creates a {@code Success} task. */
31 | public Success () {
32 | }
33 |
34 | /** Executes this {@code Success} task.
35 | * @return {@link Status#SUCCEEDED}. */
36 | @Override
37 | public Status execute () {
38 | return Status.SUCCEEDED;
39 | }
40 |
41 | // @Override
42 | // protected Task copyTo (Task task) {
43 | // return task;
44 | // }
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/btree/leaf/Wait.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.btree.leaf;
18 |
19 |
20 | import com.jzy.ai.btree.LeafTask;
21 | import com.jzy.ai.btree.annotation.TaskAttribute;
22 | import com.jzy.javalib.base.util.TimeUtil;
23 |
24 | /**
25 | * 等待执行指定次数
26 | * {@code Wait} is a leaf that keeps running for the specified amount of time
27 | * then succeeds.
28 | *
29 | * @param
30 | * type of the blackboard object that tasks use to read or modify
31 | * game state
32 | *
33 | * @author davebaol
34 | * @fix JiangZhiYong
35 | */
36 | public class Wait extends LeafTask {
37 | private static final float INIT_SECONDS = 0f;
38 |
39 | /**
40 | * Mandatory task attribute specifying the random distribution that determines
41 | * the timeout in seconds.
42 | */
43 | @TaskAttribute(required = true)
44 | public float seconds;
45 |
46 | private float startTime;
47 | private float timeout;
48 |
49 | /** Creates a {@code Wait} task that immediately succeeds. */
50 | public Wait() {
51 | this(INIT_SECONDS);
52 | }
53 |
54 | /**
55 | * Creates a {@code Wait} task running for the specified number of seconds.
56 | *
57 | * @param seconds
58 | * the number of seconds to wait for
59 | */
60 | public Wait(float seconds) {
61 | this.seconds = seconds;
62 | }
63 |
64 | /**
65 | * Draws a value from the distribution that determines the seconds to wait for.
66 | *
67 | * This method is called when the task is entered. Also, this method internally
68 | * calls {@link Timepiece#getTime() GdxAI.getTimepiece().getTime()} to get the
69 | * current AI time. This means that
70 | *
71 | * - if you forget to {@link Timepiece#update(float) update the timepiece}
72 | * this task will keep running indefinitely.
73 | * - the timepiece should be updated before this task runs.
74 | *
75 | */
76 | @Override
77 | public void start() {
78 | timeout = seconds;
79 | startTime = TimeUtil.currentTimeMillis();
80 | }
81 |
82 | /**
83 | * Executes this {@code Wait} task.
84 | *
85 | * @return {@link Status#SUCCEEDED} if the specified timeout has expired;
86 | * {@link Status#RUNNING} otherwise.
87 | */
88 | @Override
89 | public Status execute() {
90 | return TimeUtil.currentTimeMillis() - startTime < timeout ? Status.RUNNING : Status.SUCCEEDED;
91 | }
92 |
93 | // @Override
94 | // protected Task copyTo(Task task) {
95 | // ((Wait) task).seconds = seconds;
96 | // return task;
97 | // }
98 |
99 | @Override
100 | public void release() {
101 | seconds = INIT_SECONDS;
102 | startTime = 0;
103 | timeout = 0;
104 | super.release();
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fma/BoundedSlotAssignmentStrategy.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fma;
18 |
19 |
20 |
21 | import com.jzy.javalib.math.geometry.Vector;
22 |
23 | import java.util.List;
24 |
25 | /** {@code BoundedSlotAssignmentStrategy} is an abstract implementation of {@link SlotAssignmentStrategy} that supports roles.
26 | * Generally speaking, there are hard and soft roles. Hard roles cannot be broken, soft roles can.
27 | *
28 | * This abstract class provides an implementation of the {@link #calculateNumberOfSlots(List) calculateNumberOfSlots} method that
29 | * is more general (and costly) than the simplified implementation in {@link FreeSlotAssignmentStrategy}. It scans the assignment
30 | * list to find the number of filled slots, which is the highest slot number in the assignments.
31 | *
32 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface
33 | *
34 | * @author davebaol */
35 | public abstract class BoundedSlotAssignmentStrategy> implements SlotAssignmentStrategy {
36 |
37 | @Override
38 | public abstract void updateSlotAssignments (List> assignments);
39 |
40 | @Override
41 | public int calculateNumberOfSlots (List> assignments) {
42 | // Find the number of filled slots: it will be the
43 | // highest slot number in the assignments
44 | int filledSlots = -1;
45 | for (int i = 0; i < assignments.size(); i++) {
46 | SlotAssignment assignment = assignments.get(i);
47 | if (assignment.slotNumber >= filledSlots) filledSlots = assignment.slotNumber;
48 | }
49 |
50 | // Add one to go from the index of the highest slot to the number of slots needed.
51 | return filledSlots + 1;
52 | }
53 |
54 | @Override
55 | public void removeSlotAssignment (List> assignments, int index) {
56 | int sn = assignments.get(index).slotNumber;
57 | for (int i = 0; i < assignments.size(); i++) {
58 | SlotAssignment sa = assignments.get(i);
59 | if (sa.slotNumber >= sn) sa.slotNumber--;
60 | }
61 | assignments.remove(index);
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fma/FormationMember.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fma;
18 |
19 |
20 | import com.jzy.ai.util.Location;
21 | import com.jzy.javalib.math.geometry.Vector;
22 |
23 | /**
24 | * 阵型成员
25 | * Game characters coordinated by a {@link Formation} must implement this interface. Any {@code FormationMember} has a target
26 | * location which is the place where it should be in order to stay in formation. This target location is calculated by the
27 | * formation itself.
28 | *
29 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface
30 | *
31 | * @author davebaol */
32 | public interface FormationMember> {
33 |
34 | /** Returns the target location of this formation member. */
35 | public Location getTargetLocation();
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fma/FormationMotionModerator.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fma;
18 |
19 |
20 |
21 | import com.jzy.ai.util.Location;
22 | import com.jzy.javalib.math.geometry.Vector;
23 |
24 | import java.util.List;
25 |
26 | /**
27 | * 阵型调节器
28 | * A {@code FormationMotionModerator} moderates the movement of the formation based on the current positions of the members in its
29 | * slots: in effect to keep the anchor point on a leash. If the members in the slots are having trouble reaching their targets,
30 | * then the formation as a whole should be held back to give them a chance to catch up.
31 | *
32 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface
33 | *
34 | * @author davebaol */
35 | public abstract class FormationMotionModerator> {
36 |
37 | private Location tempLocation;
38 |
39 | /** Update the anchor point to moderate formation motion. This method is called at each frame.
40 | * @param anchor the anchor point */
41 | public abstract void updateAnchorPoint (Location anchor);
42 |
43 | /** Calculates the drift offset when members are in the given set of slots for the specified pattern.
44 | * @param centerOfMass the output location set to the calculated drift offset
45 | * @param slotAssignments the set of slots
46 | * @param pattern the pattern
47 | * @return the given location for chaining. */
48 | public Location calculateDriftOffset (Location centerOfMass, List> slotAssignments,
49 | FormationPattern pattern) {
50 |
51 | // Clear the center of mass
52 | centerOfMass.getPosition().setZero();
53 | float centerOfMassOrientation = 0;
54 |
55 | // Make sure tempLocation is instantiated
56 | if (tempLocation == null) tempLocation = centerOfMass.newLocation();
57 |
58 | T centerOfMassPos = centerOfMass.getPosition();
59 | T tempLocationPos = tempLocation.getPosition();
60 |
61 | // Go through each assignment and add its contribution to the center
62 | float numberOfAssignments = slotAssignments.size();
63 | for (int i = 0; i < numberOfAssignments; i++) {
64 | pattern.calculateSlotLocation(tempLocation, slotAssignments.get(i).slotNumber);
65 | centerOfMassPos.add(tempLocationPos);
66 | centerOfMassOrientation += tempLocation.getOrientation();
67 | }
68 |
69 | // Divide through to get the drift offset.
70 | centerOfMassPos.scl(1f / numberOfAssignments);
71 | centerOfMassOrientation /= numberOfAssignments;
72 | centerOfMass.setOrientation(centerOfMassOrientation);
73 |
74 | return centerOfMass;
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fma/FormationPattern.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fma;
18 |
19 |
20 | import com.jzy.ai.util.Location;
21 | import com.jzy.javalib.math.geometry.Vector;
22 |
23 | /** The {@code FormationPattern} interface represents the shape of a formation and generates the slot offsets, relative to its
24 | * anchor point. Since formations can be scalable the pattern must be able to determine if a given number of slots is supported.
25 | *
26 | * Each particular pattern (such as a V, wedge, circle) needs its own instance of a class that implements this
27 | * {@code FormationPattern} interface.
28 | *
29 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface
30 | *
31 | * @author davebaol */
32 | public interface FormationPattern> {
33 |
34 | /** Sets the number of slots.
35 | * @param numberOfSlots the number of slots to set */
36 | public void setNumberOfSlots(int numberOfSlots);
37 |
38 | /** Returns the location of the given slot index. */
39 | public Location calculateSlotLocation(Location outLocation, int slotNumber);
40 |
41 | /** Returns true if the pattern can support the given number of slots
42 | * @param slotCount the number of slots
43 | * @return {@code true} if this pattern can support the given number of slots; {@code false} othervwise. */
44 | public boolean supportsSlots(int slotCount);
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fma/FreeSlotAssignmentStrategy.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fma;
18 |
19 |
20 |
21 | import com.jzy.javalib.math.geometry.Vector;
22 |
23 | import java.util.List;
24 |
25 | /**
26 | * 自由分配策略
27 | * {@code FreeSlotAssignmentStrategy} is the simplest implementation of {@link SlotAssignmentStrategy}. It simply go through
28 | * each assignment in the list and assign sequential slot numbers. The number of slots is just the length of the list.
29 | *
30 | * Because each member can occupy any slot this implementation does not support roles.
31 | *
32 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface
33 | *
34 | * @author davebaol */
35 | public class FreeSlotAssignmentStrategy> implements SlotAssignmentStrategy {
36 |
37 | @Override
38 | public void updateSlotAssignments (List> assignments) {
39 | // A very simple assignment algorithm: we simply go through
40 | // each assignment in the list and assign sequential slot numbers
41 | for (int i = 0; i < assignments.size(); i++)
42 | assignments.get(i).slotNumber = i;
43 | }
44 |
45 | @Override
46 | public int calculateNumberOfSlots (List> assignments) {
47 | return assignments.size();
48 | }
49 |
50 | @Override
51 | public void removeSlotAssignment (List> assignments, int index) {
52 | assignments.remove(index);
53 | }
54 |
55 | }
56 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fma/SlotAssignment.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fma;
18 |
19 |
20 | import com.jzy.javalib.math.geometry.Vector;
21 |
22 | /**
23 | * 槽位分配
24 | * A {@code SlotAssignment} instance represents the assignment of a single {@link FormationMember} to its slot in the
25 | * {@link Formation}.
26 | *
27 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface
28 | *
29 | * @author davebaol */
30 | public class SlotAssignment> {
31 | public FormationMember member;
32 | public int slotNumber;
33 |
34 | /** Creates a {@code SlotAssignment} for the given {@code member}.
35 | * @param member the member of this slot assignment */
36 | public SlotAssignment (FormationMember member) {
37 | this(member, 0);
38 | }
39 |
40 | /** Creates a {@code SlotAssignment} for the given {@code member} and {@code slotNumber}.
41 | * @param member the member of this slot assignment */
42 | public SlotAssignment (FormationMember member, int slotNumber) {
43 | this.member = member;
44 | this.slotNumber = slotNumber;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fma/SlotAssignmentStrategy.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fma;
18 |
19 |
20 | import com.jzy.javalib.math.geometry.Vector;
21 |
22 | import java.util.List;
23 |
24 | /**
25 | * 槽位分配策略
26 | * This interface defines how each {@link FormationMember} is assigned to a slot in the {@link Formation}.
27 | *
28 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface
29 | *
30 | * @author davebaol */
31 | public interface SlotAssignmentStrategy> {
32 |
33 | /** Updates the assignment of members to slots */
34 | public void updateSlotAssignments(List> assignments);
35 |
36 | /** Calculates the number of slots from the assignment data. */
37 | public int calculateNumberOfSlots(List> assignments);
38 |
39 | /** Removes the slot assignment at the specified index. */
40 | public void removeSlotAssignment(List> assignments, int index);
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fma/patterns/DefensiveCircleFormationPattern.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fma.patterns;
18 |
19 |
20 | import com.jzy.ai.fma.FormationPattern;
21 | import com.jzy.ai.util.Location;
22 | import com.jzy.javalib.base.util.MathUtil;
23 | import com.jzy.javalib.math.geometry.Vector;
24 |
25 | /**
26 | * 防御圈阵型
27 | * The defensive circle posts members around the circumference of a circle, so their backs are to the center of the circle. The
28 | * circle can consist of any number of members. Although a huge number of members might look silly, this implementation doesn't
29 | * put any fixed limit.
30 | *
31 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface
32 | * @author davebaol
33 | */
34 | public class DefensiveCircleFormationPattern> implements FormationPattern {
35 | /**
36 | * The number of slots currently in the pattern.
37 | */
38 | int numberOfSlots;
39 |
40 | /**
41 | * The radius of one member. This is needed to determine how close we can pack a given number of members around circle.
42 | */
43 | float memberRadius;
44 |
45 | /**
46 | * Creates a {@code DefensiveCircleFormationPattern}
47 | *
48 | * @param memberRadius
49 | */
50 | public DefensiveCircleFormationPattern(float memberRadius) {
51 | this.memberRadius = memberRadius;
52 | }
53 |
54 | @Override
55 | public void setNumberOfSlots(int numberOfSlots) {
56 | this.numberOfSlots = numberOfSlots;
57 | }
58 |
59 | @Override
60 | public Location calculateSlotLocation(Location outLocation, int slotNumber) {
61 | if (numberOfSlots > 1) {
62 | // Place the slot around the circle based on its slot number
63 | float angleAroundCircle = (MathUtil.PI2 * slotNumber) / numberOfSlots;
64 |
65 | // The radius depends on the radius of the member,
66 | // and the number of members in the circle:
67 | // we want there to be no gap between member's shoulders.
68 | float radius = memberRadius / (float) Math.sin(Math.PI / numberOfSlots);
69 |
70 | // Fill location components based on the angle around circle.
71 | outLocation.angleToVector(outLocation.getPosition(), angleAroundCircle).scl(radius);
72 |
73 | // The members should be facing out
74 | outLocation.setOrientation(angleAroundCircle);
75 | } else {
76 | outLocation.getPosition().setZero();
77 | outLocation.setOrientation(MathUtil.PI2 * slotNumber);
78 | }
79 |
80 | // Return the slot location
81 | return outLocation;
82 | }
83 |
84 | @Override
85 | public boolean supportsSlots(int slotCount) {
86 | // In this case we support any number of slots.
87 | return true;
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fma/patterns/OffensiveCircleFormationPattern.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fma.patterns;
18 |
19 |
20 | import com.jzy.ai.util.Location;
21 | import com.jzy.javalib.base.util.MathUtil;
22 | import com.jzy.javalib.math.geometry.Vector;
23 |
24 | /**
25 | * 攻击圈阵型
26 | * The offensive circle posts members around the circumference of a circle, so their fronts are to the center of the circle. The
27 | * circle can consist of any number of members. Although a huge number of members might look silly, this implementation doesn't
28 | * put any fixed limit.
29 | *
30 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface
31 | *
32 | * @author davebaol */
33 | public class OffensiveCircleFormationPattern> extends DefensiveCircleFormationPattern {
34 |
35 | /** Creates a {@code OffensiveCircleFormationPattern}
36 | * @param memberRadius */
37 | public OffensiveCircleFormationPattern (float memberRadius) {
38 | super(memberRadius);
39 | }
40 |
41 | @Override
42 | public Location calculateSlotLocation (Location outLocation, int slotNumber) {
43 | super.calculateSlotLocation(outLocation, slotNumber);
44 | outLocation.setOrientation(outLocation.getOrientation() + MathUtil.PI);
45 | return outLocation;
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fsm/State.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fsm;
18 |
19 |
20 | import com.jzy.ai.msg.Telegram;
21 |
22 | /**
23 | * 状态接口
24 | * The state of a state machine defines the logic of the entities that enter,
25 | * exit and last this state. Additionally, a state may be delegated by an entity
26 | * to handle its messages.
27 | *
28 | * @param
29 | * is the type of the entity handled by this state machine
30 | *
31 | * @author davebaol
32 | */
33 | public interface State {
34 |
35 | /**
36 | * This method will execute when the state is entered.
37 | *
38 | * @param entity
39 | * the entity entering the state
40 | */
41 | public void enter(E entity);
42 |
43 | /**
44 | * This is the state's normal update function
45 | *
46 | * @param entity
47 | * the entity lasting the state
48 | */
49 | public void update(E entity);
50 |
51 | /**
52 | * This method will execute when the state is exited.
53 | *
54 | * @param entity
55 | * the entity exiting the state
56 | */
57 | public void exit(E entity);
58 |
59 | /**
60 | * This method executes if the {@code entity} receives a {@code telegram} from
61 | * the message dispatcher while it is in this state.
62 | *
63 | * @param entity
64 | * the entity that received the message
65 | * @param telegram
66 | * the message sent to the entity
67 | * @return true if the message has been successfully handled; false otherwise.
68 | */
69 | public boolean onMessage(E entity, Telegram telegram);
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/fsm/StateMachine.java:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright 2014 See AUTHORS file.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | ******************************************************************************/
16 |
17 | package com.jzy.ai.fsm;
18 |
19 |
20 | import com.jzy.ai.msg.Telegram;
21 | import com.jzy.ai.msg.Telegraph;
22 |
23 | /**
24 | * 状态机接口
25 | * A state machine manages the state transitions of its entity. Additionally,
26 | * the state machine may be delegated by the entity to handle its messages.
27 | *
28 | * @param
29 | * the type of the entity owning this state machine
30 | * @param
31 | * the type of the states of this state machine
32 | *
33 | * @author davebaol
34 | */
35 | public interface StateMachine> extends Telegraph {
36 |
37 | /**
38 | * Updates the state machine.
39 | *
40 | * Implementation classes should invoke first the {@code update} method of the
41 | * global state (if any) then the {@code update} method of the current state.
42 | *
43 | */
44 | public void update();
45 |
46 | /**
47 | * Performs a transition to the specified state.
48 | *
49 | * @param newState
50 | * the state to transition to
51 | */
52 | public void changeState(S newState);
53 |
54 | /**
55 | * Changes the state back to the previous state.
56 | *
57 | * @return {@code True} in case there was a previous state that we were able to
58 | * revert to. In case there is no previous state, no state change occurs
59 | * and {@code false} will be returned.
60 | */
61 | public boolean revertToPreviousState();
62 |
63 | /**
64 | * Sets the initial state of this state machine.
65 | *
66 | * @param state
67 | * the initial state.
68 | */
69 | public void setInitialState(S state);
70 |
71 | /**
72 | * Sets the global state of this state machine.
73 | *
74 | * @param state
75 | * the global state.
76 | */
77 | public void setGlobalState(S state);
78 |
79 | /** Returns the current state of this state machine. */
80 | public S getCurrentState();
81 |
82 | /**
83 | * Returns the global state of this state machine.
84 | *
85 | * Implementation classes should invoke the {@code update} method of the global
86 | * state every time the FSM is updated. Also, they should never invoke its
87 | * {@code enter} and {@code exit} method.
88 | *
89 | */
90 | public S getGlobalState();
91 |
92 | /** Returns the last state of this state machine. */
93 | public S getPreviousState();
94 |
95 | /**
96 | * Indicates whether the state machine is in the given state.
97 | *
98 | * @param state
99 | * the state to be compared with the current state
100 | * @return true if the current state's type is equal to the type of the class
101 | * passed as a parameter.
102 | */
103 | public boolean isInState(S state);
104 |
105 | /**
106 | * Handles received telegrams.
107 | *
108 | * Implementation classes should first route the telegram to the current state.
109 | * If the current state does not deal with the message, it should be routed to
110 | * the global state.
111 | *
112 | *
113 | * @param telegram
114 | * the received telegram
115 | * @return true if telegram has been successfully handled; false otherwise.
116 | */
117 | public boolean handleMessage(Telegram telegram);
118 | }
119 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/msg/MessageManager.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.msg;
3 |
4 | /**
5 | * 电报管理
6 | * The {@code MessageManager} is a singleton {@link MessageDispatcher} in charge of the creation, dispatch, and management of
7 | * telegrams.
8 | *
9 | * @author davebaol */
10 | public final class MessageManager extends MessageDispatcher {
11 |
12 | private static final MessageManager INSTANCE = new MessageManager();
13 |
14 | /** Don't let anyone else instantiate this class */
15 | private MessageManager () {
16 | }
17 |
18 | /** Returns the singleton instance of the message dispatcher. */
19 | public static MessageManager getInstance () {
20 | return INSTANCE;
21 | }
22 |
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/msg/Telegram.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.msg;
3 |
4 | import com.jzy.ai.util.IMemoryObject;
5 |
6 | /**电报
7 | *
8 | * A Telegram is the container of a message. The {@link MessageDispatcher} manages telegram life-cycle.
9 | * @author davebaol */
10 | public class Telegram implements Comparable, IMemoryObject {
11 |
12 | /** Indicates that the sender doesn't need any return receipt */
13 | public static final int RETURN_RECEIPT_UNNEEDED = 0;
14 |
15 | /** Indicates that the sender needs the return receipt */
16 | public static final int RETURN_RECEIPT_NEEDED = 1;
17 |
18 | /** Indicates that the return receipt has been sent back to the original sender of the telegram */
19 | public static final int RETURN_RECEIPT_SENT = 2;
20 |
21 | /** The agent that sent this telegram */
22 | public Telegraph sender;
23 |
24 | /** The agent that is to receive this telegram */
25 | public Telegraph receiver;
26 |
27 | /** The message type. */
28 | public int message;
29 |
30 | /** The return receipt status of this telegram. Its value should be {@link #RETURN_RECEIPT_UNNEEDED}, {@link #RETURN_RECEIPT_NEEDED} or
31 | * {@link #RETURN_RECEIPT_SENT}. */
32 | public int returnReceiptStatus;
33 |
34 | /** Messages can be dispatched immediately or delayed for a specified amount of time. If a delay is necessary, this field is
35 | * stamped with the time the message should be dispatched. */
36 | private long timestamp;
37 |
38 | /** Any additional information that may accompany the message */
39 | public Object extraInfo;
40 |
41 | /** Creates an empty {@code Telegram}. */
42 | public Telegram () {
43 | }
44 |
45 | /** Returns the time stamp of this telegram. */
46 | public long getTimestamp () {
47 | return timestamp;
48 | }
49 |
50 | /** Sets the time stamp of this telegram. */
51 | public void setTimestamp (long timestamp) {
52 | this.timestamp = timestamp;
53 | }
54 |
55 | @Override
56 | public void release () {
57 | this.sender = null;
58 | this.receiver = null;
59 | this.message = 0;
60 | this.returnReceiptStatus = RETURN_RECEIPT_UNNEEDED;
61 | this.extraInfo = null;
62 | this.timestamp = 0;
63 | }
64 |
65 | @Override
66 | public int compareTo (Telegram other) {
67 | //根据时间进行优先级排序
68 | if (this.equals(other)) return 0;
69 | return (this.timestamp - other.timestamp < 0) ? -1 : 1;
70 | }
71 |
72 | @Override
73 | public int hashCode () {
74 | final int prime = 31;
75 | int result = 1;
76 | result = prime * result + message;
77 | result = prime * result + ((receiver == null) ? 0 : receiver.hashCode());
78 | result = prime * result + ((sender == null) ? 0 : sender.hashCode());
79 | result = prime * result + Float.floatToIntBits(timestamp);
80 | return result;
81 | }
82 |
83 | @Override
84 | public boolean equals (Object obj) {
85 | if (this == obj) return true;
86 | if (obj == null) return false;
87 | if (getClass() != obj.getClass()) return false;
88 | Telegram other = (Telegram)obj;
89 | if (message != other.message) return false;
90 | if (Float.floatToIntBits(timestamp) != Float.floatToIntBits(other.timestamp)) return false;
91 | if (sender == null) {
92 | if (other.sender != null) return false;
93 | } else if (!sender.equals(other.sender)) return false;
94 | if (receiver == null) {
95 | if (other.receiver != null) return false;
96 | } else if (!receiver.equals(other.receiver)) return false;
97 | return true;
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/msg/TelegramProvider.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.msg;
3 |
4 | /**提供額外信息接口
5 | * Telegram providers respond to {@link MessageDispatcher#addListener} by providing optional {@link Telegram#extraInfo} to be sent
6 | * in a Telegram of a given type to the newly registered {@link Telegraph}.
7 | * @author avianey */
8 | public interface TelegramProvider {
9 | /** Provides {@link Telegram#extraInfo} to dispatch immediately when a {@link Telegraph} is registered for the given message
10 | * type.
11 | * @param msg the message type to provide
12 | * @param receiver the newly registered Telegraph. Providers can provide different info depending on the targeted Telegraph.
13 | * @return extra info to dispatch in a Telegram or null if nothing to dispatch
14 | * @see MessageDispatcher#addListener(Telegraph, int)
15 | * @see MessageDispatcher#addListeners(Telegraph, int...) */
16 | Object provideMessageInfo (int msg, Telegraph receiver);
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/msg/Telegraph.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.msg;
3 |
4 | /**处理电报接口
5 | * Any object implementing the {@code Telegraph} interface can act as the sender
6 | * or the receiver of a {@link Telegram}.
7 | * 任何实现Telegraph接口的对象,都可以作为电报的发送方或者接收方
8 | * @author davebaol
9 | */
10 | public interface Telegraph {
11 |
12 | /**
13 | * Handles the telegram just received.
14 | *
15 | * @param msg
16 | * The telegram
17 | * @return {@code true} if the telegram has been successfully handled;
18 | * {@code false} otherwise.
19 | */
20 | public boolean handleMessage(Telegram msg);
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/NavMesh.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav;
2 |
3 | import com.jzy.javalib.math.geometry.Vector3;
4 |
5 | import java.util.List;
6 |
7 |
8 |
9 | /**
10 | * navmesh寻路入口
11 | *
12 | * @author JiangZhiYong
13 | * @mail 359135103@qq.com
14 | */
15 | public abstract class NavMesh {
16 |
17 | /** 地图宽x轴 */
18 | protected float width;
19 | /** 地图高y轴 */
20 | protected float height;
21 | /** 配置id */
22 | protected int mapId;
23 |
24 | public float getWidth() {
25 | return width;
26 | }
27 |
28 | public void setWidth(float width) {
29 | this.width = width;
30 | }
31 |
32 | public float getHeight() {
33 | return height;
34 | }
35 |
36 | public void setHeight(float height) {
37 | this.height = height;
38 | }
39 |
40 | public int getMapId() {
41 | return mapId;
42 | }
43 |
44 | public void setMapId(int mapId) {
45 | this.mapId = mapId;
46 | }
47 |
48 | /**
49 | * 或者在路径中的坐标点
50 | * 屏幕输入坐标点
51 | *
52 | * @param x
53 | * @param z
54 | * @return
55 | */
56 | public abstract Vector3 getPointInPath(float x, float z);
57 |
58 | /**
59 | * 获取随机坐标
60 | *
61 | * @param center
62 | * 中心坐标
63 | * @param radius
64 | * 随机半径
65 | * @param minDisToCenter
66 | * 到中心点的最小距离
67 | * @return
68 | */
69 | public List getRandomPointsInPath(Vector3 center, float radius, float minDisToCenter) {
70 | throw new UnsupportedOperationException("不支持获取随机点");
71 | }
72 |
73 | /**
74 | * 获取随机坐标
75 | *
76 | * @param center
77 | * @param radius
78 | * @param minDisToCenter
79 | * @return
80 | */
81 | public Vector3 getRandomPointInPath(Vector3 center, float radius, float minDisToCenter) {
82 | throw new UnsupportedOperationException("不支持获取随机点");
83 | }
84 |
85 |
86 | /**
87 | * 获取随机坐标
88 | *
89 | * @param center
90 | * @param radius
91 | * @return
92 | */
93 | public Vector3 getRandomPointInPath(Vector3 center, float radius) {
94 | return this.getRandomPointInPath(center, radius, 0);
95 | }
96 |
97 | /**
98 | * 坐标点是否在路径中
99 | *
100 | */
101 | public boolean isPointInPath(Vector3 point) {
102 | return getPointInPath(point.x, point.z) != null;
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/polygon/PolygonData.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.polygon;
2 |
3 | import com.jzy.ai.nav.NavMeshData;
4 | import com.jzy.javalib.math.geometry.Vector3;
5 |
6 | import java.util.Map;
7 | import java.util.Set;
8 | import java.util.TreeMap;
9 | import java.util.TreeSet;
10 |
11 |
12 | /**
13 | * 多边形数据
14 | *
15 | * @author JiangZhiYong
16 | * @mail 359135103@qq.com
17 | */
18 | public class PolygonData extends NavMeshData {
19 | private static final long serialVersionUID = 1L;
20 |
21 | /** 多边形顶点序号, */
22 | private Map> pathPolygonIndexs;
23 |
24 | /**
25 | *
26 | * Unity的NavMeshData有一些共边的三角形,共边的三角形其实不是连通关系,
27 | * 共边的三角形只是他们共同构成一个凸多边形,并且这种共边的三角形,全部都是扇形排列。
28 | *
29 | *
30 | * 首先先以此划分,生成多边形列表。这个多边形列表,当然没有共边。
31 | *
32 | *
33 | * Unity的NavMeshData 那些不共边的多边形只是index索引不共边,从坐标上还是有共边的,所以我们合并掉重合顶点,重新排列多边形的index索引,就可以恢复到有共边的多边形列表和顶点列表
34 | *
35 | */
36 | @Override
37 | public void check(int scale) {
38 | scaleVector(pathVertices, scale);//地图坐标缩放计算
39 | pathPolygonIndexs=buildUnityPolygonIndex(this.pathTriangles);
40 | this.width = Math.abs(this.getEndX() - this.getStartX());
41 | this.height = Math.abs(this.getEndZ() - this.getStartZ());
42 | this.centerPsoition=new Vector3((endX-startX)/2, (endZ-startZ)/2);
43 | }
44 |
45 |
46 | /**
47 | * 构建多边形索引
48 | *
49 | * Unity的NavMeshData有一些共边的三角形,共边的三角形其实不是连通关系,
50 | * 共边的三角形只是他们共同构成一个凸多边形,并且这种共边的三角形,全部都是扇形排列。
51 | *
52 | * @param indexs
53 | * @return
54 | */
55 | private Map> buildUnityPolygonIndex(int[] indexs){
56 | Map> map=new TreeMap<>();
57 | int index=0;
58 | for(int i=0;i set=new TreeSet<>();
60 | set.add(indexs[i]);
61 | set.add(indexs[i+1]);
62 | set.add(indexs[i+2]);
63 | int jIndex=i+3;
64 | for(int j=jIndex;j> getPathPolygonIndexs() {
86 | return pathPolygonIndexs;
87 | }
88 |
89 |
90 | public void setPathPolygonIndexs(Map> pathPolygonIndexs) {
91 | this.pathPolygonIndexs = pathPolygonIndexs;
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/polygon/PolygonEdge.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.polygon;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.jzy.ai.pfa.Connection;
5 | import com.jzy.javalib.math.geometry.Vector3;
6 |
7 | /**
8 | * 多边形共享边
9 | * @author JiangZhiYong
10 | * @mail 359135103@qq.com
11 | */
12 | public class PolygonEdge implements Connection {
13 |
14 | /** 右顶点 */
15 | public Vector3 rightVertex;
16 | public Vector3 leftVertex;
17 |
18 | /** 源多边形*/
19 | public Polygon fromNode;
20 | /** 指向的多边形 */
21 | public Polygon toNode;
22 | /**两多边形中心点间的距离*/
23 | private float cost;
24 |
25 | public PolygonEdge(Polygon fromNode, Polygon toNode, Vector3 rightVertex, Vector3 leftVertex) {
26 | this.fromNode = fromNode;
27 | this.toNode = toNode;
28 | this.rightVertex = rightVertex;
29 | this.leftVertex = leftVertex;
30 | }
31 |
32 | @Override
33 | public float getCost() {
34 | if(cost==0) {
35 | cost=fromNode.center.dst(toNode.center);
36 | }
37 | return cost;
38 | }
39 |
40 | @Override
41 | public Polygon getFromNode() {
42 | return fromNode;
43 | }
44 |
45 | @Override
46 | public Polygon getToNode() {
47 | return toNode;
48 | }
49 |
50 | @Override
51 | public String toString() {
52 | return JSON.toJSONString(this);
53 | }
54 |
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/polygon/PolygonGraphPath.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.polygon;
2 |
3 |
4 | import com.jzy.ai.pfa.Connection;
5 | import com.jzy.ai.pfa.DefaultGraphPath;
6 | import com.jzy.javalib.math.geometry.Vector3;
7 |
8 | /**
9 | * 多边形路径点
10 | *
11 | * @author JiangZhiYong
12 | * @date 2018年2月20日
13 | * @mail 359135103@qq.com
14 | */
15 | public class PolygonGraphPath extends DefaultGraphPath> {
16 | public Vector3 start;
17 | public Vector3 end;
18 | public Polygon startPolygon;
19 |
20 | public Polygon getEndPolygon() {
21 | return (getCount() > 0) ? get(getCount() - 1).getToNode() : startPolygon;
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/polygon/PolygonHeuristic.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.polygon;
2 |
3 |
4 | import com.jzy.ai.pfa.Heuristic;
5 |
6 | /**
7 | * 多边形消耗计算
8 | *
9 | * @author JiangZhiYong
10 | * @date 2018年2月20日
11 | * @mail 359135103@qq.com
12 | */
13 | public class PolygonHeuristic implements Heuristic {
14 |
15 | @Override
16 | public float estimate(Polygon node, Polygon endNode) {
17 | // 多边形中点坐标距离 是否需要各个边的距离取最小值?
18 | return node.center.dst(endNode.center);
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/polygon/info.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 说明
6 |
7 |
8 | 该寻路方式采用多边形,漏斗算法进行寻路
9 | unity导出的寻路三角形需要自己转换为多边形
10 |
11 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/triangle/TriangleData.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.triangle;
2 |
3 |
4 | import com.jzy.ai.nav.NavMeshData;
5 |
6 | /**
7 | * 三角形数据
8 | * @author JiangZhiYong
9 | * @mail 359135103@qq.com
10 | */
11 | public class TriangleData extends NavMeshData {
12 | private static final long serialVersionUID = 1L;
13 |
14 | }
15 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/triangle/TriangleEdge.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.triangle;
2 |
3 |
4 | import com.jzy.ai.pfa.Connection;
5 | import com.jzy.javalib.math.geometry.Vector3;
6 |
7 | /**
8 | * 相连接三角形的共享边
9 | *
10 | * @author JiangZhiYong
11 | * @QQ 359135103 2017年11月7日 下午4:50:11
12 | */
13 | public class TriangleEdge implements Connection {
14 | /** 右顶点 */
15 | public Vector3 rightVertex;
16 | public Vector3 leftVertex;
17 |
18 | /** 源三角形 */
19 | public Triangle fromNode;
20 | /** 指向的三角形 */
21 | public Triangle toNode;
22 |
23 | public TriangleEdge(Vector3 rightVertex, Vector3 leftVertex) {
24 | this(null, null, rightVertex, leftVertex);
25 | }
26 |
27 | public TriangleEdge(Triangle fromNode, Triangle toNode, Vector3 rightVertex, Vector3 leftVertex) {
28 | this.fromNode = fromNode;
29 | this.toNode = toNode;
30 | this.rightVertex = rightVertex;
31 | this.leftVertex = leftVertex;
32 | }
33 |
34 | @Override
35 | public float getCost() {
36 | return 1;
37 | }
38 |
39 | @Override
40 | public Triangle getFromNode() {
41 | return fromNode;
42 | }
43 |
44 | @Override
45 | public Triangle getToNode() {
46 | return toNode;
47 | }
48 |
49 | @Override
50 | public String toString() {
51 | final StringBuffer sb = new StringBuffer("Edge{");
52 | sb.append("fromNode=").append(fromNode.index);
53 | sb.append(", toNode=").append(toNode == null ? "null" : toNode.index);
54 | sb.append(", rightVertex=").append(rightVertex);
55 | sb.append(", leftVertex=").append(leftVertex);
56 | sb.append('}');
57 | return sb.toString();
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/triangle/TriangleGraphPath.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.triangle;
2 | ///*******************************************************************************
3 | // * Copyright 2015 See AUTHORS file.
4 | // * Licensed under the Apache License, Version 2.0 (the "License");
5 | // * you may not use this file except in compliance with the License.
6 | // * You may obtain a copy of the License at
7 | // * http://www.apache.org/licenses/LICENSE-2.0
8 | // * Unless required by applicable law or agreed to in writing, software
9 | // * distributed under the License is distributed on an "AS IS" BASIS,
10 | // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | // * See the License for the specific language governing permissions and
12 | // * limitations under the License.
13 | // ******************************************************************************/
14 | //
15 | //package com.jzy.game.ai.nav;
16 |
17 | import com.jzy.ai.pfa.Connection;
18 | import com.jzy.ai.pfa.DefaultGraphPath;
19 | import com.jzy.javalib.math.geometry.Vector3;
20 |
21 | /**
22 | * 路径点
23 | * @author jsjolund
24 | */
25 | public class TriangleGraphPath extends DefaultGraphPath> {
26 | /**
27 | * The start point when generating a point path for this triangle path
28 | */
29 | public Vector3 start;
30 | /**
31 | * The end point when generating a point path for this triangle path
32 | */
33 | public Vector3 end;
34 | /**
35 | * If the triangle path is empty, the point path will span this triangle
36 | */
37 | public Triangle startTri;
38 |
39 | /**
40 | * @return Last triangle in the path.
41 | */
42 | public Triangle getEndTriangle() {
43 | return (getCount() > 0) ? get(getCount() - 1).getToNode() : startTri;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/triangle/TriangleHeuristic.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.triangle;
2 | ///*******************************************************************************
3 |
4 |
5 | // * Copyright 2015 See AUTHORS file.
6 | // * Licensed under the Apache License, Version 2.0 (the "License");
7 | // * you may not use this file except in compliance with the License.
8 | // * You may obtain a copy of the License at
9 | // * http://www.apache.org/licenses/LICENSE-2.0
10 | // * Unless required by applicable law or agreed to in writing, software
11 | // * distributed under the License is distributed on an "AS IS" BASIS,
12 | // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | // * See the License for the specific language governing permissions and
14 | // * limitations under the License.
15 | // ******************************************************************************/
16 | //
17 | //package com.jzy.game.ai.nav;
18 |
19 |
20 | import com.jzy.ai.pfa.Heuristic;
21 | import com.jzy.javalib.math.geometry.Vector3;
22 |
23 | /**navmesh 启发式消耗预估
24 | *
25 | * @author jsjolund
26 | */
27 | public class TriangleHeuristic implements Heuristic {
28 |
29 | private final static Vector3 A_AB = new Vector3();
30 | private final static Vector3 A_BC = new Vector3();
31 | private final static Vector3 A_CA = new Vector3();
32 | private final static Vector3 B_AB = new Vector3();
33 | private final static Vector3 B_BC = new Vector3();
34 | private final static Vector3 B_CA = new Vector3();
35 |
36 | /**
37 | * Estimates the distance between two triangles, by calculating the distance
38 | * between their edge midpoints.
39 | *
40 | * @param node
41 | * @param endNode
42 | * @return
43 | */
44 | @Override
45 | public float estimate(Triangle node, Triangle endNode) {
46 | float dst2;
47 | float minDst2 = Float.POSITIVE_INFINITY;
48 | A_AB.set(node.a).add(node.b).scl(0.5f);
49 | A_BC.set(node.b).add(node.c).scl(0.5f);
50 | A_CA.set(node.c).add(node.a).scl(0.5f);
51 |
52 | B_AB.set(endNode.a).add(endNode.b).scl(0.5f);
53 | B_BC.set(endNode.b).add(endNode.c).scl(0.5f);
54 | B_CA.set(endNode.c).add(endNode.a).scl(0.5f);
55 |
56 | if ((dst2 = A_AB.dst2(B_AB)) < minDst2)
57 | minDst2 = dst2;
58 | if ((dst2 = A_AB.dst2(B_BC)) < minDst2)
59 | minDst2 = dst2;
60 | if ((dst2 = A_AB.dst2(B_CA)) < minDst2)
61 | minDst2 = dst2;
62 |
63 | if ((dst2 = A_BC.dst2(B_AB)) < minDst2)
64 | minDst2 = dst2;
65 | if ((dst2 = A_BC.dst2(B_BC)) < minDst2)
66 | minDst2 = dst2;
67 | if ((dst2 = A_BC.dst2(B_CA)) < minDst2)
68 | minDst2 = dst2;
69 |
70 | if ((dst2 = A_CA.dst2(B_AB)) < minDst2)
71 | minDst2 = dst2;
72 | if ((dst2 = A_CA.dst2(B_BC)) < minDst2)
73 | minDst2 = dst2;
74 | if ((dst2 = A_CA.dst2(B_CA)) < minDst2)
75 | minDst2 = dst2;
76 |
77 | return (float) Math.sqrt(minDst2);
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/triangle/TriangleNavMesh.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.triangle;
2 | //package com.jzy.game.ai.nav;
3 |
4 | import com.alibaba.fastjson.JSON;
5 | import com.jzy.ai.nav.NavMesh;
6 | import com.jzy.ai.pfa.IndexedAStarPathFinder;
7 | import com.jzy.javalib.math.geometry.Vector3;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.util.List;
12 | import java.util.Optional;
13 |
14 | /**
15 | * 寻路网格
16 | *
17 | * TODO 获取不在寻路中,离当前点最近且在寻路层中的点;随机或者指定点的周围坐标点
18 | * @note 限制:三角形顶点需要在寻路层边缘,不能存在共边不共顶点
19 | * @author JiangZhiYong
20 | * @QQ 359135103 2017年11月7日 下午4:40:36
21 | */
22 | public class TriangleNavMesh extends NavMesh {
23 | private static final Logger LOGGER = LoggerFactory.getLogger(TriangleNavMesh.class);
24 |
25 | private final TriangleGraph graph; // 导航数据图
26 | private final TriangleHeuristic heuristic; // 寻路消耗计算
27 | private final IndexedAStarPathFinder pathFinder; // A*寻路算法
28 |
29 |
30 | public TriangleNavMesh(String navMeshStr) {
31 | this(navMeshStr,1);
32 | }
33 |
34 | /**
35 | *
36 | * @param navMeshStr
37 | * 导航网格数据
38 | * @param scale 放大倍数
39 | */
40 | public TriangleNavMesh(String navMeshStr,int scale) {
41 | graph = new TriangleGraph(JSON.parseObject(navMeshStr, TriangleData.class),scale);
42 | pathFinder = new IndexedAStarPathFinder(graph);
43 | heuristic = new TriangleHeuristic();
44 | }
45 |
46 | public TriangleGraph getGraph() {
47 | return graph;
48 | }
49 |
50 | public TriangleHeuristic getHeuristic() {
51 | return heuristic;
52 | }
53 |
54 | public IndexedAStarPathFinder getPathFinder() {
55 | return pathFinder;
56 | }
57 |
58 | /**
59 | * 查询路径
60 | *
61 | * @param fromPoint
62 | * @param toPoint
63 | * @param path
64 | */
65 | private boolean findPath(Vector3 fromPoint, Vector3 toPoint, TriangleGraphPath path) {
66 | path.clear();
67 | Triangle fromTriangle = getTriangle(fromPoint);
68 | if (pathFinder.searchConnectionPath(fromTriangle, getTriangle(toPoint), heuristic, path)) {
69 | path.start = new Vector3(fromPoint);
70 | path.end = new Vector3(toPoint);
71 | path.startTri = fromTriangle;
72 | return true;
73 | }
74 | return false;
75 | }
76 |
77 | /**
78 | * 获取路径
79 | *
80 | * @param fromPoint
81 | * @param toPoint
82 | * @param navMeshPointPath
83 | * @return
84 | */
85 | public List findPath(Vector3 fromPoint, Vector3 toPoint, TrianglePointPath navMeshPointPath) {
86 | TriangleGraphPath navMeshGraphPath = new TriangleGraphPath();
87 | boolean find = findPath(fromPoint, toPoint, navMeshGraphPath);
88 | if (!find) {
89 | return navMeshPointPath.getVectors();
90 | }
91 | navMeshPointPath.calculateForGraphPath(navMeshGraphPath, false);
92 | return navMeshPointPath.getVectors();
93 | }
94 |
95 |
96 | /**
97 | * 获取坐标点所在的三角形
98 | *
99 | * @note 很耗时,迭代所有三角形寻找
100 | * @param point
101 | * @return
102 | */
103 | public Triangle getTriangle(Vector3 point) {
104 | //TODO 高度判断,有可能有分层重叠多边形
105 | Optional optional = graph.getTriangles().stream().filter(t -> t.isInnerPoint(point)).findFirst();
106 | if (optional.isPresent()) {
107 | return optional.get();
108 | }
109 | return null;
110 | }
111 |
112 | /**
113 | * 或者在路径中的坐标点
114 | * 屏幕输入坐标点
115 | *
116 | * @param x
117 | * @param z
118 | * @return
119 | */
120 | public Vector3 getPointInPath(float x, float z) {
121 | Vector3 vector3 = new Vector3(x, z);
122 | Triangle triangle = getTriangle(vector3);
123 | if (triangle == null) {
124 | LOGGER.info("坐标{},{}不在路径中", x, z);
125 | return null;
126 | }
127 | vector3.y = triangle.y;
128 | return vector3;
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/triangle/info.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 说明
6 |
7 |
8 | 该寻路方式以边为关系,采用三角形漏斗算法进行寻路
9 | 限制条件
10 | 三角形顶点必须在行走层边缘
11 | 三角形共享边顶点坐标必须相同,不能存在包含关系
12 |
13 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/voronoi/Voronoi.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.nav.voronoi;
2 |
3 | /**
4 | * 泰森多边形
5 | *
6 | * 参考:http://blog.csdn.net/k346k346/article/details/52244123
7 | * @author JiangZhiYong
8 | * @mail 359135103@qq.com
9 | */
10 | public class Voronoi {
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/nav/voronoi/info.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 泰森多边形研究学习
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/pfa/Connection.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.pfa;
3 |
4 | /**
5 | * 连接关系
6 | * A connection between two nodes of the {@link Graph}. The connection has a
7 | * non-negative cost that often represents time or distance. However, the cost
8 | * can be anything you want, for instance a combination of time, distance, and
9 | * other factors.
10 | *
11 | * @param
12 | * Type of node
13 | *
14 | * @author davebaol
15 | */
16 | public interface Connection {
17 |
18 | /**通过消耗
19 | * Returns the non-negative cost of this connection */
20 | public float getCost();
21 |
22 | /** Returns the node that this connection came from */
23 | public N getFromNode();
24 |
25 | /** Returns the node that this connection leads to */
26 | public N getToNode();
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/pfa/DefaultGraphPath.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.pfa;
3 |
4 | import java.util.ArrayList;
5 | import java.util.Collections;
6 | import java.util.Iterator;
7 | import java.util.List;
8 |
9 | /**
10 | * 默认图路径
11 | *
12 | * Default implementation of a {@link GraphPath} that uses an internal
13 | * {@link ArrayList} to store nodes or connections.
14 | *
15 | * @param
16 | * Type of node
17 | *
18 | * @author davebaol
19 | */
20 | public class DefaultGraphPath implements GraphPath {
21 | public final List nodes;
22 |
23 | /** Creates a {@code DefaultGraphPath} with no nodes. */
24 | public DefaultGraphPath() {
25 | this(new ArrayList());
26 | }
27 |
28 | /** Creates a {@code DefaultGraphPath} with the given capacity and no nodes. */
29 | public DefaultGraphPath(int capacity) {
30 | this(new ArrayList(capacity));
31 | }
32 |
33 | /** Creates a {@code DefaultGraphPath} with the given nodes. */
34 | public DefaultGraphPath(ArrayList nodes) {
35 | this.nodes = nodes;
36 | }
37 |
38 | @Override
39 | public void clear() {
40 | nodes.clear();
41 | }
42 |
43 | @Override
44 | public int getCount() {
45 | return nodes.size();
46 | }
47 |
48 | @Override
49 | public void add(N node) {
50 | nodes.add(node);
51 | }
52 |
53 | @Override
54 | public N get(int index) {
55 | return nodes.get(index);
56 | }
57 |
58 | @Override
59 | public void reverse() {
60 | Collections.reverse(nodes);
61 | }
62 |
63 | @Override
64 | public Iterator iterator() {
65 | return nodes.iterator();
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/pfa/Graph.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.pfa;
3 |
4 | import java.util.List;
5 |
6 | /**
7 | * 图接口
8 | *
9 | * A graph is a collection of nodes, each one having a collection of
10 | * outgoing {@link Connection connections}.
11 | *
12 | * @param
13 | * Type of node
14 | *
15 | * @author davebaol
16 | */
17 | public interface Graph {
18 |
19 | /**和当前节点相连的连接关系
20 | * Returns the connections outgoing from the given node.
21 | *
22 | * @param fromNode
23 | * the node whose outgoing connections will be returned
24 | * @return the array of connections outgoing from the given node.
25 | */
26 | public List> getConnections(N fromNode);
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/pfa/GraphPath.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.pfa;
3 |
4 | /**图路径
5 | *
6 | * A {@code GraphPath} represents a path in a {@link Graph}. Note that a path can be defined in terms of nodes or
7 | * {@link Connection connections} so that multiple edges between the same pair of nodes can be discriminated.
8 | *
9 | * @param Type of node
10 | *
11 | * @author davebaol */
12 | public interface GraphPath extends Iterable {
13 |
14 | /** Returns the number of items of this path. */
15 | public int getCount ();
16 |
17 | /** Returns the item of this path at the given index. */
18 | public N get (int index);
19 |
20 | /** Adds an item at the end of this path. */
21 | public void add (N node);
22 |
23 | /** Clears this path. */
24 | public void clear ();
25 |
26 | /** Reverses this path. */
27 | public void reverse ();
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/pfa/Heuristic.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.pfa;
3 |
4 | /**
5 | * 消耗计算接口
6 | *
7 | * A {@code Heuristic} generates estimates of the cost to move from a given node to the goal.
8 | *
9 | * With a heuristic function pathfinding algorithms can choose the node that is most likely to lead to the optimal path. The
10 | * notion of "most likely" is controlled by a heuristic. If the heuristic is accurate, then the algorithm will be efficient. If
11 | * the heuristic is terrible, then it can perform even worse than other algorithms that don't use any heuristic function such as
12 | * Dijkstra.
13 | *
14 | * @param Type of node
15 | *
16 | * @author davebaol */
17 | public interface Heuristic {
18 |
19 | /** Calculates an estimated cost to reach the goal node from the given node.
20 | * 计算从给定节点到达目标节点的估计成本
21 | * @param node the start node
22 | * @param endNode the end node
23 | * @return the estimated cost */
24 | public float estimate (N node, N endNode);
25 | }
26 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/pfa/IndexedGraph.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.pfa;
3 |
4 |
5 | /**A*算法索引图
6 | *
7 | * A graph for the {@link IndexedAStarPathFinder}.
8 | *
9 | * @param Type of node
10 | *
11 | * @author davebaol */
12 | public interface IndexedGraph extends Graph {
13 |
14 | /** Returns the unique index of the given node.
15 | * @param node the node whose index will be returned
16 | * @return the unique index of the given node. */
17 | public int getIndex (N node);
18 |
19 | /** Returns the number of nodes in this graph. */
20 | public int getNodeCount ();
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/pfa/PathFinder.java:
--------------------------------------------------------------------------------
1 |
2 | package com.jzy.ai.pfa;
3 |
4 | /**
5 | * 寻路接口
6 | *
7 | * A {@code PathFinder} that can find a {@link GraphPath path} from one node in
8 | * an arbitrary {@link Graph graph} to a goal node based on information provided
9 | * by that graph.
10 | *
11 | * A fully implemented path finder can perform both interruptible and
12 | * non-interruptible searches. If a specific path finder is not able to perform
13 | * one of the two type of search then the corresponding method should throw an
14 | * {@link UnsupportedOperationException}.
15 | *
16 | * @param
17 | * Type of node
18 | *
19 | * @author davebaol
20 | */
21 | public interface PathFinder {
22 |
23 | /**查找连接关系
24 | * Performs a non-interruptible search, trying to find a path made up of
25 | * connections from the start node to the goal node attempting to honor costs
26 | * provided by the graph.
27 | *
28 | * @param startNode
29 | * the start node
30 | * @param endNode
31 | * the end node
32 | * @param heuristic
33 | * the heuristic function
34 | * @param outPath
35 | * the output path that will only be filled if a path is found,
36 | * otherwise it won't get touched.
37 | * @return {@code true} if a path was found; {@code false} otherwise.
38 | */
39 | public boolean searchConnectionPath(N startNode, N endNode, Heuristic heuristic,
40 | GraphPath> outPath);
41 |
42 | /**查找连接的节点
43 | *
44 | * Performs a non-interruptible search, trying to find a path made up of nodes
45 | * from the start node to the goal node attempting to honor costs provided by
46 | * the graph.
47 | *
48 | * @param startNode
49 | * the start node
50 | * @param endNode
51 | * the end node
52 | * @param heuristic
53 | * the heuristic function
54 | * @param outPath
55 | * the output path that will only be filled if a path is found,
56 | * otherwise it won't get touched.
57 | * @return {@code true} if a path was found; {@code false} otherwise.
58 | */
59 | public boolean searchNodePath(N startNode, N endNode, Heuristic heuristic, GraphPath outPath);
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/quadtree/Data.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.quadtree;
2 |
3 | /**
4 | * 数据
5 | * @author JiangZhiYong
6 | * @mail 359135103@qq.com
7 | */
8 | public abstract class Data implements Comparable>{
9 |
10 | private T value;
11 |
12 | public Data(T value) {
13 | super();
14 | this.value = value;
15 | }
16 |
17 | /**
18 | * 获取数据
19 | * @return
20 | */
21 | public T getValue() {
22 | return value;
23 | }
24 |
25 | public void setValue(T value) {
26 | this.value = value;
27 | }
28 |
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/quadtree/Func.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.quadtree;
2 |
3 |
4 | import com.jzy.ai.nav.polygon.Polygon;
5 | import com.jzy.ai.quadtree.polygon.PolygonGuadTree;
6 |
7 | /**
8 | * 功能函数
9 | *
10 | * @author JiangZhiYong
11 | * @mail 359135103@qq.com
12 | * @param
13 | */
14 | public interface Func {
15 | // public default void call(PointQuadTree quadTree, Node node) {
16 | //
17 | // }
18 |
19 | public default void call(PolygonGuadTree quadTree, Node node) {
20 |
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/jzy/ai/quadtree/Node.java:
--------------------------------------------------------------------------------
1 | package com.jzy.ai.quadtree;
2 |
3 | import java.util.ArrayList;
4 | import java.util.List;
5 |
6 | import com.jzy.ai.nav.polygon.Polygon;
7 | import com.jzy.javalib.math.geometry.Vector3;
8 |
9 |
10 | /**
11 | * 节点
12 | *
13 | * @author JiangZhiYong
14 | * @mail 359135103@qq.com
15 | */
16 | public class Node {
17 | private float x;
18 | private float z;
19 | private float w;
20 | private float h;
21 | private Node parent;
22 | private NodeType nodeType = NodeType.EMPTY;
23 | private Node nw;
24 | private Node ne;
25 | private Node sw;
26 | private Node se;
27 | private Data data;
28 | private List> datas;
29 | // 当前深度
30 | private int depth = 1;
31 | // 多边形
32 | private Polygon polygon;
33 |
34 | public Node(float x, float z, float w, float h, Node parent) {
35 | this(x, z, w, h, parent, 0);
36 | }
37 |
38 | public Node(float x, float z, float w, float h, Node parent, int depth) {
39 | super();
40 | this.x = x;
41 | this.z = z;
42 | this.w = w;
43 | this.h = h;
44 | this.parent = parent;
45 | this.depth = depth;
46 | this.polygon = new Polygon(0, new Vector3(x, z), new Vector3(x, z + h), new Vector3(x + w, z + h),
47 | new Vector3(x + w, z));
48 | }
49 |
50 | public float getX() {
51 | return x;
52 | }
53 |
54 | public void setX(float x) {
55 | this.x = x;
56 | }
57 |
58 | public float getZ() {
59 | return z;
60 | }
61 |
62 | public void setZ(float z) {
63 | this.z = z;
64 | }
65 |
66 | public float getW() {
67 | return w;
68 | }
69 |
70 | public void setW(float w) {
71 | this.w = w;
72 | }
73 |
74 | public float getH() {
75 | return h;
76 | }
77 |
78 | public void setH(float h) {
79 | this.h = h;
80 | }
81 |
82 | public Node getParent() {
83 | return parent;
84 | }
85 |
86 | public void setParent(Node parent) {
87 | this.parent = parent;
88 | }
89 |
90 | public NodeType getNodeType() {
91 | return nodeType;
92 | }
93 |
94 | public void setNodeType(NodeType nodeType) {
95 | this.nodeType = nodeType;
96 | }
97 |
98 | public Node