- use the
2017.1.0version of Unity if possible git clone --recursiveor clone Arcadia intoAssets
- Joseph Parker - GitHub selfsame
- Douglas P. Fields, Jr. - GitHub LispEngineer
- Joshua Suskalo - GitHub IGJoshua
- Ramsey Nasser - Github nasser
- Tims Gardner - Github timsgardener
Our entites are collections of parts, which are defined like:
(use 'game.entity)
(part {
:type :body
:id :business
:prefab :parts/business-body
:hp 1
:power 0
:mount-points {
:neck {:head 1}
:left-arm {:arm 1}
:right-arm {:arm 1}}
:hooks {:update (fn [root entity])}
:state {:foo 1}
:ai (behaviour [o]
(wait 1)
(fire o)
(AND (aim o)
(wait 1))
(end-fire o))}):typeuser taxonomy,:mount-pointsdeclare which types they allow. value can be a keyword or collection of keywords for multiple type registration:idoptional, helps with redefining parts without registering duplicates:prefabcorresponds to a prefab on a path withinAssets/Resources:hppart's contribution to total entity:hpstate, default is 1:powercontribution to total entity difficulty, (should only be used with weapons), default is 0:mount-pointskeys should match names of gameobjects in the part, vals are a probability map of which type is chosen. Note you can have a chance of no part ({nil 10}):hooksare a map of functions that will be routed from the root entity. The first arg is the root object, second is the part object. You may want to use a var if you plan on re-evaluating the function at runtime.:statewill be placed into the part state by the:procjam/partkey:aifunction that returns a collection oftween.core/timelinestyle functions. Recommended to use thebehaviourmacro, for more details see the AI section below.
Parts will match the rotation of their mount point transform. Our convention is Z+ is forward and Y+ is up, where an arm should extend along the Z+ axis.
Part meshes that use the SKIN material will have a color assigned. If your blend is saved in Assets/blends, you can just name a material "SKIN".
game.coresets up the game loopgame.worldconstructs game mapsgame.entityassembles parts into entitiesgame.datans with no deps for global stuffgame.playgame system functions (damage/kill), generic part hooksgame.aicomposable behaviour functionsgame.fxspecial effect fns
part definitions can go in user namespaces like selfsame.clj
Entity AI is described as timeline state machines (see https://github.com/selfsame/tween#timelines). Parts can contribute sequences via an :ai entry, which are concatenated and cycled through.
The :ai value should be a function that returns a collection of double wrapped functions (due to using timeline-1).
(part {
:type :brain
:ai (fn [root]
[(fn [] #(log "tick"))
(fn [] (wait 1))])})The game.ai/behaviour macro makes this a bit sleeker:
(part {
:type :brain
:ai (behaviour [o]
#(log "tick")
(wait 1))})It's recommended to read through the timeline docs and game.ai before designing behaviour sequences.
Here's a rundown of the default behavior:
(wait (?f 1))
;truthy while the player is far away, so the timeline parks here
(NOT (player-in-range? o 40))
; charge is always truthy, so we compose with a wait
; we also move on if the player is close enough
(AND (charge o)
(NOT (player-in-range? o 6))
(wait (?f 0.3 1.5)))
; due to our input model, we need to clear the :movement
; that was turned on during `charge`
(stop o)
; turn on :fire button
(fire o)
; aim is always truthy
(AND (aim o)
(wait (?f 0.5 2.0)))
(end-fire o)
; falsey, sets :movement
(wander o)
; spend some time walking
(wait (?f 0.5 1.0))
; compose strafe and aim (both truthy)
(AND (strafe o (rand-nth [-1 1]))
(aim o)
(wait (?f 0.5 2.0)))
(stop o)