[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [pygame] Fast Scrolling
Damien Miller wrote:
> Can anyone point me to a good example of a fast scrolling background
> (full-screen or nearly full-screen)?
i wrote a pretty cool and fast scrolling tile engine for my 48 hour
game. unfortunately i never got to creating an actual map to scroll
around. here is a small cleaned up version of the scrolling code.
#!/usr/bin/env python
"""
the Map class stores all the tiles in a big list. you can lookup
any tile by calling the "tile(x,y)" method. it does a little
voodoo to speed up the drawing loop. you call the draw() method
with a surface and "map x,y" position arguements. the x,y
coordinates are in actual pixels, and that will be the position
in the center of the screen. it allows for any size tiles and map.
i admit it's not written to be clear, as much turbo quick and
semi flexible. you can run it for a simple scrolling example
with the mouse. hopefully this is quick enough for you, i don't think it can
be much quicker with just python code. I've been thinking about
a C function in pygame to blit a "row" of images. But I'm not
certain that would make a noticeable difference?
Pete Shinners, November 21, 2002
"""
import pygame, random
from pygame import *
TILESIZE = 64, 64
MAPSIZE = 30, 30
class Tile:
blocked = 0
def __init__(self):
#make a random colored block
color = map(random.randint, [0]*3, [255]*3)
self.image = pygame.Surface(TILESIZE).convert()
self.image.fill(color)
class Map:
def __init__(self):
#initialize variables
tilew, tileh = TILESIZE
self.drawloop = [((x+1), (y+1), (x-1)*tilew, (y-1)*tileh+2)
for y in range(480/tileh+2) for x in range(640/tilew+2)]
self.tilesx, self.tilesy = MAPSIZE
self.tilew = tilew
self.tileh = tileh
#fill the map with tiles
self.tiles = [Tile() for x in range(self.tilesx*self.tilesy)]
self.outofbounds= self.tiles[0]
def tile(self, x, y):
if x<0 or y<0 or x>=self.tilesx or y>=self.tilesy:
return self.outofbounds
return self.tiles[y*self.tilesx+x]
def draw(self, screen, px, py):
px -= screen.get_rect().centerx
py -= screen.get_rect().centery
xoffs = self.tilew - (px % self.tilew)
yoffs = self.tileh - (py % self.tileh)
xtile = px / self.tilew
ytile = py / self.tileh
blit = screen.blit
for x,y,xpos,ypos in self.drawloop:
tile = self.tile(x+xtile, y+ytile)
pos = xpos+xoffs, ypos+yoffs
blit(tile.image, pos)
if __name__ == '__main__': #test it out
import pygame
pygame.init()
flags = 0 #FULLSCREEN|DOUBLEBUF
screen = pygame.display.set_mode((640, 480), flags)
posx, posy = 800, 800
map = Map()
timer = pygame.time.Clock()
pygame.time.set_timer(USEREVENT, 1000)
font = pygame.font.Font(None, 40)
message = None
while 1:
timer.tick()
for e in pygame.event.get():
if e.type == QUIT: raise SystemExit, "QUIT"
if e.type == KEYDOWN and e.key == K_ESCAPE: raise SystemExit, "ESCAPE"
if e.type == MOUSEMOTION:
posx -= e.rel[0]
posy -= e.rel[1]
elif e.type == USEREVENT:
s = "Frames Per Second: %.2f" % timer.get_fps()
message = font.render(s, 0, (255,255,255)).convert()
map.draw(screen, posx, posy)
if message: screen.blit(message, (0,0))
pygame.display.flip()