Snake AI in Pygame

In this article we will show you how to create basic game AI (Artificial Intelligence). This article will describe an AI for the game snake.

In this game (snake) both the computer and you play a snake, and the computer snake tries to catch you. In short: the opponent AI tries to determine and go to the destination point based on your location on the board.

You may like

Adding the computer player:
We extend the code with a new class called Computer which will be our computer player. This contains routines to draw and move the computer snake.

class Computer:
    x = [0]
    y = [0]
    step = 44
    direction = 0
    length = 3
 
    updateCountMax = 2
    updateCount = 0
 
    def __init__(self, length):
       self.length = length
       for i in range(0,2000):
           self.x.append(-100)
           self.y.append(-100)
 
       # initial positions, no collision.
       self.x[0] = 1*44
       self.y[0] = 4*44
 
    def update(self):
 
        self.updateCount = self.updateCount + 1
        if self.updateCount > self.updateCountMax:
 
            # update previous positions
            for i in range(self.length-1,0,-1):
                self.x[i] = self.x[i-1]
                self.y[i] = self.y[i-1]
 
            # update position of head of snake
            if self.direction == 0:
                self.x[0] = self.x[0] + self.step
            if self.direction == 1:
                self.x[0] = self.x[0] - self.step
            if self.direction == 2:
                self.y[0] = self.y[0] - self.step
            if self.direction == 3:
                self.y[0] = self.y[0] + self.step
 
            self.updateCount = 0
 
 
    def moveRight(self):
        self.direction = 0
 
    def moveLeft(self):
        self.direction = 1
 
    def moveUp(self):
        self.direction = 2
 
    def moveDown(self):
        self.direction = 3 
 
    def draw(self, surface, image):
        for i in range(0,self.length):
            surface.blit(image,(self.x[i],self.y[i]))

We then call the update and drawing method of the computer.

    def on_loop(self):
        self.player.update()
        self.computer.update()
 
....
 
    def on_render(self):
        self._display_surf.fill((0,0,0))
        self.player.draw(self._display_surf, self._image_surf)
        self.apple.draw(self._display_surf, self._apple_surf)
        self.computer.draw(self._display_surf, self._image_surf)
        pygame.display.flip()

This will make the computer snake move and be drawn on the screen. It has the same properties as the human player.

Adding the intelligence to the computer player
Because this is a simple game, we do not need to create a complete thinking machine inside the game.  We simply need some basic  intelligence exhibited by our computer player.  Intelligence in games is often quite limited because most of the time more complexity is not neccesary or there simply is not the time available to implement clever algorithms.

The algorithm we will add will simply go to the destination. It will neglect any obstacles (the human player).

    def target(self,dx,dy):
        if self.x[0] > dx:
            self.moveLeft()
 
        if self.x[0] < dx:
            self.moveRight()
 
        if self.x[0] == dx:
            if self.y[0] < dy:
                self.moveDown()
 
            if self.y[0] > dy:
                self.moveUp()

Complete code
We end up with this complete code:

from pygame.locals import *
from random import randint
import pygame
import time
 
class Apple:
    x = 0
    y = 0
    step = 44
 
    def __init__(self,x,y):
        self.x = x * self.step
        self.y = y * self.step
 
    def draw(self, surface, image):
        surface.blit(image,(self.x, self.y)) 
 
 
class Player:
    x = [0]
    y = [0]
    step = 44
    direction = 0
    length = 3
 
    updateCountMax = 2
    updateCount = 0
 
    def __init__(self, length):
       self.length = length
       for i in range(0,2000):
           self.x.append(-100)
           self.y.append(-100)
 
       # initial positions, no collision.
       self.x[0] = 1*44
       self.x[0] = 2*44
 
    def update(self):
 
        self.updateCount = self.updateCount + 1
        if self.updateCount > self.updateCountMax:
 
            # update previous positions
            for i in range(self.length-1,0,-1):
                self.x[i] = self.x[i-1]
                self.y[i] = self.y[i-1]
 
            # update position of head of snake
            if self.direction == 0:
                self.x[0] = self.x[0] + self.step
            if self.direction == 1:
                self.x[0] = self.x[0] - self.step
            if self.direction == 2:
                self.y[0] = self.y[0] - self.step
            if self.direction == 3:
                self.y[0] = self.y[0] + self.step
 
            self.updateCount = 0
 
 
    def moveRight(self):
        self.direction = 0
 
    def moveLeft(self):
        self.direction = 1
 
    def moveUp(self):
        self.direction = 2
 
    def moveDown(self):
        self.direction = 3 
 
    def draw(self, surface, image):
        for i in range(0,self.length):
            surface.blit(image,(self.x[i],self.y[i])) 
 
 
 
class Computer:
    x = [0]
    y = [0]
    step = 44
    direction = 0
    length = 3
 
    updateCountMax = 2
    updateCount = 0
 
    def __init__(self, length):
       self.length = length
       for i in range(0,2000):
           self.x.append(-100)
           self.y.append(-100)
 
       # initial positions, no collision.
       self.x[0] = 1*44
       self.y[0] = 4*44
 
    def update(self):
 
        self.updateCount = self.updateCount + 1
        if self.updateCount > self.updateCountMax:
 
            # update previous positions
            for i in range(self.length-1,0,-1):
                self.x[i] = self.x[i-1]
                self.y[i] = self.y[i-1]
 
            # update position of head of snake
            if self.direction == 0:
                self.x[0] = self.x[0] + self.step
            if self.direction == 1:
                self.x[0] = self.x[0] - self.step
            if self.direction == 2:
                self.y[0] = self.y[0] - self.step
            if self.direction == 3:
                self.y[0] = self.y[0] + self.step
 
            self.updateCount = 0
 
 
    def moveRight(self):
        self.direction = 0
 
    def moveLeft(self):
        self.direction = 1
 
    def moveUp(self):
        self.direction = 2
 
    def moveDown(self):
        self.direction = 3 
 
 
    def target(self,dx,dy):
        if self.x[0] > dx:
            self.moveLeft()
 
        if self.x[0] < dx:
            self.moveRight()
 
        if self.x[0] == dx:
            if self.y[0] < dy:
                self.moveDown()
 
            if self.y[0] > dy:
                self.moveUp()
 
    def draw(self, surface, image):
        for i in range(0,self.length):
            surface.blit(image,(self.x[i],self.y[i])) 
 
 
class Game:
    def isCollision(self,x1,y1,x2,y2,bsize):
        if x1 >= x2 and x1 <= x2 + bsize:
            if y1 >= y2 and y1 <= y2 + bsize:
                return True
        return False
 
class App:
 
    windowWidth = 800
    windowHeight = 600
    player = 0
    apple = 0
 
    def __init__(self):
        self._running = True
        self._display_surf = None
        self._image_surf = None
        self._apple_surf = None
        self.game = Game()
        self.player = Player(5) 
        self.apple = Apple(8,5)
        self.computer = Computer(5)
 
    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
 
        pygame.display.set_caption('Pygame pythonspot.com example')
        self._running = True
        self._image_surf = pygame.image.load("pygame.png").convert()
        self._apple_surf = pygame.image.load("apple.png").convert()
 
    def on_event(self, event):
        if event.type == QUIT:
            self._running = False
 
    def on_loop(self):
        self.computer.target(self.apple.x, self.apple.y)
        self.player.update()
        self.computer.update()
 
        # does snake eat apple?
        for i in range(0,self.player.length):
            if self.game.isCollision(self.apple.x,self.apple.y,self.player.x[i], self.player.y[i],44):
                self.apple.x = randint(2,9) * 44
                self.apple.y = randint(2,9) * 44
                self.player.length = self.player.length + 1
 
        # does computer eat apple?
        for i in range(0,self.player.length):
            if self.game.isCollision(self.apple.x,self.apple.y,self.computer.x[i], self.computer.y[i],44):
                self.apple.x = randint(2,9) * 44
                self.apple.y = randint(2,9) * 44
                #self.computer.length = self.computer.length + 1
 
 
        # does snake collide with itself?
        for i in range(2,self.player.length):
            if self.game.isCollision(self.player.x[0],self.player.y[0],self.player.x[i], self.player.y[i],40):
                print "You lose! Collision: "
                print "x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")"  
                print "x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")"  
                exit(0)
 
        pass
 
    def on_render(self):
        self._display_surf.fill((0,0,0))
        self.player.draw(self._display_surf, self._image_surf)
        self.apple.draw(self._display_surf, self._apple_surf)
        self.computer.draw(self._display_surf, self._image_surf)
        pygame.display.flip()
 
    def on_cleanup(self):
        pygame.quit()
 
    def on_execute(self):
        if self.on_init() == False:
            self._running = False
 
        while( self._running ):
            pygame.event.pump()
            keys = pygame.key.get_pressed() 
 
            if (keys[K_RIGHT]):
                self.player.moveRight()
 
            if (keys[K_LEFT]):
                self.player.moveLeft()
 
            if (keys[K_UP]):
                self.player.moveUp()
 
            if (keys[K_DOWN]):
                self.player.moveDown()
 
            if (keys[K_ESCAPE]):
                self._running = False
 
            self.on_loop()
            self.on_render()
 
            time.sleep (50.0 / 1000.0);
        self.on_cleanup()
 
if __name__ == "__main__" :
    theApp = App()
    theApp.on_execute()
python snake
python snake

Conclusion
You learned how to create a basic computer player using an very simple AI algorithm.

Next:  Learn basic sidescroller logic

FTP client in Python

This article will show you how to use the File Transfer Protocol (FTP)  with Python from a client side perspective.  We use ftplib, a library that implements the FTP protocol.   Using FTP we can create and access remote files through function calls.

Related course
Python Programming Bootcamp: Go from zero to hero

Directory listing
We can list the root directory using this little snippet:

import ftplib
 
ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")
 
data = []
 
ftp.dir(data.append)
 
ftp.quit()
 
for line in data:
    print "-", line

This will output the directory contents. in a simple console style output. If you want to show a specific directory you must change the directory after connecting with the ftp.cwd(‘/’) function where the parameter is the directory you want to change to.

import ftplib
 
ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")
 
data = []
 
ftp.cwd('/pub/')         # change directory to /pub/
ftp.dir(data.append)
 
ftp.quit()
 
for line in data:
    print "-", line

Download file
To download a file we use the retrbinary() function. An example below:

import ftplib
import sys
 
def getFile(ftp, filename):
    try:
        ftp.retrbinary("RETR " + filename ,open(filename, 'wb').write)
    except:
        print "Error"
 
 
ftp = ftplib.FTP("ftp.nluug.nl")
ftp.login("anonymous", "ftplib-example-1")
 
ftp.cwd('/pub/')         # change directory to /pub/
getFile(ftp,'README.nluug')
 
ftp.quit()

Uploading files
We can upload files using the storlines() command.  This will upload the file README.nluug in the main directory. If you want to upload in another directory combine it with the cwd() function.

import ftplib
import os
 
def upload(ftp, file):
    ext = os.path.splitext(file)[1]
    if ext in (".txt", ".htm", ".html"):
        ftp.storlines("STOR " + file, open(file))
    else:
        ftp.storbinary("STOR " + file, open(file, "rb"), 1024)
 
ftp = ftplib.FTP("127.0.0.1")
ftp.login("username", "password")
 
upload(ftp, "README.nluug")

Other functions
For other functions please refer to the official library documentation.

Maze in Pygame

In this tutorial you will learn how to build a maze game. The idea is simply to move around the maze with the arrow keys.

Related courses:

Getting started: Basic structure and event handling.
We define a class Player which holds the players position on the screen and the speed by which it moves. In addition we define the actions a Player instance can do (movements):

class Player:
    x = 10
    y = 10
    speed = 1
 
    def moveRight(self):
        self.x = self.x + self.speed
 
    def moveLeft(self):
        self.x = self.x - self.speed
 
    def moveUp(self):
        self.y = self.y - self.speed
 
    def moveDown(self):
        self.y = self.y + self.speed

A player object can be created and variables can be modified using the movement methods. We link those methods to the events. In Pygame we can get non-blocking keyboard input using this code:

pygame
pygame

Creating the maze

We define a matrix of NxM to represent the positions of the maze blocks. In this matrix the element 1 represents the presence of a block and element 0 represents the absence.

class Maze:
    def __init__(self):
       self.M = 10
       self.N = 8
       self.maze = [ 1,1,1,1,1,1,1,1,1,1,
                     1,0,0,0,0,0,0,0,0,1,
                     1,0,0,0,0,0,0,0,0,1,
                     1,0,1,1,1,1,1,1,0,1,
                     1,0,1,0,0,0,0,0,0,1,
                     1,0,1,0,1,1,1,1,0,1,
                     1,0,0,0,0,0,0,0,0,1,
                     1,1,1,1,1,1,1,1,1,1,]

We have this complete code to draw the maze:

from pygame.locals import *
import pygame
 
class Player:
    x = 44
    y = 44
    speed = 1
 
    def moveRight(self):
        self.x = self.x + self.speed
 
    def moveLeft(self):
        self.x = self.x - self.speed
 
    def moveUp(self):
        self.y = self.y - self.speed
 
    def moveDown(self):
        self.y = self.y + self.speed
 
class Maze:
    def __init__(self):
       self.M = 10
       self.N = 8
       self.maze = [ 1,1,1,1,1,1,1,1,1,1,
                     1,0,0,0,0,0,0,0,0,1,
                     1,0,0,0,0,0,0,0,0,1,
                     1,0,1,1,1,1,1,1,0,1,
                     1,0,1,0,0,0,0,0,0,1,
                     1,0,1,0,1,1,1,1,0,1,
                     1,0,0,0,0,0,0,0,0,1,
                     1,1,1,1,1,1,1,1,1,1,]
 
    def draw(self,display_surf,image_surf):
       bx = 0
       by = 0
       for i in range(0,self.M*self.N):
           if self.maze[ bx + (by*self.M) ] == 1:
               display_surf.blit(image_surf,( bx * 44 , by * 44))
 
           bx = bx + 1
           if bx > self.M-1:
               bx = 0 
               by = by + 1
 
 
class App:
 
    windowWidth = 800
    windowHeight = 600
    player = 0
 
    def __init__(self):
        self._running = True
        self._display_surf = None
        self._image_surf = None
        self._block_surf = None
        self.player = Player()
        self.maze = Maze()
 
    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
 
        pygame.display.set_caption('Pygame pythonspot.com example')
        self._running = True
        self._image_surf = pygame.image.load("player.png").convert()
        self._block_surf = pygame.image.load("block.png").convert()
 
    def on_event(self, event):
        if event.type == QUIT:
            self._running = False
 
    def on_loop(self):
        pass
 
    def on_render(self):
        self._display_surf.fill((0,0,0))
        self._display_surf.blit(self._image_surf,(self.player.x,self.player.y))
        self.maze.draw(self._display_surf, self._block_surf)
        pygame.display.flip()
 
    def on_cleanup(self):
        pygame.quit()
 
    def on_execute(self):
        if self.on_init() == False:
            self._running = False
 
        while( self._running ):
            pygame.event.pump()
            keys = pygame.key.get_pressed()
 
            if (keys[K_RIGHT]):
                self.player.moveRight()
 
            if (keys[K_LEFT]):
                self.player.moveLeft()
 
            if (keys[K_UP]):
                self.player.moveUp()
 
            if (keys[K_DOWN]):
                self.player.moveDown()
 
            if (keys[K_ESCAPE]):
                self._running = False
 
            self.on_loop()
            self.on_render()
        self.on_cleanup()
 
if __name__ == "__main__" :
    theApp = App()
    theApp.on_execute()
maze
maze

Concluding
You learned how to create a 2d maze in Python. Now you may want to add collision detection which we showed in our previous tutorial. Because we already explained that concept we will not go over it again 🙂

Next tutorial: AI with Pygame

Snake with Pygame

snake GameIn this tutorial you will learn how to build the game snake.  The game is an arcade game and it has very simple logic, which is why it is an ideal example to demonstrate how to build games with Pygame.

The player is represented as snake, which grows if it eats an apple. The goal of the game is to eat as many apples as possible without colliding into yourself.  This is very easy in the early phase of the game but is increasingly more difficult as the length of the snake grows.

Related courses:

Getting started: Basic structure and event handling.
We define a class Player which holds the players position on the screen and the speed by which it moves. In addition we define the actions a Player instance can do (movements):

class Player:
    x = 10
    y = 10
    speed = 1
 
    def moveRight(self):
        self.x = self.x + self.speed
 
    def moveLeft(self):
        self.x = self.x - self.speed
 
    def moveUp(self):
        self.y = self.y - self.speed
 
    def moveDown(self):
        self.y = self.y + self.speed

A player object can be created and variables can be modified using the movement methods.
We link those methods to the events. In Pygame we can get non-blocking keyboard input using this code:

 pygame.event.pump()
 keys = pygame.key.get_pressed() 
 
 if (keys[K_RIGHT]):
    print "Right arrow pressed."

The complete code gives us the ability to move the player across the screen:

from pygame.locals import *
import pygame
 
class Player:
    x = 10
    y = 10
    speed = 1
 
    def moveRight(self):
        self.x = self.x + self.speed
 
    def moveLeft(self):
        self.x = self.x - self.speed
 
    def moveUp(self):
        self.y = self.y - self.speed
 
    def moveDown(self):
        self.y = self.y + self.speed
 
class App:
 
    windowWidth = 800
    windowHeight = 600
    player = 0
 
    def __init__(self):
        self._running = True
        self._display_surf = None
        self._image_surf = None
        self.player = Player() 
 
    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
 
        pygame.display.set_caption('Pygame pythonspot.com example')
        self._running = True
        self._image_surf = pygame.image.load("pygame.png").convert()
 
    def on_event(self, event):
        if event.type == QUIT:
            self._running = False
 
    def on_loop(self):
        pass
 
    def on_render(self):
        self._display_surf.fill((0,0,0))
        self._display_surf.blit(self._image_surf,(self.player.x,self.player.y))
        pygame.display.flip()
 
    def on_cleanup(self):
        pygame.quit()
 
    def on_execute(self):
        if self.on_init() == False:
            self._running = False
 
        while( self._running ):
            pygame.event.pump()
            keys = pygame.key.get_pressed() 
 
            if (keys[K_RIGHT]):
                self.player.moveRight()
 
            if (keys[K_LEFT]):
                self.player.moveLeft()
 
            if (keys[K_UP]):
                self.player.moveUp()
 
            if (keys[K_DOWN]):
                self.player.moveDown()
 
            if (keys[K_ESCAPE]):
                self._running = False
 
            self.on_loop()
            self.on_render()
        self.on_cleanup()
 
if __name__ == "__main__" :
    theApp = App()
    theApp.on_execute()

You can now move the block around the screen with the arrow keys.

pygame
pygame example. Move the block around the screen

Building the player (snake)
The player controls a snake which has an initial length. This snake is always moving and changes the direction it moves when pressing an arrow key. To do so, update the player class:

class Player:
    x = 0
    y = 0
    speed = 32
    direction = 0
 
    def update(self):
        if self.direction == 0:
            self.x = self.x + self.speed
        if self.direction == 1:
            self.x = self.x - self.speed
        if self.direction == 2:
            self.y = self.y - self.speed
        if self.direction == 3:
            self.y = self.y + self.speed
 
    def moveRight(self):
        self.direction = 0
 
    def moveLeft(self):
        self.direction = 1
 
    def moveUp(self):
        self.direction = 2
 
    def moveDown(self):
        self.direction = 3

and don’t forget to add a delay to the game loop.

import time
...
time.sleep (100.0 / 1000.0);

This starts to act more as a snake, but it does not have a base length yet. We keep track of the snakes old positions and move the head of the snake.  We also moved the drawing method into the snake. Copy the code and you will have a moving snake:

from pygame.locals import *
import pygame
import time
 
class Player:
    x = []
    y = []
    step = 44
    direction = 0
    length = 3
 
    updateCountMax = 2
    updateCount = 0
 
    def __init__(self, length):
       self.length = length
       for i in range(0,length):
           self.x.append(0)
           self.y.append(0)
 
    def update(self):
 
        self.updateCount = self.updateCount + 1
        if self.updateCount > self.updateCountMax:
 
            # update previous positions
            for i in range(self.length-1,0,-1):
                print "self.x[" + str(i) + "] = self.x[" + str(i-1) + "]"
                self.x[i] = self.x[i-1]
                self.y[i] = self.y[i-1]
 
            # update position of head of snake
            if self.direction == 0:
                self.x[0] = self.x[0] + self.step
            if self.direction == 1:
                self.x[0] = self.x[0] - self.step
            if self.direction == 2:
                self.y[0] = self.y[0] - self.step
            if self.direction == 3:
                self.y[0] = self.y[0] + self.step
 
            self.updateCount = 0
 
 
    def moveRight(self):
        self.direction = 0
 
    def moveLeft(self):
        self.direction = 1
 
    def moveUp(self):
        self.direction = 2
 
    def moveDown(self):
        self.direction = 3 
 
    def draw(self, surface, image):
        for i in range(0,self.length):
            surface.blit(image,(self.x[i],self.y[i])) 
 
 
class App:
 
    windowWidth = 800
    windowHeight = 600
    player = 0
 
    def __init__(self):
        self._running = True
        self._display_surf = None
        self._image_surf = None
        self.player = Player(10) 
 
    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
 
        pygame.display.set_caption('Pygame pythonspot.com example')
        self._running = True
        self._image_surf = pygame.image.load("pygame.png").convert()
 
    def on_event(self, event):
        if event.type == QUIT:
            self._running = False
 
    def on_loop(self):
        self.player.update()
        pass
 
    def on_render(self):
        self._display_surf.fill((0,0,0))
        self.player.draw(self._display_surf, self._image_surf)
        pygame.display.flip()
 
    def on_cleanup(self):
        pygame.quit()
 
    def on_execute(self):
        if self.on_init() == False:
            self._running = False
 
        while( self._running ):
            pygame.event.pump()
            keys = pygame.key.get_pressed() 
 
            if (keys[K_RIGHT]):
                self.player.moveRight()
 
            if (keys[K_LEFT]):
                self.player.moveLeft()
 
            if (keys[K_UP]):
                self.player.moveUp()
 
            if (keys[K_DOWN]):
                self.player.moveDown()
 
            if (keys[K_ESCAPE]):
                self._running = False
            self.on_loop()
            self.on_render()
 
            time.sleep (50.0 / 1000.0);
        self.on_cleanup()
 
if __name__ == "__main__" :
    theApp = App()
    theApp.on_execute()

Result:

python snake
python snake

Game logic
The snake game has some rules:

  • If the snake eats an apple, the apple moves to a new position.
  • If the snake eats an apple, the snakes length grows.
  • If a snake collapses with itself, game over.

We start by creating a new class that enables us to create apples:

class Apple:
    x = 0
    y = 0
    step = 44
 
    def __init__(self,x,y):
        self.x = x * self.step
        self.y = y * self.step
 
    def draw(self, surface, image):
        surface.blit(image,(self.x, self.y))

For simplicity sake, we display the apples as green cubes.  We have this basic code, but it does not do a lot more than moving the snake and showing the apple:

from pygame.locals import *
import pygame
import time
 
class Apple:
    x = 0
    y = 0
    step = 44
 
    def __init__(self,x,y):
        self.x = x * self.step
        self.y = y * self.step
 
    def draw(self, surface, image):
        surface.blit(image,(self.x, self.y)) 
 
 
class Player:
    x = []
    y = []
    step = 44
    direction = 0
    length = 3
 
    updateCountMax = 2
    updateCount = 0
 
    def __init__(self, length):
       self.length = length
       for i in range(0,length):
           self.x.append(0)
           self.y.append(0)
 
    def update(self):
 
        self.updateCount = self.updateCount + 1
        if self.updateCount > self.updateCountMax:
 
            # update previous positions
            for i in range(self.length-1,0,-1):
                print "self.x[" + str(i) + "] = self.x[" + str(i-1) + "]"
                self.x[i] = self.x[i-1]
                self.y[i] = self.y[i-1]
 
            # update position of head of snake
            if self.direction == 0:
                self.x[0] = self.x[0] + self.step
            if self.direction == 1:
                self.x[0] = self.x[0] - self.step
            if self.direction == 2:
                self.y[0] = self.y[0] - self.step
            if self.direction == 3:
                self.y[0] = self.y[0] + self.step
 
            self.updateCount = 0
 
 
    def moveRight(self):
        self.direction = 0
 
    def moveLeft(self):
        self.direction = 1
 
    def moveUp(self):
        self.direction = 2
 
    def moveDown(self):
        self.direction = 3 
 
    def draw(self, surface, image):
        for i in range(0,self.length):
            surface.blit(image,(self.x[i],self.y[i])) 
 
 
class App:
 
    windowWidth = 800
    windowHeight = 600
    player = 0
    apple = 0
 
    def __init__(self):
        self._running = True
        self._display_surf = None
        self._image_surf = None
        self._apple_surf = None
        self.player = Player(10) 
        self.apple = Apple(5,5)
 
    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
 
        pygame.display.set_caption('Pygame pythonspot.com example')
        self._running = True
        self._image_surf = pygame.image.load("pygame.png").convert()
        self._apple_surf = pygame.image.load("apple.png").convert()
 
    def on_event(self, event):
        if event.type == QUIT:
            self._running = False
 
    def on_loop(self):
        self.player.update()
        pass
 
    def on_render(self):
        self._display_surf.fill((0,0,0))
        self.player.draw(self._display_surf, self._image_surf)
        self.apple.draw(self._display_surf, self._apple_surf)
        pygame.display.flip()
 
    def on_cleanup(self):
        pygame.quit()
 
    def on_execute(self):
        if self.on_init() == False:
            self._running = False
 
        while( self._running ):
            pygame.event.pump()
            keys = pygame.key.get_pressed() 
 
            if (keys[K_RIGHT]):
                self.player.moveRight()
 
            if (keys[K_LEFT]):
                self.player.moveLeft()
 
            if (keys[K_UP]):
                self.player.moveUp()
 
            if (keys[K_DOWN]):
                self.player.moveDown()
 
            if (keys[K_ESCAPE]):
                self._running = False
 
            self.on_loop()
            self.on_render()
 
            time.sleep (50.0 / 1000.0);
        self.on_cleanup()
 
if __name__ == "__main__" :
    theApp = App()
    theApp.on_execute()

We have thus to add the game logic. To know if the snakes position matches the apples position, we have to do collision detection. This simply means veryfing that the cordinate of the snake are intersecting with the coordinates of the apple.  We create a new method to do that:

    def isCollision(self,x1,y1,x2,y2,bsize):
        if x1 >= x2 and x1 <= x2 + bsize:
            if y1 >= y2 and y1 <= y2 + bsize:
                return True
        return False

It will return True if the coordinates (x1,y1) are intersection with (x2,y2) given its block size bsize. We call this method to determine if the snake collides with the apple. We need to check this for the entire snake and not only for the head, because we do not want the new position of the apple to be somewhere on the snake. We use the same isCollision method to determine if the snake collides with itself (= lose game).

Full source:

from pygame.locals import *
from random import randint
import pygame
import time
 
class Apple:
    x = 0
    y = 0
    step = 44
 
    def __init__(self,x,y):
        self.x = x * self.step
        self.y = y * self.step
 
    def draw(self, surface, image):
        surface.blit(image,(self.x, self.y)) 
 
 
class Player:
    x = [0]
    y = [0]
    step = 44
    direction = 0
    length = 3
 
    updateCountMax = 2
    updateCount = 0
 
    def __init__(self, length):
       self.length = length
       for i in range(0,2000):
           self.x.append(-100)
           self.y.append(-100)
 
       # initial positions, no collision.
       self.x[1] = 1*44
       self.x[2] = 2*44
 
    def update(self):
 
        self.updateCount = self.updateCount + 1
        if self.updateCount > self.updateCountMax:
 
            # update previous positions
            for i in range(self.length-1,0,-1):
                self.x[i] = self.x[i-1]
                self.y[i] = self.y[i-1]
 
            # update position of head of snake
            if self.direction == 0:
                self.x[0] = self.x[0] + self.step
            if self.direction == 1:
                self.x[0] = self.x[0] - self.step
            if self.direction == 2:
                self.y[0] = self.y[0] - self.step
            if self.direction == 3:
                self.y[0] = self.y[0] + self.step
 
            self.updateCount = 0
 
 
    def moveRight(self):
        self.direction = 0
 
    def moveLeft(self):
        self.direction = 1
 
    def moveUp(self):
        self.direction = 2
 
    def moveDown(self):
        self.direction = 3 
 
    def draw(self, surface, image):
        for i in range(0,self.length):
            surface.blit(image,(self.x[i],self.y[i])) 
 
class Game:
    def isCollision(self,x1,y1,x2,y2,bsize):
        if x1 >= x2 and x1 <= x2 + bsize:
            if y1 >= y2 and y1 <= y2 + bsize:
                return True
        return False
 
class App:
 
    windowWidth = 800
    windowHeight = 600
    player = 0
    apple = 0
 
    def __init__(self):
        self._running = True
        self._display_surf = None
        self._image_surf = None
        self._apple_surf = None
        self.game = Game()
        self.player = Player(3) 
        self.apple = Apple(5,5)
 
    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
 
        pygame.display.set_caption('Pygame pythonspot.com example')
        self._running = True
        self._image_surf = pygame.image.load("block.jpg").convert()
        self._apple_surf = pygame.image.load("block.jpg").convert()
 
    def on_event(self, event):
        if event.type == QUIT:
            self._running = False
 
    def on_loop(self):
        self.player.update()
 
        # does snake eat apple?
        for i in range(0,self.player.length):
            if self.game.isCollision(self.apple.x,self.apple.y,self.player.x[i], self.player.y[i],44):
                self.apple.x = randint(2,9) * 44
                self.apple.y = randint(2,9) * 44
                self.player.length = self.player.length + 1
 
 
        # does snake collide with itself?
        for i in range(2,self.player.length):
            if self.game.isCollision(self.player.x[0],self.player.y[0],self.player.x[i], self.player.y[i],40):
                print("You lose! Collision: ")
                print("x[0] (" + str(self.player.x[0]) + "," + str(self.player.y[0]) + ")")
                print("x[" + str(i) + "] (" + str(self.player.x[i]) + "," + str(self.player.y[i]) + ")")
                exit(0)
 
        pass
 
    def on_render(self):
        self._display_surf.fill((0,0,0))
        self.player.draw(self._display_surf, self._image_surf)
        self.apple.draw(self._display_surf, self._apple_surf)
        pygame.display.flip()
 
    def on_cleanup(self):
        pygame.quit()
 
    def on_execute(self):
        if self.on_init() == False:
            self._running = False
 
        while( self._running ):
            pygame.event.pump()
            keys = pygame.key.get_pressed() 
 
            if (keys[K_RIGHT]):
                self.player.moveRight()
 
            if (keys[K_LEFT]):
                self.player.moveLeft()
 
            if (keys[K_UP]):
                self.player.moveUp()
 
            if (keys[K_DOWN]):
                self.player.moveDown()
 
            if (keys[K_ESCAPE]):
                self._running = False
 
            self.on_loop()
            self.on_render()
 
            time.sleep (50.0 / 1000.0);
        self.on_cleanup()
 
if __name__ == "__main__" :
    theApp = App()
    theApp.on_execute()

Conclusion:

You learned how to create the game snake in Python along with concepts such as collision detection, image loading and event handling. Many things could be added to this little toy game but this serves as a very simple example. 🙂

Next tutorial

Game development with Pygame

Pygame Python
Pygame Python

Welcome to the first tutorial of the series: Building games with Pygame. Games you create with Pygame can be run on any machine that supports Python, including Windows, Linux and Mac OS.

In this tutorial we will explain the fundamental of building a game with Pygame. We’ll start of with the basics and will teach you how to create the basic framework. In the next tutorials you will learn how to make certain types of games.

You may like

PyGame introduction
You’ll end up with a program similar to the one on the right:

A game always starts in an order similar to this (pseudo code):

initialize()
while running():
   game_logic() 
   get_input()
   update_screen()
deinitialize()

The game starts with initialization. All graphics are loaded, sounds are loaded, levels are loaded and any data that needs to be loaded. The game continues running until it receives a quit event. In this game loop we update the game, get input and update the screen. Depending on the game the implementation widely varies, but this fundamental structure is common in all games.

In Pygame we define this as:

import pygame
from pygame.locals import *
 
class App:
 
    windowWidth = 640
    windowHeight = 480
    x = 10
    y = 10
 
    def __init__(self):
        self._running = True
        self._display_surf = None
        self._image_surf = None
 
    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)
        self._running = True
        self._image_surf = pygame.image.load("pygame.png").convert()
 
    def on_event(self, event):
        if event.type == QUIT:
            self._running = False
 
    def on_loop(self):
        pass
 
    def on_render(self):
        self._display_surf.blit(self._image_surf,(self.x,self.y))
        pygame.display.flip()
 
    def on_cleanup(self):
        pygame.quit()
 
    def on_execute(self):
        if self.on_init() == False:
            self._running = False
 
        while( self._running ):
            for event in pygame.event.get():
                self.on_event(event)
            self.on_loop()
            self.on_render()
        self.on_cleanup()
 
if __name__ == "__main__" :
    theApp = App()
    theApp.on_execute()

The Pygame program starts with the constructor __init__(). Once that is finished on_execute() is called. This method runs the game:  it updates the events, updates the screen.  Finally, the game is deinitialized using on_cleanup().

In the initialiasation phase we set the screen resolution and start the Pygame library:

    def on_init(self):
        pygame.init()
        self._display_surf = pygame.display.set_mode((self.windowWidth,self.windowHeight), pygame.HWSURFACE)

We also load the image.

        self._image_surf = pygame.image.load("pygame.png").convert()

This does not draw the image to the screen, that occurs in on_render().

    def on_render(self):
        self._display_surf.blit(self._image_surf,(self.x,self.y))
        pygame.display.flip()

The blit method draws the image (image_surf) to the coordinate (x,y). In Pygame the coordinates start from (0,0) top left to (wind0wWidth, windowHeight).  The method  call pygame.display.flip() updates the screen.

Continue the next tutorial and learn how to add game logic and build games 🙂

Create a chrome plugin with Python

chrome extension made with python
Google Chrome extension created with Python (serverless, method B). (click to zoom)
Google Chrome plugins are written in HTML, JavaScript and and CSS. If you have never written a Chrome plugin before I suggest chrome extensions documentation

You can use Python instead of JavaScript and in this tutorial we will show you how to do that.

In a hurry? Download the code from this site:
Download Extension Code
(and scroll down to Method B)

Create an Google Chrome Plugin

To start, we will have to create a manifest file: manifest.json.

{
  "manifest_version": 2,
 
  "name": "Python Chrome Plugin",
  "description": "This extension runs Python code.",
  "version": "1.0",
 
  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  },
  "permissions": [
    "activeTab",
    "https://ajax.googleapis.com/"
  ]
}

Create a file called popup.html

<!doctype html>
<!--
 This page is shown when the extension button is clicked, because the
 "browser_action" field in manifest.json contains the "default_popup" key with
 value "popup.html".
 -->
<html>
  <head>
    <title>Getting Started Extension's Popup</title>
    <style>
      body {
        font-family: "Segoe UI", "Lucida Grande", Tahoma, sans-serif;
        font-size: 100%;
      }
      #status {
        /* avoid an excessively wide status text */
        white-space: pre;
        text-overflow: ellipsis;
        overflow: hidden;
        max-width: 400px;
      }
    </style>
 
    <!--
      - JavaScript and HTML must be in separate files: see our Content Security
      - Policy documentation[1] for details and explanation.
      -
      - [1]: https://developer.chrome.com/extensions/contentSecurityPolicy
     -->
    <script src="popup.js"></script>
  </head>
  <body>
    <div id="status"></div>
    <img id="image-result" hidden>
  </body>
</html>

Finally get an icon and save it as icon.png. Open chrome://extensions and press developer mode. Press “load unpacked extension”, select your directory and press ok.

Adding Python to the Chrome extension

We have two options to add Python into a chrome extension:

  • Method A: Include Brython in an iframe (requires server)
  • Method B: Compile Python to Javascript using Rapydscript (best, serverless, pure extension.)

Method A: Python (Brython) in iframe

Now that you have the basics right we can add Python to the code. To run Python in the browser you have several options including Brython and emcascripten. We decided to give Brython a try. We will run the Brython script from a server. Change popup.html to:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta charset="iso-8859-1">
<style>
body {    
    margin: 0 !important;
    padding: 0 !important;
    width: 800;
}
 
#frame {
    overflow: hidden;
    width:790;
    height:324;
}
</style>
</head>
<body onLoad="">
<iframe src=http://brython.info/console.html id="frame" seamless="seamless" scrolling="no"></iframe>
</body>
</html>

Once you restart your plugin you will have a Python (Brython) interpreter inside your Google Chrome.

Python inside Google Chrome
Python inside Google Chrome

Running your own scripts
To run your own script simply change the url inside the popup.html frame:

<iframe src="BRYTHON SCRIPT URL" id="frame" seamless="seamless" scrolling="no"></iframe>

The script should run on your own server. You can run any Brython script from the web. Using Brython you can simply type Python code inside the script tags. Have a look at this Brython examples or simply browse the gallery.

Method B: Compile Python to Javascript. (no server, pure extension)

There are several tools to compile Python to Javascript. Rapydscript works fine, Pyjs does not work well with chrome (requires special parameter on start).
Install Rapydscript with:

sudo apt-get install npm
sudo ln -s /usr/bin/nodejs /usr/bin/node
sudo npm install rapydscript

Download the code from this site:
Download Extension Code
Change the file /src/hello.py to you needs:

# Example Python script 
# (for rapydscript, a python to javascript compiler)
 
#def doHelloMessage():
#    alert('hello')
#doHelloMessage()
 
# modify html page
document.getElementById("result").innerHTML = 'Compiled Python script in Chrome' 
 
# write into log 
console.log('hello from python')

Run:

./make.sh

You can find your extension in /compiledpythonextension/. Load it in chrome as unpackaged extension and see it working 🙂

Concluding:

Chrome plugins are created using HTML, JavaScript and CSS. We can use Python to create normal Chrome extensions using a Python to Javascript compiler (Rapydscript).

Leave a comment 🙂
 

Posts navigation

1 2 3 9 10 11 12 13 14 15