orientation

This commit is contained in:
monsterkodi 2016-08-17 00:01:38 +02:00
parent 8fe52dbe50
commit 113176a132
9 changed files with 217 additions and 77 deletions

View File

@ -107,7 +107,6 @@ class Bot extends Pushable
@addEventWithName "died"
@startTimedAction @getActionWithId(Action.NOOP), 500
# 0000000 000 00000000 00000000 0000000 000000000 000 0000000 000 000
# 000 000 000 000 000 000 000 000 000 000 000 0000 000
@ -371,7 +370,7 @@ class Bot extends Pushable
# 000 000 000 000 000 0000000 000 000 00000000 0000000
actionFinished: (action) ->
log "bot.actionFinished #{action.name} #{action.id}"
# log "bot.actionFinished #{action.name} #{action.id}"
# if @isDead()
# log "DIE!"
@ -391,7 +390,7 @@ class Bot extends Pushable
super action
return
if @move_action # action was not a move action -> return
if @move_action? # action was not a move action -> return
# log 'bot.actionFinished was not a move action!'
return
@ -409,9 +408,10 @@ class Bot extends Pushable
@move_action = @getActionWithId Action.CLIMB_UP
world.playSound 'BOT_LAND', @getPos(), 0.5
else if world.isUnoccupiedPos @position.plus @getDown() # below will be empty
log 'below empty', world.isUnoccupiedPos(@position.plus @getDown()), @position.plus @getDown()
# log 'bot.actionFinished below empty', world.isUnoccupiedPos(@position.plus @getDown()), @position.plus @getDown()
if @move # sticky if moving
if world.isUnoccupiedPos @position.plus @getDir() # forward will be empty
if world.isUnoccupiedPos @position.plus @getDir() # forward will be empty
log 'bot.actionFinished forward empty'
if world.isOccupiedPos @position.plus @getDir().minus @getUp() # below forward is solid
occupant = world.getOccupantAtPos @position.plus @getDir().minus @getUp()
if not occupant? or not occupant?.isSlippery()
@ -421,7 +421,7 @@ class Bot extends Pushable
if not occupant? or not occupant?.isSlippery()
@move_action = @getActionWithId Action.CLIMB_UP
if @move_action == null
if not @move_action?
@move_action = @getActionWithId Action.FALL
@direction = @getDown()
@ -431,13 +431,15 @@ class Bot extends Pushable
else
world.playSound 'BOT_LAND', @getPos()
if @move_action
if @move_action?
Timer.addAction @move_action
return
return if @rotate_action
return if @rotate_action?
if @move or @jump
@fixOrientationAndPosition()
if @move or @jump or @jump_once
@moveBot()
else
@dir_sgn = 1
@ -445,6 +447,10 @@ class Bot extends Pushable
# keep action chain flowinwg in order to detect environment changes
# @startTimedAction @getActionWithId(Action.NOOP), 0
fixOrientationAndPosition: ->
@setPosition @current_position.round()
@setOrientation @current_orientation.round()
# 00 00 0000000 000 000 00000000
# 000 000 000 000 000 000 000
# 000000000 000 000 000 000 0000000

View File

@ -51,7 +51,6 @@ class Item extends Actor
setOrientation: (q) ->
@current_orientation = @orientation = new Quaternion q
# log "item.setOrientation:", @orientation
@orientation
setCurrentPosition: (p) -> @current_position = p
setCurrentOrientation: (q) -> @current_orientation = q

View File

@ -16,7 +16,7 @@ module.exports =
player:
coordinates: [3,0,1]
nostatus: 0
orientation: roty0
orientation: rot0
exits: [
name: "exit"
active: 1

View File

@ -1,3 +1,10 @@
# 000 000 000 00 00 00000000
# 000 000 000 000 000 000 000
# 000 000 000 000000000 00000000
# 000 000 000 000 000 0 000 000
# 0000000 0000000 000 000 000
module.exports =
name: "jump"
scheme: "red_scheme"
@ -12,7 +19,9 @@ module.exports =
you can attach to a stone when falling
if you move into its direction
"""
player: position: [0,0,5]
player:
position: [0,0,5]
orientation: rotx270
exits: [
name: "exit"
active: 1

View File

@ -22,7 +22,7 @@ module.exports =
"""
player:
position: [0,0,-5]
orientation: roty0
orientation: rot0
exits: [
name: "exit"
active: 1

View File

@ -9,7 +9,7 @@ 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
@ -33,13 +33,62 @@ class Quaternion
@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
new Quaternion(Math.cos(t), v.x*s, v.y*s, v.z*s).normalize()
copy: -> new Quaternion @
clone: (q) ->
@x = q.x
@y = q.y
@z = q.z
@w = q.w
@
round: ->
@normalize()
minDist = 1000
minQuat = null
up = @rotate Vector.unitY
back = @rotate Vector.unitZ
for q in [ Quaternion.XupY
Quaternion.XupZ
Quaternion.XdownY
Quaternion.XdownZ
Quaternion.YupX
Quaternion.YupZ
Quaternion.YdownX
Quaternion.YdownZ
Quaternion.ZupX
Quaternion.ZupY
Quaternion.ZdownX
Quaternion.ZdownY
Quaternion.minusXupY
Quaternion.minusXupZ
Quaternion.minusXdownY
Quaternion.minusXdownZ
Quaternion.minusYupX
Quaternion.minusYupZ
Quaternion.minusYdownX
Quaternion.minusYdownZ
Quaternion.minusZupX
Quaternion.minusZupY
Quaternion.minusZdownX
Quaternion.minusZdownY
]
upDiff = 1 - up.dot q.rotate Vector.unitY
backDiff = 1 - back.dot q.rotate Vector.unitZ
l = upDiff + backDiff
# log "length #{upDiff} #{backDiff} #{q.name} #{l}"
if l < minDist
minDist = l
minQuat = q
if l < 0.0001
break
log "differ a lot! #{minDist}" if minDist > 0.05
return @clone minQuat
euler: -> [
Vector.RAD2DEG Math.atan2 2*(@w*@x+@y*@z), 1-2*(@x*@x+@y*@y)
Vector.RAD2DEG Math.asin 2*(@w*@y-@z*@x)
Vector.RAD2DEG Math.atan2 2*(@w*@z+@x*@y), 1-2*(@y*@y+@z*@z)]
add: (quat) ->
@w += quat.w
@ -55,6 +104,10 @@ class Quaternion
@z -= quat.z
@
minus: (quat) -> @copy().sub quat
dot: (q) -> @x*q.x + @y*q.y + @z*q.z + @w*q.w
rotate: (v) ->
qv = new Quaternion v
rq = @mul qv.mul @getConjugate()
@ -73,9 +126,9 @@ class Quaternion
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
@x = -@x/l
@y = -@y/l
@z = -@z/l
@
isZero: -> @x==@y==@z==0 and @w==1
@ -90,9 +143,9 @@ class Quaternion
@z = -@z
@
getNormal: -> new Quaternion(@).normalize()
getConjugate: -> new Quaternion(@).conjugate()
getInverse: -> new Quaternion(@).invert()
getNormal: -> @copy().normalize()
getConjugate: -> @copy().conjugate()
getInverse: -> @copy().invert()
neg: -> new Quaternion -@w,-@x,-@y,-@z
vector: -> new Vector @x, @y, @z
length: -> Math.sqrt @w*@w + @x*@x + @y*@y + @z*@z
@ -152,4 +205,99 @@ class Quaternion
scale0 * @y + scale1 * to1[1],
scale0 * @z + scale1 * to1[2]
@rotationAroundVector: (theta, vector) ->
v = new Vector vector
v.normalize()
t = Vector.DEG2RAD(theta)/2.0
s = Math.sin t
(new Quaternion Math.cos(t), v.x*s, v.y*s, v.z*s).normalize()
@rotationFromEuler: (x,y,z) ->
x = Vector.DEG2RAD x
y = Vector.DEG2RAD y
z = Vector.DEG2RAD z
q=new Quaternion Math.cos(x/2) * Math.cos(y/2) * Math.cos(z/2) + Math.sin(x/2) * Math.sin(y/2) * Math.sin(z/2),
Math.sin(x/2) * Math.cos(y/2) * Math.cos(z/2) - Math.cos(x/2) * Math.sin(y/2) * Math.sin(z/2),
Math.cos(x/2) * Math.sin(y/2) * Math.cos(z/2) + Math.sin(x/2) * Math.cos(y/2) * Math.sin(z/2),
Math.cos(x/2) * Math.cos(y/2) * Math.sin(z/2) - Math.sin(x/2) * Math.sin(y/2) * Math.cos(z/2)
q.normalize()
@rot_0 = new Quaternion()
@rot_90_X = @rotationAroundVector 90, Vector.unitX
@rot_90_Y = @rotationAroundVector 90, Vector.unitY
@rot_90_Z = @rotationAroundVector 90, Vector.unitZ
@rot_180_X = @rotationAroundVector 180, Vector.unitX
@rot_180_Y = @rotationAroundVector 180, Vector.unitY
@rot_180_Z = @rotationAroundVector 180, Vector.unitZ
@rot_270_X = @rotationAroundVector 270, Vector.unitX
@rot_270_Y = @rotationAroundVector 270, Vector.unitY
@rot_270_Z = @rotationAroundVector 270, Vector.unitZ
@XupY = @rot_270_Y
@XupZ = @rot_90_X.mul @rot_270_Y
@XdownY = @rot_180_X.mul @rot_270_Y
@XdownZ = @rot_270_X.mul @rot_270_Y
@YupX = @rot_90_Y.mul @rot_90_X
@YupZ = @rot_90_X
@YdownX = @rot_270_Y.mul @rot_90_X
@YdownZ = @rot_180_Y.mul @rot_90_X
@ZupX = @rot_90_Z.mul @rot_180_X
@ZupY = @rot_180_Z.mul @rot_180_X
@ZdownX = @rot_270_Z.mul @rot_180_X
@ZdownY = @rot_180_X
@minusXupY = @rot_90_Y
@minusXupZ = @rot_90_X.mul @rot_90_Y
@minusXdownY = @rot_180_X.mul @rot_90_Y
@minusXdownZ = @rot_270_X.mul @rot_90_Y
@minusYupX = @rot_270_Y.mul @rot_270_X
@minusYupZ = @rot_180_Y.mul @rot_270_X
@minusYdownX = @rot_90_Y.mul @rot_270_X
@minusYdownZ = @rot_270_X
@minusZupX = @rot_270_Z
@minusZupY = @rot_0
@minusZdownX = @rot_90_Z
@minusZdownY = @rot_180_Z
@rot_0.name = '@rot_0'
@rot_90_X.name = '@rot_90_X'
@rot_90_Y.name = '@rot_90_Y'
@rot_90_Z.name = '@rot_90_Z'
@rot_180_X.name = '@rot_180_X'
@rot_180_Y.name = '@rot_180_Y'
@rot_180_Z.name = '@rot_180_Z'
@rot_270_X.name = '@rot_270_X'
@rot_270_Y.name = '@rot_270_Y'
@rot_270_Z.name = '@rot_270_Z'
@XupY.name = '@XupY'
@XupZ.name = '@XupZ'
@XdownY.name = '@XdownY'
@XdownZ.name = '@XdownZ'
@YupX.name = '@YupX'
@YupZ.name = '@YupZ'
@YdownX.name = '@YdownX'
@YdownZ.name = '@YdownZ'
@ZupX.name = '@ZupX'
@ZupY.name = '@ZupY'
@ZdownX.name = '@ZdownX'
@ZdownY.name = '@ZdownY'
@minusXupY.name = '@minusXupY'
@minusXupZ.name = '@minusXupZ'
@minusXdownY.name = '@minusXdownY'
@minusXdownZ.name = '@minusXdownZ'
@minusYupX.name = '@minusYupX'
@minusYupZ.name = '@minusYupZ'
@minusYdownX.name = '@minusYdownX'
@minusYdownZ.name = '@minusYdownZ'
@minusZupX.name = '@minusZupX'
@minusZupY.name = '@minusZupY'
@minusZdownX.name = '@minusZdownX'
@minusZdownY.name = '@minusZdownY'
module.exports = Quaternion

View File

@ -331,7 +331,7 @@ class Player extends Bot
@new_dir_sgn = @dir_sgn = (combo == @key.backward) and -1 or 1
@moveBot() # perform new move action (depending on environment)
else
if @move_action.name == 'jump' and @move_action.getRelativeTime() < 1
if @move_action.id == Action.JUMP and @move_action.getRelativeTime() < 1
if world.isUnoccupiedPos(@position.plus(@getUp()).plus(@getDir())) and
world.isUnoccupiedPos(@position.plus(@getDir())) # forward and above forward also empty
action = @getActionWithId Action.JUMP_FORWARD
@ -353,12 +353,16 @@ class Player extends Bot
@jump = true # switch to jump mode until jump_key released
@jump_once = true
if not @move_action?
@moveBot() # perform new move action (depending on environment)
@moveBot() # perform jump action (depending on environment)
@jump_once = false
else
if @move_action.id == Action.MOVE and @move_action.getRelativeTime() < 0.6 or
# log 'jump:moving'
if @move_action.id == Action.FORWARD and @move_action.getRelativeTime() < 0.6 or
@move_action.id == Action.CLIMB_DOWN and @move_action.getRelativeTime() < 0.4
# abort current move and jump instead
# log 'jump:move or climb down'
if world.isUnoccupiedPos @position.plus @getUp()
# log 'jump:can do'
if world.isUnoccupiedPos @position.plus @getUp().plus @getDir()
action = @getActionWithId Action.JUMP_FORWARD
else
@ -366,6 +370,7 @@ class Player extends Bot
action.takeOver @move_action
Timer.removeAction @move_action
@move_action = action
@jump_once = false
Timer.addAction @move_action
else if @move_action.id in [Action.JUMP, Action.JUMP_FORWARD]
@jump_once = false
@ -414,13 +419,7 @@ class Player extends Bot
when @key.jump
@jump = false
@jump_once = false
# if @jump_once
# if not @move_action? and world.isUnoccupiedPos @position.plus @getUp()
# @jump_once = false
# @move_action = @getActionWithId Action.JUMP
# world.playSound 'BOT_JUMP'
# Timer.addAction @move_action
# @jump_once = false
return true
when @key.left, @key.right
@ -443,11 +442,11 @@ class Player extends Bot
false
# 0000000 000 0000000 00000000 000 0000000 000 000
# 000 000 000 000 000 000 000 000 000 000 000
# 000 000 000 0000000 00000000 000 000000000 00000
# 000 000 000 000 000 000 000 000 000
# 0000000 000 0000000 000 0000000 000 000 000
# 0000000 000 0000000 00000000 000 0000000 000 000
# 000 000 000 000 000 000 000 000 000 000 000
# 000 000 000 0000000 00000000 000 000000000 00000
# 000 000 000 000 000 000 000 000 000
# 0000000 000 0000000 000 0000000 000 000 000
step: (step) -> super step

View File

@ -42,7 +42,7 @@ class Pushable extends Item
initAction: (action) ->
switch action.id
when Action.FALL
log 'Pushable.initAction FALL direction:', @direction
# log 'Pushable.initAction FALL direction:', @direction
world.objectWillMoveToPos @, @position.plus(@direction), action.getDuration()
performAction: (action) ->
@ -58,7 +58,7 @@ class Pushable extends Item
@move_action = null
targetPos = @current_position.round()
world.objectMoved @, @position, targetPos
log "Pushable.finishAction setPosition:", targetPos
# log "Pushable.finishAction setPosition:", targetPos
@setPosition targetPos
actionFinished: (action) ->
@ -83,7 +83,7 @@ class Pushable extends Item
if world.isUnoccupiedPos @position.plus gravityDir
@direction = gravityDir
@move_action = @getActionWithId Action.FALL
log 'Pushable.actionFinished below empty, fall!'
# log 'Pushable.actionFinished below empty, fall!'
Timer.addAction @move_action
else
@direction.reset()

View File

@ -131,17 +131,17 @@ class World extends Actor
@initGlobal: () ->
return if @levels?
global.rot0 = new Quaternion()
global.rotz90 = Quaternion.rotationAroundVector 90, Vector.unitZ
global.rotz180 = Quaternion.rotationAroundVector 180, Vector.unitZ
global.roty0 = Quaternion.rotationAroundVector 0, Vector.unitY
global.roty90 = Quaternion.rotationAroundVector 90, Vector.unitY
global.roty180 = Quaternion.rotationAroundVector 180, Vector.unitY
global.roty270 = Quaternion.rotationAroundVector 270, Vector.unitY
global.rotx90 = Quaternion.rotationAroundVector 90, Vector.unitX
global.rotx180 = Quaternion.rotationAroundVector 180, Vector.unitX
global.rotx270 = Quaternion.rotationAroundVector 270, Vector.unitX
global.rot0 = Quaternion.rot_0
global.rotx90 = Quaternion.rot_90_X
global.roty90 = Quaternion.rot_90_Y
global.rotz90 = Quaternion.rot_90_Z
global.rotx180 = Quaternion.rot_180_X
global.roty180 = Quaternion.rot_180_Y
global.rotz180 = Quaternion.rot_180_Z
global.rotx270 = Quaternion.rot_270_X
global.roty270 = Quaternion.rot_270_Y
global.rotz270 = Quaternion.rot_270_Z
@levels = new Levels
@ -269,27 +269,6 @@ class World extends Actor
log 'world.levelFinished'
# saves the current level status in highscore file
# highscore.levelFinished world.level_name, Controller.player.getStatus().getMoves()
# 00000000 00000000 0000000 00000000 000000000 00000000 000 0000000 000 000 00000000 00000000
# 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000 000
# 0000000 0000000 0000000 0000000 000 00000000 000 000000000 00000 0000000 0000000
# 000 000 000 000 000 000 000 000 000 000 000 000 000 000
# 000 000 00000000 0000000 00000000 000 000 0000000 000 000 000 00000000 000 000
resetPlayer: () ->
# reset the player to it's original position and orientation
log 'world.resetPlayer', @dict.player
if @dict.player.resetOrientation?
@player.setOrientation @dict.player.resetOrientation
else if @dict.player.orientation?
@player.setOrientation @dict.player.orientation
else
@player.setOrientation rot0
if @dict.player.resetPosition?
world.moveObjectToPos @player, world.decenter @dict.player.resetPosition
else
world.moveObjectToPos @player, world.decenter @dict.player.position
# 000 000 0000000 000 000 000000000
# 000 000 000 000 000 000