λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

python

파이썬으둜 λ°°μš°λŠ” κ²Œμž„ 개발 μ‹€μ „νŽΈ chapter 2

1. 히트 체크(hit check)

  2개의 물체가 μ ‘μ‘±ν–ˆλŠ”μ§€ νŒμ •ν•˜λŠ” κ²ƒμœΌλ‘œ, κ²Œμž„μ—μ„œλŠ” λ°œμ‚¬ν•œ νƒ„ν™˜μ΄ μƒλŒ€μ—κ²Œ λ§žμ•˜λŠ”μ§€, μ•„μ΄ν…œμ„ μ£Όμ› λŠ”μ§€ λ“±μ˜ μ΄λ²€νŠΈμ— μ΄μš©ν•  수 μžˆλ‹€.

 

 1) μ‚¬κ°ν˜•μ—μ„œμ˜ 히트 체크

import tkinter

def hit_check_rect():
    dx = abs((x1 + w1 / 2) - (x2 + w2 / 2)) # dx에 두 μ‚¬κ°ν˜•μ˜ 쀑심 x λ°©ν–₯ 거리 λŒ€μž…
    dy = abs((y1 + h1 / 2) - (y2 + h2 / 2)) # dy에 두 μ‚¬κ°ν˜•μ˜ 쀑심 y λ°©ν–₯ 거리 λŒ€μž…
    if dx <= w1 / 2 + w2 / 2 and dy <= h1 / 2 + h2 / 2: # μ‚¬κ°ν˜•μ΄ κ²ΉμΉ˜λŠ” 쑰건 νŒμ •
        return True # 겹치면 True
    return False # μ•„λ‹ˆλ©΄ False λ°˜ν™˜

def mouse_move(e):
    global x1, y1 # μ „μ—­ λ³€μˆ˜ μ„ μ–Έ
    x1 = e.x - w1 / 2 # νŒŒλž€μƒ‰ μ‚¬κ°ν˜• x μ’Œν‘œλ₯Ό 포인터 μ’Œν‘œλ‘œ 함
    y1 = e.y - h1 / 2 # νŒŒλž€μƒ‰ μ‚¬κ°ν˜• y μ’Œν‘œλ₯Ό 포인터 μ’Œν‘œλ‘œ 함
    col = "blue" # col에 blue λ¬Έμžμ—΄ λŒ€μž…
    if hit_check_rect() == True: # λ§Œμ•½ 두 μ‚¬κ°ν˜•μ΄ μ ‘μ‘±ν–ˆλ‹€λ©΄
        col = "cyan" # col에 cyan λ¬Έμžμ—΄ λŒ€μž…
    canvas.delete("RECT1") # 일단 νŒŒλž€ μ‚¬κ°ν˜• μ‚­μ œ ν›„
    canvas.create_rectangle(x1, y1, x1 + w1, y1 + h1, fill=col, tag="RECT1") # νŒŒλž€ μ‚¬κ°ν˜• 그리기


root = tkinter.Tk() # μœˆλ„μš° 객체 생성
root.title("μ‚¬κ°ν˜•μ„ μ‚¬μš©ν•œ 히트 체크") # μœˆλ„μš° 타이틀 μ§€μ • 
canvas = tkinter.Canvas(width=600, height=400, bg="white") # μΊ”λ²„μŠ€ μ»΄νΌλ„ŒνŠΈ 생성
canvas.pack() # μΊ”λ²„μŠ€ 배치
canvas.bind("<Motion>", mouse_move) # 마우슀 포인터λ₯Ό 움직일 λ•Œ μ‹€ν–‰ν•  ν•¨μˆ˜ μ§€μ •

x1 = 50 # νŒŒλž€μƒ‰ μ‚¬κ°ν˜• μ™Όμͺ½ μœ„ λͺ¨μ„œλ¦¬ xμ’Œν‘œ
y1 = 50 # κ·Έ yμ’Œν‘œ
w1 = 120 # 폭 
h1 = 60 # λ„ˆλΉ„
canvas.create_rectangle(x1, y1, x1 + w1, y1 + h1, fill="blue", tag="RECT1") # μΊ”λ²„μŠ€μ— νŒŒλž€μƒ‰ μ‚¬κ°ν˜• κ·Έλ¦Ό

x2 = 300
y2 = 100
w2 = 120
h2 = 160
canvas.create_rectangle(x2, y2, x2 + w2, y2 + h2, fill="red") # μΊ”λ²„μŠ€μ— λΉ¨κ°„ μ‚¬κ°ν˜• κ·Έλ¦Ό

root.mainloop() # μœˆλ„μš° ν‘œμ‹œ

λ‹Ώμ•˜μ„ λ•Œ / μ•ˆ λ‹Ώμ•˜μ„ λ•Œ

 

μˆ˜ν•™ 곡뢀 μ•ˆν•œμ§€ 2년이 λ‹€ λ˜μ–΄μ„œ μ•„λž˜ μ½”λ“œλ§Œ 봐도 μ–΄μ§ˆμ–΄μ§ˆν–ˆλŠ”λ°....

 κ·Έλž˜λ„ κ°„λ‹¨ν•œ 예제λ₯Ό 이해 λͺ»ν•˜λŠ”κ²Œ λ„ˆλ¬΄ λΆ€λ„λŸ¬μ›Œμ„œ 계속 μ΄ν•΄ν•˜λ €κ³  λ…Έλ ₯ν•˜λŠ”μ€‘

def hit_check_rect():
    dx = abs((x1 + w1 / 2) - (x2 + w2 / 2))
    dy = abs((y1 + h1 / 2) - (y2 + h2 / 2))
    if dx <= w1 / 2 + w2 / 2 and dy <= h1 / 2 + h2 / 2:
        return True
    return False

 

이 뢀뢄을 그림으둜 ν‘œν˜„ν•˜μžλ©΄ λ‹€μŒκ³Ό κ°™λ‹€.

 

일단 μ΄λΆ€λΆ„μ—μ„œ x λ°©ν–₯의 거리인 dx와 y λ°©ν–₯ 거리인 dyλ₯Ό 이해해야 ν•œλ‹€.

 

νŒŒλž€μƒ‰ μ‚¬κ°ν˜•μ˜ 쀑심 μ’Œν‘œλŠ” (x1+w1/2, y1+h1/2), 빨간색 μ‚¬κ°ν˜•μ˜ 쀑심 μ’Œν‘œλŠ” (x2+w2/2, y2+h2/2)

 

이 λ•Œ dx의 κ°’ : νŒŒλž€μƒ‰ μ‚¬κ°ν˜•μ΄ 빨간색 μ‚¬κ°ν˜•μ˜ μ™Όμͺ½μΌ λ•ŒλŠ” (x2 + w2 / 2) - (x1 + w1 / 2), 빨간색 μ‚¬κ°ν˜•μ΄ νŒŒλž€μƒ‰ μ‚¬κ°ν˜•μ˜ μ™Όμͺ½μΌ λ•ŒλŠ” (x1 + w1 / 2) - (x2 + w2 / 2)

  => (x1 + w1 / 2) - (x2 + w2 / 2)의 μ ˆλŒ“κ°’

  => abs() λͺ…λ ΉμœΌλ‘œ μ ˆλŒ“κ°’μ„ ꡬ할 수 있음(μˆ˜ν•™μ— κ΄€ν•œ λͺ…령이어도 abs()λͺ…령은 math λͺ¨λ“ˆ μž„ν¬νŠΈ ν•„μš” μ—†μŒ)

  => dx = abs((x1 + w1 / 2) - (x2 + w2 / 2))

λ§ˆμ°¬κ°€μ§€λ‘œ dy의 값을 dy = abs((y1 + h1 / 2) - (y2 + h2 / 2)) 둜 ν‘œν˜„ν•œλ‹€.

 

  ν•˜μ§€λ§Œ μš°λ¦¬κ°€ ν•˜λ €κ³  ν•˜λŠ” 것은 두 μ‚¬κ°ν˜•μ΄ κ²ΉμΉ  λ•Œ μƒκΈ°λŠ” μ΄λ²€νŠΈμ΄λ‹€. μœ„ κ·Έλ¦Όμ—μ„œ dx의 값이 μ–΄λ–€ 값일 λ•Œ xμΆ• λ°©ν–₯μ—μ„œ 겹치게 될까? μžμ„Έν•œ 그림은 33p κ·Έλ¦Ό 2-1-3을 μ°Έκ³ ν•˜λ„λ‘ ν•΄μ•Όκ² λ‹€... (μ €κ±° μœ„ κ·Έλ¦Ό λ§Œλ“œλŠ”κ²ƒλ„ λ„ˆλ¬΄ νž˜λ“€μ—ˆλ‹€..)

μ•„λ¬΄νŠΌ! μ§±λŒμ„ 잘 ꡴렀보면 dx의 값이 w1 / 2 + w2 / 2보닀 μž‘μ„ λ•Œ, κ²ΉμΉ˜λŠ” 것을 μ•Œ 수 μžˆλ‹€. μ˜†μ˜ 캑쳐만 봐도 일단 w1의 반과 w2의 λ°˜λ³΄λ‹€ dxκ°€ μž‘μœΌλ©΄ xμΆ• λ°©ν–₯μœΌλ‘œλŠ” κ²Ήμ³μ§€λŠ”κ΅¬λ‚˜! ν•˜κ³  λŠλ‚„ 수 μžˆλ‹€.

dy도 λ§ˆμ°¬κ°€μ§€λ‹€. dy의 값이 h1/2 + h2/2보닀 μž‘λ‹€λ©΄, yμΆ• λ°©ν–₯으둜 κ²ΉμΉœλ‹€. 이 두 κ°€μ§€ 쑰건이 λͺ¨λ‘ 좩쑱될 λ•Œ 두 μ‚¬κ°ν˜•μ΄ 겹치게 λœλ‹€. 

이λ₯Ό μ ‘μ΄‰ν•˜λŠ” 것(dx의 값이 w1 / 2 + w2 / 2보닀 μž‘μ€κ²Œ μ•„λ‹ˆλΌ 같을 λ•Œ, dy도 λ§ˆμ°¬κ°€μ§€) λ˜ν•œ ν¬ν•¨ν•œλ‹€λ©΄ λ‹€μŒκ³Ό 같이 정리할 수 μžˆλ‹€.

dx <= w1 / 2 + w2 / 2 and dy <= h1 / 2 + h2 / 2

이 과정이 λͺ¨λ‘ hit_check_rect() ν•¨μˆ˜μ—μ„œ μˆ˜ν–‰λœλ‹€.

 

이 ν›„ mouse_move() ν•¨μˆ˜μ—μ„œ νŒŒλž€μƒ‰ μ‚¬κ°ν˜•μ˜ 이동을 μˆ˜ν–‰ν•œλ‹€. 이 λ•Œ 마우슀 포인터λ₯Ό 움직일 λ•Œ ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λ„λ‘ bind() λͺ…령을 μž‘μ„±ν•œλ‹€.

canvas.bind("<Motion>", mouse_move)

 

 

2) μ›ν˜•μ—μ„œμ˜ 히트 체크

import tkinter
import math


def hit_check_circle():
    dis = math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)) # dis에 두 점 사이 거리λ₯Ό 계산해 λŒ€μž…
    if dis <= r1 + r2: # dis 값이 두 원 λ°˜μ§€λ¦„μ˜ ν•© μ΄ν•˜μ΄λ©΄
        return True # True
    return False # μ•„λ‹ˆλ©΄ False λ°˜ν™˜


def mouse_move(e):
    global x1, y1 # μ „μ—­ λ³€μˆ˜ μ„ μ–Έ
    x1 = e.x # μ΄ˆλ‘μƒ‰ μ›μ˜ xμ’Œν‘œλ₯Ό 포인터 μ’Œν‘œλ‘œ 함
    y1 = e.y # μ΄ˆλ‘μƒ‰ μ›μ˜ yμ’Œν‘œλ₯Ό 포인터 μ’Œν‘œλ‘œ 함
    col = "green" # col에 green λ¬Έμžμ—΄ λŒ€μž…
    if hit_check_circle() == True: # 두 원이 μ ‘μ΄‰ν–ˆλ‹€λ©΄
        col = "lime" # col에 lime λ¬Έμžμ—΄ λŒ€μž…
    canvas.delete("CIR1") # 일단 μ΄ˆλ‘μƒ‰ 원 μ‚­μ œ ν›„ 
    canvas.create_oval(x1 - r1, y1 - r1, x1 + r1, y1 + r1, fill=col, tag="CIR1") # λ‹€μ‹œ μ΄ˆλ‘μƒ‰ 원 그리기


root = tkinter.Tk() # μœˆλ„μš° 객체 생성
root.title("원을 μ‚¬μš©ν•œ 히트 체크") # μœˆλ„μš° 타이틀 μ§€μ •
canvas = tkinter.Canvas(width=600, height=400, bg="white") # μΊ”λ²„μŠ€ μ»΄ν¬λ„ŒνŠΈ 생성
canvas.pack() # μΊ”λ²„μŠ€ 배치
canvas.bind("<Motion>", mouse_move) # 마우슀 포인터λ₯Ό 움직일 λ•Œ μ‹€ν–‰ν•  ν•¨μˆ˜ μ§€μ •

# μ΄ˆλ‘μƒ‰ 원
x1 = 50 # 원 쀑심 xμ’Œν‘œ
y1 = 50 # yμ’Œν‘œ
r1 = 40 # 원 λ°˜μ§€λ¦„
canvas.create_oval(x1 - r1, y1 - r1, x1 + r1, y1 + r1, fill="green", tag="CIR1") # μΊ”λ²„μŠ€μ— μ΄ˆλ‘μƒ‰ 원 κ·Έλ¦Ό

# 주황색 원
x2 = 300
y2 = 200
r2 = 80
canvas.create_oval(x2 - r2, y2 - r2, x2 + r2, y2 + r2, fill="orange")

root.mainloop() # μœˆλ„μš° ν‘œμ‹œ

 

  μ΄ˆλ‘μƒ‰ μ›μ˜ 쀑심 μ’Œν‘œλ₯Ό (x1, y1), λ°˜μ§€λ¦„μ˜ 길이λ₯Ό r1둜 작고 주황색 μ›μ˜ 쀑심 μ’Œν‘œλŠ” (x2, y2), λ°˜μ§€λ¦„μ˜ κΈΈμ΄λŠ” r2라고 ν•  λ•Œ 두 점 μ‚¬μ΄μ˜ 거리 κ³΅μ‹μœΌλ‘œ 계산할 수 μžˆλ‹€. 

  νŒŒμ΄μ¬μ—μ„œλŠ” λ£¨νŠΈκ°’μ„ sqrt() λͺ…λ ΉμœΌλ‘œ 계산할 수 μžˆλŠ”λ°, μ΄λŠ” μœ„μ˜ abs λͺ…λ Ήκ³Ό 달리 math λͺ¨λ“ˆμ„ μž„ν¬νŠΈ ν•΄μ•Όν•œλ‹€. 

 

 dis = math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))

 

이 값이 두 μ›μ˜ λ°˜μ§€λ¦„μ˜ 합계(r1 + r2)보닀 μž‘κ±°λ‚˜ κ°™μœΌλ©΄ 원이 κ²Ήμ³μ§€κ²Œ λœλ‹€.

 

 

2. μ‚Όκ°ν•¨μˆ˜ μ‚¬μš©λ²•

λ‚˜λŠ” 문과좩이라 μ‚Όκ°ν•¨μˆ˜μ†‘μœΌλ‘œ μ‚Όκ°ν•¨μˆ˜λ₯Ό λ°°μ› λ‹€...

 

 

μ•„λ¬΄νŠΌ μ‚Όκ°ν•¨μˆ˜λŠ” 각의 크기와 λ³€μ˜ 길이의 λΉ„λ₯Ό ν‘œμ‹œν•˜λŠ” ν•¨μˆ˜λ‘œ, 이λ₯Ό μ΄μš©ν•΄ 적기의 이동 λ°©ν–₯μ΄λ‚˜ λ°©μ‚¬ν˜• νƒ„ν™˜ λ°œμ‚¬ λͺ¨μ…˜μ„ μ œμž‘ν•  수 μžˆλ‹€.

μˆœμ„œλŒ€λ‘œ 사인, 코사인, νƒ„μ  νŠΈ ν•¨μˆ˜ / r은 λ°˜μ§€λ¦„, (x,y)λŠ” 원주 μƒμ˜ μ’Œν‘œ

κ°λ„λŠ” xμΆ• 였λ₯Έμͺ½μ—μ„œ μ‹œμž‘ν•΄ λ°˜μ‹œκ³„ λ°©ν–₯으둜 컀지며, 1바퀴λ₯Ό 돌면 360도이닀. λ‹€λ§Œ 파이썬 같은 ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œλŠ” 각도 λ°©ν–₯이 μˆ˜ν•™κ³Ό λ°˜λŒ€(μ‹œκ³„ λ°©ν–₯)μ΄λ―€λ‘œ 주의

 

 

1) sin, cos, tan κ°’ κ³„μ‚°ν•˜κΈ°

sin(), cos(), tan() λͺ…령을 μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” math λͺ¨λ“ˆμ„ μž„ν¬νŠΈν•΄μ•Όν•œλ‹€.

 

import math

d = 45 # d에 각도 κ°’ λŒ€μž…
a = math.radians(d) # d값을 λΌλ””μ•ˆμœΌλ‘œ λ³€ν™˜ν•΄ a에 λŒ€μž…
s = math.sin(a)
c = math.cos(a)
t = math.tan(a)

print("sin " + str(s))
print("cos " + str(c))
print("tan " + str(t))

tan(45&amp;ordm;) = 1μ΄μ§€λ§Œ 0.999둜 μž…λ ₯λ˜λŠ” 것은 기본적으둜 ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œ μ†Œμˆ˜λ₯Ό λ‹€λ£° λ•Œ μ˜€μ°¨κ°€ λ°œμƒν•˜λŠ” κ²½μš°κ°€ κ½€ 있기 λ•Œλ¬Έμ΄λ‹€.

  μ—¬κΈ°μ„œ μ€‘μš”ν•œ 것은 파이썬 μ‚Όκ°ν•¨μˆ˜μ˜ μΈμˆ˜λŠ” 각도가 μ•„λ‹Œ radian(λΌλ””μ•ˆ)κ°’μœΌλ‘œ μ§€μ •ν•΄μ•Ό ν•œλ‹€λŠ” 점이닀. λ‚œ 처음 λ“€μ—ˆλŠ”λ° ꡭ제적으둜 쓰인닀고 ν•œλ‹€.. μ§„μž‘ μ’€ μ•Œλ €μ£Όμ§€. μ΄λŠ” radians() λͺ…령을 μ‚¬μš©ν•΄ 각도λ₯Ό radian으둜 λ³€ν™˜ν•œλ‹€. 1 λΌλ””μ•ˆμ€ 180º/π(μ•½ 57º)이며, ν•œ 바퀴(360º)λŠ” 2πλΌλ””μ•ˆμ΄λ‹€.

 

 

2) μ‚Όκ°ν•¨μˆ˜ 계산 ν”„λ‘œκ·Έλž¨

μœˆλ„μš° ν…μŠ€νŠΈ μž…λ ₯ ν•„λ“œμ— 각도λ₯Ό μž…λ ₯ ν›„ '계산' λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ 라벨에 μ‚Όκ°ν•¨μˆ˜ 값이 ν‘œμ‹œλ˜λŠ” ν”„λ‘œκ·Έλž¨μ΄λ‹€.

 

import tkinter
import math

def trigo() : # ν•¨μˆ˜ μ •μ˜
    try : # μ˜ˆμ™Έ 처리
        d = float(entry.get()) # μž…λ ₯ ν•„λ“œκ°’μ„ μ‹€μˆ˜ν˜•μœΌλ‘œ d에 λŒ€μž…
        a = math.radians(d)  # d값을 λΌλ””μ•ˆμœΌλ‘œ λ³€ν™˜ν•΄ a에 λŒ€μž… 
        s = math.sin(a)
        c = math.cos(a)
        t = math.tan(a)
        label_s["text"] = "sin " + str(s) # 라벨에 sκ°’ ν‘œμ‹œ
        label_c["text"] = "cos " + str(c) 
        label_t["text"] = "tan " + str(t)
    except : # μ˜ˆμ™Έκ°€ λ°œμƒν•œ 경우
        print("각도λ₯Ό 도 κ°’μœΌλ‘œ μž…λ ₯ν•΄ μ£Όμ‹­μ‹œμ˜€ : ") # μ…€ μœˆλ„μš°μ— κ²½κ³ λ¬Έ 좜λ ₯

root = tkinter.Tk() # μœˆλ„μš° 객체 생성
root.geometry("300x200") # μœˆλ„μš° 크기 μ§€μ •
root.title("μ‚Όκ°ν•¨μˆ˜ κ°’") # μœˆλ„μš° 타이틀 μ§€μ •

entry = tkinter.Entry(width = 10) # 1ν–‰ ν…μŠ€νŠΈ μž…λ ₯ ν•„λ“œ 생성
entry.place(x = 20, y = 20) # ν…μŠ€νŠΈ μž…λ ₯ ν•„λ“œ 배치
button = tkinter.Button(text = "계산", command = trigo) # λ²„νŠΌ μ»΄ν¬λ„ŒνŠΈ 생성, λ²„νŠΌ 클릭 μ‹œ μ‹€ν–‰ ν•¨μˆ˜ μ§€μ •
button.place(x = 110, y = 20) # λ²„νŠΌ 배치

label_s = tkinter.Label(text="sin") # 라벨 μ»΄ν¬λ„ŒνŠΈ 생성
label_s.place(x = 20, y = 60)
label_c = tkinter.Label(text="cos")
label_c.place(x = 20, y = 100)
label_t = tkinter.Label(text="tan")
label_t.place(x = 20, y = 140)

root.mainloop() # μœˆλ„μš° ν‘œμ‹œ

 

μ‹€ν–‰ κ²°κ³Ό

 

def trigo() :
    try :
        d = float(entry.get())
        a = math.radians(d)
        s = math.sin(a)
        c = math.cos(a)
        t = math.tan(a)
        label_s["text"] = "sin " + str(s)
        label_c["text"] = "cos " + str(c)
        label_t["text"] = "tan " + str(t)
    except :
        print("각도λ₯Ό 도 κ°’μœΌλ‘œ μž…λ ₯ν•΄ μ£Όμ‹­μ‹œμ˜€ : ")

# μ€‘λž΅

button = tkinter.Button(text = "계산", command = trigo)

 

  μ½”λ“œμ—μ„œ trigo ν•¨μˆ˜λŠ” λ²„νŠΌμ„ ν΄λ¦­ν•΄μ•Όλ§Œ ν•΄λ‹Ή ν•¨μˆ˜κ°€ μ‹€ν–‰λ˜λŠ”λ°, μ΄λŠ” Button() λͺ…λ Ήμ˜ 인수인 'command = ' μ—μ„œ trigo둜 μ§€μ •ν–ˆκΈ° λ•Œλ¬Έμ΄λ‹€.

  그리고 trigo ν•¨μˆ˜μ˜ λ‚΄μš©μ€ λ‹€μŒκ³Ό κ°™λ‹€. ν…μŠ€νŠΈ μž…λ ₯ ν•„λ“œμ˜ λ¬Έμžμ—΄μ„ float() λͺ…λ ΉμœΌλ‘œ μ†Œμˆ˜λ‘œ λ³€ν™˜μ— d에 λŒ€μž…ν•œλ‹€. d의 값은 radian으둜 λ³€ν™˜λ˜μ–΄ a에 λŒ€μž…λ˜κ³ , 이후 μ‚Όκ°ν•¨μˆ˜μ˜ 값이 계산 λ˜μ–΄ 라벨에 계산 값이 ν‘œμ‹œλœλ‹€. 

ν•˜μ§€λ§Œ 숫자만 μž…λ ₯λœλ‹€λŠ” 법이 μ—†λ‹€. κ°‘μžκΈ° ν•œκΈ€μ„ μ“°κ±°λ‚˜ μ•ŒνŒŒλ²³μ΄ μž…λ ₯λ˜κ±°λ‚˜, μ–΄λ–€ 값도 μž…λ ₯ν•˜μ§€ μ•Šμ€ μƒνƒœμ—μ„œ λ²„νŠΌμ„ λˆ„λ₯Ό λ•ŒλŠ” λ³€ν™˜ν•  μˆ˜κ°€ μ—†λŠ”λ°, μ΄λŠ” try ~ except μ˜ˆμ™Έ 처리 ꡬ문을 μ΄μš©ν•˜λ©΄ λœλ‹€. μ—λŸ¬κ°€ λ°œμƒν•œ 경우 except에 적힌 μ½”λ“œκ°€ μ‹€ν–‰λ˜λŠ”λ°, μ—¬κΈ°μ„œλŠ” μ…Έ μœˆλ„μš°μ— λ©”μ‹œμ§€λ₯Ό 좜λ ₯ν•œλ‹€. try~exceptλŠ” λ‹€μŒκ³Ό 같이 μ‚¬μš©ν•œλ‹€.

 

try :
    μ˜ˆμ™Έκ°€ λ°œμƒν•  κ°€λŠ₯성이 μžˆλŠ” μ½”λ“œ
except : 
    μ˜ˆμ™Έκ°€ λ°œμƒν–ˆμ„ λ•Œ μˆ˜ν–‰ν•  처리

 

 

3) μ‚Όκ°ν•¨μˆ˜λ‘œ λ„ν˜• 그리기

import tkinter
import math

root = tkinter.Tk()
root.title("μ‚Όκ°ν•¨μˆ˜λ₯Ό ν™œμš©ν•œ μ„  그리기")
canvas = tkinter.Canvas(width = 400, height = 400, bg = "white")
canvas.pack() # μΊ”λ²„μŠ€ 배치

for d in range(0, 90, 10) : # 반볡 : d 값이 0μ—μ„œ 90κΉŒμ§€ 10μ”© 증가
    a = math.radians(d)
    x = 300 * math.cos(a)
    y = 300 * math.sin(a)
    canvas.create_line(0, 0, x, y, fill = "blue") # (0, 0)μ—μ„œ (x, y)κΉŒμ§€ μ„  κΈ‹κΈ°
root.mainloop()

 

 

  create_line() λͺ…령을 μ‚¬μš©ν•΄ μœˆλ„μš° μ™Όμͺ½ 상단 λͺ¨μ„œλ¦¬μ˜ 원점(0, 0)λΆ€ν„° cosκ³Ό sin으둜 κ³„μ‚°ν•œ μ’Œν‘œ(x, y)κΉŒμ§€ 선을 κ·Έλ¦°λ‹€.  그리고 μ™Όμͺ½ λͺ¨μ„œλ¦¬κ°€ μ„  μ‹œμž‘μ  (0, 0)이고 μ΄ν›„λ‘œλŠ” μ‹œκ³„ λ°©ν–₯으둜 선이 κ·Έμ–΄μ§€λŠ”λ°, ν”„λ‘œκ·Έλž˜λ° μ–Έμ–΄μ—μ„œλŠ” 선이 λ°˜λŒ€λ‘œ κ·Έμ–΄μ§„λ‹€κ³  ν–ˆλŠ”λ° μ—¬κΈ°μ„œ κ·Έ 사싀을 확인할 수 μžˆλ‹€. 

  for d in range(0, 90, 10)은 말 κ·ΈλŒ€λ‘œ dλ₯Ό range()μ•ˆμ— μžˆλŠ” λ²”μœ„μ—μ„œ μ¦κ°€μ‹œν‚€λ©° λ°˜λ³΅ν•˜κ² λ‹€λŠ” 것이닀. μ—¬κΈ°μ„œ 0은 첫 ν•­, 90은 끝항 + 1(ν•œλ²ˆ 더 λ°˜λ³΅ν–ˆμ„ λ•Œμ˜ 숫자둜, d = 80이 끝항이면 d = 90일 λ•Œ λ©ˆμΆ˜λ‹€λŠ” 뜻 즉 90인 κ²½μš°λŠ” μ‹€ν–‰ μ•ˆλ¨), λ§ˆμ§€λ§‰ 10은 d = d + 10의 의미둜, 10μ”© μ¦κ°€ν•œλ‹€λŠ” 것이닀. 

λ“±μ°¨μˆ˜μ—΄λ‘œ κ°„λ‹¨νžˆ μ •λ¦¬ν•˜λ©΄ for d in range(첫항, 끝항 + 곡차, 곡차)둜 λ³Ό 수 μžˆκ² λ‹€.

 

 

4) λ‹€μ–‘ν•œ μƒ‰μƒμ˜ 선그리기

import tkinter
import math

root = tkinter.Tk()
root.title("μ‚Όκ°ν•¨μˆ˜λ₯Ό ν™œμš©ν•œ λ„ν˜• 그리기")
canvas = tkinter.Canvas(width=600, height=600, bg="black")
canvas.pack()

COL = ["greenyellow", "limegreen", "aquamarine", "cyan", "deepskyblue", "blue", "blueviolet", "violet"] # 8개의 색상을 리슀트둜 μ •μ˜
for d in range(0, 360): # 반볡 : d 값이 0μ—μ„œ 360κΉŒμ§€ 1μ”© 증가
    x = 250 * math.cos(math.radians(d)) # μ„ μ˜ 끝 xμ’Œν‘œλ₯Ό cos으둜 계산
    y = 250 * math.sin(math.radians(d)) # μ„ μ˜ 끝 yμ’Œν‘œλ₯Ό sin으둜 계산
    canvas.create_line(300, 300, 300 + x, 300 + y, fill=COL[d % 8], width=2) # μΊ”λ²„μŠ€ 쀑심(300, 300)μ—μ„œ μ‚Όκ°ν•¨μˆ˜λ‘œ κ³„μ‚°ν•œ μ’Œν‘œκΉŒμ§€ 선을 그음
root.mainloop()

μœΌμ•…

 

사쑱을 λ§λΆ™μ΄μžλ©΄ deepskyblueλ₯Ό deepbluesky둜 μ μ—ˆλŠ”λ° 계속 였λ₯˜κ°€ λ‚˜κΈΈλž˜ λŒ€μ²΄ 뭐가 잘λͺ»λλ‚˜ μ‹Άμ–΄μ„œ ν•œμ°Έμ„ λ΄€μ—ˆλ˜... 

 

for d in range(0, 360):
    x = 250 * math.cos(math.radians(d))
    y = 250 * math.sin(math.radians(d))
    canvas.create_line(300, 300, 300 + x, 300 + y, fill=COL[d % 8], width=2)

 

  이번 ν”„λ‘œκ·Έλž¨μ˜ μ€‘μš”ν•œ 점은 μœˆλ„μš° 크기λ₯Ό 600 x 600둜 λ§žμ·„μœΌλ―€λ‘œ create_lineμ—μ„œ 쀑심점을 (300, 300)으둜 μž‘μ•˜λ‹€. 그리고 x와 y에 각각 250을 κ³±ν•΄μ„œ, μ›μ μœΌλ‘œλΆ€ν„°μ˜ 거리가 250ν”½μ…€μ˜ 원주 μœ„ 점을 ν–₯ν•΄ 선을 그리게 λœλ‹€. μ„ μ˜ 색깔은 d % 8둜 COL 리슀트의 0 ~ 7번 μ›μ†Œλ“€μ΄ λ°˜λ³΅ν•΄μ„œ λ‚˜μ˜€λ„λ‘ ν•œλ‹€.

  그리고 cos(), sin() λͺ…λ Ήμ˜ 인수둜 radians() λͺ…령을 μ‚¬μš©ν–ˆλŠ”λ° μ΄λŠ” ν•¨μˆ˜λ₯Ό λ‹€λ₯Έ ν•¨μˆ˜μ˜ 인수둜 μ‚¬μš©ν•  μˆ˜κ°€ μžˆλ‹€λŠ” μ–˜κΈ°λ‹€.

 

 

 

4. μΈλ±μŠ€μ™€ 타이머

1) κ²Œμž„ μ§„ν–‰ 관리

μ•„λž˜ μ½”λ“œλŠ” 인덱슀, 타이머 λ³€μˆ˜λ₯Ό μ€€λΉ„ν•΄ 타이틀 ν™”λ©΄, κ²Œμž„ ν”Œλ ˆμ΄ 쀑 ν™”λ©΄, κ²Œμž„ μ˜€λ²„ 화면을 ν‘œμ‹œν•˜λŠ” ν”„λ‘œκ·Έλž¨μ΄λ‹€.

 

import tkinter

# 폰트, 인덱슀 λ³€μˆ˜, 타이머 λ³€μˆ˜ μ •μ˜
fnt1 = ("Times New Roman", 20)
fnt2 = ("Times New Roman", 40)
index = 0
timer = 0

key = ""  # ν‚€ 값을 λŒ€μž…ν•  λ³€μˆ˜

def key_down(e):
    global key  # keyλ₯Ό μ „μ—­λ³€μˆ˜λ‘œ μ„ μ–Έ
    key = e.keysym  # key에 keysymκ°’ λŒ€μž…


def main():
    global index, timer # μ „μ—­λ³€μˆ˜ μ„ μ–Έ
    canvas.delete("STATUS") # λ¨Όμ € index와 timer ν‘œμ‹œ μ‚­μ œ
    timer = timer + 1 # timer κ°’ 1 증가
    canvas.create_text(200, 30, text="index " + str(index), fill="white", font=fnt1, tag="STATUS") # index κ°’ ν‘œμ‹œ
    canvas.create_text(400, 30, text="timer " + str(timer), fill="cyan", font=fnt1, tag="STATUS") # timer κ°’ ν‘œμ‹œ

    if index == 0: # index 0 처리 (타이틀 ν™”λ©΄)
        if timer == 1: # timer 값이 1이면
            canvas.create_text(300, 150, text = "타이틀", fill="white", font=fnt2, tag="TITLE") # 타이틀 문자 ν‘œμ‹œ
            canvas.create_text(300, 300, text = "Press[SPACE]Key", fill="lime", font=fnt1, tag="TITLE") # 'press[space]key' λ¬Έμžμ—΄ ν‘œμ‹œ
        if key == "space" : # 슀페이슀 ν‚€λ₯Ό λˆŒλ €μ„ λ•Œ
            canvas.delete("TITLE") # 타이틀 문자 μ‚­μ œ
            canvas.create_rectangle(0, 0, 600, 400, fill="blue", tag="GAME") # μΊ”λ²„μŠ€λ₯Ό νŒŒλž€μƒ‰μœΌλ‘œ 칠함
            canvas.create_text(300, 150, text = "κ²Œμž„ 쀑", fill="white", font=fnt2, tag="GAME") # 'κ²Œμž„ 쀑' λ¬Έμžμ—΄ ν‘œμ‹œ
            canvas.create_text(300, 300, text = "[E]μ’…λ£Œ", fill="yellow", font=fnt1, tag="GAME") #'[e]μ’…λ£Œ λ¬Έμžμ—΄ ν‘œμ‹œ'
            index = 1 # index κ°’ 1둜 λ³€κ²½
            timer = 0 # timer κ°’ 0으둜 λ³€κ²½

    if index == 1: # index 1 처리 (κ²Œμž„ 쀑 ν™”λ©΄)
        if key == "e": # E ν‚€λ₯Ό λˆŒλ €μ„ λ•Œ
            canvas.delete("GAME") # 'κ²Œμž„ 쀑' λ¬Έμžμ—΄ μ‚­μ œ
            canvas.create_rectangle(0, 0, 600, 400, fill = "maroon", tag="OVER") # μΊ”λ²„μŠ€ κ°ˆμƒ‰μœΌλ‘œ 칠함
            canvas.create_text(300, 150, text = "GAME OVER", fill = "red", font=fnt2, tag="OVER") # 'game over'λ¬Έμžμ—΄ ν‘œμ‹œ
            index = 2 # index κ°’ 2둜 λ³€κ²½
            timer = 0 # timer κ°’ 0으둜 λ³€κ²½

    if index == 2: # index 2 처리 (κ²Œμž„ μ˜€λ²„ ν™”λ©΄)
        if timer == 30: # timer 값이 30이 됐닀면
            canvas.delete("OVER") # 'game over'λ¬Έμžμ—΄ μ‚­μ œ
            index = 0 # index κ°’ 0으둜 λ³€κ²½
            timer = 0 # timer κ°’ 0으둜 λ³€κ²½

    root.after(100, main) # 100λ°€λ¦¬μ΄ˆ 이후 λ‹€μ‹œ main()ν•¨μˆ˜ μ‹€ν–‰

root = tkinter.Tk() # μœˆλ„μš° 객체 생성
root.title("μΈλ±μŠ€μ™€ 타이머") # μœˆλ„μš° 타이틀 μ§€μ •
root.bind("<KeyPress>", key_down) # ν‚€λ₯Ό λˆŒλ €μ„ λ•Œ main()ν•¨μˆ˜ λ‹€μ‹œ μ‹€ν–‰
canvas = tkinter.Canvas(width = 600, height = 400, bg = "black") # μΊ”λ²„μŠ€ μ»΄ν¬λ„ŒνŠΈ 생성
canvas.pack() # μΊ”λ²„μŠ€ 배치
main() # 메인 처리 μ‹€ν–‰
root.mainloop() # μœˆλ„μš° ν‘œμ‹œ

 

κ²Œμž„ μ˜€λ²„ ν™”λ©΄μ—μ„œ timer = 30 (3초)이 되면 νƒ€μ΄ν‹€λ‘œ λ˜λŒμ•„κ°„λ‹€. 타이틀 -> κ²Œμž„ -> κ²Œμž„ κ²°κ³Ό -> 타이틀

 

  μ „λ°˜μ μœΌλ‘œ 이 ν”„λ‘œκ·Έλž¨μ€ index, timer 이 λ‘κ°œμ˜ λ³€μˆ˜λ‘œ μ§„ν–‰λœλ‹€.

  main() ν•¨μˆ˜μ—μ„œ after() λͺ…령을 μ΄μš©ν•΄ 100msλ§ˆλ‹€ 계속 μ‹€ν–‰μ‹œν‚€λŠ”λ°, μ΄λŠ” timer = timer + 1 을 계속 λ°˜λ³΅μ‹œν‚€λ©΄μ„œ timer 값을 μ¦κ°€μ‹œν‚€κ²Œ λœλ‹€. 

  타이틀 ν™”λ©΄μ—μ„œλŠ” if ꡬ문으둜 슀페이슀 ν‚€λ₯Ό λˆŒλ €μ„ λ•Œ indexλ₯Ό 1둜 λ³€κ²½ν•΄ κ²Œμž„ ν”Œλ ˆμ΄ ν™”λ©΄μœΌλ‘œ μ΄λ™μ‹œν‚€κ³ , κ²Œμž„ ν”Œλ ˆμ΄ ν™”λ©΄μ—μ„œλŠ” if ꡬ문으둜 eν‚€λ₯Ό λˆŒλ €μ„ λ•Œ indexλ₯Ό 2둜 λ³€κ²½ν•΄ κ²Œμž„ μ˜€λ²„ ν™”λ©΄μœΌλ‘œ μ΄λ™μ‹œν‚¨λ‹€. κ²Œμž„ μ˜€λ²„ ν™”λ©΄μ—μ„œλŠ” timer = 30일 λ•Œ index = 0으둜 λ³€κ²½ν•΄ 타이틀 ν™”λ©΄μœΌλ‘œ λŒμ•„κ°„λ‹€. 

  책에 덧뢙여진 μ„€λͺ…μ—μ„œλŠ”... ν”„λ ˆμž„ 레이트(frame rate)λŠ” 1μ΄ˆλ§ˆλ‹€ 화면을 λ‹€μ‹œ κ·Έλ¦¬λŠ” 횟수둜, 이 ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” 0.1μ΄ˆλ§ˆλ‹€ μ²˜λ¦¬λ˜λ―€λ‘œ ν”„λ ˆμž„ λ ˆμ΄νŠΈκ°€ 10이닀.

 

 

5. μž₯μ• λ¬Ό ν”Όν•˜κΈ° κ²Œμž„ λ§Œλ“€κΈ°

 

import tkinter
import random

fnt1 = ("Times New Roman", 24)
fnt2 = ("Times New Roman", 50)
index = 0
timer = 0
score = 0
bg_pos = 0 # λ°°κ²½ ν‘œμ‹œ μœ„μΉ˜ λ³€μˆ˜
px = 240 # ν”Œλ ˆμ΄μ–΄(μš°μ£Όμ„ ) Xμ’Œν‘œ λ³€μˆ˜
py = 540 # ν”Œλ ˆμ΄μ–΄(μš°μ£Όμ„ ) Yμ’Œν‘œ λ³€μˆ˜
METEO_MAX = 30 # μœ μ„± 수
mx = [0] * METEO_MAX # μœ μ„± Xμ’Œν‘œ 관리 리슀트
my = [0] * METEO_MAX # μœ μ„± Yμ’Œν‘œ 관리 리슀트

key = "" # ν‚€ κ°’ λŒ€μž… λ³€μˆ˜
koff = False # ν‚€λ₯Ό λˆŒλ €λ‹€ 뗐을 λ•Œ μ‚¬μš©ν•  λ³€μˆ˜(ν”Œλž˜κ·Έ)

def key_down(e): # ν‚€λ₯Ό λˆŒλ €μ„ λ•Œ μ‚¬μš©ν•  ν•¨μˆ˜
    global key, koff 
    key = e.keysym # key에 keysym κ°’ λŒ€μž…
    # keysym : ν‚€λ³΄νŠΈ μ΄λ²€νŠΈμ—μ„œ λ°œμƒν•˜λŠ” ν‚€μ˜ 심볼λͺ…
    koff = False # koff에 False λŒ€μž…
    
def key_up(e): # ν‚€λ₯Ό λˆŒλ €λ‹€ 뗐을 λ•Œ μ‹€ν–‰ν•  ν•¨μˆ˜
    global koff
    koff = True 

def main(): # 메인 처리 μˆ˜ν–‰ ν•¨μˆ˜
    global key, koff, index, timer, score, bg_pos, px 
    timer = timer + 1 
    bg_pos = (bg_pos + 1) % 640 # 배경을 그릴 μœ„μΉ˜ 계산
    canvas.delete("SCREEN") # ν™”λ©΄ μƒμ˜ λͺ¨λ“  κ·Έλ¦Όκ³Ό λ¬Έμžμ—΄ μ‚­μ œ ν›„ 
    # λ°°κ²½ 우주 이미지 그리기
    canvas.create_image(240, bg_pos - 320, image=img_bg, tag="SCREEN")
    canvas.create_image(240, bg_pos + 320, image=img_bg, tag="SCREEN")
    
    if index == 0: # index 0 처리 (타이틀 ν™”λ©΄)
        canvas.create_text(240, 240, text="METEOR", fill="gold", font=fnt2, tag="SCREEN") # 타이틀 λ¬Έμžμ—΄ ν‘œμ‹œ
        canvas.create_text(240, 480, text="Press [SPACE] Key", fill="lime", font=fnt1, tag="SCREEN") # 'press[space]key' λ¬Έμžμ—΄ ν‘œμ‹œ
        if key == "space": # 슀페이슀 ν‚€λ₯Ό λˆŒλ €μ„ λ•Œ
            score = 0 
            px = 240 # μš°μ£Όμ„  μœ„μΉ˜λ₯Ό ν™”λ©΄ μ€‘μ•™μœΌλ‘œ μ§€μ •
            init_enemy() # μœ μ„± μ’Œν‘œ μ΄ˆκΈ°κ°’ λŒ€μž…
            index = 1 # index κ°’ 1둜 λ³€κ²½
            
    if index == 1: # index 1 처리(ν”Œλ ˆμ΄ 쀑 ν™”λ©΄)
        score = score + 1 # score 증가
        move_player() # μš°μ£Όμ„  이동
        move_enemy() # μœ μ„± 이동
        
    if index == 2: # index 2 처리 (κ²Œμž„ μ˜€λ²„ ν™”λ©΄)
        move_enemy() # μœ μ„± 이동
        canvas.create_text(240, timer * 4, text="GAME OVER", fill="red", font=fnt2, tag="SCREEN") # 'game over' λ¬Έμžμ—΄ ν‘œμ‹œ
        if timer == 60: # timer 값이 60일 λ•Œ
            index = 0
            timer = 0
            
    canvas.create_text(240, 30, text="SCORE " + str(score), fill="white", font=fnt1, tag="SCREEN") # score ν‘œμ‹œ
    if koff == True: # koffκ°€ True일 λ•Œ
        key = "" # key κ°’ 클리어
        koff = False 
    root.after(50, main) # 50ms ν›„ λ‹€μ‹œ main() ν•¨μˆ˜ μ‹€ν–‰

def hit_check(x1, y1, x2, y2): # 히트 체크 μˆ˜ν–‰ ν•¨μˆ˜
    if ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) < 36 * 36): # 두 점 μ‚¬μ΄μ˜ 거리 νŒμ •, 36ν”½μ…€ 미만일 λ•Œ
        return True 
    return False

def init_enemy(): # μœ μ„± μ’Œν‘œμ˜ 초기 μœ„μΉ˜ μ§€μ • ν•¨μˆ˜
    for i in range(METEO_MAX): # xμ’Œν‘œμ™€ yμ’Œν‘œλ₯Ό λ‚œμˆ˜λ‘œ κ²°μ •ν•˜λŠ” 것을 계속 반볡
        mx[i] = random.randint(0, 480) 
        my[i] = random.randint(-640, 0)

def move_enemy(): # μœ μ„± 이동 ν•¨μˆ˜
    global index, timer
    for i in range(METEO_MAX): 
        my[i] = my[i] + 6 + i / 5 # μœ μ„± y μ’Œν‘œ μ—…λ°μ΄νŠΈ
        if my[i] > 660: # y μ’Œν‘œκ°€ 660 초과일 λ•Œ x, yμ’Œν‘œλ₯Ό λ‚œμˆ˜λ‘œ κ²°μ •
            mx[i] = random.randint(0, 480) 
            my[i] = random.randint(-640, 0)
        if index == 1 and hit_check(px, py, mx[i], my[i]) == True: # κ²Œμž„ 쀑 μš°μ£Όμ„ κ³Ό μ ‘μ΄‰ν–ˆμ„ λ•Œ
            index = 2 # index κ°’ 2둜 λ³€κ²½
            timer = 0 # timer κ°’ 0으둜 λ³€κ²½
        canvas.create_image(mx[i], my[i], image=img_enemy, tag="SCREEN") # μœ μ„± 그리기

def move_player(): # μš°μ£Όμ„  이동 ν•¨μˆ˜
    global px 
    if key == "Left" and px > 30: # μ™Όμͺ½ ν‚€λ₯Ό λˆ„λ₯Έ μƒνƒœμ—μ„œ px>30일 λ•Œ
        px = px - 10 # px(xμ’Œν‘œ) 10 κ°μ†Œ
    if key == "Right" and px < 450: # 였λ₯Έμͺ½ ν‚€λ₯Ό λˆ„λ₯Έ μƒνƒœμ—μ„œ px<450일 λ•Œ
        px = px + 10 # px(xμ’Œν‘œ) 10 wmdrk
    canvas.create_image(px, py, image=img_player[timer % 2], tag="SCREEN") # μš°μ£Όμ„  그리기

root = tkinter.Tk() 
root.title("Mini Game")
root.bind("<KeyPress>", key_down) # ν‚€λ₯Ό λˆŒλ €μ„ λ•Œ μ‹€ν–‰ν•  ν•¨μˆ˜ μ§€μ •
root.bind("<KeyRelease>", key_up) # ν‚€λ₯Ό λˆŒλ €λ‹€ 뗐을 λ•Œ μ‹€ν–‰ν•  ν•¨μˆ˜ μ§€μ •
canvas = tkinter.Canvas(width=480, height=640) # μΊ”λ²„μŠ€ μ»΄ν¬λ„ŒνŠΈ 생성 
canvas.pack() # μΊ”λ²„μŠ€λ₯Ό μœˆλ„μš°μ— λΉ„μΉ˜
img_player = [ # λ¦¬μŠ€νŠΈμ— μš°μ£Όμ„  이미지 λ‘œλ”©(μ• λ‹ˆλ©”μ΄μ…˜μš©)
    tkinter.PhotoImage(file="starship0.png"),
    tkinter.PhotoImage(file="starship1.png")
]
img_enemy = tkinter.PhotoImage(file="meteo.png") # μœ μ„± 이미지 λ‘œλ”©
img_bg = tkinter.PhotoImage(file="cosmo.png") # λ°°κ²½ 이미지 λ‘œλ”©
main() # 메인 처리 μ‹€ν–‰
root.mainloop() # μœˆλ„μš° ν‘œμ‹œ

 

game over 슀으으윽 λ‚΄λ €μ˜€λŠ”κ±° μ—΄λ°›λŠ”λ‹€..γ…œ

 

μ“°λ‹€κ°€ μ’€ λ©˜λΆ•μ˜¬λ»” ν–ˆλ‹€... 이런 ν”„λ‘œκ·Έλž¨μ€ μ§€κΈˆ μƒνƒœμ—μ„œλŠ” μ ˆλŒ€ λͺ»λ§Œλ“€ 것 κ°™μ•„μ„œ.. γ…  μ‘Έμž‘ 주제 잘λͺ» μ‹ μ²­ν–ˆλ‹€ μ‹Άλ‹€.... 심지어 μ½”λ“œλ„ μ„€λͺ… 주석 μ“°λ©΄μ„œλ„ 잘 이해 λͺ»ν•œ 뢀뢄이 μžˆλ‹€.. ν˜„νƒ€ μ‹¬ν•˜κ²Œ μ˜€λŠ” 쀑..γ…  

 

1) λ³€μˆ˜μ™€ 리슀트

  • index, timer : μΈλ±μŠ€μ™€ 타이머, κ²Œμž„ μ§„ν–‰ 관리 λ³€μˆ˜
  • score : 점수 λ³€μˆ˜
  • bg_pos : λ°°κ²½ μŠ€ν¬λ‘€μ„ μœ„ν•œ μ’Œν‘œ λ³€μˆ˜
  • px, py : μš°μ£Όμ„  μ’Œν‘œ λ³€μˆ˜ 
  • METEO_MAX : 화면에 흐λ₯΄λŠ” μœ μ„± 수 (ν•œ 번 30으둜 μ •μ˜ν–ˆκ³  λ³€κ²½ν•˜μ§€ μ•ŠλŠ” κ°’μœΌλ‘œ, 이λ₯Ό μƒμˆ˜λ‘œ λΆ€λ₯΄κ³  μƒμˆ˜λŠ” λͺ¨λ‘ λŒ€λ¬Έμžλ‘œ ν‘œμ‹œν•΄μ•Ό ν•œλ‹€κ³  ν•œλ‹€.)
  • mx[], my[] : μœ μ„± μ’Œν‘œ

2) indexκ°’

  • 0 : 타이틀 ν™”λ©΄ / 슀페이슀 ν‚€λ₯Ό λˆ„λ₯΄λ©΄ 각 λ³€μˆ˜λ₯Ό μ΄ˆκΈ°ν™”ν•˜κ³  index 1둜 이동
  • 1 : κ²Œμž„ ν”Œλ ˆμ΄ 쀑 ν™”λ©΄ / μš°μ£Όμ„  이동, μœ μ„± 처리 μˆ˜ν–‰, μœ μ„± 처리 쀑 μš°μ£Όμ„ κ³Ό μ ‘μ΄‰ν•˜λ©΄ index 2둜 이동
  • 2 : κ²Œμž„ μ˜€λ²„ ν™”λ©΄ / 3초 λŒ€κΈ° ν›„ index 0으둜 이동

 

그리고 계속 이해λ₯Ό λͺ»ν•˜κ³  μžˆλŠ” 뢀뢄이 μžˆλŠ”λ°, 

if index == 2:
    move_enemy()
    canvas.create_text(240, timer * 4, text="GAME OVER", fill="red", font=fnt2, tag="SCREEN")
    if timer == 60:
        index = 0
        timer = 0

index == 2(κ²Œμž„ μ˜€λ²„ ν™”λ©΄)일 λ•Œ, timerκ°€ 60이면 타이틀 ν™”λ©΄μœΌλ‘œ λ˜λŒμ•„κ°€λŠ”λ° μ™œ μ—¬κΈ°μ„œ timer = 60이 λΆ„λͺ…ν•œλ° μ™œ 3초 λ’€λ©΄ 타이틀 ν™”λ©΄μœΌλ‘œ λŒμ•„κ°€λŠ”κ±ΈκΉŒ?

λ°”λ‘œ μ „ μ˜ˆμ œμ—μ„œλŠ” timer == 30일 λ•Œ (3초 λ’€) 타이틀 ν™”λ©΄μœΌλ‘œ λŒμ•„μ˜¨λ‹€κ³  ν–ˆμ—ˆλ‹€. 근데 μ—¬κΈ°μ„œλŠ” timer == 60인데도 3초 뒀에 타이틀 ν™”λ©΄μœΌλ‘œ λŒμ•„κ°€λŠ” 걸까... 이건 λ„ˆλ¬΄ λͺ¨λ₯΄κ² μ–΄μ„œ 일단 냅둬야겠닀.

 

 

3) ν•¨μˆ˜

  • key_down(e) : ν‚€λ₯Ό λˆŒλ €μ„ λ•Œ μ‹€ν–‰
  • key_up(e) : ν‚€λ₯Ό λˆŒλ €λ‹€ 뗐을 λ•Œ μ‹€ν–‰
  • main() : 메인 처리 μˆ˜ν–‰
  • hit_check(x1, y1, x2, y2) : 두 점 사이 거리둜 히트 체크 μˆ˜ν–‰
  • init_enemy() : μœ μ„± μ’Œν‘œ μ΄ˆκΈ°ν™”
  • move_enemy() : μœ μ„± 이동
  • move_player() : μš°μ£Όμ„  이동

 

my[i] = my[i] + 6 + i / 5

move_enemy() ν•¨μˆ˜ λ‚΄ 이 μ½”λ“œλŠ” μ’Œν‘œλ₯Ό 계속 λ³€ν™”μ‹œμΌœ μœ μ„±λ§ˆλ‹€ 속도도 λ‹¬λΌμ§€κ²Œ ν•œλ‹€. 

 

if index == 1 and hit_check(px, py, mx[i], my[i]) == True:
    index = 2

그리고 이 λΆ€λΆ„μ—μ„œλŠ” 히트 체크λ₯Ό μˆ˜ν–‰ν•΄ μœ μ„±κ³Ό μš°μ£Όμ„ μ΄ μ ‘μ΄‰ν•˜λ©΄ index = 2λ₯Ό μˆ˜ν–‰ν•΄ κ²Œμž„ μ˜€λ²„ 처리둜 μ΄λ™ν•œλ‹€.

 

 

def hit_check(x1, y1, x2, y2):
    if ((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) < 36 * 36):
        return True
    return False

히트 체크 ν•¨μˆ˜μ—μ„œλŠ” μ € μœ„ μ˜ˆμ œμ™€ 달리 sqrt() λͺ…령을 μ΄μš©ν•˜μ§€ μ•Šμ•˜λŠ”λ°, μš°λ³€μ— 36이 μ•„λ‹Œ 36의 μ œκ³±μ„ λ„£μŒμœΌλ‘œμ¨ 루트λ₯Ό μ œκ±°ν•  수 μžˆλ‹€. μ˜›λ‚  ν”„λ‘œκ·Έλž˜λ¨Έλ“€μ€ 이와 같이 ꡳ이 루트λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ•„λ„ 될 λ•ŒλŠ” 더 λΉ λ₯΄κ³  μΎŒμ ν•œ 처리λ₯Ό μœ„ν•΄ sqrt() λͺ…령을 μ‚¬μš©ν•˜μ§€ μ•Šμ•˜λ‹€κ³  ν•œλ‹€.... 

 

 

4) λ§₯μ—μ„œμ˜ ν‚€ μž…λ ₯

  λ§₯μ—μ„œλŠ” after() λͺ…령을 μ‚¬μš©ν•œ μ‹€μ‹œκ°„ 처리 ν”„λ‘œκ·Έλž¨μ—μ„œ ν‚€ μž…λ ₯을 ν•  수 μ—†λŠ” κ²½μš°κ°€ μžˆλ‹€κ³  ν•œλ‹€. λ§₯μ—μ„œλŠ” ν‚€λ₯Ό λˆŒλ €μ„ λ•Œ <KeyPress> μ΄λ²€νŠΈμ™€ <KeyRelease> μ΄λ²€νŠΈκ°€ 연속 λ°œμƒν•΄ 처리 타이밍에 따라 ν‚€ 값을 λͺ»μ–»μ–΄μ„œ 라고 ν•˜λŠ”λ° koffκ°€ λŒ€μ²΄ λ­”κ°€ λ­”κ°€ ν–ˆλ”λ‹ˆ μ—¬κΈ°μ„œ μ“°μ΄λŠ” κ±°μ˜€λ‹€.

 

key = ""
koff = False

def key_down(e):
    global key, koff
    key = e.keysym
    koff = False
def key_up(e):
    global koff
    koff = True
if koff == True:
    key = ""
    koff = False

  koff λΌλŠ” ν”Œλž˜κ·Έλ₯Ό μ΄μš©ν•΄ <KeyRelease> 이벀트 λ°œμƒ μ‹œ koff에 Trueλ₯Ό λŒ€μž…ν•΄ ν”Œλ ˆμ΄μ–΄ 캐릭터λ₯Ό μ΄λ™ν•œ ν›„ koffκ°€ True 값이면 ν‚€ 값이 λ“€μ–΄ μžˆλŠ” λ³€μˆ˜λ₯Ό ν΄λ¦¬μ–΄ν•΄μ„œ λ§₯μ—μ„œλ„ 아무렇지 μ•Šκ²Œ 잘 μ“Έ 수 μžˆλŠ” 것이라 ν•œλ‹€. 

  λ‹€λ§Œ μœˆλ„μš°μ¦ˆμ—μ„  없어도 λ˜λŠ” μ½”λ“œκ°€ μƒκΈ΄κ±°λ‹ˆ koffκ°€ 있으면 ν‚€ λ°˜μ‘μ΄ μ’€ λ‚˜λΉ μ§„λ‹€κ³  ν•œλ‹€....

 

 

5) λ‚œμ΄λ„ λ³€κ²½ν•˜κΈ°

  κ²Œμž„μ—μ„œλ„ 밸런슀 패치, λ‚œμ΄λ„ 쑰절 λ“± κ· ν˜•μ„ μž‘λŠ” 게 μ€‘μš”ν•œκ±΄ μ•Œκ³  μžˆλ‹€. 이 λ•Œ 이 ν”„λ‘œκ·Έλž¨μ—μ„œλŠ” METEO_MAX의 값을 λ³€κ²½ν•œλ‹€λ˜μ§€, move_enemy ν•¨μˆ˜μ˜ my[i] = my[i] + 6 + i / 5 λΆ€λΆ„μ˜ 계산식을 λ³€κ²½ν•΄ μœ μ„±μ˜ 속도도 λ³€κ²½ν•΄λ³Ό 수 μžˆλ‹€. 

 

 

'python' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

파이썬으둜 λ°°μš°λŠ” κ²Œμž„ 개발 μ‹€μ „νŽΈ chapter 1  (0) 2022.01.23