回到首页 返回首页
回到顶部 回到顶部
返回上一页 返回上一页

小游戏系列——简易跑酷游戏 简单

头像 dfrwh 2025.05.03 9 0

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)

评论

user-avatar