I want to make something that works with python! I thought, " Introductory course on game development made with Python " ( Practice ).
Why python's tkinter → My ultimate goal is not game development, but data collection such as scraping, data analysis, and operational efficiency. Therefore, C ++ or Unity suitable for game development? Create a game with python instead. For the same reason, I don't use the pygame library.
Even if I study scraping, data analysis, and machine learning pinpointly, I can't think of any application methods at the moment, so it's a detour, but I have the soul to learn programming while creating games. I'm eager to build NCP by incorporating machine learning and deep learning and gaining practical experience in that area.
Since I was able to learn to some extent, I tried to make something like a mysterious dungeon game by referring to the sample code (or rather remodeling).
Many people think of the trials of the wind and the torneko, but when I think of a mysterious dungeon, I think of the mysterious dungeon of Chocobo. (Is it Terry's Wonderland?) In the end, I want to make something similar to a chocobo.
For the time being, github .
The character chip was borrowed from Pipoya Warehouse .
I divided it into maze_maker.py, which automatically generates a map, and tkmaze.py, which is the game itself.
maze_maker.py
import random
class maze_maker:
"""
Automatically generate dungeons
"""
def __init__(self,MAZE_W,MAZE_H):
self.MAZE_W = MAZE_W
self.MAZE_H = MAZE_H
self.maze = [[0]*self.MAZE_W for y in range(self.MAZE_H)]
self.DUNGEON_W = MAZE_W*3
self.DUNGEON_H = MAZE_H*3
self.dungeon = [[0]*self.DUNGEON_W for y in range(self.DUNGEON_H)]
def make_maze(self):
"""
Make a maze
"""
XP = [ 0, 1, 0,-1]
YP = [-1, 0, 1, 0]
#Surrounding pillars
for x in range(self.MAZE_W):
self.maze[0][x] = 1
self.maze[self.MAZE_H-1][x] = 1
for y in range(self.MAZE_H):
self.maze[y][0] = 1
self.maze[y][self.MAZE_W-1] = 1
#Empty inside
for y in range(1,self.MAZE_H-1):
for x in range(1,self.MAZE_W-1):
self.maze[y][x] = 0
#Pillar
for y in range(2,self.MAZE_H-2,2):
for x in range(2,self.MAZE_W-2,2):
self.maze[y][x] = 1
for y in range(2,self.MAZE_H-2,2):
for x in range(2,self.MAZE_W-2,2):
d = random.randint(0,3)
if x > 2:
d = random.randint(0,2)
self.maze[y+YP[d]][x+XP[d]] = 1
def make_dungeon(self):
"""
Make a dungeon from the maze
"""
self.make_maze()
for y in range(self.DUNGEON_H):
for x in range(self.DUNGEON_W):
self.dungeon[y][x] = 9
for y in range(1,self.MAZE_H-1):
for x in range(1,self.MAZE_W-1):
dx = x*3+1
dy = y*3+1
if self.maze[y][x] == 0:
if random.randint(0,99) < 20:
for ry in range(-1,2):
for rx in range(-1,2):
self.dungeon[dy+ry][dx+rx] = 0
else:
self.dungeon[dy][dx] = 0
if self.maze[y-1][x] == 0:
self.dungeon[dy-1][dx] = 0
if self.maze[y+1][x] == 0:
self.dungeon[dy+1][dx] = 0
if self.maze[y][x-1] == 0:
self.dungeon[dy][dx-1] = 0
if self.maze[y][x+1] == 0:
self.dungeon[dy][dx+1] = 0
def put_event(self):
while True:
x = random.randint(3,self.DUNGEON_W-4)
y = random.randint(3,self.DUNGEON_H-4)
if(self.dungeon[y][x] == 0):
for ry in range(-1,2):
for rx in range(-1,2):
self.dungeon[y+ry][x+rx] = 0
self.dungeon[y][x] = 1
break
for i in range(60):
x = random.randint(3,self.DUNGEON_W-4)
y = random.randint(3,self.DUNGEON_H-4)
if(self.dungeon[y][x] == 0):
self.dungeon[y][x] = random.choice([2,3,3,3,4])
tkmaze.py
"""
Search for dark soil in the dark soil. It's a never-ending journey. There is no goal, and I just go down the stairs while avoiding the enemy.
Score count for each step. Plus when you go down the stairs. Aim for a high score!
"""
import tkinter
import maze_maker
from PIL import Image,ImageTk
import random
#Key input
key = ''
koff = False
def key_down(e):
global key,koff
key = e.keysym
koff = False
def key_up(e):
global koff
koff = True
CHIP_SIZE = 32
DIR_UP = 3
DIR_DOWN = 0
DIR_LEFT = 1
DIR_RIGHT = 2
chara_x = chara_y = 146
chara_d = chara_a = 0
obj_a = 0
emy_num = 4
emy_list_x = [0]*emy_num
emy_list_y = [0]*emy_num
emy_list_d = [0]*emy_num
emy_list_a = [0]*emy_num
ANIMATION = [1,0,1,2]
#The material is "Pipoya http://blog.pipoya.net/From
imgplayer_pass = 'image/charachip01.png'
emy_img_pass = 'image/pipo-charachip019.png'
emy2_img_pass = 'image/hone.png'
emy3_img_pass = 'image/majo.png'
emy3_kageimg_pass = 'image/majo_kage.png'
takara_img_pass = 'image/pipoya_mcset1_obj01.png'
obj_pass = 'image/pipoya_mcset1_obj02.png'
obj2_pass = 'image/pipo-hikarimono005.png'
yuka_pass = 'image/pipoya_mcset1_at_gravel1.png'
kebe_pass = 'image/pipoya_mcset1_bridge01.png'
map_data = maze_maker.maze_maker(11,7)
map_data.make_dungeon()
map_data.put_event()
tmr = 0
idx = 1
floor_count = 0
item_count = 0
pl_life=150
pl_stamina = 150
pl_damage = 0
def move_player():
global chara_x,chara_y,chara_a,chara_d,pl_stamina,pl_life
if key == 'Up':
chara_d = DIR_UP
check_wall()
if key == 'Down':
chara_d = DIR_DOWN
check_wall()
if key == 'Left':
chara_d = DIR_LEFT
check_wall()
if key == 'Right':
chara_d = DIR_RIGHT
check_wall()
check_event()
if tmr%4 == 0:
if pl_stamina > 0:
pl_stamina -= 1
else:
pl_life -= 1
if pl_life <= 0:
pl_life = 0
idx = 2
chara_a = chara_d*3 + ANIMATION[tmr%4]
def emy_set(emy_num):
while True:
x = random.randint(3,map_data.DUNGEON_W-4)
y = random.randint(3,map_data.DUNGEON_H-4)
if map_data.dungeon[y][x] == 0:
emy_list_x[emy_num] = x*CHIP_SIZE+(CHIP_SIZE//2)
emy_list_y[emy_num] = y*CHIP_SIZE+(CHIP_SIZE//2)
break
def draw_text(txt):
st_fnt = ('Times New Roman',60)
canvas.create_text(200,200,text=txt,font=st_fnt,fill='red',tag='SCREEN')
def damage_cal(pl_damage):
global pl_life,idx
if pl_life <= pl_damage:
pl_life = 0
idx = 2
else:
pl_life -= pl_damage
def move_emy(emy_num):
cy = int(emy_list_y[emy_num]//CHIP_SIZE)
cx = int(emy_list_x[emy_num]//CHIP_SIZE)
emy_list_d[emy_num] = random.randint(0,3)
if emy_list_d[emy_num] == DIR_UP:
if map_data.dungeon[cy-1][cx] != 9:
emy_list_y[emy_num] -= 32
if emy_list_d[emy_num] == DIR_DOWN:
if map_data.dungeon[cy+1][cx] != 9:
emy_list_y[emy_num] += 32
if emy_list_d[emy_num] == DIR_LEFT:
if map_data.dungeon[cy][cx-1] != 9:
emy_list_x[emy_num] -= 32
if emy_list_d[emy_num] == DIR_RIGHT:
if map_data.dungeon[cy][cx+1] != 9:
emy_list_x[emy_num] += 32
emy_list_a[emy_num] = emy_list_d[emy_num]*3 + ANIMATION[tmr%4]
if abs(emy_list_x[emy_num]-chara_x) <= 30 and abs(emy_list_y[emy_num]-chara_y) <= 30:
pl_damage = 10*random.choice([1,2,2,3,3])
damage_cal(pl_damage)
def obj_animation():
global obj_a
obj_a = ANIMATION[tmr%4]
def check_wall():
global chara_x,chara_y,chara_a,chara_d
cy = int(chara_y//CHIP_SIZE)
cx = int(chara_x//CHIP_SIZE)
if chara_d == DIR_UP:
if map_data.dungeon[cy-1][cx] != 9:
chara_y -= 32
if chara_d == DIR_DOWN:
if map_data.dungeon[cy+1][cx] != 9:
chara_y += 32
if chara_d == DIR_LEFT:
if map_data.dungeon[cy][cx-1] != 9:
chara_x -= 32
if chara_d == DIR_RIGHT:
if map_data.dungeon[cy][cx+1] != 9:
chara_x += 32
def check_event():
global chara_x,chara_y,chara_a,chara_d,idx,pl_damage
global floor_count,emy_count,item_count,pl_life,pl_stamina
cy = int(chara_y//CHIP_SIZE)
cx = int(chara_x//CHIP_SIZE)
if map_data.dungeon[cy][cx] == 1:
#Riding on the magic circle of warp
map_data.make_dungeon()
map_data.put_event()
emy_set(0)
emy_set(1)
emy_set(2)
floor_count += 1
chara_x = chara_y = 146
if map_data.dungeon[cy][cx] == 2:
#Riding the magic circle of traps
if item_count > 0:
item_count -= 1
map_data.dungeon[cy][cx] = 0
else:
pl_damage = 5*random.choice([1,2,2,3,4,3])
damage_cal(pl_damage)
map_data.dungeon[cy][cx] = 0
if map_data.dungeon[cy][cx] == 3:
#Contact the item
item_count += 1
map_data.dungeon[cy][cx] = 0
if map_data.dungeon[cy][cx] == 4:
#Contact with food
pl_stamina_recover = 5*random.choice([1,2,2,3,4,3])
if pl_stamina + pl_stamina_recover > 150:
pl_stamina = 150
else:
pl_stamina += pl_stamina_recover
map_data.dungeon[cy][cx] = 0
def split_chip(chip_pass,chip_img_x,chip_img_y):
'''
Divide multiple chips into one unit
'''
chip_list = []
for cy in range(0,chip_img_y,CHIP_SIZE):
for cx in range(0,chip_img_x,CHIP_SIZE):
chip_list.append(ImageTk.PhotoImage(Image.open(chip_pass).crop((cx,cy,cx+CHIP_SIZE,cy+CHIP_SIZE))))
return chip_list
def draw_screen():
st_fnt = ('Times New Roman',30)
canvas.delete('SCREEN')
for my in range(len(map_data.dungeon)):
for mx in range(len(map_data.dungeon[0])):
if map_data.dungeon[my][mx] != 9:
canvas.create_image(mx*CHIP_SIZE+(CHIP_SIZE//2),my*CHIP_SIZE+(CHIP_SIZE//2),image=yuka_img[8],tag='SCREEN')
if map_data.dungeon[my][mx] == 1:
canvas.create_image(mx*CHIP_SIZE+(CHIP_SIZE//2),my*CHIP_SIZE+(CHIP_SIZE//2),image=obj2_img[obj_a],tag='SCREEN')
if map_data.dungeon[my][mx] == 2:
canvas.create_image(mx*CHIP_SIZE+(CHIP_SIZE//2),my*CHIP_SIZE+(CHIP_SIZE//2),image=obj2_img[6+obj_a],tag='SCREEN')
if map_data.dungeon[my][mx] == 3:
canvas.create_image(mx*CHIP_SIZE+(CHIP_SIZE//2),my*CHIP_SIZE+(CHIP_SIZE//2),image=takara_img[5],tag='SCREEN')
if map_data.dungeon[my][mx] == 4:
canvas.create_image(mx*CHIP_SIZE+(CHIP_SIZE//2),my*CHIP_SIZE+(CHIP_SIZE//2),image=obj_img[25],tag='SCREEN')
if map_data.dungeon[my][mx] == 9:
canvas.create_image(mx*CHIP_SIZE+(CHIP_SIZE//2),my*CHIP_SIZE+(CHIP_SIZE//2),image=kabe_img[28],tag='SCREEN')
canvas.create_image(chara_x,chara_y,image=imgplayer[chara_a],tag='SCREEN')
canvas.create_image(emy_list_x[0],emy_list_y[0],image=emy_img[emy_list_a[0]],tag='SCREEN')
canvas.create_image(emy_list_x[1],emy_list_y[1],image=emy2_img[emy_list_a[1]],tag='SCREEN')
canvas.create_image(emy_list_x[2],emy_list_y[2],image=emy3_img[emy_list_a[2]],tag='SCREEN')
canvas.create_image(emy_list_x[2],emy_list_y[2],image=emy3_kageimg[emy_list_a[2]],tag='SCREEN')
canvas.create_text(1110,50,text='{}Floor'.format(floor_count),font=st_fnt,fill='black',tag='SCREEN')
canvas.create_text(1110,100,text='{}Pieces'.format(item_count),font=st_fnt,fill='black',tag='SCREEN')
canvas.create_rectangle(1060,135,1210,160,fill='black',tag='SCREEN')
canvas.create_rectangle(1060,135,1060+pl_life,160,fill='limegreen',tag='SCREEN')
canvas.create_text(1130,148,text='LIFE',font=('Times New Roman',15),fill='white',tag='SCREEN')
canvas.create_rectangle(1060,165,1210,190,fill='black',tag='SCREEN')
canvas.create_rectangle(1060,165,1060+pl_stamina,190,fill='blue',tag='SCREEN')
canvas.create_text(1130,178,text='STAMINA',font=('Times New Roman',15),fill='white',tag='SCREEN')
canvas.create_text(1155,210,text='{}Was damaged!'.format(pl_damage),font=('Times New Roman',15),fill='black',tag='SCREEN')
def main():
global tmr,koff,key,idx
tmr += 1
draw_screen()
if idx == 1:
if tmr == 1:
for emy in range(0,emy_num):
emy_set(emy)
move_player()
obj_animation()
if tmr%2 == 0:
for emy in range(0,emy_num):
move_emy(emy)
if pl_life == 0:
idx = 2
if idx == 2:
draw_text('You Died')
if tmr == 20:
idx = 1
print('hiu')
if koff == True:
key = ''
koff = False
root.after(130,main)
root = tkinter.Tk()
root.title('Explore the dark soil with a maid!')
root.bind('<KeyPress>',key_down)
root.bind('<KeyRelease>',key_up)
canvas = tkinter.Canvas(width=1256,height=864)
imgplayer = split_chip(imgplayer_pass,96,128)
emy_img = split_chip(emy_img_pass,96,128)
emy2_img = split_chip(emy2_img_pass,96,128)
emy3_img = split_chip(emy3_img_pass,96,128)
emy3_kageimg = split_chip(emy3_kageimg_pass,96,128)
takara_img = split_chip(takara_img_pass,256,64)
obj_img = split_chip(obj_pass,256,224)
obj2_img = split_chip(obj2_pass,96,128)
yuka_img = split_chip(yuka_pass,64,160)
kabe_img = split_chip(kebe_pass,256,192)
canvas.pack()
main()
root.mainloop()
Play screen. p>
It's not interesting at all, but the basic processing required for the dungeon game is reasonable, such as map generation, player changing direction while stepping on it, warp zone animation, placement / movement of enemy characters, damage calculation, etc. Did you have it? I think. By the way, the attack on the enemy has not been implemented yet (sweat)
I feel that the code has not been organized yet, so I would like to improve it little by little. p>
A function that decomposes character chips by specifying the number of pixels. I tried my best while collecting various information.