From d610e626c0f6085fa27de62a3113ef722a310f85 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 08 Jul 2008 21:11:48 +0000 Subject: Total Reorganization! Now a proper activity (I hope) --- diff --git a/activity.py b/activity.py index a64014a..99e11e8 100644 --- a/activity.py +++ b/activity.py @@ -1,370 +1,33 @@ -#================================================================== -# Physics.activity -# An attempt at a Phun / Crayon Physics style physics game -# By Alex Levenson and Brian Jordan -#================================================================== - -import sys -import math +import olpcgames import pygame -from pygame.locals import * -from pygame.color import * -from sugar.activity import activity -import elements -from elements import Elements -from elements.menu import * -from tools import * - -# =======================================Classes================================== -# tools that can be used superlcass -class Tool(object): - def __init__(self): - # default tool name - self.name = "Tool" - def handleEvents(self,event): - # default event handling - if event.type == MOUSEBUTTONDOWN: - if menu.click(event.pos): return True - if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): - # bye bye! Hope you had fun! - sys.exit() - elif event.type == KEYDOWN: - if event.key == K_SPACE: - #space pauses - world.run_physics = not world.run_physics - else: - # let the subclasses know that no events were handled yet - return False - return True - def draw(self): - # default drawing method is don't draw anything - pass - def cancel(self): - # default cancel doesn't do anything - pass - -# The circle creation tool -class CircleTool(Tool): - def __init__(self): - self.name = "Circle" - self.pt1 = None - self.radius = None - def handleEvents(self,event): - #look for default events, and if none are handled then try the custom events - if not super(CircleTool,self).handleEvents(event): - if event.type == MOUSEBUTTONDOWN: - if event.button == 1: - self.pt1 = pygame.mouse.get_pos() - elif event.type == MOUSEBUTTONUP: - if event.button == 1: - if self.radius > 1: # elements doesn't like tiny shapes :( - world.add.ball(self.pt1,self.radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5) - self.pt1 = None - self.radius = None - def draw(self): - # draw a circle from pt1 to mouse - if self.pt1 != None: - self.radius = distance(self.pt1,pygame.mouse.get_pos()) - if self.radius > 3: - thick = 3 - else: - thick = 0 - pygame.draw.circle(screen, (100,180,255),self.pt1,self.radius,thick) - pygame.draw.line(screen,(100,180,255),self.pt1,pygame.mouse.get_pos(),1) - def cancel(self): - self.pt1 = None - self.radius = None - -# The box creation tool -class BoxTool(Tool): - def __init__(self): - self.name = "Box" - self.pt1 = None - self.rect = None - def handleEvents(self,event): - #look for default events, and if none are handled then try the custom events - if not super(BoxTool,self).handleEvents(event): - if event.type == MOUSEBUTTONDOWN: - if event.button == 1: - self.pt1 = pygame.mouse.get_pos() - elif event.type == MOUSEBUTTONUP: - if event.button == 1 and self.pt1!=None: - if self.rect.width > 10 and self.rect.height > 10: # elements doesn't like small shapes :( - world.add.rect(self.rect.center, self.rect.width/2, self.rect.height/2, dynamic=True, density=1.0, restitution=0.16, friction=0.5) - self.pt1 = None - - def draw(self): - # draw a box from pt1 to mouse - if self.pt1 != None: - width = pygame.mouse.get_pos()[0] - self.pt1[0] - height = pygame.mouse.get_pos()[1] - self.pt1[1] - self.rect = pygame.Rect(self.pt1, (width, height)) - self.rect.normalize() - pygame.draw.rect(screen, (100,180,255),self.rect,3) - def cancel(self): - self.pt1 = None - self.rect = None - -# The triangle creation tool -class TriangleTool(Tool): - def __init__(self): - self.name = "Triangle" - self.pt1 = None - self.vertices = None - def handleEvents(self,event): - #look for default events, and if none are handled then try the custom events - if not super(TriangleTool,self).handleEvents(event): - if event.type == MOUSEBUTTONDOWN: - if event.button == 1: - self.pt1 = pygame.mouse.get_pos() - elif event.type == MOUSEBUTTONUP: - if event.button == 1 and self.pt1!= None: - if distance(self.pt1,pygame.mouse.get_pos()) > 15: # elements doesn't like tiny shapes :( - world.add.convexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) - self.pt1 = None - self.vertices = None - def draw(self): - # draw a triangle from pt1 to mouse - if self.pt1 != None: - self.vertices = constructTriangleFromLine(self.pt1,pygame.mouse.get_pos()) - pygame.draw.polygon(screen, (100,180,255),self.vertices, 3) - pygame.draw.line(screen,(100,180,255),self.pt1,pygame.mouse.get_pos(),1) - - def cancel(self): - self.pt1 = None - self.vertices = None - -# The Polygon creation tool -class PolygonTool(Tool): - def __init__(self): - self.name = "Polygon" - self.vertices = None - def handleEvents(self,event): - #look for default events, and if none are handled then try the custom events - if not super(PolygonTool,self).handleEvents(event): - if event.type == MOUSEBUTTONDOWN: - if event.button == 1: - if not self.vertices: - self.vertices=[event.pos] - elif distance(event.pos,self.vertices[0]) < 15: - self.vertices.append(self.vertices[0]) #connect the polygon - world.add.complexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) - self.vertices = None - else: - self.vertices.append(event.pos) - if event.button == 3: - if self.vertices: - self.vertices.append(event.pos) - world.add.complexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) - self.vertices = None - - def draw(self): - # draw the poly being created - if self.vertices: - for i in range(len(self.vertices)-1): - pygame.draw.line(screen,(100,180,255),self.vertices[i],self.vertices[i+1],3) - pygame.draw.line(screen,(100,180,255),self.vertices[-1],pygame.mouse.get_pos(),3) - pygame.draw.circle(screen,(100,180,255),self.vertices[0],15,3) - - def cancel(self): - self.vertices = None +from sugar.graphics.toolbutton import ToolButton +from gettext import gettext as _ -# The magic pen tool -class MagicPenTool(Tool): - def __init__(self): - self.name = "Magic Pen" - self.vertices = None - def handleEvents(self,event): - #look for default events, and if none are handled then try the custom events - if not super(MagicPenTool,self).handleEvents(event): - if event.type == MOUSEBUTTONDOWN: - if event.button == 1: - if not self.vertices: - self.vertices=[event.pos] - elif distance(event.pos,self.vertices[0]) < 15: - self.vertices.append(self.vertices[0]) #connect the polygon - world.add.complexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) - self.vertices = None - else: - self.vertices.append(event.pos) - elif event.type == MOUSEBUTTONUP: - if event.button == 1: - if self.vertices: - world.add.complexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) - self.vertices = None - elif event.type == MOUSEMOTION: - if self.vertices: - self.vertices.append(event.pos) - - def draw(self): - # draw the poly being created - if self.vertices: - for i in range(len(self.vertices)-1): - pygame.draw.line(screen,(100,180,255),self.vertices[i],self.vertices[i+1],3) - pygame.draw.line(screen,(100,180,255),self.vertices[-1],pygame.mouse.get_pos(),3) - pygame.draw.circle(screen,(100,180,255),self.vertices[0],15,3) - - def cancel(self): - self.vertices = None +class PhysicsActivity(olpcgames.PyGameActivity): + game_name = 'physics' + game_title = 'Physics' + game_size = None # olpcgame will choose size -# The grab tool -class GrabTool(Tool): - def __init__(self): - self.name = "Grab" - def handleEvents(self,event): - #look for default events, and if none are handled then try the custom events - if not super(GrabTool,self).handleEvents(event): - if event.type == MOUSEBUTTONDOWN: - if event.button == 1: - # grab the first object at the mouse pointer - bodylist = world.get_bodies_at_pos(event.pos, include_static=False) - if bodylist and len(bodylist) > 0: - world.add.mouseJoint(bodylist[0], event.pos) - elif event.type == MOUSEBUTTONUP: - # let it go - if event.button == 1: - world.add.remove_mouseJoint() - # use box2D mouse motion - elif event.type == MOUSEMOTION and event.buttons[0]: - world.mouse_move(event.pos) - - def cancel(self): - world.add.remove_mouseJoint() - -# The joint tool -class JointTool(Tool): - def __init__(self): - self.name = "Joint" - self.jb1 = self.jb2 = self.jb1pos = self.jb2pos = None - def handleEvents(self,event): - #look for default events, and if none are handled then try the custom events - if not super(JointTool,self).handleEvents(event): - if event.type == MOUSEBUTTONDOWN: - if event.button == 1: - # grab the first body - self.jb1pos = event.pos - self.jb1 = world.get_bodies_at_pos(event.pos) - self.jb2 = self.jb2pos = None - elif event.type == MOUSEBUTTONUP: - if event.button == 1: - # grab the second body - self.jb2pos = event.pos - self.jb2 = world.get_bodies_at_pos(event.pos) - # if we have two distinct bodies, add a joint! - if self.jb1 and self.jb2 and str(self.jb1) != str(self.jb2): - world.add.joint(self.jb1[0],self.jb2[0],self.jb1pos,self.jb2pos) - # If there's only one body, add a fixed joint - elif self.jb2: - world.add.joint(self.jb2[0],self.jb2pos) - # regardless, clean everything up - self.jb1 = self.jb2 = self.jb1pos = self.jb2pos = None - if event.button == 3: - # add a centered fixed joint - self.jb2 = world.get_bodies_at_pos(event.pos) - if self.jb2: - world.add.joint(self.jb2[0]) - def draw(self): - if self.jb1: - pygame.draw.line(screen,(100,180,255),self.jb1pos,pygame.mouse.get_pos(),3) - - def cancel(self): - self.jb1 = self.jb2 = self.jb1pos = self.jb2pos = None + # custom toolbar + def build_toolbar(self): + toolbar = super(PhysicsActivity, self).build_toolbar() -# The destroy tool -class DestroyTool(Tool): - def __init__(self): - self.name = "Destroy" - self.vertices = None - def handleEvents(self,event): - #look for default events, and if none are handled then try the custom events - if not super(DestroyTool,self).handleEvents(event): - if pygame.mouse.get_pressed()[0]: - if not self.vertices: self.vertices = [] - self.vertices.append(pygame.mouse.get_pos()) - if len(self.vertices) > 10: - self.vertices.pop(0) - tokill = world.get_bodies_at_pos(pygame.mouse.get_pos()) - if tokill: - world.world.DestroyBody(tokill[0]) - elif event.type == MOUSEBUTTONUP and event.button == 1: - self.cancel() - def draw(self): - # draw the trail - if self.vertices: - if len(self.vertices) > 1: - pygame.draw.lines(screen,(255,0,0),False,self.vertices,3) - - def cancel(self): - self.vertices = None -# set up pygame -pygame.init() -size = (pygame.display.list_modes()[0]) -screen = pygame.display.set_mode(size) -clock = pygame.time.Clock() -font = pygame.font.Font(None, 24) # font object - -# setup tools -tools = { - "Triangle": TriangleTool(), - "Box": BoxTool(), - "Circle": CircleTool(), - "Polygon": PolygonTool(), - "Magic Pen": MagicPenTool(), - "Joint": JointTool(), - "Grab": GrabTool(), - "Destroy": DestroyTool() -} -currentTool = tools["Triangle"] - -def setTool(tool,discard=None): - global currentTool - currentTool.cancel() - currentTool = tools[tool] - -# setup the menus -menu = MenuClass() -menu.set_width(size[0]) -menu.addItem('Box', callback=setTool) -menu.addItem('Circle', callback=setTool) -menu.addItem('Triangle', callback=setTool) -menu.addItem('Polygon', callback=setTool) -menu.addItem('Magic Pen', callback=setTool) -menu.addItem('Grab', callback=setTool) -menu.addItem('Joint', callback=setTool) -menu.addItem('Destroy', callback=setTool) - -# set up the world -world = elements.Elements(size) -world.renderer.set_surface(screen) - -# load enviornment -world.add.ground() - -# Main Loop: -while True: - for event in pygame.event.get(): - currentTool.handleEvents(event) - - # Clear Display - screen.fill((255,255,255)) - - # Update & Draw World - world.update() - world.draw() - - # draw output from tools - currentTool.draw() - - # draw the menu - menu.draw(screen) - - #Print all the text on the screen - text = font.render("Current Tool: "+currentTool.name, True, (255,255,255)) - textpos = text.get_rect(left=700,top=7) - screen.blit(text,textpos) - - # Flip Display - pygame.display.flip() - - # Try to stay at 30 FPS - clock.tick(30) # originally 50 + # Add buttons + toolbar.button1 = ToolButton('activity-button1') + toolbar.button1.set_tooltip(_('Button One')) + toolbar.button1.connect('clicked', self._button1_cb) + toolbar.insert(toolbar.button1, 2) + toolbar.button1.show() + + toolbar.button2 = ToolButton('activity-button2') + toolbar.button2.set_tooltip(_('button-2')) + toolbar.button2.connect('clicked', self._button2_cb) + toolbar.insert(toolbar.button2, 2) + toolbar.button2.show() + return toolbar + + def _button1_cb(self, button): + pygame.event.post(olpcgames.eventwrap.Event(pygame.USEREVENT, action='button1')) + + def _button2_cb(self, button): + pygame.event.post(olpcgames.eventwrap.Event(pygame.USEREVENT, action='button2')) diff --git a/activity/activity.info b/activity/activity.info index c61c1a9..546f39b 100755 --- a/activity/activity.info +++ b/activity/activity.info @@ -1,7 +1,7 @@ -[Activity] -name = Physics -activity_version = 1 -host_version = 1 -service_name = net.coderanger.olpc.PhysicsActivity -icon = activity-physics -class = activity.PhysicsActivity +[Activity] +name = physics +service_name = org.laptop.physics +class = activity.PhysicsActivity +icon = activity-physics +activity_version = 1 +show_launcher = yes diff --git a/helpers.py b/helpers.py new file mode 100644 index 0000000..87dd4f7 --- /dev/null +++ b/helpers.py @@ -0,0 +1,22 @@ +#================================================================== +# Physics.activity +# Helper classes and functions +# By Alex Levenson +#================================================================== +import math +# distance calculator, pt1 and pt2 are ordred pairs +def distance(pt1, pt2): + return math.sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] -pt2[1]) ** 2) + +# returns the angle between the line segment from pt1 --> pt2 and the x axis, from -pi to pi +def getAngle(pt1,pt2): + xcomp = pt2[0] - pt1[0] + ycomp = pt1[1] - pt2[1] + return math.atan2(ycomp,xcomp) + +# returns a list of ordered pairs that describe an equilteral triangle around the segment from pt1 --> pt2 +def constructTriangleFromLine(p1,p2): + halfHeightVector = (0.57735*(p2[1] - p1[1]), 0.57735*(p2[0] - p1[0])) + p3 = (p1[0] + halfHeightVector[0], p1[1] - halfHeightVector[1]) + p4 = (p1[0] - halfHeightVector[0], p1[1] + halfHeightVector[1]) + return [p2,p3,p4] diff --git a/icons/activity-button1.svg b/icons/activity-button1.svg new file mode 100755 index 0000000..5b1caef --- /dev/null +++ b/icons/activity-button1.svg @@ -0,0 +1,15 @@ + + + + +]> + + + + + + + + diff --git a/icons/activity-button2.svg b/icons/activity-button2.svg new file mode 100755 index 0000000..e1fc560 --- /dev/null +++ b/icons/activity-button2.svg @@ -0,0 +1,16 @@ + + + + +]> + + + + + + + + + diff --git a/physics.py b/physics.py new file mode 100644 index 0000000..47a91fb --- /dev/null +++ b/physics.py @@ -0,0 +1,113 @@ +#================================================================== +# Physics.activity +# An attempt at a Phun / Crayon Physics style physics game +# By Alex Levenson and Brian Jordan +#================================================================== + +import sys +import math +import pygame +from pygame.locals import * +from pygame.color import * +import olpcgames +import elements +from elements import Elements +from elements.menu import * +from tools import * +from helpers import * + +class PhysicsGame: + def __init__(self,screen): + self.screen = screen + # get everything set up + self.clock = pygame.time.Clock() + self.font = pygame.font.Font(None, 24) # font object + + # setup tools + self.tools = { + "Triangle": TriangleTool(self), + "Box": BoxTool(self), + "Circle": CircleTool(self), + "Polygon": PolygonTool(self), + "Magic Pen": MagicPenTool(self), + "Joint": JointTool(self), + "Grab": GrabTool(self), + "Destroy": DestroyTool(self) + } + self.currentTool = self.tools["Triangle"] + + # setup the menus + self.menu = MenuClass() + self.menu.set_width(self.screen.get_width()) + self.menu.addItem('Box', callback=self.setTool) + self.menu.addItem('Circle', callback=self.setTool) + self.menu.addItem('Triangle', callback=self.setTool) + self.menu.addItem('Polygon', callback=self.setTool) + self.menu.addItem('Magic Pen', callback=self.setTool) + self.menu.addItem('Grab', callback=self.setTool) + self.menu.addItem('Joint', callback=self.setTool) + self.menu.addItem('Destroy', callback=self.setTool) + + # set up the world + self.world = elements.Elements(self.screen.get_size()) + self.world.renderer.set_surface(self.screen) + + # load enviornment + self.world.add.ground() + + def run(self): + self.running = True + while self.running: + for event in pygame.event.get(): + self.currentTool.handleEvents(event) + # Clear Display + self.screen.fill((255,255,255)) + + # Update & Draw World + self.world.update() + self.world.draw() + + # draw output from tools + self.currentTool.draw() + + # draw the menu + self.menu.draw(self.screen) + + #Print all the text on the screen + text = self.font.render("Current Tool: "+self.currentTool.name, True, (255,255,255)) + textpos = text.get_rect(left=700,top=7) + self.screen.blit(text,textpos) + + # Flip Display + pygame.display.flip() + + # Try to stay at 30 FPS + self.clock.tick(30) # originally 50 + + def setTool(self,tool,Discard=None): + self.currentTool.cancel() + self.currentTool = self.tools[tool] + +def main(): + # compensate for the size of the toolbar + toolbarheight = 75 + pygame.init() + pygame.display.init() + x,y = pygame.display.list_modes()[0] + screen = pygame.display.set_mode((x,y-toolbarheight)) + # create an instance of the game + game = PhysicsGame(screen) + # start the main loop + game.run() + +# make sure that main get's called +if __name__ == '__main__': + main() + + + + + + + + diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..6ed89aa --- /dev/null +++ b/setup.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python +from sugar.activity import bundlebuilder +bundlebuilder.start() + diff --git a/tools.py b/tools.py index 87dd4f7..65b27b6 100644 --- a/tools.py +++ b/tools.py @@ -1,22 +1,296 @@ #================================================================== # Physics.activity -# Helper classes and functions +# Tool Classes # By Alex Levenson #================================================================== -import math -# distance calculator, pt1 and pt2 are ordred pairs -def distance(pt1, pt2): - return math.sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] -pt2[1]) ** 2) +import pygame +from pygame.locals import * +from helpers import * +# tools that can be used superlcass +class Tool(object): + def __init__(self,gameInstance): + self.game = gameInstance + self.name = "Tool" + def handleEvents(self,event): + # default event handling + if event.type == MOUSEBUTTONDOWN: + if self.game.menu.click(event.pos): return True + if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): + # bye bye! Hope you had fun! + self.game.running = False + elif event.type == KEYDOWN: + if event.key == K_SPACE: + #space pauses + self.game.world.run_physics = not self.game.world.run_physics + else: + # let the subclasses know that no events were handled yet + return False + return True + def draw(self): + # default drawing method is don't draw anything + pass + def cancel(self): + # default cancel doesn't do anything + pass -# returns the angle between the line segment from pt1 --> pt2 and the x axis, from -pi to pi -def getAngle(pt1,pt2): - xcomp = pt2[0] - pt1[0] - ycomp = pt1[1] - pt2[1] - return math.atan2(ycomp,xcomp) +# The circle creation tool +class CircleTool(Tool): + def __init__(self,gameInstance): + self.game = gameInstance + self.name = "Circle" + self.pt1 = None + self.radius = None + def handleEvents(self,event): + #look for default events, and if none are handled then try the custom events + if not super(CircleTool,self).handleEvents(event): + if event.type == MOUSEBUTTONDOWN: + if event.button == 1: + self.pt1 = pygame.mouse.get_pos() + elif event.type == MOUSEBUTTONUP: + if event.button == 1: + if self.radius > 1: # elements doesn't like tiny shapes :( + self.game.world.add.ball(self.pt1,self.radius, dynamic=True, density=1.0, restitution=0.16, friction=0.5) + self.pt1 = None + self.radius = None + def draw(self): + # draw a circle from pt1 to mouse + if self.pt1 != None: + self.radius = distance(self.pt1,pygame.mouse.get_pos()) + if self.radius > 3: + thick = 3 + else: + thick = 0 + pygame.draw.circle(self.game.screen, (100,180,255),self.pt1,self.radius,thick) + pygame.draw.line(self.game.screen,(100,180,255),self.pt1,pygame.mouse.get_pos(),1) + def cancel(self): + self.pt1 = None + self.radius = None + +# The box creation tool +class BoxTool(Tool): + def __init__(self,gameInstance): + self.game = gameInstance + self.name = "Box" + self.pt1 = None + self.rect = None + def handleEvents(self,event): + #look for default events, and if none are handled then try the custom events + if not super(BoxTool,self).handleEvents(event): + if event.type == MOUSEBUTTONDOWN: + if event.button == 1: + self.pt1 = pygame.mouse.get_pos() + elif event.type == MOUSEBUTTONUP: + if event.button == 1 and self.pt1!=None: + if self.rect.width > 10 and self.rect.height > 10: # elements doesn't like small shapes :( + self.game.world.add.rect(self.rect.center, self.rect.width/2, self.rect.height/2, dynamic=True, density=1.0, restitution=0.16, friction=0.5) + self.pt1 = None + + def draw(self): + # draw a box from pt1 to mouse + if self.pt1 != None: + width = pygame.mouse.get_pos()[0] - self.pt1[0] + height = pygame.mouse.get_pos()[1] - self.pt1[1] + self.rect = pygame.Rect(self.pt1, (width, height)) + self.rect.normalize() + pygame.draw.rect(self.game.screen, (100,180,255),self.rect,3) + def cancel(self): + self.pt1 = None + self.rect = None + +# The triangle creation tool +class TriangleTool(Tool): + def __init__(self,gameInstance): + self.game = gameInstance + self.name = "Triangle" + self.pt1 = None + self.vertices = None + def handleEvents(self,event): + #look for default events, and if none are handled then try the custom events + if not super(TriangleTool,self).handleEvents(event): + if event.type == MOUSEBUTTONDOWN: + if event.button == 1: + self.pt1 = pygame.mouse.get_pos() + elif event.type == MOUSEBUTTONUP: + if event.button == 1 and self.pt1!= None: + if distance(self.pt1,pygame.mouse.get_pos()) > 15: # elements doesn't like tiny shapes :( + self.game.world.add.convexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) + self.pt1 = None + self.vertices = None + def draw(self): + # draw a triangle from pt1 to mouse + if self.pt1 != None: + self.vertices = constructTriangleFromLine(self.pt1,pygame.mouse.get_pos()) + pygame.draw.polygon(self.game.screen, (100,180,255),self.vertices, 3) + pygame.draw.line(self.game.screen,(100,180,255),self.pt1,pygame.mouse.get_pos(),1) + + def cancel(self): + self.pt1 = None + self.vertices = None -# returns a list of ordered pairs that describe an equilteral triangle around the segment from pt1 --> pt2 -def constructTriangleFromLine(p1,p2): - halfHeightVector = (0.57735*(p2[1] - p1[1]), 0.57735*(p2[0] - p1[0])) - p3 = (p1[0] + halfHeightVector[0], p1[1] - halfHeightVector[1]) - p4 = (p1[0] - halfHeightVector[0], p1[1] + halfHeightVector[1]) - return [p2,p3,p4] +# The Polygon creation tool +class PolygonTool(Tool): + def __init__(self,gameInstance): + self.game = gameInstance + self.name = "Polygon" + self.vertices = None + def handleEvents(self,event): + #look for default events, and if none are handled then try the custom events + if not super(PolygonTool,self).handleEvents(event): + if event.type == MOUSEBUTTONDOWN: + if event.button == 1: + if not self.vertices: + self.vertices=[event.pos] + elif distance(event.pos,self.vertices[0]) < 15: + self.vertices.append(self.vertices[0]) #connect the polygon + self.game.world.add.complexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) + self.vertices = None + else: + self.vertices.append(event.pos) + if event.button == 3: + if self.vertices: + self.vertices.append(event.pos) + self.game.world.add.complexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) + self.vertices = None + + def draw(self): + # draw the poly being created + if self.vertices: + for i in range(len(self.vertices)-1): + pygame.draw.line(self.game.screen,(100,180,255),self.vertices[i],self.vertices[i+1],3) + pygame.draw.line(self.game.screen,(100,180,255),self.vertices[-1],pygame.mouse.get_pos(),3) + pygame.draw.circle(self.game.screen,(100,180,255),self.vertices[0],15,3) + + def cancel(self): + self.vertices = None + +# The magic pen tool +class MagicPenTool(Tool): + def __init__(self,gameInstance): + self.game = gameInstance + self.name = "Magic Pen" + self.vertices = None + def handleEvents(self,event): + #look for default events, and if none are handled then try the custom events + if not super(MagicPenTool,self).handleEvents(event): + if event.type == MOUSEBUTTONDOWN: + if event.button == 1: + if not self.vertices: + self.vertices=[event.pos] + elif distance(event.pos,self.vertices[0]) < 15: + self.vertices.append(self.vertices[0]) #connect the polygon + self.game.world.add.complexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) + self.vertices = None + else: + self.vertices.append(event.pos) + elif event.type == MOUSEBUTTONUP: + if event.button == 1: + if self.vertices: + self.game.world.add.complexPoly(self.vertices, dynamic=True, density=1.0, restitution=0.16, friction=0.5) + self.vertices = None + elif event.type == MOUSEMOTION: + if self.vertices: + self.vertices.append(event.pos) + + def draw(self): + # draw the poly being created + if self.vertices: + for i in range(len(self.vertices)-1): + pygame.draw.line(self.game.screen,(100,180,255),self.vertices[i],self.vertices[i+1],3) + pygame.draw.line(self.game.screen,(100,180,255),self.vertices[-1],pygame.mouse.get_pos(),3) + pygame.draw.circle(self.game.screen,(100,180,255),self.vertices[0],15,3) + + def cancel(self): + self.vertices = None + +# The grab tool +class GrabTool(Tool): + def __init__(self,gameInstance): + self.game = gameInstance + self.name = "Grab" + def handleEvents(self,event): + #look for default events, and if none are handled then try the custom events + if not super(GrabTool,self).handleEvents(event): + if event.type == MOUSEBUTTONDOWN: + if event.button == 1: + # grab the first object at the mouse pointer + bodylist = self.game.world.get_bodies_at_pos(event.pos, include_static=False) + if bodylist and len(bodylist) > 0: + self.game.world.add.mouseJoint(bodylist[0], event.pos) + elif event.type == MOUSEBUTTONUP: + # let it go + if event.button == 1: + self.game.world.add.remove_mouseJoint() + # use box2D mouse motion + elif event.type == MOUSEMOTION and event.buttons[0]: + self.game.world.mouse_move(event.pos) + + def cancel(self): + self.game.world.add.remove_mouseJoint() + +# The joint tool +class JointTool(Tool): + def __init__(self,gameInstance): + self.game = gameInstance + self.name = "Joint" + self.jb1 = self.jb2 = self.jb1pos = self.jb2pos = None + def handleEvents(self,event): + #look for default events, and if none are handled then try the custom events + if not super(JointTool,self).handleEvents(event): + if event.type == MOUSEBUTTONDOWN: + if event.button == 1: + # grab the first body + self.jb1pos = event.pos + self.jb1 = self.game.world.get_bodies_at_pos(event.pos) + self.jb2 = self.jb2pos = None + elif event.type == MOUSEBUTTONUP: + if event.button == 1: + # grab the second body + self.jb2pos = event.pos + self.jb2 = self.game.world.get_bodies_at_pos(event.pos) + # if we have two distinct bodies, add a joint! + if self.jb1 and self.jb2 and str(self.jb1) != str(self.jb2): + self.game.world.add.joint(self.jb1[0],self.jb2[0],self.jb1pos,self.jb2pos) + # If there's only one body, add a fixed joint + elif self.jb2: + self.game.world.add.joint(self.jb2[0],self.jb2pos) + # regardless, clean everything up + self.jb1 = self.jb2 = self.jb1pos = self.jb2pos = None + if event.button == 3: + # add a centered fixed joint + self.jb2 = world.get_bodies_at_pos(event.pos) + if self.jb2: + self.game.world.add.joint(self.jb2[0]) + def draw(self): + if self.jb1: + pygame.draw.line(self.game.screen,(100,180,255),self.jb1pos,pygame.mouse.get_pos(),3) + + def cancel(self): + self.jb1 = self.jb2 = self.jb1pos = self.jb2pos = None + +# The destroy tool +class DestroyTool(Tool): + def __init__(self,gameInstance): + self.game = gameInstance + self.name = "Destroy" + self.vertices = None + def handleEvents(self,event): + #look for default events, and if none are handled then try the custom events + if not super(DestroyTool,self).handleEvents(event): + if pygame.mouse.get_pressed()[0]: + if not self.vertices: self.vertices = [] + self.vertices.append(pygame.mouse.get_pos()) + if len(self.vertices) > 10: + self.vertices.pop(0) + tokill = self.game.world.get_bodies_at_pos(pygame.mouse.get_pos()) + if tokill: + self.game.world.world.DestroyBody(tokill[0]) + elif event.type == MOUSEBUTTONUP and event.button == 1: + self.cancel() + def draw(self): + # draw the trail + if self.vertices: + if len(self.vertices) > 1: + pygame.draw.lines(self.game.screen,(255,0,0),False,self.vertices,3) + + def cancel(self): + self.vertices = None \ No newline at end of file -- cgit v0.9.1