From d8286b39e0ac3e37fc6450d598b7715d69efc0a9 Mon Sep 17 00:00:00 2001 From: monsterkodi Date: Sat, 13 Aug 2016 19:43:42 +0200 Subject: [PATCH] bot --- coffee/bot.coffee | 25 +++++++-------- coffee/cell.coffee | 3 +- coffee/lib/pos.coffee | 18 ++++++----- coffee/lib/quaternion.coffee | 61 +++++++++++++++++++++++------------- coffee/lib/vector.coffee | 60 ++++++++++++++++++++++------------- coffee/player.coffee | 15 ++++----- coffee/world.coffee | 15 ++++----- 7 files changed, 116 insertions(+), 81 deletions(-) diff --git a/coffee/bot.coffee b/coffee/bot.coffee index 49b711e..4e0c670 100644 --- a/coffee/bot.coffee +++ b/coffee/bot.coffee @@ -74,10 +74,10 @@ class Bot extends Pushable @startTimedAction @getActionWithId(Action.NOOP), 500 - getDown: -> @orientation.rotate(new Vector 0,1,0).neg() getUp: -> @orientation.rotate(new Vector 0,1,0) getDir: -> @orientation.rotate(new Vector 0,0,1).mul @dir_sgn + getCurrentDir: -> @current_orientation.rotate(new Vector(0,0,1)).normal() addMoves: (m) -> @moves += m addHealth: (h) -> @health = Math.max @health+h @@ -123,24 +123,24 @@ class Bot extends Pushable switch action.id when Action.NOOP then return - - when Action.FORWARD then newPos += @getDir() - when Action.CLIMB_DOWN then newPos += @getDir() + @getDown() - when Action.JUMP then newPos += @getUp() - when Action.JUMP_FORWARD then newPos += @getUp() + @getDir() - when Action.FALL_FORWARD then newPos += @getDown() + @getDir() + when Action.FORWARD then newPos.add @getDir() + when Action.CLIMB_DOWN then newPos.add @getDir().plus @getDown() + when Action.JUMP then newPos.add @getUp() + when Action.JUMP_FORWARD then newPos.add @getUp().plus @getDir() + when Action.FALL_FORWARD then newPos.add @getDown().plus @getDir() when Action.FALL if not @direction.isZero() super action return else - newPos += @getDown() + newPos.add @getDown() break else super action return - if newPos != @position + if not newPos.eql @position + log 'bot.initAction', newPos world.objectWillMoveToPos @, newPos, action.getDuration() performAction: (action) -> @@ -148,8 +148,8 @@ class Bot extends Pushable relTime = action.getRelativeTime() dltTime = action.getRelativeDelta() - log "Bot.performAction #{action.name} #{action.current} #{action.last} #{action.duration} id #{actionId}" - log "Bot.performAction #{action.name} #{relTime} #{dltTime} id #{actionId}" + # log "Bot.performAction #{action.name} #{action.current} #{action.last} #{action.duration} id #{actionId}" + # log "Bot.performAction #{action.name} #{relTime} #{dltTime} id #{actionId}" switch actionId when Action.SHOOT @@ -398,9 +398,6 @@ class Bot extends Pushable @move_action.keepRest() # try to make subsequent actions smooth Timer.addAction @move_action - getCurrentDir: -> @current_orientation.rotate(new Vector(0,0,1)).normal() - getDir: -> @dir_sgn * @orientation.rotate new Vector 0,0,1 - render: () -> radius = 0.5 tireRadius = 0.15 diff --git a/coffee/cell.coffee b/coffee/cell.coffee index 036e0b2..8722ee7 100644 --- a/coffee/cell.coffee +++ b/coffee/cell.coffee @@ -10,7 +10,8 @@ TmpObject = require './tmpobject' class Cell constructor: () -> @objects = [] - + + isEmpty: -> @objects.length == 0 getObjectsOfType: (clss) -> @objects.filter (o) -> o instanceof clss getObjectOfType: (clss) -> _.find @objects, (o) -> o instanceof clss diff --git a/coffee/lib/pos.coffee b/coffee/lib/pos.coffee index 46eb54d..c3188b4 100644 --- a/coffee/lib/pos.coffee +++ b/coffee/lib/pos.coffee @@ -5,13 +5,14 @@ # 000 000 000 000 # 000 0000000 0000000 +log = require '/Users/kodi/s/ko/js/tools/log' Vector = require './vector' class Pos constructor: (x=0, y=0, z=0) -> - if x instanceof Vector or x instanceof Pos + if (x instanceof Vector) or (x instanceof Pos) @x = parseInt x.x @y = parseInt x.y @z = parseInt x.z @@ -23,6 +24,9 @@ class Pos @x = parseInt x @y = parseInt y @z = parseInt z + # log "Pos #{x} #{y} #{z}", @ + if Number.isNaN @x + throw new Error vector: () -> new Vector x, y, z minus: (p) -> new Pos @x-p.x, @y-p.y, @z-p.z @@ -32,15 +36,15 @@ class Pos eql: (p) -> @x==p.x and @y==p.y and @z==p.z add: (p) -> - @x += p.x - @y += p.y - @z += p.z + @x = parseInt @x + p.x + @y = parseInt @y + p.y + @z = parseInt @z + p.z @ sub: (p) -> - @x -= p.x - @y -= p.y - @z -= p.z + @x = parseInt @x - p.x + @y = parseInt @y - p.y + @z = parseInt @z - p.z @ module.exports = Pos diff --git a/coffee/lib/quaternion.coffee b/coffee/lib/quaternion.coffee index a4c0d0d..6e38a5d 100644 --- a/coffee/lib/quaternion.coffee +++ b/coffee/lib/quaternion.coffee @@ -5,27 +5,40 @@ # 000 0000 000 000 000 000 000 000 000 000 000 0000 000 000 000 000 0000 # 00000 00 0000000 000 000 000 00000000 000 000 000 000 000 0000000 000 000 +log = require '/Users/kodi/s/ko/js/tools/log' Vector = require './vector' class Quaternion - constructor: (@w=1, @x=0, @y=0, @z=0) -> - if @w instanceof Vector - @x = @w.x - @y = @w.y - @z = @w.z + constructor: (w=1, x=0, y=0, z=0) -> + if w instanceof Vector + @x = w.x + @y = w.y + @z = w.z @w = 0 - else if @w instanceof Quaternion - @x = @w.x - @y = @w.y - @z = @w.z - @w = @w.w + else if w instanceof Quaternion + @x = w.x + @y = w.y + @z = w.z + @w = w.w + else if Array.isArray w + @w = w[0] + @x = w[1] + @y = w[2] + @z = w[3] + else + @x = x + @y = y + @z = z + @w = w + if Number.isNaN @x + throw new Error @rotationAroundVector: (theta, vector) -> v = new Vector vector v.normalize() t = Vector.DEG2RAD(theta)/2.0 - s = Math.sin(t) + s = Math.sin t new Quaternion(Math.cos(t), v.x*s, v.y*s, v.z*s).normalize() add: (quat) -> @@ -48,15 +61,21 @@ class Quaternion new Vector rq.x, rq.y, rq.z normalize: -> - l = Math.sqrt(w*w + x*x + y*y + z*z) + l = Math.sqrt @w*@w + @x*@x + @y*@y + @z*@z if l != 0.0 - w /= l; x /= l; y /= l; z /= l + @w /= l + @x /= l + @y /= l + @z /= l @ invert: -> - l = Math.sqrt(w*w + x*x + y*y + z*z) + l = Math.sqrt @w*@w + @x*@x + @y*@y + @z*@z if l != 0.0 - w /= l; x = -x/l; y = -y/l; z = -z/l + @w /= l + @x = -x/l + @y = -y/l + @z = -z/l @ isZero: -> @x==@y==@z==0 and @w==1 @@ -120,17 +139,17 @@ class Quaternion to1[3] = quat.w if (1.0 - cosom) > 0.001 # calculate coefficients - omega = Math.acos(cosom) # standard case (slerp) - sinom = Math.sin(omega) + omega = Math.acos cosom # standard case (slerp) + sinom = Math.sin omega scale0 = Math.sin((1.0 - t) * omega) / sinom scale1 = Math.sin(t * omega) / sinom else # "from" and "to" quaternions are very close -> we can do a linear interpolation scale0 = 1.0 - t scale1 = t - new Quaternion scale0 * w + scale1 * to1[3], - scale0 * x + scale1 * to1[0], - scale0 * y + scale1 * to1[1], - scale0 * z + scale1 * to1[2] + new Quaternion scale0 * @w + scale1 * to1[3], + scale0 * @x + scale1 * to1[0], + scale0 * @y + scale1 * to1[1], + scale0 * @z + scale1 * to1[2] module.exports = Quaternion \ No newline at end of file diff --git a/coffee/lib/vector.coffee b/coffee/lib/vector.coffee index f3004af..35c3aa7 100644 --- a/coffee/lib/vector.coffee +++ b/coffee/lib/vector.coffee @@ -5,28 +5,32 @@ # 000 000 000 000 000 000 000 000 # 0 00000000 0000000 000 0000000 000 000 -# X = 0 -# SX = 0 -# Y = 1 -# Z = 2 -# W = 3 -# SY = 5 -# SZ = 10 -# TX = 12 -# TY = 13 -# TZ = 14 +log = require '/Users/kodi/s/ko/js/tools/log' class Vector - constructor: (@x,@y,@z,@w) -> - if @x instanceof Vector - @copy @x + constructor: (x=0,y=0,z=0,w=0) -> + if x.x? and x.y? + @copy x + else if Array.isArray x + @x = x[0] + @y = x[1] + @z = x[2] + @w = x[3] ? 0 + else + @x = x + @y = y + @z = z + @w = w + if Number.isNaN @x + throw new Error + # log "Vector #{x} #{y} #{z} #{w} -> #{@x} #{@y} #{@z} #{@w}" copy: (v) -> @x = v.x @y = v.y - @z = v.z - @w = v.w + @z = v.z ? 0 + @w = v.w ? 0 @ normal: -> new Vector(@).normalize() @@ -64,18 +68,19 @@ class Vector xyangle: (v) -> thisXY = new Vector(@x, @y).normal() otherXY = new Vector(v.x, v.y).normal() - if thisXY.xyperp() * otherXY >= 0 - return Vector.RAD2DEG(Math.acos(thisXY * otherXY)) - -Vector.RAD2DEG(Math.acos(thisXY * otherXY)); + if thisXY.xyperp().dot otherXY >= 0 + return Vector.RAD2DEG(Math.acos(thisXY.dot otherXY)) + -Vector.RAD2DEG(Math.acos(thisXY.dot otherXY)) length: -> Math.sqrt @x*@x+@y*@y+@z*@z+@w*@w - angle: (v) -> Vector.RAD2DEG Math.acos @normal()*v.normal() + angle: (v) -> Vector.RAD2DEG Math.acos @normal().dot v.normal() dot: (v) -> @x*v.x + @y*v.y + @z*v.z + @w*v.w - mul: (f) -> new Vector @x*f, @y*f, @z*f, @w*f - div: (d) -> new Vector @x/d, @y/d, @z/d, @w/d + mul: (f) -> new Vector @x*f, @y*f, @z*f, @w*f + div: (d) -> new Vector @x/d, @y/d, @z/d, @w/d plus: (v) -> new Vector @x+v.x, @y+v.y, @z+v.z, @w+v.w minus: (v) -> new Vector @x-v.x, @y-v.y, @z-v.z, @w-v.w + neg: -> new Vector -@x, -@y, -@z, -@w add: (v) -> @x += v.x @@ -102,9 +107,20 @@ class Vector @x = @y = @z = @w = 0 @ - isZero: -> @x == @y == @z == 0 + isZero: -> @x == @y == @z == @w == 0 @DEG2RAD: (d) -> Math.PI*d/180.0 @RAD2DEG: (r) -> r*180.0/Math.PI + + @X = 0 + @SX = 0 + @Y = 1 + @Z = 2 + @W = 3 + @SY = 5 + @SZ = 10 + @TX = 12 + @TY = 13 + @TZ = 14 module.exports = Vector \ No newline at end of file diff --git a/coffee/player.coffee b/coffee/player.coffee index 4941602..cf55245 100644 --- a/coffee/player.coffee +++ b/coffee/player.coffee @@ -120,7 +120,7 @@ class Player extends Bot getProjection: () -> # smooth camera movement a little bit posDelta = world.getSpeed() / 10.0 - @projection.setPosition ((1.0 - posDelta) * @projection.getPosition() + posDelta * @current_position) + @projection.setPosition @projection.getPosition().mul(1.0 - posDelta).plus @current_position.mul posDelta playerDir = @getCurrentDir() playerUp = @current_orientation.rotate(new Vector(0,1,0)).normal() @@ -129,11 +129,11 @@ class Player extends Bot @projection.setXVector playerUp.cross(playerDir).normal() @look_rot = Quaternion.rotationAroundVector @look_angle, @projection.getXVector() @projection.setYVector @look_rot.rotate playerUp - @projection.setZVector @look_rot.rotate -playerDir + @projection.setZVector @look_rot.rotate playerDir.neg() else # smooth camera rotation a little bit lookDelta = (2.0 - @projection.getZVector().dot playerDir) * world.getSpeed() / 50.0 - newLookVector = @projection.getZVector().mul(1.0 - lookDelta).minus playerDir.mul lookDelta + newLookVector = @projection.getZVector().mul(1.0 - lookDelta).minus playerDir.mul lookDelta newLookVector.normalize() @projection.setXVector playerUp.cross(newLookVector).normal() @@ -172,7 +172,7 @@ class Player extends Bot @projection.setXVector(playerUp.cross(playerDir).normal()) KQuaternion look_rot = KQuaternion.rotationAroundVector(@look_angle, @projection.getXVector()) @projection.setYVector(look_rot.rotate(playerUp)) - @projection.setZVector(look_rot.rotate(-playerDir)) + @projection.setZVector(look_rot.rotate(playerDir.neg())) else # smooth camera rotation a little bit lookDelta = 0.3 @@ -294,11 +294,12 @@ class Player extends Bot actionId = action.id switch actionId when Action.CLIMB_DOWN, Action.FORWARD - @status.addMoves 1 + # @status.addMoves 1 + log 'init action forward' when Action.TURN_LEFT, Action.TURN_RIGHT world.playSound 'BOT_MOVE' - when Action.JUMP, Action.JUMP_FORWARD - @status.addMoves actionId == Action.JUMP and 1 or 2 + when Action.JUMP + # @status.addMoves actionId == Action.JUMP and 1 or 2 world.playSound 'BOT_JUMP' super action diff --git a/coffee/world.coffee b/coffee/world.coffee index e1d2082..6eba8a1 100644 --- a/coffee/world.coffee +++ b/coffee/world.coffee @@ -345,7 +345,7 @@ class World extends Actor world.moveObjectToPos player, world.decenter(player_dict["position"]) performAction: (name, time) -> - log "world.performAction #{name}" + # log "world.performAction #{name}" # action callback. used to exit current world if /exit/.test name @finish() @@ -564,7 +564,7 @@ class World extends Actor cell.removeObject object if cell.isEmpty() # delete cell - @cells[posToIndex(pos)] = null + @cells[@posToIndex(pos)] = null newObject: (object) -> if _.isString object @@ -657,20 +657,17 @@ class World extends Actor objectWillMoveToPos: (object, pos, duration) -> log "world.objectWillMoveToPos", pos - cell = @getCellAtPos pos - + if @isInvalidPos pos log "objectWillMoveToPos invalid pos:", pos - if object.getPos() == pos + if object.getPos().eql pos log "WARNING objectWillMoveToPos equal pos:", pos return - - if cell + + if cell = @getCellAtPos pos if objectAtNewPos = cell.getOccupant() if objectAtNewPos instanceof TmpObject - tmpObject = objectAtNewPos - if objectAtNewPos.time < 0 and -objectAtNewPos.time <= duration # temporary object at new pos will vanish before object will arrive . delete it objectAtNewPos.del()