Search code examples
pythonfor-looptkinterminecraft

How to make variables and functions that are attached on every single widget in for-loop in python?


I want to create 2D minecraft test game. Got page with textures and so on... And then, I realized I need to create 25*25 map!

In this code below you will see, that I created 5 functions and 5 labels in for-loop and if you are good at this language you will see I created block breaking animation. I'm going to care about holding animation after(if you know how to create holding animation please let me know)...

Code you can test:

from tkinter import *
tk=Tk()
tk.title('Minecraft 2D')
tk.config(bg='lightblue')
tk.resizable(False, False)
app_width=1500
app_height=750
screen_width=tk.winfo_screenwidth()
screen_height=tk.winfo_screenheight()
x=(screen_width/2)-(app_width/2)
y=(screen_height/2)-(app_height/2)
tk.geometry(f'{app_width}x{app_height}+{int(x)}+{int(y)}')
DestroyCounter=0
for i in range(10, 15):
    def Destroy1():
        global DestroyCounter
        if DestroyCounter==0:
            DestroyCounter=1
            GrassBlockSprite.config(bg='gray30')
        elif DestroyCounter==1:
            DestroyCounter=2
            GrassBlockSprite.config(bg='gray26')
        elif DestroyCounter==2:
            DestroyCounter=3
            GrassBlockSprite.config(bg='gray22')
        elif DestroyCounter==3:
            DestroyCounter=4
            GrassBlockSprite.config(bg='gray18')
        elif DestroyCounter==4:
            DestroyCounter=5
            GrassBlockSprite.place_forget()
    GrassBlockSprite=Canvas(tk, width=48, height=48, bg='brown', bd=0)
    GrassBlockSprite.place(relx=((i+0.2)/31.5), rely=0.305)
    GrassBlockSprite.bind('<Button-1>', lambda e:Destroy1())
tk.mainloop()

    

There just last block accepts animation, not other ones. How to make this animation for other blocks? How to make variables and functions that will not overlap such as a loop in a thread? Do I need to create threads? But how to create them for every block in for loop? You can answer with just these 5 blocks in code. You can fix code too if you want.


Solution

  • Consider this as a replacement:

    animation = ['gray30','gray26','gray22','gray18']
    
    DestroyCounter=[]
    GrassBlockSprite=[]
    
    def Destroy(n):
        if DestroyCounter[n] < len(animation):
            GrassBlockSprite[n].config(bg=animation[DestroyCounter[n]])
        else:
            GrassBlockSprite[n].place_forget()
        DestroyCounter[n] += 1
    
    for i in range(5):
        gbs=Canvas(tk, width=48, height=48, bg='brown', bd=0)
        gbs.place(relx=((i+10.2)/31.5), rely=0.305)
        gbs.bind('<Button-1>', lambda e, i=i:Destroy(i))
        GrassBlockSprite.append(gbs)
        DestroyCounter.append(0)