#!/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()