テトリスのソースを読む(その4)

http://www.zetcode.com/wxpython/thetetrisgame/のソース解読の続き。

self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)のところ。
wx.EVT_KEY_DOWNはキー入力を表す。その解説は、http://ymasuda.jp/python/wxpython/simplesample.htmlに詳しい。
ここでのイベントハンドラは、

def OnKeyDown(self, event):
    if not self.isStarted or self.curPiece.shape() == Tetrominoes.NoShape:
        event.Skip()
        return

    keycode = event.GetKeyCode()   #押されたキーのコードを返す

    if keycode == ord('P') or keycode == ord('p'):  #ordは指定された文字のアスキーコードを返す
        self.pause()       #たぶん一時停止だろうなー
        return
    if self.isPaused:      #一時停止中であったら何もしない
        return
    elif keycode == wx.WXK_LEFT:   #たぶん左矢印キー
        self.tryMove(self.curPiece, self.curX-1, self.curY)
    elif keycode == wx.WXK_RIGHT:   #たぶん右矢印キー
        self.tryMove(self.curPiece, self.curX+1, self.curY)
    elif keycode == wx.WXK_DOWN:   #たぶん下矢印キー
        self.tryMove(self.curPiece.rotateRight(), self.curX, self.curY)
    elif keycode == wx.WXK_UP:    #たぶん上矢印キー
        self.tryMove(self.curPiece.rotateLeft(), self.curX, self.curY)
    elif keycode == wx.WXK_SPACE:  #これはスペースキー間違いない
        self.dropDown()
    elif keycode == ord('D') or keycode == ord('d'):
        self.oneLineDown()
    else:
        event.Skip()   #他のキーだったら何もしない

ここは比較的やっていることが推測しやすいのだが、実際に動かしたときには矢印キーを押してもなんの反応もない。だめじゃん。スペースキーや'P'はちゃんと動作するのだが...。

続いてself.Bind(wx.EVT_PAINT, self.OnPaint)のところ。
wx.EVT_PAINTが何なのか皆目見当がつかないが、イベントハンドラself.OnPaintをとりあえず見る。

def OnPaint(self, event):

    dc = wx.PaintDC(self)       # これはこういうものだ、として置いておく

    size = self.GetClientSize()  # たぶん作ったパネルのサイズだろうな
    boardTop = size.GetHeight() - Board.BoardHeight * self.squareHeight()  # ※1
  #たぶん下に堆積しているブロックを描いている
    for i in range(Board.BoardHeight):   #高さ方向
        for j in range(Board.BoardWidth):   #横方向
            shape = self.shapeAt(j, Board.BoardHeight-i-1)   # ※2
            if shape != Tetrominoes.NoShape:       # NoShapeでなければ
                self.drawSquare(dc,
                    0+j*self.squareWidth(),
                    boardTop + i*self.squareHeight(), shape)  # ブロックを描くメソッドだろう
    if self.curPiece.shape() != Tetrominoes.NoShape:   # 落ちているブロックのことかな
        for i in range(4):    #落ちている状態のブロックを描く?
            x = self.curX + self.curPiece.x(i)
            y = self.curY - self.curPiece.y(i)      #xとyで符号が違う。x,yは整数なんだよな
            self.drawSquare(dc, 0+x*self.squareWidth(),
                boardTop + (Board.BoardHeight-y-1) * self.squareHeight(),
                self.curPiece.shape())

※1について。Board.BoardWidth=10で横方向のブロック数の最大値を与え、Board.BoardHeight=22で縦方向のブロック数の最大値を与えている(と思う)。だとすると、ブロックのサイズは以下のメソッドで求められる。これらは整数になる?

def squareWidth(self):
    return self.GetClientSize().GetWidth() / Board.BoardWidth  #ブロックの横幅

def squareHeight(self):
    return self.GetClientSize().GetHeight() / Board.BoardHeight #ブロックの縦幅

とすると、※1のboardTopは0だよな。

※2のメソッドself.shapeAtは、次のように値を返すだけ。

def shapeAt(self, x, y):
    return self.board[(y*Board.BoardWidth) + x]

でも(y*Board.BoardWidth)+xとしている理由がわからない。とりあえずパスする。

self.drawSquareの引数を見ると、x座標 0+j*self.squareWidth()、y座標 boardTop+i*self.squareHeight()は、ブロックの左下隅の座標なのではなかろうか。