Pygame, simple physics engine, how to hold points between planes?
Question: I'm trying to write [this](http://www.wildbunny.co.uk/blog/2011/04/06/physics-
engines-for-dummies/) tutorial in Pygame(Python) and having problems about
holding points between planes.

My code is: [fiz2.py](https://github.com/osa1/pygame-
playground/raw/master/fiz2.py)

Vector class: [vector.py](https://github.com/osa1/pygame-
playground/raw/master/vector.py)

If you move mouse on the Pygame screen, the planes will rotate. And when the
planes are rotating, points are passing through planes and going outside.

I tried to fix points' positions on every iteration but they still passed the
planes. I have no idea about where should I fix their positions.

NOTE: I know my code is a little bit messy, this is my first 2d program and I
had really hard times getting used to Pygame's coordinate plane and vectors. I
will re-write when I solve this.

NOTE2: Yes, I wrote the comment about how to hold points between planes on the
tutorial, I understand the way he fixes positions but have no idea about
how(and where, in code) to implement it.

Thanks.


Answer: I can't tell looking at the code. My guess is a variable-timestep, causing
instability. But I can't verify if the math is right. Although, I have useful
information :

# Vectors

You can simplify code, by using vectors as a class vs list/tuple. (velocity,
acceleration, location) are treated as one object, verses separate .x and .y
values.

    
    
    # example:
    pos[0] += vel[0]
    pos[1] += vel[1]
    
    # vs
    pos += vel
    

There is a python-only implementation:
[euclid.py](http://partiallydisassembled.net/euclid.html) You can use to
compare with your vector.py.

Or use [NumPy](http://numpy.scipy.org/) [ used for 3d graphics, in openGL. ]
Is a popular, mature lib.

# physics

(It looks like you want to learn by writing your own physics), but check out
[PyMunk](http://code.google.com/p/pymunk/)

# colors

You can use: [pygame.Color](http://www.pygame.org/docs/ref/color.html)

    
    
    import pygame
    from pygame import Color
    color = Color('white')
    color2 = Color('lightgray')
    color3 = Color(0,128,128)
    

# collisions #

Look at [pygame.sprite.*collide](http://www.pygame.org/docs/ref/sprite.html) ,
and [pygame.Rect.*collide](http://www.pygame.org/docs/ref/rect.html)

# pygame Game loop with numpy vector's

Boilerplate I wrote

    
    
    """ Pygame boilerplate. <ninmonkey>2011/04
            pygame main Game() loop, and numpy for vector math.
    
    note:
            this might not be the most effecient way to use numpy as vectors, but it's an intro.
    
            And this does not force fixed-timesteps. If you want a stable simulation, you need to use a fixed timestep.
            see: http://gafferongames.com/game-physics/fix-your-timestep/
    
    Keys:
        ESC : exit
        Space : game_init()
    """
    
    import pygame
    from pygame.locals import * 
    from pygame import Color, Rect
    
    import numpy as np
    
    def get_screen_size():
        """return screen (width, height) tuple"""
        screen = pygame.display.get_surface()
        return screen.get_size()
    
    class Actor():
        """basic actor, moves randomly.
    
        members:
            loc = position vector
            velocity = velocity vector
            width, height        
        """
        def __init__(self, loc=None, velocity=None):
            """optional initial loc and velocity vectors"""
            self.width = 50
            self.height = 50
    
            # if loc or velocity are not set: use random
            if loc is None: self.rand_loc()
            else: self.loc = loc
    
            if velocity is None: self.rand_velocity()
            else: self.velocity = velocity
    
        def update(self):
            """update movement""" 
            self.loc += self.velocity
    
        def rand_velocity(self):
            """set a random vector , based on random direction. Using unit circle:        
                    x = cos(deg) * speed
            """
            rad = np.radians( np.random.randint(0,360) )
            speed = np.random.randint(1,15)
            x = np.cos(rad)
            y = np.sin(rad)
            velocity = np.array( [x,y])
            velocity *= speed
            self.velocity = velocity 
    
        def rand_loc(self):
            """random location onscreen"""
            width,height = get_screen_size()
            x = np.random.randint(0,width)
            y = np.random.randint(0,height)
            self.loc = np.array([x,y])
    
        def is_onscreen(self):
            """test is screen.colliderect(actor) true?"""
            x,y = self.loc
            w,h = get_screen_size()
    
            screen = Rect(0, 0, w, h)
            actor = Rect(x, y, self.width, self.height)
    
            if screen.colliderect(actor): return True
            else: return False
    
    class GameMain():
        """game Main entry point. handles intialization of game and graphics."""
        done = False
        debug = False
        color_gray = Color('lightgray')
    
        def __init__(self, width=800, height=600, color_bg=None):
            """Initialize PyGame"""        
            pygame.init()
            self.width, self.height = width, height
            self.screen = pygame.display.set_mode(( self.width, self.height ))
            pygame.display.set_caption( "boilerplate : pygame" )        
    
            self.clock = pygame.time.Clock()
            self.limit_fps = True
            self.limit_fps_max = 60  
    
            if color_bg is None: color_bg = Color(50,50,50)       
            self.color_bg = color_bg
    
            self.game_init()
    
        def game_init(self):
            """new game/round"""
            self.actors = [Actor() for x in range(10)]
    
        def loop(self):
            """Game() main loop"""
            while not self.done:
                self.handle_events()
                self.update()
                self.draw()
    
                if self.limit_fps: self.clock.tick( self.limit_fps_max )
                else: self.clock.tick()
    
        def update(self):        
            """update actors, handle physics"""
            for a in self.actors:
                a.update()
    
                if not a.is_onscreen():
                    a.rand_loc()
    
        def handle_events(self):
            """handle regular events. """        
            events = pygame.event.get()
            # kmods = pygame.key.get_mods() # key modifiers
    
            for event in events:
                if event.type == pygame.QUIT: sys.exit()
                elif event.type == KEYDOWN:
                    if (event.key == K_ESCAPE): self.done = True
                    elif (event.key == K_SPACE): self.game_init()
    
        def draw(self):
            """render screen"""
            # clear screen
            self.screen.fill( self.color_bg )
    
            # Actor: draw
            for a in self.actors:
                x,y = a.loc
                w,h = a.width, a.height
                r = Rect(x, y, w, h)
                self.screen.fill(self.color_gray, r)
    
            # will call update on whole screen Or flip buffer.
            pygame.display.flip()
    
    if __name__ == '__main__':
        g = GameMain()
        g.loop()
    

