1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

開発のお役立ち情報Advent Calendar 2023

Day 20

Pythonならクリスマスツリーを簡単に描けるはず

Last updated at Posted at 2023-12-19

こんにちは!

12月は季節柄、クリスマスツリーを飾る家庭が多いと思います。
我が家でもツリーを飾っているのですが、片付けが面倒、と思うこともしばしば。

そこで今回は、Pythonの豊富なライブラリを利用して、クリスマスツリーを描いてみることにしました。
ツリーを出さなくていいレベルになるか分かりませんが、やってみます。

やりたいこと

  • クリスマスツリーを描く
  • ライトをチカチカ光らせる
  • 雪を降らせる
  • GIFアニメーションとして保存する

環境構築

Pythonの仮想環境を作ります。

python -m venv tree-art
cd tree-art

ディレクトリに移動した直後の状態

$ ls
bin/		include/	lib/		pyvenv.cfg

仮想環境の有効化

source bin/activate

必要なライブラリのインストール

pip install Pillow

Pillowとは

Pythonに画像処理機能を追加するライブラリです。
様々な画像形式に対応しており、読み込んだ画像の編集もできます。

コード

main.py
import random
import math
from PIL import Image, ImageDraw

frames = []
number_of_frames = 20

# RGBカラーコードで明るい色を定義
led_colors = [
    (255, 128, 128),    # 赤
    (0, 255, 128),      # 緑
    (0, 128, 255),      # 青
    (128, 128, 255),    # 紫
    (255, 255, 64),     # 黄
]

# 星の描画
def draw_star(draw, center, size, color):
    x, y = center
    outer = size
    inner = size / 2.5
    points = []
    angle = 0
    for i in range(5):
        outer_x = x + outer * math.cos(math.radians(angle))
        outer_y = y - outer * math.sin(math.radians(angle))
        points.append((outer_x, outer_y))
        angle += 36
        inner_x = x + inner * math.cos(math.radians(angle))
        inner_y = y - inner * math.sin(math.radians(angle))
        points.append((inner_x, inner_y))
        angle += 36
    draw.polygon(points, fill=color)

# 画像の設定
width, height = 500, 700

for frame_number in range(number_of_frames):
    # 画像と描画オブジェクトの生成
    image = Image.new('RGB', (width, height), color='RGB(0, 0, 110)')
    draw = ImageDraw.Draw(image)

    # 背景に雪を降らせる
    for _ in range(200):  # 雪の数
        snow_x = random.randint(0, width)
        snow_y = random.randint(0, height)
        snow_size = random.randint(2, 5)
        draw.ellipse([snow_x - snow_size, snow_y - snow_size,
                      snow_x + snow_size, snow_y + snow_size], fill="RGB(256, 256, 256)")

    # ツリーの描画
    tree_color = 'RGB(0, 88, 88)'
    tree_positions = [(250, 450), (250, 350), (250, 250)]
    # ツリーの各層を描画
    for i, (x, y) in enumerate(tree_positions):
        size = 250 - i * 50
        draw.polygon([x - size, y, x, y - size * 1.5, x + size, y], fill=tree_color)

    # 雪を積もらせる
    draw.rectangle([0, 550, width, height], fill='RGB(256, 256, 256)')

    # ツリーの幹の描画
    draw.rectangle([230, 450, 270, 550], fill='RGB(101, 67, 33)')

    total_ornaments = 0
    for i, (x, y) in enumerate(tree_positions):
        size = 250 - i * 50
        ornaments_count = 50 - i * 3 * 5
        total_ornaments += ornaments_count
        for _ in range(ornaments_count):
            # ツリーの層の形に基づいて装飾を配置するための計算
            rand_y = random.uniform(y - size * 1.5, y)
            # Y座標に基づいてX座標の最大オフセットを計算
            max_x_offset = (size * 1.5 - (y - rand_y)) / 1.5
            rand_x = random.uniform(x - max_x_offset, x + max_x_offset)
            ornament_color = random.choice(led_colors)
            ornament_size = random.randint(3, 8)
            draw.ellipse((rand_x - ornament_size, rand_y - ornament_size,
                          rand_x + ornament_size, rand_y + ornament_size),
                          fill=ornament_color)

    # 星の描画
    draw_star(draw, (250, 50), 40, 'gold')

    # 生成したフレームをリストに追加
    frames.append(image)

# GIFアニメーションとして保存
frames[0].save('christmas_tree_animation.gif',
               save_all=True,
               append_images=frames[1:],
               duration=1500,  # フレームごとの表示時間(ミリ秒)
               loop=0)  # アニメーションを無限ループ

実行結果

Pythonで描いたツリーはこちらです!
今回はこれが限界でございます🎅
christmas_tree_animation.gif
これはPythonではなく、作成者のデザインセンスの問題ですね。

まとめ

今回は、Pythonでクリスマスツリーを描いてみました🎄
自宅では今年もツリーを出すことになりそうですが、いつの日か、本物のツリーがいらなくなるくらいの精度に仕上げようと思います🎅

みなさんも一緒に頑張りましょう!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?