Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PYTHON Trouble using escape key to exit

Tags:

python

pygame

I'm having trouble with the following code. It seems to respond to the escape key but it freezes really bad. I'm using pyscripter with python 2.7 and 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()
like image 753
pandoragami Avatar asked Aug 13 '11 23:08

pandoragami


People also ask

How do I use the Esc key in Python?

An escape character is a backslash \ followed by the character you want to insert.

What is the escape key called in Python?

Learn More. In Python strings, the backslash "\" is a special character, also called the "escape" character. It is used in representing certain whitespace characters: "\t" is a tab, "\n" is a newline, and "\r" is a carriage return.

How do I close pygame Windows?

We put exit() after pygame. quit(), because pygame. quit() makes the system exit and exit() closes that window.

What is Keydown in Pygame?

KEYDOWN and pygame. KEYUP to detect if a key is physically pressed down or released. You can activate keyboard repeat by using pygame. key.


2 Answers

I just modified the code like so, thanks 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
like image 200
pandoragami Avatar answered Oct 28 '22 21:10

pandoragami


Make sure that you call pygame.quit() before you exit your main function.

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

Another possible solution would be to try running the program straight from the command line.

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

like image 23
Brien Avatar answered Oct 28 '22 20:10

Brien