# with - pygame sprite rect

## How to move a rectangle in a curved path in pygames? (2)

``````y_speed = 0
x_speed = -10
gravity = -3 # Depending on how fast you want gravity to be
while True:
x += x_speed
y += y_speed
y_speed += gravity
gameDisplay.fill(white)
pygame.draw.rect(gameDisplay, black, (x, y, 50,50))
pygame.display.update()
clock.tick(FPS)``````

Having taken some Physics can help with programming. I would suggest looking into some basic kinematic equations if you're still confused

moving a rectangle in a straight line on pygames is easy. But how do i implement gravity into the rectangle's path? Like instead of a straight path, move in an curved path. Perhaps, the image below will help you understand what i am trying to achieve.

Here is the code to move the rectangle in a straight path to the left.

``````import pygame
import time

pygame.init()
white = (255,255,255)
black = (0,0,0)
display_width = 800
display_height  = 700
gameDisplay = pygame.display.set_mode((display_width,display_height))
clock = pygame.time.Clock()
FPS = 30

x = 300
y = 100
while True:
x -= 10
gameDisplay.fill(white)
pygame.draw.rect(gameDisplay, black, (x, y, 50,50))
pygame.display.update()
clock.tick(FPS)``````

## Gravity in pygame

There is a tutorial for creating a bouncing ball which I think might be helpful to you.

Now, to add gravity to that simulation, you'd simply add some extra speed in the y-direction every time through the loop:

``speed[1] += gravity``

What you end up with is kind of goofy however, since the image quickly descends below the bottom of the window never to be seen again :)

The next step is therefore to clip the position of the ball so it must remain in the window:

``````import os
import sys, pygame
pygame.init()

size = width, height = 320, 240
speed = [1, 1]
black = 0, 0, 0
gravity = 0.1

screen = pygame.display.set_mode(size)

image_file = os.path.expanduser("~/pybin/pygame_examples/data/ball.png")
ballrect = ball.get_rect()

def clip(val, minval, maxval):
return min(max(val, minval), maxval)

while 1:
for event in pygame.event.get():
if event.type == pygame.QUIT: sys.exit()

speed[1] += gravity

ballrect = ballrect.move(speed)
if ballrect.left < 0 or ballrect.right > width:
speed[0] = -speed[0]
if ballrect.top < 0 or ballrect.bottom > height:
speed[1] = -speed[1]

# clip the position to remain in the window

ballrect.left = clip(ballrect.left, 0, width)
ballrect.right = clip(ballrect.right, 0, width)
ballrect.top = clip(ballrect.top, 0, height)
ballrect.bottom = clip(ballrect.bottom, 0, height)

screen.fill(black)
screen.blit(ball, ballrect)
pygame.display.flip()``````

Okay, now you can incorporate that in your current code and you'll be off and running. However, there are some things you can do to make your code more organized and less repetitive.

For example, consider the massive `if...then` blocks that follow

``for event in pygame.event.get(): ``

You could rewrite it as something like:

``````delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay``````

You could also benefit from putting all the logic associated with the movement of your image into a class:

``````class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.rect = self.image.get_rect()
self.speed = [0, 0]
area = pygame.display.get_surface().get_rect()
self.width, self.height = area.width, area.height

def update(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > self.width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > self.height:
self.speed[1] = -self.speed[1]
self.rect.left = clip(self.rect.left, 0, self.width)
self.rect.right = clip(self.rect.right, 0, self.width)
self.rect.top = clip(self.rect.top, 0, self.height)
self.rect.bottom = clip(self.rect.bottom, 0, self.height)                ``````

Notice the `update` method is very similar to the code presented by the tutorial. One of the nice things about creating a Ball class is that the rest of your program does not need to know much about how a Ball moves. All the logic is in `Ball.update`. Moreover, it makes it easy to instantiate many balls. And you could create other classes (airplanes, birds, paddles, etc.) that move differently too and add them to your simulation relatively painlessly.

So, putting it all together, you would end up with something like this:

``````"""
http://.com/a/15459868/190597 (unutbu)
Based on http://www.pygame.org/docs/tut/intro/intro.html
Draws a red ball bouncing around in the window.
Pressing the arrow keys moves the ball
"""

import sys
import pygame
import os

image_file = os.path.expanduser("~/pybin/pygame_examples/data/ball.png")

delta = {
pygame.K_LEFT: (-20, 0),
pygame.K_RIGHT: (+20, 0),
pygame.K_UP: (0, -20),
pygame.K_DOWN: (0, +20),
}

gravity = +1

class Ball(pygame.sprite.Sprite):
def __init__(self):
pygame.sprite.Sprite.__init__(self)
self.rect = self.image.get_rect()
self.speed = [0, 0]
area = pygame.display.get_surface().get_rect()
self.width, self.height = area.width, area.height

def update(self):
self.rect = self.rect.move(self.speed)
if self.rect.left < 0 or self.rect.right > self.width:
self.speed[0] = -self.speed[0]
if self.rect.top < 0 or self.rect.bottom > self.height:
self.speed[1] = -self.speed[1]
self.rect.left = clip(self.rect.left, 0, self.width)
self.rect.right = clip(self.rect.right, 0, self.width)
self.rect.top = clip(self.rect.top, 0, self.height)
self.rect.bottom = clip(self.rect.bottom, 0, self.height)

def clip(val, minval, maxval):
return min(max(val, minval), maxval)

class Main(object):
def __init__(self):
self.setup()
def setup(self):
pygame.init()
size = (self.width, self.height) = (640,360)
self.screen = pygame.display.set_mode(size, 0, 32)
self.ball = Ball()
self.setup_background()
def setup_background(self):
self.background = pygame.Surface(self.screen.get_size())
self.background = self.background.convert()
self.background.fill((0, 0, 0))
self.screen.blit(self.background, (0, 0))
pygame.display.flip()
def draw(self):
self.screen.blit(self.background, (0, 0))
self.screen.blit(self.ball.image, self.ball.rect)
pygame.display.flip()
def event_loop(self):
ball = self.ball
friction = 1
while True:
for event in pygame.event.get():
if ((event.type == pygame.QUIT) or
(event.type == pygame.KEYDOWN and
event.key == pygame.K_ESCAPE)):
sys.exit()
elif event.type == pygame.KEYDOWN:
deltax, deltay = delta.get(event.key, (0, 0))
ball.speed[0] += deltax
ball.speed[1] += deltay
friction = 1
elif event.type == pygame.KEYUP:
friction = 0.99

ball.speed = [friction*s for s in ball.speed]
ball.speed[1] += gravity
ball.update()
self.draw()
pygame.time.delay(10)

if __name__ == '__main__':
app = Main()
app.event_loop()``````