# Car simulation to demonstrate screen wrapping

I have been interested in writing some code that allows an object to wrap around the screen. It turned out to be much simpler than I was expecting, so I kept working and changed the white box that I had to a car that can rotate and move in the direction that it is facing by using basic trigonometry. I then expanded it further to include an image of a track underneath, so that the car would move faster when on the track and slower when on the grass.

However, I'm not sure if the method of checking the red value of the pixel that the car is on is the best solution. So really I'd like to know if there are any better ways of testing for that, but also a review of the rest of the code to see if it could be improved at all.

import sys, pygame
from pygame.locals import *
from math import *

pygame.init()

WIDTH  = 800
HEIGHT = 600
SCREEN = pygame.display.set_mode((WIDTH,HEIGHT))
FPS    = pygame.time.Clock()

pygame.display.set_caption('Screen Wrapping')

def on_track(sprite):
'''Tests to see if car is on the track'''
if sprite.x > 1 and sprite.x < WIDTH - 1 and sprite.y > 1 and sprite.y < HEIGHT - 1:
if track.get_at((int(sprite.x), int(sprite.y))).r == 163 or track.get_at((int(sprite.x), int(sprite.y))).r == 0 or track.get_at((int(sprite.x), int(sprite.y))).r == 255:
return True
return False

class Car(object):
def __init__(self, start_pos = (73, 370), start_angle = 90, image = 'Car.png'):
'''Initialises the Car object'''
self.x     = start_pos[0]
self.y     = start_pos[1]
self.angle = start_angle
self.speed = 0

self.rotcar   = pygame.transform.rotate(self.image, self.angle)

def move(self, forward_speed = 1, rearward_speed = 0.2):
'''Moves the car when the arrow keys are pressed'''
keys = pygame.key.get_pressed()

#Move the car depending on which keys have been pressed
if keys[K_a] or keys[K_LEFT]:
self.angle += self.speed
if keys[K_d] or keys[K_RIGHT]:
self.angle -= self.speed
if keys[K_w] or keys[K_UP]:
self.speed += forward_speed
if keys[K_s] or keys[K_DOWN]:
self.speed -= rearward_speed

#Keep the angle between 0 and 359 degrees
self.angle %= 359

#Apply friction
if on_track(self): self.speed *= 0.95
else: self.speed *= 0.75

#Change the position of the car

def wrap(self):
'''Wrap the car around the edges of the screen'''
self.wrap_around = False

if self.x <  0 :
self.x += WIDTH
self.wrap_around = True

if self.x  + self.rotcar.get_width() > WIDTH:
self.x -= WIDTH
self.wrap_around = True

if self.y  < 0:
self.y += HEIGHT
self.wrap_around = True

if self.y + self.rotcar.get_height() > HEIGHT:
self.y -= HEIGHT
self.wrap_around = True

if self.wrap_around:
SCREEN.blit(self.rotcar, self.rotcar.get_rect(center = (self.x, self.y)))

self.x %= WIDTH
self.y %= HEIGHT

def render(self):
'''Renders the car on the screen'''
self.rotcar   = pygame.transform.rotate(self.image, self.angle)

SCREEN.blit(self.rotcar, self.rotcar.get_rect(center = (self.x, self.y)))

def main():
car   = Car()

while True:
#Blit the track to the background
SCREEN.blit(track, (0, 0))

#Test if the game has been quit
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
pygame.quit()
sys.exit()

car.move()
car.wrap()
car.render()

pygame.display.update()
FPS.tick(30)

if __name__ == '__main__': main()


Here are the images that I've used in the game

Car.png:

Track.png:

• Good job. I like the wrap code.
– skrx
Apr 28, 2017 at 0:22

In the on_track function you can just check if the r value is in the tuple (163, 0, 255). It also looks like you can remove this line if sprite.x > 1 and sprite.x < WIDTH - 1 and sprite.y > 1 and sprite.y < HEIGHT - 1: to check if the pos is in the game area (or can it be outside?).

def on_track(sprite):
"""See if car is on the track."""
color = track.get_at((int(sprite.x), int(sprite.y)))
return color.r in (163, 0, 255)


In render just blit the image at (self.x, self.y):

SCREEN.blit(self.rotcar, (self.x, self.y))


I recommend to load the images globally not in the __init__ method of the classes, otherwise the image has to be loaded again and again when you create a new instance.

Don't use star imports, since they make code harder to read and can cause bugs if they override duplicate names/variables. from pygame.locals import * can be used, but better avoid other star imports.

• Okay, thanks for the advice! I think the if statement in the on_track funcion is necessary, otherwise a list index out of range error is given. And with the blitting of the car, I have to use the center so that it rotates about that point, I'll see if I can implement the other things you've suggested once I get home. Apr 28, 2017 at 6:26
• I had written a very similar comment about the on_track function Apr 28, 2017 at 14:40