#!/usr/bin/env python # An example of a vertical scrolling map with pygame # # Copyright (C) 2013 Antonio Ospite # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # Reference: # https://www.cs.ucsb.edu/~pconrad/cs5nm/topics/pygame/drawing/ import pygame import sys import os IMAGE_PATH = 'road.png' SCREEN_WIDTH = 800 SCREEN_HEIGHT = 480 class VerticalScrollingMap(pygame.Surface): """ There are some assumptions on the scrolling image for the seamless looping effect to work: - The image height must be at least twice the height of the screen/viewport. - The image must have two identical regions, one at the top and one at the bottom, of the same height as the screen/viewport. """ def __init__(self, image, *args, **kwargs): super(VerticalScrollingMap, self).__init__(*args, **kwargs) self.viewport_width, self.viewport_height = self.get_size() self.texture = pygame.image.load(image) self.texture_widht, self.texture_height = self.texture.get_size() self.offset = 0 self.y = 0 # Center along X self.x = (self.viewport_width - self.texture_widht) / 2.0 # NOTE, we assume that the texture has at least twice the height of the # viewport self.lastframe_limit = -(self.texture_height - self.viewport_height) def draw(self, screen): self.y += self.offset # Wrap around to cycle seamlessly self.y %= self.lastframe_limit screen.blit(self.texture, (self.x, self.y)) def set_offset(self, offset): self.offset = offset def inc_offset(self, amount=1): self.offset += amount def dec_offset(self, amount=1): self.offset -= amount def main(): pygame.init() screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.HWSURFACE | pygame.DOUBLEBUF) pygame.display.set_caption('Vertical Scrolling Map') pygame.mouse.set_visible(0) screen_size = screen.get_size() bg_color = (0, 0, 0) background = pygame.Surface(screen_size) background.fill(bg_color) screen.blit(background.convert(), (0, 0)) scrolling_map = VerticalScrollingMap(IMAGE_PATH, screen_size) # If there is a joustick connected it will take precedence # to set the scrolling offset over the key presses try: joystick = pygame.joystick.Joystick(0) joystick.init() axis = 1 except: joystick = None if len(sys.argv) > 1: if sys.argv[1] == '-': outputfile = sys.stdout.fileno() else: outputfile = os.open(sys.argv[1], os.O_WRONLY) else: outputfile = None clock = pygame.time.Clock() fps = 30 exit = False while not exit: msElapsed = clock.tick(fps) for event in pygame.event.get(): if event.type == pygame.QUIT: exit = True break if joystick: val = joystick.get_axis(axis) scrolling_map.set_offset(int(val * 50)) key = pygame.key.get_pressed() if key[pygame.K_ESCAPE]: exit = True if key[pygame.K_UP]: scrolling_map.inc_offset() if key[pygame.K_DOWN]: scrolling_map.dec_offset() if exit: break screen.blit(background.convert(), (0, 0)) scrolling_map.draw(screen) if outputfile: buf = pygame.image.tostring(pygame.display.get_surface(), "RGB", False) os.write(outputfile, buf) pygame.display.update() pygame.quit() if __name__ == '__main__': main()