Python Forum
PyGame Nibbles tutorial for beginners.
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
PyGame Nibbles tutorial for beginners.
#1
I would have summit this in tutorial request and submission. There is no post thread there.

First thing. Build a boiler plate. Opens a pygame screen.
# Step 1. Let start out with the basic boiler plate.

import os
import pygame
# global Container
class Game:
    pass

def main():
    # Center screen
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    pygame.init()
    pygame.display.set_caption("Nibbles Tutorial")
    Game.screen = pygame.display.set_mode((720,420))
    Game.running = True

    clock = pygame.time.Clock()

    # Mainloop
    while Game.running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                Game.running = False

        Game.screen.fill((0,10,0))
        pygame.display.flip()
        clock.tick(30)
    pygame.quit()

if __name__ == '__main__':
    main()
Next draw a snake and basic screen rect.
It a good thing to store values in variables for later use.
# Step 2. Draw the snake

import os
import pygame
# global Container
class Game:
    pass

def main():
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    pygame.init()
    pygame.display.set_caption("Nibbles Tutorial")
    # Let define block size.
    Game.block_size = 12
    # Set blocks width
    Game.width = 72
    width = Game.block_size * Game.width
    # Set blocks height
    Game.height = 42
    height = Game.block_size * Game.height
    # Rect to keep are snake within
    Game.rect = pygame.Rect(0,0,width,height)
    Game.screen = pygame.display.set_mode(Game.rect.size)
    Game.running = True

    Game.snake_color = pygame.Color('lawngreen')
    size = Game.block_size
    x = Game.width / 2 * size
    y = Game.height / 2 * size
    # Build the snake body
    Game.snake = [(x, y), (x, y + size), (x, y + size * 2)]

    clock = pygame.time.Clock()

    # Mainloop
    while Game.running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                Game.running = False

        Game.screen.fill((0,10,0))

        # Draw the snake
        for body in Game.snake:
            rect = pygame.Rect(body[0], body[1], Game.block_size, Game.block_size)
            Game.screen.fill(Game.snake_color, rect)

        pygame.display.flip()
        clock.tick(30)
    pygame.quit()

if __name__ == '__main__':
    main()
Now get the snake moving and colliding with border.
# Step 3. Make the snake move

import os
import pygame
# Global Container
class Game:
    pass

def add_tuples(lhs, rhs):
    return lhs[0] + rhs[0], lhs[1] + rhs[1]

def keys_down():
    # let get the keypressed states
    keypress = pygame.key.get_pressed()
    # press left arrow key and it not moving right
    if keypress[pygame.K_LEFT] and Game.snake_direction[0] != Game.block_size:
        # set snake direction to left
        Game.snake_direction = -Game.block_size, 0 # (-10, 0) (right or left, up or down)
    # press right arrow key and it not moving left
elif keypress[pygame.K_RIGHT] and Game.snake_direction[0] != -Game.block_size:
        # set snake direction to right
        Game.snake_direction = Game.block_size, 0
    # press up arrow key and it not moving down
elif keypress[pygame.K_UP] and Game.snake_direction[1] != Game.block_size:
        # set snake direction to up
        Game.snake_direction = 0, -Game.block_size
    # press down arrow key and it not moving up
elif keypress[pygame.K_DOWN] and Game.snake_direction[1] != -Game.block_size:
        # set snake direction to down
        Game.snake_direction = 0, Game.block_size

def snake_move():
    # Move the snake
    head = add_tuples(Game.snake[0], Game.snake_direction)
    # Add head and drop tail. Simulate forward motion
    Game.snake = [head] + Game.snake[:-1]
    # snake collide with outside wall
    if not Game.rect.collidepoint(head):
        new_game()

# Move snake here for quick restart
def new_game():
    size = Game.block_size
    # Give snake a direction
    Game.snake_direction = 0, -size # up
    x = Game.width / 2 * size
    y = Game.height / 2 * size
    Game.snake = [ (x, y), (x, y + size), (x, y + size * 2)

def main():
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    pygame.init()
    pygame.display.set_caption("Nibbles Tutorial")
    Game.block_size = 12
    Game.width = 72
    width = Game.block_size * Game.width
    Game.height = 42
    height = Game.block_size * Game.height
    Game.rect = pygame.Rect(0,0,width,height)
    Game.screen = pygame.display.set_mode(Game.rect.size)
    Game.running = True

    Game.snake_color = pygame.Color('lawngreen')
    new_game()

    clock = pygame.time.Clock()

    # Mainloop
    while Game.running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                Game.running = False

        # See if key is pressed
        keys_down()
        # Move every loop
        snake_move()
        Game.screen.fill((0,10,0))
        # Draw the snake
        for body in Game.snake:
            rect = pygame.Rect(body[0], body[1], Game.block_size, Game.block_size)
            Game.screen.fill(Game.snake_color, rect)

        pygame.display.flip()
        # reduce framerate for movement
        clock.tick(10)
    pygame.quit()

if __name__ == '__main__':
    main()
Okay now let not use framerate to control speed.
Let give the snake some food to gather.
Let give the snake random start direction.
Have to have snake_head to avoid fast keys down changes.
# Step 4. Food, better snake movement timing, and random start direction

import os
import pygame
from random import choice, randrange
# Global Container
class Game:
    pass

def add_tuples(lhs, rhs):
    return lhs[0] + rhs[0], lhs[1] + rhs[1]

def sub_tuples(lhs, rhs):
    return lhs[0] - rhs[0], lhs[1] - rhs[1]

def keys_down():
    # let get the keypressed states
    keypress = pygame.key.get_pressed()
    if keypress[pygame.K_LEFT] and Game.snake_head[0] != Game.block_size:
        Game.snake_direction = -Game.block_size, 0 # (-10, 0) (right or left, up or down)
    elif keypress[pygame.K_RIGHT] and Game.snake_head[0] != -Game.block_size:
        Game.snake_direction = Game.block_size, 0
    elif keypress[pygame.K_UP] and Game.snake_head[1] != Game.block_size:
        Game.snake_direction = 0, -Game.block_size
    elif keypress[pygame.K_DOWN] and Game.snake_head[1] != -Game.block_size:
        Game.snake_direction = 0, Game.block_size

def snake_move():
    # Assign snake_head to snake_direction here
    Game.snake_head = Game.snake_direction
    # Move the snake
    head = add_tuples(Game.snake[0], Game.snake_direction)

    if not Game.rect.collidepoint(head):
        new_game()
    # Snake body collision
    elif head in Game.snake:
        new_game()
    # Food collision
    elif head == Game.food:
        Game.snake = [head] + Game.snake
        # Make snake move faster
        Game.movement_timer['length'] -= 2
        # make more food
        create_food()
    else:
        Game.snake = [head] + Game.snake[:-1]

def create_food():
    Game.food = None
    # Let make sure food doesn't collide with snake
    while Game.food is None:
        x = randrange(1, Game.width, 1) * Game.block_size
        y = randrange(1, Game.height, 1) * Game.block_size
        Game.food = (x, y)
        if Game.food in Game.snake:
            Game.food = None

    size = Game.block_size - 2
    Game.food_rect = (x + 1, y + 1, size, size)

def new_game():
    size = Game.block_size
    # random start direction
    Game.snake_direction = choice(((0, -size), (0, size), (-size, 0), (size, 0)))
    d = Game.snake_direction
    x = Game.width / 2 * size
    y = Game.height / 2 * size
    # Give snake a head to avoid opposite collision
    Game.snake_head = Game.snake_direction
    # Build snake body according to direction.
    Game.snake = [(x, y), sub_tuples((x, y), d), sub_tuples(sub_tuples((x,y), d), d)]
    # Make a Tick Timer, Ticks are in milliseconds.
    Game.movement_timer = {'length': 120, 'next tick': pygame.time.get_ticks()}
    # New food spot on every new game
    create_food()

def timer_elasped(timer, ticks):
    if ticks > timer['next tick'] + timer['length']:
        timer['next tick'] += timer['length']
        return True
    return False

def main():
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    pygame.init()
    pygame.display.set_caption("Nibbles Tutorial")
    Game.block_size = 12
    Game.width = 72
    width = Game.block_size * Game.width
    Game.height = 42
    height = Game.block_size * Game.height
    Game.rect = pygame.Rect(0,0,width,height)
    Game.screen = pygame.display.set_mode(Game.rect.size)
    Game.running = True
    Game.snake_color = pygame.Color('lawngreen')
    Game.food_color = pygame.Color('yellow')
    new_game()
    clock = pygame.time.Clock()
    # Mainloop
    while Game.running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                Game.running = False

        keys_down()
        # Get pygame ticks
        ticks = pygame.time.get_ticks()
        # Only move snake if timer elasped
        if timer_elasped(Game.movement_timer, ticks):
            snake_move()

        Game.screen.fill((0,10,0))
        # Draw food
        Game.screen.fill(Game.food_color, Game.food_rect)

        # Draw the snake
        for body in Game.snake:
            rect = pygame.Rect(body[0], body[1], Game.block_size, Game.block_size)
            Game.screen.fill(Game.snake_color, rect)

        pygame.display.flip()
        clock.tick(60)
    pygame.quit()

if __name__ == '__main__':
    main()
Final let create a stage. Walls for the snake to avoid.
Create a snake surface over color.
# Step 5. Walls and better looking snake

import os
import pygame
from random import choice, randrange
# Global Container
class Game:
    pass

def add_tuples(lhs, rhs):
    return lhs[0] + rhs[0], lhs[1] + rhs[1]

def sub_tuples(lhs, rhs):
    return lhs[0] - rhs[0], lhs[1] - rhs[1]

def keys_down():
    # let get the keypressed states
    keypress = pygame.key.get_pressed()
    if keypress[pygame.K_LEFT] and Game.snake_head[0] != Game.block_size:
        Game.snake_direction = -Game.block_size, 0 # (-10, 0) (right or left, up or down)
    elif keypress[pygame.K_RIGHT] and Game.snake_head[0] != -Game.block_size:
        Game.snake_direction = Game.block_size, 0
    elif keypress[pygame.K_UP] and Game.snake_head[1] != Game.block_size:
        Game.snake_direction = 0, -Game.block_size
    elif keypress[pygame.K_DOWN] and Game.snake_head[1] != -Game.block_size:
        Game.snake_direction = 0, Game.block_size

def snake_move():
    # Assign snake_head to snake_direction here
    Game.snake_head = Game.snake_direction
    # Move the snake
    head = add_tuples(Game.snake[0], Game.snake_direction)

    if not Game.rect.collidepoint(head):
        new_game()
    # Snake body collision
    elif head in Game.snake or head in Game.walls:
        new_game()
    # Food collision
    elif head == Game.food:
        Game.snake = [head] + Game.snake
        # Make snake move faster
        Game.movement_timer['length'] -= 2
        # make more food
        create_food()
    else:
        Game.snake = [head] + Game.snake[:-1]

def create_food():
    Game.food = None
    # Let make sure food doesn't collide with snake
    while Game.food is None:
        x = randrange(1, Game.width, 1) * Game.block_size
        y = randrange(1, Game.height, 1) * Game.block_size
        Game.food = (x, y)
        # Don't have food spawn in walls
        if Game.food in Game.snake or Game.food in Game.walls:
            Game.food = None


    size = Game.block_size - 2
    Game.food_rect = (x + 1, y + 1, size, size)

def new_game():
    # First Stage
    create_stage1()
    size = Game.block_size
    # random start direction
    Game.snake_direction = choice(((0, -size), (0, size), (-size, 0), (size, 0)))
    d = Game.snake_direction
    x = Game.width / 2 * size
    y = Game.height / 2 * size
    # Give snake a head to avoid opposite collision
    Game.snake_head = Game.snake_direction
    # Build snake body according to direction.
    Game.snake = [(x, y), sub_tuples((x, y), d), sub_tuples(sub_tuples((x,y), d), d)]
    # Make a Tick Timer, Ticks are in milliseconds.
    Game.movement_timer = {'length': 120, 'next tick': pygame.time.get_ticks()}
    # New food spot on every new game
    create_food()

def timer_elasped(timer, ticks):
    if ticks > timer['next tick'] + timer['length']:
        timer['next tick'] += timer['length']
        return True
    return False

def create_snake():
    surface = pygame.Surface((Game.block_size, Game.block_size))
    surface.fill(pygame.Color('lawngreen'))
    size = Game.block_size
    mid = int(Game.block_size / 2)
    color = pygame.Color('forestgreen')
    for i in [1,2,3]:
        j = i * 2
        pygame.draw.line(surface, color, (mid - i, j), (mid - i, size - j))
        pygame.draw.line(surface, color, (mid + i, j), (mid + i, size - j))
        pygame.draw.line(surface, color, (j, mid - i), (size - j, mid - i))
        pygame.draw.line(surface, color, (j, mid + i), (size - j, mid + i))
    return surface

def create_stage1():
    # Classic first stage
    Game.walls = []
    for y in range(7, Game.height - 7):
        Game.walls.append((12 * Game.block_size, y * Game.block_size))
        Game.walls.append(((Game.width - 12) * Game.block_size, y * Game.block_size))

def main():
    os.environ['SDL_VIDEO_CENTERED'] = '1'
    pygame.init()
    pygame.display.set_caption("Nibbles Tutorial")
    Game.block_size = 12
    Game.width = 72
    width = Game.block_size * Game.width
    Game.height = 42
    height = Game.block_size * Game.height
    Game.rect = pygame.Rect(0,0,width,height)
    Game.screen = pygame.display.set_mode(Game.rect.size)
    Game.running = True
    Game.snake_body = create_snake()
    Game.food_color = pygame.Color('yellow')
    new_game()
    clock = pygame.time.Clock()
    # Mainloop
    while Game.running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                Game.running = False

        keys_down()
        # Get pygame ticks
        ticks = pygame.time.get_ticks()
        # Only move snake if timer elasped
        if timer_elasped(Game.movement_timer, ticks):
            snake_move()

        Game.screen.fill((0,10,0))
        # Draw food
        Game.screen.fill(Game.food_color, Game.food_rect)
        # Draw walls
        for wall in Game.walls:
            rect = pygame.Rect(wall[0], wall[1], Game.block_size, Game.block_size)
            Game.screen.fill(pygame.Color('gray30'), rect)
        # Draw the snake
        for body in Game.snake:
            rect = pygame.Rect(body[0], body[1], Game.block_size, Game.block_size)
            #Game.screen.fill(Game.snake_color, rect)
            Game.screen.blit(Game.snake_body, rect)

        pygame.display.flip()
        clock.tick(60)
    pygame.quit()

if __name__ == '__main__':
    main()
Challenges.
1. Rewrite this game using classes. Basic function are still aloud.
2. Make the snake grow by 2 or 3 per food.
3. Make another stage. Have it change to next stage after snake gets so big.
99 percent of computer problems exists between chair and keyboard.
Reply


Messages In This Thread
PyGame Nibbles tutorial for beginners. - by Windspar - Dec-16-2017, 03:04 AM
RE: Nibbles tutorial for beginners. - by Larz60+ - Dec-16-2017, 03:38 AM
RE: Nibbles tutorial for beginners. - by metulburr - Dec-16-2017, 04:19 AM

Possibly Related Threads…
Thread Author Replies Views Last Post
  [Basic] Python Tutorial for Beginners MK_CodingSpace 0 2,290 Dec-03-2020, 09:43 PM
Last Post: MK_CodingSpace
  [Basic] Python Tutorial for Beginners in One Lesson (98 minutes) artur_m 0 4,158 Jan-23-2020, 09:15 AM
Last Post: artur_m
  [Basic] Interactive tutorial for beginners (codetheblocks) abhin 1 3,437 Feb-21-2018, 05:09 AM
Last Post: Larz60+
  A good tutorial for beginners? (Youtube) Peter_EU 11 8,522 Dec-06-2017, 09:43 PM
Last Post: apollo

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020