ゲーム作成に役立つオブジェクト指向7

はじめに

今回はFacadeパターンです。
Facadeパターンは「シンプルな窓口」を提供する方法です。
 
簡単に言えば、
「複雑な操作・手順」を
「簡単」に行えるようにしたラッパークラス、
といえます。

クラス図

ファサードパターン
これは、DirectXAPIに対してFacadeパターンを適用したものです。
 
サブシステムとして、
DirectGraphics/DirectSound/DirectMusic/DirectPlay/DirectInput/DirectShow/Win32
というそれぞれのAPIをラップしたクラスを作っておきます。
 
これらをそのまま使っても良いのですが、さらにそれをラップしたDirectXクラスを作ります。
 
そうやって、ハードウェア部分の操作を行う場合、
DirectXAPIを直接呼ぶことはせず、DirectXクラスの高レベルなAPIを呼ぶだけでよいので、
操作がとても楽になります。
 

メリットとデメリット

メリットに関しては、

  • APIの操作が楽になる
  • 別ハードへの移植が容易になる

という点があります。
 
別ハードへの移植が容易になる、ということに関しては、
例えば画像を表示する場合には、MainはDirectX::Draw()を呼ぶだけで中身の処理のことは考えません。
中身ではDirectXの汚いコードを実行していようが、外には全く関係ないのです。
 
これにより、グラフィックスライブラリを、OpenGLに置き換えた場合、
DirectXクラスを、OpenGLをラップしたOpenGLクラスに置き換えればよいことになります。
(ただ、DirectXクラスなんて名前だと、ソースコードに手を入れる必要があるので、
もっと適切な名前にすれば、ソースコードの修正はなくなるでしょう)
 
デメリットとしては、チーム開発をしている場合に、
DirectXクラスがしっかり完成していないと、開発の進捗がそこで止まってしまう、
ということがあります。
 
そうなった場合に、DirectXクラスの完成を待ちきれない人たちが、
直接APIを呼び出してしまう恐れがあります。
 
で、
「これだったら、最初から直接API叩いてりゃ良かったんだよ!!」
という話になってしまいます。
 
そうならないように、DirectXクラスは充分なゆとりを持って開発することが必要となります。
 

Pygameで画像処理9

グレースケールの改良版です。
 
人の目は緑に最も良く反応し、続いて赤、青という反応をします。
 
よって、このように重みをかけると、
自然なグレースケールになるわけです。
 

import pygame
import math

_gSrc = None

def main():
	pygame.init()
	pygame.display.set_mode((250, 250), 0, 32)
	pygame.display.set_caption("グレースケール2")
	_gScr = pygame.display.get_surface()
	tBuf = pygame.image.load("nyan.bmp").convert()

	for j in range(tBuf.get_height()):
		for i in range(tBuf.get_width()):
			rgba = tBuf.get_at((i, j))
			gray = (
				rgba[0] * 0.299   # r
				+ rgba[1] * 0.587 # g
				+ rgba[2] * 0.114 # b
				) / 3
			tBuf.set_at((i, j), (gray, gray, gray, 255))
	while True:
		_gScr.blit(tBuf, (0, 0), tBuf.get_rect())
		pygame.display.update()
		for e in pygame.event.get():
			if e.type == pygame.QUIT: return
		pygame.time.wait(10)

if __name__ == '__main__':
	main()

Pygameで画像処理10

モザイク化です。
 
画面遷移時に使えますね。

import pygame
import math

# Mosaic
# @param tBuf サーフェス
# @param RECT モザイクをかける範囲
# @param SIZE モザイクの大きさ
def transMosaic(tBuf, RECT, SIZE):
	if(SIZE < 1): return None
	retBuf = pygame.transform.scale(tBuf, tBuf.get_size())
	for j in range(RECT.top, RECT.bottom, SIZE):
		for i in range(RECT.left, RECT.right, SIZE):
			colorSum = 0, 0, 0
			for b in range(SIZE):
				for a in range(SIZE):
					rgba = tBuf.get_at((i+a, j+b))
					colorSum = (
						colorSum[0] + rgba[0],
						colorSum[1] + rgba[1],
						colorSum[2] + rgba[2])
			colorSum = (
				colorSum[0] / ((SIZE)**2),
				colorSum[1] / ((SIZE)**2),
				colorSum[2] / ((SIZE)**2),
				255)
			for b in range(SIZE):
				for a in range(SIZE):
					retBuf.set_at((i+a, j+b), colorSum)
	return retBuf
# Main
def main():
	pygame.init()
	pygame.display.set_mode((250, 250), 0, 32)
	pygame.display.set_caption("モザイク")
	_gScr = pygame.display.get_surface()
	tBuf = pygame.image.load("nyan.bmp").convert()

	i = 1
	while True:
		dstBuf = transMosaic(tBuf, pygame.Rect(50, 50, 100, 100), i)
		i += 1
		if(i > 50): i = 1
		_gScr.blit(dstBuf, (0, 0), dstBuf.get_rect())
		pygame.display.update()
		for e in pygame.event.get():
			if e.type == pygame.QUIT: return
		pygame.time.wait(10)

if __name__ == '__main__':
	main()