#!/usr/bin/python # Physics, a 2D Physics Playground for Kids # Copyright (C) 2008 Alex Levenson and Brian Jordan # Copyright (C) 2012 Daniel Francis # Copyright (C) 2012-13 Walter Bender # Copyright (C) 2013 Sai Vineet # Copyright (C) 2012-13 Sugar Labs # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Elements is Copyright (C) 2008, The Elements Team, # Wiki: http://wiki.sugarlabs.org/go/Activities/Physics # Code: git://git.sugarlabs.org/physics/mainline.git import os import sys import gtk import pygame from pygame.locals import * from pygame.color import * sys.path.append('lib/') # If your architecture is different, comment these lines and install # the modules in your system. sys.path.append('lib/Box2D-2.0.2b1-py2.5-linux-i686.egg') import Box2D as box2d import elements import tools from helpers import * class PhysicsGame: def __init__(self, activity): self.activity = activity # Get everything set up self.clock = pygame.time.Clock() self.canvas = activity.canvas self.in_focus = True # Create the name --> instance map for components self.toolList = {} for c in tools.allTools: if c.name == tools.EraseAllTool.name: self.toolList[c.name] = c(self, activity) continue self.toolList[c.name] = c(self) self.currentTool = self.toolList[tools.allTools[0].name] # Set up the world (instance of Elements) self.box2d = box2d self.opening_queue = None self.loop = True self.pygame_started = False self.full_pos_list = [] self.tracked_bodies = 0 self.trackinfo = {} def switch_off_fake_pygame_cursor_cb(self, panel, event): self.show_fake_cursor = False def switch_on_fake_pygame_cursor_cb(self, panel, event): self.show_fake_cursor = True def write_file(self, path): #Saving to journal self.world.add.remove_mouseJoint() additional_data = { 'trackinfo': self.trackinfo, 'full_pos_list': self.full_pos_list, 'tracked_bodies': self.tracked_bodies } self.world.json_save(path, additional_data, serialize=True) def read_file(self, path): #Loading from journal self.opening_queue = path def run(self, restart=False): self.screen = pygame.display.get_surface() if not restart: pygame.init() pygame.display.init() # pygame.mixer.quit() self.pygame_started = True # Fake a Sugar cursor for the pyGame canvas area self.show_fake_cursor = True pygame.mouse.set_cursor((8, 8), (0, 0), (0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0)) self.cursor_picture = pygame.image.load('standardcursor.png') self.cursor_picture.convert_alpha() self.canvas.connect('enter_notify_event', self.switch_on_fake_pygame_cursor_cb) self.canvas.connect('leave_notify_event', self.switch_off_fake_pygame_cursor_cb) self.canvas.add_events(gtk.gdk.ENTER_NOTIFY_MASK | gtk.gdk.LEAVE_NOTIFY_MASK) self.world = elements.Elements(self.screen.get_size()) self.world.renderer.set_surface(self.screen) self.world.add.ground() if self.opening_queue: path = self.opening_queue.encode('ascii', 'convert') if os.path.exists(path): self.world.json_load(path, serialized=True) if 'full_pos_list' in self.world.additional_vars: self.full_pos_list = \ self.world.additional_vars['full_pos_list'] if 'trackinfo' in self.world.additional_vars: self.trackinfo = self.world.additional_vars['trackinfo'] if 'tracked_bodies' in self.world.additional_vars: self.tracked_bodies = \ self.world.additional_vars['tracked_bodies'] while self.loop: while gtk.events_pending(): gtk.main_iteration() if not self.loop: pygame.quit() self.pygame_started = False break for event in pygame.event.get(): self.currentTool.handleEvents(event) if event.type == MOUSEBUTTONUP: if event.button == 1: self.show_fake_cursor = True if self.in_focus: # Drive motors if self.world.run_physics: bodies_present = len(self.world.world.GetBodyList()) clear_all_active = self.activity.clear_all.get_sensitive() if (bodies_present > 1) and clear_all_active is False: self.activity.clear_all.set_sensitive(True) elif (bodies_present > 1) is False and \ clear_all_active is True: self.activity.clear_all.set_sensitive(False) poslist = self.full_pos_list clear_trace_active = \ self.activity.clear_trace.get_sensitive() if poslist: if not poslist[0]: if clear_trace_active: self.activity.clear_trace.set_sensitive(False) else: if clear_trace_active is False: self.activity.clear_trace.set_sensitive(True) for key, info in self.trackinfo.iteritems(): # [host_body, tracker, color, destroyed?] body = info[1] if info[3] is False: # Not destroyed the pen trackdex = info[4] def to_screen(pos): px = self.world.meter_to_screen( pos[0]) py = self.world.meter_to_screen( pos[1]) py = self.world.renderer.get_surface() \ .get_height() - py return (px, py) x = body.position.x y = body.position.y tupled_pos = to_screen((x, y)) posx = tupled_pos[0] posy = tupled_pos[1] try: self.full_pos_list[trackdex].append(posx) self.full_pos_list[trackdex].append(posy) except IndexError: self.full_pos_list.append([posx, posy]) ''' for body in self.world.world.GetBodyList(): if isinstance(body.userData, dict): if 'rollMotor' in body.userData: rollmotor = body.userData['rollMotor'] diff = rollmotor['targetVelocity'] - \ body.GetAngularVelocity() body.ApplyTorque(rollmotor['strength'] * \ diff * body.getMassData().I) ''' # Update & Draw World self.world.update() self.screen.fill((255, 255, 255)) # 255 for white self.world.draw() # Draw output from tools self.currentTool.draw() # Show Sugar like cursor for UI consistancy if self.show_fake_cursor: self.screen.blit(self.cursor_picture, pygame.mouse.get_pos()) # Flip Display pygame.display.flip() # Stay < 30 FPS to help keep the rest of the platform responsive self.clock.tick(30) # Originally 50 def setTool(self, tool): self.currentTool.cancel() self.currentTool = self.toolList[tool] def main(activity): game = PhysicsGame(activity) return game # Make sure that main get's called if __name__ == '__main__': main()