AB键左右移动,T触摸键跳跃,地形生成有点慢要等一下
from mpython import *
import time
import random
TILE = 8
MAP_W = 16
MAP_H = 8
MAX_JUMP = 4
MIN_JUMP = 2
MAX_Y_DIFF = 3 # Y 方向最大落差限制
def generate_map():
while True:
new_map = [[0 for _ in range(MAP_W)] for _ in range(MAP_H)]
path = []
y = MAP_H - 4 # 起点行数
valid = True
for x in range(MAP_W):
y += random.choice([-1, 0, 1])
y = max(1, min(MAP_H - 2, y))
# 检查与前一个块的 Y 差值是否超过 MAX_Y_DIFF
if path:
_, prev_y = path[-1]
if abs(y - prev_y) > MAX_Y_DIFF:
valid = False
break
new_map[y][x] = 1
path.append((x, y))
if not valid:
continue
# 设置最底行全是地面
for x in range(MAP_W):
new_map[MAP_H - 1][x] = 1
# 设置目标位置
gx, gy = path[-1]
new_map[gy][gx] = 2
if gy + 1 < MAP_H:
new_map[gy + 1][gx] = 1
# 添加尖刺
candidates = [
(x, y)
for x in range(1, MAP_W - 1) # 遍历地图中所有方块,排除左右边界
for y in range(1, MAP_H - 2) # 排除顶部和底部
if new_map[y][x] == 0 and new_map[y + 1][x] == 1 and (x, y) not in path # 条件:该位置为空且下方是平台,且不在路径上
]
# 用一个集合来记录已放置尖刺的位置
used = set()
# 随机选择放置尖刺的位置,最多放置 10 个尖刺(或者候选位置的数量,取较小值)
while len(used) < min(4, len(candidates)): # 选择尖刺数量为候选位置数量与 10 的较小值
sx, sy = random.choice(candidates) # 从候选位置中随机选择一个
if (sx, sy) not in used: # 确保该位置未被放置过尖刺
new_map[sy][sx] = 3 # 设置该位置为尖刺
used.add((sx, sy)) # 将该位置添加到已使用的集合中,避免重复放置
return new_map, path
def find_spawn_point(game_map):
for y in range(MAP_H - 1):
for x in range(MAP_W):
if game_map[y][x] == 0 and game_map[y + 1][x] == 1:
return x, y
return 0, 0
def is_solid(x, y):
if 0 <= x < MAP_W and 0 <= y < MAP_H:
return game_map[y][x] == 1
return True
def is_goal(x, y):
if 0 <= x < MAP_W and 0 <= y < MAP_H:
return game_map[y][x] == 2
return False
def is_spike(x, y):
if 0 <= x < MAP_W and 0 <= y < MAP_H:
return game_map[y][x] == 3
return False
def can_jump(from_x, from_y, to_x, to_y):
distance = abs(to_x - from_x) + abs(to_y - from_y)
return MIN_JUMP <= distance <= MAX_JUMP and abs(to_y - from_y) <= MAX_Y_DIFF
def draw_map():
for y in range(MAP_H):
for x in range(MAP_W):
tile = game_map[y][x]
if tile == 1:
oled.fill_rect(x*TILE, y*TILE, TILE, TILE, 1)
elif tile == 2:
oled.rect(x*TILE, y*TILE, TILE, TILE, 1)
elif tile == 3:
# 绘制尖刺(三角形)
cx = x*TILE + TILE//2
cy = y*TILE
oled.pixel(cx, cy, 1)
oled.line(cx - 3, cy + 7, cx, cy, 1)
oled.line(cx + 3, cy + 7, cx, cy, 1)
def draw_player():
oled.fill_rect(player_x*TILE, player_y*TILE, TILE, TILE, 1)
def game_over():
oled.fill(0)
oled.text("GAME OVER", 26, 29)
oled.show()
time.sleep(2)
def next_level():
oled.fill(0)
oled.text("NEXT LEVEL", 23, 29)
oled.show()
time.sleep(1)
def is_level_solvable():
for i in range(1, len(path)):
x1, y1 = path[i-1]
x2, y2 = path[i]
if not can_jump(x1, y1, x2, y2):
return False
return True
# 主循环
while True:
while True:
game_map, path = generate_map()
if is_level_solvable():
break
player_x, player_y = find_spawn_point(game_map)
vel_y = 0
jumping = False
while True:
oled.fill(0)
if button_a.value() == 0 and not is_solid(player_x - 1, player_y):
player_x -= 1
time.sleep(0.1)
if button_b.value() == 0 and not is_solid(player_x + 1, player_y):
player_x += 1
time.sleep(0.1)
if touchPad_T.read() < 200 and not jumping:
vel_y = -3
jumping = True
if vel_y < 2:
vel_y += 1
if vel_y > 0:
for i in range(vel_y):
if is_solid(player_x, player_y + 1):
vel_y = 0
jumping = False
break
player_y += 1
elif vel_y < 0:
for i in range(-vel_y):
if is_solid(player_x, player_y - 1):
vel_y = 0
break
player_y -= 1
if is_spike(player_x, player_y):
game_over()
break
if is_goal(player_x, player_y):
next_level()
break
draw_map()
draw_player()
oled.show()
time.sleep(0.05)
评论