changeset 66:12ec95a2e8ea

Bouncing.
author Simon Cross <hodgestar@gmail.com>
date Sun, 03 Apr 2011 22:56:47 +0200
parents bcf3d0b2a6d8
children 64b135316b80
files skaapsteker/constants.py skaapsteker/physics.py
diffstat 2 files changed, 45 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/skaapsteker/constants.py	Sun Apr 03 22:46:25 2011 +0200
+++ b/skaapsteker/constants.py	Sun Apr 03 22:56:47 2011 +0200
@@ -9,6 +9,8 @@
 
 DEBUG = True
 
+EPSILON = 1e-10
+
 # Layer defination
 class Layers(object):
     BACKGROUND = 0  # Absolute background
--- a/skaapsteker/physics.py	Sun Apr 03 22:46:25 2011 +0200
+++ b/skaapsteker/physics.py	Sun Apr 03 22:56:47 2011 +0200
@@ -7,7 +7,7 @@
 import pygame.draw
 import pygame
 import time
-from constants import DEBUG, Layers
+from constants import DEBUG, EPSILON
 
 class Sprite(pygame.sprite.DirtySprite):
 
@@ -25,7 +25,9 @@
         self.visible = 1
         self.dirty = 1
         self.blendmode = 0
-        self._layer = Layers.BACKGROUND
+
+    def init_pos(self):
+        self._float_pos = self.rect.topleft
 
     def draw_debug(self, surface):
         pygame.draw.rect(surface, (240, 0, 0), self.rect, 1)
@@ -42,8 +44,24 @@
 
     def deltap(self, dt):
         v_x, v_y = self.velocity
+        f_x, f_y = self._float_pos
         d_x, d_y = v_x * dt, v_y * dt
-        self.rect.move_ip(d_x, d_y)
+        f_x, f_y = f_x + d_x, f_y + d_y
+        self._float_pos = f_x, f_y
+        self.rect.topleft = int(f_x), int(f_y)
+
+    def collide(self, other):
+        print "Collided:", self, other
+
+    def collide_immobile(self, immobile):
+        print "Collided with immobile:", self, immobile
+        v_x, v_y = self.velocity
+        clip = self.rect.clip(immobile.rect)
+        frac_x = clip.width / abs(v_x) if abs(v_x) > EPSILON else 0.0
+        frac_y = clip.height / abs(v_y) if abs(v_y) > EPSILON else 0.0
+        frac = max(frac_x, frac_y)
+        self.velocity = (-v_x, -v_y)
+        self.deltap(frac)
 
 
 class World(object):
@@ -53,13 +71,17 @@
     def __init__(self):
         self._all = pygame.sprite.LayeredUpdates()
         self._mobiles = pygame.sprite.Group()
+        self._immobiles = pygame.sprite.Group()
         self._gravitators = pygame.sprite.Group()
         self._last_time = None
 
     def add(self, sprite):
+        sprite.init_pos()
         self._all.add(sprite)
         if sprite.mobile:
             self._mobiles.add(sprite)
+        else:
+            self._immobiles.add(sprite)
         if sprite.gravitates:
             self._gravitators.add(sprite)
 
@@ -82,10 +104,24 @@
             sprite.deltap(dt)
 
         # check for collisions
-        for sprite1, sprites in pygame.sprite.groupcollide(self._mobiles, self._all, False, False).iteritems():
-            for sprite2 in sprites:
-                if sprite1 is sprite2:
-                    continue
+        collisions = []
+        collide = collisions.append
+        for sprite1 in self._mobiles.sprites():
+            spritecollide = sprite1.rect.colliderect
+            for sprite2 in self._mobiles.sprites():
+                if id(sprite1) < id(sprite2) and spritecollide(sprite2):
+                    collide((sprite1, sprite2))
+            for sprite2 in self._immobiles.sprites():
+                if spritecollide(sprite2):
+                    collide((sprite1, sprite2))
+        self.dispatch_collisions(collisions)
+
+    def dispatch_collisions(self, collisions):
+        for s1, s2 in collisions:
+            if not s2.mobile:
+                s1.collide_immobile(s2)
+            else:
+                s1.collide(s2)
 
     def draw(self, surface):
         self._all.draw(surface)