如何阻止Pygame中.blit()像素跨屏环绕及地形交互实现
问题解决方案
一、修复滚动与地形生成问题
原代码的滚动逻辑是直接复制屏幕内容偏移,导致旧地形在屏幕另一侧重复出现。正确的做法是维护独立的地形数据,只绘制当前可见区域的地形:
- 用列表存储所有地形列的Y坐标(每列宽度16px,和方块尺寸一致)
- 滚动时不直接操作屏幕,而是调整偏移量
scroll_offset_x - 当偏移量超过一个方块宽度时,移除最左侧的旧地形,生成新的右侧地形,同时重置偏移量
二、玩家碰撞检测方案
不推荐用像素颜色检测(效率低、易出错),直接维护地形数据列表更可靠:
- 记录玩家的坐标(
player_x,player_y) - 移动时计算玩家即将进入的位置对应的地形列,检查该列的地形Y坐标是否和玩家位置重叠
- 如果重叠则阻止移动,否则允许移动
修改后的完整代码
import pygame as py import random as r py.init() # 基础设置 SCREEN_WIDTH = 512 SCREEN_HEIGHT = 512 BLOCK_SIZE = 16 FPS = 4 # 和原代码0.25秒间隔对应 # 地形与滚动相关 terrain_columns = [] scroll_offset_x = 0 # 初始化屏幕可见的所有地形列(32列,512/16=32) for _ in range(SCREEN_WIDTH // BLOCK_SIZE): terrain_columns.append(r.randint(0, 15)) # 玩家设置 player_x = BLOCK_SIZE * 5 # 初始在屏幕左侧 player_y = BLOCK_SIZE * 8 player_size = BLOCK_SIZE # 用16px方块代表玩家,方便检测 screen = py.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) clock = py.time.Clock() def generate_new_terrain(): # 生成新地形列,延续之前的趋势避免突变 last_y = terrain_columns[-1] change = round(r.randint(0,5) ** (1/4)) if r.randint(0,1) == 0: change = -change new_y = last_y + change new_y = max(0, min(15, new_y)) # 限制在0-15之间 return new_y running = True while running: clock.tick(FPS) screen.fill((175, 215, 225)) # 处理事件 for event in py.event.get(): if event.type == py.QUIT: running = False # 玩家移动控制 if event.type == py.KEYDOWN: if event.key == py.K_LEFT: target_x = player_x - BLOCK_SIZE col_idx = (target_x // BLOCK_SIZE) - (scroll_offset_x // BLOCK_SIZE) if col_idx >= 0: terrain_y = terrain_columns[col_idx] * BLOCK_SIZE if not (player_y + player_size > terrain_y and player_y < terrain_y + BLOCK_SIZE): player_x = target_x if event.key == py.K_RIGHT: target_x = player_x + BLOCK_SIZE col_idx = (target_x // BLOCK_SIZE) - (scroll_offset_x // BLOCK_SIZE) if col_idx < len(terrain_columns): terrain_y = terrain_columns[col_idx] * BLOCK_SIZE if not (player_y + player_size > terrain_y and player_y < terrain_y + BLOCK_SIZE): player_x = target_x if event.key == py.K_UP: target_y = player_y - BLOCK_SIZE if target_y >= 0: player_y = target_y if event.key == py.K_DOWN: target_y = player_y + BLOCK_SIZE col_idx = (player_x // BLOCK_SIZE) - (scroll_offset_x // BLOCK_SIZE) terrain_y = terrain_columns[col_idx] * BLOCK_SIZE if target_y + player_size <= SCREEN_HEIGHT and not (target_y + player_size > terrain_y and target_y < terrain_y + BLOCK_SIZE): player_y = target_y # 自动向右滚动 scroll_offset_x += BLOCK_SIZE # 偏移量超过方块宽度时更新地形列表 if scroll_offset_x >= BLOCK_SIZE: scroll_offset_x -= BLOCK_SIZE terrain_columns.pop(0) terrain_columns.append(generate_new_terrain()) # 绘制所有可见地形 for idx, y in enumerate(terrain_columns): block_x = idx * BLOCK_SIZE - scroll_offset_x block_y = y * BLOCK_SIZE py.draw.rect(screen, (0, 100, 20), py.Rect(block_x, block_y, BLOCK_SIZE, BLOCK_SIZE)) # 绘制玩家 py.draw.rect(screen, (255, 0, 0), py.Rect(player_x, player_y, player_size, player_size)) py.display.flip() py.quit()
代码说明
- 地形维护:用
terrain_columns列表存储每列地形的Y坐标,滚动时只更新列表首尾,保证地形无限延伸且不重复 - 滚动逻辑:通过
scroll_offset_x控制地形绘制偏移,每次滚动一个方块宽度后,移除旧列添加新列,实现无缝滚动 - 碰撞检测:移动玩家时计算目标位置对应的地形列,直接对比坐标判断是否重叠,高效准确
- 玩家控制:添加方向键控制,移动时检查地形阻挡,避免穿过地形
内容的提问来源于stack exchange,提问作者mn mnn
相关产品推荐
相关产品推荐

