python - Pygame mouse movement failing -
i working through pygame tutorials , @ moment trying figure out how select circle firing ball ball hits ball in turn knocks box down. knocking of box works fine when ball hits box. however, when add mouse movement can select ball again , place in same position can hit again box knocks again. ball rolls backwards without firing second ball knock box.here previous code works 1 ball firing ball without mouse movements i.e without allowing ball selected , dragged.
import pygame pygame.locals import * pygame.color import * import pymunk pm pymunk import vec2d import sys random import randint def to_pygame(p): """small hack convert pymunk pygame coordinates""" return int(p[0]), int(-p[1]+600) def draw_ball(screen, ball, colour): r = ball.radius rot = ball.body.rotation_vector p = to_pygame(ball.body.position) p2 = vec2d(rot.x, -rot.y) * r * 0.9 pygame.draw.line(screen, thecolors["red"], p, p+p2) pygame.draw.circle(screen, colour, p, int(r), 3) def add_ball(space, x=0, y=130): mass = 1.3 radius = 20 inertia = pm.moment_for_circle(mass, 0, radius, (0,0)) body = pm.body(mass, inertia) body.position = (x,y) shape = pm.circle(body, radius, (0,0)) shape.friction = 10.0 shape.elasticity = 1.0 space.add(body, shape) return shape def add_box(space, size, pos, mass=0.3): points = [(-size, -size), (-size, size), (size,size), (size, -size)] moment = pm.moment_for_poly(int(mass), points, (0,0)) body = pm.body(mass, moment) body.position = pos shape = pm.poly(body, points, (0,0)) shape.friction = 1 space.add(body,shape) return shape def draw_box(screen, box): ps = box.get_points() ps.append(ps[0]) newps = [to_pygame(x) x in ps] pygame.draw.polygon(screen, thecolors["blue"], newps, 3) def main(): pygame.init() screen = pygame.display.set_mode((600, 600)) pygame.display.set_caption("impulsive balls") clock = pygame.time.clock() balls = [] space = pm.space() space.gravity = (0.0, -300.0) # ground body = pm.body() shape = pm.segment(body, (0,100), (450,100), .0) shape.friction = 6.0 space.add(shape) # hidden ramp body = pm.body() slope = pm.segment(body, (0,100), (180,150), .0) space.add(slope) balls.append(add_ball(space, 10, 130)) balls.append(add_ball(space, 100, 150)) #joint = pm.pinjoint(balls[0].body, balls[1].body) #joint.distance = 90 mass = 1.0 size = 20 box = add_box(space, size, (400,100+size), mass) count = 0 while 1: space.step(1/30.0) clock.tick(30) event in pygame.event.get(): if event.type == quit: pygame.quit() sys.exit(0) elif event.type == keydown: if event.key == k_escape: pygame.quit() sys.exit(0) if count == 10: pm.body.apply_impulse(balls[0].body, (450,0)) screen.fill(thecolors["white"]) pygame.draw.line(screen, thecolors["red"], to_pygame((0,100)), to_pygame((450,100)), 3) pygame.draw.line(screen, thecolors["red"], to_pygame((0,100)), to_pygame((180,150)), 3) draw_box(screen, box) ball in balls: draw_ball(screen, ball, thecolors["green"]) pygame.display.flip() count += 1 if __name__ == '__main__': main()
here second version add mouse movement code
import pygame pygame.locals import * pygame.color import * import pymunk pm pymunk import vec2d import sys random import randint def to_pygame(p): """small hack convert pymunk pygame coordinates""" return int(p[0]), int(-p[1]+600) def from_pygame(p): return to_pygame(p) def draw_ball(screen, ball, colour): r = ball.radius rot = ball.body.rotation_vector p = to_pygame(ball.body.position) p2 = vec2d(rot.x, -rot.y) * r * 0.9 pygame.draw.line(screen, thecolors["blue"], p, p+p2) pygame.draw.circle(screen, colour, p, int(r), 3) def add_ball(space, x=0, y=130): mass = 1.3 #1.5 radius = 20 inertia = pm.moment_for_circle(mass, 0, radius, (0,0)) body = pm.body(mass, inertia) body.position = (x,y) shape = pm.circle(body, radius, (0,0)) shape.friction = 10.0 shape.elasticity = 1.0 space.add(body, shape) return shape def add_box(space, size, pos, mass=0.3): points = [(-size, -size), (-size, size), (size,size), (size, -size)] moment = pm.moment_for_poly(int(mass), points, (0,0)) body = pm.body(mass, moment) body.position = pos shape = pm.poly(body, points, (0,0)) shape.friction = 1 space.add(body,shape) return shape def draw_box(screen, box): ps = box.get_points() ps.append(ps[0]) newps = [to_pygame(x) x in ps] pygame.draw.polygon(screen, thecolors["blue"], newps, 3) def main(): pygame.init() screen = pygame.display.set_mode((600, 600)) pygame.display.set_caption("impulsive balls") clock = pygame.time.clock() body = [] selected = none balls = [] space = pm.space() space.gravity = (0.0, -300.0) # ground body = pm.body() shape = pm.segment(body, (0,100), (450,100), .0) shape.friction = 6.0 space.add(shape) # hidden ramp body = pm.body() slope = pm.segment(body, (0,100), (180,150), .0) space.add(slope) balls.append(add_ball(space, 10, 130)) balls.append(add_ball(space, 100, 150)) #joint = pm.pinjoint(balls[0].body, balls[1].body) #joint.distance = 90 mass = 1.0 size = 20 box = add_box(space, size, (400,100+size), mass) count = 0 while 1: space.step(1/30.0) clock.tick(30) event in pygame.event.get(): if event.type == quit: pygame.quit() sys.exit(0) elif event.type == keydown: if event.key == k_escape: pygame.quit() sys.exit(0) if count == 10: pm.body.apply_impulse(balls[0].body, (450,0)) if event.key == k_p: balls[0].body.apply_impulse((450,0)) if event.key == k_s: balls[0].body.apply_impulse((-450,0)) elif event.type == mousebuttondown: p = from_pygame(vec2d(event.pos)) selected = space.point_query_first(p) elif event.type == mousebuttonup: if selected != none: selected = none elif event.type == mousemotion: if selected != none: selected.body.position = from_pygame(event.pos) screen.fill(thecolors["white"]) pygame.draw.line(screen, thecolors["red"], to_pygame((0,100)), to_pygame((450,100)), 3) pygame.draw.line(screen, thecolors["red"], to_pygame((0,100)), to_pygame((180,150)), 3) draw_box(screen, box) ball in balls: draw_ball(screen, ball, thecolors["green"]) pygame.display.flip() count += 1 if __name__ == '__main__': main()
also, how can have ball @ same position can drag , push other ball knock box instead of making ball roll back, later can select fired ball again , place next ball without rolling back
for first issue, ball not firing in second file. problem have put code event block, happens when external event fired (like pressing key). fix it, chunk needs moved out of loop shown below:
... while 1: space.step(1/30.0) clock.tick(30) event in pygame.event.get(): if event.type == quit: pygame.quit() sys.exit(0) elif event.type == keydown: if event.key == k_escape: pygame.quit() sys.exit(0) if event.key == k_p: balls[0].body.apply_impulse((450,0)) if event.key == k_s: balls[0].body.apply_impulse((-450,0)) elif event.type == mousebuttondown: p = from_pygame(vec2d(event.pos)) selected = space.point_query_first(p) elif event.type == mousebuttonup: if selected != none: selected = none elif event.type == mousemotion: if selected != none: selected.body.position = from_pygame(event.pos) if count == 10: pm.body.apply_impulse(balls[0].body, (450,0)) ...
to keep ball moving, recommend place them on flat ground. i've made following changes main show mean. please note disabled ball firing can see balls stay in position. i'd recommend put invisible walls off screen on keep of objects stuck inside frame.
... def main(): pygame.init() screen = pygame.display.set_mode((600, 600)) pygame.display.set_caption("impulsive balls") clock = pygame.time.clock() body = [] selected = none balls = [] space = pm.space() space.gravity = (0.0, -300.0) # ground body = pm.body() shape = pm.segment(body, (0,100), (450,100), .0) shape.friction = 6.0 space.add(shape) # hidden ramp body = pm.body() slope = pm.segment(body, (20,100), (180,150), .0) space.add(slope) body = pm.body() slopetop = pm.segment(body, (180,150), (190,150), .0) space.add(slopetop) balls.append(add_ball(space, 10, 130)) balls.append(add_ball(space, 185, 170)) #joint = pm.pinjoint(balls[0].body, balls[1].body) #joint.distance = 90 mass = 1.0 size = 20 box = add_box(space, size, (400,100+size), mass) count = 0 while 1: space.step(1/30.0) clock.tick(30) event in pygame.event.get(): if event.type == quit: pygame.quit() sys.exit(0) elif event.type == keydown: if event.key == k_escape: pygame.quit() sys.exit(0) if event.key == k_p: balls[0].body.apply_impulse((450,0)) if event.key == k_s: balls[0].body.apply_impulse((-450,0)) elif event.type == mousebuttondown: p = from_pygame(vec2d(event.pos)) selected = space.point_query_first(p) elif event.type == mousebuttonup: if selected != none: selected = none elif event.type == mousemotion: if selected != none: selected.body.position = from_pygame(event.pos) if count == 10 , 0: pm.body.apply_impulse(balls[0].body, (450,0)) screen.fill(thecolors["white"]) pygame.draw.line(screen, thecolors["red"], to_pygame((0,100)), to_pygame((450,100)), 3) pygame.draw.line(screen, thecolors["red"], to_pygame((20,100)), to_pygame((180,150)), 3) pygame.draw.line(screen, thecolors["red"], to_pygame((180,150)), to_pygame((190,150)), 3) draw_box(screen, box) ball in balls: draw_ball(screen, ball, thecolors["green"]) pygame.display.flip() count += 1 ...
Comments
Post a Comment