Pygameを使ってFeedタイトルを電光掲示板っぽく

ちょっとPythonネタ。学校の授業の関係で最近Pygameを触ってる。今回のネタも課題のプログラムを少し調整したものになってる。ってよく考えたら課題と関係ねえ。

ともあれ、作ったのはPythonのRSS/Atom feed用モジュールであるfeedparserで読み込んだFeedを、Pygameを使って電光掲示板のようにスクロールして表示するスクリプト。実行すると以下のように表示される。

feed_neon

実際は右向きあるいは左向きにタイトルがスクロールしている。Pygameはそもそもゲーム作成用フレームワークなのでそういうアニメーションがかなり楽なんだよねー。

まぁ、これは、使い道と言っても、できるのはフィードのタイトルを眺めるくらいだし、そもそもPygameの実行環境持ってる人なんてほとんどいなさそうなので、どうしようもなかったりするんだけど。一応ソースは以下へ。

#!/usr/bin/evn python
# -*- coding:utf-8 -*-

import sys
import feedparser
import random
import pygame
from pygame.locals import *

SCREEN_WIDTH = 640
SCREEN_HIGHT = 480
MOVE_SPEED   = 10
FONT_PATH    = '/path/to/your/favorite/font'
FEED_LIMIT   = 10

class ScrollText(pygame.sprite.Sprite):
    def __init__(self, text, position = (0,0)):
        pygame.sprite.Sprite.__init__(self)

        font = pygame.font.Font(FONT_PATH, 32)

        self.image = font.render(
            text,
            True,
            (random.randint(0,255), random.randint(0,255), random.randint(0,255))
        )
        self.rect  = self.image.get_rect()
        self.speed = random.choice([-1, 1]) * random.randint(1,5)

        self.rect.topleft = position

    def update(self):
        self.rect = self.rect.move(self.speed, 0)

        if self.rect.left > SCREEN_WIDTH:
            self.rect.right = 0
        elif self.rect.right < 0:
            self.rect.left = SCREEN_WIDTH


def get_titles_from(url):
    feed = feedparser.parse(url)
    titles = []
    for entry in feed['entries']:
        titles.append(entry.title)
    return titles;


def main():
    pygame.init()
    screen = pygame.display.set_mode( (SCREEN_WIDTH, SCREEN_HIGHT) )
    pygame.display.set_caption('feed neon')
    
    if len(sys.argv) > 1:
        feed_url = sys.argv[1]
    else:
        feed_url = 'http://b.hatena.ne.jp/hotentry?mode=rss'
        
    feed_titles = get_titles_from(feed_url)

    text_group = pygame.sprite.Group()
    count = 0
    for feed_title in feed_titles:
        text = ScrollText(
            feed_title,
            (random.randint(0,SCREEN_WIDTH), 10 + 40 * count)
        )
        text_group.add(text)

        count += 1
        if count > FEED_LIMIT:
            break
        
    clock = pygame.time.Clock()

    while True:
        clock.tick(60)

        for event in pygame.event.get():
            if (event.type == QUIT
               or (event.type == KEYDOWN and event.key == K_ESCAPE)):
                return

        screen.fill( (0,0,0) )

        text_group.update()
        text_group.draw(screen)

        pygame.display.flip()


if __name__ == '__main__': main()