画面はこんな感じです.
昔,X68000で遊んでいたゲームです.最近は同じ名前の別のゲームがあるようですが...
以下がソースコードです.
#!/usr/bin/env python # -*- coding: utf-8 -*- # Python 2.7.5 on OS X 10.9.2 # by Mitsuharu Arimura 2015/3/14 import Tkinter as Tk import datetime as dt import time, random, math import sys, os, csv # ゲームフィールドのサイズ FIELD_WIDTH = 17 FIELD_HEIGHT = 24 # ブロックのサイズ PIECE_WIDTH = 4 PIECE_HEIGHT = 4 # 1個の六角形セルの1辺の長さ CELL_SIZE = 15 SQRT3 = math.sqrt(3.0) # 六角形を作る関数 def CreateHexagon( canvas, x, y, offset ): # (x0, y0): 六角形の中心 x0 = CELL_SIZE * (x * 1.5 + 1) + offset y0 = CELL_SIZE * (y + 0.5 + x * 0.5) * SQRT3 + offset #print "(%d, %d): (%.1f, %.1f)" % (x, y, x0, y0) # vtx_x, vty_y: 六角形の頂点のx座標と座標の配列(6個) vtx_x = [ x0 + CELL_SIZE * math.cos(i*math.pi/3.0) for i in range(0, 6) ] vtx_y = [ y0 + CELL_SIZE * math.sin(i*math.pi/3.0) for i in range(0, 6) ] #print "x: ", vtx_x #print "y: ", vtx_y r = canvas.create_polygon( vtx_x[0], vtx_y[0], vtx_x[1], vtx_y[1], vtx_x[2], vtx_y[2], vtx_x[3], vtx_y[3], vtx_x[4], vtx_y[4], vtx_x[5], vtx_y[5], fill='white', outline='gray', width=1) return r # ゲーム本体の画面 View class Board( Tk.Canvas ): # フィールドのピクセル数 BOARD_WIDTH = (FIELD_WIDTH + 0.5) * CELL_SIZE * 1.5 BOARD_HEIGHT = (FIELD_HEIGHT + 0.5) * CELL_SIZE * SQRT3 + 3 margin = 2 def __init__( self, master ): self.width = self.BOARD_WIDTH self.height = self.BOARD_HEIGHT Tk.Canvas.__init__( self, master, relief=Tk.RAISED, bd=2, bg='gray', width=self.BOARD_WIDTH, height=self.BOARD_HEIGHT ) #print "Canvas width %d x %d" % ( self.BOARD_WIDTH, self.BOARD_HEIGHT ) # Canvas上の rectangle の2次元配列 # 周囲に1マスずつ余計に取って,グレーに塗り潰しておくのが簡単 self.Field = [[0 for y in range(- int(x*0.5), FIELD_HEIGHT-int(x*0.5))] for x in range(FIELD_WIDTH)] offset = self.margin * 2 + 3 for x in range( FIELD_WIDTH ): for y in range( -int(x*0.5), FIELD_HEIGHT-int(x*0.5) ): self.Field[x][y] = CreateHexagon( self, x, y, offset ) # PAUSEの文字 TEXT_font = ('Helvetica','60','bold') TEXT_color = 'red' self.pause_text = self.create_text( self.BOARD_WIDTH/2, 100, text='PAUSE', font=TEXT_font, fill=TEXT_color, justify=Tk.CENTER) self.hidePauseText() def SetColor( self, x, y, value ): #print "SetColor:" if x < 0: return if x >= FIELD_WIDTH: return if y < -int(x * 0.5): return if y >= FIELD_HEIGHT - int(x * 0.5): return #print "(%d, %d)=>%d" % (x, y, value) if value == 1: self.itemconfigure( self.Field[x][y], fill='black') elif value == 2: self.itemconfigure( self.Field[x][y], fill='gray') elif value == 3: self.itemconfigure( self.Field[x][y], fill='slate gray') else: self.itemconfigure( self.Field[x][y], fill='white') # PAUSE中にPAUSEの文字を表示する def showPauseText( self ): self.itemconfigure( self.pause_text, state=Tk.NORMAL ) # PAUSEが終わるときにPAUSEの文字を非表示にする def hidePauseText( self ): self.itemconfigure( self.pause_text, state=Tk.HIDDEN ) # 次のピースを表示する画面 View class NextPieceBoard( Tk.Canvas ): # 次のピースを表示する場所のサイズ NEXT_BOARD_WIDTH = (PIECE_WIDTH + 0.5) * CELL_SIZE * 1.5 NEXT_BOARD_HEIGHT = (PIECE_HEIGHT + 1.5) * CELL_SIZE * SQRT3 + 3 margin = 2 def __init__( self, master ): Tk.Canvas.__init__( self, master, relief=Tk.RAISED, bd=self.margin, bg='white', width=self.NEXT_BOARD_WIDTH, height=self.NEXT_BOARD_HEIGHT ) self.RectArray = [[0 for y in range(PIECE_HEIGHT)] for x in range(PIECE_WIDTH)] #print self.RectArray offset = self.margin * 2 + 3 for x in range( PIECE_WIDTH ): for y in range( PIECE_HEIGHT ): self.RectArray[x][y] = CreateHexagon( self, x, y, offset ) def DisplayPiecePattern( self, pattern ): p = pattern for x in range( PIECE_WIDTH ): for y in range( PIECE_HEIGHT ): #print "p[%d][%d] = %d" % (x, y, p[x][y]) if p[x][y] == 1: # print "p[%d][%d] = red" % (x, y) self.itemconfigure( self.RectArray[x][y], fill='black' ) else: # print "p[%d][%d] = blue" % (x, y) self.itemconfigure( self.RectArray[x][y], fill='white' ) # ゲーム全体の画面および Controller class Frame( Tk.Frame ): def __init__( self, master=None ): Tk.Frame.__init__( self, master, width=600, height=800 ) self.master.title( 'Hextris' ) ######################################### # board frame #BOARD_WIDTH = (FIELD_WIDTH + 0.5) * CELL_SIZE * 1.5 #BOARD_HEIGHT = (FIELD_HEIGHT + 0.5) * CELL_SIZE * SQRT3 + 3 self.bframe = Tk.Frame( self, bd=1, relief=Tk.RIDGE ) self.bframe.pack( side=Tk.LEFT, padx=10, pady=10 ) self.board = Board( self.bframe ) self.board.pack( side=Tk.LEFT, padx=0, pady=0 ) ######################################### # display frame frame = Tk.Frame( self, bd=1, relief=Tk.RIDGE ) # exit button self.btExit = Tk.Button( frame, text='Exit', command=self.exitGame ) self.btExit.pack( anchor=Tk.E, padx=10, pady=10 ) # replay (not start) button #self.btReplay = Tk.Button( frame, text='Replay', # command=self.replayGame ) #self.btReplay.pack( anchor=Tk.E, padx=10, pady=0 ) # start button self.btStart = Tk.Button( frame, text='Start', command=self.startGame ) self.btStart.pack( anchor=Tk.E, padx=10, pady=0 ) # next piece display self.next_piece = NextPieceBoard( frame ) self.next_piece.pack( anchor = Tk.E, padx=10, pady=10 ) TEXT_font = ('Helvetica','12','italic') NUM_font = ('Helvetica','24','bold') # time text self.time_text = Tk.Label( frame, text='PLAY TIME', font=TEXT_font ) self.time_text.pack( anchor = Tk.E, padx=10, pady=0 ) # timer self.time_box = Tk.Label( frame, text='00\'00\"', font=NUM_font, bd=1, relief=Tk.RIDGE ) self.time_box.pack( anchor = Tk.E, padx=10, pady=0 ) frame.pack( side=Tk.RIGHT, padx=10, pady=10 ) # key bind self.bind( "", self.keyPressed ) self.bind( " ", self.keyLeft ) self.bind( " ", self.keyRight ) self.bind( " ", self.keyUp ) self.bind( " ", self.keyDown ) self.focus_set() self.hextris = Hextris( self ) self.processing_down = False self.timerEventCount = 0 self.timerCount = 0 #self.DisableReplayButton() self.hextris.PrepareStartGame() # exit button def exitGame( self ): self.hextris.playing = False sys.exit() # start button def startGame( self ): self.hextris.playing = True # ボタンは押せなくする self.DisableStartButton() #self.DisableReplayButton() # カウンタをリセットしてタイマーをスタートする self.timerEventCount = 0 self.timerCount = 0 # これ以降,timerEventが0.5秒に一回呼び出される self.after( 500, self.timerEvent ) # prepare replay def replayGame( self ): self.EnableStartButton() self.hextris.PrepareStartGame() self.timerEventCount = 0 self.timerCount = 0 self.DisplayTime( 0, 0 ) # 0.5秒ごとに呼び出される def timerEvent( self ): if self.hextris.playing == False: return if self.hextris.pausing == True: return self.timerEventCount = self.timerEventCount + 1 # 0.5秒に1回呼び出されるので2回→1秒に1回の点数アップ if self.timerEventCount % 2 == 0: self.timerCount = self.timerCount + 1 self.DisplayTime( self.timerCount / 60, self.timerCount % 60 ) # print "count %d" % self.timerEventCount # print "timer %d" % self.timerCount # ブロックを1段落とす self.keyDown( None ) # 0.5秒後に自分を呼び出す self.after( 500, self.timerEvent ) def endGame( self ): self.focus_set() self.replayGame() def DisableExitButton( self ): self.btExit.configure( state=Tk.DISABLED ) def EnableExitButton( self ): self.btExit.configure( state=Tk.NORMAL ) def DisableReplayButton( self ): #self.btReplay.configure( state=Tk.DISABLED ) pass def EnableReplayButton( self ): #self.btReplay.configure( state=Tk.NORMAL ) pass def DisableStartButton( self ): self.btStart.configure( state=Tk.DISABLED ) def EnableStartButton( self ): self.btStart.configure( state=Tk.NORMAL ) def DisplayTime( self, min=0, sec=0 ): self.time_box.configure( text="%02d\'%02d\"" % (min, sec) ) # 以下はキー入力処理 def keyPressed( self, event ): c = event.char # space: pause if self.hextris.playing == False: return if c == ' ': if self.hextris.pausing == False: print "PAUSE!!!" self.hextris.pausing = True # PAUSEを表示 self.board.showPauseText() else: print "PAUSE END!!!" self.hextris.pausing = False # PAUSEを隠す self.board.hidePauseText() # 再度タイマーを開始 self.after( 500, self.timerEvent ) def keyLeft( self, event ): if self.hextris.playing == False: return if self.hextris.pausing == True: return # print "press Left" if self.hextris.CanMovePiece( move='left' ) == 0: self.hextris.MovePiece( move='left' ) self.hextris.RedrawAllField() def keyRight( self, event ): if self.hextris.playing == False: return if self.hextris.pausing == True: return # print "press Right" if self.hextris.CanMovePiece( move='right' ) == 0: self.hextris.MovePiece( move='right' ) self.hextris.RedrawAllField() # キーで呼ばれるのとタイマーで呼ばれるのが同時に重なる場合が # あるので再入防止している def keyDown( self, event ): #print "keyDown" if self.hextris.playing == False: return if self.hextris.pausing == True: return # print "press Down" if self.processing_down == True: return self.processing_down = True res = self.hextris.CanMovePiece( move='down' ) if res == 0: self.hextris.MovePiece( move='down' ) self.hextris.RedrawAllField() elif res == 2: self.hextris.FixPieceAndGetNextPiece() self.processing_down = False # 回転 def keyUp( self, event ): if self.hextris.playing == False: return if self.hextris.pausing == True: return # print "press Up" if self.hextris.CanTurnPiece() == True: self.hextris.TurnPiece() self.hextris.RedrawAllField() # Hextrisゲームの Data class Hextris: # ゲームフィールド field = [[0 for y in range(FIELD_HEIGHT)] for x in range(FIELD_WIDTH)] # 現在移動中のブロック piece = [[0 for y in range(PIECE_HEIGHT)] for x in range(PIECE_WIDTH)] # ブロックの左上端の座標(フィールドは左上が(x,y) = (0,0)でyが下向き) location = [0, 0] # ブロック # 種類の数を揃えておくこと!!! # listにaddしていくと,ここで数を書く必要は無い ID_NUM = 10 id = 0 # 0...ID_NUM-1の8種類 id_next = 0 # 次のピース ORIENT_NUM = 6 orientation = 0 # 0...ORIENT_NUM-1の6種類 # 次のブロック nextPiece = [[[0 for y in range(PIECE_HEIGHT)] for x in range(PIECE_WIDTH)] for o in range(ORIENT_NUM)] # ブロックの全てのパターン index, orientation, x, y毎に1, 0 piecePattern = [[[[0 for y in range(PIECE_HEIGHT)] for x in range(PIECE_WIDTH)] for o in range(ORIENT_NUM)] for i in range(ID_NUM)] piecePattern[0] = [ [[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]], # 方向0の[x][y] [[0,1,0,0],[0,1,0,0],[0,1,0,0],[0,1,0,0]], # 方向1 [[0,0,0,1],[0,0,1,0],[0,1,0,0],[1,0,0,0]], # 方向2 [[0,0,0,0],[1,1,1,1],[0,0,0,0],[0,0,0,0]], # 方向3 [[0,1,0,0],[0,1,0,0],[0,1,0,0],[0,1,0,0]], # 方向4 [[0,0,0,1],[0,0,1,0],[0,1,0,0],[1,0,0,0]]] # 方向5 piecePattern[1] = [ [[0,0,0,0],[1,1,0,0],[0,1,1,0],[0,0,0,0]], # 方向0の[x][y] [[0,0,1,0],[0,0,1,0],[0,1,0,0],[0,1,0,0]], # 方向1 [[0,0,0,1],[0,1,1,0],[1,0,0,0],[0,0,0,0]], # 方向2 [[0,0,0,0],[1,1,0,0],[0,1,1,0],[0,0,0,0]], # 方向3 [[0,0,1,0],[0,0,1,0],[0,1,0,0],[0,1,0,0]], # 方向4 [[0,0,0,1],[0,1,1,0],[1,0,0,0],[0,0,0,0]]] # 方向5 piecePattern[2] = [ [[0,0,0,0],[0,0,1,1],[1,1,0,0],[0,0,0,0]], # 方向0の[x][y] [[0,1,0,0],[0,1,1,0],[0,0,1,0],[0,0,0,0]], # 方向1 [[0,0,1,0],[0,1,0,0],[0,1,0,0],[1,0,0,0]], # 方向2 [[0,0,0,0],[0,0,1,1],[1,1,0,0],[0,0,0,0]], # 方向3 [[0,1,0,0],[0,1,1,0],[0,0,1,0],[0,0,0,0]], # 方向4 [[0,0,1,0],[0,1,0,0],[0,1,0,0],[1,0,0,0]]] # 方向5 piecePattern[3] = [ [[0,1,0,0],[1,1,0,0],[1,0,0,0],[0,0,0,0]], # 方向0の[x][y] [[0,1,1,0],[1,1,0,0],[0,0,0,0],[0,0,0,0]], # 方向1 [[0,1,1,0],[0,1,1,0],[0,0,0,0],[0,0,0,0]], # 方向2 [[0,1,0,0],[1,1,0,0],[1,0,0,0],[0,0,0,0]], # 方向3 [[0,1,1,0],[1,1,0,0],[0,0,0,0],[0,0,0,0]], # 方向4 [[0,1,1,0],[0,1,1,0],[0,0,0,0],[0,0,0,0]]] # 方向5 piecePattern[4] = [ [[0,0,0,0],[0,0,0,1],[1,1,1,0],[0,0,0,0]], # 方向0の[x][y] [[0,1,0,0],[0,1,0,0],[0,1,1,0],[0,0,0,0]], # 方向1 [[0,0,0,1],[0,0,1,0],[0,1,0,0],[0,1,0,0]], # 方向2 [[0,0,0,0],[0,1,1,1],[1,0,0,0],[0,0,0,0]], # 方向3 [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]], # 方向4 [[0,0,1,0],[0,0,1,0],[0,1,0,0],[1,0,0,0]]] # 方向5 piecePattern[5] = [ [[0,0,0,0],[1,1,1,0],[0,0,1,0],[0,0,0,0]], # 方向0の[x][y] [[0,1,0,0],[0,1,0,0],[0,1,0,0],[1,0,0,0]], # 方向1 [[0,0,0,1],[0,0,1,0],[1,1,0,0],[0,0,0,0]], # 方向2 [[0,0,0,0],[1,0,0,0],[1,1,1,0],[0,0,0,0]], # 方向3 [[0,1,0,0],[1,0,0,0],[1,0,0,0],[1,0,0,0]], # 方向4 [[0,0,1,1],[0,1,0,0],[1,0,0,0],[0,0,0,0]]] # 方向5 piecePattern[6] = [ [[0,0,0,0],[0,0,1,0],[1,1,1,0],[0,0,0,0]], # 方向0の[x][y] [[0,1,0,0],[0,1,1,0],[0,1,0,0],[0,0,0,0]], # 方向1 [[0,0,1,0],[0,1,0,0],[1,1,0,0],[0,0,0,0]], # 方向2 [[0,0,0,0],[0,1,1,1],[0,1,0,0],[0,0,0,0]], # 方向3 [[0,0,1,0],[0,1,1,0],[0,0,1,0],[0,0,0,0]], # 方向4 [[0,0,0,0],[0,0,1,1],[0,0,1,0],[0,1,0,0]]] # 方向5 piecePattern[7] = [ [[0,0,0,0],[0,1,1,1],[0,0,1,0],[0,0,0,0]], # 方向0の[x][y] [[0,0,1,0],[0,0,1,0],[0,1,1,0],[0,0,0,0]], # 方向1 [[0,0,0,0],[0,0,1,0],[1,1,0,0],[1,0,0,0]], # 方向2 [[0,0,0,0],[0,1,0,0],[1,1,1,0],[0,0,0,0]], # 方向3 [[0,1,1,0],[0,1,0,0],[0,1,0,0],[0,0,0,0]], # 方向4 [[0,0,1,0],[0,1,1,0],[1,0,0,0],[0,0,0,0]]] # 方向5 piecePattern[8] = [ [[0,1,1,0],[1,0,0,0],[1,0,0,0],[0,0,0,0]], # 方向0の[x][y] [[0,1,1,0],[1,0,1,0],[0,0,0,0],[0,0,0,0]], # 方向1 [[0,1,1,0],[0,0,1,0],[0,1,0,0],[0,0,0,0]], # 方向2 [[0,0,1,0],[0,0,1,0],[1,1,0,0],[0,0,0,0]], # 方向3 [[0,0,0,0],[1,0,1,0],[1,1,0,0],[0,0,0,0]], # 方向4 [[0,1,0,0],[1,0,0,0],[1,1,0,0],[0,0,0,0]]] # 方向5 piecePattern[9] = [ [[0,0,1,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]], # 方向0の[x][y] [[0,1,0,0],[0,1,1,0],[1,0,0,0],[0,0,0,0]], # 方向1 [[0,0,1,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]], # 方向2 [[0,1,0,0],[0,1,1,0],[1,0,0,0],[0,0,0,0]], # 方向3 [[0,0,1,0],[1,1,0,0],[0,1,0,0],[0,0,0,0]], # 方向4 [[0,1,0,0],[0,1,1,0],[1,0,0,0],[0,0,0,0]]] # 方向5 def __init__( self, parent ): self.main_frame = parent self.main_board = parent.board self.next_piece = parent.next_piece # ゲームの開始準備 def PrepareStartGame( self ): self.playing = False self.pausing = False self.game_end = False # 盤面の初期化 # 全部を白で塗る for y in range( FIELD_HEIGHT ): for x in range( FIELD_WIDTH ): self.field[x][y] = 0 # 周囲1列を3で塗る for y in range( FIELD_HEIGHT ): self.field[0][y] = 3 for x in range( FIELD_WIDTH ): self.field[x][ -int(x*0.5)+FIELD_HEIGHT - 1 ] = 3 for y in range( FIELD_HEIGHT ): self.field[ FIELD_WIDTH-1 ][-int((FIELD_WIDTH-1)*0.5)+y] = 3 # 1個目のピースを準備する self.GetNextPiece( True ) self.RedrawAllField() # 1行だけ消す処理 # offset: 0 or 1 def DeleteOneLine( self, line, offset ): # 上から1行落とす # 下から上に向かって1行ずつ,上の行を下の行にコピーする for y in range(line, 1, -1): for x in range(1,FIELD_WIDTH-1): # offsetが0か1かでジグザグのパターンが変わる y0 = y-int((x+offset)*0.5) self.field[x][y0] = self.field[x][y0-1] self.RedrawAllField() # 埋まっている行を全て消す処理 def DeleteFilledLines( self ): #print "Start Delete Line!!!" # yとoffsetで両方のパターンのジグザグのカウントをする y = FIELD_HEIGHT - 2 # 一番下の行を除く. offset = 0 deleted_line = 0 # 削除できた行の数 all_clear = 0 # 残りが0になった場合 # 一番上の行まで確認 count_sum = 0 while y >= 0: # 1行に埋まってるセルの個数を数える #print "count line %d, offset %d:" % (y, offset), # 1行のカウント count = 0 for x in range(1, FIELD_WIDTH-1): # 両端を除く #print "%d" % self.field[x][y-int((x+offset)*0.5)], # offsetが0か1かでジグザグのパターンが変わる if self.field[x][y-int((x+offset)*0.5)] == 2: count = count + 1 #print "count %d" % count # 全部が埋まっていたら行の削除処理 if count == FIELD_WIDTH - 2: # 両端を除いた数 # 削除できた場合にはyは増えない offsetも増えないのが良い #print "clear line %d" % y self.DeleteOneLine(y, offset) deleted_line = deleted_line + 1 else: count_sum = count_sum + count # 全部が埋まっていなかったら次の行へ行く if offset == 0: offset = 1 else: # offset == 1 offset = 0 y = y - 1 print "end Delete Line!!! (%d lines)" % deleted_line print "%d cells left (including double counting)" % count_sum # count_sumが0だったらボーナス if count_sum == 0: all_clear == 1 print '########################################' print '######## ALL CELLS CLEARED #############' print '########################################' # 現在のピースが落ち切ったので,ここに固定する # 行が埋まったら消す # 次のピースを開始する def FixPieceAndGetNextPiece( self ): # 現在のピースを現在の位置に固定する for x in range(PIECE_WIDTH): for y in range(PIECE_HEIGHT): if self.piece[x][y] == 1: self.field[self.location[0]+x][self.location[1]+y] = 2 # 埋まっている行を消す self.DeleteFilledLines() # 次のピース self.GetNextPiece( False ) self.RedrawAllField() # next pieceの領域に次のピースを作成する def CreatePiece( self ): self.id_next = random.randint(0, len(self.piecePattern)-1) #self.id_next = 9 #print "piece pattern [%d]" % self.id_next, self.orientation = 0 #print "piece orientation [%d]" % self.orientation # パターンi self.nextPiece = self.piecePattern[self.id_next] #print "-->", self.nextPiece #print "orientation 0 -->", self.nextPiece[0] # 向き0を表示する self.next_piece.DisplayPiecePattern( self.nextPiece[0] ) # next pieceの領域からピースを持ってきて一番上に置く # 既にここまでピースが積んであったらゲームオーバー判定 def GetNextPiece( self, is_first ): if is_first: self.CreatePiece() #print self.nextPiece self.location[0] = 5 self.location[1] = -2 # 次のピースを持ってくる(向きは0方向) self.id = self.id_next self.piece = self.piecePattern[self.id][0] for x in range( PIECE_WIDTH ): for y in range( PIECE_HEIGHT ): # フィールドに置く self.main_board.SetColor( self.location[0]+x, self.location[1]+y, self.piece[x][y]) # ゲーム終了判定 for y in range( PIECE_HEIGHT ): # 内側のxのloopから抜けて来ていたら,ここでも抜ける if self.game_end == True: break for x in range( PIECE_WIDTH ): # フィールドに置いた瞬間,既にその場所にブロックがあったら if ( self.piece[x][y] == 1 and self.field[self.location[0]+x][self.location[1]+y] == 2): # 終わり self.game_end = True # 次回でタイマーでのloopを止める self.playing = False # 1個重なっていれば十分なので,ここで抜ける break if self.game_end == False: # 終わっていなかったら続ける self.CreatePiece() else: # ゲームオーバー処理の開始 print "GAME END !!!" self.main_frame.endGame() def MoveOrientation( self, move ): xmove = ymove = 0 if move == 'down': ymove = 1 elif move == 'left': xmove = -1 if self.location[0] % 2 == 1: ymove = 1 elif move == 'right': xmove = 1 if self.location[0] % 2 == 0: ymove = -1 return ( xmove, ymove ) def MovePiece( self, move ): ( xmove, ymove ) = self.MoveOrientation( move ) self.location[0] = self.location[0] + xmove self.location[1] = self.location[1] + ymove def TurnPiece( self ): self.orientation = (self.orientation + 1) % self.ORIENT_NUM self.piece = self.piecePattern[self.id][self.orientation] # 移動した先を計算して,fieldとかぶらないか,はみ出ないかを見る # return 1: 左右の壁に当たって移動できない # return 2: 積んであるフィールド上のセルと重なるか, # 下に当たっているので,これで固定する def CanMovePiece( self, move='down' ): ( xmove, ymove ) = self.MoveOrientation( move ) ( x0, y0 ) = ( self.location[0], self.location[1] ) # フィールド上のセルと重なっている場合 flag = 0 for x in range(PIECE_WIDTH): for y in range(PIECE_HEIGHT): if ( self.piece[x][y] == 1 and self.field[x0+x+xmove][y0+y+ymove] >= 1 ): flag = 1 #print "move NG (4) (%d,%d)->(%d,%d)" % ( # self.location[0]+x, self.location[1]+y, # self.location[0]+x+xmove, self.location[1]+y+ymove ) break if flag == 1: if ymove == 1: return 2 # 下に動けない場合はこれで固定 else: return 1 # 左右ぶつかっている場合は,動けないだけ # 以上のチェックに引っかからない場合は動ける return 0 # 回転した先を計算して,fieldとかぶらないか,はみ出ないかを見る # True: 回転できる def CanTurnPiece( self ): turnedPiece = [[0 for y in range(PIECE_HEIGHT)] for x in range(PIECE_WIDTH)] o = (self.orientation + 1) % self.ORIENT_NUM turnedPiece = self.piecePattern[self.id][o] # 確認 flag = 0 for x in range(PIECE_WIDTH): for y in range(PIECE_HEIGHT): # 添字が範囲を越えているかどうかの判定 xx = self.location[0] + x yy = self.location[1] + y if ( xx < 0 or xx >= FIELD_WIDTH ): flag = 1 print "turn NG (1)" break if ( yy < -int((self.location[0]+x) * 0.5) or yy >= FIELD_HEIGHT - int((self.location[0]+x) * 0.5) ): flag = 1 print "turn NG (2)" break # 重なっている場合 if ( turnedPiece[x][y] == 1 and self.field[xx][yy] >= 1 ): flag = 1 print "turn NG (3)" break if flag == 1: return False else: return True # 再描画 def RedrawAllField( self ): # ゲームの終了後は実行しない # 開始前は表示する if self.game_end == True: return #print "RedrawAllField" # まず固定セル for x in range( FIELD_WIDTH ): for y in range( - int(x * 0.5), FIELD_HEIGHT - int(x * 0.5) ): self.main_board.SetColor( x, y, self.field[x][y] ) # 次に移動中のpiece for x in range( PIECE_WIDTH ): for y in range( PIECE_HEIGHT ): xx = x + self.location[0] yy = y + self.location[1] if xx < 0: pass if xx >= FIELD_WIDTH: pass if yy < -int(x * 0.5): pass if yy >= FIELD_HEIGHT - int(x * 0.5): pass # 描かれていない場所まで塗らないようにする if self.piece[x][y] == 1: self.main_board.SetColor( xx, yy, 1 ) ##------ if __name__ == '__main__': f = Frame() f.pack() f.mainloop() # EOF
0 件のコメント:
コメントを投稿