|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
本帖最后由 Aaron栩生阿龙 于 2025-10-12 21:21 编辑
前两天上课的时候突然产生了在renpy里塞俄罗斯方块的想法,而且找到了一个特别简单的方式,在群里问了一下好像之前没有人做这个,于是我花了两个小时的时间写了一个,这里放上代码
注意这个是纯Python代码
[RenPy] 纯文本查看 复制代码
"""renpy
init -2 python:
"""
import random
class Tetris():
def __init__(self, width=10, height=20):
self.width = width
self.height = height
self.shapes = [
[[1, 1, 1, 1]], # I
[[1, 1], [1, 1]], # O
[[0, 1, 0], [1, 1, 1]], # T
[[0, 0, 1], [1, 1, 1]], # L
[[1, 0, 0], [1, 1, 1]], # J
[[0, 1, 1], [1, 1, 0]], # S
[[1, 1, 0], [0, 1, 1]], # Z
]
self.reset_game()
def reset_game(self):
self.board = [[0 for _ in range(self.width)] for _ in range(self.height)]
self.score = 0
self.gameover = False
self.current_shape = None
self.current_color = None
self.current_x = 0
self.current_y = 0
self.next_shape = None
self.next_color = None
self._generate_next_shape()
self._new_shape()
def _generate_next_shape(self):
self.next_shape = random.choice(self.shapes)
self.next_color = random.randint(1, 7)
def _new_shape(self):
self.current_shape = self.next_shape
self.current_color = self.next_color
self.current_x = self.width // 2 - len(self.current_shape[0]) // 2 # 水平居中
self.current_y = 0
self._generate_next_shape()
if self.check_collision(0, 0):
self.gameover = True
def check_collision(self, dx, dy, rotated_shape=None):
shape = rotated_shape if rotated_shape is not None else self.current_shape
for y, row in enumerate(shape):
for x, cell in enumerate(row):
if cell:
new_x = self.current_x + x + dx
new_y = self.current_y + y + dy
if (new_x < 0 or new_x >= self.width or # 左右边界
new_y >= self.height or # 下边界
(new_y >= 0 and self.board[new_y][new_x])): # 下方的方块
return True
return False
def rotate_shape(self):
# 这里的逻辑是将矩阵转置然后反转每一行,相当于是顺时针旋转90°
rows = len(self.current_shape)
cols = len(self.current_shape[0])
rotated = [
[self.current_shape[rows - j -1][i] for j in range(rows)] for i in range(cols)
]
if not self.check_collision(0, 0, rotated):
self.current_shape = rotated
def move(self, dx):
if not self.gameover and not self.check_collision(dx, 0):
self.current_x += dx
def drop(self):
if not self.gameover and not self.check_collision(0, 1):
self.current_y += 1
else: # 这里是如果没法落下就说明碰到了下边界或者下面的方块,那么就把当前的方块固定
self.lock_shape()
self.clear_lines()
self._new_shape()
def lock_shape(self):
for y, row in enumerate(self.current_shape):
for x, cell in enumerate(row):
if cell:
board_x = self.current_x + x
board_y = self.current_y + y
if board_y >= 0:
self.board[board_y][board_x] = self.current_color
def clear_lines(self):
cleared_lines = 0
new_board = []
for row in self.board:
if 0 not in row:
cleared_lines += 1
else:
new_board.append(row)
for _ in range(cleared_lines):
new_board.insert(0, [0 for _ in range(self.width)])
self.board = new_board
self.score += cleared_lines ** 2
def dropping_cell(self):
temp_board = [row.copy() for row in self.board]
for y, row in enumerate(self.current_shape):
for x, cell in enumerate(row):
if cell:
temp_x = self.current_x + x
temp_y = self.current_y + y
if 0 <= temp_y < self.height and 0 <= temp_x < self.width:
temp_board[temp_y][temp_x] = self.current_color
return temp_board
上面的是整体的逻辑部分,接下来是界面部分,这里是renpy代码
[RenPy] 纯文本查看 复制代码
image c0 = Solid('#000000', xysize=(30, 30))
image c1 = Solid('#66D2D6', xysize=(30, 30))
image c2 = Solid('#FFEE99', xysize=(30, 30))
image c3 = Solid('#A67FDB', xysize=(30, 30))
image c4 = Solid('#F9B384', xysize=(30, 30))
image c5 = Solid('#6C8CD5', xysize=(30, 30))
image c6 = Solid('#8CD98C', xysize=(30, 30))
image c7 = Solid('#E88388', xysize=(30, 30))
init python:
tetris = Tetris()
def tetris_board(st, at, tetris):
cells = []
for row in tetris.dropping_cell():
for cell in row:
cells.append(f'c{cell}')
board = Grid(tetris.width, tetris.height, *cells)
return board, 0.1
def tetris_next_shape(st, at, tetris):
cells = []
for row in tetris.next_shape:
for cell in row:
if cell != 0:
cell = tetris.next_color
cells.append(f'c{cell}')
row = len(tetris.next_shape)
col = len(tetris.next_shape[0])
board = Grid(col, row, *cells)
return board, 0.1
screen tetris_screen(tetris):
add Solid('#FFF8', xysize=((tetris.width+2)*30, (tetris.height+2)*30)) align (0.5, 0.5)
add DynamicDisplayable(tetris_board, tetris) align (0.5, 0.5)
vbox:
pos (1600, 400)
spacing 50
text '当前分数:[tetris.score]'
text '下一个:'
add DynamicDisplayable(tetris_next_shape, tetris)
key 'K_LEFT' action Function(tetris.move, -1)
key 'K_RIGHT' action Function(tetris.move, 1)
key 'K_SPACE' action Function(tetris.rotate_shape)
key 'K_DOWN' action Function(tetris.drop)
if not tetris.gameover:
timer 0.5 action Function(tetris.drop) repeat True
else:
frame:
modal True
align (0.5, 0.5)
xysize (400, 300)
vbox:
align (0.5, 0.5)
text 'you lose' xalign 0.5
null height 100
hbox:
xalign 0.5
textbutton '重新开始' action Function(tetris.reset_game)
textbutton '退出游戏' action Return()
label start:
call screen tetris_screen(tetris)
然后就可以玩了
用键盘的左右方向键控制水平方向的移动,按下键可以加速方块下落(不是长按,是连按),点击空格可以旋转方块
这里暂时就先放代码,我之后会出一期视频教程发布在B站上,发布之后会在这里更新链接
|
评分
-
查看全部评分
|