Skip to content Skip to sidebar Skip to footer

Bouncing An Image In A Polygonal Way With Pygame

Hey guys am new to pygame .I have to make a ball image ball.jpg to bounce in polygonal way.I have also an another ball image which is running in a square way.What i need is to add

Solution 1:

You'll need some vector math to do this.

Create a list of points that describe the path the object should move, then calculate a vector describing the direction from the current position to the target position. Then move the object by using that vector. Once you hit your target, aim for the next point to move.

Here's an example:

import pygame
import math
from itertools import cycle

# some simple vector helper functions, stolen from http://stackoverflow.com/a/4114962/142637
def magnitude(v):
    return math.sqrt(sum(v[i]*v[i] for i in range(len(v))))

def add(u, v):
    return [ u[i]+v[i] for i in range(len(u)) ]

def sub(u, v):
    return [ u[i]-v[i] for i in range(len(u)) ]    

def dot(u, v):
    return sum(u[i]*v[i] for i in range(len(u)))

def normalize(v):
    vmag = magnitude(v)
    return [ v[i]/vmag  for i in range(len(v)) ]

screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()    

class Ball(object):
    def __init__(self, path):
        self.x, self.y = (0, 0)
        self.speed = 2.5
        self.color = (200, 200, 200)
        self.path = cycle(path)
        self.set_target(next(self.path))

    @property
    def pos(self):
        return self.x, self.y

    # for drawing, we need the position as tuple of ints
    # so lets create a helper property
    @property
    def int_pos(self):
        return map(int, self.pos)

    @property
    def target(self):
        return self.t_x, self.t_y

    @property
    def int_target(self):
        return map(int, self.target)   

    def next_target(self):
        self.set_target(self.pos)
        self.set_target(next(self.path))

    def set_target(self, pos):
        self.t_x, self.t_y = pos

    def update(self):
        # if we won't move, don't calculate new vectors
        if self.int_pos == self.int_target:
            return self.next_target()

        target_vector = sub(self.target, self.pos) 

        # a threshold to stop moving if the distance is to small.
        # it prevents a 'flickering' between two points
        if magnitude(target_vector) < 2: 
            return self.next_target()

        # apply the balls's speed to the vector
        move_vector = [c * self.speed for c in normalize(target_vector)]

        # update position
        self.x, self.y = add(self.pos, move_vector)

    def draw(self):
        pygame.draw.circle(screen, self.color, self.int_pos, 4)

pygame.init()
quit = False

path = [(26, 43),
        (105, 110),
        (45, 225),
        (145, 295),
        (266, 211),
        (178, 134),
        (250, 56),
        (147, 12)]

path2 = [(26, 43),
         (105, 10),
         (45, 125),
         (150, 134),
         (150, 26),
         (107, 12)]

ball = Ball(path)
ball.speed = 1.9

ball2 = Ball(path2)
ball2.color = (200, 200, 0)

balls = [ball, ball2]

while not quit:
    quit = pygame.event.get(pygame.QUIT)
    pygame.event.poll()

    map(Ball.update, balls)

    screen.fill((0, 0, 0))

    map(Ball.draw, balls)

    pygame.display.flip()
    clock.tick(60)

enter image description here


Here's an example without a custom class:

import pygame
import math
from itertools import cycle

# some simple vector helper functions, stolen from http://stackoverflow.com/a/4114962/142637
def magnitude(v):
    return math.sqrt(sum(v[i]*v[i] for i in range(len(v))))

def sub(u, v):
    return [ u[i]-v[i] for i in range(len(u)) ]    

def normalize(v):
    vmag = magnitude(v)
    return [ v[i]/vmag  for i in range(len(v)) ]

screen = pygame.display.set_mode((300, 300))
clock = pygame.time.Clock()    

pygame.init()
quit = False

path = [(26, 43),
        (105, 110),
        (45, 225),
        (145, 295),
        (266, 211),
        (178, 134),
        (250, 56),
        (147, 12)]
path = cycle(path)         
target = next(path)
ball = pygame.rect.Rect(target[0], target[1], 10, 10)
speed = 3.6

while not quit:
    quit = pygame.event.get(pygame.QUIT)
    pygame.event.poll()

    if ball.topleft == target:
        target = next(path)

    target_vector = sub(target, ball.topleft) 

    if magnitude(target_vector) < 2: 
        target = next(path)
    else:
        move_vector = [c * speed for c in normalize(target_vector)]
        ball.move_ip(move_vector)

    screen.fill((0, 0, 0))
    pygame.draw.rect(screen, pygame.color.Color('Grey'), ball)
    pygame.display.flip()
    clock.tick(60)

Post a Comment for "Bouncing An Image In A Polygonal Way With Pygame"