Polish Python Coders Group Forum

Wszystko o języku Python => Wasza twórczość => Wątek zaczęty przez: Unk 17:12 04/02/09



Tytuł: Game of life (pygame)
Wiadomość wysłana przez: Unk 17:12 04/02/09
Chciałbym się pochwalić pierwszym programikiem w pygame jaki właśnie napisałem :). Jest to standardowa gra w życie (http://pl.wikipedia.org/wiki/Game_of_life (http://pl.wikipedia.org/wiki/Game_of_life)).

Program można wywołać w standardowych ustawieniach bez żadnych opcji - tworzy się wtedy plansza 50x50 losowo wypełniona. Można też użyć opcji:

-h wyświetli się help
-f nazwa_pliku załaduje się obrazek który wcześniej można sobie przygotować, najlepiej w formacie PNG
-s liczba zmieniamy rozmiar kwadratu (komórki)
-r liczba liczba zmieniamy rozmiary X Y planszy

W grze mamy też opisane zachowanie dla klawiszy:
ESC wyjście z programu
F przełączenie na pełen ekran i z powrotem
Num- Num+ zmiana rozdzielczości

Opisane też są klawisze strzałek ale to na razie nie działa, a ma obsługiwać przesunięcie ekranu gdyby komórki się na nim już nie mieściły. Nie wiem czemu to nie działa, ale będę jeszcze walczył, jak będzie gotowe to wkleję nowa wersję programu :).Wywaliłem to z programu.

Poniżej kilka fajnych figur które można załadować do programu i zobaczyć jak latają :):

(http://rfmf.webs.com/inne/dakota.png)
(http://rfmf.webs.com/inne/fontanna.png)
(http://rfmf.webs.com/inne/szybowiec.png)

Przy roznych wymiarach XY cos sie sypie :)

Kod
#! usr/bin/env python
 
import pygame, sys, os
from random import randint
import pygame.font
from pygame.locals import *
import copy
from optparse import OptionParser
import Image
import time
 
 
class Pole():
def __init__(self,x,y,czy_zywy,kolor,bok_kwadratu):
self.x = x
self.y = y
self.kolor = kolor
self.zywy = czy_zywy
self.bok = bok_kwadratu
 
def obiekt(self):
if self.zywy == 1:
pozycja = (self.x, self.y)
rozmiar = (self.bok,self.bok)
pygame.draw.rect(screen, self.kolor, Rect(pozycja, rozmiar))
 
def numer(self):
numer = "X" + str(self.x/self.bok) +"Y"+ str(self.y/self.bok)
numertext = czcionka.render(numer, 1, (250, 250, 250))
screen.blit(numertext, (self.x, self.y))
 
class Plansza:
def __init__(self, numer, x, y):
self.plansza = []
self.x = x
self.y = y
if options.square:
self.bok_kwadratu = options.square
else:
self.bok_kwadratu = 10
self.wypelnij_plansze()
 
def wypelnij_plansze(self):
for i in range(self.x):
for j in range(self.y):
czy_zywy = 0
kolor = 1
pole = Pole(i*self.bok_kwadratu,j*self.bok_kwadratu,czy_zywy,kolor,self.bok_kwadratu)
self.plansza.append(pole)
 
def przelicz_xy_na_liste(self, wspolrzedne):
self.j = (wspolrzedne[1]*self.x) + (wspolrzedne[0])
return self.j
 
def rysuj_plansze(self):
for i in range(self.x):
for j in range(self.y):
numer_pola = self.przelicz_xy_na_liste((i,j))
self.plansza[numer_pola].obiekt()
"""Odkomentuj linie ponizej aby zobaczyc wspolrzedne dla kazdej komorki. Dobrze wyglada tylko gdy bok kwadratu >50"""
#self.plansza[numer_pola].numer()
 
def wylosujPoczatkowyStan(self):
for x in range(self.x):
for y in range(self.y):
wspolrzedne = [x,y]
self.plansza[self.przelicz_xy_na_liste(wspolrzedne)].zywy = randint(0, 1)
 
def zaladuj_obrazek(self):
im = Image.open(options.filename)
for x in range(im.size[0]):
for y in range(im.size[1]):
if im.getpixel((x,y)) == (255, 255, 255):
self.plansza[self.przelicz_xy_na_liste((y,x))].zywy = 0
else:
self.plansza[self.przelicz_xy_na_liste((y,x))].zywy = 1
 
 
class Generacja:
def __init__(self,x,y):
self.x = x
self.y = y
self.zywe = [2,3]
self.martwe = [3]
self.tablica = Plansza(1,self.x,self.y)
if options.filename:
self.tablica.zaladuj_obrazek()
else:
self.tablica.wylosujPoczatkowyStan()
self.tablica_nowa = Plansza(2,self.x,self.y)
 
 
def przejscie(self):
if generacja == 0:
self.tablica.rysuj_plansze()
else:
for x in range(self.tablica.x):
for y in range(self.tablica.y):
"""Sprawdzamy ilu komorka [x,y] ma sasiadow i jaki jest jej los.
Funkcja los_komorki() wypelnia nam obiekt tablica_nowa"
""
wspolrzedne = [x,y]
self.los_komorki(self.policz_sasiadow(wspolrzedne),wspolrzedne)
self.tablica = copy.deepcopy(self.tablica_nowa)
self.tablica.rysuj_plansze()
 
 
def los_komorki(self, liczba_sasiadow, wspolrzedne):
"""Ustawiamy wartosc komorki w nastepnej generacji w zaleznosci od liczby jej saisadow i jej stanu obecnego."""
self.liczba_sasiadow = liczba_sasiadow
self.komorka = self.tablica.przelicz_xy_na_liste(wspolrzedne)
 
"""Standardowo: Zywa komorka z 2 albo 3 zywymi sasiadami pozostaje nadal zywa; przy innej liczbie sasiadow umiera."""
if (self.tablica.plansza[self.komorka].zywy == 1):
"""Sprawdzamy czy liczba sisiadow dla zywej komorki zgadza sie z warunkami okreslonymi w self.zywe"""
if (self.liczba_sasiadow in self.zywe):
self.tablica_nowa.plansza[self.komorka].zywy = 1
self.tablica_nowa.plansza[self.komorka].kolor = (81,128,69) #ciemny zielony
else:
self.tablica_nowa.plansza[self.komorka].zywy = 0
else:
"""Sprawdzamy czy liczba sisiadow dla martwej komorki zgadza sie z warunkami okreslonymi w self.martwe"""
if (self.liczba_sasiadow in self.martwe):
self.tablica_nowa.plansza[self.komorka].zywy = 1
self.tablica_nowa.plansza[self.komorka].kolor = (81,174,69) #jasny zielony
else:
self.tablica_nowa.plansza[self.komorka].zywy = 0
 
def policz_sasiadow(self, wspolrzedne):
"""Sprawdzamy ili sasiadow ma zywa/martwa komorka z danej pozycji."""
liczba_sasiadow = 0
akt_wspolrzedne = wspolrzedne
 
 
x = akt_wspolrzedne[0]
y = akt_wspolrzedne[1]
 
"""Opisujemy kierunki geograficznie. Komorka znajduje sie w centrum  - [x,y]"""
pn_zach = [x-1,y-1]
pn = [x,y-1]
pn_wsch = [x+1,y-1]
zach = [x-1,y]
wsch = [x+1,y]
pd_zach = [x-1,y+1]
pd = [x,y+1,0]
pd_wsch = [x+1,y+1]
 
"""Szczegolne przypadki gdy komorka [x,y] znajduje sie na krawedzi planszy"""
 
if y == 0:
pn_zach = [x-1,self.tablica.y-1]
pn = [x,self.tablica.y-1]
pn_wsch = [x+1,self.tablica.y-1]
if y == self.tablica.y-1:
pd_zach = [x-1,0]
pd = [x,0]
pd_wsch = [x+1,0]
if x == 0:
pn_zach = [self.tablica.x-1,y-1]
zach = [self.tablica.x-1,y]
pd_zach = [self.tablica.x-1,y+1]
if x == self.tablica.x-1:
pn_wsch = [0,y-1]
wsch = [0,y]
pd_wsch = [0,y+1]
if (x == 0) and (y == 0):
pn_zach = [self.tablica.x-1,self.tablica.y-1]
if (x == 0) and (y == self.tablica.y-1):
pd_zach = [self.tablica.x-1,0]
if (x == self.tablica.x-1) and (y == 0):
pn_wsch = [0,self.tablica.y-1]
if (x == self.tablica.x-1) and (y == self.tablica.y-1):
pd_wsch = [0,0]
 
 
"""Sprawdzamy ilu sasiadow ma komorka [x,y]"""
 
if self.tablica.plansza[self.tablica.przelicz_xy_na_liste(pn_zach)].zywy == 1:
liczba_sasiadow += 1
if self.tablica.plansza[self.tablica.przelicz_xy_na_liste(pn)].zywy == 1:
liczba_sasiadow += 1
if self.tablica.plansza[self.tablica.przelicz_xy_na_liste(pn_wsch)].zywy == 1:
liczba_sasiadow += 1
if self.tablica.plansza[self.tablica.przelicz_xy_na_liste(zach)].zywy == 1:
liczba_sasiadow += 1
if self.tablica.plansza[self.tablica.przelicz_xy_na_liste(wsch)].zywy == 1:
liczba_sasiadow += 1
if self.tablica.plansza[self.tablica.przelicz_xy_na_liste(pd_zach)].zywy == 1:
liczba_sasiadow += 1
if self.tablica.plansza[self.tablica.przelicz_xy_na_liste(pd)].zywy == 1:
liczba_sasiadow += 1
if self.tablica.plansza[self.tablica.przelicz_xy_na_liste(pd_wsch)].zywy == 1:
liczba_sasiadow += 1
 
 
return liczba_sasiadow
 
def policz_zywych(self):
liczba_zywych = 0
for i in range(len(self.tablica.plansza)):
if self.tablica.plansza[i].zywy == 1:
liczba_zywych += 1
else:
pass
return liczba_zywych
 
 
def parser():
parser = OptionParser()
parser.add_option("-f", "--file", dest="filename",
 type="string", action="store",
                 help="Poczatkowa tablica utworzona zostanie ze wskazanego obrazka.")
parser.add_option("-r", "--rozmiary",
                 type="int", dest="rozmiary", nargs=2,
                 help="Rozmiary wymiarow X Y. Np. -r 10, -r 100 100 itp. Domyslnie 50x50.")
parser.add_option("-s", "--square",
                 type="int", dest="square",
                 help="Romiar boku kwadratu (pojedynczej komorki) w px. Np. -s 20. Domyslnie 10.")
global options
(options, args) = parser.parse_args()
 
def zmiana_rozdzielczosci(zmiana):
"""Funkcja zmiany rozdzielczosci."""
rozdzielczosci = pygame.display.list_modes()
rozdzielczosci.reverse() #odwracamy tak aby mniejsze byly na poczatku
obecna_rozdzielczosc = rozdzielczosci.index(rozdzielczosc)
print obecna_rozdzielczosc
if zmiana == "plus":
if obecna_rozdzielczosc != (len(rozdzielczosci)-1):
nowa_rozdzielczosc = rozdzielczosci[obecna_rozdzielczosc+1]
else:
nowa_rozdzielczosc = rozdzielczosci[obecna_rozdzielczosc]
elif zmiana == "minus":
if obecna_rozdzielczosc != 0:
nowa_rozdzielczosc = rozdzielczosci[obecna_rozdzielczosc-1]
else:
nowa_rozdzielczosc = rozdzielczosci[obecna_rozdzielczosc]
"""Ustawiamy nowa rozdzielczosc w zaleznosci czy aktualnie znajdujemy sie w trybie Fullscreen czy nie"""
if Fullscreen:
screen = pygame.display.set_mode(nowa_rozdzielczosc, FULLSCREEN, 32)
else:
screen = pygame.display.set_mode(nowa_rozdzielczosc, 0, 32)
 
"""Zwracamy nowa rozdzielczosc"""
return nowa_rozdzielczosc
 
 
def wymiary_obrazka():
im = Image.open(options.filename)
wymiary = im.size
return wymiary
 
def main():
pygame.init()
pygame.font.init()
parser()
"""Opis okna i wyswietlenie:"""
"""1) ustawienie rozdzielczosci"""
rozdzielczosc = width, height = 800, 600
"""2) ustawienie wartosci Fullscreen (False - wyswietlanie w oknie, True - wyswietlanie pelnoekranowe)"""
Fullscreen = False
"""3) stworzenie okna"""
screen = pygame.display.set_mode(rozdzielczosc, Fullscreen, 32)
"""4) ustawienie napisu na pasku"""
pygame.display.set_caption('Game Of Life')
"""5) ustawienie czy myszka ma byc widoczna na oknie (1) czy nie (0)"""
pygame.mouse.set_visible(1)
"""6) ustawienie czcionki"""
czcionka = pygame.font.SysFont("dejavusans", 10)
"""7) ustawienie zmiennych jako globalne (potrzebne w funkcji zmiany rozdzielczosci i w klasie Plansza"""
global czcionka
global rozdzielczosc
global screen
global Fullscreen
"""8) inicjacja okna"""
pygame.display.init()
"""Koniec opisu okna"""
 
generacja = 0
global generacja
if options.filename:
x,y = wymiary_obrazka()
gen = Generacja(x,y)
else:
if options.rozmiary:
gen = Generacja(options.rozmiary[0],options.rozmiary[1])
else:
gen = Generacja(50,50)
 
while True:
"""Opis zdarzen"""
for event in pygame.event.get():
"""Przycisk zamykajacy okno (X)"""
if event.type == QUIT:
sys.exit()
"""Opis zdarzen dla klawiszy"""
if event.type == pygame.KEYDOWN:
"""Klawisz zamkniecia okna"""
if event.key == K_ESCAPE:
sys.exit()
"""Klawisz Fullscreen"""
if event.key == K_f:
Fullscreen = not Fullscreen
if Fullscreen:
print "Fullscreen On"
screen = pygame.display.set_mode(rozdzielczosc, FULLSCREEN, 32)
else:
print "Fullscreen Off"
screen = pygame.display.set_mode(rozdzielczosc, 0, 32)
"""Klawisze do funkcji zmieniajacych rozdzielczosc"""
if event.key == K_KP_PLUS:
print "rozdzielczosc plus"
zmiana = "plus"
rozdzielczosc = zmiana_rozdzielczosci(zmiana)
if event.key == K_KP_MINUS:
print "rozdzielczosc minus"
zmiana = "minus"
rozdzielczosc = zmiana_rozdzielczosci(zmiana)
 
"""Monitorowanie ruchu myszka"""
if event.type == pygame.MOUSEMOTION:
print "mouse at (%d, %d)" % event.pos
else:
print event
 
"""Dzielimy ekran na czesci. 3/4 na gre, 1/4 na informacje"""
"""1) Czesc z gra"""
screen.set_clip(0, 0,rozdzielczosc[1],rozdzielczosc[0]*3/4)
"""Czyscimy ekran gry i robimy przejscie"""
screen.fill((0, 0, 0))
gen.przejscie()
"""2) Czesc z info"""
screen.set_clip(rozdzielczosc[0]*3/4, 0,rozdzielczosc[1],rozdzielczosc[0])
"""Czyscimy ekran info"""
screen.fill((0, 0, 0))
"""Tworzymy napis z rozmiarami planszy i wyswietlamy go"""
rozmiary = "rozmiar planszy: " + str(gen.x) + "x" +  str(gen.y)
rozmiary_text = czcionka.render(rozmiary, 1, (250, 250, 250))
screen.blit(rozmiary_text, (rozdzielczosc[0]*3/4+10, 10))
"""Tworzymy napis z numerem generacji i wyswietlamy go"""
numer_generacji = "generacja: " + str(generacja)
numer_generacji_text = czcionka.render(numer_generacji, 1, (250, 250, 250))
screen.blit(numer_generacji_text, (rozdzielczosc[0]*3/4+10, 30))
"""Tworzymy napis z liczba zywych w danej generacji i wyswietlamy go"""
liczba_zywych_teraz = gen.policz_zywych()
liczba_zywych_w_generacji = "liczba zywych: " + str(liczba_zywych_teraz)
liczba_zywych_w_generacji_text = czcionka.render(liczba_zywych_w_generacji, 1, (250, 250, 250))
screen.blit(liczba_zywych_w_generacji_text, (rozdzielczosc[0]*3/4+10, 50))
"""Tworzymy info o klawiszach"""
klawisze = "KLAWISZE:"
wyjscie = "wyjscie: ESC"
pelen_ekran = "pelen ekran: F"
rozdz = "zmiana rozdzielczosci: Num+ Num-"
klawisze_text = czcionka.render(klawisze, 1, (250, 250, 250))
wyjscie_text = czcionka.render(wyjscie, 1, (250, 250, 250))
pelen_ekran_text = czcionka.render(pelen_ekran, 1, (250, 250, 250))
rozdz_text = czcionka.render(rozdz, 1, (250, 250, 250))
screen.blit(klawisze_text, (rozdzielczosc[0]*3/4+10, 70))
screen.blit(wyjscie_text, (rozdzielczosc[0]*3/4+10, 90))
screen.blit(pelen_ekran_text, (rozdzielczosc[0]*3/4+10, 110))
screen.blit(rozdz_text, (rozdzielczosc[0]*3/4+10, 130))
"""Tworzymy info o autorze"""
autor = "by Unk :)"
autor_text = czcionka.render(autor, 1, (250, 250, 250))
screen.blit(autor_text, (rozdzielczosc[0]*3/4+10, rozdzielczosc[1]-15))
 
 
generacja += 1
 
 
 
pygame.display.flip()
 
 
if __name__ == '__main__':
main()