diff --git a/app/lib/LevelBus.coffee b/app/lib/LevelBus.coffee
index 18985716b..707b0cef8 100644
--- a/app/lib/LevelBus.coffee
+++ b/app/lib/LevelBus.coffee
@@ -22,6 +22,7 @@ module.exports = class LevelBus extends Bus
     'level-show-victory': 'onVictory'
     'tome:spell-changed': 'onSpellChanged'
     'tome:spell-created': 'onSpellCreated'
+    'self-wizard:move': 'moveWizard'
 
   constructor: ->
     super(arguments...)
@@ -240,3 +241,12 @@ module.exports = class LevelBus extends Bus
   destroy: ->
     @session.off 'change:multiplayer', @onMultiplayerChanged, @
     super()
+
+  moveWizard : (x, y) =>
+    wizardSprite = @getSelfWizard()
+    position = wizardSprite.getCurrentPosition()
+    position.x += x
+    position.y += y
+    wizardSprite.setTarget(position,1000)
+    wizardSprite.updatePosition()
+    Backbone.Mediator.publish 'camera-zoom-to', position
diff --git a/app/lib/surface/Camera.coffee b/app/lib/surface/Camera.coffee
index 6c5ec946f..70ee37884 100644
--- a/app/lib/surface/Camera.coffee
+++ b/app/lib/surface/Camera.coffee
@@ -42,6 +42,7 @@ module.exports = class Camera extends CocoClass
     'level:restarted': 'onLevelRestarted'
     'sprite:mouse-down': 'onMouseDown'
     'sprite:dragged': 'onMouseDragged'
+    'camera-zoom-to': 'onZoomTo'
 
   # TODO: Fix tests to not use mainLayer
   constructor: (@canvasWidth, @canvasHeight, angle=Math.asin(0.75), hFOV=d2r(30)) ->
@@ -169,7 +170,7 @@ module.exports = class Camera extends CocoClass
   onMouseDown: (e) ->
     return if @dragDisabled
     @lastPos = {x: e.originalEvent.rawX, y: e.originalEvent.rawY}
-    
+
   onMouseDragged: (e) ->
     return if @dragDisabled
     target = @boundTarget(@target, @zoom)
@@ -180,7 +181,7 @@ module.exports = class Camera extends CocoClass
     @zoomTo newPos, @zoom, 0
     @lastPos = {x: e.originalEvent.rawX, y: e.originalEvent.rawY}
     Backbone.Mediator.publish 'camera:dragged'
-    
+
   onLevelRestarted: ->
     @setBounds(@firstBounds, false)
 
@@ -220,7 +221,7 @@ module.exports = class Camera extends CocoClass
     newTarget ?= {x:0, y:0}
     newTarget = (@newTarget or @target) if @locked
     newZoom = Math.min((Math.max @minZoom, newZoom), MAX_ZOOM)
-    
+
     thangType = @target?.sprite?.thangType
     if thangType
       @offset = _.clone(thangType.get('positions')?.torso or {x: 0, y:0})
@@ -229,7 +230,7 @@ module.exports = class Camera extends CocoClass
       @offset.y *= scale
     else
       @offset = {x: 0, y:0}
-      
+
     return if @zoom is newZoom and newTarget is newTarget.x and newTarget.y is newTarget.y
 
     @finishTween(true)
@@ -247,7 +248,7 @@ module.exports = class Camera extends CocoClass
       @target = newTarget
       @zoom = newZoom
       @updateZoom true
-      
+
   focusedOnSprite: ->
     return @target?.name
 
@@ -308,3 +309,6 @@ module.exports = class Camera extends CocoClass
     createjs.Tween.removeTweens @
     @finishTween = null
     super()
+
+  onZoomTo: (pos) ->
+    @zoomTo(@worldToSurface(pos), @zoom)
diff --git a/app/views/play/level/playback_view.coffee b/app/views/play/level/playback_view.coffee
index f9c13a9e3..404201e9e 100644
--- a/app/views/play/level/playback_view.coffee
+++ b/app/views/play/level/playback_view.coffee
@@ -36,6 +36,10 @@ module.exports = class PlaybackView extends View
     '⌘+p, p, ctrl+p': 'onTogglePlay'
     '⌘+[, ctrl+[': 'onScrubBack'
     '⌘+], ctrl+]': 'onScrubForward'
+    'w, up': 'onMoveUpKey'
+    's, down': 'onMoveDownKey'
+    'a, left': 'onMoveLeftKey'
+    'd, right': 'onMoveRightKey'
 
   constructor: ->
     super(arguments...)
@@ -215,3 +219,15 @@ module.exports = class PlaybackView extends View
     $(window).off('resize', @onWindowResize)
     @onWindowResize = null
     super()
+
+  onMoveUpKey: ->
+    Backbone.Mediator.publish 'self-wizard:move', 0, 10
+
+  onMoveDownKey: ->
+    Backbone.Mediator.publish 'self-wizard:move', 0, -10
+
+  onMoveLeftKey: ->
+    Backbone.Mediator.publish 'self-wizard:move', -10, 0
+
+  onMoveRightKey: ->
+    Backbone.Mediator.publish 'self-wizard:move', 10, 0