Talk:Physics Jam/Help
Jump to navigation
Jump to search
Non-screen flipping graphics
import pygame from pygame.locals import * from pygame.color import * import Box2D2 as box2d from math import * global SCENERY global ROLLCAT_WHEEL global ROLLCAT_BODY (SCENERY, ROLLCAT_WHEEL, ROLLCAT_BODY) = (0,1,2) global contactList contactList = [] class X2OGame: def __init__(self, screen): self.pixelsPerMeter = 20 self.updateList = [] self.screen = screen # get everything set up self.clock = pygame.time.Clock() #self.font = pygame.font.Font(None, 24) # font object #self.canvas = olpcgames.ACTIVITY.canvas #self.joystickobject = None self.debug = True self.initializeWorld() self.screen.fill((0,0,0)) self.leftLPress = False self.leftRPress = False # create the name --> instance map for components def worldToScreen(self, worldX, worldY): return (worldX * self.pixelsPerMeter, - worldY * self.pixelsPerMeter) def screenToWorld(self, screenX, screenY): return (screenX / self.pixelsPerMeter, - screenY / self.pixelsPerMeter) def initializeWorld(self): worldAABB = box2d.b2AABB() worldAABB.lowerBound.Set(- 100, - 100) worldAABB.upperBound.Set(100, 100) gravity = box2d.b2Vec2(0, - 10) doSleep = True self.world = box2d.b2World(worldAABB, gravity, doSleep) bodyDef2 = box2d.b2BodyDef() bodyDef2.position.Set(10, - 20) body2 = self.world.CreateBody(bodyDef2) shapeDef2 = box2d.b2PolygonDef() shapeDef2.SetAsBox(50, .2) body2.CreateShape(shapeDef2) body2.SetXForm(body2.GetXForm().position,-.02) BodySprite(body2, 'pic2.png',100,.4,0,0,self.worldToScreen, self.screenToWorld) body2.type = SCENERY self.updateList.append(RollCat(self,(10,0))) self.updateList.append(RollCat(self,(13,0))) self.updateList.append(RollCat(self,(16,0))) self.updateList.append(RollCat(self,(19,0))) self.updateList.append(RollCat(self,(22,0))) self.updateList.append(RollCat(self,(25,0))) print body2.type def run(self): self.running = True while self.running: for event in pygame.event.get(): if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): self.running = False if (event.type == KEYDOWN and event.key == K_a): self.leftLPress = True if (event.type == KEYUP and event.key == K_a): self.leftLPress = False if (event.type == KEYDOWN and event.key == K_d): self.leftRPress = True if (event.type == KEYUP and event.key == K_d): self.leftRPress = False #self.currentTool.handleEvents(event) # Clear Display #self.screen.fill((0,0,0)) #255 for white contactList = [] self.world.Step(1.0/60,10) for updatable in self.updateList: updatable.update() #Print all the text on the screen #text = self.font.render("Current Tool: "+self.currentTool.name, True, (0,0,0)) #textpos = text.get_rect(left=700,top=7) #self.screen.blit(text,textpos) for char in BodySprite.bodySpriteList: char.update() for char in BodySprite.bodySpriteList: self.screen.blit(char.blank, char.old) for char in BodySprite.bodySpriteList: self.screen.blit(char.image, char.rect) for char in BodySprite.bodySpriteList: pygame.display.update([char.old, char.rect]) # Flip Display #pygame.display.flip() # Try to stay at 30 FPS self.clock.tick(60) # originally 50 class BodySprite(pygame.sprite.Sprite): blankColor = (0, 0, 0) bodySpriteList = [] def __init__(self, body, imageName, imageWidthMeters, imageHeightMeters, imageOffsetXMeters, imageOffsetYMeters, worldToScreenFunction, screenToWorldFunction): pygame.sprite.Sprite.__init__(self) BodySprite.bodySpriteList.append(self) # Save a copy of the screen's rectangle self.screen = pygame.display.get_surface().get_rect() self.w2s = worldToScreenFunction self.s2w = screenToWorldFunction self.body = body newWidth = self.w2s(imageWidthMeters, imageHeightMeters)[0] - self.w2s(0, 0)[0] newHeight = self.w2s(imageWidthMeters, imageHeightMeters)[1] - self.w2s(0, 0)[1] self.offsetX = imageOffsetXMeters self.offsetY = imageOffsetYMeters if newWidth < 0: newWidth *= - 1 if newHeight < 0: newHeight *= - 1 # Create a variable to store the previous position of the sprite self.old = (0, 0, 0, 0) self.angle = 0 self.originalImage = pygame.transform.scale(pygame.image.load(imageName).convert_alpha(), (newWidth, newHeight)) self.image = pygame.transform.rotate(self.originalImage, self.angle) self.rect = self.image.get_rect() # Create a Surface the size of our character self.blank = pygame.Surface((self.rect.width * 2, self.rect.height * 2), 0, self.screen) self.blank.fill(BodySprite.blankColor) self.alreadyRendered = False # self. def update(self): if ((self.body.IsStatic() or self.body.IsSleeping()) and self.alreadyRendered): return self.alreadyRendered = True # Make a copy of the current rectangle for use in erasing self.old = self.rect angle = self.body.GetAngle() self.image = pygame.transform.rotate(self.originalImage, angle * 180 / 3.1415) # Move the rectangle by the specified amount self.rect = self.image.get_rect() cosAngle = cos(- angle) sinAngle = sin(- angle) vrotx = - (cosAngle * self.offsetX - sinAngle * self.offsetY) vroty = (sinAngle * self.offsetX + cosAngle * self.offsetY) (self.x, self.y) = self.w2s(self.body.GetXForm().position.x + vrotx, self.body.GetXForm().position.y + vroty) self.rect.center = (self.x, self.y) class myContactListener(box2d.b2ContactListener): def __init__(self): super(myContactListener, self).__init__() def Add(self, point): pass def Persist(self, point): contact def Remove(self, point): pass def Result(self, point): pass class RollCat: def __init__(self, game, location): self.game = game self.world = game.world bodyDef = box2d.b2BodyDef() bodyDef.position.Set(location[0], location[1]+1) #bodyDef.fixedRotation = True body = self.world.CreateBody(bodyDef) shapeDef = box2d.b2PolygonDef() shapeDef.SetAsBox(1, 1) shapeDef.density = 1 shapeDef.restitution = 0.5 shapeDef.friction = 1.0 body.CreateShape(shapeDef) body.SetMassFromShapes() self.torso = body self.torso.type = ROLLCAT_BODY bodyDef3 = box2d.b2BodyDef() bodyDef3.position.Set(location[0],location[1]) body3 = self.world.CreateBody(bodyDef3) shapeDef3 = box2d.b2CircleDef() shapeDef3.radius = 1.0 shapeDef3.density = 1 shapeDef3.restitution = 0.5 shapeDef3.friction = 1.0 body3.CreateShape(shapeDef3) body3.SetMassFromShapes() self.wheel = body3 self.wheel.type = ROLLCAT_WHEEL sensorDef = box2d.b2CircleDef() sensorDef.radius = 0.5 sensorDef.isSensor = True sensorDef.localPosition = box2d.b2Vec2(0,-2) sensorShape = self.torso.CreateShape(sensorDef) jd = box2d.b2RevoluteJointDef() jd.Initialize(body, body3, box2d.b2Vec2(location[0],location[1])) revJoint = self.world.CreateJoint(jd).getAsType() self.axle = revJoint revJoint.EnableMotor(True) revJoint.SetMotorSpeed(0) revJoint.SetMaxMotorTorque(5000) self.motorSpeed = 0 self.targetAngle = 0 BodySprite(body3,'Rollcats_bottom.png',2, 2, 0, 0, self.game.worldToScreen, self.game.screenToWorld) BodySprite(body,'Rollcats_top.png',2, 2, 0, 0,self.game.worldToScreen, self.game.screenToWorld) #def canJump(self): def update(self): moveSpeed = .1 moveForce = 100 angle = self.torso.GetAngle() - self.targetAngle angVel = self.torso.GetAngularVelocity() if (self.game.leftLPress): self.targetAngle = .95*self.targetAngle + .05 * .4 self.wheel.ApplyForce(box2d.b2Vec2(-moveForce,0),self.wheel.GetWorldCenter()) elif (self.game.leftRPress): self.targetAngle = .95*self.targetAngle - .05 * .4 self.wheel.ApplyForce(box2d.b2Vec2(moveForce,0),self.wheel.GetWorldCenter()) else: vx = self.wheel.GetLinearVelocity().x self.targetAngle = .9*self.targetAngle self.wheel.ApplyForce(box2d.b2Vec2(-.1*moveForce*vx,0),self.wheel.GetWorldCenter()) while (angle > 3.1415): angle -= 2*3.1415 while (angle < -3.1415): angle += 2*3.1415 correctionFactor = 2 correctionDragFactor = .1 #torque = -correctionFactor*angle - correctionDragFactor*angVel #self.torso.ApplyTorque(torque) self.motorSpeed += correctionFactor*angle + correctionDragFactor*angVel self.axle.SetMotorSpeed(self.motorSpeed) def main(): pygame.init() pygame.display.init() x, y = (1200,800)#pygame.display.list_modes()[0] #toolbarheight = 10 #tabheight = 10 screen = pygame.display.set_mode((x, y)) # create an instance of the game game = X2OGame(screen) # start the main loop game.run() # function for loading sounds (mostly borrowed from Pete Shinners pygame tutorial) def loadSound(name): # if the mixer didn't load, then create an empy class that has an empty play method # this way the program will run if the mixer isn't present (sans sound) class NoneSound: def play(self): pass def set_volume(self): pass if not pygame.mixer: return NoneSound() try: sound = pygame.mixer.Sound(name) except: print "error with sound: " + name return NoneSound() return sound # make sure that main get's called if __name__ == '__main__': main()
Binding sprites and bodies:
import pygame from Box2D2 import * import sys from math import * class BodySprite(pygame.sprite.Sprite): blankColor = (0, 0, 0) bodySpriteList = [] def __init__(self, body, imageName, imageWidthMeters, imageHeightMeters, imageOffsetXMeters, imageOffsetYMeters, worldToScreenFunction, screenToWorldFunction): pygame.sprite.Sprite.__init__(self) BodySprite.bodySpriteList.append(self) # Save a copy of the screen's rectangle self.screen = pygame.display.get_surface().get_rect() self.w2s = worldToScreenFunction self.s2w = screenToWorldFunction self.body = body newWidth = self.w2s(imageWidthMeters,imageHeightMeters)[0] - self.w2s(0,0)[0] newHeight = self.w2s(imageWidthMeters,imageHeightMeters)[1] - self.w2s(0,0)[1] self.offsetX = imageOffsetXMeters self.offsetY = imageOffsetYMeters if newWidth < 0: newWidth *= -1 if newHeight < 0: newHeight *= -1 # Create a variable to store the previous position of the sprite self.old = (0, 0, 0, 0) self.angle = 0 self.originalImage = pygame.transform.scale(pygame.image.load(imageName).convert_alpha(),(newWidth,newHeight)) self.image = pygame.transform.rotate(self.originalImage,self.angle) self.rect = self.image.get_rect() # Create a Surface the size of our character self.blank = pygame.Surface((self.rect.width*2, self.rect.height*2),0,screen) self.blank.fill(BodySprite.blankColor) # self. def update(self): # Make a copy of the current rectangle for use in erasing self.old = self.rect angle = self.body.GetAngle() self.image = pygame.transform.rotate(self.originalImage,angle * 180 / 3.1415) # Move the rectangle by the specified amount self.rect = self.image.get_rect() cosAngle = cos(-angle) sinAngle = sin(-angle) vrotx = -(cosAngle * self.offsetX - sinAngle * self.offsetY) vroty = (sinAngle * self.offsetX + cosAngle * self.offsetY) (self.x, self.y) = self.w2s(self.body.GetXForm().position.x + vrotx, self.body.GetXForm().position.y + vroty) self.rect.center = (self.x, self.y) global pixelsPerMeter pixelsPerMeter = 20 #screen to world conversion def s2w(screenX, screenY): return (screenX / pixelsPerMeter, -screenY / pixelsPerMeter) #world to screen conversion def w2s(worldX, worldY): return (worldX * pixelsPerMeter, -worldY * pixelsPerMeter) pygame.init() screen = pygame.display.set_mode((640, 480)) pygame.display.set_caption('Body + Sprite Example') screen.fill((159, 182, 205)) worldAABB = b2AABB() worldAABB.lowerBound.Set(-100,-100) worldAABB.upperBound.Set(100,100) gravity = b2Vec2(0, -10) doSleep = True world = b2World(worldAABB, gravity, doSleep) bodyDef = b2BodyDef() bodyDef.position.Set(10,-10) bodyDef.fixedRotation = True body = world.CreateBody(bodyDef) body.SetLinearVelocity(b2Vec2(1.0,0.0)) shapeDef = b2PolygonDef() shapeDef.SetAsBox(1, 1) shapeDef.density = 1 shapeDef.restitution = 0.5 shapeDef.friction = 1.0 body.CreateShape(shapeDef) body.SetMassFromShapes() bodyDef2 = b2BodyDef() bodyDef2.position.Set(10,-20) body2 = world.CreateBody(bodyDef2) shapeDef2 = b2PolygonDef() shapeDef2.SetAsBox(50,.2) body2.CreateShape(shapeDef2) bodyDef3 = b2BodyDef() bodyDef3.position.Set(10,-11) body3 = world.CreateBody(bodyDef3) shapeDef3 = b2CircleDef() shapeDef3.radius = 1.0 shapeDef3.density = 1 shapeDef3.restitution = 0.5 shapeDef3.friction = 1.0 body3.CreateShape(shapeDef3) body3.SetMassFromShapes() jd = b2RevoluteJointDef() jd.Initialize(body, body3, b2Vec2(10,-11)) revJoint = world.CreateJoint(jd) BodySprite(body3,'wheel.png',2, 2, 0, 0, w2s, s2w) BodySprite(body,'pic2.png',2, 2, 0, 0,w2s,s2w) BodySprite(body2, 'pic2.png',100,.4,0,0,w2s,s2w) pygame.display.update() while True: count = 0 world.Step(1.0/60.0, 10) for event in pygame.event.get(): 0 for char in BodySprite.bodySpriteList: char.update() # Erase the old position by putting our blank Surface on it for char in BodySprite.bodySpriteList: screen.blit(char.blank, char.old) for char in BodySprite.bodySpriteList: screen.blit(char.image, char.rect) for char in BodySprite.bodySpriteList: pygame.display.update([char.old, char.rect])