いぬおさんのおもしろ数学実験室

おいしい紅茶でも飲みながら数学、物理、工学、プログラミング、そして読書を楽しみましょう

ゲームプログラミングの「スプライト」とは何か

 2Dのゲームなどを作るときの「スプライト」という技術があります。正確な定義は知りませんが、実際にどんなものなのか説明しましょう。背景が表示されていて、そこで小さなキャラクタが動き回るときに使います。背景は固定、動くのはキャラクタだけです。こんな感じです。
f:id:Inuosann:20200527113841p:plain:w200
f:id:Inuosann:20200527113848p:plain:w200

下のような背景があります。数値の並びですが、コンピュータでは画像は数値の並びとして扱います。数値の大きさは明るさと考えてください。
f:id:Inuosann:20200527124138p:plain:w200
この背景の中を次のようなキャラクタを動かします。中程の0でない数値の辺りがキャラクタです。
f:id:Inuosann:20200527111319p:plain:w200
これを単純に背景に重ねるとキャラクタの絵だけでなく四角形全体の絵が背景に描き込まれてしまい、うまくありません。そこで、次の抜き型を用いるのです。背景×抜き型(かけ算)を各ドットで実行します。
f:id:Inuosann:20200527115216p:plain:w200
かけ算で次のような絵が得られます。背景からキャラクタの位置の部分を切り抜いた絵です。
f:id:Inuosann:20200527124451p:plain:w200
上の絵と、キャラクタを合成(各ドットで足し算する)すると次の通り。
f:id:Inuosann:20200527124249p:plain:w200
これで背景の一部にキャラクタが合成されました!! これを繰り返して背景の中をキャラクタが動くように見せているのです。実際には「かけ算」、「足し算」のところは「and」、「or」なのですが、分かりやすさを優先ました。
 以下のPythonのコードでは(原理は同じようなものなのでしょうが)かなり異なり、キャラクタの絵の中で色としては扱わない、透過して背景が見える色を指定しています。ここではキャラクタの画像の真っ白の部分が透過して背景が見えるように指定しています。最初のやり方に比べるとずっと楽です。

import sys
import pygame as pg
from pygame.locals import QUIT
SURFACE = pg.display.set_mode((1200, 800))
img1 = pg.image.load("abc.png").convert()
img2 = pg.image.load("sample.png").convert()
img2.set_colorkey((255,255,255)) #透過色をセット
FPSCLOCK = pg.time.Clock()
counter = 1
x=0
y=0
while True:
    for event in pg.event.get():
        if event.type == QUIT:
            pg.quit()
            sys.exit()
    SURFACE.fill((0, 0, 0))
    SURFACE.blit(img1, (250,250))
    SURFACE.blit(img2, (x,y)) #スプライト描画
    x += 1
    y += 1
    pg.display.update()
    FPSCLOCK.tick(10)
    counter += 1

最初の★の絵はこれで描きました。使いやすいです。やっていることは恐らく同じようなものでしょうが、今回前半で紹介した理屈は本当の原理、ハードウェアも使わない、元々のスプライトです。

追加:
 「元々のスプライト」は時代としては次の本が出ていた頃のこと。著者の日高氏は当時有名なゲームプログラマで、ぼくも彼の描いた本を何冊も持っていました。 

この本もそのうちの1冊。手元に置いてなく、この本にスプライトが載っていたかどうか分かりませんが、とにかく著者が元気で、読んで「自分も頑張ろう!」と思ったものです。たいしたツールも何もなく(音を鳴らすのも自分でルーチンを書く!)、必要なものは全部自分で作らなければならなかった時代です。何もかも懐かしいです……。