Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex <alex@Tiresias.(none)>2008-07-08 21:11:48 (GMT)
committer Alex <alex@Tiresias.(none)>2008-07-08 21:11:48 (GMT)
commitd610e626c0f6085fa27de62a3113ef722a310f85 (patch)
tree8af609d2aceb9abca5f302b7bfdd7b3057445885
parente2e93519e067f526ff285db53921e900f259ad72 (diff)
Total Reorganization! Now a proper activity (I hope)
-rw-r--r--activity.py395
-rwxr-xr-xactivity/activity.info14
-rw-r--r--helpers.py22
-rwxr-xr-xicons/activity-button1.svg15
-rwxr-xr-xicons/activity-button2.svg16
-rw-r--r--physics.py113
-rwxr-xr-xsetup.py4
-rw-r--r--tools.py306
8 files changed, 496 insertions, 389 deletions
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY fill_color "#FFFFFF">
+ <!ENTITY stroke_color "#000000">
+]>
+<svg version="1.1" id="Layer_5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="74.5px" height="74px" viewBox="0 0 74.5 74" enable-background="new 0 0 74.5 74" xml:space="preserve">
+<g>
+ <circle cx="37.026" cy="37.18" r="30" fill="&fill_color;"/>
+ <g>
+ <line fill="none" stroke="&stroke_color;" stroke-width="4" x1="55.026" y1="37.18" x2="19.026" y2="37.18"/>
+ </g>
+</g>
+</svg>
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 13.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
+ <!ENTITY fill_color "#FFFFFF">
+ <!ENTITY stroke_color "#000000">
+]>
+<svg version="1.1" id="Layer_5" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+ width="74.5px" height="74px" viewBox="0 0 74.5 74" enable-background="new 0 0 74.5 74" xml:space="preserve">
+<g>
+ <circle cx="37.026" cy="37.18" r="30" fill="&fill_color;"/>
+ <g>
+ <line fill="none" stroke="&stroke_color;" stroke-width="4" x1="37.026" y1="19.18" x2="37.026" y2="55.18"/>
+ <line fill="none" stroke="&stroke_color;" stroke-width="4" x1="55.026" y1="37.18" x2="19.026" y2="37.18"/>
+ </g>
+</g>
+</svg>
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