Recently I've been trying to make a simple game with pymunk. My goal (at the moment) is for the boxes to be affected by gravity, and to 'jump' when they have their up()
function called.
Here is my code.
import pygame
from pygame.locals import *
from pygame.color import *
import pymunk
import pymunk.pygame_util
#constants
WALL_BOUNCINESS = 0
FLOOR_FRICTION = 1
accuracy=1
WALL_PADDING=5
#pygame initiation stuff
pygame.init()
width,height=1500,750
screen = pygame.display.set_mode((width, height))
#main loop initialisations
clock = pygame.time.Clock()
running = True
#physics things
space=pymunk.Space()
space.gravity=(0,-900)
#where the magic happens
draw_options = pymunk.pygame_util.DrawOptions(screen)
#boundaries
wall_body = space.static_body
walls = [pymunk.Segment(wall_body, (WALL_PADDING,height-WALL_PADDING), (width-WALL_PADDING,height-WALL_PADDING),1),
pymunk.Segment(wall_body, (WALL_PADDING,height-WALL_PADDING), (WALL_PADDING,WALL_PADDING), 1),
pymunk.Segment(wall_body, (WALL_PADDING,WALL_PADDING), (width-WALL_PADDING,WALL_PADDING), 1),
pymunk.Segment(wall_body, (width-WALL_PADDING,WALL_PADDING), (width-WALL_PADDING,height-WALL_PADDING),1)]
for wall in walls:
wall.elasticity = WALL_BOUNCINESS
wall.friction = FLOOR_FRICTION
space.add(walls)
#keybindings
keybindings={}
#adding objects
class player(): #using a class for neatness, not instantiation purposes
def __init__(self, starting_coords, keyset_LUR=None):
x,y=starting_coords[0], starting_coords[1]
mass=10
inertia = pymunk.moment_for_box(mass, (100,100))
self.body = pymunk.Body(mass, inertia)
self.shape = pymunk.Poly(self.body,((x,y),(x+100,y),(x+100,y+100),(x,y+100)))
self.shape.elasticity = 0
self.shape.friction = 0.5
space.add(self.body, self.shape)
if keyset_LUR:
funcs=iter((self.left, self.up, self.right))
for key in keyset_LUR:
keybindings[key]=next(funcs)
def left(self):...
def right(self):...
def up(self):
self.body.apply_impulse_at_local_point((0,100))
p1=player((100,100),(K_a,K_w,K_d))
p2=player((1300,100),(K_LEFT,K_UP,K_RIGHT))
#main løóp
while running:
for event in pygame.event.get():
if event.type == QUIT: running = False
elif event.type == KEYDOWN:
if event.key in keybindings: keybindings[event.key]()
screen.fill(THECOLORS["white"])
space.debug_draw(draw_options) #so happy this exists
dt=1/(60*accuracy)
for _ in range(accuracy):
space.step(dt)
pygame.display.flip()
clock.tick(60)
Apologies for my informal commenting. I've tried to use simple variable names so that the code's not too hard to follow. I believe the problem is with the player class, as it controls how the squares behave. My physics knowledge is bad, and I don't really understand the concept of inertia, so if I've made a mistake relating to a fundamental concept related to physics, I'd really appreciate any explanations which could help clear up my misunderstanding. This is how it currently behaves.
PS. I'm trying to teach myself pymunk/python, and have very little formal education in either of the two, so I apologise for any 'unorthodox' code, hopefully it's not too hard to follow.
Thanks :)
The problem is that the player box is not centered. The box center of gravity is at (0,0) in world coordinates.
So, what you want to do is to put the poly shape to be a box (-50,-50) to (50,50). Then to put it in the place you want it you move the body that the shape is attached to.
So, first replace
self.shape = pymunk.Poly(self.body,((x,y),(x+100,y),(x+100,y+100),(x,y+100)))
with
self.shape = pymunk.Poly(self.body,((-50,-50),(50,-50),(50,50),(-50,50)))
Then set the body position to x,y right after
self.body.position = x,y