├── .gitignore ├── 1.navmesh ├── 101.navmesh ├── README.md ├── pom.xml └── src └── main └── java └── com └── jzy └── ai ├── btree ├── BehaviorTree.java ├── BehaviorTree.xsd ├── BehaviorTreeConstants.java ├── BehaviorTreeManager.java ├── BranchTask.java ├── Decorator.java ├── LeafTask.java ├── LoopDecorator.java ├── SingleRunningChildBranch.java ├── Task.java ├── annotation │ ├── TaskAttribute.java │ └── TaskConstraint.java ├── branch │ ├── DynamicGuardSelector.java │ ├── Parallel.java │ ├── RandomSelector.java │ ├── RandomSequence.java │ ├── ScoreSelector.java │ ├── Selector.java │ └── Sequence.java ├── decorator │ ├── AlwaysFail.java │ ├── AlwaysSucceed.java │ ├── Invert.java │ ├── Random.java │ ├── Repeat.java │ ├── SemaphoreGuard.java │ ├── UntilFail.java │ └── UntilSuccess.java └── leaf │ ├── Failure.java │ ├── Success.java │ └── Wait.java ├── fma ├── BoundedSlotAssignmentStrategy.java ├── Formation.java ├── FormationMember.java ├── FormationMotionModerator.java ├── FormationPattern.java ├── FreeSlotAssignmentStrategy.java ├── SlotAssignment.java ├── SlotAssignmentStrategy.java ├── SoftRoleSlotAssignmentStrategy.java └── patterns │ ├── DefensiveCircleFormationPattern.java │ └── OffensiveCircleFormationPattern.java ├── fsm ├── DefaultStateMachine.java ├── StackStateMachine.java ├── State.java └── StateMachine.java ├── msg ├── MessageDispatcher.java ├── MessageManager.java ├── Telegram.java ├── TelegramProvider.java └── Telegraph.java ├── nav ├── NavMesh.java ├── NavMeshData.java ├── polygon │ ├── Polygon.java │ ├── PolygonData.java │ ├── PolygonEdge.java │ ├── PolygonGraph.java │ ├── PolygonGraphPath.java │ ├── PolygonHeuristic.java │ ├── PolygonNavMesh.java │ ├── PolygonPointPath.java │ ├── info.html │ └── ui │ │ ├── MovePlayer.java │ │ ├── PolygonMeshWindow.java │ │ ├── PolygonNavStart.form │ │ ├── PolygonNavStart.java │ │ └── PolygonViewPane.java ├── triangle │ ├── Triangle.java │ ├── TriangleData.java │ ├── TriangleEdge.java │ ├── TriangleGraph.java │ ├── TriangleGraphPath.java │ ├── TriangleHeuristic.java │ ├── TriangleNavMesh.java │ ├── TrianglePointPath.java │ ├── info.html │ └── ui │ │ ├── TriangleNavMeshWindow.java │ │ ├── TriangleNavStart.form │ │ ├── TriangleNavStart.java │ │ ├── TrianglePlayer.java │ │ └── TriangleViewPane.java └── voronoi │ ├── DelaunayTriangle.java │ ├── Voronoi.java │ └── info.html ├── pfa ├── Connection.java ├── DefaultGraphPath.java ├── Graph.java ├── GraphPath.java ├── Heuristic.java ├── IndexedAStarPathFinder.java ├── IndexedGraph.java ├── NodeBinaryHeap.java └── PathFinder.java ├── quadtree ├── Data.java ├── Func.java ├── Node.java ├── NodeType.java ├── QuadTree.java ├── QuadTreeException.java ├── point │ └── PointData.java └── polygon │ └── PolygonGuadTree.java ├── steer ├── GroupBehavior.java ├── Limiter.java ├── Proximity.java ├── Steerable.java ├── SteerableAdapter.java ├── SteeringAcceleration.java ├── SteeringBehavior.java ├── behaviors │ ├── Alignment.java │ ├── Arrive.java │ ├── BlendedSteering.java │ ├── Cohesion.java │ ├── CollisionAvoidance.java │ ├── Evade.java │ ├── Face.java │ ├── Flee.java │ ├── FollowFlowField.java │ ├── FollowPath.java │ ├── Hide.java │ ├── Interpose.java │ ├── Jump.java │ ├── LookWhereYouAreGoing.java │ ├── MatchVelocity.java │ ├── PrioritySteering.java │ ├── Pursue.java │ ├── RaycastObstacleAvoidance.java │ ├── ReachOrientation.java │ ├── Seek.java │ ├── Separation.java │ └── Wander.java ├── limiters │ ├── AngularAccelerationLimiter.java │ ├── AngularLimiter.java │ ├── AngularSpeedLimiter.java │ ├── FullLimiter.java │ ├── LinearAccelerationLimiter.java │ ├── LinearLimiter.java │ ├── LinearSpeedLimiter.java │ └── NullLimiter.java ├── proximities │ ├── FieldOfViewProximity.java │ ├── InfiniteProximity.java │ ├── ProximityBase.java │ └── RadiusProximity.java └── util │ ├── Path.java │ ├── RayConfiguration.java │ ├── paths │ └── LinePath.java │ └── rays │ ├── CentralRayWithWhiskersConfiguration.java │ ├── ParallelSideRayConfiguration.java │ ├── RayConfigurationBase.java │ └── SingleRayConfiguration.java └── util ├── ArithmeticUtils.java ├── Collision.java ├── IMemoryObject.java ├── Location.java ├── MemoryPool.java ├── NonBlockingSemaphore.java ├── NonBlockingSemaphoreRepository.java ├── Ray.java ├── RaycastCollisionDetector.java └── SimpleNonBlockingSemaphore.java /.gitignore: -------------------------------------------------------------------------------- 1 | # java文件 2 | *.class 3 | *.jar 4 | *.log 5 | *.war 6 | *.zip 7 | *.tar.gz 8 | *.rar 9 | 10 | 11 | # ide工具文件 12 | .classpath 13 | .project 14 | .settings 15 | /.idea/ 16 | *.iml 17 | *~ 18 | .DS_Store 19 | 20 | 21 | # 项目文件 22 | log/ 23 | target/ 24 | **/target/ 25 | 26 | 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GameAI4j 2 | ### Description 3 |     Modified based on GDX-AI,Client for Unity,backend for java game server.Add extra features: 4 | * [Behavior-tree xml config](https://github.com/jzyong/GameAI4j/tree/main/src/main/java/com/jzy/ai/btree) 5 | * [Unity navmesh polygon or triangle pathfinding](https://github.com/jzyong/GameAI4j/tree/main/src/main/java/com/jzy/ai/nav) 6 | * [Quad-tree coordinate spatial query](https://github.com/jzyong/GameAI4j/tree/main/src/main/java/com/jzy/ai/quadtree) 7 | * [NavMesh Java desktop preview and operation](https://github.com/jzyong/GameAI4j/tree/main/src/main/java/com/jzy/ai/nav/polygon/ui) 8 | * [Unity Navmesh export plugin-in](https://github.com/jzyong/NavMeshDemo) 9 | 10 | 11 | 12 | ### Installation 13 | 14 | 15 | com.jzy.ai 16 | game-ai-4j 17 | 0.0.1 18 | 19 | 20 | ### Document 21 | * [Unity export NavMesh](https://github.com/jzyong/NavMeshDemo/blob/master/Documents/Guide.md) 22 | * Video presentation [YouTube](https://youtu.be/xT1FImnYk-E)    [B站](https://www.bilibili.com/video/BV19pmiYSEDX) 23 | * [Game presentation](https://www.bilibili.com/video/BV1Kv411a7yk) 24 | 25 | ### TODO 26 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.jzy.ai 8 | game-ai-4j 9 | 0.0.1 10 | jar 11 | 12 | 13 | UTF-8 14 | 17 15 | 17 16 | 17 17 | true 18 | 19 | 20 | 21 | 22 | com.jzy.javalib 23 | javalib-math 24 | 0.0.7 25 | 26 | 27 | org.dom4j 28 | dom4j 29 | 2.1.3 30 | 31 | 32 | com.alibaba 33 | fastjson 34 | 1.2.83 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | maven-compiler-plugin 43 | 3.10.0 44 | 45 | 46 | org.apache.maven.plugins 47 | maven-jar-plugin 48 | 3.4.2 49 | 50 | 51 | org.apache.maven.plugins 52 | maven-dependency-plugin 53 | 3.2.0 54 | 55 | 56 | 57 | 58 | 59 | maven-compiler-plugin 60 | 61 | 17 62 | 17 63 | 64 | 65 | 66 | org.apache.maven.plugins 67 | maven-jar-plugin 68 | 69 | 70 | 71 | true 72 | lib/ 73 | com.jzy.ai.nav.polygon.ui.PolygonNavStart 74 | 75 | 76 | 77 | 78 | 79 | org.apache.maven.plugins 80 | maven-dependency-plugin 81 | 82 | 83 | copy 84 | package 85 | 86 | copy-dependencies 87 | 88 | 89 | 90 | ${project.build.directory}/lib 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | github 102 | GitHub jzyong Apache Maven Packages 103 | https://maven.pkg.github.com/jzyong/GameAI4j 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/BehaviorTreeConstants.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.btree; 2 | 3 | /** 4 | * 行为树常量 5 | * 6 | * @author JiangZhiYong 7 | * @mail 359135103@qq.com 8 | * 9 | */ 10 | public class BehaviorTreeConstants { 11 | 12 | /** xml根节点 */ 13 | public static final String XML_ROOT = "Root"; 14 | 15 | /** 描述节点 */ 16 | public static final String XML_INFO = "Info"; 17 | 18 | /** id标识节点 */ 19 | public static final String XML_ID = "Id"; 20 | 21 | /** 行为树标识节点 */ 22 | public static final String XML_TREE = "Tree"; 23 | 24 | /** 选择器标识节点 */ 25 | public static final String XML_SELECTOR = "Selector"; 26 | 27 | /** 随机选择器标识节点 */ 28 | public static final String XML_RANDOM_SELECTOR = "RandomSelector"; 29 | 30 | /** 顺序执行标识节点 */ 31 | public static final String XML_SEQUENCE = "Sequence"; 32 | 33 | /** 随机顺序执行标识节点 */ 34 | public static final String XML_RANDOM_SEQUENCE = "RandomSequence"; 35 | 36 | /** 并行执行标识节点 */ 37 | public static final String XML_PARALLEL = "Parallel"; 38 | 39 | /** 防御节点标识 */ 40 | public static final String XML_GUARD = "Guard"; 41 | 42 | /** 叶子节点标识 */ 43 | public static final String XML_LEAF = "Leaf"; 44 | 45 | /** 直接失败节点标识 */ 46 | public static final String XML_ALWAYS_FAIL = "AlwaysFail"; 47 | 48 | /** 直接成功节点标识 */ 49 | public static final String XML_ALWAYS_SUCCEED = "AlwaysSucceed"; 50 | 51 | /** 颠倒结果节点标识 */ 52 | public static final String XML_INVERT = "Invert"; 53 | 54 | /** 重复执行指定次数节点标识 */ 55 | public static final String XML_REPEAT = "Repeat"; 56 | 57 | /** 任务信号量节点标识 */ 58 | public static final String XML_SEAMPHORE_GUARD = "SemaphoreGuard"; 59 | 60 | /** 一直到到失败节点标识 */ 61 | public static final String XML_UNTIL_FAIL = "UntilFail"; 62 | 63 | /** 一直到成功节点标识 */ 64 | public static final String XML_UNTIL_SUCCESS = "UntilSuccess"; 65 | 66 | /** 随机节点标识 */ 67 | public static final String XML_RANDOM = "Random"; 68 | 69 | /** xml name属性 */ 70 | public static final String XML_ATTRIBUTE_NAME = "name"; 71 | 72 | /** xml class属性 */ 73 | public static final String XML_ATTRIBUTE_CLASS = "class"; 74 | 75 | /** xml policy属性 */ 76 | public static final String XML_ATTRIBUTE_POLICY = "policy"; 77 | 78 | /** xml orchestrator属性 */ 79 | public static final String XML_ATTRIBUTE_ORCHESTRATOR = "orchestrator"; 80 | 81 | /** xml times属性 */ 82 | public static final String XML_ATTRIBUTE_TIMES = "times"; 83 | 84 | /** xml success属性 */ 85 | public static final String XML_ATTRIBUTE_SUCCESS = "success"; 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/BranchTask.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; 18 | 19 | import com.jzy.ai.btree.annotation.TaskConstraint; 20 | 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | 25 | 26 | /** 27 | * 分支任务节点
28 | * A branch task defines a behavior tree branch, contains logic of starting or 29 | * running sub-branches and leaves 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 | @TaskConstraint(minChildren = 1) 39 | public abstract class BranchTask extends Task { 40 | 41 | /** The children of this branch task. */ 42 | protected List> children; 43 | 44 | /** Create a branch task with no children */ 45 | public BranchTask() { 46 | this(new ArrayList<>()); 47 | } 48 | 49 | /** 50 | * Create a branch task with a list of children 51 | * 52 | * @param tasks 53 | * list of this task's children, can be empty 54 | */ 55 | public BranchTask(List> tasks) { 56 | this.children = tasks; 57 | } 58 | 59 | @Override 60 | protected int addChildToTask(Task child) { 61 | children.add(child); 62 | return children.size() - 1; 63 | } 64 | 65 | @Override 66 | public int getChildCount() { 67 | return children.size(); 68 | } 69 | 70 | @Override 71 | public Task getChild(int i) { 72 | return children.get(i); 73 | } 74 | 75 | @Override 76 | public void release() { 77 | children.clear(); 78 | super.release(); 79 | } 80 | 81 | } 82 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/Decorator.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; 18 | 19 | 20 | import com.jzy.ai.btree.annotation.TaskConstraint; 21 | 22 | /** 23 | * 装饰模式任务
24 | * 25 | * A {@code Decorator} is a wrapper that provides custom behavior for its child. 26 | * The child can be of any kind (branch task, leaf task, or another decorator). 27 | * 28 | * @param 29 | * type of the blackboard object that tasks use to read or modify 30 | * game state 31 | * 32 | * @author implicit-invocation 33 | * @author davebaol 34 | */ 35 | @TaskConstraint(minChildren = 1, maxChildren = 1) 36 | public abstract class Decorator extends Task { 37 | 38 | /** The child task wrapped by this decorator */ 39 | protected Task child; 40 | 41 | /** Creates a decorator with no child task. */ 42 | public Decorator() { 43 | } 44 | 45 | /** 46 | * Creates a decorator that wraps the given task. 47 | * 48 | * @param child 49 | * the task that will be wrapped 50 | */ 51 | public Decorator(Task child) { 52 | this.child = child; 53 | } 54 | 55 | @Override 56 | protected int addChildToTask(Task child) { 57 | if (this.child != null) 58 | throw new IllegalStateException("A decorator task cannot have more than one child"); 59 | this.child = child; 60 | return 0; 61 | } 62 | 63 | @Override 64 | public int getChildCount() { 65 | return child == null ? 0 : 1; 66 | } 67 | 68 | @Override 69 | public Task getChild(int i) { 70 | if (i == 0 && child != null) { 71 | return child; 72 | } 73 | throw new IndexOutOfBoundsException("index can't be >= size: " + i + " >= " + getChildCount()); 74 | } 75 | 76 | @Override 77 | public void run() { 78 | if (child.status == Status.RUNNING) { 79 | child.run(); 80 | } else { 81 | child.setControl(this); 82 | child.start(); 83 | if (child.checkGuard(this)) { 84 | child.run(); 85 | } else { 86 | child.fail(); 87 | } 88 | } 89 | } 90 | 91 | @Override 92 | public void childRunning(Task runningTask, Task reporter) { 93 | running(); 94 | } 95 | 96 | @Override 97 | public void childFail(Task runningTask) { 98 | fail(); 99 | } 100 | 101 | @Override 102 | public void childSuccess(Task runningTask) { 103 | success(); 104 | } 105 | 106 | @Override 107 | public void release() { 108 | child = null; 109 | super.release(); 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/LeafTask.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; 18 | 19 | 20 | import com.jzy.ai.btree.annotation.TaskConstraint; 21 | 22 | /** 23 | * 叶子节点任务
24 | * A {@code LeafTask} is a terminal task of a behavior tree, contains action or 25 | * condition logic, can not have any child. 26 | * 27 | * @param 28 | * type of the blackboard object that tasks use to read or modify 29 | * game state 30 | * 31 | * @author implicit-invocation 32 | * @author davebaol 33 | * @fix JiangZhiYong 34 | */ 35 | @TaskConstraint(minChildren = 0, maxChildren = 0) 36 | public abstract class LeafTask extends Task { 37 | 38 | /** Creates a leaf task. */ 39 | public LeafTask() { 40 | } 41 | 42 | /** 43 | * This method contains the update logic of this leaf task. The actual 44 | * implementation MUST return one of {@link Status#RUNNING} , 45 | * {@link Status#SUCCEEDED} or {@link Status#FAILED}. Other return values will 46 | * cause an {@code IllegalStateException}. 47 | * 48 | * @return the status of this leaf task 49 | */ 50 | public abstract Status execute(); 51 | 52 | /** 53 | * This method contains the update logic of this task. The implementation 54 | * delegates the {@link #execute()} method. 55 | */ 56 | @Override 57 | public final void run() { 58 | Status result = execute(); 59 | if (result == null) { 60 | throw new IllegalStateException("Invalid status 'null' returned by the execute method"); 61 | } 62 | switch (result) { 63 | case SUCCEEDED: 64 | success(); 65 | return; 66 | case FAILED: 67 | fail(); 68 | return; 69 | case RUNNING: 70 | running(); 71 | return; 72 | default: 73 | throw new IllegalStateException("Invalid status '" + result.name() + "' returned by the execute method"); 74 | } 75 | } 76 | 77 | /** 78 | * Always throws {@code IllegalStateException} because a leaf task cannot have 79 | * any children. 80 | */ 81 | @Override 82 | protected int addChildToTask(Task child) { 83 | throw new IllegalStateException("A leaf task cannot have any children"); 84 | } 85 | 86 | @Override 87 | public int getChildCount() { 88 | return 0; 89 | } 90 | 91 | @Override 92 | public Task getChild(int i) { 93 | throw new IndexOutOfBoundsException("A leaf task can not have any child"); 94 | } 95 | 96 | @Override 97 | public final void childRunning(Task runningTask, Task reporter) { 98 | } 99 | 100 | @Override 101 | public final void childFail(Task runningTask) { 102 | } 103 | 104 | @Override 105 | public final void childSuccess(Task runningTask) { 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/LoopDecorator.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; 18 | 19 | /** 20 | * 循环装饰模式
21 | * {@code LoopDecorator} is an abstract class providing basic functionalities 22 | * for concrete looping decorators. 23 | * 24 | * @param 25 | * type of the blackboard object that tasks use to read or modify 26 | * game state 27 | * 28 | * @author davebaol 29 | * @fix JiangZhiYong 30 | */ 31 | public abstract class LoopDecorator extends Decorator { 32 | 33 | /** Whether the {@link #run()} method must keep looping or not. */ 34 | protected boolean loop; 35 | 36 | /** Creates a loop decorator with no child task. */ 37 | public LoopDecorator() { 38 | } 39 | 40 | /** 41 | * Creates a loop decorator that wraps the given task. 42 | * 43 | * @param child 44 | * the task that will be wrapped 45 | */ 46 | public LoopDecorator(Task child) { 47 | super(child); 48 | } 49 | 50 | /** 51 | * Whether the {@link #run()} method must keep looping or not. 52 | * 53 | * @return {@code true} if it must keep looping; {@code false} otherwise. 54 | */ 55 | public boolean condition() { 56 | return loop; 57 | } 58 | 59 | @Override 60 | public void run() { 61 | loop = true; 62 | while (condition()) { 63 | if (child.status == Status.RUNNING) { 64 | child.run(); 65 | } else { 66 | child.setControl(this); 67 | child.start(); 68 | if (child.checkGuard(this)) 69 | child.run(); 70 | else 71 | child.fail(); 72 | } 73 | } 74 | } 75 | 76 | @Override 77 | public void childRunning(Task runningTask, Task reporter) { 78 | super.childRunning(runningTask, reporter); 79 | loop = false; 80 | } 81 | 82 | @Override 83 | public void release() { 84 | loop = false; 85 | super.release(); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/annotation/TaskAttribute.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.annotation; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | /** 25 | * This field level annotation defines a task attribute. 26 | * 27 | * @author davebaol 28 | */ 29 | @Retention(RetentionPolicy.RUNTIME) 30 | @Target(ElementType.FIELD) 31 | public @interface TaskAttribute { 32 | 33 | /** 34 | * Specifies the attribute's name; if empty the name of the field is used 35 | * instead. 36 | * 37 | * @return the attribute's name or an empty string if the name of the field must 38 | * be used. 39 | */ 40 | public String name() default ""; 41 | 42 | /** 43 | * Specifies whether the attribute is required or not. 44 | * 45 | * @return {@code true} if the attribute is required; {@code false} if it is 46 | * optional. 47 | */ 48 | public boolean required() default false; 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/annotation/TaskConstraint.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.annotation; 18 | 19 | import java.lang.annotation.Documented; 20 | import java.lang.annotation.ElementType; 21 | import java.lang.annotation.Inherited; 22 | import java.lang.annotation.Retention; 23 | import java.lang.annotation.RetentionPolicy; 24 | import java.lang.annotation.Target; 25 | 26 | /** 27 | * This annotation specifies how many children the task can have. It is applied 28 | * to the task class. 29 | * 30 | * @author davebaol 31 | */ 32 | @Retention(RetentionPolicy.RUNTIME) 33 | @Target(ElementType.TYPE) 34 | @Inherited 35 | @Documented 36 | public @interface TaskConstraint { 37 | 38 | /** 39 | * Returns the minimum number of allowed children, defaults to 0. 40 | * 41 | * @return the minimum number of allowed children. 42 | */ 43 | public int minChildren() default 0; 44 | 45 | /** 46 | * Returns the maximum number of allowed children, defaults to 47 | * {@code Integer.MAX_VALUE}. 48 | * 49 | * @return the maximum number of allowed children. 50 | */ 51 | public int maxChildren() default Integer.MAX_VALUE; 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/branch/DynamicGuardSelector.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.branch; 18 | 19 | import com.jzy.ai.btree.BranchTask; 20 | import com.jzy.ai.btree.Task; 21 | 22 | import java.util.Arrays; 23 | import java.util.List; 24 | 25 | 26 | /** 27 | * A {@code DynamicGuardSelector} is a branch task that executes the first child 28 | * whose guard is evaluated to {@code true}. At every AI cycle, the children's 29 | * guards are re-evaluated, so if the guard of the running child is evaluated to 30 | * {@code false}, it is cancelled, and the child with the highest priority 31 | * starts running. The {@code DynamicGuardSelector} task finishes when no guard 32 | * is evaluated to {@code true} (thus failing) or when its active child finishes 33 | * (returning the active child's termination status). 34 | * 35 | * @param 36 | * type of the blackboard object that tasks use to read or modify 37 | * game state 38 | * 39 | * @author davebaol 40 | */ 41 | public class DynamicGuardSelector extends BranchTask { 42 | 43 | /** The child in the running status or {@code null} if no child is running. */ 44 | protected Task runningChild; 45 | 46 | /** Creates a {@code DynamicGuardSelector} branch with no children. */ 47 | public DynamicGuardSelector() { 48 | super(); 49 | } 50 | 51 | /** 52 | * Creates a {@code DynamicGuardSelector} branch with the given children. 53 | * 54 | * @param tasks 55 | * the children of this task 56 | */ 57 | @SuppressWarnings("unchecked") 58 | public DynamicGuardSelector(Task... tasks) { 59 | super(Arrays.asList(tasks)); 60 | } 61 | 62 | /** 63 | * Creates a {@code DynamicGuardSelector} branch with the given children. 64 | * 65 | * @param tasks 66 | * the children of this task 67 | */ 68 | public DynamicGuardSelector(List> tasks) { 69 | super(tasks); 70 | } 71 | 72 | @Override 73 | public void childRunning(Task task, Task reporter) { 74 | runningChild = task; 75 | running(); // Return a running status when a child says it's running 76 | } 77 | 78 | @Override 79 | public void childSuccess(Task task) { 80 | this.runningChild = null; 81 | success(); 82 | } 83 | 84 | @Override 85 | public void childFail(Task task) { 86 | this.runningChild = null; 87 | fail(); 88 | } 89 | 90 | @Override 91 | public void run() { 92 | // Check guards 93 | Task childToRun = null; 94 | for (int i = 0, n = children.size(); i < n; i++) { 95 | Task child = children.get(i); 96 | if (child.checkGuard(this)) { 97 | childToRun = child; 98 | break; 99 | } 100 | } 101 | 102 | if (runningChild != null && runningChild != childToRun) { 103 | runningChild.cancel(); 104 | runningChild = null; 105 | } 106 | if (childToRun == null) { 107 | fail(); 108 | } else { 109 | if (runningChild == null) { 110 | runningChild = childToRun; 111 | runningChild.setControl(this); 112 | runningChild.start(); 113 | } 114 | runningChild.run(); 115 | } 116 | } 117 | 118 | @Override 119 | public void resetTask() { 120 | super.resetTask(); 121 | this.runningChild = null; 122 | } 123 | 124 | // @Override 125 | // protected Task copyTo(Task task) { 126 | // DynamicGuardSelector branch = (DynamicGuardSelector) task; 127 | // branch.runningChild = null; 128 | // 129 | // return super.copyTo(task); 130 | // } 131 | 132 | @Override 133 | public void release() { 134 | runningChild = null; 135 | super.release(); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/branch/RandomSelector.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.branch; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | import com.jzy.ai.btree.Task; 23 | 24 | 25 | /**随机选择器
26 | * A {@code RandomSelector} is a selector task's variant that runs its children in a random order. 27 | * 28 | * @param type of the blackboard object that tasks use to read or modify game state 29 | * 30 | * @author implicit-invocation */ 31 | public class RandomSelector extends Selector { 32 | private static final long serialVersionUID = 1L; 33 | 34 | /** Creates a {@code RandomSelector} branch with no children. */ 35 | public RandomSelector () { 36 | super(); 37 | } 38 | 39 | /** Creates a {@code RandomSelector} branch with the given children. 40 | * 41 | * @param tasks the children of this task */ 42 | public RandomSelector (Task... tasks) { 43 | super(Arrays.asList(tasks)); 44 | } 45 | 46 | /** Creates a {@code RandomSelector} branch with the given children. 47 | * 48 | * @param tasks the children of this task */ 49 | public RandomSelector (List> tasks) { 50 | super(tasks); 51 | } 52 | 53 | @Override 54 | public void start () { 55 | super.start(); 56 | if (randomChildren == null) randomChildren = createRandomChildren(); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/branch/RandomSequence.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.branch; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | import com.jzy.ai.btree.Task; 23 | 24 | 25 | /**随机顺序执行节点
26 | * A {@code RandomSequence} is a sequence task's variant that runs its children 27 | * in a random order. 28 | * 29 | * @param 30 | * type of the blackboard object that tasks use to read or modify 31 | * game state 32 | * 33 | * @author implicit-invocation 34 | */ 35 | public class RandomSequence extends Sequence { 36 | 37 | /** Creates a {@code RandomSequence} branch with no children. */ 38 | public RandomSequence() { 39 | super(); 40 | } 41 | 42 | /** 43 | * Creates a {@code RandomSequence} branch with the given children. 44 | * 45 | * @param tasks 46 | * the children of this task 47 | */ 48 | public RandomSequence(List> tasks) { 49 | super(tasks); 50 | } 51 | 52 | /** 53 | * Creates a {@code RandomSequence} branch with the given children. 54 | * 55 | * @param tasks 56 | * the children of this task 57 | */ 58 | public RandomSequence(Task... tasks) { 59 | super(Arrays.asList(tasks)); 60 | } 61 | 62 | @Override 63 | public void start() { 64 | super.start(); 65 | if (randomChildren == null) 66 | randomChildren = createRandomChildren(); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/branch/ScoreSelector.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.btree.branch; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import com.jzy.ai.btree.Task; 7 | 8 | 9 | /** 10 | * 分数选择器,分数越高,优先执行 11 | * 12 | * @author JiangZhiYong 13 | * @mail 359135103@qq.com 14 | * @param 15 | * 黑板对象 16 | */ 17 | public abstract class ScoreSelector extends Selector { 18 | /** 根据分数排序后的任务列表 */ 19 | private List> scoreChildren = new ArrayList<>(); 20 | 21 | @Override 22 | public void start() { 23 | super.start(); 24 | calculateScore(); 25 | if (scoreChildren.size() < 1) { 26 | scoreChildren.addAll(this.children); 27 | } 28 | } 29 | 30 | @Override 31 | public void run() { 32 | if (runningChild != null) { 33 | runningChild.run(); 34 | } else { 35 | if (currentChildIndex < scoreChildren.size()) { 36 | runningChild = scoreChildren.get(currentChildIndex); 37 | runningChild.setControl(this); 38 | runningChild.start(); 39 | if (!runningChild.checkGuard(this)) 40 | runningChild.fail(); 41 | else 42 | run(); 43 | } else { 44 | // Should never happen; this case must be handled by subclasses in childXXX 45 | // methods 46 | } 47 | } 48 | } 49 | 50 | /** 51 | * 计算子节点的分数
52 | * 节点可根据名称获取 53 | */ 54 | protected abstract void calculateScore(); 55 | 56 | @Override 57 | public void resetTask() { 58 | super.resetTask(); 59 | this.scoreChildren.clear(); 60 | } 61 | 62 | @Override 63 | public void release() { 64 | super.release(); 65 | this.scoreChildren.clear(); 66 | } 67 | 68 | public List> getScoreChildren() { 69 | return scoreChildren; 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/branch/Selector.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.branch; 18 | 19 | import com.jzy.ai.btree.SingleRunningChildBranch; 20 | import com.jzy.ai.btree.Task; 21 | 22 | import java.util.Arrays; 23 | import java.util.List; 24 | 25 | 26 | 27 | /** 28 | * 选择节点
29 | * A {@code Selector} is a branch task that runs every children until one of 30 | * them succeeds. If a child task fails, the selector will start and run the 31 | * next child task. 32 | * 33 | * @param 34 | * type of the blackboard object that tasks use to read or modify 35 | * game state 36 | * 37 | * @author implicit-invocation 38 | */ 39 | public class Selector extends SingleRunningChildBranch { 40 | 41 | /** Creates a {@code Selector} branch with no children. */ 42 | public Selector() { 43 | super(); 44 | } 45 | 46 | /** 47 | * Creates a {@code Selector} branch with the given children. 48 | * 49 | * @param tasks 50 | * the children of this task 51 | */ 52 | public Selector(Task... tasks) { 53 | super(Arrays.asList(tasks)); 54 | } 55 | 56 | /** 57 | * Creates a {@code Selector} branch with the given children. 58 | * 59 | * @param tasks 60 | * the children of this task 61 | */ 62 | public Selector(List> tasks) { 63 | super(tasks); 64 | } 65 | 66 | @Override 67 | public void childFail(Task runningTask) { 68 | super.childFail(runningTask); 69 | if (++currentChildIndex < children.size()) { 70 | run(); // Run next child 71 | } else { 72 | fail(); // All children processed, return failure status 73 | } 74 | } 75 | 76 | @Override 77 | public void childSuccess(Task runningTask) { 78 | super.childSuccess(runningTask); 79 | success(); // Return success status when a child says it succeeded 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/branch/Sequence.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.branch; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | 22 | import com.jzy.ai.btree.SingleRunningChildBranch; 23 | import com.jzy.ai.btree.Task; 24 | 25 | 26 | /**顺序执行任务节点
27 | * A {@code Sequence} is a branch task that runs every children until one of them fails. If a child task succeeds, the selector 28 | * will start and run the next child task. 29 | * 30 | * @param type of the blackboard object that tasks use to read or modify game state 31 | * 32 | * @author implicit-invocation */ 33 | public class Sequence extends SingleRunningChildBranch { 34 | 35 | /** Creates a {@code Sequence} branch with no children. */ 36 | public Sequence () { 37 | super(); 38 | } 39 | 40 | /** Creates a {@code Sequence} branch with the given children. 41 | * 42 | * @param tasks the children of this task */ 43 | public Sequence (List> tasks) { 44 | super(tasks); 45 | } 46 | 47 | /** Creates a {@code Sequence} branch with the given children. 48 | * 49 | * @param tasks the children of this task */ 50 | public Sequence (Task... tasks) { 51 | super(Arrays.asList(tasks)); 52 | } 53 | 54 | @Override 55 | public void childSuccess (Task runningTask) { 56 | super.childSuccess(runningTask); 57 | if (++currentChildIndex < children.size()) { 58 | run(); // Run next child 59 | } else { 60 | success(); // All children processed, return success status 61 | } 62 | } 63 | 64 | @Override 65 | public void childFail (Task runningTask) { 66 | super.childFail(runningTask); 67 | fail(); // Return failure status when a child says it failed 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/decorator/AlwaysFail.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 | import com.jzy.ai.btree.Decorator; 20 | import com.jzy.ai.btree.Task; 21 | 22 | /**直接失败 23 | * An {@code AlwaysFail} decorator will fail no matter the wrapped task fails or succeeds. 24 | * 25 | * @param type of the blackboard object that tasks use to read or modify game state 26 | * 27 | * @author implicit-invocation */ 28 | public class AlwaysFail extends Decorator { 29 | 30 | /** Creates an {@code AlwaysFail} decorator with no child. */ 31 | public AlwaysFail () { 32 | } 33 | 34 | /** Creates an {@code AlwaysFail} decorator with the given child. 35 | * 36 | * @param task the child task to wrap */ 37 | public AlwaysFail (Task task) { 38 | super(task); 39 | } 40 | 41 | @Override 42 | public void childSuccess (Task runningTask) { 43 | childFail(runningTask); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/decorator/AlwaysSucceed.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 | import com.jzy.ai.btree.Decorator; 20 | import com.jzy.ai.btree.Task; 21 | 22 | /**直接成功
23 | * An {@code AlwaysSucceed} decorator will succeed no matter the wrapped task succeeds or fails. 24 | * 25 | * @param type of the blackboard object that tasks use to read or modify game state 26 | * 27 | * @author implicit-invocation */ 28 | public class AlwaysSucceed extends Decorator { 29 | 30 | /** Creates an {@code AlwaysSucceed} decorator with no child. */ 31 | public AlwaysSucceed () { 32 | } 33 | 34 | /** Creates an {@code AlwaysSucceed} decorator with the given child. 35 | * 36 | * @param task the child task to wrap */ 37 | public AlwaysSucceed (Task task) { 38 | super(task); 39 | } 40 | 41 | @Override 42 | public void childFail (Task runningTask) { 43 | childSuccess(runningTask); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/decorator/Invert.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 | import com.jzy.ai.btree.Decorator; 19 | import com.jzy.ai.btree.Task; 20 | 21 | /** 22 | * 结果翻转
23 | * An {@code Invert} decorator will succeed if the wrapped task fails and will 24 | * fail if the wrapped task succeeds. 25 | * 26 | * @param 27 | * type of the blackboard object that tasks use to read or modify 28 | * game state 29 | * 30 | * @author implicit-invocation 31 | */ 32 | public class Invert extends Decorator { 33 | private static final long serialVersionUID = 1L; 34 | 35 | /** Creates an {@code Invert} decorator with no child. */ 36 | public Invert() { 37 | } 38 | 39 | /** 40 | * Creates an {@code Invert} decorator with the given child. 41 | * 42 | * @param task 43 | * the child task to wrap 44 | */ 45 | public Invert(Task task) { 46 | super(task); 47 | } 48 | 49 | @Override 50 | public void childSuccess(Task runningTask) { 51 | super.childFail(runningTask); 52 | } 53 | 54 | @Override 55 | public void childFail(Task runningTask) { 56 | super.childSuccess(runningTask); 57 | } 58 | 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/btree/decorator/Repeat.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 | import com.jzy.ai.btree.annotation.TaskAttribute; 23 | 24 | /** 25 | * 重复执行指定次数的任务节点
26 | * A {@code Repeat} decorator will repeat the wrapped task a certain number of 27 | * times, possibly infinite. This task always succeeds when reaches the 28 | * specified number of repetitions. 29 | * 30 | * @param 31 | * type of the blackboard object that tasks use to read or modify 32 | * game state 33 | * 34 | * @author implicit-invocation 35 | * 36 | */ 37 | public class Repeat extends LoopDecorator { 38 | private static final long serialVersionUID = 1L; 39 | 40 | /** 41 | * Optional task attribute specifying the integer distribution that determines 42 | * how many times the wrapped task must be repeated. Defaults to 43 | * {@link ConstantIntegerDistribution#NEGATIVE_ONE} which indicates an infinite 44 | * number of repetitions. 45 | * 46 | * @see #start() 47 | */ 48 | @TaskAttribute 49 | public int times; 50 | 51 | private int count; 52 | 53 | /** Creates an infinite repeat decorator with no child task. */ 54 | public Repeat() { 55 | this(null); 56 | } 57 | 58 | /** 59 | * 60 | * @param times 循环次数 61 | */ 62 | public Repeat(int times) { 63 | this(times, null); 64 | } 65 | 66 | /** 67 | * Creates an infinite repeat decorator that wraps the given task. 68 | * 69 | * @param child 70 | * the task that will be wrapped 71 | */ 72 | public Repeat(Task child) { 73 | this(-1, child); 74 | } 75 | 76 | 77 | 78 | /** 79 | * Creates a repeat decorator that executes the given task the number of times 80 | * (possibly infinite) determined by the given distribution. The number of times 81 | * is drawn from the distribution by the {@link #start()} method. Any negative 82 | * value means forever. 83 | * 84 | * @param times 85 | * the integer distribution specifying how many times the child must 86 | * be repeated. 负数,无限循环 87 | * @param child 88 | * the task that will be wrapped 89 | */ 90 | public Repeat(int times, Task 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 getNw() { 99 | return nw; 100 | } 101 | 102 | public void setNw(Node nw) { 103 | this.nw = nw; 104 | } 105 | 106 | public Node getNe() { 107 | return ne; 108 | } 109 | 110 | public void setNe(Node ne) { 111 | this.ne = ne; 112 | } 113 | 114 | public Node getSw() { 115 | return sw; 116 | } 117 | 118 | public void setSw(Node sw) { 119 | this.sw = sw; 120 | } 121 | 122 | public Node getSe() { 123 | return se; 124 | } 125 | 126 | public void setSe(Node se) { 127 | this.se = se; 128 | } 129 | 130 | public Data getData() { 131 | return data; 132 | } 133 | 134 | public void setData(Data data) { 135 | this.data = data; 136 | } 137 | 138 | public List> getDatas() { 139 | if (datas == null) { 140 | datas = new ArrayList<>(); 141 | } 142 | return datas; 143 | } 144 | 145 | public void setDatas(List> datas) { 146 | this.datas = datas; 147 | } 148 | 149 | public int getDepth() { 150 | return depth; 151 | } 152 | 153 | public void setDepth(int depth) { 154 | this.depth = depth; 155 | } 156 | 157 | public Polygon getPolygon() { 158 | return polygon; 159 | } 160 | 161 | } 162 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/quadtree/NodeType.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.quadtree; 2 | 3 | /** 4 | * 节点类型 5 | * @author JiangZhiYong 6 | * @mail 359135103@qq.com 7 | */ 8 | public enum NodeType { 9 | EMPTY, 10 | LEAF, 11 | POINTER 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/quadtree/QuadTree.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.quadtree; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * 四叉树 7 | * 8 | * @author JiangZhiYong 9 | * @mail 359135103@qq.com 10 | */ 11 | public abstract class QuadTree { 12 | /** 根节点 */ 13 | protected Node root; 14 | /** 数量 */ 15 | protected int count; 16 | 17 | public QuadTree(float minX, float minZ, float maxX, float maxZ) { 18 | this.root = new Node<>(minX, minZ, maxX - minX, maxZ - minZ, null); 19 | } 20 | 21 | /** 22 | * 获取根节点 23 | * 24 | * @return 25 | */ 26 | public Node getRootNode() { 27 | return root; 28 | } 29 | 30 | /** 31 | * 设置四叉树的值 32 | * 33 | * @param k 34 | * 键 35 | * @param v 36 | * 键对应值 37 | */ 38 | public abstract void set(K k, V v); 39 | 40 | /** 41 | * 获取数据 42 | * 43 | * @param k 44 | * 键 45 | * @param defaultValue 46 | * 默认值 47 | * @return 48 | */ 49 | public abstract V get(K k, V defaultValue); 50 | 51 | /** 52 | * 查询当前节点包含key的值 53 | * 54 | * @param node 55 | * 当前节点 56 | * @param k 57 | * 键 58 | * @return 59 | */ 60 | public abstract Node find(Node node, K k); 61 | 62 | /** 63 | * 移除数据 64 | * 65 | * @param k 66 | * @return 67 | */ 68 | public abstract V remove(K k); 69 | 70 | /** 71 | * 是否包含值 72 | * 73 | * @param k 74 | * @return 75 | */ 76 | public boolean contains(K k) { 77 | return get(k, null) != null; 78 | } 79 | 80 | /** 81 | * @return Whether the tree is empty. 82 | */ 83 | public boolean isEmpty() { 84 | return this.root.getNodeType() == NodeType.EMPTY; 85 | } 86 | 87 | /** 88 | * 获取数据数量 89 | * 90 | * @return 91 | */ 92 | public int getCount() { 93 | return count; 94 | } 95 | 96 | /** 97 | * Removes all items from the tree. 98 | */ 99 | public void clear() { 100 | this.root.setNw(null); 101 | this.root.setNe(null); 102 | this.root.setSw(null); 103 | this.root.setSe(null); 104 | this.root.setNodeType(NodeType.EMPTY); 105 | this.root.setData(null); 106 | this.count = 0; 107 | } 108 | 109 | /** 110 | * 获取键值对数据 111 | * @return 112 | */ 113 | public abstract List getKeyValues(); 114 | 115 | /** 116 | * 获取键 117 | * @return 118 | */ 119 | public abstract List getKeys(); 120 | 121 | /** 122 | * 获取值 123 | * @return 124 | */ 125 | public abstract List getValues(); 126 | 127 | /** 128 | * 是否相交 129 | * 130 | * @param left 131 | * @param bottom 132 | * @param right 133 | * @param top 134 | * @param node 135 | * @return 136 | */ 137 | protected boolean intersects(double left, double bottom, double right, double top, Node node) { 138 | return !(node.getX() > right || (node.getX() + node.getW()) < left || node.getZ() > bottom 139 | || (node.getZ() + node.getH()) < top); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/quadtree/QuadTreeException.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.quadtree; 2 | 3 | /** 4 | * 四叉树异常 5 | * @author JiangZhiYong 6 | * @mail 359135103@qq.com 7 | */ 8 | public class QuadTreeException extends RuntimeException { 9 | /** 10 | * 11 | */ 12 | private static final long serialVersionUID = 1L; 13 | 14 | public QuadTreeException(String s) { 15 | super(s); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/quadtree/point/PointData.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.quadtree.point; 2 | 3 | 4 | import com.jzy.ai.quadtree.Data; 5 | import com.jzy.javalib.math.geometry.Vector3; 6 | 7 | /** 8 | * 坐标点数据结构 9 | * 10 | * @author JiangZhiYong 11 | * @mail 359135103@qq.com 12 | */ 13 | public class PointData extends Data { 14 | 15 | private Vector3 point; 16 | 17 | public PointData(Vector3 point, T value) { 18 | super(value); 19 | this.point = point; 20 | } 21 | 22 | public Vector3 getPoint() { 23 | return point; 24 | } 25 | 26 | public void setPoint(Vector3 point) { 27 | this.point = point; 28 | } 29 | 30 | @Override 31 | public int compareTo(Data data) { 32 | PointData o=(PointData) data; 33 | if (this.point.x < o.point.x) { 34 | return -1; 35 | } else if (this.point.x > o.point.x) { 36 | return 1; 37 | } else { 38 | if (this.point.z < o.point.z) { 39 | return -1; 40 | } else if (this.point.z > o.point.z) { 41 | return 1; 42 | } 43 | return 0; 44 | } 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return "PointData [point=" + point + ", getValue()=" + getValue() + "]"; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/GroupBehavior.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.steer; 18 | 19 | 20 | import com.jzy.javalib.math.geometry.Vector; 21 | 22 | /** 23 | * 组转向行为
    24 | * {@code GroupBehavior} is the base class for the steering behaviors that take into consideration the agents in the game world 25 | * that are within the immediate area of the owner. This immediate area is defined by a {@link Proximity} that is in charge of 26 | * finding and processing the owner's neighbors through the given {@link Proximity.ProximityCallback}. 27 | * 28 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 29 | * 30 | * @author davebaol */ 31 | public abstract class GroupBehavior> extends SteeringBehavior { 32 | 33 | /** The proximity decides which agents are considered neighbors. */ 34 | protected Proximity proximity; 35 | 36 | /** Creates a GroupBehavior for the specified owner and proximity. 37 | * @param owner the owner of this behavior. 38 | * @param proximity the proximity to detect the owner's neighbors */ 39 | public GroupBehavior(Steerable owner, Proximity proximity) { 40 | super(owner); 41 | this.proximity = proximity; 42 | } 43 | 44 | /** Returns the proximity of this group behavior */ 45 | public Proximity getProximity () { 46 | return proximity; 47 | } 48 | 49 | /** Sets the proximity of this group behavior 50 | * @param proximity the proximity to set */ 51 | public void setProximity (Proximity proximity) { 52 | this.proximity = proximity; 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/Limiter.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.steer; 2 | 3 | /******************************************************************************* 4 | * Copyright 2014 See AUTHORS file. 5 | * 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 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | ******************************************************************************/ 18 | 19 | 20 | /** A {@code Limiter} provides the maximum magnitudes of speed and acceleration for both linear and angular components. 21 | * 22 | * @author davebaol */ 23 | public interface Limiter { 24 | 25 | /** Returns the threshold below which the linear speed can be considered zero. It must be a small positive value near to zero. 26 | * Usually it is used to avoid updating the orientation when the velocity vector has a negligible length. */ 27 | public float getZeroLinearSpeedThreshold (); 28 | 29 | /** Sets the threshold below which the linear speed can be considered zero. It must be a small positive value near to zero. 30 | * Usually it is used to avoid updating the orientation when the velocity vector has a negligible length. */ 31 | public void setZeroLinearSpeedThreshold (float value); 32 | 33 | /** Returns the maximum linear speed. */ 34 | public float getMaxLinearSpeed (); 35 | 36 | /** Sets the maximum linear speed. */ 37 | public void setMaxLinearSpeed (float maxLinearSpeed); 38 | 39 | /** Returns the maximum linear acceleration. */ 40 | public float getMaxLinearAcceleration (); 41 | 42 | /** Sets the maximum linear acceleration. */ 43 | public void setMaxLinearAcceleration (float maxLinearAcceleration); 44 | 45 | /** Returns the maximum angular speed. */ 46 | public float getMaxAngularSpeed (); 47 | 48 | /** Sets the maximum angular speed. */ 49 | public void setMaxAngularSpeed (float maxAngularSpeed); 50 | 51 | /** Returns the maximum angular acceleration. */ 52 | public float getMaxAngularAcceleration (); 53 | 54 | /** Sets the maximum angular acceleration. */ 55 | public void setMaxAngularAcceleration (float maxAngularAcceleration); 56 | } 57 | 58 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/Steerable.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.steer; 2 | 3 | /******************************************************************************* 4 | * Copyright 2014 See AUTHORS file. 5 | * 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 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | ******************************************************************************/ 18 | 19 | 20 | import com.jzy.ai.util.Location; 21 | import com.jzy.javalib.math.geometry.Vector; 22 | 23 | /**可转向对象接口
    24 | * A {@code Steerable} is a {@link Location} that gives access to the character's data required by steering system. 25 | *

    26 | * Notice that there is nothing to connect the direction that a Steerable is moving and the direction it is facing. For 27 | * instance, a character can be oriented along the x-axis but be traveling directly along the y-axis. 28 | * 29 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 30 | * 31 | * @author davebaol */ 32 | public interface Steerable> extends Location, Limiter { 33 | 34 | /** Returns the vector indicating the linear velocity of this Steerable. */ 35 | public T getLinearVelocity (); 36 | 37 | /** Returns the float value indicating the the angular velocity in radians of this Steerable. */ 38 | public float getAngularVelocity (); 39 | 40 | /** Returns the bounding radius of this Steerable. */ 41 | public float getBoundingRadius (); 42 | 43 | /** Returns {@code true} if this Steerable is tagged; {@code false} otherwise. */ 44 | public boolean isTagged (); 45 | 46 | /** Tag/untag this Steerable. This is a generic flag utilized in a variety of ways. 47 | * @param tagged the boolean value to set */ 48 | public void setTagged (boolean tagged); 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/SteerableAdapter.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.steer; 18 | 19 | 20 | import com.jzy.ai.util.Location; 21 | import com.jzy.javalib.math.geometry.Vector; 22 | 23 | /** An adapter class for {@link Steerable}. You can derive from this and only override what you are interested in. For example, 24 | * this comes in handy when you have to create on the fly a target for a particular behavior. 25 | * 26 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 27 | * 28 | * @author davebaol */ 29 | public class SteerableAdapter> implements Steerable { 30 | 31 | @Override 32 | public float getZeroLinearSpeedThreshold () { 33 | return 0.001f; 34 | } 35 | 36 | @Override 37 | public void setZeroLinearSpeedThreshold (float value) { 38 | } 39 | 40 | @Override 41 | public float getMaxLinearSpeed () { 42 | return 0; 43 | } 44 | 45 | @Override 46 | public void setMaxLinearSpeed (float maxLinearSpeed) { 47 | } 48 | 49 | @Override 50 | public float getMaxLinearAcceleration () { 51 | return 0; 52 | } 53 | 54 | @Override 55 | public void setMaxLinearAcceleration (float maxLinearAcceleration) { 56 | } 57 | 58 | @Override 59 | public float getMaxAngularSpeed () { 60 | return 0; 61 | } 62 | 63 | @Override 64 | public void setMaxAngularSpeed (float maxAngularSpeed) { 65 | } 66 | 67 | @Override 68 | public float getMaxAngularAcceleration () { 69 | return 0; 70 | } 71 | 72 | @Override 73 | public void setMaxAngularAcceleration (float maxAngularAcceleration) { 74 | } 75 | 76 | @Override 77 | public T getPosition () { 78 | return null; 79 | } 80 | 81 | @Override 82 | public float getOrientation () { 83 | return 0; 84 | } 85 | 86 | @Override 87 | public void setOrientation (float orientation) { 88 | } 89 | 90 | @Override 91 | public T getLinearVelocity () { 92 | return null; 93 | } 94 | 95 | @Override 96 | public float getAngularVelocity () { 97 | return 0; 98 | } 99 | 100 | @Override 101 | public float getBoundingRadius () { 102 | return 0; 103 | } 104 | 105 | @Override 106 | public boolean isTagged () { 107 | return false; 108 | } 109 | 110 | @Override 111 | public void setTagged (boolean tagged) { 112 | } 113 | 114 | @Override 115 | public Location newLocation () { 116 | return null; 117 | } 118 | 119 | @Override 120 | public float vectorToAngle (T vector) { 121 | return 0; 122 | } 123 | 124 | @Override 125 | public T angleToVector (T outVector, float angle) { 126 | return null; 127 | } 128 | 129 | } 130 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/behaviors/Alignment.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.steer.behaviors; 18 | 19 | 20 | import com.jzy.ai.steer.*; 21 | import com.jzy.javalib.math.geometry.Vector; 22 | 23 | /** 24 | * 25 | * {@code Alignment} is a group behavior producing a linear acceleration that attempts to keep the owner aligned with the agents in 26 | * its immediate area defined by the given {@link Proximity}. The acceleration is calculated by first iterating through all the 27 | * neighbors and averaging their linear velocity vectors. This value is the desired direction, so we just subtract the owner's 28 | * linear velocity to get the steering output. 29 | *

    30 | * Cars moving along roads demonstrate {@code Alignment} type behavior. They also demonstrate {@link Separation} as they try to 31 | * keep a minimum distance from each other. 32 | * 33 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 34 | * 35 | * @author davebaol */ 36 | public class Alignment> extends GroupBehavior implements Proximity.ProximityCallback { 37 | 38 | private T averageVelocity; 39 | 40 | /** Creates an {@code Alignment} behavior for the specified owner and proximity. 41 | * @param owner the owner of this behavior 42 | * @param proximity the proximity */ 43 | public Alignment(Steerable owner, Proximity proximity) { 44 | super(owner, proximity); 45 | } 46 | 47 | @Override 48 | protected SteeringAcceleration calculateRealSteering (SteeringAcceleration steering) { 49 | steering.setZero(); 50 | 51 | averageVelocity = steering.linear; 52 | 53 | int neighborCount = proximity.findNeighbors(this); 54 | 55 | if (neighborCount > 0) { 56 | // Average the accumulated velocities 57 | averageVelocity.scl(1f / neighborCount); 58 | 59 | // Match the average velocity. 60 | // Notice that steering.linear and averageVelocity are the same vector here. 61 | averageVelocity.sub(owner.getLinearVelocity()).limit(getActualLimiter().getMaxLinearAcceleration()); 62 | } 63 | 64 | return steering; 65 | } 66 | 67 | @Override 68 | public boolean reportNeighbor (Steerable neighbor) { 69 | // Accumulate neighbor velocity 70 | averageVelocity.add(neighbor.getLinearVelocity()); 71 | return true; 72 | } 73 | 74 | // 75 | // Setters overridden in order to fix the correct return type for chaining 76 | // 77 | 78 | @Override 79 | public Alignment setOwner (Steerable owner) { 80 | this.owner = owner; 81 | return this; 82 | } 83 | 84 | @Override 85 | public Alignment setEnabled (boolean enabled) { 86 | this.enabled = enabled; 87 | return this; 88 | } 89 | 90 | /** Sets the limiter of this steering behavior. The given limiter must at least take care of the maximum linear acceleration. 91 | * @return this behavior for chaining. */ 92 | @Override 93 | public Alignment setLimiter (Limiter limiter) { 94 | this.limiter = limiter; 95 | return this; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/behaviors/Cohesion.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.steer.behaviors; 18 | 19 | 20 | import com.jzy.ai.steer.*; 21 | import com.jzy.javalib.math.geometry.Vector; 22 | 23 | /** {@code Cohesion} is a group behavior producing a linear acceleration that attempts to move the agent towards the center of mass 24 | * of the agents in its immediate area defined by the given {@link Proximity}. The acceleration is calculated by first iterating 25 | * through all the neighbors and averaging their position vectors. This gives us the center of mass of the neighbors, the place 26 | * the agents wants to get to, so it seeks to that position. 27 | *

    28 | * A sheep running after its flock is demonstrating cohesive behavior. Use this behavior to keep a group of agents together. 29 | * 30 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 31 | * 32 | * @author davebaol */ 33 | public class Cohesion> extends GroupBehavior implements Proximity.ProximityCallback { 34 | 35 | private T centerOfMass; 36 | 37 | /** Creates a {@code Cohesion} for the specified owner and proximity. 38 | * @param owner the owner of this behavior. 39 | * @param proximity the proximity to detect the owner's neighbors */ 40 | public Cohesion(Steerable owner, Proximity proximity) { 41 | super(owner, proximity); 42 | } 43 | 44 | @Override 45 | protected SteeringAcceleration calculateRealSteering (SteeringAcceleration steering) { 46 | 47 | steering.setZero(); 48 | 49 | centerOfMass = steering.linear; 50 | 51 | int neighborCount = proximity.findNeighbors(this); 52 | 53 | if (neighborCount > 0) { 54 | 55 | // The center of mass is the average of the sum of positions 56 | centerOfMass.scl(1f / neighborCount); 57 | 58 | // Now seek towards that position. 59 | centerOfMass.sub(owner.getPosition()).nor().scl(getActualLimiter().getMaxLinearAcceleration()); 60 | } 61 | 62 | return steering; 63 | } 64 | 65 | @Override 66 | public boolean reportNeighbor (Steerable neighbor) { 67 | // Accumulate neighbor position 68 | centerOfMass.add(neighbor.getPosition()); 69 | return true; 70 | } 71 | 72 | // 73 | // Setters overridden in order to fix the correct return type for chaining 74 | // 75 | 76 | @Override 77 | public Cohesion setOwner (Steerable owner) { 78 | this.owner = owner; 79 | return this; 80 | } 81 | 82 | @Override 83 | public Cohesion setEnabled (boolean enabled) { 84 | this.enabled = enabled; 85 | return this; 86 | } 87 | 88 | /** Sets the limiter of this steering behavior. The given limiter must at least take care of the maximum linear acceleration. 89 | * @return this behavior for chaining. */ 90 | @Override 91 | public Cohesion setLimiter (Limiter limiter) { 92 | this.limiter = limiter; 93 | return this; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/behaviors/Evade.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.steer.behaviors; 2 | 3 | /******************************************************************************* 4 | * Copyright 2014 See AUTHORS file. 5 | * 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 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | ******************************************************************************/ 18 | 19 | 20 | import com.jzy.ai.steer.Limiter; 21 | import com.jzy.ai.steer.Steerable; 22 | import com.jzy.javalib.math.geometry.Vector; 23 | 24 | /** 25 | * 逃离
    26 | * {@code Evade} behavior is almost the same as {@link Pursue} except that the agent flees from the estimated future position of 27 | * the pursuer. Indeed, reversing the acceleration is all we have to do. 28 | * 29 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 30 | * 31 | * @author davebaol */ 32 | public class Evade> extends Pursue { 33 | 34 | /** Creates a {@code Evade} behavior for the specified owner and target. Maximum prediction time defaults to 1 second. 35 | * @param owner the owner of this behavior 36 | * @param target the target of this behavior, typically a pursuer. */ 37 | public Evade (Steerable owner, Steerable target) { 38 | this(owner, target, 1); 39 | } 40 | 41 | /** Creates a {@code Evade} behavior for the specified owner and pursuer. 42 | * @param owner the owner of this behavior 43 | * @param target the target of this behavior, typically a pursuer 44 | * @param maxPredictionTime the max time used to predict the pursuer's position assuming it continues to move with its current 45 | * velocity. */ 46 | public Evade (Steerable owner, Steerable target, float maxPredictionTime) { 47 | super(owner, target, maxPredictionTime); 48 | } 49 | 50 | @Override 51 | protected float getActualMaxLinearAcceleration () { 52 | // Simply return the opposite of the max linear acceleration so to evade the target 53 | return -getActualLimiter().getMaxLinearAcceleration(); 54 | } 55 | 56 | // 57 | // Setters overridden in order to fix the correct return type for chaining 58 | // 59 | 60 | @Override 61 | public Evade setOwner (Steerable owner) { 62 | this.owner = owner; 63 | return this; 64 | } 65 | 66 | @Override 67 | public Evade setEnabled (boolean enabled) { 68 | this.enabled = enabled; 69 | return this; 70 | } 71 | 72 | /** Sets the limiter of this steering behavior. The given limiter must at least take care of the maximum linear acceleration. 73 | * @return this behavior for chaining. */ 74 | @Override 75 | public Evade setLimiter (Limiter limiter) { 76 | this.limiter = limiter; 77 | return this; 78 | } 79 | 80 | @Override 81 | public Evade setTarget (Steerable target) { 82 | this.target = target; 83 | return this; 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/behaviors/Flee.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.steer.behaviors; 2 | 3 | /******************************************************************************* 4 | * Copyright 2014 See AUTHORS file. 5 | * 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 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | ******************************************************************************/ 18 | 19 | 20 | import com.jzy.ai.steer.Limiter; 21 | import com.jzy.ai.steer.Steerable; 22 | import com.jzy.ai.steer.SteeringAcceleration; 23 | import com.jzy.ai.util.Location; 24 | import com.jzy.javalib.math.geometry.Vector; 25 | 26 | /**逃离到某个坐标点
    27 | * {@code Flee} behavior does the opposite of {@link Seek}. It produces a linear steering force that moves the agent away from a 28 | * target position. 29 | * 30 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 31 | * 32 | * @author davebaol */ 33 | public class Flee> extends Seek { 34 | 35 | /** Creates a {@code Flee} behavior for the specified owner. 36 | * @param owner the owner of this behavior. */ 37 | public Flee (Steerable owner) { 38 | this(owner, null); 39 | } 40 | 41 | /** Creates a {@code Flee} behavior for the specified owner and target. 42 | * @param owner the owner of this behavior 43 | * @param target the target agent of this behavior. */ 44 | public Flee (Steerable owner, Location target) { 45 | super(owner, target); 46 | } 47 | 48 | @Override 49 | protected SteeringAcceleration calculateRealSteering (SteeringAcceleration steering) { 50 | // We just do the opposite of seek, i.e. (owner.getPosition() - target.getPosition()) 51 | // instead of (target.getPosition() - owner.getPosition()) 52 | steering.linear.set(owner.getPosition()).sub(target.getPosition()).nor().scl(getActualLimiter().getMaxLinearAcceleration()); 53 | 54 | // No angular acceleration 55 | steering.angular = 0; 56 | 57 | // Output steering acceleration 58 | return steering; 59 | } 60 | 61 | // 62 | // Setters overridden in order to fix the correct return type for chaining 63 | // 64 | 65 | @Override 66 | public Flee setOwner (Steerable owner) { 67 | this.owner = owner; 68 | return this; 69 | } 70 | 71 | @Override 72 | public Flee setEnabled (boolean enabled) { 73 | this.enabled = enabled; 74 | return this; 75 | } 76 | 77 | /** Sets the limiter of this steering behavior. The given limiter must at least take care of the maximum linear acceleration. 78 | * @return this behavior for chaining. */ 79 | @Override 80 | public Flee setLimiter (Limiter limiter) { 81 | this.limiter = limiter; 82 | return this; 83 | } 84 | 85 | @Override 86 | public Flee setTarget (Location target) { 87 | this.target = target; 88 | return this; 89 | } 90 | 91 | } 92 | 93 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/behaviors/Seek.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.steer.behaviors; 2 | 3 | /******************************************************************************* 4 | * Copyright 2014 See AUTHORS file. 5 | * 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 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | ******************************************************************************/ 18 | 19 | 20 | import com.jzy.ai.steer.Limiter; 21 | import com.jzy.ai.steer.Steerable; 22 | import com.jzy.ai.steer.SteeringAcceleration; 23 | import com.jzy.ai.steer.SteeringBehavior; 24 | import com.jzy.ai.util.Location; 25 | import com.jzy.javalib.math.geometry.Vector; 26 | 27 | /**寻找某个目标点
    28 | * {@code Seek} behavior moves the owner towards the target position. Given a target, this behavior calculates the linear steering 29 | * acceleration which will direct the agent towards the target as fast as possible. 30 | * 31 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 32 | * 33 | * @author davebaol */ 34 | public class Seek> extends SteeringBehavior { 35 | 36 | /** The target to seek */ 37 | protected Location target; 38 | 39 | /** Creates a {@code Seek} behavior for the specified owner. 40 | * @param owner the owner of this behavior. */ 41 | public Seek (Steerable owner) { 42 | this(owner, null); 43 | } 44 | 45 | /** Creates a {@code Seek} behavior for the specified owner and target. 46 | * @param owner the owner of this behavior 47 | * @param target the target agent of this behavior. */ 48 | public Seek (Steerable owner, Location target) { 49 | super(owner); 50 | this.target = target; 51 | } 52 | 53 | @Override 54 | protected SteeringAcceleration calculateRealSteering (SteeringAcceleration steering) { 55 | // Try to match the position of the character with the position of the target by calculating 56 | // the direction to the target and by moving toward it as fast as possible. 57 | steering.linear.set(target.getPosition()).sub(owner.getPosition()).nor().scl(getActualLimiter().getMaxLinearAcceleration()); 58 | 59 | // No angular acceleration 60 | steering.angular = 0; 61 | 62 | // Output steering acceleration 63 | return steering; 64 | } 65 | 66 | /** Returns the target to seek. */ 67 | public Location getTarget () { 68 | return target; 69 | } 70 | 71 | /** Sets the target to seek. 72 | * @return this behavior for chaining. */ 73 | public Seek setTarget (Location target) { 74 | this.target = target; 75 | return this; 76 | } 77 | 78 | // 79 | // Setters overridden in order to fix the correct return type for chaining 80 | // 81 | 82 | @Override 83 | public Seek setOwner (Steerable owner) { 84 | this.owner = owner; 85 | return this; 86 | } 87 | 88 | @Override 89 | public Seek setEnabled (boolean enabled) { 90 | this.enabled = enabled; 91 | return this; 92 | } 93 | 94 | /** Sets the limiter of this steering behavior. The given limiter must at least take care of the maximum linear acceleration. 95 | * @return this behavior for chaining. */ 96 | @Override 97 | public Seek setLimiter (Limiter limiter) { 98 | this.limiter = limiter; 99 | return this; 100 | } 101 | 102 | } 103 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/limiters/AngularAccelerationLimiter.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.steer.limiters; 18 | 19 | /** An {@code AngularAccelerationLimiter} provides the maximum magnitude of angular acceleration. All other methods throw an 20 | * {@link UnsupportedOperationException}. 21 | * 22 | * @author davebaol */ 23 | public class AngularAccelerationLimiter extends NullLimiter { 24 | 25 | private float maxAngularAcceleration; 26 | 27 | /** Creates an {@code AngularAccelerationLimiter}. 28 | * @param maxAngularAcceleration the maximum angular acceleration */ 29 | public AngularAccelerationLimiter (float maxAngularAcceleration) { 30 | this.maxAngularAcceleration = maxAngularAcceleration; 31 | } 32 | 33 | /** Returns the maximum angular acceleration. */ 34 | @Override 35 | public float getMaxAngularAcceleration () { 36 | return maxAngularAcceleration; 37 | } 38 | 39 | /** Sets the maximum angular acceleration. */ 40 | @Override 41 | public void setMaxAngularAcceleration (float maxAngularAcceleration) { 42 | this.maxAngularAcceleration = maxAngularAcceleration; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/limiters/AngularLimiter.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.steer.limiters; 18 | 19 | /** An {@code AngularLimiter} provides the maximum magnitudes of angular speed and angular acceleration. Linear methods throw an 20 | * {@link UnsupportedOperationException}. 21 | * 22 | * @author davebaol */ 23 | public class AngularLimiter extends NullLimiter { 24 | 25 | private float maxAngularAcceleration; 26 | private float maxAngularSpeed; 27 | 28 | /** Creates an {@code AngularLimiter}. 29 | * @param maxAngularAcceleration the maximum angular acceleration 30 | * @param maxAngularSpeed the maximum angular speed */ 31 | public AngularLimiter (float maxAngularAcceleration, float maxAngularSpeed) { 32 | this.maxAngularAcceleration = maxAngularAcceleration; 33 | this.maxAngularSpeed = maxAngularSpeed; 34 | } 35 | 36 | /** Returns the maximum angular speed. */ 37 | @Override 38 | public float getMaxAngularSpeed () { 39 | return maxAngularSpeed; 40 | } 41 | 42 | /** Sets the maximum angular speed. */ 43 | @Override 44 | public void setMaxAngularSpeed (float maxAngularSpeed) { 45 | this.maxAngularSpeed = maxAngularSpeed; 46 | } 47 | 48 | /** Returns the maximum angular acceleration. */ 49 | @Override 50 | public float getMaxAngularAcceleration () { 51 | return maxAngularAcceleration; 52 | } 53 | 54 | /** Sets the maximum angular acceleration. */ 55 | @Override 56 | public void setMaxAngularAcceleration (float maxAngularAcceleration) { 57 | this.maxAngularAcceleration = maxAngularAcceleration; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/limiters/AngularSpeedLimiter.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.steer.limiters; 18 | 19 | /** An {@code AngularSpeedLimiter} provides the maximum magnitudes of angular speed. All other methods throw an 20 | * {@link UnsupportedOperationException}. 21 | * 22 | * @author davebaol */ 23 | public class AngularSpeedLimiter extends NullLimiter { 24 | 25 | private float maxAngularSpeed; 26 | 27 | /** Creates an {@code AngularSpeedLimiter}. 28 | * @param maxAngularSpeed the maximum angular speed */ 29 | public AngularSpeedLimiter (float maxAngularSpeed) { 30 | this.maxAngularSpeed = maxAngularSpeed; 31 | } 32 | 33 | /** Returns the maximum angular speed. */ 34 | @Override 35 | public float getMaxAngularSpeed () { 36 | return maxAngularSpeed; 37 | } 38 | 39 | /** Sets the maximum angular speed. */ 40 | @Override 41 | public void setMaxAngularSpeed (float maxAngularSpeed) { 42 | this.maxAngularSpeed = maxAngularSpeed; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/limiters/FullLimiter.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.steer.limiters; 18 | 19 | 20 | import com.jzy.ai.steer.Limiter; 21 | 22 | /** A {@code FullLimiter} provides the maximum magnitudes of speed and acceleration for both linear and angular components. 23 | * 24 | * @author davebaol */ 25 | public class FullLimiter implements Limiter { 26 | 27 | private float maxLinearAcceleration; 28 | private float maxLinearSpeed; 29 | private float maxAngularAcceleration; 30 | private float maxAngularSpeed; 31 | private float zeroLinearSpeedThreshold; 32 | 33 | /** Creates a {@code FullLimiter}. 34 | * @param maxLinearAcceleration the maximum linear acceleration 35 | * @param maxLinearSpeed the maximum linear speed 36 | * @param maxAngularAcceleration the maximum angular acceleration 37 | * @param maxAngularSpeed the maximum angular speed */ 38 | public FullLimiter (float maxLinearAcceleration, float maxLinearSpeed, float maxAngularAcceleration, float maxAngularSpeed) { 39 | this.maxLinearAcceleration = maxLinearAcceleration; 40 | this.maxLinearSpeed = maxLinearSpeed; 41 | this.maxAngularAcceleration = maxAngularAcceleration; 42 | this.maxAngularSpeed = maxAngularSpeed; 43 | } 44 | 45 | @Override 46 | public float getMaxLinearSpeed () { 47 | return maxLinearSpeed; 48 | } 49 | 50 | @Override 51 | public void setMaxLinearSpeed (float maxLinearSpeed) { 52 | this.maxLinearSpeed = maxLinearSpeed; 53 | } 54 | 55 | @Override 56 | public float getMaxLinearAcceleration () { 57 | return maxLinearAcceleration; 58 | } 59 | 60 | @Override 61 | public void setMaxLinearAcceleration (float maxLinearAcceleration) { 62 | this.maxLinearAcceleration = maxLinearAcceleration; 63 | } 64 | 65 | @Override 66 | public float getMaxAngularSpeed () { 67 | return maxAngularSpeed; 68 | } 69 | 70 | @Override 71 | public void setMaxAngularSpeed (float maxAngularSpeed) { 72 | this.maxAngularSpeed = maxAngularSpeed; 73 | } 74 | 75 | @Override 76 | public float getMaxAngularAcceleration () { 77 | return maxAngularAcceleration; 78 | } 79 | 80 | @Override 81 | public void setMaxAngularAcceleration (float maxAngularAcceleration) { 82 | this.maxAngularAcceleration = maxAngularAcceleration; 83 | } 84 | 85 | @Override 86 | public float getZeroLinearSpeedThreshold () { 87 | return zeroLinearSpeedThreshold; 88 | } 89 | 90 | @Override 91 | public void setZeroLinearSpeedThreshold (float zeroLinearSpeedThreshold) { 92 | this.zeroLinearSpeedThreshold = zeroLinearSpeedThreshold; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/limiters/LinearAccelerationLimiter.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.steer.limiters; 18 | 19 | /** A {@code LinearAccelerationLimiter} provides the maximum magnitude of linear acceleration. All other methods throw an 20 | * {@link UnsupportedOperationException}. 21 | * 22 | * @author davebaol */ 23 | public class LinearAccelerationLimiter extends NullLimiter { 24 | 25 | private float maxLinearAcceleration; 26 | 27 | /** Creates a {@code LinearAccelerationLimiter}. 28 | * @param maxLinearAcceleration the maximum linear acceleration */ 29 | public LinearAccelerationLimiter (float maxLinearAcceleration) { 30 | this.maxLinearAcceleration = maxLinearAcceleration; 31 | } 32 | 33 | /** Returns the maximum linear acceleration. */ 34 | @Override 35 | public float getMaxLinearAcceleration () { 36 | return maxLinearAcceleration; 37 | } 38 | 39 | /** Sets the maximum linear acceleration. */ 40 | @Override 41 | public void setMaxLinearAcceleration (float maxLinearAcceleration) { 42 | this.maxLinearAcceleration = maxLinearAcceleration; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/limiters/LinearLimiter.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.steer.limiters; 18 | 19 | /** A {@code LinearLimiter} provides the maximum magnitudes of linear speed and linear acceleration. Angular methods throw an 20 | * {@link UnsupportedOperationException}. 21 | * 22 | * @author davebaol */ 23 | public class LinearLimiter extends NullLimiter { 24 | 25 | private float maxLinearAcceleration; 26 | private float maxLinearSpeed; 27 | 28 | /** Creates a {@code LinearLimiter}. 29 | * @param maxLinearAcceleration the maximum linear acceleration 30 | * @param maxLinearSpeed the maximum linear speed */ 31 | public LinearLimiter (float maxLinearAcceleration, float maxLinearSpeed) { 32 | this.maxLinearAcceleration = maxLinearAcceleration; 33 | this.maxLinearSpeed = maxLinearSpeed; 34 | } 35 | 36 | /** Returns the maximum linear speed. */ 37 | @Override 38 | public float getMaxLinearSpeed () { 39 | return maxLinearSpeed; 40 | } 41 | 42 | /** Sets the maximum linear speed. */ 43 | @Override 44 | public void setMaxLinearSpeed (float maxLinearSpeed) { 45 | this.maxLinearSpeed = maxLinearSpeed; 46 | } 47 | 48 | /** Returns the maximum linear acceleration. */ 49 | @Override 50 | public float getMaxLinearAcceleration () { 51 | return maxLinearAcceleration; 52 | } 53 | 54 | /** Sets the maximum linear acceleration. */ 55 | @Override 56 | public void setMaxLinearAcceleration (float maxLinearAcceleration) { 57 | this.maxLinearAcceleration = maxLinearAcceleration; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/limiters/LinearSpeedLimiter.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.steer.limiters; 18 | 19 | /** A {@code LinearSpeedLimiter} provides the maximum magnitudes of linear speed. All other methods throw an 20 | * {@link UnsupportedOperationException}. 21 | * 22 | * @author davebaol */ 23 | public class LinearSpeedLimiter extends NullLimiter { 24 | 25 | private float maxLinearSpeed; 26 | 27 | /** Creates a {@code LinearSpeedLimiter}. 28 | * @param maxLinearSpeed the maximum linear speed */ 29 | public LinearSpeedLimiter (float maxLinearSpeed) { 30 | this.maxLinearSpeed = maxLinearSpeed; 31 | } 32 | 33 | /** Returns the maximum linear speed. */ 34 | @Override 35 | public float getMaxLinearSpeed () { 36 | return maxLinearSpeed; 37 | } 38 | 39 | /** Sets the maximum linear speed. */ 40 | @Override 41 | public void setMaxLinearSpeed (float maxLinearSpeed) { 42 | this.maxLinearSpeed = maxLinearSpeed; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/limiters/NullLimiter.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.steer.limiters; 18 | 19 | 20 | import com.jzy.ai.steer.Limiter; 21 | 22 | /** A {@code NullLimiter} always throws {@link UnsupportedOperationException}. Typically it's used as the base class of partial or 23 | * immutable limiters. 24 | * 25 | * @author davebaol */ 26 | public class NullLimiter implements Limiter { 27 | 28 | /** An immutable limiter whose getters return {@link Float#POSITIVE_INFINITY} and setters throw 29 | * {@link UnsupportedOperationException}. */ 30 | public static final NullLimiter NEUTRAL_LIMITER = new NullLimiter() { 31 | 32 | @Override 33 | public float getMaxLinearSpeed () { 34 | return Float.POSITIVE_INFINITY; 35 | } 36 | 37 | @Override 38 | public float getMaxLinearAcceleration () { 39 | return Float.POSITIVE_INFINITY; 40 | } 41 | 42 | @Override 43 | public float getMaxAngularSpeed () { 44 | return Float.POSITIVE_INFINITY; 45 | } 46 | 47 | @Override 48 | public float getMaxAngularAcceleration () { 49 | return Float.POSITIVE_INFINITY; 50 | } 51 | 52 | }; 53 | 54 | /** Creates a {@code NullLimiter}. */ 55 | public NullLimiter () { 56 | } 57 | 58 | /** Guaranteed to throw UnsupportedOperationException. 59 | * @throws UnsupportedOperationException always */ 60 | @Override 61 | public float getMaxLinearSpeed () { 62 | throw new UnsupportedOperationException(); 63 | } 64 | 65 | /** Guaranteed to throw UnsupportedOperationException. 66 | * @throws UnsupportedOperationException always */ 67 | @Override 68 | public void setMaxLinearSpeed (float maxLinearSpeed) { 69 | throw new UnsupportedOperationException(); 70 | } 71 | 72 | /** Guaranteed to throw UnsupportedOperationException. 73 | * @throws UnsupportedOperationException always */ 74 | @Override 75 | public float getMaxLinearAcceleration () { 76 | throw new UnsupportedOperationException(); 77 | } 78 | 79 | /** Guaranteed to throw UnsupportedOperationException. 80 | * @throws UnsupportedOperationException always */ 81 | @Override 82 | public void setMaxLinearAcceleration (float maxLinearAcceleration) { 83 | throw new UnsupportedOperationException(); 84 | } 85 | 86 | /** Guaranteed to throw UnsupportedOperationException. 87 | * @throws UnsupportedOperationException always */ 88 | @Override 89 | public float getMaxAngularSpeed () { 90 | throw new UnsupportedOperationException(); 91 | } 92 | 93 | /** Guaranteed to throw UnsupportedOperationException. 94 | * @throws UnsupportedOperationException always */ 95 | @Override 96 | public void setMaxAngularSpeed (float maxAngularSpeed) { 97 | throw new UnsupportedOperationException(); 98 | } 99 | 100 | /** Guaranteed to throw UnsupportedOperationException. 101 | * @throws UnsupportedOperationException always */ 102 | @Override 103 | public float getMaxAngularAcceleration () { 104 | throw new UnsupportedOperationException(); 105 | } 106 | 107 | /** Guaranteed to throw UnsupportedOperationException. 108 | * @throws UnsupportedOperationException always */ 109 | @Override 110 | public void setMaxAngularAcceleration (float maxAngularAcceleration) { 111 | throw new UnsupportedOperationException(); 112 | } 113 | 114 | @Override 115 | public float getZeroLinearSpeedThreshold () { 116 | return 0.001f; 117 | } 118 | 119 | /** Guaranteed to throw UnsupportedOperationException. 120 | * @throws UnsupportedOperationException always */ 121 | @Override 122 | public void setZeroLinearSpeedThreshold (float zeroLinearSpeedThreshold) { 123 | throw new UnsupportedOperationException(); 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/proximities/InfiniteProximity.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.steer.proximities; 18 | 19 | 20 | import com.jzy.ai.steer.Proximity; 21 | import com.jzy.ai.steer.Steerable; 22 | import com.jzy.javalib.math.geometry.Vector; 23 | 24 | /** {@code InfiniteProximity} is likely the simplest type of Proximity one can imagine. All the agents contained in the specified 25 | * list are considered neighbors of the owner, excluded the owner itself (if it is part of the list). 26 | * 27 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 28 | * 29 | * @author davebaol */ 30 | public class InfiniteProximity> extends ProximityBase { 31 | 32 | /** Creates a {@code InfiniteProximity} for the specified owner and list of agents. 33 | * @param owner the owner of this proximity 34 | * @param agents the list of agents */ 35 | public InfiniteProximity(Steerable owner, Iterable> agents) { 36 | super(owner, agents); 37 | } 38 | 39 | @Override 40 | public int findNeighbors (Proximity.ProximityCallback callback) { 41 | int neighborCount = 0; 42 | for (Steerable currentAgent : agents) { 43 | // Make sure the agent being examined isn't the owner 44 | if (currentAgent != owner) { 45 | if (callback.reportNeighbor(currentAgent)) { 46 | neighborCount++; 47 | } 48 | } 49 | } 50 | 51 | return neighborCount; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/proximities/ProximityBase.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.steer.proximities; 18 | 19 | 20 | import com.jzy.ai.steer.Proximity; 21 | import com.jzy.ai.steer.Steerable; 22 | import com.jzy.javalib.math.geometry.Vector; 23 | 24 | /** {@code ProximityBase} is the base class for any concrete proximity based on an iterable collection of agents. 25 | * 26 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 27 | * 28 | * @author davebaol */ 29 | public abstract class ProximityBase> implements Proximity { 30 | 31 | /** The owner of this proximity. */ 32 | protected Steerable owner; 33 | 34 | /** The collection of the agents handled by this proximity. 35 | *

    36 | * Note that, being this field of type {@code Iterable}, you can either use java or libgdx collections. See 37 | * https://github.com/libgdx/gdx-ai/issues/65 */ 38 | protected Iterable> agents; 39 | 40 | /** Creates a {@code ProximityBase} for the specified owner and list of agents. 41 | * @param owner the owner of this proximity 42 | * @param agents the list of agents */ 43 | public ProximityBase(Steerable owner, Iterable> agents) { 44 | this.owner = owner; 45 | this.agents = agents; 46 | } 47 | 48 | @Override 49 | public Steerable getOwner () { 50 | return owner; 51 | } 52 | 53 | @Override 54 | public void setOwner (Steerable owner) { 55 | this.owner = owner; 56 | } 57 | 58 | /** Returns the the agents that represent potential neighbors. */ 59 | public Iterable> getAgents () { 60 | return agents; 61 | } 62 | 63 | /** Sets the agents that represent potential neighbors. */ 64 | public void setAgents (Iterable> agents) { 65 | this.agents = agents; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/util/Path.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.steer.util; 18 | 19 | 20 | import com.jzy.javalib.math.geometry.Vector; 21 | 22 | /** The {@code Path} for an agent having path following behavior. A path can be shared by multiple path following behaviors because 23 | * its status is maintained in a {@link PathParam} local to each behavior. 24 | *

    25 | * The most common type of path is made up of straight line segments, which usually gives reasonably good results while keeping 26 | * the math simple. However, some driving games use splines to get smoother curved paths, which makes the math more complex. 27 | * 28 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 29 | * @param

    Type of path parameter implementing the {@link PathParam} interface 30 | * 31 | * @author davebaol */ 32 | public interface Path, P extends Path.PathParam> { 33 | 34 | /** Returns a new instance of the path parameter. */ 35 | public P createParam(); 36 | 37 | /** Returns {@code true} if this path is open; {@code false} otherwise. */ 38 | public boolean isOpen(); 39 | 40 | /** Returns the length of this path. */ 41 | public float getLength(); 42 | 43 | /** Returns the first point of this path. */ 44 | public T getStartPoint(); 45 | 46 | /** Returns the last point of this path. */ 47 | public T getEndPoint(); 48 | 49 | /** Maps the given position to the nearest point along the path using the path parameter to ensure coherence and returns the 50 | * distance of that nearest point from the start of the path. 51 | * @param position a location in game space 52 | * @param param the path parameter 53 | * @return the distance of the nearest point along the path from the start of the path itself. */ 54 | public float calculateDistance(T position, P param); 55 | 56 | /** Calculates the target position on the path based on its distance from the start and the path parameter. 57 | * @param out the target position to calculate 58 | * @param param the path parameter 59 | * @param targetDistance the distance of the target position from the start of the path */ 60 | public void calculateTargetPosition(T out, P param, float targetDistance); 61 | 62 | /** A path parameter used by path following behaviors to keep the path status. 63 | * 64 | * @author davebaol */ 65 | public static interface PathParam { 66 | 67 | /** Returns the distance from the start of the path */ 68 | public float getDistance(); 69 | 70 | /** Sets the distance from the start of the path 71 | * @param distance the distance to set */ 72 | public void setDistance(float distance); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/util/RayConfiguration.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.steer.util; 18 | 19 | 20 | import com.jzy.ai.util.Ray; 21 | import com.jzy.javalib.math.geometry.Vector; 22 | 23 | /** A {@code RayConfiguration} is a collection of rays typically used for collision avoidance. 24 | * 25 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 26 | * 27 | * @author davebaol */ 28 | public interface RayConfiguration> { 29 | Ray[] updateRays(); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/util/rays/CentralRayWithWhiskersConfiguration.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.steer.util.rays; 18 | 19 | 20 | import com.jzy.ai.steer.Steerable; 21 | import com.jzy.ai.util.Ray; 22 | import com.jzy.javalib.math.geometry.Vector; 23 | 24 | /** A {@code CentralRayWithWhiskersConfiguration} uses a long central ray and two shorter whiskers. 25 | *

    26 | * A central ray with short whiskers is often the best initial configuration to try but can make it impossible for the character 27 | * to move down tight passages. Also, it is still susceptible to the corner trap, far less than the parallel configuration though. 29 | * 30 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 31 | * 32 | * @author davebaol */ 33 | public class CentralRayWithWhiskersConfiguration> extends RayConfigurationBase { 34 | 35 | private float rayLength; 36 | private float whiskerLength; 37 | private float whiskerAngle; 38 | 39 | /** Creates a {@code CentralRayWithWhiskersConfiguration} for the given owner where the central ray has the specified length and 40 | * the two whiskers have the specified length and angle. 41 | * @param owner the owner of this configuration 42 | * @param rayLength the length of the central ray 43 | * @param whiskerLength the length of the two whiskers (usually shorter than the central ray) 44 | * @param whiskerAngle the angle in radians of the whiskers from the central ray */ 45 | public CentralRayWithWhiskersConfiguration (Steerable owner, float rayLength, float whiskerLength, float whiskerAngle) { 46 | super(owner, 3); 47 | this.rayLength = rayLength; 48 | this.whiskerLength = whiskerLength; 49 | this.whiskerAngle = whiskerAngle; 50 | } 51 | 52 | @Override 53 | public Ray[] updateRays () { 54 | T ownerPosition = owner.getPosition(); 55 | T ownerVelocity = owner.getLinearVelocity(); 56 | 57 | float velocityAngle = owner.vectorToAngle(ownerVelocity); 58 | 59 | // Update central ray 60 | rays[0].start.set(ownerPosition); 61 | rays[0].end.set(ownerVelocity).nor().scl(rayLength).add(ownerPosition); 62 | 63 | // Update left ray 64 | rays[1].start.set(ownerPosition); 65 | owner.angleToVector(rays[1].end, velocityAngle - whiskerAngle).scl(whiskerLength).add(ownerPosition); 66 | 67 | // Update right ray 68 | rays[2].start.set(ownerPosition); 69 | owner.angleToVector(rays[2].end, velocityAngle + whiskerAngle).scl(whiskerLength).add(ownerPosition); 70 | 71 | return rays; 72 | } 73 | 74 | /** Returns the length of the central ray. */ 75 | public float getRayLength () { 76 | return rayLength; 77 | } 78 | 79 | /** Sets the length of the central ray. */ 80 | public void setRayLength (float rayLength) { 81 | this.rayLength = rayLength; 82 | } 83 | 84 | /** Returns the length of the two whiskers. */ 85 | public float getWhiskerLength () { 86 | return whiskerLength; 87 | } 88 | 89 | /** Sets the length of the two whiskers. */ 90 | public void setWhiskerLength (float whiskerLength) { 91 | this.whiskerLength = whiskerLength; 92 | } 93 | 94 | /** Returns the angle in radians of the whiskers from the central ray. */ 95 | public float getWhiskerAngle () { 96 | return whiskerAngle; 97 | } 98 | 99 | /** Sets the angle in radians of the whiskers from the central ray. */ 100 | public void setWhiskerAngle (float whiskerAngle) { 101 | this.whiskerAngle = whiskerAngle; 102 | } 103 | 104 | } 105 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/util/rays/ParallelSideRayConfiguration.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.steer.util.rays; 18 | 19 | 20 | import com.jzy.ai.steer.Steerable; 21 | import com.jzy.ai.util.Ray; 22 | import com.jzy.javalib.base.util.MathUtil; 23 | import com.jzy.javalib.math.geometry.Vector; 24 | 25 | /** A {@code ParallelSideRayConfiguration} uses two rays parallel to the direction of motion. The rays have the same length and 26 | * opposite side offset. 27 | *

    28 | * The parallel configuration works well in areas where corners are highly obtuse but is very susceptible to the corner trap. 30 | * 31 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 32 | * 33 | * @author davebaol */ 34 | public class ParallelSideRayConfiguration> extends RayConfigurationBase { 35 | 36 | private static final float HALF_PI = MathUtil.PI * 0.5f; 37 | 38 | private float length; 39 | private float sideOffset; 40 | 41 | /** Creates a {@code ParallelSideRayConfiguration} for the given owner where the two rays have the specified length and side 42 | * offset. 43 | * @param owner the owner of this ray configuration 44 | * @param length the length of the rays. 45 | * @param sideOffset the side offset of the rays. */ 46 | public ParallelSideRayConfiguration (Steerable owner, float length, float sideOffset) { 47 | super(owner, 2); 48 | this.length = length; 49 | this.sideOffset = sideOffset; 50 | } 51 | 52 | @Override 53 | public Ray[] updateRays () { 54 | float velocityAngle = owner.vectorToAngle(owner.getLinearVelocity()); 55 | 56 | // Update ray 0 57 | owner.angleToVector(rays[0].start, velocityAngle - HALF_PI).scl(sideOffset).add(owner.getPosition()); 58 | rays[0].end.set(owner.getLinearVelocity()).nor().scl(length); // later we'll add rays[0].start; 59 | 60 | // Update ray 1 61 | owner.angleToVector(rays[1].start, velocityAngle + HALF_PI).scl(sideOffset).add(owner.getPosition()); 62 | rays[1].end.set(rays[0].end).add(rays[1].start); 63 | 64 | // add start position to ray 0 65 | rays[0].end.add(rays[0].start); 66 | 67 | return rays; 68 | } 69 | 70 | /** Returns the length of the rays. */ 71 | public float getLength () { 72 | return length; 73 | } 74 | 75 | /** Sets the length of the rays. */ 76 | public void setLength (float length) { 77 | this.length = length; 78 | } 79 | 80 | /** Returns the side offset of the rays. */ 81 | public float getSideOffset () { 82 | return sideOffset; 83 | } 84 | 85 | /** Sets the side offset of the rays. */ 86 | public void setSideOffset (float sideOffset) { 87 | this.sideOffset = sideOffset; 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/util/rays/RayConfigurationBase.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.steer.util.rays; 18 | 19 | 20 | import com.jzy.ai.steer.Steerable; 21 | import com.jzy.ai.steer.util.RayConfiguration; 22 | import com.jzy.ai.util.Ray; 23 | import com.jzy.javalib.math.geometry.Vector; 24 | 25 | /** {@code RayConfigurationBase} is the base class for concrete ray configurations having a fixed number of rays. 26 | * 27 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 28 | * 29 | * @author davebaol */ 30 | public abstract class RayConfigurationBase> implements RayConfiguration { 31 | 32 | protected Steerable owner; 33 | protected Ray[] rays; 34 | 35 | /** Creates a {@code RayConfigurationBase} for the given owner and the specified number of rays. 36 | * @param owner the owner of this configuration 37 | * @param numRays the number of rays used by this configuration */ 38 | @SuppressWarnings("unchecked") 39 | public RayConfigurationBase (Steerable owner, int numRays) { 40 | this.owner = owner; 41 | this.rays = new Ray[numRays]; 42 | for (int i = 0; i < numRays; i++) 43 | this.rays[i] = new Ray(owner.getPosition().cpy().setZero(), owner.getPosition().cpy().setZero()); 44 | } 45 | 46 | /** Returns the owner of this configuration. */ 47 | public Steerable getOwner () { 48 | return owner; 49 | } 50 | 51 | /** Sets the owner of this configuration. */ 52 | public void setOwner (Steerable owner) { 53 | this.owner = owner; 54 | } 55 | 56 | /** Returns the rays of this configuration. */ 57 | public Ray[] getRays () { 58 | return rays; 59 | } 60 | 61 | /** Sets the rays of this configuration. */ 62 | public void setRays (Ray[] rays) { 63 | this.rays = rays; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/steer/util/rays/SingleRayConfiguration.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.steer.util.rays; 18 | 19 | 20 | import com.jzy.ai.steer.Steerable; 21 | import com.jzy.ai.util.Ray; 22 | import com.jzy.javalib.math.geometry.Vector; 23 | 24 | /** As the name suggests, a {@code SingleRayConfiguration} uses just one ray cast. 25 | *

    26 | * This configuration is useful in concave environments but grazes convex obstacles. It is not susceptible to the corner trap, though. 28 | * 29 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 30 | * 31 | * @author davebaol */ 32 | public class SingleRayConfiguration> extends RayConfigurationBase { 33 | 34 | private float length; 35 | 36 | /** Creates a {@code SingleRayConfiguration} for the given owner where the ray has the specified length. 37 | * @param owner the owner of this configuration 38 | * @param length the length of the ray */ 39 | public SingleRayConfiguration (Steerable owner, float length) { 40 | super(owner, 1); 41 | this.length = length; 42 | } 43 | 44 | @Override 45 | public Ray[] updateRays () { 46 | rays[0].start.set(owner.getPosition()); 47 | rays[0].end.set(owner.getLinearVelocity()).nor().scl(length).add(rays[0].start); 48 | return rays; 49 | } 50 | 51 | /** Returns the length of the ray. */ 52 | public float getLength () { 53 | return length; 54 | } 55 | 56 | /** Sets the length of the ray. */ 57 | public void setLength (float length) { 58 | this.length = length; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/util/Collision.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.util; 18 | 19 | 20 | import com.jzy.javalib.math.geometry.Vector; 21 | 22 | /** A {@code Collision} is made up of a collision point and the normal at that point of collision. 23 | * 24 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 25 | * 26 | * @author davebaol */ 27 | public class Collision> { 28 | 29 | /** The collision point. */ 30 | public T point; 31 | 32 | /** The normal of this collision. */ 33 | public T normal; 34 | 35 | /** Creates a {@code Collision} with the given {@code point} and {@code normal}. 36 | * @param point the point where this collision occurred 37 | * @param normal the normal of this collision */ 38 | public Collision(T point, T normal) { 39 | this.point = point; 40 | this.normal = normal; 41 | } 42 | 43 | /** Sets this collision from the given collision. 44 | * @param collision The collision 45 | * @return this collision for chaining. */ 46 | public Collision set (Collision collision) { 47 | this.point.set(collision.point); 48 | this.normal.set(collision.normal); 49 | return this; 50 | } 51 | 52 | /** Sets this collision from the given point and normal. 53 | * @param point the collision point 54 | * @param normal the normal of this collision 55 | * @return this collision for chaining. */ 56 | public Collision set (T point, T normal) { 57 | this.point.set(point); 58 | this.normal.set(normal); 59 | return this; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/util/IMemoryObject.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.util; 2 | 3 | /** 4 | * 对象池对象 5 | */ 6 | public interface IMemoryObject { 7 | 8 | /** 9 | * 对象释放 10 | */ 11 | public void release(); 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/util/Location.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.util; 2 | 3 | /******************************************************************************* 4 | * Copyright 2014 See AUTHORS file. 5 | * 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 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | ******************************************************************************/ 18 | 19 | 20 | import com.jzy.javalib.math.geometry.Vector; 21 | 22 | /** The {@code Location} interface represents any game object having a position and an orientation. 23 | * 24 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 25 | * 26 | * @author davebaol */ 27 | public interface Location> { 28 | 29 | /** Returns the vector indicating the position of this location. */ 30 | public T getPosition (); 31 | 32 | /** Returns the float value indicating the orientation of this location. The orientation is the angle in radians representing 33 | * the direction that this location is facing. */ 34 | public float getOrientation (); 35 | 36 | /** Sets the orientation of this location, i.e. the angle in radians representing the direction that this location is facing. 37 | * @param orientation the orientation in radians */ 38 | public void setOrientation (float orientation); 39 | 40 | /** Returns the angle in radians pointing along the specified vector. 41 | * @param vector the vector */ 42 | public float vectorToAngle (T vector); 43 | 44 | /** Returns the unit vector in the direction of the specified angle expressed in radians. 45 | * @param outVector the output vector. 46 | * @param angle the angle in radians. 47 | * @return the output vector for chaining. */ 48 | public T angleToVector (T outVector, float angle); 49 | 50 | /** Creates a new location. 51 | *

    52 | * This method is used internally to instantiate locations of the correct type parameter {@code T}. This technique keeps the API 53 | * simple and makes the API easier to use with the GWT backend because avoids the use of reflection. 54 | * @return the newly created location. */ 55 | public Location newLocation (); 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/util/MemoryPool.java: -------------------------------------------------------------------------------- 1 | package com.jzy.ai.util; 2 | 3 | import java.io.Serializable; 4 | import java.util.concurrent.LinkedBlockingQueue; 5 | 6 | /** 7 | * 缓存池 8 | */ 9 | public class MemoryPool implements Serializable { 10 | 11 | private static final long serialVersionUID = 943760723073862247L; 12 | 13 | private final LinkedBlockingQueue cache; 14 | 15 | 16 | public MemoryPool(int max) { 17 | cache = new LinkedBlockingQueue<>(max); 18 | } 19 | 20 | public void put(T value) { 21 | value.release(); 22 | this.cache.add(value); 23 | } 24 | 25 | public T get(Class c) { 26 | try { 27 | T t = this.cache.poll(); 28 | if (t == null) { 29 | t = c.newInstance(); 30 | } 31 | return t; 32 | } catch (InstantiationException e) { 33 | e.printStackTrace(); 34 | } catch (IllegalAccessException e) { 35 | e.printStackTrace(); 36 | } 37 | return null; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/util/NonBlockingSemaphore.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.util; 18 | 19 | /**非阻塞信号量
    20 | * A counting semaphore that does not block the thread when the requested 21 | * resource is not available. No actual resource objects are used; the semaphore 22 | * just keeps a count of the number available and acts accordingly. 23 | * 24 | * @author davebaol 25 | */ 26 | public interface NonBlockingSemaphore { 27 | 28 | /** 29 | * Acquires a resource if available. 30 | *

    31 | * An invocation of this method yields exactly the same result as 32 | * {@code acquire(1)} 33 | * 34 | * @return {@code true} if the resource has been acquired; {@code false} 35 | * otherwise. 36 | */ 37 | public boolean acquire(); 38 | 39 | /** 40 | * Acquires the specified number of resources if they all are available. 41 | * 42 | * @return {@code true} if all the requested resources have been acquired; 43 | * {@code false} otherwise. 44 | */ 45 | public boolean acquire(int resources); 46 | 47 | /** 48 | * Releases a resource returning it to this semaphore. 49 | *

    50 | * An invocation of this method yields exactly the same result as 51 | * {@code release(1)} 52 | * 53 | * @return {@code true} if the resource has been released; {@code false} 54 | * otherwise. 55 | */ 56 | public boolean release(); 57 | 58 | /** 59 | * Releases the specified number of resources returning it to this semaphore. 60 | * 61 | * @return {@code true} if all the requested resources have been released; 62 | * {@code false} otherwise. 63 | */ 64 | public boolean release(int resources); 65 | 66 | /** 67 | * Abstract factory for creating concrete instances of classes implementing 68 | * {@link NonBlockingSemaphore}. 69 | * 70 | * @author davebaol 71 | */ 72 | public interface Factory { 73 | 74 | /** 75 | * Creates a semaphore with the specified name and resources. 76 | * 77 | * @param name 78 | * the name of the semaphore 79 | * @param maxResources 80 | * the maximum number of resource 81 | * @return the newly created semaphore. 82 | */ 83 | public NonBlockingSemaphore createSemaphore(String name, int maxResources); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/util/NonBlockingSemaphoreRepository.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.util; 18 | 19 | import java.util.HashMap; 20 | import java.util.Map; 21 | 22 | /** 23 | * 非阻塞信号量仓库 24 | * 25 | * @author davebaol 26 | */ 27 | public class NonBlockingSemaphoreRepository { 28 | 29 | private static final Map REPO = new HashMap<>(); 30 | 31 | private static NonBlockingSemaphore.Factory FACTORY = new SimpleNonBlockingSemaphore.Factory(); 32 | 33 | public static void setFactory(NonBlockingSemaphore.Factory factory) { 34 | FACTORY = factory; 35 | } 36 | 37 | public static NonBlockingSemaphore addSemaphore(String name, int maxResources) { 38 | NonBlockingSemaphore sem = FACTORY.createSemaphore(name, maxResources); 39 | REPO.put(name, sem); 40 | return sem; 41 | } 42 | 43 | public static NonBlockingSemaphore getSemaphore(String name) { 44 | return REPO.get(name); 45 | } 46 | 47 | public static NonBlockingSemaphore removeSemaphore(String name) { 48 | return REPO.remove(name); 49 | } 50 | 51 | public static void clear() { 52 | REPO.clear(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/util/Ray.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.util; 18 | 19 | 20 | import com.jzy.javalib.math.geometry.Vector; 21 | 22 | /** A {@code Ray} is made up of a starting point and an ending point. 23 | * 24 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 25 | * 26 | * @author davebaol */ 27 | public class Ray> { 28 | 29 | /** The starting point of this ray. */ 30 | public T start; 31 | 32 | /** The ending point of this ray. */ 33 | public T end; 34 | 35 | /** Creates a {@code Ray} with the given {@code start} and {@code end} points. 36 | * @param start the starting point of this ray 37 | * @param end the starting point of this ray */ 38 | public Ray(T start, T end) { 39 | this.start = start; 40 | this.end = end; 41 | } 42 | 43 | /** Sets this ray from the given ray. 44 | * @param ray The ray 45 | * @return this ray for chaining. */ 46 | public Ray set (Ray ray) { 47 | start.set(ray.start); 48 | end.set(ray.end); 49 | return this; 50 | } 51 | 52 | /** Sets this Ray from the given start and end points. 53 | * @param start the starting point of this ray 54 | * @param end the starting point of this ray 55 | * @return this ray for chaining. */ 56 | public Ray set (T start, T end) { 57 | this.start.set(start); 58 | this.end.set(end); 59 | return this; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/util/RaycastCollisionDetector.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.util; 18 | 19 | 20 | import com.jzy.javalib.math.geometry.Vector; 21 | 22 | /** A {@code RaycastCollisionDetector} finds the closest intersection between a ray and any object in the game world. 23 | * 24 | * @param Type of vector, either 2D or 3D, implementing the {@link Vector} interface 25 | * 26 | * @author davebaol */ 27 | public interface RaycastCollisionDetector> { 28 | 29 | /** Casts the given ray to test if it collides with any objects in the game world. 30 | * @param ray the ray to cast. 31 | * @return {@code true} in case of collision; {@code false} otherwise. */ 32 | public boolean collides(Ray ray); 33 | 34 | /** Find the closest collision between the given input ray and the objects in the game world. In case of collision, 35 | * {@code outputCollision} will contain the collision point and the normal vector of the obstacle at the point of collision. 36 | * @param outputCollision the output collision. 37 | * @param inputRay the ray to cast. 38 | * @return {@code true} in case of collision; {@code false} otherwise. */ 39 | public boolean findCollision(Collision outputCollision, Ray inputRay); 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/jzy/ai/util/SimpleNonBlockingSemaphore.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.util; 18 | 19 | /** 20 | * 非线程安全的信号量
    21 | * A non-blocking semaphore that does not ensure the atomicity of its 22 | * operations, meaning that it's not tread-safe. 23 | * 24 | * @author davebaol 25 | */ 26 | public class SimpleNonBlockingSemaphore implements NonBlockingSemaphore { 27 | 28 | String name; 29 | int maxResources; 30 | int acquiredResources; 31 | 32 | /** 33 | * Creates a {@code SimpleNonBlockingSemaphore} with the given name and number 34 | * of resources. 35 | * 36 | * @param name 37 | * the name of this semaphore 38 | * @param maxResources 39 | * the number of resources 40 | */ 41 | public SimpleNonBlockingSemaphore(String name, int maxResources) { 42 | this.name = name; 43 | this.maxResources = maxResources; 44 | this.acquiredResources = 0; 45 | } 46 | 47 | @Override 48 | public boolean acquire() { 49 | return acquire(1); 50 | } 51 | 52 | @Override 53 | public boolean acquire(int resources) { 54 | if (acquiredResources + resources <= maxResources) { 55 | acquiredResources += resources; 56 | // System.out.println("sem." + name + ": acquired = TRUE, acquiredResources = " 57 | // + acquiredResources); 58 | return true; 59 | } 60 | // System.out.println("sem." + name + ": acquired = FALSE, acquiredResources = " 61 | // + acquiredResources); 62 | return false; 63 | } 64 | 65 | @Override 66 | public boolean release() { 67 | return release(1); 68 | } 69 | 70 | @Override 71 | public boolean release(int resources) { 72 | if (acquiredResources - resources >= 0) { 73 | acquiredResources -= resources; 74 | // System.out.println("sem." + name + ": released = TRUE, acquiredResources = " 75 | // + acquiredResources); 76 | return true; 77 | } 78 | // System.out.println("sem." + name + ": released = FALSE, acquiredResources = " 79 | // + acquiredResources); 80 | return false; 81 | } 82 | 83 | /** 84 | * A concrete factory that can create instances of 85 | * {@link SimpleNonBlockingSemaphore}. 86 | * 87 | * @author davebaol 88 | */ 89 | public static class Factory implements NonBlockingSemaphore.Factory { 90 | 91 | public Factory() { 92 | } 93 | 94 | @Override 95 | public NonBlockingSemaphore createSemaphore(String name, int maxResources) { 96 | return new SimpleNonBlockingSemaphore(name, maxResources); 97 | } 98 | 99 | } 100 | 101 | } 102 | --------------------------------------------------------------------------------