You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Tkinter Canvas.move()实现外星人移动时拖影问题的解决请求

解决Tkinter太空侵略者游戏外星人移动拖影问题

我用Python的Tkinter制作《太空侵略者》游戏时,遇到了外星人横向移动留下像素拖影的问题。玩家和激光用同样的Canvas.move()方法却没有这个问题,现在外星人移动逻辑还没完成,想先解决拖影,让外星人正常向右移动。我是编程新手,Tkinter和游戏开发经验不足,附上外星人相关代码恳请帮助。

外星人相关代码(不含玩家和激光部分)

from tkinter import * # Graphical user interface (GUI) module as part of standard library
import random
import time 

GAME_WIDTH = 1000
GAME_HEIGHT = 500
ALIEN_SPEED = 100
ALIEN_SIZE = 50
BACKGROUND_COLOUR = "black"

score = 0 #initial score
direction = "right" #initial direction
aliens = [] #global variable to create a row of aliens 

#initial set up 
window = Tk() #from tkinter to create the window
window.title("Alien Game")
label = Label(window, text = f"Score: {score}", font = ('consolas', 40))
label.pack()

canvas = Canvas(window, background= BACKGROUND_COLOUR, height= GAME_HEIGHT, width= GAME_WIDTH)
canvas.pack()



class Alien: #create individual alien body
    def __init__(self, x, y):
        self.x, self.y = x, y
        self.body = []
        self.face = canvas.create_rectangle(self.x, self.y, self.x+ALIEN_SIZE, self.y+ALIEN_SIZE, fill = 'yellow', outline='', width=0)
        self.eye1 = canvas.create_rectangle(self.x+0.2*ALIEN_SIZE, self.y+0.2*ALIEN_SIZE, self.x+0.4*ALIEN_SIZE, self.y+0.4*ALIEN_SIZE, fill = 'black', outline='', width=0)
        self.eye2 = canvas.create_rectangle(self.x+0.6*ALIEN_SIZE, self.y+0.2*ALIEN_SIZE, self.x+0.8*ALIEN_SIZE, self.y+0.4*ALIEN_SIZE, fill = 'black', outline='', width=0)
        self.mouth = canvas.create_rectangle(self.x+0.2*ALIEN_SIZE, self.y+0.8*ALIEN_SIZE, self.x+0.8*ALIEN_SIZE, self.y+ALIEN_SIZE, fill = 'black', outline='', width=0)
        self.body.extend((self.face, self.eye1, self.eye2, self.mouth))


def create_aliens(): # create multiple aliens in a row
    for i in range (int((GAME_WIDTH/(2*ALIEN_SIZE))*0.8)):
        aliens.append(Alien(x = i*2*ALIEN_SIZE, y = ALIEN_SIZE/2))
    return aliens

def move_aliens(): #move row of alien across screen
    global direction
    aliens = create_aliens()
    if direction == 'right':
        if aliens[-1].x <= (GAME_WIDTH-ALIEN_SIZE): # test if reached screen edge 
            for alien in aliens:
                for body_part in alien.body:
                    canvas.move(body_part, 10, 0)
                
        else:
            direction = 'left'
    elif direction == 'left':
        if aliens[0].x >= (0):
            for alien in aliens:
                canvas.move(alien.body, -5, 0)
                alien.x -=5
        else:
            direction = 'right'
    print (direction)
    window.after(ALIEN_SPEED, move_aliens)

#to centre the window on the screen (top left is position 0,0)
window.update()
x= int((window.winfo_screenwidth() - window.winfo_width())/2) #centre x position
y = int((window.winfo_screenheight() - window.winfo_height())/2) #centre y position
window.geometry(f'{window.winfo_width()}x{window.winfo_height()}+{x}+{y-30}') #format of (window width) x (window height) at + (position width) + (position height)

move_aliens()

window.mainloop()

问题截图

  • 初始状态:外星人初始状态
  • 移动后状态:外星人移动后拖影状态

问题根源与解决方法

问题出在哪?

每次调用move_aliens()时,你都执行了aliens = create_aliens(),这会重新创建一整排外星人,而之前的外星人并没有被删除。旧外星人留在画布上,新外星人跟着移动,就出现了拖影。另外,向右移动时没有更新外星人的self.x属性,导致判断边界的逻辑失效,外星人会一直往右跑。

修改步骤

  1. 只初始化一次外星人:在游戏启动时调用create_aliens(),不要在move_aliens()里重复创建
  2. 同步外星人坐标:每次移动后更新外星人的self.x,保证边界判断准确
  3. 修正移动逻辑:移除move_aliens()里的create_aliens()调用,直接使用全局的aliens列表

修改后的完整代码

from tkinter import *
import time 

GAME_WIDTH = 1000
GAME_HEIGHT = 500
ALIEN_SPEED = 100
ALIEN_SIZE = 50
BACKGROUND_COLOUR = "black"

score = 0
direction = "right"
aliens = [] 

window = Tk()
window.title("Alien Game")
label = Label(window, text = f"Score: {score}", font = ('consolas', 40))
label.pack()

canvas = Canvas(window, background= BACKGROUND_COLOUR, height= GAME_HEIGHT, width= GAME_WIDTH)
canvas.pack()

class Alien:
    def __init__(self, x, y):
        self.x, self.y = x, y
        self.body = []
        self.face = canvas.create_rectangle(self.x, self.y, self.x+ALIEN_SIZE, self.y+ALIEN_SIZE, fill = 'yellow', outline='', width=0)
        self.eye1 = canvas.create_rectangle(self.x+0.2*ALIEN_SIZE, self.y+0.2*ALIEN_SIZE, self.x+0.4*ALIEN_SIZE, self.y+0.4*ALIEN_SIZE, fill = 'black', outline='', width=0)
        self.eye2 = canvas.create_rectangle(self.x+0.6*ALIEN_SIZE, self.y+0.2*ALIEN_SIZE, self.x+0.8*ALIEN_SIZE, self.y+0.4*ALIEN_SIZE, fill = 'black', outline='', width=0)
        self.mouth = canvas.create_rectangle(self.x+0.2*ALIEN_SIZE, self.y+0.8*ALIEN_SIZE, self.x+0.8*ALIEN_SIZE, self.y+ALIEN_SIZE, fill = 'black', outline='', width=0)
        self.body.extend((self.face, self.eye1, self.eye2, self.mouth))


def create_aliens():
    for i in range (int((GAME_WIDTH/(2*ALIEN_SIZE))*0.8)):
        aliens.append(Alien(x = i*2*ALIEN_SIZE, y = ALIEN_SIZE/2))
    return aliens

def move_aliens():
    global direction
    # 移除重复创建外星人的代码
    if direction == 'right':
        # 用最后一个外星人的当前x判断边界
        if aliens[-1].x <= (GAME_WIDTH - ALIEN_SIZE - 10): # 减去移动步长,避免超出屏幕
            for alien in aliens:
                for body_part in alien.body:
                    canvas.move(body_part, 10, 0)
                alien.x += 10 # 更新外星人的x坐标
        else:
            direction = 'left'
    elif direction == 'left':
        if aliens[0].x >= 10: # 减去移动步长,避免超出屏幕
            for alien in aliens:
                for body_part in alien.body:
                    canvas.move(body_part, -10, 0)
                alien.x -= 10 # 更新外星人的x坐标
        else:
            direction = 'right'
    window.after(ALIEN_SPEED, move_aliens)

# 初始化窗口位置
window.update()
x= int((window.winfo_screenwidth() - window.winfo_width())/2)
y = int((window.winfo_screenheight() - window.winfo_height())/2)
window.geometry(f'{window.winfo_width()}x{window.winfo_height()}+{x}+{y-30}')

# 只创建一次外星人
create_aliens()
move_aliens()

window.mainloop()

关键修改点说明

  • 把create_aliens()的调用移到move_aliens()外面,游戏启动时只创建一次外星人
  • 向右移动时,每次移动后更新alien.x +=10,保证和Canvas元素的实际位置同步
  • 边界判断时减去移动步长,避免外星人刚好碰到边界时就转向,导致视觉上的卡顿
  • 左右移动的步长统一为10,让移动更平滑

内容的提问来源于stack exchange,提问作者Ben

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 14:02:04