Pygameラッパライブラリ
Pygameを使いやすくするためのラッパライブラリを作ってみました。
Pygame自体が優れたライブラリなので、ラッパする必要なないのですが…。
しかし、なんというか、逆に使いにくくなっているかもしれません(´▽`;
提供する機能は、マウス入力と、単純な図形の描画機能のラッパです。
あと、シーン遷移クラスを用意しています。
使い方についてはmain.pyのサンプルを見ることになります。(手抜きだ…(´Д`;
<pygamelib.py>
# PygameLib # Pygameを使いやすくしたライブラリです。 import pygame import pygraphics import pyinput class PygameLib: def __init__(self): self.sceneManager = None # シーンマネージャ self.width = 0 # 画面サイズ(横) self.height = 0 # 画面サイズ(縦) self.clearColor = (0, 0, 0) # 消去色 self.flgExit = False # ゲーム終了フラグ self.wait = 10 # 更新ウェイト self.graphics = pygraphics.PyGraphics() self.input = pyinput.PyInput() # シーンマネージャ登録 def registSceneManager(self, mng): self.sceneManager = mng # 初期化処理 def initialize(self, width, height): pygame.init() self.width = width self.height = height pygame.display.set_mode((width, height), 0, 32) self._screen = pygame.display.get_surface() for scene in self.sceneManager.sceneDict.values(): scene.create(self, self.graphics, self.input) # ゲームループ def run(self): while True: if(self.flgExit): return for e in pygame.event.get(): if(e.type == pygame.QUIT): return pygame.display.update() pygame.time.wait(self.wait) self._screen.fill(self.clearColor) # 入力情報更新 self.input.reflesh() # シーン実行 self.getScene().update() # シーン遷移 def changeScene(self, key): self.sceneManager.changeScene(key) # シーン取得 def getScene(self): return self.sceneManager.scene
<pygraphics.py>
# 描画関連のラッパークラスです import pygame from util import * import math class PyGraphics: # 文字列の描画 def drawMessage(self, pos, message, size=25, fColor=(255, 255, 255, 255), bColor=None): font = pygame.font.SysFont("", size) if(bColor == None): pygame.display.get_surface().blit(font.render(message, 0, fColor), pos.getTuble()) else: pygame.display.get_surface().blit(font.render(message, 0, fColor, bColor), pos.getTuble()) # 線分描画 def drawLine(self, pos1, pos2, color=(0, 0, 255, 255)): pygame.draw.line(pygame.display.get_surface(), color, pos1.getTuble(), pos2.getTuble()) # 円描画 def drawCircle(self, pos, radius, color=(0, 0, 255, 255)): pygame.draw.circle(pygame.display.get_surface(), color, pos.getTuble(), radius) # 矩形描画 def drawRect(rect, color=(0, 0, 255, 255)): pygame.draw.rect(pygame.display.get_surface(), color, rect)
<pyinput.py>
# 入力関連のラッパークラスです import pygame from util import * class PyInput: def __init__(self): self.pushDict = {} self.pressDict = {} self.pressDictPrev = {} self.mouse = Vec2D() def reflesh(self): self.refleshMouse() self.refleshPress() self.refleshPush() def refleshMouse(self): self.mouse.x, self.mouse.y = pygame.mouse.get_pos() def refleshPush(self): for key in self.pressDict.keys(): if(self.pressDict[key] and not(self.pressDictPrev[key])): if(self.pushDict.has_key(key)): del self.pushDict[key] self.pushDict[key] = True else: self.pushDict[key] = False def refleshPress(self): for item in self.pressDict.iteritems(): self.pressDictPrev[item[0]] = item[1] mouseL, mouseM, mouseR = pygame.mouse.get_pressed() self.pressDict["M_L"] = mouseL self.pressDict["M_M"] = mouseM self.pressDict["M_R"] = mouseR # そのフレーム内に押したかどうか def isPush(self, strKey): if(self.pushDict.has_key(strKey)): return self.pushDict[strKey] else: return False # 押しているかどうか def isPress(self, strKey): if(self.pressDict.has_key(strKey)): return self.pressDict[strKey] else: return False
<scene.py>
# シーン抽象クラス class IScene: def create(self, p, g, i): self.p = p self.g = g self.i = i def initialze(self): raise "Cannot instance." def update(self): raise "Cannot instance." # シーン管理クラス class SceneManager: def __init__(self): self.sceneDict = {} self.scene = None def regist(self, key, scene): self.sceneDict[key] = scene def getScene(self): return self.scene def changeScene(self, key): if(self.sceneDict.has_key(key)): self.scene = self.sceneDict[key] else: raise "Non-Existance Key :%s" % (key)
<util.py>
import math # 2次元ベクトル class Vec2D: def __init__(self, x=0, y=0): self.x = x self.y = y def __add__(self, pos): return Vec2D(self.x + pos.x, self.y + pos.y) def __iadd__(self, pos): return Vec2D(self.x + pos.x, self.y + pos.y) def __sub__(self, pos): return Vec2D(self.x - pos.x, self.y - pos.y) def __mul__(self, vec): return self.x*vec.x + self.y*vec.y def __eq__(self, vec): return (self.x==vec.x and self.y==vec.y) def nomalize(self): d = math.sqrt(self.x ** 2 + self.y ** 2) * 1.0 if(d == 0): d = 1 return Vec2D(self.x / d, self.y / d) def cross(self, scalar): return Vec2D(self.x*scalar, self.y*scalar) def lengthSq(self): return self.x*self.x + self.y*self.y def distance(self, vec): return math.sqrt(pow(self.x - vec.x, 2) + pow(self.y - vec.y, 2)) def distanceSq(self, vec): return pow(self.x - vec.x, 2) + pow(self.y - vec.y, 2) def getOrthogonalVector(self): return Vec2D(self.y, -self.x) def reverse(self): return Vec2D(self.x*-1, self.y*-1) def getTuble(self): return (self.x, self.y) def debug(self): print "(x,y)=(%f,%f)" % (self.x, self.y) # タスク基底クラス class Task: def __init__(self, pos=Vec2D(0,0), mov=Vec2D(0,0), age=-99): self.pos = pos self.mov = mov self.age = age self.alive = True def update(self): self.pos += self.mov self.age -= 1 if(self.age == 0): return False return True def debug(self): print "p(x,y)=(%d,%d) m(x,y)=(%d,%d) a=%d" % (self.pos.x, self.pos.y, self.mov.x, self.mov.y, self.alive)
<main.py>
import pygamelib import scene import math import random from util import * # タイトルシーン class SceneTitle(scene.IScene): def __init__(self): self.timer = 0 def initialize(self): self.timer = 0 def update(self): posX = random.randint(-1, 1) posY = random.randint(-1, 1) self.g.drawMessage(Vec2D(200+posX, 100+posY), "Atomic Bomb ver 0.1", 30) self.timer += 2 if(self.timer > 360): self.timer -= 360 alpha = 255*abs(math.sin(math.radians(self.timer))) self.g.drawMessage( Vec2D(240, 200), "Push Left Click!", 25, (255, 255, 255, 255), (alpha, 0, 0, alpha)) if(self.i.isPush("M_L")): self.p.changeScene(1) self.p.getScene().initialize() # 爆弾タスク class Bomb(Task): def __init__(self, pos): self.r = 1 self.pos = pos self.color = (0, 255, 0, 255) def Update(self): self.r += 1 if(self.r > 300): self.r = 300 color = self.r*255/100.0 if(color > 255): color = 255 self.color = (color, 255-color, 0, 255) if(self.r > 100): return False # ドカン return True # メインシーン class SceneMain(scene.IScene): def __init__(self): self.score = 0 self.bombList = [] self.effectList = [] self.gameover = False def initialize(self): self.score = 0 self.bombList = [] self.effectList = [] self.gameover = False self.p.wait = 100 def update(self): posX = random.randint(-5, 5) posY = random.randint(-5, 5) size = random.randint(30, 32) self.g.drawMessage(Vec2D(200+posX, 100+posY), "Atomic Bomb ver 0.1", size) if(random.randint(0, 30) == 0): if(len(self.bombList) < 64): # 爆弾登場 bomb = Bomb(Vec2D(random.randint(100, 540), random.randint(100, 380))) self.bombList.append(bomb) # 爆弾 tmpList = [] emergency = False for bomb in self.bombList: if(not(self.gameover)): if(self.i.isPush("M_L")): if(self.i.mouse.distance(bomb.pos) < bomb.r): # 爆破 self.score += 10 # スコア self.p.wait /= 2 # タイマを早める if(self.p.wait < 1): self.p.wait = 1 for i in range(10): effect = Task( Vec2D(bomb.pos.x, bomb.pos.y), Vec2D(random.randint(-5, 5), random.randint(-5, 5)), 30) self.effectList.append(effect) continue if(not(bomb.Update())): self.gameover = True if(bomb.r > 50): emergency = True # 爆弾描画 self.g.drawCircle(bomb.pos, bomb.r, bomb.color) tmpList.append(bomb) self.bombList = tmpList if(emergency and not(self.gameover)): self.g.drawMessage(Vec2D(240, 150), "Emergency!!!", 25, (255, 0, 0, 0)) # 爆破 tmpList = [] for effect in self.effectList: if(effect.update()): effect.mov.y += 0.1 alpha = math.sin(math.radians(effect.age * 90 / 20)) * 255 self.g.drawCircle(effect.pos, 5, (alpha, alpha, 0, alpha)) tmpList.append(effect) self.effectList = tmpList # ゲームオーバー if(self.gameover): self.g.drawMessage(Vec2D(250, 200), "GAME OVER") self.g.drawMessage( Vec2D(240, 250), "Push Right Click", 25, (255, 255, 255, 255)) if(self.i.isPush("M_R")): self.p.changeScene(0) self.p.getScene().initialize() # スコア self.g.drawMessage(Vec2D(0, 0), "SCORE:%d" % (self.score)) def main(): # シーン登録 mng = scene.SceneManager() sTitle = SceneTitle() sMain = SceneMain() mng.regist(0, sTitle) mng.regist(1, sMain) mng.changeScene(0) pgl = pygamelib.PygameLib() pgl.registSceneManager(mng) # 初期化 pgl.initialize(640, 480) # 実行 pgl.run() if(__name__ == "__main__"): main()