Last active
August 1, 2019 09:00
-
-
Save kiyotune/fdff6672734617b9b8eb19d74a458e9e to your computer and use it in GitHub Desktop.
『テトリス風ゲームづくりで学ぶ初めてのPYTHONプログラミング』写経
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/python3 | |
#coding: UTF-8 | |
import tkinter as tk | |
from tkinter import messagebox | |
import threading, copy, random | |
def exit_app(self, event=None): | |
print("\n[exit_app]") | |
if(messagebox.askokcancel("py_tetris", "exit ?")): | |
quit() | |
class BoardSize: | |
Piece = 20 | |
Width = 10 | |
Height = 22 | |
def light_color(color, light): | |
color_rgb_r = int(color[1:3], 16) | |
color_rgb_g = int(color[3:5], 16) | |
color_rgb_b = int(color[5:7], 16) | |
rgb_r = int((255 - color_rgb_r) * (light - 100) / 100 + color_rgb_r) | |
rgb_g = int((255 - color_rgb_g) * (light - 100) / 100 + color_rgb_g) | |
rgb_b = int((255 - color_rgb_b) * (light - 100) / 100 + color_rgb_b) | |
return '#%02x%02x%02x' % (rgb_r, rgb_g, rgb_b) | |
def dark_color(color, dark): | |
color_rgb_r = int(color[1:3], 16) | |
color_rgb_g = int(color[3:5], 16) | |
color_rgb_b = int(color[5:7], 16) | |
rgb_r = int(color_rgb_r * dark / 100) | |
rgb_g = int(color_rgb_g * dark / 100) | |
rgb_b = int(color_rgb_b * dark / 100) | |
return '#%02x%02x%02x' % (rgb_r, rgb_g, rgb_b) | |
class Block: | |
shapeNo = [[0, 0],[0, 0],[0, 0],[0, 0]] | |
shapeZ = [[0, -1],[0, 0],[-1, 0],[-1, 1]] | |
shapeS = [[0, -1],[0, 0],[1, 0],[1, 1]] | |
shapeLine = [[0, -1],[0, 0],[0, 1],[0, 2]] | |
shapeT = [[-1, 0],[0, 0],[1, 0],[0, 1]] | |
shapeSquare = [[0, 0],[1, 0],[0, 1],[1, 1]] | |
shapeL = [[-1, -1],[0, -1],[0, 0],[0, 1]] | |
shapeMirroredL = [[1, -1],[0, -1],[0, 0],[0, 1]] | |
BlockTable = [shapeNo, shapeZ, shapeS, shapeLine, shapeT, shapeSquare, shapeL, shapeMirroredL] | |
sRED='#ff0000' | |
sGREEN='#00ff00' | |
sBLUE='#0000ff' | |
sYELLOW='#ffff00' | |
sCYAN='#00ffff' | |
sLIGHT_BLUE='#add8e6' | |
sVIOLET_RED='#d02090' | |
Colors = ['BLACK', sRED, sGREEN, sBLUE, sYELLOW, sCYAN, sLIGHT_BLUE, sVIOLET_RED] | |
light = ['BLACK'] | |
dark = ['BLACK'] | |
for i in range(1,8): | |
light.append(light_color(Colors[i], 150)) | |
dark.append(dark_color(Colors[i], 50)) | |
Light = light | |
Dark = dark | |
class GameBoard(tk.Canvas): | |
def __init__(self, app): | |
tk.Canvas.__init__(self, app) | |
self.initGameBoard() | |
self.timerStop = False | |
self.timeInterval = 0.4 | |
self.myTimer() | |
app.protocol('WM_DELETE_WINDOW', self.windowClose) | |
def initGameBoard(self): | |
self.BlockTable = Block.BlockTable | |
self.colors = Block.Colors | |
self.light = Block.Light | |
self.dark = Block.Dark | |
self.board=[] | |
for i in range(BoardSize.Height): | |
board_row = [0] * BoardSize.Width | |
self.board.append(board_row) | |
self.pSize = BoardSize.Piece - 1 | |
self.pre_board = copy.deepcopy(self.board) | |
self.isCurBlock = False | |
def SetBlockOnBoard(self, set_board, block_coords, x, y, block_shape): | |
for i in range(4): | |
piece_x = block_coords[i][0] + x | |
piece_y = block_coords[i][1] + y | |
set_board[piece_y][piece_x] = block_shape | |
def DrawBlock(self, copy_board, block_coords, x, y, block_shape): | |
self.SetBlockOnBoard(copy_board, block_coords, x, y, block_shape) | |
self.board = copy.deepcopy(copy_board) | |
self.curBlockCoords = copy.deepcopy(block_coords) | |
[self.curShape, self.curX, self.curY] = [block_shape, x, y] | |
try: | |
self.OnPaint() | |
except: | |
pass | |
def OnTimer(self): | |
copy_board = copy.deepcopy(self.board) | |
if not self.isCurBlock: | |
newShape = random.randint(1, 7) | |
newBlockCoords = copy.deepcopy(self.BlockTable[newShape]) | |
[newX, newY] = [int(BoardSize.Width / 2), 1] | |
self.DrawBlock(copy_board, newBlockCoords, newX, newY, newShape) | |
self.isCurBlock = True | |
else: | |
self.SetBlockOnBoard(copy_board, self.curBlockCoords, self.curX, self.curY, 0) | |
if self.curY > BoardSize.Height - 4: | |
self.timerStop = True | |
else: | |
self.DrawBlock(copy_board, self.curBlockCoords, self.curX, self.curY+1, self.curShape) | |
def OnPaint(self): | |
for i in range(BoardSize.Height): | |
for j in range(BoardSize.Width): | |
self.pre_shape = self.pre_board[i][j] | |
shape = self.board[i][j] | |
tag_name = 'Piece_' + str(i) + '_' + str(j) | |
if shape != self.pre_shape: | |
if self.pre_shape != 0: | |
self.delete(tag_name) | |
if shape != 0: | |
[x, y] = [j * BoardSize.Piece, i * BoardSize.Piece] | |
print(f'x={x}, y={y}, self.pSize = {self.pSize}') | |
self.create_rectangle(x, y, x + self.pSize, y + self.pSize, fill=self.colors[shape], tag=tag_name) | |
self.create_line(x, y, x, y + self.pSize, fill=self.light[shape], tag=tag_name) | |
self.create_line(x, y, x + self.pSize, y, fill=self.light[shape], tag=tag_name) | |
self.create_line(x, y + self.pSize, x + self.pSize, y + self.pSize, fill=self.dark[shape], tag=tag_name) | |
self.create_line(x + self.pSize, y + self.pSize, x + self.pSize, y, fill=self.dark[shape], tag=tag_name) | |
self.pre_board = copy.deepcopy(self.board) | |
def myTimer(self): | |
if self.timerStop == False: | |
self.OnTimer() | |
self.timer_thread = threading.Timer(self.timeInterval, self.myTimer) | |
self.timer_thread.daemon = True | |
self.timer_thread.start() | |
def windowClose(self): | |
self.timerStop = True | |
app.destroy() | |
class TetGame: | |
def __init__(self, app): | |
self.app = app | |
self.w = BoardSize.Piece * BoardSize.Width | |
self.h = BoardSize.Piece * BoardSize.Height | |
gameboard = GameBoard(app) | |
gameboard.place(x=0, y=0) | |
gameboard.config(width=self.w, height=self.h, bg='black', highlightthickness=2) | |
self.Center() | |
def Center(self): | |
ws = self.app.winfo_screenwidth() | |
hs = self.app.winfo_screenheight() | |
x = int((ws/2)-((self.w+4)/2)) | |
y = int((hs/2)-((self.h+4)/2)) | |
self.app.geometry(f'{self.w+4}x{self.h+4}+{x}+{y}') #ex) 400x300+500+250 | |
app = tk.Tk() | |
app.title("TetGame") | |
tetgame = TetGame(app) | |
app.bind("<Escape>", exit_app) | |
app.mainloop() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment