简体   繁体   English

pygame鼠标移动失败

[英]Pygame mouse movement failing

I am working through pygame tutorials and at the moment I am trying to figure out how to select a circle which is firing a ball where a ball hits another ball which in turn knocks a box down. 我正在研究pygame教程,此刻我正试图找出如何选择一个发射球的圆圈,其中一个球击中另一个球,进而击倒一个盒子。 The knocking of the box works fine when the ball hits the box. 当球击中盒子时,敲盒子的动作很好。 However, when I add the mouse movement so that I can select the ball again and place it in the same position so that it can be hit again so that the box knocks again. 但是,当我添加鼠标移动时,可以再次选择球并将其放置在相同位置,以便可以再次击中球,以便再次敲击盒子。 The ball just rolls backwards without firing the second ball to knock the box.Here is the previous code that works with one ball firing another ball but without the mouse movements ie without allowing the ball to be selected and dragged. 球只是向后滚动而没有发射第二个球来敲打盒子。这是先前的代码,它适用于一个球发射另一个球,但没有鼠标移动,即不允许选择和拖动球。

import pygame
from pygame.locals import *
from pygame.color import *
import pymunk as pm
from pymunk import Vec2d
import sys
from random import randint

def to_pygame(p):
    """Small hack to convert pymunk to 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) for 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)

        for 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)
        for ball in balls:
            draw_ball(screen, ball, THECOLORS["green"])

        pygame.display.flip()
        count += 1

if __name__ == '__main__':
    main()

Here is the second version where I add the mouse movement code 这是我添加鼠标移动代码的第二个版本

import pygame
from pygame.locals import *
from pygame.color import *
import pymunk as pm
from pymunk import Vec2d
import sys
from random import randint

def to_pygame(p):
    """Small hack to convert pymunk to 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) for 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)

        for 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)
        for ball in balls:
            draw_ball(screen, ball, THECOLORS["green"])

        pygame.display.flip()
        count += 1

if __name__ == '__main__':
    main()

Also, how can I have the ball at the same position so that I can drag it and push the other ball to knock the box instead of making the ball roll back, so later I can select the fired ball again and place it next to the ball without rolling back 另外,如何将球放在相同的位置,以便可以拖动它并推动另一个球来敲打盒子而不是使球回滚,所以以后我可以再次选择发射的球并将其放在球的旁边球不回滚

For your first issue, where the ball is not firing in the second file. 对于您的第一个问题,第二个文件中球不发球。 The problem is that you have put that code into the event block, which only happens when an external event is fired (like pressing a key). 问题在于您已将该代码放入事件块中,该事件块仅在触发外部事件(如按下键)时发生。 To fix it, that chunk needs to be moved out of that for loop as shown below: 要修复它,需要将该块移出for循环,如下所示:

...

while 1:
    space.step(1/30.0)
    clock.tick(30)

    for 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 the ball from moving, what I would recommend is to place them on flat ground. 为了防止球移动,我建议将它们放在平坦的地面上。 I've made the following changes to main to show what I mean. 我对main进行了以下更改以显示我的意思。 Please note that I disabled the ball firing so that you can see that the balls stay in position. 请注意,我禁用了球发射功能,以便您可以看到球保持在原位。 I'd also recommend that you put some invisible walls off the screen on to keep all of the objects stuck inside the 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)

        for 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 and 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)
        for ball in balls:
            draw_ball(screen, ball, THECOLORS["green"])

        pygame.display.flip()
        count += 1
...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM