PYTHON使用转义键退出时出现问题

时间:2011-08-13 23:35:01

标签: python pygame

我遇到以下代码时遇到问题。它似乎响应了逃生键,但它冻结真的很糟糕。我正在使用pyscripter和python 2.7以及pygame。

# An example implementation of the algorithm described at
# http://www.niksula.cs.hut.fi/~hkankaan/Homepages/metaballs.html
#
# The code contains some references to the document above, in form
# ### Formula (x)
# to make clear where each of the formulas is implemented (and what
# it looks like in Python)
#
# Since Python doesn't have an in-built vector type, I used complex
# numbers for coordinates (x is the real part, y is the imaginary part)
#
# Made by Hannu Kankaanpää. Use for whatever you wish.

import math

import pygame
from pygame.locals import *


def main():
    # This is where the execution starts.
    # First initialize the screen.
    pygame.init()
    screen = pygame.display.set_mode((640, 480))

    # Then create a couple of balls
    balls = [Ball(350 + 100j, size=3),
             Ball(20  + 200j, size=2),
             Ball(280 + 140j, size=4),
             Ball(400 + 440j, size=3)]

    # And a metaball system (see below for class definition)
    mbs = MetaballSystem(balls, goo=2.0, threshold=0.0004, screen=screen)

    while True:
        # clear screen with black
        screen.fill((0, 0, 0))

        # move ball number 0 according to mouse position
        if pygame.mouse.get_focused():
            balls[0].pos = complex(*pygame.mouse.get_pos())

        # Draw the balls.
        # Try different methods: euler, rungeKutta2 and rungeKutta4
        drawBalls(differentialMethod=rungeKutta2, metaballSystem=mbs,
                  step=20, screen=screen)
        pygame.display.flip()

        # exit when esc is pressed
        for event in pygame.event.get():
            if event.type == QUIT:
                return
            elif event.type == KEYDOWN:
                if event.key == K_ESCAPE:
                    return


def drawBalls(differentialMethod, metaballSystem, step, screen):
    mbs = metaballSystem
    balls = mbs.balls

    # First, track the border for all balls and store
    # it to pos0 and edgePos. The latter will move along the border,
    # pos0 stays at the initial coordinates.
    for ball in balls:
        ball.pos0 = mbs.trackTheBorder(ball.pos + 1j)
        ball.edgePos = ball.pos0
        ball.tracking = True

    loopIndex = 0
    while loopIndex < 200:
        loopIndex += 1
        for ball in balls:
            if not ball.tracking:
                continue

            # store the old coordinates
            old_pos = ball.edgePos

            # walk along the tangent, using chosen differential method
            ball.edgePos = differentialMethod(ball.edgePos, step, mbs.calcTangent)

            # correction step towards the border
            ball.edgePos, tmp = mbs.stepOnceTowardsBorder(ball.edgePos)

            pygame.draw.line(screen, (255, 255, 255),
                             (old_pos.real, old_pos.imag),
                             (ball.edgePos.real, ball.edgePos.imag))

            # check if we've gone a full circle or hit some other
            # edge tracker
            for ob in balls:
                if (ob is not ball or loopIndex > 3) and \
                   abs(ob.pos0 - ball.edgePos) < step:
                    ball.tracking = False

        tracking = 0
        for ball in balls:
            if ball.tracking:
                tracking += 1
        if tracking == 0:
            break


class Ball:
    """Single metaball."""
    def __init__(self, pos, size):
        self.pos = pos
        self.size = size


class MetaballSystem:
    """A class that manages the metaballs and can calculate
       several useful values from the system.
    """

    def __init__(self, balls, goo, threshold, screen):
        self.balls = balls
        self.goo = goo
        self.threshold = threshold
        self.minSize = min([ball.size for ball in balls])
        self.screen = screen

    def calcForce(self, pos):
        """Return the metaball field's force at point 'pos'."""
        force = 0
        for ball in self.balls:
            ### Formula (1)
            div = abs(ball.pos - pos)**self.goo
            if div != 0: # to prevent division by zero
                force += ball.size / div
            else:
                force += 10000 #"big number"
        return force

    def calcNormal(self, pos):
        """Return a normalized (magnitude = 1) normal at point 'pos'."""
        np = 0j
        for ball in self.balls:
            ### Formula (3)
            div = abs(ball.pos - pos)**(2 + self.goo)
            np += -self.goo * ball.size * (ball.pos - pos) / div
        return np / abs(np)

    def calcTangent(self, pos):
        """Return a normalized (magnitude = 1) tangent at point 'pos'."""
        np = self.calcNormal(pos)
        ### Formula (7)
        return complex(-np.imag, np.real)

    def stepOnceTowardsBorder(self, pos):
        """Step once towards the border of the metaball field, return
           new coordinates and force at old coordinates.
        """
        force = self.calcForce(pos)
        np = self.calcNormal(pos)
        ### Formula (5)
        stepsize = (self.minSize / self.threshold)**(1 / self.goo) - \
                   (self.minSize / force)**(1 / self.goo) + 0.01
        return (pos + np * stepsize, force)

    def trackTheBorder(self, pos):
        """Track the border of the metaball field and return new
           coordinates.
        """
        force = 9999999
        # loop until force is weaker than the desired threshold
        while force > self.threshold:
            pos, force = self.stepOnceTowardsBorder(pos)
            # show a little debug output (i.e. plot yellow pixels)
            sz = self.screen.get_size()
            if 0 <= pos.real < sz[0] and 0 <= pos.imag < sz[1]:
                self.screen.set_at((int(pos.real), int(pos.imag)), (255, 255, 0))
        return pos


def euler(pos, h, func):
    """Euler's method.
       The most simple way to solve differential systems numerically.
    """
    return pos + h * func(pos)


def rungeKutta2(pos, h, func):
    """Runge-Kutta 2 (=mid-point).
       This is only a little more complex than the Euler's method,
       but significantly better.
    """
    return pos + h * func(pos + func(pos) * h / 2)


def rungeKutta4(pos, h, func):
    """Runge-Kutta 4.
       RK4 is quite a bit more complex than RK2. RK2 with a
       small stepsize is often more useful than this.
    """
    t1 = func(pos)
    t2 = func(pos + t1 * h / 2)
    t3 = func(pos + t2 * h / 2)
    t4 = func(pos + t3 * h)
    return pos + (h / 6) * (t1 + 2*t2 + 2*t3 + t4)


if __name__ == '__main__': main()

3 个答案:

答案 0 :(得分:4)

请确保在退出主要功能之前致电pygame.quit()

running = True
while running:
    # other code
    event = pygame.event.wait ()
    if event.type == pygame.QUIT:
         running = False  # Be interpreter friendly
pygame.quit()

另一种可能的解决方案是尝试直接从命令行运行程序。

http://www.pygame.org/wiki/FrequentlyAskedQuestions

答案 1 :(得分:4)

我刚修改了代码,感谢giantenigma

#exit when esc is pressed
        for event in pygame.event.get():
           if event.type == QUIT:
               return
           elif event.type == KEYDOWN:
               if event.key == K_ESCAPE:
                   pygame.quit()
                   return

答案 2 :(得分:0)

if(key == "escape"):

工作比

更好
if(key == K_ESCAPE):

根据我的经验。

(在你我之间,K_ESCAPE 根本不起作用