[CLANAK 7.] - Python 4: Klase i instance 1

Koki007 nas uvodi u svijet Pythona i PyGamea!

Moderator: Danijel Korent

Post Reply
User avatar
Danijel Korent
Romulanski špijun na Zemlji
Posts: 1583
Joined: Fri Sep 05, 2008 12:35 pm
Smallest prime number bigger than 20: 23
Location: Njemacka
Contact:

[CLANAK 7.] - Python 4: Klase i instance 1

Post by Danijel Korent » Wed Dec 29, 2010 12:25 pm

7. PYTHON 4. - KLASE I INSTANCE 1

Kao i u prosloj lekciji, vise cu se baviti primjerima nego teorijom. Pa cu stoga krenuti s jednim primjerom, tocnije nastaviti s kodom iz zadnjeg primjera, brodom koji prati kursora. Pokusat cu dodati jos nekoliko brodova koji ce pratiti mis, prvo primjer sa znanjem iz dosadasnjim tutova, pa onda pomocu klasa. Cheers!


Znaci pocinjemo sa zadnjim kodom iz prosle lekcije, dakle ovaj:

Primjer_1
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *
from sys import exit
import os
import math

pygame.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'

glavni_buffer = pygame.display.set_mode((800, 600), DOUBLEBUF)

# varijable koje prate "stanje" broda
brod_PozicijaX = 400
brod_PozicijaY = 300
brod_KretanjeX = 0
brod_KretanjeY = 0
brod_Kut = 60
brod_Brzina = 2

brod_Slika = pygame.image.load('brod.png').convert()

glavna_petlja = True

tajmer = pygame.time.Clock()

#varijable koje prate poziciju misa
MisX = 0
MisY = 0
   


while glavna_petlja == True:

    for event in pygame.event.get():
		
        if event.type == QUIT:
            exit()

        #dobivanje koordinata misa i spremanje u varijable MisX i MisY
        if event.type == MOUSEMOTION:
            MisX = event.pos[0]
            MisY = event.pos[1]
 
    
    #dobivanje vektora izmedu broda i misa u odnosu na poziciju broda
    smjerX = MisX - brod_PozicijaX
    smjerY = MisY - brod_PozicijaY
    
    #racunanje kuta iz dobivenog vektora
    kut = math.atan2( -smjerY, smjerX)
    kut = math.degrees(kut)
    brod_Kut = kut
    

    # kretanje broda, odnosno racunanje nove pozicije na temelju vektora kretanja
    magnutuda_vektora_smjera = math.sqrt( smjerX**2 + smjerY**2 )
    smjerX = smjerX / magnutuda_vektora_smjera
    smjerY = smjerY / magnutuda_vektora_smjera
    
    brod_PozicijaX = brod_PozicijaX + smjerX * brod_Brzina
    brod_PozicijaY = brod_PozicijaY + smjerY * brod_Brzina
    
    
    
    #rotiranje osnovne slike broda (one koja gleda "prema" 0 stupnjeva)
    brod_zarotirani = pygame.transform.rotate(brod_Slika, brod_Kut)
    
    # crtanje pozadine i broda
    glavni_buffer.fill((18, 176, 227)) # pozadina je plava
    glavni_buffer.blit( brod_zarotirani, (brod_PozicijaX - brod_zarotirani.get_width() / 2, brod_PozicijaY - brod_zarotirani.get_height() / 2) )
    
    # update prozora nakon svih crtanja
    pygame.display.flip()  
    
    #ogranicavanje frameratea na 60fps-a
    tajmer.tick(60)
Pa recimo dodajmo jos dva broda. Kako? Naravno svaki pravi programer koji imalo drzi do sebe je lijena zivina i upotrijebit ce vrlo popularnu tehniku programiranja nazvanu "copy/paste", te onda grupno preimenovati varijable. Ovako:

Primjer_2
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *
from sys import exit
import os
import math

pygame.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'

glavni_buffer = pygame.display.set_mode((800, 600), DOUBLEBUF)


# varijable koje prate "stanje" brodova
brod1_PozicijaX = 10
brod1_PozicijaY = 10
brod1_KretanjeX = 0
brod1_KretanjeY = 0
brod1_Kut = 60
brod1_Brzina = 1
brod1_Slika = pygame.image.load('brod.png').convert()

brod2_PozicijaX = 580
brod2_PozicijaY = 10
brod2_KretanjeX = 0
brod2_KretanjeY = 0
brod2_Kut = 60
brod2_Brzina = 1.5
brod2_Slika = pygame.image.load('brod.png').convert()

brod3_PozicijaX = 400
brod3_PozicijaY = 550
brod3_KretanjeX = 0
brod3_KretanjeY = 0
brod3_Kut = 60
brod3_Brzina = 2
brod3_Slika = pygame.image.load('brod.png').convert()

glavna_petlja = True

tajmer = pygame.time.Clock()

#varijable koje prate poziciju misa
MisX = 0
MisY = 0
   


while glavna_petlja == True:


    # PROVJERA INPUTA    

    # provjeravama sto user radi, sa misom ovdjde konkretno
    for event in pygame.event.get():
		
        # ako je pritisnut X na prozoru
        if event.type == QUIT:
            exit()

        #dobivanje koordinata misa i spremanje u varijable MisX i MisY
        if event.type == MOUSEMOTION:
            MisX = event.pos[0]
            MisY = event.pos[1]
 

    # AZURIRANJE IGRE

    # PRVI BROD!!
    #dobivanje vektora izmedu broda i misa u odnosu na poziciju broda
    smjerX = MisX - brod1_PozicijaX
    smjerY = MisY - brod1_PozicijaY
    
    #racunanje kuta iz dobivenog vektora
    kut = math.atan2( -smjerY, smjerX)
    kut = math.degrees(kut)
    brod1_Kut = kut
    

    # kretanje broda, odnosno racunanje nove pozicije na temelju vektora kretanja
    magnutuda_vektora_smjera = math.sqrt( smjerX**2 + smjerY**2 )
    smjerX = smjerX / magnutuda_vektora_smjera
    smjerY = smjerY / magnutuda_vektora_smjera
    
    brod1_PozicijaX = brod1_PozicijaX + smjerX * brod1_Brzina
    brod1_PozicijaY = brod1_PozicijaY + smjerY * brod1_Brzina
    
    #rotiranje osnovne slike broda (one koja gleda "prema" 0 stupnjeva)
    brod1_zarotirani = pygame.transform.rotate(brod1_Slika, brod1_Kut)

 



    # DRUGI BROD!!
    #dobivanje vektora izmedu broda i misa u odnosu na poziciju broda
    smjerX = MisX - brod2_PozicijaX
    smjerY = MisY - brod2_PozicijaY
    
    #racunanje kuta iz dobivenog vektora
    kut = math.atan2( -smjerY, smjerX)
    kut = math.degrees(kut)
    brod2_Kut = kut
    

    # kretanje broda, odnosno racunanje nove pozicije na temelju vektora kretanja
    magnutuda_vektora_smjera = math.sqrt( smjerX**2 + smjerY**2 )
    smjerX = smjerX / magnutuda_vektora_smjera
    smjerY = smjerY / magnutuda_vektora_smjera
    
    brod2_PozicijaX = brod2_PozicijaX + smjerX * brod2_Brzina
    brod2_PozicijaY = brod2_PozicijaY + smjerY * brod2_Brzina
    
    #rotiranje osnovne slike broda (one koja gleda "prema" 0 stupnjeva)
    brod2_zarotirani = pygame.transform.rotate(brod2_Slika, brod2_Kut)

   



    #TRECI BROD!!!
    #dobivanje vektora izmedu broda i misa u odnosu na poziciju broda
    smjerX = MisX - brod3_PozicijaX
    smjerY = MisY - brod3_PozicijaY
    
    #racunanje kuta iz dobivenog vektora
    kut = math.atan2( -smjerY, smjerX)
    kut = math.degrees(kut)
    brod3_Kut = kut
    

    # kretanje broda, odnosno racunanje nove pozicije na temelju vektora kretanja
    magnutuda_vektora_smjera = math.sqrt( smjerX**2 + smjerY**2 )
    smjerX = smjerX / magnutuda_vektora_smjera
    smjerY = smjerY / magnutuda_vektora_smjera
    
    brod3_PozicijaX = brod3_PozicijaX + smjerX * brod3_Brzina
    brod3_PozicijaY = brod3_PozicijaY + smjerY * brod3_Brzina
    
    #rotiranje osnovne slike broda (one koja gleda "prema" 0 stupnjeva)
    brod3_zarotirani = pygame.transform.rotate(brod3_Slika, brod3_Kut)




    # CRTANJE IGRE

    # prije svega neka bude voda!
    glavni_buffer.fill((18, 176, 227)) # pozadina je plava

    #crtanje brodova
    glavni_buffer.blit( brod1_zarotirani, (brod1_PozicijaX - brod1_zarotirani.get_width() / 2, brod1_PozicijaY - brod1_zarotirani.get_height() / 2) )
    glavni_buffer.blit( brod2_zarotirani, (brod2_PozicijaX - brod2_zarotirani.get_width() / 2, brod2_PozicijaY - brod2_zarotirani.get_height() / 2) )
    glavni_buffer.blit( brod3_zarotirani, (brod3_PozicijaX - brod3_zarotirani.get_width() / 2, brod3_PozicijaY - brod3_zarotirani.get_height() / 2) )
    



    # update prozora nakon svih crtanja
    pygame.display.flip()  
    
    #ogranicavanje frameratea na 60fps-a
    tajmer.tick(60)
Super, brzo, efikasno i radi perfektno, bas sam ponosan na sebe! Zamislite sada da c/p-amo recimo 200 brodica. Zamislite sada sa smo odlucili promijeniti nacin ponasanja broda, te moramo promjeniti jednu liniju koda kod azuriranja pozicije broda. Da 200 linija koda za promjeniti! :). Buduci da je taj sav kod isti i radi sam istim varijablama samo s razlicitim vrijednostima, sljedeci logicni korak je da napravimo zajednicke funkcije koje ce obradivati te podatke:

Primjer_3
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *
from sys import exit
import os
import math

pygame.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'

glavni_buffer = pygame.display.set_mode((800, 600), DOUBLEBUF)


# varijable koje prate "stanje" brodova
brod1_PozicijaX = 10
brod1_PozicijaY = 10
brod1_KretanjeX = 0
brod1_KretanjeY = 0
brod1_Kut = 60
brod1_Brzina = 1
brod1_Slika = pygame.image.load('brod.png').convert()

brod2_PozicijaX = 580
brod2_PozicijaY = 10
brod2_KretanjeX = 0
brod2_KretanjeY = 0
brod2_Kut = 60
brod2_Brzina = 1.5
brod2_Slika = pygame.image.load('brod.png').convert()

brod3_PozicijaX = 400
brod3_PozicijaY = 550
brod3_KretanjeX = 0
brod3_KretanjeY = 0
brod3_Kut = 60
brod3_Brzina = 2
brod3_Slika = pygame.image.load('brod.png').convert()

glavna_petlja = True

tajmer = pygame.time.Clock()

#varijable koje prate poziciju misa
MisX = 0
MisY = 0
   

# azuriranje pozicije broda - okretanje prema misu i kretanje prema naprijed
def Azuriraj_poziciju(mis_x, mis_y, brod_PozicijaX, brod_PozicijaY, brod_Brzina):

    #dobivanje vektora izmedu broda i misa u odnosu na poziciju broda
    smjerX = MisX - brod_PozicijaX
    smjerY = MisY - brod_PozicijaY
    
    #racunanje kuta iz dobivenog vektora
    kut = math.atan2( -smjerY, smjerX)
    kut = math.degrees(kut)
    

    # kretanje broda, odnosno racunanje nove pozicije na temelju vektora kretanja
    magnutuda_vektora_smjera = math.sqrt( smjerX**2 + smjerY**2 )
    smjerX = smjerX / magnutuda_vektora_smjera
    smjerY = smjerY / magnutuda_vektora_smjera
    
    brod_PozicijaX = brod_PozicijaX + smjerX * brod_Brzina
    brod_PozicijaY = brod_PozicijaY + smjerY * brod_Brzina

    return brod_PozicijaX, brod_PozicijaY, kut



# rotiranje slike broda na kut za koji je okrenut i crtanje
def Nacrtaj_brod(brod_Slika,brod_PozicijaX, brod_PozicijaY, brod_Kut):
    brod_zarotirani = pygame.transform.rotate(brod_Slika, brod_Kut)
    glavni_buffer.blit( brod_zarotirani, (brod_PozicijaX - brod_zarotirani.get_width() / 2, brod_PozicijaY - brod_zarotirani.get_height() / 2) )
    pass


while glavna_petlja == True:


    # PROVJERA INPUTA    

    # provjeravama sto user radi, sa misom ovdjde konkretno
    for event in pygame.event.get():
		
        # ako je pritisnut X na prozoru
        if event.type == QUIT:
            exit()

        #dobivanje koordinata misa i spremanje u varijable MisX i MisY
        if event.type == MOUSEMOTION:
            MisX = event.pos[0]
            MisY = event.pos[1]
 

    # AZURIRANJE IGRE
    brod1_PozicijaX, brod1_PozicijaY, brod1_Kut  = Azuriraj_poziciju(MisX, MisY, brod1_PozicijaX, brod1_PozicijaY, brod1_Brzina)
    brod2_PozicijaX, brod2_PozicijaY, brod2_Kut  = Azuriraj_poziciju(MisX, MisY, brod2_PozicijaX, brod2_PozicijaY, brod2_Brzina)
    brod3_PozicijaX, brod3_PozicijaY, brod3_Kut  = Azuriraj_poziciju(MisX, MisY, brod3_PozicijaX, brod3_PozicijaY, brod3_Brzina)
    

    # CRTANJE IGRE
    # prije svega neka bude voda!
    glavni_buffer.fill((18, 176, 227)) # pozadina je plava
    Nacrtaj_brod(brod1_Slika, brod1_PozicijaX, brod1_PozicijaY, brod1_Kut )
    Nacrtaj_brod(brod2_Slika, brod2_PozicijaX, brod2_PozicijaY, brod2_Kut )
    Nacrtaj_brod(brod3_Slika, brod3_PozicijaX, brod3_PozicijaY, brod3_Kut )

    # update prozora nakon svih crtanja
    pygame.display.flip()  
    
    #ogranicavanje frameratea na 60fps-a
    tajmer.tick(60)
Evo, sada ovaj kod izgleda bas pregledno, logicno i definitivno se bezbolnije mijenja. No sigurno se moze i bolje, bilo bi bolje i preglednije da te sve varijable koje opisuju brod i njegovo trenutno stanje mozemo staviti(grupirati) pod neko zajednicko ime-referencu, sto na srecu u vecini jezika i mozemo. Mozda ne zvuci toliko vazno, no vidjet cemo na samom kodu sto sa time dobivamo.

Takvi oblik podataka se u racunalnom svijetu najcesce zove "record" ili "struct". A sad konkretno, u pythonu mozemo takav oblik podatka stvoriti koristeci keyword "class" i ja cu je ovjde zvati klasa iliti klase. Koristeci klase mozemo, laicki opisano, kreirati nove tipove kompleksnijih varijabli koje imaju podvarijable (te varijable onda zovemo objekti). Necu opisivat napamet nego cu bacit ovdje primjer:

Primjer_4
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-


# definiranje klase pod imenom "Osoba"
class Osoba:
    ime = 'prazno'
    prezime = 'prazno'
    godine = 0
    pass


# stvaranje(instanciranje) objekta tipa "Osoba"
Ivek = Osoba()
Osoba_2 = Osoba()


# citanje i pisanje "podvarijabala" iliti attributa
# one nakon stvaranja imaju vrijednosti koje smo im zadali (gore) kod definiranja
# primjetite da van se, ako pokusate ispisati samo objekt bez zadane podvarijable, ispise kakav objekt se nalazi u varijabli i na kojoj adresi, a ne njene vrijednosti kako bi mozda netko ocekivao
print "Pocetno stanje varijable Ivek:\n", Ivek, Ivek.ime, Ivek.prezime, Ivek.godine, "\n"
Ivek.ime = "Ivan"
Ivek.prezime = "Horvat"
Ivek.godine = 29
print "Stanje varijable Ivek nakon pisanja:\n", Ivek, Ivek.ime, Ivek.prezime, Ivek.godine, "\n"


Osoba_2.ime = "Imbra"
Osoba_2.prezime = "Grabaric"
Osoba_2.godine = 50
print "Stanje varijable Osoba_2:\n", Osoba_2, Osoba_2.ime, Osoba_2.prezime, Osoba_2.godine

# OPREZ - posebno pazite na to da dobro pisete imena podvarijabli(atributa) kod pridruzivanja vrijednosti, clanove mozete dodavati i nakon definiranja, pa ako slucajno napisete krivo ime python vam naravno nece javiti gresu da ta podvarijabla ne postoji nego ce ju stvoriti, sto nekad zna voditi do vrlo depresivnih trenutaka u vasoj friskoj programerskoj karijeri
Osoba_2.greska = 10
print "\ngreska:", Osoba_2.greska

Code: Select all

class Osoba:
    ime = 'prazno'
    prezime = 'prazno'
    godine = 0
"Osoba" je ime nase klase (da posebno napomenem, klasa je samo "sablona" za varijablu a ne sama varijabla), i kad se zeli stvoriti varijablu tog tipa (iliti instancirati objekt kako se to strucnije zove) koristimo to ime za stvaranje. Sve klase tipa "Osoba" ce sadrzavati podvarijable "ime", "prezime" i "godine".

Code: Select all

Ivek = Osoba()
Osoba_2 = Osoba()

Dakle te varijable(objekte) stvaramo na slican nacin kao i ostale standardne tipove poput strigova i brojeva, samo sto nakon znaka jednakosti umjesto stringa ili broja napisemo ime koje smo napisali kod definiranja klase, te nakon toga otvorenu i zatvorenu zagradu. (naknadno cete doznati zasto zagrade)

Code: Select all

Ivek.ime = "Ivan"
Ivek.prezime = "Horvat"
Ivek.godine = 29
Da bi pristupili i procitali ili mijenjali vrijednost onim definiranim "podvarijablama" (iliti attributia kako ih se strucnije zove) treba nakon imena objekta staviti tocku te napisati ime podvarijable, ostalo je sve isto kao i sa standardnim varijablama!

U pythonu koristenje ovog tipa podataka ima jos jednu dobru stranu. U samoj funkciji mozemo mijenjati ubaceni objekt, dok smo kod proslog primjera morali vracati vrijednosti iz funkcija. Evo jednostavan primjer:

Primjer_5
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-


# PRIMJER 1
prvi = 10
drugi = 50

def Pokus(a, b):
    b = a + 10
    print a, b


Pokus(prvi, drugi)
print prvi, drugi, "\n"



# PRIMJER 2
class Podatak:
    prvi = 10
    drugi = 20

def Pokus2(a):
    a.prvi = a.drugi + 10
    print a.prvi, a.drugi


var_1 = Podatak()

Pokus2(var_1)
print var_1.prvi, var_1.drugi
U prvom primjeru se vidi da "obicna" varijabla ubacena u funkciju ostaje ista nakon izvrsenja funkcije, to je zbog toga sto python u funkciji napravi kopije ubacenih varijabala te s njima radi unutar funkcije, stoga varijable koje su ubacene ostaju iste nakon izvrsenja. Za razliku od njih, kod objekata definiranih sa keywordom "class" funkcija ne radi kopije nego ih direktno koristi, pa se im stoga mogu mijenjati vrijednosti unutar funkcija, kao sto se i vidi u drugom primjeru.


A sada to primjenjeno kod onog primjera sa brodovima:

Primjer_6
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *
from sys import exit
import os
import math

pygame.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'

glavni_buffer = pygame.display.set_mode((800, 600), DOUBLEBUF)


# definiranje klase "Brod"
class Brod:
    PozicijaX = 0
    PozicijaY = 0
    KretanjeX = 0
    KretanjeY = 0
    Kut = 0
    Brzina = 1
    Slika = None
    zarotirani = None


# stvaranje tri objekta tipa "Brod"
brod1 = Brod()
brod2 = Brod()
brod3 = Brod()


# postavljanje vrijednosti objekta
brod1.PozicijaX = 10
brod1.PozicijaY = 10
brod1.KretanjeX = 0
brod1.KretanjeY = 0
brod1.Kut = 60
brod1.Brzina = 1
brod1.Slika = pygame.image.load('brod.png').convert()

brod2.PozicijaX = 580
brod2.PozicijaY = 10
brod2.KretanjeX = 0
brod2.KretanjeY = 0
brod2.Kut = 60
brod2.Brzina = 1.5
brod2.Slika = pygame.image.load('brod.png').convert()

brod3.PozicijaX = 400
brod3.PozicijaY = 550
brod3.KretanjeX = 0
brod3.KretanjeY = 0
brod3.Kut = 60
brod3.Brzina = 2
brod3.Slika = pygame.image.load('brod.png').convert()


glavna_petlja = True

tajmer = pygame.time.Clock()

MisX = 0
MisY = 0
   

# azuriranje pozicije broda - okretanje prema misu i kretanje prema naprijed
def Azuriraj_poziciju(mis_x, mis_y, brod):

    #dobivanje vektora izmedu broda i misa u odnosu na poziciju broda
    smjerX = MisX - brod.PozicijaX
    smjerY = MisY - brod.PozicijaY
    
    #racunanje kuta iz dobivenog vektora
    kut = math.atan2( -smjerY, smjerX)
    brod.Kut = math.degrees(kut)
    

    # kretanje broda, odnosno racunanje nove pozicije na temelju vektora kretanja
    magnutuda_vektora_smjera = math.sqrt( smjerX**2 + smjerY**2 )
    smjerX = smjerX / magnutuda_vektora_smjera
    smjerY = smjerY / magnutuda_vektora_smjera
    
    brod.PozicijaX = brod.PozicijaX + smjerX * brod.Brzina
    brod.PozicijaY = brod.PozicijaY + smjerY * brod.Brzina



# rotiranje slike broda na kut za koji je okrenut i crtanje
def Nacrtaj_brod(brod):
    brod.zarotirani = pygame.transform.rotate(brod.Slika, brod.Kut)
    glavni_buffer.blit( brod.zarotirani, (brod.PozicijaX - brod.zarotirani.get_width() / 2, brod.PozicijaY - brod.zarotirani.get_height() / 2) )
    pass


while glavna_petlja == True:


    # PROVJERA INPUTA    

    # provjeravama sto user radi, sa misom ovdjde konkretno
    for event in pygame.event.get():
		
        # ako je pritisnut X na prozoru
        if event.type == QUIT:
            exit()

        #dobivanje koordinata misa i spremanje u varijable MisX i MisY
        if event.type == MOUSEMOTION:
            MisX = event.pos[0]
            MisY = event.pos[1]
 

    # AZURIRANJE IGRE
    Azuriraj_poziciju(MisX, MisY, brod1)
    Azuriraj_poziciju(MisX, MisY, brod2)
    Azuriraj_poziciju(MisX, MisY, brod3)
    

    # CRTANJE IGRE
    # prije svega neka bude voda!
    glavni_buffer.fill((18, 176, 227)) # pozadina je plava
    Nacrtaj_brod( brod1 )
    Nacrtaj_brod( brod2 )
    Nacrtaj_brod( brod3 )

    # update prozora nakon svih crtanja
    pygame.display.flip()  
    
    #ogranicavanje frameratea na 60fps-a
    tajmer.tick(60)


Kao sto se i vidi ovako je primjetno urednije, te lakse za citati i razumjeti kod. No mozda bi moglo i bolje, onim dvjema funkcijama je sada primarna svrha, u biti jedina svrha, obradivati objete tipa "Brod", pa bi bilo logicno da se i te funkcije mogu "grupirati" zajedno sa onim podvarijablama(attributima). To je naravno nekome vec palo na pamet, pred mnogo godina, pa tako te gore spomenute varijable sa podvarijablama mogu za clanice imati i funkcije. Te funkcije-clanice (iliti metode kako se strucnije zove) dodajemo jednako kao i obicne samo sto su unutar indenta, odnosno unutar definicije klase. Pa da probamo:

Primjer_7
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-


class Osoba:
    ime = "prazno"
    godine = 0

    def Ispisi():
        print "Moje ime je", ime, "i imam", godine, "godina"


Ivek = Osoba()
Ivek.ime = "Ivek"
Ivek.godine = "27"

Ivek.Ispisi()


Ako ste probali pokrenuti ovaj program python vas je iznenadio sa ovom neobjasnjivom greskom:

Code: Select all

primjer_7.py", line 17, in <module>
    Ivek.Ispisi()
TypeError: Ispisi() takes no arguments (1 given)
Python tvrdi da smo poslali jedan argument(varijablu) u funkciju(metodu) "Ispisi" kad ocito nista nismo poslali, te javlja gresku jer kod definicije metode "Ispisi" nema nikakvih definiranih argumenata. Ovo cemo privremeno ignorirati i jednostavno dodati u definiciju jedan argument tek toliko da python ne davi za tu fantomsku varijablu. Taj argument cu nazvati recimo, argument_1. Eto pa probajmo sada:

Code: Select all

primjer_7.py", line 10, in Ispisi
    print "Moje ime je", ime, "i imam", godine, "godina"
NameError: global name 'ime' is not defined

Python vas je vjerojatno opet iznenadio. Kako to da kaze da varijabla "ime" ne postoji kad smo ju upravo gore definirali? Problem je u tome sto Python metode tretira kao najobicnije funkcije, koje vide samo ono sto im je poslano kao argument. A buduci da "ime" nije ni argument ni stvoreno nigdje u definiciji metode, Python logicno javlja gresku da "ime" ne postoji. Pa kako onda unutar metode nekog objekta pristupiti atributima tog istog objekta? Jednostavno, isto kao sto im pristupili i sa funkcijama van definicije klase, poslat cemo kao argument objekt cijim atributima zelima pristupiti, odnosno onutar metode nekog objekta cemo kao argument poslati taj isti objekt. Da malo cudno zvuci, ali evo primjer:

Primjer_8
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-


class Osoba:
    ime = "prazno"
    godine = 0

    def Ispisi(argument_1, objekt):
        print id(argument_1)
        print "Moje ime je", objekt.ime, "i imam", objekt.godine, "godina"



Ivek = Osoba()
Ivek.ime = "Ivek"
Ivek.godine = "27"

Ivek.Ispisi(Ivek)
print id(Ivek)


Ako ste pokrenuli mozete vidjeti da sve ok radi. A sad cu vam usput predstaviti jednu ugradenu funkciju pythona naziva "id". id prima jedan argument, i kao rezulatat vraca nazovimo to "identifikacijski" broj objekta koji se nalazi u varijabli poslanoj kao argument. Pa recimo ako u gornjem primjeru napisete "print id(Ivek)" on vam ispise "id" tog objekta. Napravite to, pa onda to napravite i za onaj "argument_1" u metodi "Ispisi" s kojim smo se rijesili one poslane fontomske varijable. Ako ste pokrenuli program vidjet cete da su brojevi isti. Da, da, kod svakog poziva bilo koje metode python sam posalje kao prvi argument objekt iz kojeg je pozvana ta metoda, te tako pomocu tog argumenta vi mozete pristupati atributima objekta kojem ta metoda pripada. Tako da se iz primjera_8 svim attributima (i metodama) moze pristupati i pomocu argument_1, te mi ne trebamo nista slati u metodu da bi pristupili atributima. Tom prvom objektu se najcesce daje ime "self", i to se preporucuje, pa cu tako i ja raditi u svim primjerima, i evo primjer opisanog:

Primjer_9
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-


class Osoba:
    ime = "prazno"
    godine = 0

    def Ispisi(self):
        print "Moje ime je", self.ime, "i imam", self.godine, "godina"
        print id(self)



Ivek = Osoba()
Ivek.ime = "Ivek"
Ivek.godine = "27"
print id(Ivek)

Ivek.Ispisi()

Bilo bi zgodno da napravimo funkciju za popunjavanje atributa, da ne moramo to diretno pristupati svakom atributu, no bilo bi jos zgodnije da to mozemo i kod samog instanciranja. I to naravno mozemo. Python svakoj klasi po defaultu dodaje neke metode ako ih samo ne definiramo, jedna od njih se zove __init__(). Posebnost "__init__" metode je da se prilikom svakog istanciranja ona automatski pokrene (sa argumnetima koje smo ubacili kod instanciranja). Dakle ako zelimo da se prilikom stvaranja objekta iz klase pokrene neki odredeni kod, recimo postave pocetnja stanja, pozove neka funkcija, to mozemo tu napraviti. Kako je koristiti? Jedostavno je dodajte u definiciju kao i svaku drugu metodu i python ce koristiti tu vasu definiciju umjesto defautne. Ako joj dodamo argumente mozemo odma kod instanciranja postaviti pocetna stanja za svaki objekt posebno. Evo to u nasem primjeru:

Primjer_10
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-


class Osoba:
    
    # metoda koja se automatski pokrece prilikom instanciranja ove klase
    def __init__(self, ime, godine):
		self.ime = ime
		self.godine = godine
		

    def Ispisi(self):
        print "Moje ime je", self.ime, "i imam", self.godine, "godina"



Ivek = Osoba("Ivek", 27)
Ivek.Ispisi()


Dudek = Osoba("Dras Katalenic", 47)
Dudek.Ispisi()


primjetite da su sada ona definiranja atributa ime i godine van metoda izbacena, vise nisu potrebna jer ih sada definiramo unutar __init__() metode. I tako i trebate definirati sve atribute unutar klase, jer ako se definiraju van metode ona postanu i "staticki clanovi klase" sto vam u vecini slucajeva nije potrebno, i moze dovesti do "slucajnih" bugova u kodu.


I sada da se sve to primjeni na primjeru s brodicima:

Primjer_11
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-

import pygame
from pygame.locals import *
from sys import exit
import os
import math


# definiranje klase "Brod"
class Brod:
	
	def __init__(self, pozX, pozY, brzina):
		self.PozicijaX = pozX
		self.PozicijaY = pozY
		self.KretanjeX = 0
		self.KretanjeY = 0
		self.Kut = 0
		self.Brzina = brzina
		self.Slika = Slika = pygame.image.load('brod.png').convert()
		self.zarotirani = None

	# azuriranje pozicije broda - okretanje prema misu i kretanje prema naprijed
	def Azuriraj_poziciju(self, mis_x, mis_y):

		#dobivanje vektora izmedu broda i misa u odnosu na poziciju broda
		smjerX = mis_x - self.PozicijaX
		smjerY = mis_y - self.PozicijaY
		
		#racunanje kuta iz dobivenog vektora
		kut = math.atan2( -smjerY, smjerX)
		self.Kut = math.degrees(kut)
		

		# kretanje broda, odnosno racunanje nove pozicije na temelju vektora kretanja
		magnutuda_vektora_smjera = math.sqrt( smjerX**2 + smjerY**2 )
		smjerX = smjerX / magnutuda_vektora_smjera
		smjerY = smjerY / magnutuda_vektora_smjera
		
		self.PozicijaX = self.PozicijaX + smjerX * self.Brzina
		self.PozicijaY = self.PozicijaY + smjerY * self.Brzina
		
		
	# rotiranje slike broda na kut za koji je okrenut i crtanje
	def Nacrtaj_brod(self):
		self.zarotirani = pygame.transform.rotate(self.Slika, self.Kut)
		glavni_buffer.blit( self.zarotirani, (self.PozicijaX - self.zarotirani.get_width() / 2, self.PozicijaY - self.zarotirani.get_height() / 2) )
		pass
		


pygame.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'

glavni_buffer = pygame.display.set_mode((800, 600), DOUBLEBUF)

# stvaranje tri objekta tipa "Brod"
brod1 = Brod(10, 10, 1)
brod2 = Brod(580, 10, 1.5)
brod3 = Brod(400, 550, 2)


glavna_petlja = True

tajmer = pygame.time.Clock()

MisX = 0
MisY = 0
   

while glavna_petlja == True:


    # PROVJERA INPUTA    

    # provjeravama sto user radi, sa misom ovdjde konkretno
    for event in pygame.event.get():
		
        # ako je pritisnut X na prozoru
        if event.type == QUIT:
            exit()

        #dobivanje koordinata misa i spremanje u varijable MisX i MisY
        if event.type == MOUSEMOTION:
            MisX = event.pos[0]
            MisY = event.pos[1]
 

    # AZURIRANJE IGRE
    brod1.Azuriraj_poziciju(MisX, MisY)
    brod2.Azuriraj_poziciju(MisX, MisY)
    brod3.Azuriraj_poziciju(MisX, MisY)
    

    # CRTANJE IGRE
    # prije svega neka bude voda!
    glavni_buffer.fill((18, 176, 227)) # pozadina je plava
    brod1.Nacrtaj_brod()
    brod2.Nacrtaj_brod()
    brod3.Nacrtaj_brod()

    # update prozora nakon svih crtanja
    pygame.display.flip()  
    
    #ogranicavanje frameratea na 60fps-a
    tajmer.tick(60)

Da jos dodatno pojasnim neke pojmove i korelacije jer sam primjetio da to mnoge buni. Klasa nije varijabla koja "fizicki" postoji, objekt je taj koji fizicki postoji, a klasa je samo "sablona" iliti opis koje i kakve sve clanove taj objekt treba imati. Dakle kad si zazelimo neku varijablu sa nekim odredenim podvarijablama, prvo napravimo sablonu iliti klasu, da racunalo moze znati kakav objekt zelimo, a onda po toj sabloni stvorimo varijablu/objekt s kojim konkretno mozemo raditi*, te svaki objekt sadrzi svoj vlastiti memorijski prostor i vlastite vrijednosti varijabala:

objekt = klasa()
objekt.neka_varijabla = 10

*(mada ako se kod definiranja klase neki atribut definira van neke metode te klase, moguce je napraviti ovo: "print klasa.atribut" ili "klasa.atribut = 10", no to necu ovdje objasnjavati, to se ukratko zove staticki atribut klase)

i sto se tice imena, neka varijabla koja je clanica neke klase onda zovemo ATRIBUT, a funkciju koja je clanica neke klase zovemo METODA



Mogli bi usput iz ovoga napraviti i neku malu igricu po KISS principu, npr. nesto slicno sa onom zabom sto prelazi preko ceste (kako li se samo zove ta igra? hmm ). Stavit cu da po duzini kanala prelaze brodovi gore/dolje, a vi (kapetan naravno :D ) morate konvoj brodova prevesti preko kanala bez da se zaletite neki od tih brodova. Prvo cu si napraviti malu listu sto sve trebam dodati/modificirati:

1. suziti povrsinu da podsjeca na kanal (samo cu prozor suziti)
2. staviti da brodovi jedan drugog prate u "lanac"
3. ograniciti udaljenost na koju brod koji prati moze doci (da se ne zaletavaju jedan u drugog, a i primjetili ste da ako brod dode do koordinata koje prati da postane malo neodlucan u koji smjer bi gledao :D )
4. dodati novu klasu brodova koji koji se krecu kao "po traci", idu i neki smjer, i kad dodu do kraja prozora krenu ponovo sa suprotne strane prozora
5. nova klasa mora provjeravati dal je bilo sudara sa "nasim" brodovima
6. dodati uvjete kod pobjede i poraza (i slike koje prikaze) - poraz naravno kad dotakne drugi brod - pobjeda kad dode do kraja mape (do odredene vrijednosti po x-osi prvi ili zadnji brod, jos cemo vidjeti)

To je to, nadam se da sam se svega sjetio, idem sada korak po korak:

1. nadam se da svi imaju rezoluciju od barem 1024px po x-osi, pa cu prvo staviti toliko, a y-os na pola, znaci:
glavni_buffer = pygame.display.set_mode((1024, 512), DOUBLEBUF)

2. ovo je jednostavno, prvi brod prati koordinate kursora misa, drugi brod koordinate prvog broda, a treci koord drugog broda:

Code: Select all

    brod1.Azuriraj_poziciju(MisX, MisY)
    brod2.Azuriraj_poziciju(brod1.PozicijaX, brod1.PozicijaY)
    brod3.Azuriraj_poziciju(brod2.PozicijaX, brod2.PozicijaY)
i ujedno malo srediti pocetne pozicije brodova, stavit cu da se pojave na desnoj strani kanala, i jedan od drugo udaljeni za pola svoje duzine:

Code: Select all

brod1 = Brod(800, 250, 1)
brod2 = Brod(875, 250, 1)
brod3 = Brod(950, 250, 1)

3. ovo cemo vrlo lako napraviti, buduci da udaljenost vec i tako racunamo svaki turn, i spremamo u varijablu "magnutuda_vektora_smjera" (koja ocito ima tipfeler O.o), jednostavno cemo dodati uvjet da se kretanje broda odradi samo ako je ta varijabla (a to znaci i udaljenost) veca od neke vrijednosti, recimo od 60:

Code: Select all

if magnutuda_vektora_smjera > 60:
    
    smjerX = smjerX / magnutuda_vektora_smjera
    smjerY = smjerY / magnutuda_vektora_smjera
        
    self.PozicijaX = self.PozicijaX + smjerX * self.Brzina
    self.PozicijaY = self.PozicijaY + smjerY * self.Brzina

.. radi super, samo malo bode za oci sto brodovi stanu neprirodno brzo, instantno. Da se to rijesiti inercijom, al ja cu rade na jednostavniji nacin, stavit cu da imaju razlicite brzine (sto malo da i na tezini), pa nece odma sva tri stati nego ce na kratko dostizati jedan drugoga.

4. Klasa je mastovito nazvana "Neprijatelj", prvo sam htio napraviti copy/paste klase "Brod" i malo je modificirati, al sam svatio da je puno bolje da je drugiciom logikom napisem jer je jednostavnija:

Code: Select all

class Neprijatelj:
    
    def __init__(self, pozX, pozY, smjerY):
        self.PozicijaX = pozX
        self.PozicijaY = pozY
        self.SmjerY = smjerY
        
        slika = Slika = pygame.image.load('brod.png').convert()
        
        kut = 0
        if smjerY < 0: kut = 90
        else: kut = 270
        
        self.zarotirani = pygame.transform.rotate(slika, kut)
        
	# azuriranje pozicije broda - okretanje prema misu i kretanje prema naprijed
    def Azuriraj_poziciju(self):
     
        self.PozicijaY = self.PozicijaY + self.SmjerY
        
        if self.PozicijaY < 0:
            self.PozicijaY = Prozor_Y 
           
        if self.PozicijaY > Prozor_Y:
            self.PozicijaY = 0
        
		
    # rotiranje slike broda na kut za koji je okrenut i crtanje
    def Nacrtaj_brod(self):
        glavni_buffer.blit( self.zarotirani, (self.PozicijaX - self.zarotirani.get_width() / 2, self.PozicijaY - self.zarotirani.get_height() / 2) )
        pass
5. dodat cu klasi "Neprijatelj" metodu koja ce primati 3 objekta klase brod i provjeravati da li je koji sudareni, ako dode do sudara metoda vraca "True":

Code: Select all

    def Provjeri_sudar(self, brod1, brod2, brod3):
        neprijatelj_rect = self.zarotirani.get_rect()
        neprijatelj_rect.center = self.PozicijaX, self.PozicijaY
        
        rect_brod1 = brod1.zarotirani.get_rect()
        rect_brod1.center = brod1.PozicijaX, brod1.PozicijaY
        if neprijatelj_rect.colliderect(rect_brod1): return True
        
        rect_brod2 = brod2.zarotirani.get_rect()
        rect_brod2.center = brod2.PozicijaX, brod2.PozicijaY
        if neprijatelj_rect.colliderect(rect_brod2): return True
        
        rect_brod3 = brod3.zarotirani.get_rect()
        rect_brod3.center = brod3.PozicijaX, brod3.PozicijaY
        if neprijatelj_rect.colliderect(rect_brod3): return True
6. dodat cu jednu varijablu koja prati dal je igra zavrsena ili ne, te ce s obzirom na stanje ili azurirati objekte u igri ili prikazivati poruku pobjeda/poraz. Varijabla ce se mastovito zvati "igra_zavrsena":

Code: Select all

igra_zavrsena = 0

slika_pobjeda = pygame.image.load('pobjeda.png').convert()
slika_poraz = pygame.image.load('poraz.png').convert()
kad se igra zavrsi, odnosno kad nas brod takne neki drugi brod stavit cu da varijabla "igra_zavrsena" bude 1, a kad igrac pobjedi bude 2.

Code: Select all

if Neprijatelj1.Provjeri_sudar(brod1, brod2, brod3): igra_zavrsena = 1
i za pobjedu: (privremena vrijednost 300, i tako ce se mijenjati kod balansiranja)

Code: Select all

    cilj_Xos = 300
    if brod1.PozicijaX < cilj_Xos:
        igra_zavrsena = 2

I naravno crtanje poruke ako je igra zavrsena:

Code: Select all

    if igra_zavrsena == 1:
        glavni_buffer.blit( slika_poraz, (Prozor_X / 2 - 100, Prozor_Y / 2 - 50) )
    elif igra_zavrsena == 2:
        glavni_buffer.blit( slika_pobjeda, (Prozor_X / 2 - 100, Prozor_Y / 2 - 50) )
Ostavio sam da se protivnici krecu i nakon zavrsetka igre, nekako je ljepse ;)

Nebi bilo lose da se prije nego pocne igra mora kliknuti misem, tako da se igrac ima vremena pripraviti. Stoga ce igra poceti pauzirana, tj. stavit cemo varijablu "igra_zavrsena" na neku pocetnu vrijednost tako da igra pocne pauzirana, recimo broj 3 (jer se 1 i 2 vec koriste), te kad je broj tri da se ispusje poruku "Klikni misem za pocetak igre", te fa taj klik varijablu "igra_zavrsena" stavlja na 0.

loadiranje fonta i stvaranje "slike" (surface) text-a

Code: Select all

font = pygame.font.SysFont('Arial', 32, False)
text_klik_misem = font.render("Klikni misem za pocetak igre", True, (255,255,0))
ako je igra_zavrsena == 3 crta text na ekran

Code: Select all

    elif igra_zavrsena == 3:
        glavni_buffer.blit( text_klik_misem, (Prozor_X / 2 - 200, Prozor_Y / 2 - 50) )
te jos da klik misa pokrene igru:

Code: Select all

       if event.type == MOUSEBUTTONDOWN:
            igra_zavrsena = 0
primjetiti da prije pocetka igre svi su brodu okrenuti prema desno umjesto lijevo, to cemo srediti tako sto cemo u klasi za pocetni kut staviti 180 umjesto 0: "self.Kut = 180"

Evo vec lici na nesto, ali da dignemo malo napetost u igri, dodat cemo i jedan tajmer koji ce odbrojavati sekunde od pocetka igre i zaustaviti se na kraju igre. Za to cemo koristiti pygame funkciju "pygame.time.get_ticks" koja vraca predene milisekunde od pokretanja aplikacije, kod pocetka igre cemo zapamtiti pocetno vrijeme, tj. vrijeme kada je klinutno na mis, te onda to prodeno vrijeme umanjivati za zapamceno vrijeme da bi dobili prodeno vrijeme od pocetka igre. Prodeno vrijeme ce se racunati samo kad je igra aktivna, kad zavrsi ce stati na vremenu u tom trenutku:

Prvo dodajemo varijable za pracenje:

Code: Select all

pocetno_vrijeme_igre = 0
prodeno_vrijeme_igre = 0

kod azuriranja da racuna prodeno vrijeme:

Code: Select all

    if not igra_zavrsena:
        
        prodeno_vrijeme_igre = pygame.time.get_ticks() - pocetno_vrijeme_igre
i da se crta to vrijeme:

Code: Select all

    text_vrijeme = font.render( str(prodeno_vrijeme_igre/1000.0) , True, (255,0,0))
    glavni_buffer.blit(text_vrijeme, (900, 10))
Eto i to je to, sad slijedi mukotrpno balansiranje s cime se necu previse zamarati, max 15min pa kako bude bude. Eventualno jos dodam jednu liniju da se jasnije vidi di je cilj:

pygame.draw.line(glavni_buffer, (0,255,0), (cilj_Xos, 0), (cilj_Xos, Prozor_Y), 2)

I jos cu samo kod crtanja brodova dodati da se vidiju "rectovi"-pravokutnici pomocu kojih vrsimo detekciju sudara, pa da vidite zasto je detekcija nekad "cudljiva":

pygame.draw.rect(glavni_buffer, (255,255,255), self.zarotirani.get_rect(center = (self.PozicijaX, self.PozicijaY)), 1)

Evo kod za primjer 12:
Spoiler! :

Code: Select all

#! /usr/bin/env python
# -*- coding: utf-8 -*-


import pygame
from pygame.locals import *
from sys import exit
import os
import math


# definiranje klase "Brod"
class Brod:
    
    def __init__(self, pozX, pozY, brzina):
        self.PozicijaX = pozX
        self.PozicijaY = pozY
        self.KretanjeX = 0
        self.KretanjeY = 0
        self.Kut = 180
        self.Brzina = brzina
        self.Slika = Slika = pygame.image.load('brod.png').convert()
        self.zarotirani = pygame.transform.rotate(self.Slika, self.Kut)

	# azuriranje pozicije broda - okretanje prema misu i kretanje prema naprijed
    def Azuriraj_poziciju(self, mis_x, mis_y):

        #dobivanje vektora izmedu broda i misa u odnosu na poziciju broda
        smjerX = mis_x - self.PozicijaX
        smjerY = mis_y - self.PozicijaY
        
        #racunanje kuta iz dobivenog vektora
        kut = math.atan2( -smjerY, smjerX)
        self.Kut = math.degrees(kut)
        

        # kretanje broda, odnosno racunanje nove pozicije na temelju vektora kretanja
        magnutuda_vektora_smjera = math.sqrt( smjerX**2 + smjerY**2 )
        if magnutuda_vektora_smjera > 60:
            
            smjerX = smjerX / magnutuda_vektora_smjera
            smjerY = smjerY / magnutuda_vektora_smjera
                
            self.PozicijaX = self.PozicijaX + smjerX * self.Brzina
            self.PozicijaY = self.PozicijaY + smjerY * self.Brzina
        
		
    # rotiranje slike broda na kut za koji je okrenut i crtanje
    def Nacrtaj_brod(self):
        self.zarotirani = pygame.transform.rotate(self.Slika, self.Kut)
        glavni_buffer.blit( self.zarotirani, (self.PozicijaX - self.zarotirani.get_width() / 2, self.PozicijaY - self.zarotirani.get_height() / 2) )
        pygame.draw.rect(glavni_buffer, (255,255,255), self.zarotirani.get_rect(center = (self.PozicijaX, self.PozicijaY)), 1)
        pass
		


class Neprijatelj:
    
    def __init__(self, pozX, pozY, smjerY):
        self.PozicijaX = pozX
        self.PozicijaY = pozY
        self.SmjerY = smjerY
        
        slika = Slika = pygame.image.load('brod.png').convert()
        
        kut = 0
        if smjerY < 0: kut = 90
        else: kut = 270
        
        self.zarotirani = pygame.transform.rotate(slika, kut)
        
	# azuriranje pozicije broda - okretanje prema misu i kretanje prema naprijed
    def Azuriraj_poziciju(self):
     
        self.PozicijaY = self.PozicijaY + self.SmjerY
        
        if self.PozicijaY < 0:
            self.PozicijaY = Prozor_Y 
           
        if self.PozicijaY > Prozor_Y:
            self.PozicijaY = 0
        
		
    # rotiranje slike broda na kut za koji je okrenut i crtanje
    def Nacrtaj_brod(self):
        glavni_buffer.blit( self.zarotirani, (self.PozicijaX - self.zarotirani.get_width() / 2, self.PozicijaY - self.zarotirani.get_height() / 2) )
        pygame.draw.rect(glavni_buffer, (255,255,255), self.zarotirani.get_rect(center = (self.PozicijaX, self.PozicijaY)), 1)
        pass
        
        
    def Provjeri_sudar(self, brod1, brod2, brod3):
        neprijatelj_rect = self.zarotirani.get_rect()
        neprijatelj_rect.center = self.PozicijaX, self.PozicijaY
        
        rect_brod1 = brod1.zarotirani.get_rect()
        rect_brod1.center = brod1.PozicijaX, brod1.PozicijaY
        if neprijatelj_rect.colliderect(rect_brod1): return True
        
        rect_brod2 = brod2.zarotirani.get_rect()
        rect_brod2.center = brod2.PozicijaX, brod2.PozicijaY
        if neprijatelj_rect.colliderect(rect_brod2): return True
        
        rect_brod3 = brod3.zarotirani.get_rect()
        rect_brod3.center = brod3.PozicijaX, brod3.PozicijaY
        if neprijatelj_rect.colliderect(rect_brod3): return True




pygame.init()
os.environ['SDL_VIDEO_CENTERED'] = '1'

Prozor_X = 1024
Prozor_Y = 512

glavni_buffer = pygame.display.set_mode((Prozor_X, Prozor_Y), DOUBLEBUF)
        
        
# stvaranje tri objekta tipa "Brod"
brod1 = Brod(950, 250, 1.5)
brod2 = Brod(1025, 250, 1.4)
brod3 = Brod(1100, 250, 1.3)


Neprijatelj1 = Neprijatelj(200, 10, -1.2)
Neprijatelj2 = Neprijatelj(200, 250, -1.2)
Neprijatelj3 = Neprijatelj(400, 10, 1.5)
Neprijatelj4 = Neprijatelj(600, 10, -1)
Neprijatelj5 = Neprijatelj(600, 250, -1)
Neprijatelj6 = Neprijatelj(450, 200, -1.5)

glavna_petlja = True

tajmer = pygame.time.Clock()

MisX = 0
MisY = 0


igra_zavrsena = 3

slika_pobjeda = pygame.image.load('pobjeda.png').convert()
slika_poraz = pygame.image.load('poraz.png').convert()


font = pygame.font.SysFont('Arial', 32, False)
text_klik_misem = font.render("Klikni misem za pocetak igre", True, (255,255,0))


pocetno_vrijeme_igre = 0 #pygame.time.get_ticks() # dodajemo 
prodeno_vrijeme_igre = 0

while glavna_petlja == True:


    # PROVJERA INPUTA    

    # provjeravama sto user radi, sa misom ovdjde konkretno
    for event in pygame.event.get():
		
        # ako je pritisnut X na prozoru
        if event.type == QUIT:
            exit()

        #dobivanje koordinata misa i spremanje u varijable MisX i MisY
        if event.type == MOUSEMOTION:
            MisX = event.pos[0]
            MisY = event.pos[1]
 
        if event.type == MOUSEBUTTONDOWN:
            igra_zavrsena = 0

    
    Neprijatelj1.Azuriraj_poziciju()
    Neprijatelj2.Azuriraj_poziciju()
    Neprijatelj3.Azuriraj_poziciju()
    Neprijatelj4.Azuriraj_poziciju()
    Neprijatelj5.Azuriraj_poziciju()
    Neprijatelj6.Azuriraj_poziciju()
    
    if not igra_zavrsena:
        
        prodeno_vrijeme_igre = pygame.time.get_ticks() - pocetno_vrijeme_igre
        
        # AZURIRANJE IGRE 
        brod1.Azuriraj_poziciju(MisX, MisY)
        brod2.Azuriraj_poziciju(brod1.PozicijaX, brod1.PozicijaY)
        brod3.Azuriraj_poziciju(brod2.PozicijaX, brod2.PozicijaY)

        if Neprijatelj1.Provjeri_sudar(brod1, brod2, brod3): igra_zavrsena = 1
        elif Neprijatelj2.Provjeri_sudar(brod1, brod2, brod3): igra_zavrsena = 1
        elif Neprijatelj3.Provjeri_sudar(brod1, brod2, brod3): igra_zavrsena = 1
        elif Neprijatelj4.Provjeri_sudar(brod1, brod2, brod3): igra_zavrsena = 1
        elif Neprijatelj5.Provjeri_sudar(brod1, brod2, brod3): igra_zavrsena = 1
        elif Neprijatelj6.Provjeri_sudar(brod1, brod2, brod3): igra_zavrsena = 1

    cilj_Xos = 50
    if brod1.PozicijaX < cilj_Xos:
        igra_zavrsena = 2

    # CRTANJE IGRE
    # prije svega neka bude voda!
    glavni_buffer.fill((18, 176, 227)) # pozadina je plava
    
    pygame.draw.line(glavni_buffer, (0,255,0), (cilj_Xos, 0), (cilj_Xos, Prozor_Y), 2)
    
    brod1.Nacrtaj_brod()
    brod2.Nacrtaj_brod()
    brod3.Nacrtaj_brod()
    
    Neprijatelj1.Nacrtaj_brod()
    Neprijatelj2.Nacrtaj_brod()
    Neprijatelj3.Nacrtaj_brod()
    Neprijatelj4.Nacrtaj_brod()
    Neprijatelj5.Nacrtaj_brod()
    Neprijatelj6.Nacrtaj_brod()
    
    if igra_zavrsena == 1:
        glavni_buffer.blit( slika_poraz, (Prozor_X / 2 - 100, Prozor_Y / 2 - 50) )
    elif igra_zavrsena == 2:
        glavni_buffer.blit( slika_pobjeda, (Prozor_X / 2 - 100, Prozor_Y / 2 - 50) )
    elif igra_zavrsena == 3:
        glavni_buffer.blit( text_klik_misem, (Prozor_X / 2 - 200, Prozor_Y / 2 - 50) )
        
    text_vrijeme = font.render( str(prodeno_vrijeme_igre/1000.0) , True, (255,0,0))
    glavni_buffer.blit(text_vrijeme, (900, 10))

    # update prozora nakon svih crtanja
    pygame.display.flip()  
    
    #ogranicavanje frameratea na 60fps-a
    tajmer.tick(60)
To je sve za danas, see ya!
You do not have the required permissions to view the files attached to this post.

User avatar
Danijel Korent
Romulanski špijun na Zemlji
Posts: 1583
Joined: Fri Sep 05, 2008 12:35 pm
Smallest prime number bigger than 20: 23
Location: Njemacka
Contact:

Re: [CLANAK 7.] - Python 4: Klase i instance 1

Post by Danijel Korent » Wed Dec 29, 2010 12:26 pm

Nemam bas vremena za provjeravati tipfelere i sl. greske pa mi javite ako naidete na koju!
a.k.a. Koki

Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest