#!/usr/bin/env python # -*- coding: utf-8 -*- import pygame import random # Parameters WIDTH = 960 HEIGHT = 480 ROAD_COLOR = pygame.Color('#000000FF') WALL_COLOR = pygame.Color('#FFFFFFFF') FONT_COLOR = pygame.Color('#00FF00FF') CAR_COLOR = [pygame.Color('#FF0000FF'), pygame.Color('#0000FFFF')] OPPONENT_COLOR = pygame.Color('#AAAAAAFF') WHEEL_COLOR = pygame.Color('#7F7F7FFF') LEFT = [pygame.K_s, pygame.K_LEFT] RIGHT = [pygame.K_f, pygame.K_RIGHT] FONT = 'Monospace' WAIT = 5000 # Secondary parameters MID_WIDTH = WIDTH//2 TRACK_WIDTH = MID_WIDTH//3 CAR_SIZE = TRACK_WIDTH//10 SEGMENTS_PER_LINE = (HEIGHT//3)//CAR_SIZE SEG_MIN_X = 0 SEG_MAX_X = MID_WIDTH-TRACK_WIDTH ABS_MAX_DIR = TRACK_WIDTH//10 OFFSETS = [0, TRACK_WIDTH, MID_WIDTH, MID_WIDTH+TRACK_WIDTH] curTopRow = 1 curPlayerX = [WIDTH//4, MID_WIDTH+WIDTH//4] lastDir = 0 lastX = TRACK_WIDTH lastRow = 0 segmentsUntilNewDir = SEGMENTS_PER_LINE segments = [] players = [] opponents = [] proba_op = 0.05 scores = [0, 0] class Segment: def __init__(self): global lastDir, lastX, lastRow, segmentsUntilNewDir lastRow += 1 self.row = lastRow self.top_x = lastX if (lastX+lastDir < SEG_MIN_X) or (lastX+lastDir > SEG_MAX_X): lastDir = -lastDir self.dir = lastDir lastX += lastDir segmentsUntilNewDir -= 1 if segmentsUntilNewDir == 0: segmentsUntilNewDir = SEGMENTS_PER_LINE lastDir = random.randrange(0, 2*ABS_MAX_DIR)-ABS_MAX_DIR def draw(self, scroll): s = pygame.display.get_surface() y = (self.row-curTopRow)*CAR_SIZE+scroll s.lock() for o in OFFSETS: pygame.draw.line(s, WALL_COLOR, (o+self.top_x, y), (o+self.top_x+self.dir, y+CAR_SIZE)) s.unlock() def delete(self, scroll): s = pygame.display.get_surface() if self.dir > 0: x = self.top_x else: x = self.top_x+self.dir y = (self.row-curTopRow)*CAR_SIZE+scroll for o in OFFSETS: s.fill(ROAD_COLOR, pygame.Rect(o+x, y, abs(self.dir)+1, CAR_SIZE+1)) def collides(self, rect, scroll): if self.dir > 0: x = self.top_x else: x = self.top_x+self.dir y = (self.row-curTopRow)*CAR_SIZE+scroll for o in OFFSETS: if rect.colliderect(pygame.Rect(o+x, y, abs(self.dir)+1, CAR_SIZE+1)): return True return False class Car: def create_surface(self, color): s = pygame.Surface((8, 8)).convert() s.lock() s.fill(ROAD_COLOR) pygame.draw.rect(s, WHEEL_COLOR, pygame.Rect(0, 0, 2, 3), 1) pygame.draw.rect(s, WHEEL_COLOR, pygame.Rect(0, 4, 2, 3), 1) pygame.draw.rect(s, WHEEL_COLOR, pygame.Rect(6, 0, 2, 3), 1) pygame.draw.rect(s, WHEEL_COLOR, pygame.Rect(6, 4, 2, 3), 1) pygame.draw.rect(s, color, pygame.Rect(3, 0, 2, 8), 1) pygame.draw.rect(s, color, pygame.Rect(2, 1, 4, 1), 1) pygame.draw.rect(s, color, pygame.Rect(2, 5, 4, 1), 1) pygame.draw.rect(s, color, pygame.Rect(1, 7, 6, 1), 1) s.unlock() self.surf = pygame.transform.scale(s, (CAR_SIZE, CAR_SIZE)) class Opponent(Car): def __init__(self): self.row = lastRow self.top_x = random.randrange(lastX, lastX+TRACK_WIDTH-CAR_SIZE) self.create_surface(OPPONENT_COLOR) def draw(self, scroll): for p in [0, 1]: pygame.display.get_surface().blit(self.surf, self.rect(p, scroll)) def delete(self, scroll): for p in [0, 1]: pygame.display.get_surface().fill(ROAD_COLOR, self.rect(p, scroll)) def collides(self, rect, scroll): for p in [0, 1]: if rect.colliderect(self.rect(p, scroll)): return True return False def rect(self, player, scroll): y = (self.row-curTopRow)*CAR_SIZE+scroll return pygame.Rect(self.top_x+player*MID_WIDTH, y, CAR_SIZE, CAR_SIZE) class Player(Car): def __init__(self, player): self.player = player self.ok = True self.create_surface(CAR_COLOR[player]) def draw(self, scroll): if self.ok: pygame.display.get_surface().blit(self.surf, self.rect()) if scroll == CAR_SIZE-1: scores[self.player] += 1 self.score = font.render(str(scores[self.player]), False, FONT_COLOR).convert() pygame.display.get_surface().blit(self.score, self.score.get_rect().move((self.player*MID_WIDTH, HEIGHT-self.score.get_height()))) def delete(self): if self.ok: pygame.display.get_surface().fill(ROAD_COLOR, self.rect()) pygame.display.get_surface().fill(ROAD_COLOR, self.score.get_rect().move((self.player*MID_WIDTH, HEIGHT-self.score.get_height()))) def rect(self): return pygame.Rect(curPlayerX[self.player], 0, CAR_SIZE, CAR_SIZE) def crash(self): self.ok = False # Initialisation pygame.init() pygame.event.set_allowed([pygame.QUIT, pygame.KEYDOWN, pygame.KEYUP]) pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption('Course') pygame.display.get_surface().fill(ROAD_COLOR) pygame.mouse.set_visible(0) dir = [0, 0] font = pygame.font.SysFont(FONT, max(8, WIDTH//50)) for i in range(1, HEIGHT//CAR_SIZE): segments.append(Segment()) opponents.append(None) for i in [0, 1]: players.append(Player(i)) # Main loop run = True scroll = CAR_SIZE-1 while run: # collide? run = False for p in [0, 1]: if players[p].ok: if segments[0].collides(players[p].rect(), scroll) or (opponents[0] and opponents[0].collides(players[p].rect(), scroll)): players[p].crash() else: run = True # draw for s in segments: s.draw(scroll) for o in opponents: if o: o.draw(scroll) for p in players: p.draw(scroll) pygame.display.update() # wait pygame.time.wait(150//CAR_SIZE) # clear & next for s in segments: s.delete(scroll) for o in opponents: if o: o.delete(scroll) for c in players: c.delete() scroll -= 1 if scroll < 0: curTopRow += 1 scroll = CAR_SIZE-1 segments.pop(0) opponents.pop(0) segments.append(Segment()) if random.random() < proba_op: opponents.append(Opponent()) else: opponents.append(None) proba_op += 0.001 # manage events for evt in pygame.event.get(): if evt.type == pygame.QUIT: run = False WAIT = 0 elif evt.type == pygame.KEYUP: for p in [0, 1]: if evt.key == LEFT[p] and dir[p] < 0: dir[p] = 0 break if evt.key == RIGHT[p] and dir[p] > 0: dir[p] = 0 break elif evt.type == pygame.KEYDOWN: if evt.key == pygame.K_ESCAPE: run = False WAIT = 0 else: for p in [0, 1]: if evt.key == LEFT[p]: dir[p] = -1 break elif evt.key == RIGHT[p]: dir[p] = 1 break for p in [0, 1]: if dir[p] < 0: curPlayerX[p] -= 1 elif dir[p] > 0: curPlayerX[p] += 1 pygame.time.wait(WAIT)