728x90
반응형
SMALL

아래 이미지 파일을 다운로드 & 소스와 같은 폴더에 복사후 실행하기 바랍니다.

arrow.png
0.32MB

 

protocol() 함수는 이벤트와 함수를 연결하는 기능을 하며 아래 코드에는 위도우 창 닫기 이벤트(WM_DELETE_WINDOW)와 on_closing() 함수를 연결하여, 윈도우 창을 닫을 때 on_closing() 함수를 호출합니다.

 

from tkinter import *


class StageCanvas:
    def __init__(self,window):
        self.window = window
        self.canvas=Canvas(self.window, bg ="white") # game scene canvas
        self.canvas.create_text(320,300,font="Times 15 italic bold",text="Backspace 키 메뉴로 돌아가기")
        self.canvas.create_text(320,360,font="Times 15 italic bold",text="Stage Scene")
        

    def display(self):
        pass

    def pack(self):
        self.canvas.pack(expand=True, fill=BOTH)

    def unpack(self):
        self.canvas.pack_forget()

    def keyReleaseHandler(self, event):
        if event.keycode == 8:
            return 0
        else:
            return -1

    def destroy(self):
        self.canvas.destroy()


class MenuCanvas:
    def __init__(self,window):
        self.window = window
        self.menu_idx = 0

        self.canvas=Canvas(self.window, bg ="white")# menu canvas

        self.canvas.create_text(320,360,font="Times 15 italic bold",text="Scene Change")
                
        self.canvas.create_text(320,160,font="Times 15 italic bold",text="Start")
        self.canvas.create_text(320,200,font="Times 15 italic bold",text="Option")
        self.canvas.create_text(320,240,font="Times 15 italic bold",text="Exit")


        self.arrowimg = PhotoImage(file="arrow.png").subsample(20)
        self.arrow = self.canvas.create_image(250,160, image = self.arrowimg,tags="arrow")


    def display(self):
        pass
        

    def pack(self):
        self.canvas.pack(expand=True, fill=BOTH)

    def unpack(self):
        self.canvas.pack_forget()


    def keyReleaseHandler(self, event):
        if event.keycode == 38 and self.menu_idx > 0: # up direction key
            self.menu_idx = self.menu_idx - 1
            self.canvas.move(self.arrow, 0, -40)
            return -1
        elif event.keycode == 40 and self.menu_idx < 2: # down direction key
            self.menu_idx = self.menu_idx + 1
            self.canvas.move(self.arrow, 0, 40)
            return -1
        elif event.keycode == 32:
            return self.menu_idx


    def destroy(self):
        self.canvas.destroy()




class SceneChange:
    def __init__(self):
        self.window = Tk()
        self.window.title("장면전환")
        self.window.geometry("640x480")

        self.window.protocol("WM_DELETE_WINDOW", self.on_closing)

        self.scene_idx = 0
        
        self.stage = StageCanvas(self.window)
        self.menu = MenuCanvas(self.window)
        self.menu.pack()


        self.canvas_list = []
        self.canvas_list.append(self.stage)
        self.canvas_list.append(self.stage)

        self.window.bind("<KeyPress>",self.keyPressHandler)
        self.window.bind("<KeyRelease>",self.keyReleaseHandler)

        while True:
            #
            #
            for canvas in self.canvas_list:
                canvas.display()


            self.window.after(33)
            self.window.update()

    def on_closing(self):
        for canvas in self.canvas_list:
            canvas.destroy()

        self.window.destroy()

    def keyReleaseHandler(self, event):

        result = -1

        if self.scene_idx == 0:
            result = self.menu.keyReleaseHandler(event)

        elif self.scene_idx == 1:
            result = self.stage.keyReleaseHandler(event)

        if self.scene_idx == 0 and result==0:
            self.scene_idx = 1
            self.menu.unpack()
            self.stage.pack()

        elif self.scene_idx==1 and result==0:
            self.scene_idx = 0
            self.menu.pack()#메뉴 canvas 나타남
            self.stage.unpack()# Main 장면 canvas 사라짐
                
    def keyPressHandler(self,event):
        print(event.keycode)


SceneChange()
728x90
반응형
LIST
728x90
반응형
SMALL

tkinter 를 이용하여 메뉴 만들기 코드 입니다.

아래 이미지파일을 다운로드받고 소스코드와 같은 폴더에서 복사하여 주세요

arrow.png
0.32MB

from tkinter import *

class Menu:
    def __init__(self):
        window = Tk()
        window.title("키보드 이벤트")
        window.geometry("640x480")
        self.menu_idx = 0
        self.canvas=Canvas(window, bg ="white")
        self.canvas.pack(expand=True, fill=BOTH)
        window.bind("<KeyPress>",self.keyPressHandler)
        window.bind("<KeyRelease>",self.keyReleaseHandler)
        self.canvas.create_text(320,360,font="Times 15 italic bold",text="Menu Example")
                
        self.canvas.create_text(320,160,font="Times 15 italic bold",text="Menu 1")
        self.canvas.create_text(320,200,font="Times 15 italic bold",text="Menu 2")
        self.canvas.create_text(320,240,font="Times 15 italic bold",text="Menu 3")

        self.menustr = "Menu selection: "
        self.menu_id = self.canvas.create_text(320,320,font="Times 15 italic bold",text=self.menustr)    


        self.arrowimg = PhotoImage(file="arrow.png").subsample(20)
        self.arrow = self.canvas.create_image(250,160, image = self.arrowimg,tags="arrow")
        while True:
            #
            #
            window.after(33)
            window.update()

    def keyReleaseHandler(self, event):
        if event.keycode == 38 and self.menu_idx > 0: # up direction key
            self.menu_idx = self.menu_idx - 1
            self.canvas.move(self.arrow, 0, -40)
        if event.keycode == 40 and self.menu_idx < 2: # down direction key
            self.menu_idx = self.menu_idx + 1
            self.canvas.move(self.arrow, 0, 40)
        if event.keycode == 32:
            self.menustr = "Menu selection: " + str(self.menu_idx)
            self.canvas.itemconfigure(self.menu_id, text=self.menustr)#object 속성 수정

    def keyPressHandler(self,event):
        print(event.keycode)


Menu()

게임 사운드 코드

 

게임 사운드

from tkinter import * import pygame class GameSound: def __init__(self): window = Tk() # 윈도우 생성 window.title("게임사운드") # 제목을 설정 window.geometry("640x480") # 윈도우 크기 설정 window.resizable(0,0) self.canvas = Canvas(win

ckang.tistory.com

네트워크 채팅 코드

 

파이썬 네트워크 통신 채팅 프로그램 서버 클라이언트 예제

# 서버코드import socketimport argparseimport threadingimport timeuser_list = {}def handle_receive(client_socket, addr, user): while 1: data = client_socket.recv(1024) data = data.decode() if data == "/종료" or data == "/exit" : break print(user,data)

ckang.tistory.com

슈팅 게임 서버 클라인 언트 코드

 

파이썬 네트워크 게임 서버 클라이언트 (socket, ast, json, threading)

클라이언트 코드 입니다. from tkinter import * # tkinter에서 모든 정의를 임포트한다.import timeimport pygameimport randomimport timeimport socketimport astimport jsonimport threadingclass GameClient: def __init__(self,user,host,port):

ckang.tistory.com

 

728x90
반응형
LIST
728x90
반응형
SMALL
from tkinter import *

class BasicForm:
    def __init__(self):
        window = Tk()
        window.title("기본폼")
        window.geometry("640x480")
        
        self.canvas=Canvas(window, bg ="white")
        self.canvas.pack(expand=True, fill=BOTH)

        self.canvas.create_text(320,440,font="Times 15 italic bold",text="Basic Form")
        
        while True:
            #
            window.after(33)
            window.update()


BasicForm()

위 코드와 이후 공유되는 코드들은 파이썬에서 GUI 개발 모듈인 tkinter 를 이용한 게임 제작에 필요한 몇가지 기능들을 구현한 내용입니다.

코드에 대한 설명은 기초적인 파이썬 문법과 클래스에 대한 이해와 사용이 가능하다는 가정하에 작성을 하도록 하겠습니다.

-------------------------------------------------------------------------------------------------------

파이썬에서 tkinter 모듈을 이용하여 GUI 기반의 윈도우 프로그래밍을 할 수 있다. tkinter 에서 가장 기본 단위를 위젯이라고 하며 위젯의 종류에는 버튼(button), 라벨(label), 콤보박스(combobox), 캔버스(canvas) 등 이 있다. 게임을 위해서는 이미지를 이용한 애니메이션이 기본이되며 이와 같은 기능 구현은 캔버스에서 가능하다. 그러므로 작성된 코드에는 사운드를 제외한 대부분의 기능들을 캔버스만을 이용한다.

 

그림 1. 게임 코드 영역

게임을 만들때 일반적으로 코드는 3가지 영역(준비, 무한루프, 이벤트처리)으로 구분되어 작성된다.

  1. 준비영역에서는 윈도우를 생성, 사운드 및 이미지 파일등의 리소스 파일 로딩, 그리고 게임에 필요한 변수들을 초기화하는 코드가 작성된다(line5 ~12). 
  2. 무한루프 영역에서는 게임이 실행되는 동안 변화되는 데이터, 이미지의 위치, 사운드 on / off 등에 대한 코드를 작성한다.(line 15~17)
  3. 마지막으로 이벤츠처리 영역에는 키 또는 마우스 입력이 있을 때 처리해야 될 코드(이미지 위치값 이동, 사운드 on/off등)를 작성한다.(위 예제코드에는 이벤트처리 영역이 미 작성됨)

준비영역은 최초 게임 코드가 시작될 시 한번만 실행되며, 무한루프 영역은 계속 반복해서 실행된다.(일반적으로 while 을 이용한 무한루프형식으로 작성됨) 이벤트처리 영역은 키 또는 마우스 입력이 있을 시 실행되고 실행이 끝나면 다시 무한루프 영역의 코드가 실행되며, 이러한 방식을 Event-based Programming 방식이라고 한다. 무한루프 영역에서 키 또는 마우스 입력이 있을 시 바로 이벤트처리 영역으로 이동하는 것이 아닌 루프영역에서 마지막 코드인 window.update() 함수 호출시 이벤트처리 영역으로 이동하여 코드가 실행된다.

 

준비 영역과 무한루프 영역에 대한 코드 설명은 아래와 같다.

  • 윈도우 프로그래밍에서 가장 먼저 해야될 일은 윈도우 만들기다. Tk 클래스를 이용하여 윈도우 창을 생성할 수 있다.(line 5) 그리고 title, geometry 함수를 이용하여 윈도우 이름과 크기를 설정한다. (line 6~7)
  • 다음으로 캔버스 객체를 생성하는데, 생성시 캔버스가 붙여질 윈도우를 인수로 작성한다.(line 9) 윈도우 틀이 만들어지고 그 앞에 캔버스를 붙인 후 캔버스 위에 원하는 위치에 이미지를 그릴 수 있는 것이다.

그림 2. 윈도우, 캔버스, 이미지 레이어 구조

  • 윈도우도 하나의 위젯으로 생각할 수 있는데 위젯 간에 서로 붙이기 위해서는 붙일 대상 위젯 지정(line 9)과 실제 붙이는 동작이 있어야 되며 그 중에 하나가 pack() 이라는 함수이다.(line 10) 옵션은 윈도우에 꽉차게 그리기 위해 expand를 true 그리고 fill=BOTH로 설정하였다.
  • 캔버스는 도화지 처럼 무엇이든 그릴 수 있는 함수를 제공하고 있다. 그 함수들의 이름은 "create_"로 시작되며 create_rectangle, create_oval, create_line, create_text, create_image 등 그리는데 필요한 다양한 함수들을 이용할 수 있다. 위 코드에서는 create_text() 함수를 이용하여 "Basic Form" 글자를 320, 400 위치에 작성한다.

그림 3. canvas 클래스에서 사용되는 다양한 create 함수들

  • 캔버스에 무언가를 그리기 위해서는 기준좌표와 기준점이 어디 인지 알아야 된다. 아래 그림은 width: 640, hegiht: 480 크기로 그려진 윈도우의 좌표를 보여준다. 윈도우의 기준좌표는 왼쪽 위가 되며 0, 0 의 좌표값을 가진다. 그리고 그려지는 글자는 글자크기의 가운데 위치가 기준점이 된다. 그래서 글자는 코드에서 작성된 320, 400 의 위치에 글자의 기준점이 맞춰서 그려지게 된다.

그림 4. 기준좌표와 기준점

  • 무한루프 영역에서는 윈도우 클래스의 after()와 update() 함수가 호출된다(line 16, 17). after() 에는 33 이 작성되어 있으며 33은 대기 시간(단위: ms) 나타낸다. 위 코드에서는 게임영상을 초당 30 프레임로 동작하게 하기위해 33 을 작성하였다. 마지막으로 update() 함수 호출시 변화된 내용의 반영과 앞서 설명된 키 또는 마우스 이벤트들이 처리된다.
  • 무한루프 영역에서 이미지의 위치 변경 코드가 작성되어 있으면 그 코드가 호출된 시점에서 바로 이미지의 위치변경이 되는 것은 아니다. 이미지의 위치변경 코드가 많을 경우 코드마다 바로 위치변경하여 화면에 보여주게 되면 컴퓨터가 많은 부하가 발생할 수 있다. 그렇게 때문에 변화된 내용들을 모아서 특정 시간 마다 한번에 처리하면 부하를 줄일 수 있다. 모든 게임에서 그래픽 애니메이션은 이러한 방식으로 처리됨을 명심하기 바란다.

앞서 설명된 내용들은 다른 프로그래밍 언어(c++, java, visual basic등)로 게임을 제작할 때도 동일한 영역과 동작방식을 가지고 있어서 위 내용들을 이해하면 다른 프로그래밍 언어를 이용한 게임제작도 쉽게 할 수 있다. 모든 게임 개발 및 동작을 위한 코드 구조가 위와 동일하다고 생각하면된다(Unity, UnReal Engine 역시 기본구조는 동일함).

이상으로 게임 기본구조에 대한 설명 끝~~!

 

코드 실행결과

728x90
반응형
LIST

+ Recent posts