Skip to content

Instantly share code, notes, and snippets.

@nakosung
Created November 25, 2016 14:29
Show Gist options
  • Save nakosung/27f836bf59a566b56cc46ee211050c40 to your computer and use it in GitHub Desktop.
Save nakosung/27f836bf59a566b56cc46ee211050c40 to your computer and use it in GitHub Desktop.
/// <reference path="typings/ue.d.ts">/>
let _ = require('lodash')
function maybe_create_ai() {
let controller = GWorld.GetAllActorsOfClass(AIController).OutActors[0]
if (!controller) {
let BP = Blueprint.Load('/Game/TopDownBP/Blueprints/TopDownCharacter.TopDownCharacter')
let old = GWorld.GetAllActorsOfClass(Character).OutActors[0]
let pos = old.GetActorLocation()
let character = new BP.GeneratedClass(GWorld,{X:pos.X + 100,Y:pos.Y + 100,Z:pos.Z})
controller = new AIController(GWorld)
controller.Possess(character)
let cc = new CapsuleComponent(character)
cc.SetCapsuleRadius(400)
controller.overlapping = () => _.without(cc.GetOverlappingActors().OverlappingActors,character)
cc.AttachTo(character.GetRootComponent())
cc.RegisterComponent()
}
let callback
function moveTo(pos) {
let result = controller.MoveToLocation(pos,10,true,true,true,true)
if (result == 'RequestSuccessful') {
return new Promise(resolve => callback = resolve)
} else if (result == 'AlreadyAtGoal') {
return Promise.resolve()
} else {
return Promise.reject(new Error(result))
}
}
// Hook up delegate
controller.ReceiveMoveCompleted = [function() {
console.log('relay',...arguments,callback)
let fn = callback
callback = null
fn && fn()
}]
// Add js method (only visible to js)
controller.moveTo = moveTo
controller.destroy = function() {
let character = controller.GetControlledPawn()
character.DestroyActor()
controller.DestroyActor()
}
return controller
}
function show_widget(elem) {
if (!global.$widget) {
let widget = GWorld.CreateWidget(JavascriptWidget, GWorld.GetPlayerController(0))
widget.proxy = {}
widget.JavascriptContext = Context
widget.AddToViewport()
global.$widget = widget
}
let widget = global.$widget
widget.RemoveFromViewport()
widget.SetRootWidget(elem)
widget.AddToViewport()
}
function demo_ui(msg) {
let UMG = require('UMG')
function click_1() {
console.log("HELLO")
}
function click_2() {
console.log("WORLD")
}
let ui = UMG.div({},
UMG.text({},"Demo"),
UMG.span({},
UMG(Button,{Slot:{Size:{SizeRule:'Fill'}},OnClicked:click_1},"This button"),
UMG(Button,{Slot:{Size:{SizeRule:'Fill'}},OnClicked:click_2},"Rocks")
),
UMG.text({TextDelegate: msg},"")
)
let instantiator = require('instantiator')
show_widget(instantiator(ui))
}
function network() {
let convnetjs = require('convnetjs')
let layer_defs = [
{type:'input', out_sx:1, out_sy:1, out_depth:2},
{type:'fc', num_neurons:20, activation:'relu'},
{type:'fc', num_neurons:20, activation:'relu'},
{type:'softmax', num_classes:2}
]
let net = new convnetjs.Net()
net.makeLayers(layer_defs)
let trainer = new convnetjs.SGDTrainer(net, {learning_rate:0.001})
let denom = 1000
function X(pos) {
return new convnetjs.Vol([pos.X/denom,pos.Y/denom])
}
return {
predict: x => {
return net.forward(X(x)).w[1]
},
train: (x,y) => trainer.train(X(x),y).loss
}
}
module.exports = function () {
let controller = maybe_create_ai()
let net = network()
let stat = ''
function train() {
let pos = controller.GetActorLocation()
let prob = net.predict(pos)
let overlap = controller.overlapping()
let loss = net.train(pos, overlap.length)
stat = `loss: ${loss.toFixed(4)} overlap:${overlap.length>0}`
}
demo_ui(_ => stat)
function step() {
return controller.moveTo(GWorld.GetRandomReachablePointInRadius(controller.GetActorLocation(), 500))
}
function sequence(head,...tail) {
return head().then(_ => tail.length && sequence(...tail))
}
let alive = true
function loop() {
if (!alive) return
train()
process.nextTick(loop)
}
loop()
sequence(step,step,step,step,step)
.then(_ => alive = false)
.then(_ => console.log("BT completed"))
.then(_ => controller.destroy())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment