Python - 피하기 게임(개인 프로젝트)

2022. 6. 8. 19:08·Python/개인 공부

학기 끝나기전에 공부한걸로 뭐라도 해보고싶어서 파이썬으로 게임을 짜봤다.

학기끝날때 공모전도 한다고하니 제출해볼 예정..

쓰레드 구현방법을 알았다면 더 쉽게 만들었을텐데 아직 쓰레드를 잘 몰라 after메소드를 사용해서 구현했다.

그냥 의식의 흐름대로 코딩해서 에러가 엄청많이 나온다. ㅜ

나중에 수정할 예정이고

코드설명은 나중에 따로 포스팅 하겠음

실행모습(좌측 상단에 버틴시간)
적과 충돌하면 종료창

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
from tkinter import*
import random #적 랜덤생성 하려고
from datetime import datetime #경과시간 구하려고(pip로 datetime패키지 설치하였음)
 
window=Tk()
window.title("Game") 
window.geometry("400x400") #크기(400x400)
window.resizable(0, 0) #게임창 크기 변경 불가능!
 
canvas=Canvas(window, width=400, height=400, bg="black", bd=0, highlightthickness=0) #게임창 생성
canvas.pack()
 
player=canvas.create_rectangle(190, 290, 210, 310, fill="white") #플레이어 생성
text=canvas.create_text(30, 10, text="Start!!!", fill="white") #start!!! 문구만 나옴(별다른 의미x)
score=canvas.create_text(80, 10, text="score : ", fill="white") #점수표시, 버틴시간만큼 점수
 
keyInput="" #키 값 초기화
 
#<플레이어 움직임>
def player_move():
    window.bind("<KeyPress>", key_Press) #bind함수 키 입력 받음, (이벤트, 함수)
    window.bind("<KeyRelease>", key_Release)
 
    global player_position #전역으로 선언 -> 다른 함수에서도 이용해야함
    player_position=canvas.coords(player) #플레이어 위치 좌표로 반환(리스트 형식) [x1, y1, x2, y2]
 
    if keyInput=="Up" and (player_position[1]>=0): #캔버스 밖으로 안나가게 함, 벽에 닿으면 and조건 만족못해서 못움직임
        canvas.move(player, 0, -5) #y축으로 -5만큼 이동(canvas에서는 밑으로가면 y+임)
    if keyInput=="Down" and (player_position[3]<=400):
        canvas.move(player, 0, 5)                                      
    if keyInput=="Right" and (player_position[2]<=400): 
        canvas.move(player, 5, 0)                     
    if keyInput=="Left" and (player_position[0]>=0):
        canvas.move(player, -5, 0)
    window.after(10, player_move) #0.01초마다 입력받음 5픽셀씩 움직임(속도 조절 가능)
 
def key_Press(e): #키 프레스 함수
    global keyInput #전역변수 keyInput을 사용하기 위함 global로 선언
    keyInput=e.keysym #keysym을 이용해서 누른 키가 뭔지 알아냄
 
def key_Release(e): #키 릴리즈 함수
    global keyInput
    keyInput="" #눌렀던 키를 떼면 키값이 초기화 된다.
     
#<적 오브젝트 클래스>
class enemy_objects: #적이 여러개가 생성되야하기 때문에 클래스로 객체 계속 생성하기로 함
    def __init__(self, posx1): #생성자, 생성되는 x1좌표만 알면 사각형 생성가능
        self.posx1=posx1
        self.posy1=0
        self.p1=(self.posx1, self.posy1)
        self.posx2=self.posx1+10
        self.posy2=10
        self.p2=(self.posx2, self.posy2)
        self.enemy=canvas.create_rectangle(self.p1, self.p2, fill="blue")
 
    def enemy_move(self): #움직임 관여
        self.enemy_position=canvas.coords(self.enemy) #coords는 좌표를 리스트 형식으로 반환 [x1, y1, x2, y2]
        canvas.move(self.enemy, 0, 3)
 
        if(self.enemy_position[3]>=400): #끝에 닿으면 적(그 객체) 지운다
            canvas.delete(self.enemy)
        window.after(5, self.enemy_move) #0.005초마다 3픽셀씩 움직인다(적 움직임 속도 조절 가능)
    
    def enemy_collision(self): #충돌 관여, 충돌 시 게임종료(적의 좌표와 플레이어 좌표가 겹치면 충돌했다고 판단)
        if(self.enemy_position[2]>=player_position[0] and self.enemy_position[2]<player_position[2] and self.enemy_position[0]<player_position[0] and self.enemy_position[3]>=player_position[1] and self.enemy_position[1]<player_position[1]):
            end_sign() #충돌하면 종료함수 호출
        elif(self.enemy_position[0]>=player_position[0] and self.enemy_position[0]<player_position[2] and self.enemy_position[2]>player_position[0] and self.enemy_position[2]<=player_position[2] and self.enemy_position[3]>=player_position[1] and self.enemy_position[1]<player_position[1]):
            end_sign()
        elif(self.enemy_position[2]>player_position[2] and self.enemy_position[0]>player_position[0] and self.enemy_position[0]<=player_position[2] and self.enemy_position[3]>=player_position[1] and self.enemy_position[1]<player_position[1]):
            end_sign()
        window.after(10, self.enemy_collision) #0.01초마다 충돌검사
 
#<3단계-적 생성기>
def enemy_generator_level3():
    enemy=enemy_objects(random.choice(range(391))) #랜덤한 위치에서 적 객체를 생성
    enemy.enemy_move() #생성된 객체의 움직임 함수 호출
    enemy.enemy_collision() #생성된 객체의 출동함수 호출
 
    if(enemy.enemy_position[3]>=400): #y2가 땅에 닿으면
        del enemy #밑으로 끝까지가면 객체삭제
    
    window.update() #여러번의 테스트 결과, update()함수를 남발하면 여러개의 함수에서 update함수를 계속해서 쓰기때문에 렉 걸리는듯.
                    #때문에 여기서만 update함수를 써서 렉 안걸리게함. 0.1초마다 update해도 게임에 지장있는 수준은 아님.
 
    window.after(100, enemy_generator_level3) #0.1초마다 enemy객체를 만든다
 
#<시간 점수 계산>
def score_time():
    global t_delta #end_sign함수에서 사용하기 위해서 전역으로 선언
    t_0=datetime.now() #시작한 시각
    score_text=canvas.create_text(110, 10, text=0, fill="white") #시간초 표시
 
    while True: #이곳은 그냥 while문으로 돌려도 다른곳에선 after함수때문에 스레드 따로돌리게됨 상관없음
        canvas.delete(score_text) #시간초 지움(지웠다가 다시 쓰고 반복함)
        t_now=datetime.now() #while돌렸기 때문에 현재시각이 계속 바뀜
        t_delta=round((t_now-t_0).total_seconds()) #현재시각 - 시작한시각 = 버틴 시간초(delta_t)가 계산된다. round함수로 정수형으로 만들어줌
        score_text=canvas.create_text(110, 10, text=str(t_delta), fill="white") #지웠던 시간초를 다시 생성
        window.update()
 
#<충돌하면 게임 종료>
def end_sign():
    window.destroy() #원래있던 게임창 지움
    end=Tk() #새로운 창 생성(얼마만큼 버텼는지 나오는 새 창)
    end.title("게임종료")
    end.geometry("230x120")
    end.resizable(0, 0)
 
    gameover=Label(end, text="-Game Over-")
    text=Label(end, text="버틴 시간")
    gamescore=Label(end, text=str(t_delta)) #버틴 시간초를 표시(delta_t)
 
    gameover.pack()
    text.pack()
    gamescore.pack()
    
    end.mainloop()
 
#<게임 실행>
player_move() #다른 작업을 동시에 수행해야하는데 아직 쓰레드, 멀티프로세싱 개념을 잘 몰라서 찾아본 결과
              #after메소드를 사용하게 된다면 독자적인 쓰레드를 구현해준다는걸 알았음
              #그리고 중간에 while문이 들어가게 되면 while문이 계속 도느라 다른 함수가 실행이안됨.
              #->그래서 score_time()에만 while문을 사용하고, score_time실행을 뒤에 시킨다면, 다른 함수들은 after메소드로 각각 작업을 수행하면서,
              # 마지막에 score_time에서는 while으로 시간이 계속 흘러가는것을 구현가능
enemy_generator_level3()
score_time() #while문때문에 제일 뒤에서 실행
 
window.mainloop()
Colored by Color Scripter
cs

'Python > 개인 공부' 카테고리의 다른 글

Python - 함수의 파라미터 여러개 일때(*args)  (0) 2022.06.21
Mac os - 터미널 명령어 정리(2022.06.20)  (0) 2022.06.20
Python - 소수 구하기  (0) 2022.06.13
Python - print문의 사용 (end, sep) (내가 헷갈려서..)  (0) 2022.06.10
'Python/개인 공부' 카테고리의 다른 글
  • Python - 함수의 파라미터 여러개 일때(*args)
  • Mac os - 터미널 명령어 정리(2022.06.20)
  • Python - 소수 구하기
  • Python - print문의 사용 (end, sep) (내가 헷갈려서..)
Jminu
Jminu
  • Jminu
    뇌 구조가 바이너리
    Jminu
  • 전체
    오늘
    어제
    • 분류 전체보기 N
      • C프로그래밍
        • 오류해결
        • 개인 공부
        • Programming Lab(학교수업)
        • MemoryTracker
      • C++
        • 개인 공부
      • 자료구조(Data Structure)
      • ARM arch N
        • Cortex-M N
        • FreeRTOS
      • 컴퓨터 공학(Computer Science)
        • OS
        • 컴퓨터 구조
      • Qualcomm 기업과제
      • Linux N
      • Web
      • 똥글
      • 백준
      • Git 학습
        • 오류해결
        • 학습중
      • Python
        • 오류해결
        • 개인 공부
  • 블로그 메뉴

    • 태그
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    파일 입출력
    exception vector table
    C++
    스택
    ptrace
    thumb2
    memory mapped io
    Git
    버퍼
    파이썬
    포인터
    commit
    자료구조
    과속탐지
    이진 트리
    백준
    Branch
    피보나치
    c언어
    yolo
    Qualcomm
    INIT
    커널
    rubikpi3
    동적메모리
    rubik pi
    arm
    순환
    소수
    aapcs
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
Jminu
Python - 피하기 게임(개인 프로젝트)
상단으로

티스토리툴바