Skip to navigation
Logo Penaz's Area

cat /dev/random > penaz

Pygame: Un esempio di Platform di base


Un esempio della costruzione di un gioco a piattaforme estremamente basilare in Python e PyGame: Pointless Platformer!!

Buongiorno a tutti, dopo diverso tempo ho deciso di riprendere in mano pygame ( sito ufficiale ) e provare a costruire un piccolo gioco a piattaforme, con tutti i problemi che ne derivano. Alla fine di tutto sono uscito con questo esempio molto condensato che spero sia utile a chi un giorno si ritrovasse con la voglia di programmare per davvero (senza strumenti come GameMaker o Game Editor) un videogioco.

Questo gioco non ha alcun obiettivo (per questo è Pointless) ma ha tutte le caratteristiche di un gioco a piattaforme:

  • Simulazione della gravità (senza velocità terminale, anche se è semplice aggiungerla)
  • Collisioni con i blocchi delle piattaforme
  • Movimento del personaggio in tutte le direzioni, salti compresi
  • Una piccola routine per costruire i livelli (a partire da una lista di "#")

Il codice è ampiamente commentato nella gran parte delle proprie sezioni e, diversamente da altri miei progetti come Primitive Shooter è scritto in Python3.

Se volete provarlo ed annoiarvi un pochino i pulsanti sono semplicemente:

  • Freccia Destra > Vai a destra
  • Freccia Sinistra > Vai a sinistra
  • Freccia Su > Salta

Per uscire dal gioco è sufficiente chiudere la finestra di pygame.

Attenzione: *A causa di un baco di Pygame se avviate il gioco con IDLE (L'editor di Python usato soprattutto sotto windows) vi ritroverete con l'editor bloccato se chiuderete la finestra di pygame, in tal caso è sufficiente inserire la riga

pygame.quit()

prima di quit()

in modo da ottenere:

if event.type==QUIT:
    pygame.quit()
    quit()</p>

Il gioco sta comodamente entro le 150 righe, commenti compresi, ecco il codice:

#!/usr/bin/env python
#Imports
import pygame
from pygame.locals import *
from sys import exit
#Inizializziamo Pygame, schermo e clock
pygame.init()
screen=pygame.display.set_mode((640,480),0,32)
pygame.display.set_caption("Pointless Platformer!!")
clock=pygame.time.Clock()
"""Creiamo i 2 principali gruppi di sprites: le sprites da disegnare in generale
e le piattaforme, in un gruppo separato per poter usare le funzioni di collisione"""
todraw=pygame.sprite.Group()
plats=pygame.sprite.Group()
#Classe per la creazione delle piattaforme
class Platform(pygame.sprite.Sprite):
    def __init__(self,x,y):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((20,20))
        self.image.fill((255,0,0))
        self.rect=self.image.get_rect()
        self.rect.x=x
        self.rect.y=y
        plats.add(self)
    def update(self):
        screen.blit(self.image, (self.rect.x, self.rect.y))
#Classe giocatore
class Player(pygame.sprite.Sprite):
    move_x=0
    move_y=0
    onground=False
    def __init__(self):
        pygame.sprite.Sprite.__init__(self)
        self.image=pygame.Surface((10,10))
        self.image.fill((255,255,255))
        self.rect=self.image.get_rect()
        self.rect.x=20
        self.rect.y=20
        todraw.add(self)
    def update(self):
        self.rect.x+=self.move_x
        xcoll()
        self.rect.y+=self.move_y
        ycoll()
        screen.blit(self.image, (self.rect.x, self.rect.y))
""" Le collisioni vengono calcolate separatamente sull'asse x ed y
altrimenti il nostro personaggio sembrerà teletrasportarsi"""
def xcoll():
    collision=pygame.sprite.spritecollide(player, plats, False)
    for block in collision:
        if player.move_x>0:
            player.rect.right=block.rect.left
        if player.move_x<0:
            player.rect.left=block.rect.right
def ycoll():
        collision=pygame.sprite.spritecollide(player, plats, False)
        player.onground=False
        for block in collision:
            if player.move_y==0:
                player.onground=True
            if player.move_y<0:
                player.rect.top=block.rect.bottom
                player.move_y=0     #serve per evitare l'impressione che il giocatore si "appiccichi" al soffitto
                player.onground=False
            if player.move_y>0:
                player.rect.bottom=block.rect.top
                player.onground=True
"""Una semplice routine per costruire il livello, ogni "#" corrisponde
ad un blocco 20x20 pixel di terreno/piattaforma"""
def build():
    myx=0
    myy=0
    level=[
            '###########################',
            '#             #           #',
            '#            #######      #',
            '#                      ####',
            '#   ##            ##      #',
            '#  ####      #########    #',
            '###########################']
    for r in level:
        for c in r:
            if c==' ':
                pass
            elif c=='#':
                p=Platform(myx,myy)
            myx+=20
        myy+=20
        myx=0
#Simulazione di gravità, molto semplicistica
def gravity():
    if not player.onground:
        player.move_y+=0.9
player=Player()
build()
#Ciclo di gioco
while True:
    screen.fill((0,0,0))
    gravity()
    #Ciclo eventi
    for event in pygame.event.get():
        if event.type==QUIT:  #Uscita
            exit()
        if event.type==KEYDOWN: #Viene premuto un tasto
            if event.key==K_UP:   #Su
                if player.onground:   #Salta solo se il giocatore è a terra
                    player.move_y=-9
                    player.onground=False
            if event.key==K_LEFT: #Sinistra
                player.move_x=-5
            if event.key==K_RIGHT:   #Destra
                player.move_x=5
        if event.type==KEYUP:  #Viene rilasciato un tasto
            if event.key==K_LEFT:
                player.move_x=0
            if event.key==K_RIGHT:
                player.move_x=0
    #Aggiorna tutte le sprites e lo schermo
    todraw.update()
    plats.update()
    pygame.display.update()
    #Faccio in modo che il gioco non vada oltre i 30FPS
    clock.tick(30)

Questo è quanto. Buona programmazione a tutti!

Saluti e alla prossima!

Penaz.