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)
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