diff --git a/README.md b/README.md index 07718fbb..e791b35c 100644 --- a/README.md +++ b/README.md @@ -14,3 +14,94 @@ You can also run Snake-Game in Gitpod, a free online dev environment for GitHub: If you're intersted in a paid subscription with GitPod use the coupon code: **TECHWITHTIM19** [![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](https://gitpod.io/#https://github.com/techwithtim/Snake-Game/blob/master/snake.py) + + + +------------------------------------------ + + + + +1. 게임 속도 조절 +기존에 빠르게 움직이던 뱀의 속도를 늦추고 5레벨씩 달성 시 +뱀의 속도를 전의 속도보다 1.5배 빨라지게 설정했습니다. + +pygame을 모듈내장함수 init함수로 초기화하고 +clock변수에 게임의 시간을 받았습니다. + +기존 코드 속 class snake 에 있는 move함수를 수정해 +level변수에 5단계 단위로 정수를 저장하고 +최초 속도를 6으로 하고 5단계 단위로 속도를 1.5배 해 fps 변수에 넣었습니다. +그리고 내장함수 tick 이용해 조절한 속도를 적용하였습니다. + + +2.최종 레벨 25로 달성 시 종료 +-class snake안에 end_game함수 생성, sys.exit(0)에 의해 게임 종료 +-기존 main함수에서 최종 레벨 25달성시, 게임을 종료하는 end_함수를 실행하는 코드 추가 + + +3. Tk()를 이용하여 window라는 윈도우를 생성하고 타이틀은 "NEW Snake Game"으로 정한다. window.geometry 명령어를 통해 사이즈 설정과 윈도우 창이 뜨는 위치를 설정해 주었습니다. +label1을 라벨 객체로 생성하고 “Game Start \n Let’s go”를 텍스트에 넣어 윈도우 창에 뜨웁니다. 글씨의 색상은 파란색으로 정했습니다. relief는 라벨의 테두리 모양을 저지정하는 함수로 “sunken”을 써서 오목하게 보여줬습니다. +b1을 버튼 객체로 생성하고 command=window.destroy 코드를 통해 window 윈도우창을 닫고 메인 보드 게임으로 들어갑니다. +라벨과 버튼 둘 다 pack()을 통해 윈도우창에 띄웠습니다. + + +4. 게임판에 레벨 출력 +메인 게임판 위에 뱀의 길이에 따른 레벨이 담긴 정보를 보여줍니다. + +기존 코드 속 class snake 에 show_info함수를 정의하였습니다. +font 변수로 폰트의 정보를 지정하고 +내장함수 render로 뱀의 길이에 따른 레벨을 출력합니다. +출력 내용을 게임보드의 위치를 왼쪽 상단으로 지정합니다. + +게임판을 출력하는 redrawWindow 함수에서 +스네이크 객체 s를 이용해 show_info를 호출합니다. + + +5. finish_game함수를 정의해줍니다. +fin 윈도우를 만들고 label2객체를 생성하여 “!! SUCCESS !!”를 출력해줍니다. +b2 객체를 생성하여 “끝내기”버튼을 생성하고 버튼을 클릭시 command = fin.destroy 코드를 통해 윈도우를 종료 시켜줍니다. + + +6. 메인 게임 보드 설정 조절 +메인 게임 보드 속 사소한 부분의 설정을 조절하였습니다. + +win.full으로 배경 색을 바꾸고 +게임보드의 크기를 500제곱에서 700제곱으로 변경합니다. +rows도 20 줄에서 25줄로 격자의 양을 늘립니다. +class cube 내의 설정을 위한 변수의 크기도 변경 시킵니다. +gird 의 라인 색상도 변경합니다. +늘어난 메인 게임 보드의 크기만큼 뱀이 보들를 벗어 날 시 +발생하는 충돌 reset에 대한 설정도 20에서 25로 넓힙니다. + + +7.종료시 게임 total time 출력 +- start_ticks객체는 main함수가 호출된 시점의 시작시간을 tick를 통해 받아옴(start_tick=고정값) +-while문 안에서 pygame이 호출된 이후 증가하며 흐르는 시간을 리턴하는 함수를 이용해 경과 시간을 구하기 위해 seconds객체 생성 +경과 시간 계산은 밀리세컨들 출력되므로 1000으로 나눠 1초로 표시 +-finish_game함수에서 게임이 종료되면 뜨는 윈도우창에 경과시간를 나타낸 객체 seconds를 출력 + + +8. 점수가 있는 큐브 생성 + +뱀과 충돌시 점수를 내는 변수 버그와 스낵을 선언하고 +메인 게임 보드에 정보를 출력합니다. + +랜덤큐브를 생성하는 bug를 main에서 선언합니다. + +if문을 이용해 스낵과 뱀의 머리가 충돌하면 +뱀의 바디를 늘리는 함수를 addcube를 객체 호출하고 +다음 레벨에서 다시 랜덤 큐브를 생성시킵니다. +그리고 score 변수에 점수를 +10으로 계산합니다. + +같은 방법으로 if문을 이용해 버그와 뱀의 머리가 충돌하면 +다음 레벨에서 랜덤큐브를 생성하고 점수를 -10으로 계산합니다. + +redrawWindow 안에서 호출한 show_info로 +계산한 점수를 게임 메인 모드에 출력합니다. + + +9. main 함수 안에 Sound 객체인 eatsnack, eatbug, gameoversound를 생성하여 +gameoversound는 뱀이 메인 게임보드 밖에 나갔을 때 play되도록 gameoversound.play()를 넣어줍니다.(243줄) +eatsnack 사운드는 뱀이 snack을 먹었을 때 나오도록 eatsnack.play()를 넣어줍니다.(248줄) +eatbug 사운드는 뱀이 bug를 먹었을 때 나오도록 eatbug.play()를 넣어줍니다.(256줄) diff --git a/gameover.wav b/gameover.wav new file mode 100644 index 00000000..c4ad4b44 Binary files /dev/null and b/gameover.wav differ diff --git a/grow.wav b/grow.wav new file mode 100644 index 00000000..18d61aa4 Binary files /dev/null and b/grow.wav differ diff --git a/shrink.wav b/shrink.wav new file mode 100644 index 00000000..42789091 Binary files /dev/null and b/shrink.wav differ diff --git a/snake.py b/snake.py index 14fd8c97..f8e24cee 100644 --- a/snake.py +++ b/snake.py @@ -3,36 +3,54 @@ import pygame import random import tkinter as tk -from tkinter import messagebox +from tkinter import * -width = 500 -height = 500 +width = 700 +height = 700 cols = 25 -rows = 20 +rows = 25 + +pygame.init() +clock = pygame.time.Clock() +background = pygame.display.set_mode((width, height)) + + +window=Tk() +window.title("NEW Snake Game") +window.geometry('300x120+470+200') + +label1=Label(window, text="Game Start\nLet's go",width=30,height=5,fg="blue",relief="sunken") +label1.pack() + +b1=Button(window,text="시작하기",width=10,bg='yellow',command = window.destroy) +b1.pack(padx = 10, pady = 5) + +window.mainloop() class cube(): - rows = 20 - w = 500 + rows = 25 + w = 700 def __init__(self, start, dirnx=1, dirny=0, color=(255,0,0)): self.pos = start self.dirnx = dirnx - self.dirny = dirny # "L", "R", "U", "D" + self.dirny = dirny self.color = color def move(self, dirnx, dirny): self.dirnx = dirnx self.dirny = dirny self.pos = (self.pos[0] + self.dirnx, self.pos[1] + self.dirny) - + def draw(self, surface, eyes=False): dis = self.w // self.rows i = self.pos[0] j = self.pos[1] - + pygame.draw.rect(surface, self.color, (i*dis+1,j*dis+1,dis-2,dis-2)) + if eyes: centre = dis//2 radius = 3 @@ -40,15 +58,14 @@ def draw(self, surface, eyes=False): circleMiddle2 = (i*dis + dis -radius*2, j*dis+8) pygame.draw.circle(surface, (0,0,0), circleMiddle, radius) pygame.draw.circle(surface, (0,0,0), circleMiddle2, radius) - + class snake(): body = [] turns = {} def __init__(self, color, pos): - #pos is given as coordinates on the grid ex (1,5) self.color = color self.head = cube(pos) self.body.append(self.head) @@ -88,7 +105,10 @@ def move(self): self.turns.pop(p) else: c.move(c.dirnx,c.dirny) - + + level = int(len(self.body) / 5) + fps = 6 + (1.5*level) + clock.tick(fps) def reset(self,pos): self.head = cube(pos) @@ -121,31 +141,58 @@ def draw(self, surface): else: c.draw(surface) + def end_game(): + print("Score:", len(self.body)) + sys.exit(0) + + + def show_info(self,score): + font = pygame.font.SysFont('malgungothic',30,bold=5) + image = font.render(f' {len(self.body)} .Lv 점수 : {score}', True, (0,0,0)) + pos = image.get_rect() + pos.move_ip(20,20) + pygame.draw.rect(image, (0,0,0),(pos.x-15, pos.y-15, pos.width, pos.height), 2) + background.blit(image, pos) + + +def finish_game(seconds): + fin=Tk() + fin.title("Full Level") + fin.geometry('400x150+500+200') + b=int(seconds) + print ("Total Time :", b) + label2=Label(fin, text="!! SUCCESS !!\nTotal Time :"+str(b),width=30,height=5,fg="red",relief="raised") + label2.pack() + + b2=Button(fin, text="끝내기",width=20,bg='yellow',command = fin.destroy) + b2.pack(padx = 10, pady = 20) + + fin.mainloop() def redrawWindow(): global win - win.fill((0,0,0)) + win.fill((176,224,230)) drawGrid(width, rows, win) s.draw(win) snack.draw(win) + bug.draw(win) + s.show_info(score) pygame.display.update() pass - - def drawGrid(w, rows, surface): - sizeBtwn = w // rows + sizeBtwn = w // rows x = 0 y = 0 + for l in range(rows): x = x + sizeBtwn y = y +sizeBtwn - pygame.draw.line(surface, (255,255,255), (x, 0),(x,w)) - pygame.draw.line(surface, (255,255,255), (0, y),(w,y)) - + pygame.draw.line(surface, (150,150,150), (x, 0),(x,w)) + pygame.draw.line(surface, (150,150,150), (0, y),(w,y)) def randomSnack(rows, item): @@ -163,36 +210,69 @@ def randomSnack(rows, item): def main(): - global s, snack, win + + global s, snack,bug, win, b, score + win = pygame.display.set_mode((width,height)) s = snake((255,0,0), (10,10)) s.addCube() snack = cube(randomSnack(rows,s), color=(0,255,0)) + bug = cube(randomSnack(rows,s), color=(0,0,255)) flag = True clock = pygame.time.Clock() - + start_ticks=pygame.time.get_ticks() + + score=0 + + eatsnack = pygame.mixer.Sound('grow.wav') + eatsnack.set_volume(0.8) + eatbug = pygame.mixer.Sound('shrink.wav') + eatbug.set_volume(0.8) + gameoversound = pygame.mixer.Sound('gameover.wav') + gameoversound.set_volume(0.8) + + while flag: pygame.time.delay(50) clock.tick(10) s.move() headPos = s.head.pos - if headPos[0] >= 20 or headPos[0] < 0 or headPos[1] >= 20 or headPos[1] < 0: + seconds=(pygame.time.get_ticks()-start_ticks)/1000 + + if headPos[0] >= 25 or headPos[0] < 0 or headPos[1] >= 25 or headPos[1] < 0: + gameoversound.play() print("Score:", len(s.body)) s.reset((10, 10)) if s.body[0].pos == snack.pos: + eatsnack.play() s.addCube() snack = cube(randomSnack(rows,s), color=(0,255,0)) + bug = cube(randomSnack(rows,s), color=(0,0,255)) + score +=10 + redrawWindow() + + if s.body[0].pos == bug.pos: + eatbug.play() + snack = cube(randomSnack(rows,s), color=(0,255,0)) + bug = cube(randomSnack(rows,s), color=(0,0,255)) + score -= 10 + redrawWindow() + + for x in range(len(s.body)): if s.body[x].pos in list(map(lambda z:z.pos,s.body[x+1:])): print("Score:", len(s.body)) s.reset((10,10)) break - + + + if len(s.body) > 25: + finish_game(seconds) + end_game() + redrawWindow() main() - - - + \ No newline at end of file