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/142637defmagnitude(v):
    return math.sqrt(sum(v[i]*v[i] for i inrange(len(v))))

defadd(u, v):
    return [ u[i]+v[i] for i inrange(len(u)) ]

defsub(u, v):
    return [ u[i]-v[i] for i inrange(len(u)) ]    

defdot(u, v):
    returnsum(u[i]*v[i] for i inrange(len(u)))

defnormalize(v):
    vmag = magnitude(v)
    return [ v[i]/vmag  for i inrange(len(v)) ]

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

classBall(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))

    @propertydefpos(self):
        return self.x, self.y

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

    @propertydeftarget(self):
        return self.t_x, self.t_y

    @propertydefint_target(self):
        returnmap(int, self.target)   

    defnext_target(self):
        self.set_target(self.pos)
        self.set_target(next(self.path))

    defset_target(self, pos):
        self.t_x, self.t_y = pos

    defupdate(self):
        # if we won't move, don't calculate new vectorsif 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 pointsif 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)

    defdraw(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]

whilenot 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"