Awesome code Kamilche. I really like it. I'm going to put it in my favorites folder :)
/J On Sat, Mar 8, 2008 at 5:51 AM, Kamilche <[EMAIL PROTECTED]> wrote: > Here's a perspective test I wrote, that I thought others might find > enjoyable. It illustrates a single-point perspective (a 'vanishing > point'), and shows how a room with a floor, ceiling, door, and avatar > changes as the vanishing point changes. > > > import pygame, os, sys, urllib > > SCREENSIZE = (1024, 768) > BACKCOLOR = (150, 150, 150) > INVISIBLE = ( 0, 0, 0, 0) > PERSPECTIVECOLOR = ( 0, 0, 0, 128) > PERSPECTIVEWIDTH = 2 > WALLCOLOR = (255, 128, 0, 220) > WINDOWCOLOR = ( 0, 64, 200, 100) > DOORCOLOR = (100, 64, 50, 200) > CEILINGCOLOR = (255, 255, 255, 255) > FLOORCOLOR = (121, 74, 81, 255) > HORIZONCOLOR = ( 0, 128, 0, 200) > VPCOLOR = (255, 0, 0, 255) > WALLDEPTH = .35 > > VANISHINGPOINT = (SCREENSIZE[0]/2, SCREENSIZE[1]/2) > > bg = None > temp = None > girl = None > > def CalculatePoint(depth, point): > xa, ya = VANISHINGPOINT > xb, yb = point > xbb = xa + depth * (xb-xa) > ybb = ya + depth * (yb-ya) > return int(xbb), int(ybb) > > def Intersection(a,b,c,d): > Ax,Ay = a; Bx,By = b; Cx,Cy = c; Dx,Dy = d > u = float((Dx-Cx)*(Ay-Cy)-(Dy-Cy)*(Ax-Cx)) / > float((Dy-Cy)*(Bx-Ax)-(Dx-Cx)*(By-Ay)) > x = Ax + u*(Bx-Ax) > y = Ay + u*(By-Ay) > return int(x),int(y) > > def DrawWall(): > w, h = SCREENSIZE > topleft = CalculatePoint(WALLDEPTH, (0, 0)) > topright = CalculatePoint(WALLDEPTH, (w, 0)) > bottomleft = CalculatePoint(WALLDEPTH, (0, h)) > bottomright = CalculatePoint(WALLDEPTH, (w, h)) > pos = topleft > wallwidth = int(topright[0]-topleft[0]) > wallheight = int(bottomleft[1]-topleft[1]) > temp.fill(WALLCOLOR) > bg.blit(temp, topleft, [0, 0, wallwidth, wallheight]) > pygame.draw.lines(bg, PERSPECTIVECOLOR, 1, [topleft, topright, > bottomright, bottomleft], PERSPECTIVEWIDTH) > > def DrawOrthogonals(): > pygame.draw.line(bg, PERSPECTIVECOLOR, (0, 0), VANISHINGPOINT, > PERSPECTIVEWIDTH) > pygame.draw.line(bg, PERSPECTIVECOLOR, (SCREENSIZE[0], 0), > VANISHINGPOINT, PERSPECTIVEWIDTH) > pygame.draw.line(bg, PERSPECTIVECOLOR, (0, SCREENSIZE[1]), > VANISHINGPOINT, PERSPECTIVEWIDTH) > pygame.draw.line(bg, PERSPECTIVECOLOR, SCREENSIZE, VANISHINGPOINT, > PERSPECTIVEWIDTH) > pygame.draw.line(bg, HORIZONCOLOR, (0, VANISHINGPOINT[1]), > (SCREENSIZE[0], VANISHINGPOINT[1]), PERSPECTIVEWIDTH) > > def DrawDoor(): > w, h = SCREENSIZE > topleft = CalculatePoint(.9, (0, .25*h)) > topright = CalculatePoint(.7, (0, .25*h)) > bottomleft = CalculatePoint(.9, (0, h)) > bottomright = CalculatePoint(.7, (0, h)) > pos = topleft > windowwidth = int(topright[0]-topleft[0]) > windowheight = int(bottomleft[1]-topleft[1]) > lst = [topleft, topright, bottomright, bottomleft, topleft] > temp.fill(INVISIBLE) > pygame.draw.polygon(temp, DOORCOLOR, lst) > bg.blit(temp, [0, 0]) > pygame.draw.circle(bg, DOORCOLOR, topleft, 5) > pygame.draw.circle(bg, DOORCOLOR, topright, 5) > pygame.draw.circle(bg, DOORCOLOR, bottomright, 5) > pygame.draw.circle(bg, DOORCOLOR, bottomleft, 5) > > def DrawCeiling(): > w, h = SCREENSIZE > vx, vy = VANISHINGPOINT > numtiles = 8 > for i in range(0, SCREENSIZE[0]+1, SCREENSIZE[0]/numtiles): > pygame.draw.line(bg, CEILINGCOLOR, (i, 0), VANISHINGPOINT, 1) > > # Calculate horizontal lines > topright = CalculatePoint(WALLDEPTH, (w, 0)) > for i in range(0, SCREENSIZE[0]+1, SCREENSIZE[0]/numtiles): > try: > x, y = Intersection((0, 0), topright, (i, 0), VANISHINGPOINT) > left = Intersection([0, y], [w, y], (0, 0), VANISHINGPOINT) > right = Intersection([0, y], [w, y], (w, 0), VANISHINGPOINT) > pygame.draw.line(bg, CEILINGCOLOR, left, right, 1) > except: > pass > #pygame.draw.line(bg, CEILINGCOLOR, (0, 0), topright, 1) > > def DrawFloor(): > w, h = SCREENSIZE > factor = 4 > for i in range(-w*factor, w*2*factor, 100): > pygame.draw.line(bg, FLOORCOLOR, (i, h), VANISHINGPOINT, 1) > > def DrawGirl(): > w, h = SCREENSIZE > data = [(.8, (75, h)), (.9, (w/2+50, h)), (WALLDEPTH+.05, (150, h))] > data.sort() > for depth, dest in data: > pt = CalculatePoint(depth, dest) > resizedgirl = pygame.transform.rotozoom(girl, 0, depth) > bg.blit(resizedgirl, [pt[0]-resizedgirl.get_width()/2, > pt[1]-resizedgirl.get_height()]) > pygame.draw.circle(bg, (0, 0, 255), pt, 5) > > def Text(s, _font = []): > if len(_font) == 0: > font = pygame.font.Font(None, 24) > _font.append(font) > font = _font[0] > shadow = font.render(s, 1, (0, 0, 0)) > color = font.render(s, 1, (255, 255, 0)) > w, h = color.get_size() > pic = pygame.Surface((w, h), pygame.SRCALPHA, 32).convert_alpha() > pic.fill(INVISIBLE) > pic.blit(shadow, [1, 1]) > pic.blit(color, [0, 0]) > return pic > > def Draw(): > bg.fill(BACKCOLOR) > DrawCeiling() > DrawFloor() > DrawOrthogonals() > DrawDoor() > DrawWall() > DrawGirl() > pygame.draw.circle(bg, VPCOLOR, VANISHINGPOINT, 5) > > def main(): > global bg, temp, girl, VANISHINGPOINT, WALLDEPTH > pygame.init() > pygame.key.set_repeat(500, 30) > bg = pygame.display.set_mode(SCREENSIZE, 0, 32) > temp = pygame.Surface(SCREENSIZE, pygame.SRCALPHA, 32).convert_alpha() > filename = "posette.png" > if os.path.exists(filename): > girl = pygame.image.load(filename).convert_alpha() > else: > try: > url = "http://www.kamilche.org/webimages/posette.png" > urllib.urlretrieve(url, filename) > girl = pygame.image.load(filename).convert_alpha() > except: > girl = pygame.Surface((150, 300), pygame.SRCALPHA, > 32).convert_alpha() > girl.fill((255, 0, 0, 128)) > > quit = 0 > info1 = Text("Click to move vanishing point, arrow keys to move > wall.") > caption = "" > while not quit: > Draw() > info2 = Text(caption) > bg.blit(info1, [5, 5]) > bg.blit(info2, [5, info1.get_height()+5]) > pygame.display.flip() > pygame.event.pump() > for event in pygame.event.get(): > if event.type == pygame.QUIT: > quit = 1 > break > elif (event.type == pygame.MOUSEBUTTONDOWN and event.button > == 1) or (event.type == pygame.MOUSEMOTION and event.buttons[0] == 1): > # Move vanishing point > VANISHINGPOINT = event.pos > caption = 'Vanishing point = %s' % str(VANISHINGPOINT) > elif event.type == pygame.KEYDOWN: > # Move back wall > if event.key in [pygame.K_LEFT, pygame.K_UP]: > WALLDEPTH = max(0.01, WALLDEPTH - .05) > elif event.key in [pygame.K_RIGHT, pygame.K_DOWN]: > WALLDEPTH = min(1.0, WALLDEPTH + .05) > > pygame.quit() > > main() >