I made a puzzle game (like) with Tkinter in Python

I am a beginner with several months of programming experience. I wanted to make a game, so I made a falling block puzzle that seems to have a relatively low threshold. This is Qiita's first post.

It's a game like this (gif 30 seconds, long) ezgif-3-3eee2fbd7703.gif

The explanation is commented on the code. (It seems that there are many mistakes)

panepon.py


import tkinter
import random
import math

phase = 0           #Variables for managing game progress
cursor_x = 2        #X coordinate of cursor(initial)
cursor_y = 11       #Cursor y coordinate(initial)
cursor_dx = 1       #Cursor movement x
cursor_dy = 1       #Cursor movement amount y
block_width = 64    #Block width
block_height = 64   #Block height

def right(e):                       #Processing when the right key is pressed
    global cursor_x, cursor_dx      #Global declaration to rewrite global variables
    cursor_x += cursor_dx
    if cursor_x > 4:                #Processing to prevent the cursor from going to the right of the game frame
        cursor_x = 4

def left(e):                        #Processing when the left key is pressed
    global cursor_x, cursor_dx
    cursor_x -= cursor_dx
    if cursor_x < 0:                #Processing to prevent the cursor from going to the left of the game frame
        cursor_x = 0

def up(e):                          #Processing when the up key is pressed
    global cursor_y, cursor_dy
    cursor_y -= cursor_dy
    if cursor_y < 0:                #Processing to prevent the cursor from going above the game frame
        cursor_y = 0

def down(e):                        #Processing when the down key is pressed
    global cursor_y, cursor_dy
    cursor_y += cursor_dy
    if cursor_y > 11:               #Processing to prevent the cursor from going below the game frame
        cursor_y = 11

def press_a(e):                     #Processing when the A key is pressed
    global a                        #Definition of global variable a
    a = 1                           #Manage that A key is pressed

def press_c(e):                     #Processing when the C key is pressed
    global c
    c = 1

def press_r(e):                     #Processing when the R key is pressed
    global r
    r = 1

block = []  #Array that manages the placement of blocks
check = []  #Array for checking

for i in range(17):
    block.append([0,0,0,0,0,0])
    check.append([0,0,0,0,0,0])

def draw_block():                   #Function for drawing blocks
    cvs.delete("BLOCK")             #Delete the block that was drawn until now
    for y in range(17):
        for x in range(6):
            if block[y][x] > 0:     #If the block exists
                cvs.create_image(x * block_width + 35, y * block_height - block_height * 4 - 35, image=img_block[block[y][x]], tag="BLOCK")
                                    #Drawing of block image Array for block image

def check_block():                  #Function to check blocks
    for y in range(17):
        for x in range(6):
            check[y][x] = block[y][x]  #Assign the current block layout to the check array

    for y in range(1,16):
        for x in range(6):
            if check[y][x] > 0:      #If the block exists
                if check[y-1][x] == check[y][x] and check[y+1][x] == check[y][x]:  #When blocks of the same color are lined up vertically in three or more rows
                    if check[y][x] == 1:  #If the blocks lined up are red, turn them into hearts
                        block[y-1][x] = 6
                        block[y][x] = 6
                        block[y+1][x] = 6
                    if check[y][x] == 2:  #If the blocks lined up are blue, turn them into dolphins
                        block[y-1][x] = 7
                        block[y][x] = 7
                        block[y+1][x] = 7
                    if check[y][x] == 3:  #If the blocks lined up are green, change to clover
                        block[y-1][x] = 8
                        block[y][x] = 8
                        block[y+1][x] = 8
                    if check[y][x] == 4:  #If the blocks lined up are yellow, change to beer
                        block[y-1][x] = 9
                        block[y][x] = 9
                        block[y+1][x] = 9
                    if check[y][x] == 5:  #If the blocks lined up are purple, change to wine
                        block[y-1][x] = 10
                        block[y][x] = 10
                        block[y+1][x] = 10
                        

    for y in range(17):
        for x in range(1,5):
            if check[y][x] > 0:
                if check[y][x-1] == check[y][x] and check[y][x+1] == check[y][x]:  #When blocks of the same color are lined up side by side in three or more rows
                    if check[y][x] == 1:
                        block[y][x-1] = 6
                        block[y][x] = 6
                        block[y][x+1] = 6
                    if check[y][x] == 2:
                        block[y][x-1] = 7
                        block[y][x] = 7
                        block[y][x+1] = 7
                    if check[y][x] == 3:
                        block[y][x-1] = 8
                        block[y][x] = 8
                        block[y][x+1] = 8
                    if check[y][x] == 4:
                        block[y][x-1] = 9
                        block[y][x] = 9
                        block[y][x+1] = 9
                    if check[y][x] == 5:
                        block[y][x-1] = 10
                        block[y][x] = 10
                        block[y][x+1] = 10
    

def sweep_block():                  #Function to erase blocks
    num = 0                         #Counting the number of disappeared blocks
    for y in range(17):
        for x in range(6):
            if block[y][x] == 6:
                block[y][x] = 0
                num += 1
            if block[y][x] == 7:
                block[y][x] = 0
                num += 1
            if block[y][x] == 8:
                block[y][x] = 0
                num += 1
            if block[y][x] == 9:
                block[y][x] = 0
                num += 1
            if block[y][x] == 10:
                block[y][x] = 0
                num += 1
    return num                                          #Returns the number of disappeared blocks to the caller

def drop_block():                                       #Function to drop a block
    flg = False                                         #Check for phase transition
    for y in range(15, -1, -1):                         #Examine y from the second row from the bottom
        for x in range(6):
            if block[y][x] != 0 and block[y+1][x] == 0: #If there is a block in the place you are checking and there is no block one square below
                block[y+1][x] = block[y][x]             #Copy the block below
                block[y][x] = 0                         #Erase the original block
                flg = True
    return flg                                          #Return flg to the caller

def over_block():           #Function for game over processing
    for x in range(6):
        if block[5][x] > 0: #When the block is at the top of the game frame
            return True
    return False

def set_up():                               #A function that moves a block up one step
    for y in range(5, 16):
        for x in range(6):
            block[y][x] = block[y + 1][x]

def set_block():                            #Function that puts the block at the bottom
    for x in range(6):
        block[16][x] = random.randint(1, 5) #At the bottom, 1 of the block image array~5 randomly placed

def ojama_block(ojama_num):                     #A function that randomly arranges blocks in the upper row
    for y in range(0, ojama_num):
        for x in range(6):
            block[y][x] = random.randint(1, 5)

def cross_block():                                                          #Function to swap left and right in the cursor
    if c == 1:                                                              #When the C key is pressed
        source = block[cursor_y + 5][cursor_x]                              #Assign the block on the left side of the cursor to the variable source
        block[cursor_y + 5][cursor_x] = block[cursor_y + 5][cursor_x + 1]   #Make the block on the left side of the cursor the same as the block on the right side
        block[cursor_y + 5][cursor_x + 1] = source                          #Make the block on the right side of the cursor the same as the source

def draw_text(text, x, y, size, col, tag):                         #Function to display text
    font = ("Times New Roman", size, "bold")                       #Enter the font, font size, and font weight first.
    cvs.create_text(x, y, text=text, fill=col, font=font, tag=tag) #Display text Based on the coordinates to display the text and the information brought in as an argument

def game_main():                #Main processing
    global phase, a, c, r, score, combo, ojama_num, over, force, cursor_x, cursor_y
    if phase == 0:              #When phase is early(title screen)
        cvs.delete("OVER")      #Delete process for restart from here
        cvs.delete("CHARA")
        cvs.delete("RESTART")
        for y in range(17):
            for x in range(6):
                block[y][x] = 0
                draw_block()    #Delete process for restart up to here
        draw_text("Panel ◯", 384, 334, 100,"violet","TITLE") #Drawing text
        draw_text(
        """
With the A key
Game
Let's get started!
        
        """, 425, 590, 25, "blue", "TITLE")
        cvs.create_image(576, 650, image=chara, tag="CHARA")
        phase = 1       #Move to phase 1
        score = 0       #Numerical value for score display
        combo = 1       #Variables for managing the number of combos
        ojama_num = 0   #Numerical value for dropping blocks from above
        force = 1       #Numerical value for dropping blocks from above
        over = 0        #Variables for game over management
        a = 0           #A key is not pressed
        c = 0
        r = 0
    elif phase == 1:                 #When phase is 1
        if a == 1:                   #When you press the A key
            for y in range(15):
                for x in range(6):
                    block[y][x] = 0
                    a = 0               #Return to the state where the A key is not pressed
                    draw_block()        #Drawing blocks
                    cvs.delete("TITLE") #title(text)Delete
                    draw_text("Game description", 576, 30, 40, "blue", "READ")
                    draw_text("↑ ↓ ← → The cursor moves with the key!", 576, 130, 20, "blue", "READ")
                    draw_text("Use the A key to put out a block at the bottom!", 576, 180, 20, "blue", "READ")
                    draw_text("Swap left and right with the C key!", 576, 230, 20, "blue", "READ")
                    draw_text("It will disappear if 3 or more are lined up vertically or horizontally!", 576, 280, 20, "blue", "READ")
                    draw_text("If you erase it a certain number of times, blocks will fall from above!", 576, 330, 20, "blue", "READ")
                    draw_text("Don't do it when the block reaches the top!", 576, 380, 20, "blue", "READ")
                    phase = 2
    elif phase == 2:
        if c == 1:
            cross_block()
            c = 0
        if drop_block() == False:  #If flg is False
            phase = 3
        draw_block()
    elif phase == 3:
        check_block()
        draw_block()
        phase = 4
    elif phase == 4:
        sc = sweep_block()  #Substitute the number num where the block disappeared into sc
        if sc > 9:        #Manage the amount of increase in score sc according to the number disappeared from here
            sc += 100
        elif sc > 8:
            sc += 50
        elif sc > 7:
            sc += 30
        elif sc > 6:
            sc += 15
        elif sc > 5:
            sc += 7
        elif sc > 4:
            sc += 3
        elif sc > 3:
            sc += 1                 #Manage the increase in score sc according to the number of disappeared
        sc *= combo ** 4            #Multiply the 4th power of the combo amount by the increase amount sc of the score
        score += sc                 #Add the amount of increase to the score
        if sc > 0:                  #If the block has been erased
            combo += 1              #Add 1 combo
            if combo > 2:
                cvs.delete("COMBO") #Deleted the combo display that was displayed until now
                draw_text(str(combo - 1)+"chain!", 480, 550, 50, "blue", "COMBO")
                                    #Text to display the number of combos
            ojama_num += 0.4        #The amount of blocks dropped from above is 0.4 increase
            force += 0.05           #Every time I erase a block, ojama_The number to be multiplied by num increases
            phase = 2
        else:
            if over_block() == False:
                phase = 5
            else:
                over = 1            #To game over processing
        draw_block()
    elif phase == 5:
        combo = 1                   #Restore the number of combos
        cvs.delete("COMBO")         #Turn off the combo number display
        if ojama_num >= 1:          #ojama_When num is 1 or more
            ojama_num = math.floor(ojama_num * (force))  #ojama_Multiply num by force and truncate a decimal
            ojama_block(ojama_num)  #ojama_Same number as the number of num(Column), Set the block on
            ojama_num = 0
        if c == 1:
            cross_block()
            c = 0
            phase = 2
        if a == 1:
            a = 0
            set_up()
            set_block()
            score += 10
            phase = 2
    cvs.delete("INFO")  #Turn off the score display
    if phase > 1:
        draw_text("SCORE", 576, 450, 40, "black", "INFO")
        draw_text(score * 10, 576, 490, 40, "black", "INFO") #Display the score
    draw_block()
    if over == 1:           #Game over processing
        cvs.delete("CHARA")                                    #Erase the character you were drawing
        cvs.create_image(576, 650, image=chara2, tag="CHARA")  #Change the character image to another
        draw_text("GAME OVER", 384, 384, 100, "black", "OVER")
        cvs.delete("READ")  #Erase the rule description
        cvs.delete("COMBO") #Turn off the combo display
        draw_text(
        """
With R key
In the title
I'll be back...
        
        """, 425, 590, 25, "blue", "RESTART")
        if r == 1:
            phase = 0
    cvs.delete("CURSOR")  #Erase the cursor image
    cvs.create_image(cursor_x * block_width + 67, cursor_y * block_height + 29, image=cursor, tag="CURSOR")
                          #Draw a cursor image
    root.after(100,game_main)  #0.1 second later game_Call the main function

root = tkinter.Tk()          #Make a window
root.title("Panel ◯")         #Title setting
root.resizable(False,False)  #Prevents window resizing
root.bind("<Right>",right)   #The right function is called when the Right key is pressed.
root.bind("<Left>",left)
root.bind("<Up>",up)
root.bind("<Down>",down)
root.bind("<a>",press_a)
root.bind("<c>",press_c)
root.bind("<r>",press_r)
cvs = tkinter.Canvas(root,width=768, height=768)  #Make the canvas size 768x768 pixels
cvs.pack()                                        #Place the canvas

bg = tkinter.PhotoImage(file="bg.png ")  #Substitute image for bg

img_block = [
  None,
  tkinter.PhotoImage(file="red.png "),
  tkinter.PhotoImage(file="blue.png "),
  tkinter.PhotoImage(file="green.png "),
  tkinter.PhotoImage(file="yellow.png "),
  tkinter.PhotoImage(file="purple.png "),
  tkinter.PhotoImage(file="heart.png "),
  tkinter.PhotoImage(file="dolphin.png "),
  tkinter.PhotoImage(file="clover.png "),
  tkinter.PhotoImage(file="ale.png "),
  tkinter.PhotoImage(file="wine.png ")
]   #Array for block images

cursor = tkinter.PhotoImage(file="cursor.png ")
chara = tkinter.PhotoImage(file="chara.png ")
chara2 = tkinter.PhotoImage(file="chara2.png ")
cvs.create_image(384,384,image=bg)
game_main()
root.mainloop()  #Show GUI

Looking at it like this, there are many magic numbers. I want to be careful

I want to make an RPG next time. (I studied a little, but it's really difficult.)

Recommended Posts

I made a puzzle game (like) with Tkinter in Python
I made a simple typing game with tkinter in Python
I made a roguelike game with Python
[Python] I made a Youtube Downloader with Tkinter.
I made a bin picking game with Python
I made a Christmas tree lighting game with Python
I made a fortune with Python.
I made a daemon with Python
I made a payroll program in Python!
I made a character counter with Python
I made a Hex map with Python
I made a life game with Numpy
I made a simple blackjack with Python
I made a configuration file with Python
I made a neuron simulator with Python
Life game with Python [I made it] (on the terminal & Tkinter)
〇✕ I made a game
I made a poker game server chat-holdem using websocket with python
I made a weather forecast bot-like with Python.
I made a GUI application with Python + PyQt5
I tried playing a typing game in Python
I made a Twitter fujoshi blocker with Python ①
I want to make a game with Python
I made a Caesar cryptographic program in Python.
I made a Mattermost bot with Python (+ Flask)
I made blackjack with python!
I made a python text
I made blackjack with Python.
I made wordcloud with Python.
I made a Twitter BOT with GAE (python) (with a reference)
I made a prime number generation program in Python
I made a vim learning game "PacVim" with Go
I made a window for Log output with Tkinter
I made a net news notification app with Python
I made a Python3 environment on Ubuntu with direnv.
I want to work with a robot in python.
I made a LINE BOT with Python and Heroku
I made a prime number generation program in Python 2
I made a falling block game with Sense HAT
I made a Line-bot using Python!
I made a package to filter time series with python
Numer0n with items made in Python
I made a quick feed reader using feedparser in Python
I made a simple book application with python + Flask ~ Introduction ~
I made a Numer0n battle game in Java (I also made AI)
Othello game development made with Python
Zura made like a life game
I tried to make a stopwatch using tkinter in python
I tried a stochastic simulation of a bingo game with Python
I made a class to get the analysis result by MeCab in ndarray with python
I made a program to collect images in tweets that I liked on twitter with Python
I wrote a doctest in "I tried to simulate the probability of a bingo game with Python"
I made a library to easily read config files with Python
I made a package that can compare morphological analyzers with Python
Difference in behavior of transparent Frame made with tkinter in pyinstaller [Python]
I made a lot of files for RDP connection with Python
[Python] I made an image viewer with a simple sorting function.
I tried to implement a misunderstood prisoner's dilemma game in Python
I made a shuffle that can be reset (reverted) with Python
I made a segment tree with python, so I will introduce it
I made a program that automatically calculates the zodiac with tkinter