Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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줄)
Binary file addedgameover.wav
Binary file not shown.
Binary file addedgrow.wav
Binary file not shown.
Binary file addedshrink.wav
Binary file not shown.
132 changes: 106 additions & 26 deletions snake.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,52 +3,69 @@
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
circleMiddle = (i*dis+centre-radius,j*dis+8)
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)
Expand DownExpand Up@@ -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)
Expand DownExpand Up@@ -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):
Expand All@@ -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()




, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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줄)
Binary file addedgameover.wav
Binary file not shown.
Binary file addedgrow.wav
Binary file not shown.
Binary file addedshrink.wav
Binary file not shown.
132 changes: 106 additions & 26 deletions snake.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,52 +3,69 @@
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
circleMiddle = (i*dis+centre-radius,j*dis+8)
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)
Expand DownExpand Up@@ -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)
Expand DownExpand Up@@ -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):
Expand All@@ -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()




, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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줄)
Binary file addedgameover.wav
Binary file not shown.
Binary file addedgrow.wav
Binary file not shown.
Binary file addedshrink.wav
Binary file not shown.
132 changes: 106 additions & 26 deletions snake.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,52 +3,69 @@
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
circleMiddle = (i*dis+centre-radius,j*dis+8)
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)
Expand DownExpand Up@@ -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)
Expand DownExpand Up@@ -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):
Expand All@@ -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()




, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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줄)
Binary file addedgameover.wav
Binary file not shown.
Binary file addedgrow.wav
Binary file not shown.
Binary file addedshrink.wav
Binary file not shown.
132 changes: 106 additions & 26 deletions snake.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,52 +3,69 @@
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
circleMiddle = (i*dis+centre-radius,j*dis+8)
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)
Expand DownExpand Up@@ -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)
Expand DownExpand Up@@ -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):
Expand All@@ -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()




, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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줄)
Binary file addedgameover.wav
Binary file not shown.
Binary file addedgrow.wav
Binary file not shown.
Binary file addedshrink.wav
Binary file not shown.
132 changes: 106 additions & 26 deletions snake.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,52 +3,69 @@
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
circleMiddle = (i*dis+centre-radius,j*dis+8)
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)
Expand DownExpand Up@@ -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)
Expand DownExpand Up@@ -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):
Expand All@@ -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()




, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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줄)
Binary file addedgameover.wav
Binary file not shown.
Binary file addedgrow.wav
Binary file not shown.
Binary file addedshrink.wav
Binary file not shown.
132 changes: 106 additions & 26 deletions snake.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,52 +3,69 @@
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
circleMiddle = (i*dis+centre-radius,j*dis+8)
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)
Expand DownExpand Up@@ -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)
Expand DownExpand Up@@ -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):
Expand All@@ -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()




, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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줄)
Binary file addedgameover.wav
Binary file not shown.
Binary file addedgrow.wav
Binary file not shown.
Binary file addedshrink.wav
Binary file not shown.
132 changes: 106 additions & 26 deletions snake.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,52 +3,69 @@
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
circleMiddle = (i*dis+centre-radius,j*dis+8)
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)
Expand DownExpand Up@@ -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)
Expand DownExpand Up@@ -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):
Expand All@@ -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()




, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -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줄)
Binary file addedgameover.wav
Binary file not shown.
Binary file addedgrow.wav
Binary file not shown.
Binary file addedshrink.wav
Binary file not shown.
132 changes: 106 additions & 26 deletions snake.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,52 +3,69 @@
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
circleMiddle = (i*dis+centre-radius,j*dis+8)
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)
Expand DownExpand Up@@ -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)
Expand DownExpand Up@@ -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):
Expand All@@ -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()