<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff>@@ -44,8 +44,13 @@ class Sprite &lt; Widget
     parent.contents.select { |c| c != self }
   end
 
+  def relations
+    siblings.unshift parent
+  end
+
   def gravity( gx, gy )
     @gravity_x, @gravity_y = gx, gy
+    @stuck = false
   end
 
   def push( px, py )
@@ -56,6 +61,8 @@ class Sprite &lt; Widget
     @velocity_y = @max_velocity_y  if @velocity_y &gt; @max_velocity_y
     @velocity_x = -@max_velocity_x if @velocity_x &lt; -@max_velocity_x
     @velocity_y = -@max_velocity_y if @velocity_y &lt; -@max_velocity_y
+
+    @stuck = false
   end
 
   def update_bounce( dx, dy )
@@ -63,7 +70,7 @@ class Sprite &lt; Widget
       pw, ph = parent.width, parent.height
 
       if @left &lt; 0
-        @left = 0
+        @left = 1
         if @gravity_x &lt; 0 &amp;&amp;
            (@gravity_x * @friction_x - @velocity_x) &lt; @min_velocity_x
           @velocity_x = 0
@@ -71,7 +78,7 @@ class Sprite &lt; Widget
           @velocity_x = -@velocity_x
         end
       elsif @left + @width &gt; pw
-        @left = pw - @width
+        @left = pw - @width - 1
         if @gravity_x &gt; 0 &amp;&amp;
            (@velocity_x - @gravity_x * @friction_x) &lt; @min_velocity_x
           @velocity_x = 0
@@ -81,7 +88,7 @@ class Sprite &lt; Widget
       end
 
       if @top &lt; 0
-        @top = 0
+        @top = 1
         if @gravity_y &lt; 0 &amp;&amp;
            (@gravity_y * @friction_y - @velocity_y) &lt; @min_velocity_y
           @velocity_y = 0
@@ -89,7 +96,7 @@ class Sprite &lt; Widget
           @velocity_y = -@velocity_y
         end
       elsif @top + @height &gt; ph
-        @top = ph - @height
+        @top = ph - @height - 1
         if @gravity_y &gt; 0 &amp;&amp;
            (@velocity_y - @gravity_y * @friction_y) &lt; @min_velocity_y
           @velocity_y = 0
@@ -105,47 +112,146 @@ class Sprite &lt; Widget
       sx, sy, sw, sh = sib.left, sib.top, sib.width, sib.height
       rebound = sib.style[:push]
 
+      unless @left + @width &lt;= sx || @left &gt;= sx + sw ||
+             @top + @height &lt;= sy || @top &gt;= sy + sh
+
+        # collision!
+
+        if @velocity_y &lt; 0 &amp;&amp; @top - dy &gt; sy + sh
+          @top = sy + sh - 1
+          @velocity_y = -@velocity_y + rebound
+        end
+
+        if @velocity_y &gt; 0 &amp;&amp; @top - dy + @height &lt; sy
+          @top = sy - @height + 1
+          @velocity_y = -@velocity_y - rebound
+        end
+
+        if @velocity_x &lt; 0 &amp;&amp; @left - dx &gt; sx + sw
+          @left = sx + sw - 1
+          @velocity_x = -@velocity_x + rebound
+        end
+
+        if @velocity_x &gt; 0 &amp;&amp; @left - dx + @width &lt; sx
+          @left = sx - @width + 1
+          @velocity_x = -@velocity_x - rebound
+        end
+      end
+    end
+  end
+
+  def update_stick( dx, dy )
+    if parent.style[:sticky]
+      pw, ph = parent.width, parent.height
+
+      if @velocity_y &lt; 0 &amp;&amp; @top &lt; 0
+        @top = 1
+        @velocity_x = 0
+        @velocity_y = 0
+        @stuck = true
+      end
+
+      if @velocity_y &gt; 0 &amp;&amp; @top + @height &gt; ph
+        @top = ph - @height - 1
+        @velocity_x = 0
+        @velocity_y = 0
+        @stuck = true
+      end
+
+      if @velocity_x &lt; 0 &amp;&amp; @left &lt; 0
+        @left = 1
+        @velocity_x = 0
+        @velocity_y = 0
+        @stuck = true
+      end
+
+      if @velocity_x &gt; 0 &amp;&amp; @left + @width &gt; pw
+        @left = pw - @width - 1
+        @velocity_x = 0
+        @velocity_y = 0
+        @stuck = true
+      end
+    end
+
+    siblings.each do |sib|
+      next unless sib.style[:sticky]
+
+      sx, sy, sw, sh = sib.left, sib.top, sib.width, sib.height
+      rebound = sib.style[:push]
+
       unless @left + @width &lt; sx || @left &gt; sx + sw ||
              @top + @height &lt; sy || @top &gt; sy + sh
 
         # collision!
-
-        a = []
+        @stuck = true
 
         if @velocity_y &lt; 0 &amp;&amp; @top - dy &gt; sy + sh
           @top = sy + sh + 1
-          @velocity_y = -@velocity_y + rebound
+          @velocity_x = 0
+          @velocity_y = 0
         end
 
         if @velocity_y &gt; 0 &amp;&amp; @top - dy + @height &lt; sy
           @top = sy - @height - 1
-          @velocity_y = -@velocity_y - rebound
+          @velocity_x = 0
+          @velocity_y = 0
         end
 
         if @velocity_x &lt; 0 &amp;&amp; @left - dx &gt; sx + sw
           @left = sx + sw + 1
-          @velocity_x = -@velocity_x + rebound
+          @velocity_x = 0
+          @velocity_y = 0
         end
 
         if @velocity_x &gt; 0 &amp;&amp; @left - dx + @width &lt; sx
           @left = sx - @width - 1
-          @velocity_x = -@velocity_x - rebound
+          @velocity_x = 0
+          @velocity_y = 0
         end
       end
     end
   end
 
+  def touching?( sibling, edge )
+    sx, sy, sw, sh = sibling.left, sibling.top, sibling.width, sibling.height
+
+    case edge
+      when :top    
+        @top == sy - @height - 1 &amp;&amp; 
+        ! (@left &gt; sx + sw || @left + @width &lt; sx)
+      when :bottom 
+        @top == sy + sh + 1 &amp;&amp;
+        ! (@left &gt; sx + sw || @left + @width &lt; sx)
+      when :left   
+        @left == sx - @width - 1 &amp;&amp;
+        ! (@top &gt; sy + sh || @top + @height &lt; sy)
+      when :right
+        @left == sx + sw + 1 &amp;&amp;
+        ! (@top &gt; sy + sh || @top + @height &lt; sy)
+    end
+  end
+
   def update_movement( delta )
-    change = false
+    return if @stuck
 
     if (@gravity_x &gt; 0 &amp;&amp; @left + @width &lt; parent.width) ||
        (@gravity_x &lt; 0 &amp;&amp; @left &gt; 0)
-      @velocity_x += @gravity_x * delta
+
+      if (@gravity_x &gt; 0 &amp;&amp; ! siblings.any? { |s| touching?( s, :left ) }) ||
+         (@gravity_x &lt; 0 &amp;&amp; ! siblings.any? { |s| touching?( s, :right ) }) 
+
+        @velocity_x += @gravity_x * delta
+      end
     end
 
     if (@gravity_y &gt; 0 &amp;&amp; @top + @height &lt; parent.height) ||
-       (@gravity_y &lt; 0 &amp;&amp; @top &gt; 0)
-      @velocity_y += @gravity_y * delta
+       (@gravity_y &lt; 0 &amp;&amp; @top &gt; 0) 
+
+      if (@gravity_y &gt; 0 &amp;&amp; ! siblings.any? { |s| touching?( s, :top ) }) ||
+         (@gravity_y &lt; 0 &amp;&amp; ! siblings.any? { |s| touching?( s, :bottom ) })
+
+        @velocity_y += @gravity_y * delta
+      end
     end
 
     return if @velocity_x == 0.0 &amp;&amp; @velocity_y == 0.0
@@ -154,6 +260,7 @@ class Sprite &lt; Widget
     @top  += (dy = @velocity_y * delta)
 
     update_bounce( dx, dy )
+    update_stick( dx, dy )
 
     @velocity_x *= 1.0 - (1.0 - @friction_x) * delta
     @velocity_y *= 1.0 - (1.0 - @friction_y) * delta
@@ -177,7 +284,7 @@ Shoes.app :width =&gt; 400, :height =&gt; 400, :title =&gt; &quot;Sprite Demo&quot; do
   stack :top =&gt; 0, :left =&gt; 0, :width =&gt; 400, :height =&gt; 400, :bouncy =&gt; true do
   
     stack :top =&gt; 186, :left =&gt; 100, :width =&gt; 200, :height =&gt; 28,
-          :bouncy =&gt; true, :push =&gt; 100 do
+                   :bouncy =&gt; true, :push =&gt; 100 do
       background &quot;ddd&quot;
       @p = para &quot;down&quot;, :align =&gt; 'center'
     end
@@ -195,10 +302,24 @@ Shoes.app :width =&gt; 400, :height =&gt; 400, :title =&gt; &quot;Sprite Demo&quot; do
       when :up    then @s.push(   0, -90 )
       when :down  then @s.push(   0,  90 )
 
-      when :alt_j then @s.gravity( -80,   0 ); @p.text = &quot;left&quot;
-      when :alt_l then @s.gravity(  80,   0 ); @p.text = &quot;right&quot;
-      when :alt_i then @s.gravity(   0, -80 ); @p.text = &quot;up&quot;
-      when :alt_k then @s.gravity(   0,  80 ); @p.text = &quot;down&quot;
+      when :shift_left  then @s.gravity( -80,   0 ); @p.text = &quot;left&quot;
+      when :shift_right then @s.gravity(  80,   0 ); @p.text = &quot;right&quot;
+      when :shift_up    then @s.gravity(   0, -80 ); @p.text = &quot;up&quot;
+      when :shift_down  then @s.gravity(   0,  80 ); @p.text = &quot;down&quot;
+
+      when :alt_s 
+        @s.relations.each do |r| 
+          r.style[:bouncy] = false
+          r.style[:sticky] = true
+        end
+        @p.text = &quot;sticky&quot;
+
+      when :alt_b 
+        @s.relations.each do |r| 
+          r.style[:bouncy] = true
+          r.style[:sticky] = false
+        end
+        @p.text = &quot;bouncy&quot;
     end
   end
 </diff>
      <filename>sprite/sprite.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>345d016a03252e93d99944dd5ced8865a0e5fbcd</id>
    </parent>
  </parents>
  <author>
    <name>Eric K Idema</name>
    <email>eki@vying.org</email>
  </author>
  <url>http://github.com/eki/shoesfest/commit/9ab43d9cb02da0f5ffbf8b9133e360d4352dc867</url>
  <id>9ab43d9cb02da0f5ffbf8b9133e360d4352dc867</id>
  <committed-date>2008-07-25T21:06:36-07:00</committed-date>
  <authored-date>2008-07-25T21:06:36-07:00</authored-date>
  <message>Get sticky.</message>
  <tree>4e5d76e801e9f2dd700126a7cab93650995cdd5f</tree>
  <committer>
    <name>Eric K Idema</name>
    <email>eki@vying.org</email>
  </committer>
</commit>
