728x90
학기 끝나기전에 공부한걸로 뭐라도 해보고싶어서 파이썬으로 게임을 짜봤다.
학기끝날때 공모전도 한다고하니 제출해볼 예정..
쓰레드 구현방법을 알았다면 더 쉽게 만들었을텐데 아직 쓰레드를 잘 몰라 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()
|
cs |
728x90
'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 |