12 Days of Python – Day 9
This is Day 9 of 12 Days of Python This is the ninth in a series of posts where we use Python and the Pygame module to draw a Christmas scene. Each day we add something else to the scene, and we show a new aspect of Python or Pygame. We’re also having a giveaway, where you can win a Kindle Touch!
On Day 1, we made a Pygame window and used the Pygame draw functions to draw Santa using lines circles and polygons. On Day 2, we made Santa’s arm wave. On Day 3, we added a calendar. On Day 4 we added code to cross off the days on the calendar. On Day 5, we added a background. On Day 6, we added a Christmas tree (using recursion). On Day 7, we drew some Christmas lights. On Day 8, we added a picture on the wall behind Santa.
For Day 9 we’re adding some presents to the scene. To do this, we draw some rectangles, and we use some randomly-placed circles for “wrapping paper” for the presents. The color of the wrapping paper (both the background and the circles) is random. The position of the circles is random, and the presents are also random sizes. So they will look different every time the program is run.
Each present is its own surface, which makes it easy to draw the circles only on the present, and not spill over onto the rest of the scene. We also make a new surface for all the presents to be drawn onto, so the presents can display in front of the tree instead of behind it.
There is a new function called draw_a_present()
, which runs once for each present we draw.
# santa_9.py # This is the code for Day 9 of "12 Days of Python", # by the authors of "Hello World! Computer Programming for Kids and Other Beginners". import pygame, sys, math, datetime, random def draw_a_light(surface, pos): pygame.draw.circle(surface, pygame.color.THECOLORS[random.choice(pygame.color.THECOLORS.keys())], pos, 6) def rotatePointAroundCenter(point, center, degrees): displacement = (point[0] - center[0], point[1] - center[1]) radians = math.radians(degrees) newPoint = [0,0] newPoint[0] = displacement[0] * math.cos(radians) + displacement[1] * math.sin(radians) newPoint[1] = displacement[1] * math.cos(radians) - displacement[0] * math.sin(radians) return newPoint def draw_a_present(surface, (x,y)): (w,h) = random.choice([(100, 100), (50, 50), (75, 75)]) present = pygame.surface.Surface((w,h)) present.fill(pygame.color.THECOLORS[random.choice(pygame.color.THECOLORS.keys())]) spotcolor = pygame.color.THECOLORS[random.choice(pygame.color.THECOLORS.keys())] for i in range(20): spotpos = (random.randint(0, 100), random.randint(0,100)) pygame.draw.circle(present, spotcolor, spotpos, 10) pygame.draw.circle(present, (0,0,0), spotpos, 10, 2) presentrect= present.get_rect() presentrect.bottom = y presentrect.centerx = x surface.blit(present, presentrect) def draw_a_tree(surface, leaf_size, (x,y), is_trunk=True): if is_trunk: rect = pygame.rect.Rect((x - 25, y - 30), (50,60)) pygame.draw.rect(surface, (102,68,34), rect) draw_a_tree(surface, leaf_size, (x, y-30), False) elif leaf_size <= 2: return else: pygame.draw.polygon(surface, (0,200,0),((x-leaf_size/2,y),(x+leaf_size/2,y),(x,y-(2*leaf_size/3)))) draw_a_tree(surface, 3*leaf_size/4, (x, y-leaf_size/3), False) if leaf_size > 30: light_rect=pygame.rect.Rect((0,0), (1,1)) light_rect.width = leaf_size light_rect.height = 2*leaf_size/3 light_rect.bottom = y light_rect.centerx = x pygame.draw.arc(surface, (0,0,0), light_rect, math.radians(-143), math.radians(74-110), 2) draw_a_light(surface, (x,y)) draw_a_light(surface, (x - leaf_size/4, y-leaf_size/20)) draw_a_light(surface, (x + leaf_size/4, y-leaf_size/20)) pygame.init() pygame.display.set_caption("12 Days of Python") screen = pygame.display.set_mode((640,480)) santa = pygame.surface.Surface((640,480)).convert_alpha() santa.fill((0,0,0,0)) screen.fill((0,0,0)) santasArm = pygame.surface.Surface((640,480)).convert_alpha() santasArm.fill((0,0,0,0)) background = pygame.surface.Surface((640,480)) background.fill((255,0,0)) #---BACKGROUND DRAW pygame.draw.polygon(background, (148,123,90), ((0,480), (100,320), (540, 320), (640, 480))) pygame.draw.polygon(background, (139,89,49), ((0,0), (100,0), (100,320), (0,480))) pygame.draw.polygon(background, (139,89,49), ((640,0), (540,0), (540,320), (640,480))) pygame.draw.polygon(background, (102,68,34), ((100,0) ,(540, 0), (540, 320), (100, 320))) calendar = pygame.surface.Surface((189,150)) calendar.fill((255,255,255)) tree = pygame.surface.Surface((640,480)).convert_alpha() tree.fill((0,0,0,0)) draw_a_tree(tree, 200, (100, 360)) #---ARTWORK DRAW artwork = pygame.surface.Surface((640,480)) artwork.fill((0,0,0)) for i in range (100): width = random.randint(0, 250) height = random.randint(0, 100) top = random.randint(0, 400) left = random.randint(0, 500) color_name = random.choice(pygame.color.THECOLORS.keys()) color = pygame.color.THECOLORS[color_name] line_width = random.randint(6, 9) pygame.draw.rect(artwork, color, [left, top, width, height], line_width) artwork = pygame.transform.scale(artwork, (160, 120)) #---PRESENT DRAW presents = pygame.surface.Surface((640,480)).convert_alpha() presents.fill((0,0,0,0)) draw_a_present(presents, (500,400)) draw_a_present(presents, (460,430)) draw_a_present(presents, (70,420)) draw_a_present(presents, (130,440)) #---LIGHTS DRAW pygame.draw.arc(background, (0,0,0), pygame.rect.Rect((0,-30),(320, 60)), -math.pi, 0, 5) pygame.draw.arc(background, (0,0,0), pygame.rect.Rect((320,-30),(320, 60)), -math.pi, 0, 5) draw_a_light(background, (6,6)) draw_a_light(background, (80,25)) draw_a_light(background, (160,30)) draw_a_light(background, (240, 25)) draw_a_light(background, (320, 6)) draw_a_light(background, (400,25)) draw_a_light(background, (480,30)) draw_a_light(background, (560, 25)) draw_a_light(background, (634, 6)) #---CALENDAR DRAW for i in range(0, 189, 27): pygame.draw.line(calendar, (0,0,0), (i,30), (i,150), 2) for i in range(30, 151, 24): pygame.draw.line(calendar, (0,0,0), (0, i), (189, i), 2) cal_head_font = pygame.font.Font(None, 26) cal_head_surface = cal_head_font.render("DECEMBER", True, (0,0,0)) cal_head_rect = cal_head_surface.get_rect() cal_head_rect.center = (94.5, 15) cal_num_font = pygame.font.Font(None, 20) for i in range(1,32): cal_num_surface= cal_num_font.render(str(i), True, (0,0,0)) cal_num_rect = cal_num_surface.get_rect() cal_num_rect.center = (((i+3) % 7 * 27) + 13.5,((i+3) // 7 * 24) + 42) calendar.blit(cal_num_surface, cal_num_rect) calendar.blit(cal_head_surface, cal_head_rect) #---CALENDAR CROSSOUT today = datetime.datetime.now().day for i in range(1, today): pygame.draw.line(calendar, (0,0,0), (((i+3) % 7 * 27) + 27, ((i + 3) // 7 * 24) + 30), (((i + 3) % 7 * 27), ((i + 3) // 7 * 24)+54), 3 ) #---L ARM DRAW pygame.draw.polygon(santasArm,(255,0,0),((274,207),(264,197),(243,182),(226,168), (215,154),(212,153),(206,158),(192,155),(183,157), (182,172),(204,190),(219,208),(244,231),(261,245))) #arm n hand pygame.draw.polygon(santasArm, (255,255,255),((243,182),(242,176),(231,167), (226,168),(218,181),(204,190),(204,200),(212,208), (219,208),(232,197))) #arm fur santasRotArm = santasArm.subsurface(pygame.rect.Rect((182,153),(92, 92))) #---R ARM DRAW pygame.draw.polygon(santa,(255,0,0),((358,191),(405,202),(428,207),(448,212), (457,220),(459,226),(457,232),(444,236),(440,243),(421,237), (399,233),(389,233),(344,236))) #arm n hand pygame.draw.polygon(santa,(255,255,255),((428,207),(418,197),(406,197), (407,204),(400,215),(401,237),(421,238),(421,223))) #arm fur #---L LEG DRAW pygame.draw.polygon(santa,(255,0,0),((270,323),(268,345),(266,352),(305,361), (309,352),(317,326),(319,312),(272,306))) #leg pygame.draw.polygon(santa,(102,68,34),((301,370),(266,361),(247,356),(231,357), (224,368),(227,380),(245,388),(272,386),(274,390),(295,391))) #boot pygame.draw.polygon(santa,(255,255,255), ((301,370),(312,355),(303,352),(293,348), (279,346),(268,342),(263,343),(266,361))) #fur #---R LEG DRAW pygame.draw.polygon(santa,(255,0,0),((322,326),(330,352),(331,359),(372,350), (369,323),(367,311),(316,314))) #leg pygame.draw.polygon(santa, (102,68,34),((340,369),(373,361),(396,356),(410,359), (415,375),(400,387),(366,386),(365,392),(347,393),(340,386))) #boot pygame.draw.polygon(santa,(255,255,255),((373,361),(340,369),(334,368),(326,353), (345,348),(359,347),(375,343))) #---BODY DRAW pygame.draw.polygon(santa, (255,255,255), ((234,289),(226,299),(230,316), (281,322),(304,327),(317,326),(333,322),(363,324), (408,304),(410,287),(402,275),(328,208),(281,207))) #vest fur pygame.draw.polygon(santa, (255,0,0), ((271,188),(245,231),(236,259),(234,272), (235,287),(241,295),(294,302),(300,298),(304,285), (298,217))) #vest 1 pygame.draw.polygon(santa, (255,0,0), ((326,235),(328,286),(330,295),(335,300), (369,297),(401,277),(389,234),(357,192),(334,197))) #vest 2 pygame.draw.circle(santa,(0,0,0),(315,243),4) pygame.draw.circle(santa,(0,0,0),(314,257),4) pygame.draw.circle(santa,(0,0,0),(315,274),4) pygame.draw.circle(santa,(0,0,0),(317,293),4) #---HEAD DRAW pygame.draw.polygon(santa, (255,255,255),((278,153),(272,188), (281,211),(300,232),(315,238),(326,232),(346,215),(357,191), (351,151),(278,153))) #beard pygame.draw.polygon(santa, (255, 218, 185),((282,151),(283,166),(309,178), (315,179),(321,177),(345,166),(346,152),(335,140),(310,133), (289,141))) #head pygame.draw.polygon(santa, (255,0,0),((266,139),(278,123), (293,112),(315,110),(343,115),(312,85),(260,134))) #hat main pygame.draw.polygon(santa,(255,255,255),((346,152),(335,140),(310,133), (289,141),(282,151),(270,150),(261,146),(266,139),(278,123), (293,112),(315,110),(343,115),(357,132))) #hat rim pygame.draw.circle(santa,(255,255,255),(255,149),15) #hat ball pygame.draw.circle(santa,( 50, 50, 50),(307,151),3) #eye pygame.draw.circle(santa,( 50, 50, 50),(319,151),3) #eye pygame.draw.polygon(santa,(255,255,255),((310,140),(301,141),(294,145),(294,149), (303,145),(309,144))) #eyebrow pygame.draw.polygon(santa,(255,255,255),((315,146),(324,146),(330,150),(331,146), (326,142),(317,140))) #eyebrow pygame.draw.polygon(santa,(255,255,255),((283,167),(287,177),(296,182),(311,176), (305,169),)) #mustachelet pygame.draw.polygon(santa,(255,255,255),((344,168),(323,166),(319,176),(336,178))) #mustachelet pygame.draw.lines(santa, (0,0,0), False, ((307,165),(307,169),(310,173),(321,171),(322,164)),2) #nose counter = 0 clock = pygame.time.Clock() while 1: clock.tick(30) for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() screen.fill((0,0,0)) #screen.blit(santasArm, (0,0)) rotatedArm = pygame.transform.rotate(santasRotArm,math.sin(counter/5.0)*10-7) rotArmRect = rotatedArm.get_rect() rotArmPos = rotatePointAroundCenter((86,73),santasRotArm.get_rect().center,-math.sin(counter/5.0)*10+7) rotArmPos[0] += 190 rotArmPos[1] += 180 rotArmRect.center = rotArmPos screen.blit(background, (0,0)) screen.blit(artwork, (120,50)) screen.blit(tree, (0,0)) screen.blit(presents, (0,0)) screen.blit(calendar, (400, 20)) screen.blit(rotatedArm, rotArmRect) screen.blit(santa, (0,0)) pygame.display.flip() counter += 1
Here’s what it looks like when you run it:
To try the code out yourself, you can cut-and-paste it from the code window above into your favorite Python editor.
On Day 10, we’ll add a window to the room.
Warren & Carter