[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[pygame] Back to the Scrolling



I've been tinkering with the scrolling screens in pygame more. I've 
added a test function to pygame that draws a row of images in C. I was 
thinking this would make a noticeable impact in speed and still be very 
flexible (since you could still do isometric engines and such by 
blitting a row at a time).

in the end, it doesn't really seem to be speeding things up for me. at 
this point i'm trying to determine if the extra function is worth the 
effort. the function is named "pygame.draw.tilerow()". if you grab the 
latest cvs pygame you can test it out.

i've attached an updated of the now popular scrolling colored blocks 
example. is anyone seeing a difference between this new one and the 
originals we did a couple weeks ago?

in the end i'm not so sure about this. unless it proves valuable to 
someone out there, i have a feeling it will be dropped. at this point 
the C code could still be optimized a bit, but i wouldn't expect much 
more out of it.

note, if you do update from cvs, be sure to rebuild all the c modules, 
there were some internal changes that require a rebuild. this is easy to 
do, "python setup.py install build_ext --force"

everyone feel free to send in ideas on how this could be improved a bit. 
if there's a nice general way to get rid of the python overhead in 
scrolling, i'm all for it. the big performance problem with full 
scrolling is really copying all that memory around, and SDL makes it 
happen twice internally, ugh.


#!/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.numtilesx = 640/tilew+2
	self.numtilesy = 480/tileh+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]
	
	self.cachetilerows()

    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 cachetilerows(self):
    	for y in range(self.tilesy):
	    for x in range(self.tilesx):
	    	tile = self.tile(x,y)
		tile.rowtiles = [self.tile(x+z,y) for z in range(self.numtilesx)]

    def draw(self, screen, px, py):
        #px -= screen.get_rect().centerx
        #py -= screen.get_rect().centery
	startx = px / self.tilew
	starty = py / self.tileh
	px = - (px % self.tilew)
	py = - (py % self.tileh)
	#rowrange = range(startx, startx+self.numtilesx)
    	for y in range(starty, starty + self.numtilesy):
	    #imgs = [self.tile(x,y).image for x in rowrange]
	    imgs = [t.image for t in self.tile(startx,y).rowtiles]
	    pygame.draw.tilerow(screen, imgs, (px, py))
	    py += self.tileh



def main():
    import pygame
    pygame.init()
    flags = 0 #FULLSCREEN|DOUBLEBUF
    screen = pygame.display.set_mode((640, 480), flags)
    print pygame.display.Info()
    print screen
    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), (0,0,0)).convert()
            
        map.draw(screen, posx, posy)
        if message:
	    screen.blit(message, (0,0))
        pygame.display.flip()

if __name__ == '__main__':
    main()