『Pythonゲームプログラミング入門』のコードを気取った感じに書き直す

itertoolとかmapとかzipとかを使って。

P98 リスト4-1 すべての色を含む画像の生成(allcolors.py)

元のコード。三重ループなのでネストが深くなってしまっている。

import pygame
from itertools import product
pygame.init()
screen = pygame.display.set_mode((640, 480))
all_colors = pygame.Surface((4096, 4096), depth=24)
for r in xrange(256):
    print r+1, "out of 256"
    x = (r&15)*256
    y = (r>>4)*256
    for g in xrange(256):
        for b in xrange(256):
            all_colors.set_at((x+g, y+b), (r, g, b)) 

pygame.image.save(all_colors, "all_colors.bmp")

itertool.productを利用すると一段で記述できる。r,g,bという変数の並びを見るだけでそれなりに気分がいい。

import pygame
from itertools import product
pygame.init()
screen = pygame.display.set_mode((640, 480))
all_colors = pygame.Surface((4096, 4096), depth=24)
rng = xrange(256)
for r, g, b in product(rng, rng, rng):
    print r+1, "out of 256"
    x = (r&15)*256
    y = (r>>4)*256
    all_colors.set_at((x+g, y+b), (r, g, b)) 

pygame.image.save(all_colors, "all_colors.bmp")

P102 リスト4-3 色をスケーリングするための関数

元のコードは丁寧にcolorを三色の一時変数に分配して、それぞれ計算を行ったあと集約し直している。

def scale_color(color, scale):
    red, green, blue = color
    red = int(red*scale)
    green = int(green*scale)
    blue = int(blue*scale)
    return red, green, blue

mapとlambdaを組み合わせると一行で書き直せる。mapの返り値はlistになるのね。tupleあまり使わないから不明な点が多い。

def scale_color(color, scale):
    return tuple(map(lambda x: int(x*scale), color))

fireball_orange = (221, 99, 20)
print scale_color(fireball_orange, .5) # => (110, 49, 10)

saturate_colorについても同様。

def saturate_color(color):
    return tuple(map(lambda x: min(x, 255), color))

print saturate_color((442, 198, 40)) # => (255, 198, 40)

P104 リスト4-6 線形補間による色のブレンディング

元のコード(一部)。

def blend_color(color1, color2, blend_factor):
    red1, green1, blue1 = color1
    red2, green2, blue2 = color2
    red = red1 + (red2 - red1)*blend_factor
    green = green1 + (green2 - green1)*blend_factor
    blue = blue1 + (blue2 - blue1)*blend_factor
    return int(red), int(green), int(blue)

一行で書くと、zip関数を使って次のようになる。

def blend_color(color1, color2, blend_factor):
    return tuple(map(lambda x: int(x[0]+(x[1]-x[0])*blend_factor), zip(color1, color2)))

と言いたいところだが、これは横に長すぎる(88文字)。一行80文字以下というPythonのコーディングスタイルに反するため、適当に分割する。

def blend_color(color1, color2, blend_factor):
    blend = lambda x: int(x[0] + (x[1] - x[0])*blend_factor)
    return tuple(map(blend, zip(color1, color2)))