         when 'fall'
           velocity.y = 0
 
-      samus.action = null
 
       # TODO: Gravity system?
       # TODO: always apply? or just when airborn?
       # velocity.y += 100/1000 * dt
+      # if samus.action != 'run' and samus.action != 'stand'
       max = 200/1000
       velocity.y += max/10
       velocity.y = max if velocity.y > max
-      # console.log "v #{velocity.x} #{velocity.y}"
-    
+        # console.log "v #{velocity.x} #{velocity.y}"
+      samus.action = null
+    
+
+tileWidth = 16
+samusWidth = 12
+halfSamusWidth = samusWidth/2
+samusHeight = 32
 
 Systems.register 'velocity_position', class GestureAction
   run: (estore,dt,input) ->
     for velocity in estore.getComponentsOfType('velocity')
       if position = estore.getComponent(velocity.eid, 'position')
-        dx = velocity.x * dt
-        dy = velocity.y * dt
-
+        # Current pos and velocity:
+        velX = velocity.x
+        velY = velocity.y
+
+        # Proposed movement:
+        dx = velX * dt
+        dy = velY * dt
+
+        # Proposed resulting position:
         newX = position.x + dx
         newY = position.y + dy
 
-        # Detect map collisions
-        tileRow = Math.floor(newY/16)
-        tileCol = Math.floor(newX/16)
-        row = roomData[tileRow]
-        block = null
-        if row?
-          block = row[tileCol]
-          if block?
-            if velocity.y > 0
-              newY = (tileRow * 16)
-              velocity.y = 0
-
-        if newY > 240
-          newY = 240
-          velocity.y = 0
+        # Samus box:
+        left = position.x - halfSamusWidth
+        right = left + samusWidth
+        bottom = position.y
+        top = bottom - samusHeight
+
+        newLeft = newX - samusWidth/2
+        newRight = left + samusWidth
+        newBottom = newY
+        newTop = bottom - samusHeight
+
+        # Collisions:
+        leftHits = tileSearchVertical(roomData, newLeft, top+1,bottom-1)
+        rightHits = tileSearchVertical(roomData, newRight, top+1,bottom-1)
+        topHits = tileSearchHorizontal(roomData, newTop, left+1,right-1)
+        bottomHits = tileSearchHorizontal(roomData, newBottom, left+1,right-1)
+
+
+        if leftHits.length > 0
+          newX = (Math.floor(newLeft/tileWidth) + 1) * tileWidth + halfSamusWidth
+          velX = 0 if velX < 0
+
+        if rightHits.length > 0
+          newX = Math.floor(newRight/tileWidth) * tileWidth - halfSamusWidth
+          velX = 0 if velX > 0
+
+        if bottomHits.length > 0
+          newY = Math.floor(newBottom/tileWidth) * tileWidth
+          velY = 0 if velY > 0
+
+        if topHits.length > 0
+          newY = (Math.floor(newBottom/tileWidth) + 1) * tileWidth
+          velY = 0 if velY < 0
+
+
+        # Floor safety check:
+        screenBottom = 240
+        if newY > screenBottom
+          newY = screenBottom
+          velY = 0
+
+        velocity.x = velX
+        velocity.y = velY
 
         position.x = newX
         position.y = newY

  [ null,null,null,null, null,null,null,null, null,null,null,null, null,null,null,null ]
  [ null,null,null,null, null,null,null,null, null,null,null,null, null,null,null,null ]
]

    @handleAdminControls()

    p1in = @p1Controller.update()
    # console.log p1in if p1in
    @input.controllers.player1 = p1in
    # @input.controllers.player2 = @p2Controller.update()

