ーー python (GUI 開発の基礎) ーー
python [ IDLE ] でリアルタイムに画像処理する手法。
Game開発などで使われる
今まで謎だったリアル画像の動的処理を Win10 上で行う試み
Game開発の基礎を学ぶ
pythonでRPG,ダンジョンGameを解析し構造を理解する。
##sinnki 2
import tkinter
import random
FNT = ("Times New Roman", 20, "bold")
key = ""
keyoff = False
idx = 0
tmr = 0
stage = 0
score = 0
bar_x = 0
bar_y = 540
ball_x = 0
ball_y = 0
ball_xp = 0
ball_yp = 0
is_clr = True
block = []
for i in range(5):
block.append([1]*10)
for i in range(10):
block.append([0]*10)
def key_down(e):
global key
key = e.keysym
def key_up(e):
global keyoff
keyoff = True
def draw_block():
global is_clr
is_clr = True
cvs.delete("BG")
for y in range(15):
for x in range(10):
gx = x*80
gy = y*40
if block[y][x] == 1:
cvs.create_rectangle(gx+1, gy+4, gx+79, gy+32, fill=block_color(x,y), width=0, tag="BG")
is_clr = False
cvs.create_text(200, 20, text="STAGE "+str(stage), fill="white", font=FNT, tag="BG")
cvs.create_text(600, 20, text="SCORE "+str(score), fill="white", font=FNT, tag="BG")
def block_color(x, y): # format()命令で16進数の値に変換できる
col = "#{0:x}{1:x}{2:x}".format(15-x-int(y/3), x+1, y*3+3)
return col
def draw_bar():
cvs.delete("BAR")
cvs.create_rectangle(bar_x-80, bar_y-12, bar_x+80, bar_y+12, fill="silver", width=0, tag="BAR")
cvs.create_rectangle(bar_x-78, bar_y-14, bar_x+78, bar_y+14, fill="silver", width=0, tag="BAR")
cvs.create_rectangle(bar_x-78, bar_y-12, bar_x+78, bar_y+12, fill="white", width=0, tag="BAR")
def move_bar():
global bar_x
if key == "Left" and bar_x > 80:
bar_x = bar_x - 40
if key == "Right" and bar_x < 720:
bar_x = bar_x + 40
def draw_ball():
cvs.delete("BALL")
cvs.create_oval(ball_x-20, ball_y-20, ball_x+20, ball_y+20, fill="gold", outline="orange", width=2, tag="BALL")
cvs.create_oval(ball_x-16, ball_y-16, ball_x+12, ball_y+12, fill="yellow", width=0, tag="BALL")
def move_ball():
global idx, tmr, score, ball_x, ball_y, ball_xp, ball_yp
ball_x = ball_x + ball_xp
if ball_x < 20:
ball_x = 20
ball_xp = -ball_xp
if ball_x > 780:
ball_x = 780
ball_xp = -ball_xp
x = int(ball_x/80)
y = int(ball_y/40)
if block[y][x] == 1:
block[y][x] = 0
ball_xp = -ball_xp
score = score + 10
ball_y = ball_y + ball_yp
if ball_y >= 600:
idx = 2
tmr = 0
return
if ball_y < 20:
ball_y = 20
ball_yp = -ball_yp
x = int(ball_x/80)
y = int(ball_y/40)
if block[y][x] == 1:
block[y][x] = 0
ball_yp = -ball_yp
score = score + 10
if bar_y-40 <= ball_y and ball_y <= bar_y:
if bar_x-80 <= ball_x and ball_x <= bar_x+80:
ball_yp = -10
score = score + 1
elif bar_x-100 <= ball_x and ball_x <= bar_x-80:
ball_yp = -10
ball_xp = random.randint(-20, -10)
score = score + 2
elif bar_x+80 <= ball_x and ball_x <= bar_x+100:
ball_yp = -10
ball_xp = random.randint(10, 20)
score = score + 2
def main_proc():
global key, keyoff
global idx, tmr, stage, score
global bar_x, ball_x, ball_y, ball_xp, ball_yp
if idx == 0:
tmr = tmr + 1
if tmr == 1:
stage = 1
score = 0
if tmr == 2:
ball_x = 160
ball_y = 240
ball_xp = 10
ball_yp = 10
bar_x = 400
draw_block()
draw_ball()
draw_bar()
cvs.create_text(400, 300, text="START", fill="cyan", font=FNT, tag="TXT")
if tmr == 30:
cvs.delete("TXT")
idx = 1
elif idx == 1:
move_ball()
move_bar()
draw_block()
draw_ball()
draw_bar()
if is_clr == True:
idx = 3
tmr = 0
elif idx == 2:
tmr = tmr + 1
if tmr == 1:
cvs.create_text(400, 260, text="GAME OVER", fill="red", font=FNT, tag="TXT")
if tmr == 15:
cvs.create_text(300, 340, text="[R]eplay", fill="cyan", font=FNT, tag="TXT")
cvs.create_text(500, 340, text="[N]ew game", fill="yellow", font=FNT, tag="TXT")
if key == "r":
cvs.delete("TXT")
idx = 0
tmr = 1
if key == "n":
cvs.delete("TXT")
for y in range(5):
for x in range(10):
block[y][x] = 1
idx = 0
tmr = 0
elif idx == 3:
tmr = tmr + 1
if tmr == 1:
cvs.create_text(400, 260, text="STAGE CLEAR", fill="lime", font=FNT, tag="TXT")
if tmr == 15:
cvs.create_text(400, 340, text="NEXT [SPACE]", fill="cyan", font=FNT, tag="TXT")
if key == "space":
cvs.delete("TXT")
for y in range(5):
for x in range(10):
block[y][x] = 1
idx = 0
tmr = 1
stage = stage + 1
if keyoff == True:
keyoff = False
if key != "":
key = ""
root.after(50, main_proc)
root = tkinter.Tk()
root.title("ブロックゲーム")
root.resizable(False, False)
root.bind("<Key>", key_down)
root.bind("<KeyRelease>", key_up)
cvs = tkinter.Canvas(root, width=800, height=600, bg="black")
cvs.pack()
main_proc()
root.mainloop()
## sinnki 1
import tkinter
import tkinter.messagebox
import pygame
import sys
idx = 0
tmr = 0
stage = 1
ix = 0
iy = 0
key = 0
def key_down(e):
global key
key = e.keysym
def key_up(e):
global key
key = 0
maze = [[],[],[],[],[],[],[],[]]
def stage_data():
global ix, iy
global maze##リスト全体を変更する場合global宣言が必要
if stage == 1:
ix = 1
iy = 1
maze = [##0が床、1が塗った場所、9が壁
[9,9,9,9,9,9,9,9,9,9],
[9,0,9,0,0,0,9,0,0,9],
[9,0,9,0,9,0,9,0,0,9],
[9,0,9,0,9,0,9,0,9,9],
[9,0,9,0,9,0,9,0,0,9],
[9,0,9,0,9,0,9,9,0,9],
[9,0,0,0,9,0,0,0,0,9],
[9,9,9,9,9,9,9,9,9,9]
]
if stage == 2:
ix = 8
iy = 6
maze = [##0が床、1が塗った場所、9が壁
[9,9,9,9,9,9,9,9,9,9],
[9,0,0,0,9,0,0,0,0,9],
[9,0,9,0,9,0,9,0,0,9],
[9,0,9,0,9,0,9,0,9,9],
[9,0,9,0,9,0,9,0,0,9],
[9,0,9,0,9,0,9,9,0,9],
[9,0,0,0,0,0,9,9,0,9],
[9,9,9,9,9,9,9,9,9,9]
]
if stage == 3:
ix = 1
iy = 1
maze = [##0が床、1が塗った場所、9が壁
[9,9,9,9,9,9,9,9,9,9],
[9,0,9,0,0,0,9,0,0,9],
[9,0,9,0,9,0,9,0,0,9],
[9,0,9,0,9,0,0,0,0,9],
[9,0,9,0,9,9,9,9,0,9],
[9,0,9,0,9,9,9,9,0,9],
[9,0,0,0,0,0,0,0,0,9],
[9,9,9,9,9,9,9,9,9,9]
]
if stage == 4:
ix = 1
iy = 1
maze = [##0が床、1が塗った場所、9が壁
[9,9,9,9,9,9,9,9,9,9],
[9,0,9,0,0,0,9,0,0,9],
[9,0,9,0,9,0,9,0,0,9],
[9,0,9,0,9,0,9,0,9,9],
[9,0,9,0,9,0,9,0,0,9],
[9,0,9,0,9,0,9,9,0,9],
[9,0,0,0,9,0,0,0,0,9],
[9,9,9,9,9,9,9,9,9,9]
]
if stage == 5:
ix = 1
iy = 1
maze = [##0が床、1が塗った場所、9が壁
[9,9,9,9,9,9,9,9,9,9],
[9,0,9,0,0,0,9,0,0,9],
[9,0,9,0,9,0,9,0,0,9],
[9,0,9,0,9,0,9,0,9,9],
[9,0,9,0,9,0,9,0,0,9],
[9,0,9,0,9,0,9,9,0,9],
[9,0,0,0,9,0,0,0,0,9],
[9,9,9,9,9,9,9,9,9,9]
]
maze[iy][ix] = 1
def draw_bg():
for y in range(8):
for x in range(10):
gx = 80*x
gy = 80*y
if maze[y][x] == 0:
cvs.create_rectangle(gx, gy, gx+80, gy+80, fill="white", width=0, tag="BG")
if maze[y][x] == 9:
cvs.create_image(gx+40, gy+40, image=wall, tag="BG")
cvs.create_text(120, 40, text="STAGE "+str(stage), fill="white", font=("TImes New Roman", 30, "bold"), tag="BG")
gx = 80*ix
gy = 80*iy
cvs.create_rectangle(gx, gy, gx+80, gy+80, fill="pink", width=0, tag="BG")
cvs.create_image(gx+42, gy+40, image=pen, tag="PEN")
def erase_bg():
cvs.delete("BG")
cvs.delete("PEN")
def move_pen():
global idx, tmr, ix, iy, key
bx = ix
by = iy
if key == "Left" and maze[iy][ix-1] == 0:
ix = ix-1
if key == "Right" and maze[iy][ix+1] == 0:
ix = ix+1
if key == "Up" and maze[iy-1][ix] == 0:
iy = iy-1
if key == "Down" and maze[iy+1][ix] == 0:
iy = iy+1
if ix != bx or iy != by:
maze[iy][ix] = 2
gx = 80*ix
gy = 80*iy
cvs.create_rectangle(gx, gy ,gx+80, gy+80, fill="pink", width=0, tag="BG")
cvs.delete("PEN")
cvs.create_image(gx+42, gy+40, image=pen, tag="PEN")
if key == "g" or key == "G" or key == "Shift_L":
key = 0
ret = tkinter.messagebox.askyesno("ギブアップ","やり直しますか?")
root.focus_force()##for mac
if ret == True:
stage_data()
erase_bg()
draw_bg()
def count_tile():
cnt = 0
for y in range(8):
for x in range(10):
if maze[y][x] == 0:
cnt = cnt + 1
return cnt
def game_main():
global idx, tmr, stage
if idx == 0:##初期化
pygame.mixer.music.load("ohd_bgm_field.ogg")
pygame.mixer.music.play(-1)
pygame.mixer.music.set_volume(0.3)##BGMボリューム設定0から1まで
stage_data()
draw_bg()
idx = 1
if idx == 1:##ペンの移動とクリアの判定
move_pen()
if count_tile() == 0:
txt = "STAGE CLEAR"
if stage == 5:
txt = "ALL STAGE CLEAR!"
cvs.create_text(400, 320, text=txt, fill="white", font=("Times New Roman", 40, "bold"), tag="BG")
idx = 2
tmr = 0
if idx == 2:##ステージクリア
tmr = tmr + 1
if tmr == 30:
if stage < 5:
stage = stage + 1
stage_data()
erase_bg()
draw_bg()
idx = 1
if stage == 5:
stage = 0
root.after(200, game_main)
pygame.init()
root = tkinter.Tk()
root.title("一筆書き迷路ゲーム")
root.resizable(False, False)
root.bind("<KeyPress>", key_down)
root.bind("<KeyRelease>", key_up)
cvs = tkinter.Canvas(root, width=800, height=640)
cvs.pack()
pen = tkinter.PhotoImage(file="pen.png")
wall = tkinter.PhotoImage(file="wall.png")
game_main()
root.mainloop()
##Dungeon Game 解析用
import pygame
import sys
import random
from pygame.locals import *
# 色の定義
WHITE = (255, 255, 255)
BLACK = ( 0, 0, 0)
RED = (255, 0, 0)
CYAN = ( 0, 255, 255)
BLINK = [(224,255,255), (192,240,255), (128,224,255), (64,192,255), (128,224,255), (192,240,255)]
# 画像の読み込み
imgTitle = pygame.image.load("image/title.png")
imgWall = pygame.image.load("image/wall.png")
imgWall2 = pygame.image.load("image/wall2.png")
imgDark = pygame.image.load("image/dark.png")
imgPara = pygame.image.load("image/parameter.png")
imgBtlBG = pygame.image.load("image/btlbg.png")
imgEnemy = pygame.image.load("image/enemy0.png")##敵のimage
imgItem = [
pygame.image.load("image/potion.png"),
pygame.image.load("image/blaze_gem.png"),
pygame.image.load("image/spoiled.png"),
pygame.image.load("image/apple.png"),
pygame.image.load("image/meat.png")
]
imgFloor = [
pygame.image.load("image/floor.png"),##床0
pygame.image.load("image/tbox.png"),##宝1
pygame.image.load("image/cocoon.png"),##繭2
pygame.image.load("image/stairs.png")##階段3
]
imgPlayer = [
pygame.image.load("image/mychr0.png"),##上
pygame.image.load("image/mychr1.png"),##上2
pygame.image.load("image/mychr2.png"),##下
pygame.image.load("image/mychr3.png"),##下2
pygame.image.load("image/mychr4.png"),##左
pygame.image.load("image/mychr5.png"),##左2
pygame.image.load("image/mychr6.png"),##右
pygame.image.load("image/mychr7.png"),##右2
pygame.image.load("image/mychr8.png")##死亡
]
imgEffect = [
pygame.image.load("image/effect_a.png"),##py攻撃 剣
pygame.image.load("image/effect_b.png")##py魔法 炎
]
# 変数の宣言
speed = 1
idx = 0
tmr = 0
floor = 0
fl_max = 1
welcome = 0
pl_x = 0
pl_y = 0
pl_d = 0
pl_a = 0
pl_lifemax = 0
pl_life = 0
pl_str = 0
food = 0
potion = 0
blazegem = 0
treasure = 0
emy_name = ""
emy_lifemax = 0
emy_life = 0
emy_str = 0
emy_x = 0
emy_y = 0
emy_step = 0
emy_blink = 0
dmg_eff = 0
btl_cmd = 0
COMMAND = ["[A]ttack", "[P]otion", "[B]laze gem", "[R]un"]
TRE_NAME = ["Potion", "Blaze gem", "Food spoiled.", "Food +20", "Food +100"]
EMY_NAME = [
"Green slime", "Red slime", "Axe beast", "Ogre", "Sword man",
"Death hornet", "Signal slime", "Devil plant", "Twin killer", "Hell"
]
MAZE_W = 11
MAZE_H = 9
maze = []
for y in range(MAZE_H):
maze.append([0]*MAZE_W)
DUNGEON_W = MAZE_W*3
DUNGEON_H = MAZE_H*3
dungeon = []
for y in range(DUNGEON_H):
dungeon.append([0]*DUNGEON_W)
def make_dungeon(): # ダンジョンの自動生成
XP = [ 0, 1, 0,-1]
YP = [-1, 0, 1, 0]
#周りの壁
for x in range(MAZE_W):
maze[0][x] = 1
maze[MAZE_H-1][x] = 1
for y in range(1, MAZE_H-1):
maze[y][0] = 1
maze[y][MAZE_W-1] = 1
#中を何もない状態に
for y in range(1, MAZE_H-1):
for x in range(1, MAZE_W-1):
maze[y][x] = 0
#柱
for y in range(2, MAZE_H-2, 2):
for x in range(2, MAZE_W-2, 2):
maze[y][x] = 1
#柱から上下左右に壁を作る
for y in range(2, MAZE_H-2, 2):
for x in range(2, MAZE_W-2, 2):
d = random.randint(0, 3)
if x > 2: # 二列目からは左に壁を作らない
d = random.randint(0, 2)
maze[y+YP[d]][x+XP[d]] = 1
# 迷路からダンジョンを作る
#全体を壁にする
for y in range(DUNGEON_H):
for x in range(DUNGEON_W):
dungeon[y][x] = 9
#部屋と通路の配置
for y in range(1, MAZE_H-1):
for x in range(1, MAZE_W-1):
dx = x*3+1
dy = y*3+1
if maze[y][x] == 0:
if random.randint(0, 99) < 20: # 部屋を作る
for ry in range(-1, 2):
for rx in range(-1, 2):
dungeon[dy+ry][dx+rx] = 0
else: # 通路を作る
dungeon[dy][dx] = 0
if maze[y-1][x] == 0: dungeon[dy-1][dx] = 0
if maze[y+1][x] == 0: dungeon[dy+1][dx] = 0
if maze[y][x-1] == 0: dungeon[dy][dx-1] = 0
if maze[y][x+1] == 0: dungeon[dy][dx+1] = 0
def draw_dungeon(bg, fnt): # ダンジョンを描画する
bg.fill(BLACK)
for y in range(-4, 6):
for x in range(-5, 6):
X = (x+5)*80
Y = (y+4)*80
dx = pl_x + x
dy = pl_y + y
if 0 <= dx and dx < DUNGEON_W and 0 <= dy and dy < DUNGEON_H:
if dungeon[dy][dx] <= 3:
bg.blit(imgFloor[dungeon[dy][dx]], [X, Y])
if dungeon[dy][dx] == 9:
bg.blit(imgWall, [X, Y-40])
if dy >= 1 and dungeon[dy-1][dx] == 9:
bg.blit(imgWall2, [X, Y-80])
if x == 0 and y == 0: # 主人公キャラの表示
bg.blit(imgPlayer[pl_a], [X, Y-40])
bg.blit(imgDark, [0, 0]) # 四隅が暗闇の画像を重ねる
draw_para(bg, fnt) # 主人公の能力を表示
def put_event(): # 床にイベントを配置する
global pl_x, pl_y, pl_d, pl_a
# 階段の配置
while True:
x = random.randint(3, DUNGEON_W-4)
y = random.randint(3, DUNGEON_H-4)
if(dungeon[y][x] == 0):
for ry in range(-1, 2): # 階段の周囲を床にする
for rx in range(-1, 2):
dungeon[y+ry][x+rx] = 0
dungeon[y][x] = 3##階段imgFloor
break
# 宝箱 1 と繭 2 の配置
for i in range(60):
x = random.randint(3, DUNGEON_W-4)
y = random.randint(3, DUNGEON_H-4)
if(dungeon[y][x] == 0):
dungeon[y][x] = random.choice([1,2,2,2,2])
# プレイヤーの初期位置
while True:
pl_x = random.randint(3, DUNGEON_W-4)
pl_y = random.randint(3, DUNGEON_H-4)
if(dungeon[pl_y][pl_x] == 0):
break
pl_d = 1
pl_a = 2
def move_player(key): # 主人公の移動
global idx, tmr, pl_x, pl_y, pl_d, pl_a, pl_life, food, potion, blazegem, treasure
if dungeon[pl_y][pl_x] == 1: # 宝箱 1 に載った
dungeon[pl_y][pl_x] = 0
treasure = random.choice([0,0,0,1,1,1,1,1,1,2])
if treasure == 0:##potion入手
potion = potion + 1
if treasure == 1:##blazegem入手
blazegem = blazegem + 1
if treasure == 2:##毒 food/2
food = int(food/2)
idx = 3
tmr = 0
return
if dungeon[pl_y][pl_x] == 2: # 繭 2 に載った
dungeon[pl_y][pl_x] = 0
r = random.randint(0, 99)
if r < 40: # 食料
treasure = random.choice([3,3,3,4])
if treasure == 3: food = food + 20
if treasure == 4: food = food + 100
idx = 3
tmr = 0
else: # 敵出現
idx = 10
tmr = 0
return
if dungeon[pl_y][pl_x] == 3: # 階段 3 に載った
idx = 2
tmr = 0
return
# 方向キーで上下左右に移動
x = pl_x
y = pl_y
if key[K_UP] == 1:##上 0 が押された 上が9の壁でなければ代入
pl_d = 0
if dungeon[pl_y-1][pl_x] != 9:
pl_y = pl_y - 1
if key[K_DOWN] == 1:##下 1
pl_d = 1
if dungeon[pl_y+1][pl_x] != 9:
pl_y = pl_y + 1
if key[K_LEFT] == 1:##左 2
pl_d = 2
if dungeon[pl_y][pl_x-1] != 9:
pl_x = pl_x - 1
if key[K_RIGHT] == 1:##右 3
pl_d = 3
if dungeon[pl_y][pl_x+1] != 9:
pl_x = pl_x + 1
pl_a = pl_d*2
if pl_x != x or pl_y != y: # 移動したら食料の量と体力を計算
pl_a = pl_a + tmr%2 # 移動したら足踏みのアニメーション
if food > 0:
food = food - 1
if pl_life < pl_lifemax:
pl_life = pl_life + 1
else:##食料がなければ1マス動くごとにライフが-5
pl_life = pl_life - 5
if pl_life <= 0:
pl_life = 0
pygame.mixer.music.stop()
idx = 9
tmr = 0
##look## draw_text
def draw_text(bg, txt, x, y, fnt, col): # 影付き文字の表示
sur = fnt.render(txt, True, BLACK)
bg.blit(sur, [x+1, y+2])
sur = fnt.render(txt, True, col)
bg.blit(sur, [x, y])
##look## draw_para
def draw_para(bg, fnt): # 主人公の能力を表示
X = 30
Y = 600
bg.blit(imgPara, [X, Y])##image/parameter
col = WHITE
if pl_life < 10 and tmr%2 == 0: col = RED
draw_text(bg, "{}/{}".format(pl_life, pl_lifemax), X+128, Y+6, fnt, col)
draw_text(bg, str(pl_str), X+128, Y+33, fnt, WHITE)
col = WHITE
if food == 0 and tmr%2 == 0: col = RED
draw_text(bg, str(food), X+128, Y+60, fnt, col)
draw_text(bg, str(potion), X+266, Y+6, fnt, WHITE)
draw_text(bg, str(blazegem), X+266, Y+33, fnt, WHITE)
##look## init_battle
def init_battle(): # 戦闘に入る準備をする
global imgEnemy, emy_name, emy_lifemax, emy_life, emy_str, emy_x, emy_y
typ = random.randint(0, floor)##深層フロアに行くほどtyp数多くなる
if floor >= 10:##10階以上は全ての敵が出現
typ = random.randint(0, 9)
lev = random.randint(1, floor)##敵レベルの決定
imgEnemy = pygame.image.load("image/enemy"+str(typ)+".png")##敵のimageを読み込む0~9まで
emy_name = EMY_NAME[typ] + " LV" + str(lev)##名前
emy_lifemax = 60*(typ+1) + (lev-1)*10##ライフ最大
emy_life = emy_lifemax##ライフ
emy_str = int(emy_lifemax/8)##攻撃力 ライフmaxの1/8
emy_x = 440-imgEnemy.get_width()/2##表示位置
emy_y = 560-imgEnemy.get_height()
##look## draw_bar
def draw_bar(bg, x, y, w, h, val, max): # 敵の体力を表示するバー
pygame.draw.rect(bg, WHITE, [x-2, y-2, w+4, h+4])##矩形表示 空の枠線が白
pygame.draw.rect(bg, BLACK, [x, y, w, h])##中身が黒
if val > 0:
pygame.draw.rect(bg, (0,128,255), [x, y, w*val/max, h])##valはemy_life 敵にライフがあれば
##(0,128,255) =青 wは200 w*val/maxはw ライフ分は青く 空白は黒く 表示
##draw_battle? emy_blink は idx 12で代入確認せよ
def draw_battle(bg, fnt): # 戦闘画面の描画
global emy_blink, dmg_eff
bx = 0
by = 0
if dmg_eff > 0:##画面を揺らす
dmg_eff = dmg_eff - 1
bx = random.randint(-20, 20)
by = random.randint(-10, 10)
bg.blit(imgBtlBG, [bx, by])
##py攻撃 emy_blink敵の明滅 敵の攻撃 emy_step敵を前方へ
if emy_life > 0 and emy_blink%2 == 0:
bg.blit(imgEnemy, [emy_x, emy_y+emy_step])
draw_bar(bg, 340, 580, 200, 10, emy_life, emy_lifemax)##draw_bar上の関数
if emy_blink > 0:##emy_blink 敵を前に出す 数値を-1し減らしていく
emy_blink = emy_blink - 1
for i in range(10): # 戦闘メッセージの表示 10
draw_text(bg, message[i], 600, 100+i*50, fnt, WHITE)
draw_para(bg, fnt) # 主人公の能力を表示
##look## battle_command
def battle_command(bg, fnt, key): # コマンドの入力と表示 btl_cmdでカーソル制御 entがTrueの返り値
global btl_cmd
ent = False
if key[K_a]: # Aキー
btl_cmd = 0
ent = True
if key[K_p]: # Pキー
btl_cmd = 1
ent = True
if key[K_b]: # Bキー
btl_cmd = 2
ent = True
if key[K_r]: # Rキー
btl_cmd = 3
ent = True
if key[K_UP] and btl_cmd > 0: #↑キー
btl_cmd -= 1
if key[K_DOWN] and btl_cmd < 3: #↓キー
btl_cmd += 1
if key[K_SPACE] or key[K_RETURN]:
ent = True
for i in range(4):##選択されているコマンドが虹色に表示される
c = WHITE
if btl_cmd == i: c = BLINK[tmr%6]##BKINK 色の配列 虹色に変化
draw_text(bg, COMMAND[i], 20, 360+i*60, fnt, c)
return ent
##戦闘メッセージの表示処理
message = [""]*10
##look## init_message
def init_message():
for i in range(10):
message[i] = ""
##look## set_message
def set_message(msg):
for i in range(10):
if message[i] == "":
message[i] = msg
return
for i in range(9):
message[i] = message[i+1]
message[9] = msg
def main(): # メイン処理
global speed, idx, tmr, floor, fl_max, welcome
global pl_a, pl_lifemax, pl_life, pl_str, food, potion, blazegem
global emy_life, emy_step, emy_blink, dmg_eff
dmg = 0
lif_p = 0
str_p = 0
pygame.init()
pygame.display.set_caption("One hour Dungeon")
screen = pygame.display.set_mode((880, 720))
clock = pygame.time.Clock()
font = pygame.font.Font(None, 40)
fontS = pygame.font.Font(None, 30)
se = [ # 効果音とジングル
pygame.mixer.Sound("sound/ohd_se_attack.ogg"),##プレイヤーアタック時
pygame.mixer.Sound("sound/ohd_se_blaze.ogg"),
pygame.mixer.Sound("sound/ohd_se_potion.ogg"),
pygame.mixer.Sound("sound/ohd_jin_gameover.ogg"),
pygame.mixer.Sound("sound/ohd_jin_levup.ogg"),
pygame.mixer.Sound("sound/ohd_jin_win.ogg")
]
while True:##スピード調整
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
if event.type == KEYDOWN:
if event.key == K_s:
speed = speed + 1
if speed == 4:
speed = 1
tmr = tmr + 1
key = pygame.key.get_pressed()
##look## main
if idx == 0: # タイトル画面
if tmr == 1:
pygame.mixer.music.load("sound/ohd_bgm_title.ogg")
pygame.mixer.music.play(-1)
screen.fill(BLACK)
screen.blit(imgTitle, [40, 60])
if fl_max >= 2:
draw_text(screen, "You reached floor {}.".format(fl_max), 300, 460, font, CYAN)
draw_text(screen, "Press space key", 320, 560, font, BLINK[tmr%6])
if key[K_SPACE] == 1:##Game START
make_dungeon()##
put_event()##pl_a 2 pl_b 1
floor = 1
welcome = 15
pl_lifemax = 300
pl_life = pl_lifemax
pl_str = 100
food = 300
potion = 0
blazegem = 0
idx = 1
pygame.mixer.music.load("sound/ohd_bgm_field.ogg")
pygame.mixer.music.play(-1)
##look## idx 1
elif idx == 1: # プレイヤーの移動
move_player(key)##分岐の基幹部分
draw_dungeon(screen, fontS)
draw_text(screen, "floor {} ({},{})".format(floor, pl_x, pl_y), 60, 40, fontS, WHITE)
if welcome > 0:##最高フロア回数を表示
welcome = welcome - 1
draw_text(screen, "Welcome to floor {}.".format(floor), 300, 180, font, CYAN)
##look## idx 2 $$解明$$ draw.rectの塗りつぶしと解放の配列の動作が不明
elif idx == 2: # 階段 画面切り替え
draw_dungeon(screen, fontS)##ダンジョンを描写
if 1 <= tmr and tmr <= 5:
h = 80*tmr
##画面サイズ x880 y720 上下から黒で段々に塗る
pygame.draw.rect(screen, BLACK, [0, 0, 880, h])
pygame.draw.rect(screen, BLACK, [0, 720-h, 880, h])
if tmr == 5:##全ての画面が塗りつぶされる
floor = floor + 1
if floor > fl_max:##floormaxが更新されていれば代入
fl_max = floor
welcome = 15
make_dungeon()
put_event()
if 6 <= tmr and tmr <= 9:
h = 80*(10-tmr)##6 320 7 240 8 160 9 80
pygame.draw.rect(screen, BLACK, [0, 0, 880, h])
pygame.draw.rect(screen, BLACK, [0, 720-h, 880, h])
if tmr == 10:
idx = 1
##look## idx 3
elif idx == 3: # アイテム入手もしくはトラップ
draw_dungeon(screen, fontS)# ダンジョンを描画する
screen.blit(imgItem[treasure], [320, 220])##move_playerでtreasureを定義
draw_text(screen, TRE_NAME[treasure], 380, 240, font, WHITE)
if tmr == 10:
idx = 1
##look## idx 9
elif idx == 9: # ゲームオーバー def move_player(key)から tmr=0
if tmr <= 30:
PL_TURN = [2, 4, 0, 6]##キャラ 下 左 上 右 の回転
pl_a = PL_TURN[tmr%4]##PL_TURNを順番に取り出す
if tmr == 30: pl_a = 8 # 倒れた絵
draw_dungeon(screen, fontS)##ダンジョンとキャラを描写する
elif tmr == 31:
se[3].play()##gemeover効果音とテキスト表示
draw_text(screen, "You died.", 360, 240, font, RED)
draw_text(screen, "Game over.", 360, 380, font, RED)
elif tmr == 100:##idxからリスタート
idx = 0
tmr = 0
##look## idx 10
elif idx == 10: # 戦闘開始
if tmr == 1:
pygame.mixer.music.load("sound/ohd_bgm_battle.ogg")
pygame.mixer.music.play(-1)
init_battle()
init_message()
elif tmr <= 4:##ダンジョン画面から戦闘画面に左から右にスイープ挿入
bx = (4-tmr)*220
by = 0
screen.blit(imgBtlBG, [bx, by])
draw_text(screen, "Encounter!", 350, 200, font, WHITE)
elif tmr <= 16:
draw_battle(screen, fontS)
draw_text(screen, emy_name+" appear!", 300, 200, font, WHITE)##emy_nameはLvまで代入されている
else:
idx = 11
tmr = 0
##look## idx 11
elif idx == 11: # プレイヤーのターン(入力待ち)
draw_battle(screen, fontS)
if tmr == 1: set_message("Your turn.")
if battle_command(screen, font, key) == True:##battle_comanndの戻り値btl_cmd=数値によりコマンド実行
if btl_cmd == 0:
idx = 12##確認
tmr = 0
if btl_cmd == 1 and potion > 0:
idx = 20##確認
tmr = 0
if btl_cmd == 2 and blazegem > 0:
idx = 21##確認
tmr = 0
if btl_cmd == 3:
idx = 14##確認
tmr = 0
##look## idx12
elif idx == 12: # プレイヤーの攻撃
draw_battle(screen, fontS)
if tmr == 1:
set_message("You attack!")
se[0].play()##効果音 「切る音」
dmg = pl_str + random.randint(0, 9)##プレイヤーのstrに0~9までの値を加算し攻撃値とする
if 2 <= tmr and tmr <= 4:##剣のエフェクト3回 2 $$460 140$$ 3 $$340 260$$ 4 220 380
screen.blit(imgEffect[0], [700-tmr*120, -100+tmr*120])
if tmr == 5:##emy_blinkが5代入されるもemy_step無し 消費され次へ
emy_blink = 5##敵を明滅させる変数4 2 1 で敵を表示 他 消す
set_message(str(dmg)+"pts of damage!")
##dmgをemy_lifeから引き 敵ライフが0なら勝利 idx16 へ
if tmr == 11:
emy_life = emy_life - dmg
if emy_life <= 0:
emy_life = 0
idx = 16
tmr = 0
##tmr 16 なら idx13 敵のターンへ
if tmr == 16:
idx = 13
tmr = 0
##look## idx 13
elif idx == 13: # 敵のターン、敵の攻撃
draw_battle(screen, fontS)
if tmr == 1:
set_message("Enemy turn.")
if tmr == 5:
set_message(emy_name + " attack!")
se[0].play()##効果音 「切る音」
emy_step = 30##敵を前に出す変数
if tmr == 9:
dmg = emy_str + random.randint(0, 9)
set_message(str(dmg)+"pts of damage!")
dmg_eff = 5##pyを揺らす変数
emy_step = 0##emyの位置を戻す変数
if tmr == 15:##pyのライフを計算
pl_life = pl_life - dmg
if pl_life < 0:##pyのライフが0以下なら0とし idx15 敗北
pl_life = 0
idx = 15
tmr = 0
##pyが生存ならpyのターン
if tmr == 20:
idx = 11
tmr = 0
##
elif idx == 14: # 逃げられる?
draw_battle(screen, fontS)
if tmr == 1: set_message("...")
if tmr == 2: set_message("......")
if tmr == 3: set_message(".........")
if tmr == 4: set_message("............")
if tmr == 5:
if random.randint(0, 99) < 60:
idx = 22
else:
set_message("You failed to flee.")
if tmr == 10:
idx = 13
tmr = 0
elif idx == 15: # 敗北
draw_battle(screen, fontS)
if tmr == 1:
pygame.mixer.music.stop()
set_message("You lose.")
if tmr == 11:
idx = 9
tmr = 29
elif idx == 16: # 勝利
draw_battle(screen, fontS)
if tmr == 1:
set_message("You win!")
pygame.mixer.music.stop()
se[5].play()
if tmr == 28:
idx = 22
if random.randint(0, emy_lifemax) > random.randint(0, pl_lifemax):
idx = 17
tmr = 0
elif idx == 17: # レベルアップ
draw_battle(screen, fontS)
if tmr == 1:
set_message("Level up!")
se[4].play()
lif_p = random.randint(10, 20)
str_p = random.randint(5, 10)
if tmr == 21:
set_message("Max life + "+str(lif_p))
pl_lifemax = pl_lifemax + lif_p
if tmr == 26:
set_message("Str + "+str(str_p))
pl_str = pl_str + str_p
if tmr == 50:
idx = 22
elif idx == 20: # Potion
draw_battle(screen, fontS)
if tmr == 1:
set_message("Potion!")
se[2].play()
if tmr == 6:
pl_life = pl_lifemax
potion = potion - 1
if tmr == 11:
idx = 13
tmr = 0
elif idx == 21: # Blaze gem
draw_battle(screen, fontS)
img_rz = pygame.transform.rotozoom(imgEffect[1], 30*tmr, (12-tmr)/8)
X = 440-img_rz.get_width()/2
Y = 360-img_rz.get_height()/2
screen.blit(img_rz, [X, Y])
if tmr == 1:
set_message("Blaze gem!")
se[1].play()
if tmr == 6:
blazegem = blazegem - 1
if tmr == 11:
dmg = 1000
idx = 12
tmr = 4
elif idx == 22: # 戦闘終了
pygame.mixer.music.load("sound/ohd_bgm_field.ogg")
pygame.mixer.music.play(-1)
idx = 1
draw_text(screen, "[S]peed "+str(speed), 740, 40, fontS, WHITE)
pygame.display.update()
clock.tick(4+2*speed)
if __name__ == '__main__':
main()