「Pythonでテトリス」を書き換えてHextrisを作ってみました.
画面はこんな感じです.
昔,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