import pygame
import tkinter as tk
from tkinter import filedialog, simpledialog
from PIL import Image
import os
import random
import sys
# === Constants ===
TILE_SIZE = 20
DEFAULT_GRID = 20
FPS = 10
# === Globals (updated via GUI) ===
snake_head_img_path = "assets/default_head.png"
snake_body_img_path = "assets/default_body.png"
GRID_SIZE = DEFAULT_GRID
def load_skin(path, size):
img = Image.open(path).resize((size, size)).convert("RGBA")
return pygame.image.fromstring(img.tobytes(), img.size, img.mode)
def ask_user_inputs():
global snake_head_img_path, snake_body_img_path, GRID_SIZE
root = tk.Tk()
root.withdraw()
if filedialog.askyesno("Snake Skin", "Do you want to upload custom snake head image?"):
snake_head_img_path = filedialog.askopenfilename(title="Select Head Image")
if filedialog.askyesno("Snake Skin", "Do you want to upload custom snake body image?"):
snake_body_img_path = filedialog.askopenfilename(title="Select Body Image")
try:
GRID_SIZE = int(simpledialog.askstring("Grid Size", "Enter grid size (e.g., 20 for 20x20):") or DEFAULT_GRID)
except:
GRID_SIZE = DEFAULT_GRID
def draw_grid(screen, color=(40, 40, 40)):
for x in range(0, GRID_SIZE * TILE_SIZE, TILE_SIZE):
for y in range(0, GRID_SIZE * TILE_SIZE, TILE_SIZE):
rect = pygame.Rect(x, y, TILE_SIZE, TILE_SIZE)
pygame.draw.rect(screen, color, rect, 1)
class Snake:
def __init__(self):
self.body = [(5, 5), (4, 5), (3, 5)]
self.direction = (1, 0)
self.grow = False
def move(self):
head = self.body[0]
new_head = (head[0] + self.direction[0], head[1] + self.direction[1])
self.body.insert(0, new_head)
if not self.grow:
self.body.pop()
else:
self.grow = False
def change_direction(self, new_dir):
# Prevent reversing
if (new_dir[0] * -1, new_dir[1] * -1) != self.direction:
self.direction = new_dir
def draw(self, screen, head_img, body_img):
for i, segment in enumerate(self.body):
x, y = segment[0] * TILE_SIZE, segment[1] * TILE_SIZE
if i == 0:
screen.blit(head_img, (x, y))
else:
screen.blit(body_img, (x, y))
def check_collision(self):
head = self.body[0]
return (
head in self.body[1:] or
head[0] < 0 or head[1] < 0 or
head[0] >= GRID_SIZE or head[1] >= GRID_SIZE
)
def generate_food(snake):
while True:
pos = (random.randint(0, GRID_SIZE - 1), random.randint(0, GRID_SIZE - 1))
if pos not in snake.body:
return pos
def main():
ask_user_inputs()
pygame.init()
screen = pygame.display.set_mode((GRID_SIZE * TILE_SIZE, GRID_SIZE * TILE_SIZE))
pygame.display.set_caption("🐍 Custom Snake Game")
clock = pygame.time.Clock()
head_img = load_skin(snake_head_img_path, TILE_SIZE)
body_img = load_skin(snake_body_img_path, TILE_SIZE)
snake = Snake()
food = generate_food(snake)
running = True
while running:
clock.tick(FPS)
screen.fill((0, 0, 0))
draw_grid(screen)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_UP:
snake.change_direction((0, -1))
elif event.key == pygame.K_DOWN:
snake.change_direction((0, 1))
elif event.key == pygame.K_LEFT:
snake.change_direction((-1, 0))
elif event.key == pygame.K_RIGHT:
snake.change_direction((1, 0))
snake.move()
if snake.body[0] == food:
snake.grow = True
food = generate_food(snake)
if snake.check_collision():
print("Game Over!")
pygame.quit()
sys.exit()
snake.draw(screen, head_img, body_img)
fx, fy = food[0] * TILE_SIZE, food[1] * TILE_SIZE
pygame.draw.rect(screen, (255, 0, 0), (fx, fy, TILE_SIZE, TILE_SIZE))
pygame.display.flip()
if __name__ == "__main__":
main()
No comments:
Post a Comment