Собственно это даже не вопрос. Выкладываю скрипт примитивной игрушки которую сделал в выходные от безделья. Думаю это поможет тем кто хочет чутка разобраться в потоках и понять зачем они нужны. Также реализован механизм защиты для tkinter, так как tkinter является непотокобезопасным. Есть в скрипте и недочеты, например не правильно работает clear_display(), так как несколько потоков одновременно захватывают текст из поля и выводят его после обработки обратно. Если есть желание у кого разобраться как обойти этот момент, то добро пожаловать в тему.
import tkinter as tk
from tkinter import ttk
from tkinter import *
import time
from threading import Thread
from random import randint
x = 14
y = 1
bullet = False
alien = 'Ж'
alienX = 0
alienY = 0
score = 0
HP = 3
stop = False
speed = 0.4
exit_game = False
def clear_display():
text.delete(1.0, END)
def update_display(*arg):
"""создает один кадр изображения"""
display_1 = text.get(1.0, 1.28)
display_2 = text.get(2.0, 2.28)
display_3 = text.get(3.0, 3.28)
display_4 = text.get(4.0, 4.28)
display_5 = text.get(5.0, 5.28)
display_6 = text.get(6.0, 6.28)
display_7 = text.get(7.0, 7.28)
display_8 = text.get(8.0, 8.28)
display_9 = text.get(9.0, 9.28)
display_10 = text.get(10.0, 10.28)
display_11 = text.get(11.0, 11.28)
display_12 = text.get(12.0, 12.28)
display_13 = text.get(13.0, 13.28)
s, x, y = arg
display_1 = ' ' * 28
display_1 = display_1[:2] + 'Score: ' + str(score) + ' '*12
display_1 = display_1[:18] + 'HP: ' + str(HP)
if y == 2:
display_2 = ' ' * 28
display_2 = display_2[:x-1] + s + display_2[x+len(s):]
elif y == 3:
display_3 = ' ' * 28
display_3 = display_3[:x-1] + s + display_3[x+len(s):]
elif y == 4:
display_4 = ' ' * 28
display_4 = display_4[:x-1] + s + display_4[x+len(s):]
elif y == 5:
display_5 = ' ' * 28
display_5 = display_5[:x-1] + s + display_5[x+len(s):]
elif y == 6:
display_6 = ' ' * 28
display_6 = display_6[:x-1] + s + display_6[x+len(s):]
elif y == 7:
display_7 = ' ' * 28
display_7 = display_7[:x-1] + s + display_7[x+len(s):]
elif y == 8:
display_8 = ' ' * 28
display_8 = display_8[:x-1] + s + display_8[x+len(s):]
elif y == 9:
display_9 = ' ' * 28
display_9 = display_9[:x-1] + s + display_9[x+len(s):]
elif y == 10:
display_10 = ' ' * 28
display_10 = display_10[:x-1] + s + display_10[x+len(s):]
elif y == 11:
display_11 = ' ' * 28
display_11 = display_11[:x-1] + s + display_11[x+len(s):]
elif y == 12:
display_12 = ' ' * 28
display_12 = display_12[:x-1] + s + display_12[x+len(s):]
elif y == 13:
display_13 = ' ' * 28
display_13 = display_13[:x-2] + s + display_13[x+1:]
display = display_1 + '\n' +\
display_2 + '\n' +\
display_3 + '\n' +\
display_4 + '\n' +\
display_5 + '\n' +\
display_6 + '\n' +\
display_7 + '\n' +\
display_8 + '\n' +\
display_9 + '\n' +\
display_10 + '\n' +\
display_11 + '\n' +\
display_12 + '\n' +\
display_13
return display
def alien_ship():
global alien, alienX, alienY, HP, stop, speed, exit_game, root
alienX = randint(2, 27)
clear_display()
draw_display(('<0>',x, 13))
for i in range(2, 12):
if i < 11 and not stop:
alienY = i + 1
draw_display((alien, alienX, alienY),(' ', alienX, i))
#draw_display((alien, alienX, alienY))
time.sleep(speed)
if i == 11 and alien == 'Ж' and not stop:
alienY = i + 1
HP -= 1
draw_display(('@', alienX, alienY),(' ', alienX, i))
#draw_display(('@', alienX, alienY))
if HP == 0:
stop = True
if alien == '~' and not stop:
clear_display()
draw_display(('<0>',x, 13))
break
if not stop:
if speed > 0.002:
speed -= 0.002
else:
speed = 0.4
alien = 'Ж'
th = Thread(target=alien_ship)
th.start()
if stop and not exit_game:
clear_display()
draw_display(('GAME OVER', 10, 6))
if stop and exit_game:
root.destroy()
def move_left(event):
global x
if x != 2:
x -= 1
draw_display(('<0>', x, 13))
def move_right(event):
global x
if x != 27:
x += 1
draw_display(('<0>', x, 13))
def draw_display(*args):
for i in args:
obj, x , y = i
display = update_display(obj, x, y)
text.config(state='normal')
text.delete(0.0, END)
text.insert(0.0, display)
text.config(state='disabled')
def bullet_go():
global x, bullet, alien, alienX, alienY, score, stop, HP, speed
bullet = True
bullet_x = x
for i in range(1, 14):
if i == 1:
draw_display(('X', bullet_x, 12))
elif i > 1 and i < 12:
draw_display((' ', bullet_x, 14-i),('|', bullet_x, 13-i))
if alienX == bullet_x and alien == 'Ж' and (alienY == 13-i\
or alienY == 12-i):
alien = '~'
score += 1
elif i == 13:
draw_display(('*', bullet_x, 2))
time.sleep(0.02)
draw_display((' ', bullet_x, 2))
if stop:
stop = False
score = 0
HP = 3
speed = 0.4
th = Thread(target=alien_ship)
th.start()
time.sleep(0.02)
bullet = False
def bullet_run(event):
global bullet
if not bullet:
th = Thread(target=bullet_go)
th.start()
def on_closing():
global stop, exit_game
if stop:
root.destroy()
stop = True
exit_game = True
root = tk.Tk()
root.geometry("250x250+200+200")
text_frame = ttk.Frame(root, width=200, height=200)
text_frame.pack(anchor="nw")
text = tk.Text(text_frame, width=28, height=13)
text.pack(anchor="nw")
text.focus_set()
text.bind('<KeyPress-Left>', move_left)
text.bind('<KeyPress-Right>', move_right)
text.bind('<Escape>', bullet_run)
if __name__ == '__main__':
th = Thread(target=alien_ship)
th.start()
root.protocol("WM_DELETE_WINDOW", on_closing)
root.mainloop()