Skip to content

Instantly share code, notes, and snippets.

@FDelporte
Last active November 18, 2024 13:10
Show Gist options
  • Save FDelporte/e40202e6dfb188b7de1073ce02aa6439 to your computer and use it in GitHub Desktop.
Save FDelporte/e40202e6dfb188b7de1073ce02aa6439 to your computer and use it in GitHub Desktop.
A Goal Oriented Action Planning (GOAP) example, implemented with FXGL (JavaFX game library)
///usr/bin/env jbang "$0" "$@" ; exit $?
// The GOAP functionality is not fully integrated in FXGL yet, so we need to grab it
// from the Snapshots Maven Central repository.
//REPOS mavencentralsnapshots,acme=https://oss.sonatype.org/content/repositories/snapshots
// This is the FXGL version we need for this demo.
// 21+dev-SNAPSHOT has a first implementation of the GOAP functionality.
//DEPS com.github.almasb:fxgl:21+dev-SNAPSHOT
package com.almasb.fxglgames.geowars;
import com.almasb.fxgl.ai.goap.GoapAction;
import com.almasb.fxgl.ai.goap.GoapPlanner;
import com.almasb.fxgl.app.GameApplication;
import com.almasb.fxgl.app.GameSettings;
import com.almasb.fxgl.core.collection.PropertyMap;
import com.almasb.fxgl.core.math.FXGLMath;
import com.almasb.fxgl.dsl.components.WaypointMoveComponent;
import com.almasb.fxgl.entity.Entity;
import javafx.geometry.Point2D;
import javafx.geometry.Rectangle2D;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import java.util.*;
import static com.almasb.fxgl.dsl.FXGL.*;
/**
* This is a Goal Oriented Action Planning (GOAP) example,
* implemented with FXGL (JavaFX game library).
* The full info is available in a JFX In Action interview with Almas Baim.
*
* Make sure you have JBang installed, see https://www.jbang.dev/download/.
*
* Run it with:
* jbang FXGLGoapExample.java
*
* While the application is running, you can press `CTRL + R` to restart it.
*/
public class FXGLGoapExample extends GameApplication {
private Map<GoapAction, Entity> actionMap = new HashMap<>();
@Override
protected void initSettings(GameSettings settings) {
settings.setWidth(1280);
settings.setHeight(720);
}
@Override
protected void initGame() {
// Initialize the player, buildings, and GOAP actions
var player = spawnPlayer();
var allActions = new ArrayList<GoapAction>();
for (int i = 1; i <= 3; i++) {
var building = spawnBuilding(i);
GoapAction action = new GoapAction();
if (i > 1) {
action.addPrecondition("visit" + (i - 1), true);
}
action.addEffect("visit" + i, true);
allActions.add(action);
actionMap.put(action, building);
}
// Use GOAP AI to plan the move
var goal = new PropertyMap();
goal.setValue("visit3", true);
var actions = GoapPlanner.INSTANCE
.plan(new HashSet<>(allActions),
new PropertyMap(),
goal);
var points = actions.stream()
.map(a -> actionMap.get(a).getPosition())
.toList();
// Move the player to the goals according to the preconditions
player.getComponent(WaypointMoveComponent.class)
.move(points);
}
private Entity spawnPlayer() {
return entityBuilder()
.at(150, 150)
.viewWithBBox(new Rectangle(40, 40, Color.BLUE))
.with(new WaypointMoveComponent(200, Collections.emptyList()))
.buildAndAttach();
}
private Entity spawnBuilding(int i) {
return entityBuilder()
.at(FXGLMath.randomPoint(
new Rectangle2D(0, 0, getAppWidth() - 100, getAppHeight() - 100)
))
.view(new Rectangle(100, 100, FXGLMath.randomColor()))
.view(getUIFactoryService().newText("Building " + i, Color.RED, 18.0))
.buildAndAttach();
}
public static void main(String[] args) {
launch(args);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment