Jocs amb Python¶
Frameworks per al desenvolupament de jocs¶
| Framework | Descripció |
|---|---|
| Pygame | El més popular. Basat en SDL, ideal per a jocs 2D. |
| PyKyra | Basat en SDL i Kyra, molt ràpid. |
| Pyglet | Sense dependències, usa OpenGL directament. |
| PyOpenGL | Binding de Python per a OpenGL. |
| Kivy | Interfícies multitàctil, funciona en mòbil i escriptori. |
| Panda3D | Motor 3D complet. |
| Cocos2d | Jocs 2D amb escenes i transicions. |
| Python-Ogre | Binding del motor 3D Ogre. |
| Ren'Py | Especialitzat en visual novels. |
Referència: Pygame Tutorial — GeeksforGeeks
Exemples inclosos¶
Egg Catcher — samples/egg/egg.py¶
Tecnologia: Tkinter (Canvas)
Joc en què ous de colors cauen des de la part superior de la pantalla i el jugador ha de recollir-los amb una cistella que es mou esquerra/dreta amb les tecles de cursor.
Mecàniques:
- Ous generats aleatòriament a intervals regulars
- La velocitat i la freqüència augmenten amb cada ou recollit (factor de dificultat
0.95) - 3 vides: es perd una vida cada cop que un ou toca terra
- Puntuació de 10 punts per ou recollit
Controls: ← →
Conceptes Python il·lustrats:
tkinter.Canvas: dibuix de formes (create_oval,create_arc,create_rectangle)itertools.cycleper ciclar colorsroot.after()per al bucle de joc sense bloquejar la interfície- Detecció de col·lisions manual comparant coordenades
Codi:
from itertools import cycle
from random import randrange
from tkinter import Canvas, Tk, messagebox, font
canvas_width = 800
canvas_height = 400
root = Tk()
root.title("Egg Catcher")
c = Canvas(root, width=canvas_width, height=canvas_height, background="deep sky blue")
c.create_rectangle(-5, canvas_height-100, canvas_width+5, canvas_height+5, fill="sea green", width=0)
c.create_oval(-80, -80, 120, 120, fill='orange', width=0)
c.pack()
color_cycle = cycle(["light blue", "light green", "light pink", "light yellow", "light cyan"])
egg_width = 45
egg_height = 55
egg_score = 10
egg_speed = 250
egg_interval = 4000
difficulty = 0.95
catcher_color = "blue"
catcher_width = 100
catcher_height = 100
catcher_startx = canvas_width / 2 - catcher_width / 2
catcher_starty = canvas_height - catcher_height - 20
catcher_startx2 = catcher_startx + catcher_width
catcher_starty2 = catcher_starty + catcher_height
catcher = c.create_arc(catcher_startx, catcher_starty, catcher_startx2, catcher_starty2,
start=200, extent=140, style="arc", outline=catcher_color, width=3)
game_font = font.nametofont("TkFixedFont")
game_font.config(size=18)
score = 0
score_text = c.create_text(10, 10, anchor="nw", font=game_font, fill="darkblue",
text="Score: " + str(score))
lives_remaining = 3
lives_text = c.create_text(canvas_width-10, 10, anchor="ne", font=game_font, fill="darkblue",
text="Lives: " + str(lives_remaining))
eggs = []
def create_egg():
x = randrange(10, 740)
y = 40
new_egg = c.create_oval(x, y, x+egg_width, y+egg_height, fill=next(color_cycle), width=0)
eggs.append(new_egg)
root.after(egg_interval, create_egg)
def move_eggs():
for egg in eggs:
(eggx, eggy, eggx2, eggy2) = c.coords(egg)
c.move(egg, 0, 10)
if eggy2 > canvas_height:
egg_dropped(egg)
root.after(egg_speed, move_eggs)
def egg_dropped(egg):
eggs.remove(egg)
c.delete(egg)
lose_a_life()
if lives_remaining == 0:
messagebox.showinfo("Game Over!", "Final Score: " + str(score))
root.destroy()
def lose_a_life():
global lives_remaining
lives_remaining -= 1
c.itemconfigure(lives_text, text="Lives: " + str(lives_remaining))
def check_catch():
(catcherx, catchery, catcherx2, catchery2) = c.coords(catcher)
for egg in eggs:
(eggx, eggy, eggx2, eggy2) = c.coords(egg)
if catcherx < eggx and eggx2 < catcherx2 and catchery2 - eggy2 < 40:
eggs.remove(egg)
c.delete(egg)
increase_score(egg_score)
root.after(100, check_catch)
def increase_score(points):
global score, egg_speed, egg_interval
score += points
egg_speed = int(egg_speed * difficulty)
egg_interval = int(egg_interval * difficulty)
c.itemconfigure(score_text, text="Score: " + str(score))
def move_left(event):
(x1, y1, x2, y2) = c.coords(catcher)
if x1 > 0:
c.move(catcher, -20, 0)
def move_right(event):
(x1, y1, x2, y2) = c.coords(catcher)
if x2 < canvas_width:
c.move(catcher, 20, 0)
c.bind("<Left>", move_left)
c.bind("<Right>", move_right)
c.focus_set()
root.after(1000, create_egg)
root.after(1000, move_eggs)
root.after(1000, check_catch)
root.mainloop()
Snake — samples/snake/snake.py¶
Tecnologia: Pygame
El clàssic joc de la serp: controla una serp que creix cada cop que menja un aliment. El joc acaba si la serp xoca amb les parets o amb ella mateixa.
Nota: Pygame pot no estar disponible per a Python 3.11+. Si cal, instal·la-ho amb
pip install pygame --pre.
Mecàniques:
- Serp formada per una llista de segments de
10×10píxels - Aliment col·locat aleatòriament en posicions alineades a la graella
- En menjar, la longitud de la serp augmenta en 1
- Si la serp surt dels límits o es mossega, apareix pantalla de game over
- Opció de tornar a jugar (
C) o sortir (Q)
Controls: ← → ↑ ↓
Conceptes Python il·lustrats:
- Bucle de joc amb
pygame.time.Clockiclock.tick() - Dibuix amb
pygame.draw.rect - Gestió d'events de teclat amb
pygame.event.get() - Llista com a cua de segments de la serp
Codi:
import pygame
import time
import random
pygame.init()
white = (255, 255, 255)
yellow = (255, 255, 102)
black = (0, 0, 0)
red = (213, 50, 80)
green = (0, 255, 0)
blue = (50, 153, 213)
dis_width = 800
dis_height = 600
dis = pygame.display.set_mode((dis_width, dis_height))
pygame.display.set_caption('Snake Game')
clock = pygame.time.Clock()
snake_block = 10
snake_speed = 10
font_style = pygame.font.SysFont("bahnschrift", 25)
score_font = pygame.font.SysFont("comicsansms", 35)
def Your_score(score):
value = score_font.render("Your Score: " + str(score), True, yellow)
dis.blit(value, [0, 0])
def our_snake(snake_block, snake_list):
for x in snake_list:
pygame.draw.rect(dis, black, [x[0], x[1], snake_block, snake_block])
def message(msg, color):
mesg = font_style.render(msg, True, color)
dis.blit(mesg, [dis_width / 6, dis_height / 3])
def gameLoop():
game_over = False
game_close = False
x1 = dis_width / 2
y1 = dis_height / 2
x1_change = 0
y1_change = 0
snake_List = []
Length_of_snake = 1
foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
while not game_over:
while game_close:
dis.fill(blue)
message("You Lost! Press C-Play Again or Q-Quit", red)
Your_score(Length_of_snake - 1)
pygame.display.update()
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_q:
game_over = True
game_close = False
if event.key == pygame.K_c:
gameLoop()
for event in pygame.event.get():
if event.type == pygame.QUIT:
game_over = True
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
x1_change = -snake_block
y1_change = 0
elif event.key == pygame.K_RIGHT:
x1_change = snake_block
y1_change = 0
elif event.key == pygame.K_UP:
y1_change = -snake_block
x1_change = 0
elif event.key == pygame.K_DOWN:
y1_change = snake_block
x1_change = 0
if x1 >= dis_width or x1 < 0 or y1 >= dis_height or y1 < 0:
game_close = True
x1 += x1_change
y1 += y1_change
dis.fill(blue)
pygame.draw.rect(dis, green, [foodx, foody, snake_block, snake_block])
snake_Head = [x1, y1]
snake_List.append(snake_Head)
if len(snake_List) > Length_of_snake:
del snake_List[0]
for x in snake_List[:-1]:
if x == snake_Head:
game_close = True
our_snake(snake_block, snake_List)
Your_score(Length_of_snake - 1)
pygame.display.update()
if x1 == foodx and y1 == foody:
foodx = round(random.randrange(0, dis_width - snake_block) / 10.0) * 10.0
foody = round(random.randrange(0, dis_height - snake_block) / 10.0) * 10.0
Length_of_snake += 1
clock.tick(snake_speed)
pygame.quit()
quit()
gameLoop()
Cursa de Tortugues — samples/turtle/index.py¶
Tecnologia: Mòdul turtle (estàndard de Python)
Simulació d'una cursa de 6 tortugues de colors. El jugador aposta per una tortuga abans de la cursa i al final s'anuncia si ha guanyat o perdut.
Mecàniques:
- 6 tortugues (vermell, taronja, groc, verd, blau, morat) alineades a l'esquerra
- Cada iteració del bucle, cada tortuga avança un nombre aleatori de passos (0–10)
- La primera que supera
x = 230guanya - L'aposta s'introdueix amb
screen.textinput()abans de la cursa
Conceptes Python il·lustrats:
- Mòdul
turtle:Turtle,Screen,penup(),goto(),forward(),xcor() screen.textinput()per a entrada de l'usuari en una finestra gràfica- Bucle
whileamb condició d'acabada basada en l'estat del joc - Llista de tortugues i iteració simultània
Codi:
from turtle import Turtle, Screen
import random
race_active = False
screen = Screen()
screen.setup(width=500, height=400)
turtle_bet = screen.textinput(
title="Make your bet!",
prompt="Which turtle do you think will win? Enter a colour: "
)
colours = ["red", "orange", "yellow", "green", "blue", "purple"]
y_positions = (-100, -60, -20, 20, 60, 100)
all_turtles = []
for turtle_index in range(0, 6):
new_turtle = Turtle(shape="turtle")
new_turtle.color(colours[turtle_index])
new_turtle.penup()
new_turtle.goto(x=-200, y=(y_positions[turtle_index]))
all_turtles.append(new_turtle)
if turtle_bet:
race_active = True
while race_active:
for turtle in all_turtles:
if turtle.xcor() > 230:
race_active = False
winning_colour = turtle.pencolor()
if winning_colour == turtle_bet:
print(f"You win! The {winning_colour} turtle is the winner.")
else:
print(f"You lose. The {winning_colour} turtle is the winner.")
rand_distance = random.randint(0, 10)
turtle.forward(rand_distance)
screen.exitonclick()