Processing math: 100%

Prijavi problem


Obeleži sve kategorije koje odgovaraju problemu

Još detalja - opišite nam problem


Uspešno ste prijavili problem!
Status problema i sve dodatne informacije možete pratiti klikom na link.
Nažalost nismo trenutno u mogućnosti da obradimo vaš zahtev.
Molimo vas da pokušate kasnije.

Час 13 - Анимације више објеката, oчитавање миша и тастатуре

Анимације више објеката

Аутомобил и авион

Напиши програм који приказује анимацију авиона који се креће по небу и аутомобила који се креће по земљи, при чему је брзина авиона два пута већа него аутомобила. Када неко возило изађе на десном крају екрана, појављује се поново на левом. Поново можеш употребити слике auto.png и avion.png.

../_images/auto.png ../_images/avion.png

Задатак веома једноставно можемо решити тако што практично два пута поновимо кôд који смо написали у програму у ком смо вршили симулацију аутомобила. Понављање истог или сличног кода више пута је иначе веома лоша пракса и касније ћемо видети начине да се то избегне када се ради са више објеката, али с обзиром на то да се овде кôд понавља само једном, то можемо толерисати.

 
1
import math
2
import pygame as pg
3
import pygamebg
4
5
(sirina, visina) = (500, 300)  # otvaramo prozor
6
prozor = pygamebg.open_window(sirina, visina, "Ауто и авион")
7
8
avion_slika = pg.image.load("avion.png")
9
(avion_x, avion_y) = (0, ???)
10
auto_slika = pg.image.load("auto.png")
11
(auto_x, auto_y) = (0, ???)
12
13
def crtaj():
14
    prozor.fill(pg.Color("white"))
15
    prozor.blit(avion_slika, (avion_x, avion_y)) # crtamo avion
16
    ???                                          # crtamo auto
17
18
def novi_frejm():
19
    global avion_x, avion_y, auto_x, auto_y
20
21
    # pomeramo avion
22
    avion_x += 2
23
    if avion_x > sirina:
24
        avion_x = - avion_slika.get_width()
25
26
    # pomeramo auto
27
    ???
28
29
    crtaj()
30
31
pygamebg.frame_loop(100, novi_frejm)
32

(auto_avion)

Две лоптице

Напиши програм који приказује црвену и плаву лоптицу које се крећу по екрану, одбијају од ивица и одбијају међусобно (једноставности ради претпостави да приликом сударе две лоптице једноставно размене векторе кретања).

Поново независно вршимо анимацију два различита објекта. Кључна новина је то што се објекти могу међусобно сударати. Два круга се сударају (пресецају) ако и само ако је растојање њихових центара веће од збира њихових полупречника. Растојање рачунамо на уобичајени начин, Питагорином теоремом. Ако се лоптице сударају, размењујемо им помераје по x и помераје по y оси (векторе брзине).

48
 
1
import math
2
import pygame as pg
3
import pygamebg
4
5
(sirina, visina) = (300, 200)  # otvaramo prozor
6
prozor = pygamebg.open_window(sirina, visina, "Две лоптице")
7
8
r = 20
9
(x1, y1) = (r, r)
10
(dx1, dy1) = (1, 1)
11
(x2, y2) = (sirina - r, visina - r)
12
(dx2, dy2) = (-1, -1)
13
14
def crtaj():
15
    prozor.fill(pg.Color("white"))
16
    pg.draw.circle(prozor, pg.Color("red"), (x1, y1), r)
17
    pg.draw.circle(prozor, pg.Color("blue"), (x2, y2), r)
18
19
# rastojanje između centara loptica
20
def rastojanje():
21
    return math.sqrt((x1-x2)**2 + (y1-y2)**2)
22
23
# provera da li se dve loptice sudaraju
24
def sudar():
25
    return rastojanje() <= 2*r
26
27
def novi_frejm():
28
    global x1, y1, x2, y2, dx1, dy1, dx2, dy2
29
30
    # pomeramo prvu lopticu i proveravamo sudar sa ivicama prozora
31
    x1 += dx1
32
    y1 += dy1
33
    if x1 - r < 0 or x1 + r > sirina:
34
        dx1 = -dx1
35
    if y1 - r < 0 or y1 + r > visina:
36
        dy1 = -dy1
37
38
    # pomeramo drugu lopticu i proveravamo sudar sa ivicama prozora
39
    ???
40
41
    # ispitujemo sudar dve loptice
42
    if sudar():
43
        (dx1, dy1, dx2, dy2) = (dx2, dy2, dx1, dy1)
44
45
    crtaj()
46
47
pygamebg.frame_loop(100, novi_frejm)
48

(dve_loptice)

Пахуљице

Напиши програм који приказује анимацију пахуља које падају са врха на дно екрана. Можеш употребити слику pahulja.png. Када пахуље падну на дно екрана, нове крећу да падају са врха.

../_images/pahulja.png

Центре пахуљица можемо памтити у листи парова. Један начин да реализујемо померање пахуљица је тај да од текуће листе направимо нову у којој ће x координате свих елемената бити неизмењене, а у којој ће y координате бити увећане за 1. При том, из листе можемо избацити пахуље које су пале испод дна екрана (којима је y координата врха већа од висине прозора) и за сваку пахуљу која испадне у листу додамо нову пахуљу (њој координате одређујемо насумично, тако да се по ширини налази унутар прозора, а да по висини креће да пада из појаса изнад екрана који је широк једну петину екрана).

32
 
1
import random
2
import pygame as pg
3
import pygamebg
4
5
(sirina, visina) = (800, 400)  # otvaramo prozor
6
prozor = pygamebg.open_window(sirina, visina, "Пахуљице")
7
8
pahulja_slika = pg.image.load("pahulja.png")  # slika pahuljice
9
broj_pahulja = 10                             # ukupan broj pahuljica
10
# nasumično generišemo centre pahuljica
11
centri_pahulja = [(???, ???)
12
                  for i in range(???)]
13
14
def crtaj():
15
    prozor.fill(pg.Color("white"))    # bojimo pozadinu u belo
16
    dim = pahulja_slika.get_width()   # dimenzije slike pahulje
17
    for (x, y) in ???:                # crtamo sve pahulje
18
        prozor.blit(pahulja_slika, (???, ???))
19
20
def novi_frejm():
21
    global centri_pahulja
22
23
    # pomeramo pahulje i u listi ostavljamo samo one koje još nisu ispale
24
    centri_pahulja = [(x, y+1) for (x, y) in centri_pahulja if ???]
25
    # popunjavamo prazna mesta novih pahuljama koje kreću da padaju iznad vrha ekrana
26
    while len(centri_pahulja) < ???:
27
        centri_pahulja.append((random.randint(0, sirina),
28
                               random.randint(-visina // 5, 0)))
29
    crtaj()
30
31
pygamebg.frame_loop(50, novi_frejm)
32

(pahuljice)

Очитавање миша и тастатуре

Корисник интеракцију са програмом обично врши мишем или тастатуром. Напреднији облици интеракције подразумевају реаговање на догађаје и њих ћемо описати у наредном поглављу посвећеном догађајима. Ипак наше анимације можемо веома једноставно учинити интересантнијим помоћу веома једноставне функционалности очитавања стања миша и тастатуре (за шта нам нису потребни догађаји).

  • Функција pg.mouse.get_pos() враћа уређени пар координата тачке на којој се тренутно налази показивач миша.

  • Функција pg.mouse.get_pressed() враћа торку од три елемента (уређену тројку), који се користе као логичке вредности. Елементи торке редом одговарају левом, средњем и десном тастеру миша. Вредност True означава да је тастер притиснут, а False да није. Тако се, на пример, условом if pg.mouse.get_pressed()[0]: могу оградити наредбе које се извршавају само ако је притиснут леви тастер миша.

  • Функција pg.key.get_pressed() враћа торку чији се елементи користе као логичке вредности, а показују за сваки тастер на тастатури да ли је он тренутно притиснут или не. Пошто је тастера пуно, за њихово очитавање се користе именоване константе. Константе pg.K_LEFT, pg.K_RIGHT, pg.K_UP, pg.K_DOWN одговарају тастерима са стрелицама, размаку одговара константа pg.K_SPACE, док тастерима слова, на пример a, b, c, одговарају константе pg.K_a, pg.K_b, pg.K_c итд. Тако се, на пример, условом if pg.key.get_pressed()[pg.K_SPACE]: могу оградити наредбе које се извршавају само ако је притиснут тастер за размак.

У овом приручнику нећемо пуно инсистирати на коришћењу ове технике, јер ћемо детаљније обрадити механизам догађајај. Прикажимо само неколико једноставних примера.

Анимирани лептир кога померамо мишем

Напиши програм који приказује анимираног лептира који лети по екрану и чији се центар налази увек тачно изнад показивача миша. За анимацију можеш употребити слике leptir1.png и leptir2.png.

../_images/leptir1.png ../_images/leptir2.png
32
 
1
import random, math
2
import pygame as pg
3
import pygamebg
4
5
(sirina, visina) = (400, 400)  # otvaramo prozor
6
prozor = pygamebg.open_window(sirina, visina, "Лептир прати миша")
7
8
# učitavamo dve slike leptira u listu
9
leptir_slike = []
10
for i in range(2):
11
    naziv_slike = "leptir" + str(???) + ".png"
12
    leptir_slike.append(???)
13
14
broj_frejma = 0 # redni broj tekućeg frejma
15
16
def crtaj():
17
    prozor.fill(pg.Color("white"))                        # bojimo pozadinu u belo
18
    (mis_x, mis_y) = pg.mouse.get_pos()                   # koordinate miša
19
    broj_slike = (broj_frejma // 10) % len(leptir_slike)  # redni broj slike - svaka se slika prikazuje 10 frejmova
20
    slika = leptir_slike[broj_slike]                      # slika koja se prikazuje
21
    slika_sirina = ???                                    # prikazujemo sliku centrirano
22
    slika_visina = ???
23
    (x, y) = (???, ???)
24
    prozor.blit(slika, (x, y))
25
26
def novi_frejm():
27
    global broj_frejma
28
    ???    # uvećavamo redni broj frejma
29
    crtaj()
30
31
pygamebg.frame_loop(50, novi_frejm)
32

(animirani_leptir)

Лоптица која прати миша

Напиши програм који приказује лоптицу која се увек полако креће ка тренутној позицији миша.

У програму ћемо памтити текућу позицију лоптице. Кључно питање је како одредити позицију лоптице у наредном фрејму. Нека тачка A представља текућу позицију центра лоптице, нека тачка B представља текућу позицију показивача миша и нека тачка X представља нову позицију центра лоптице. Пошто се центар помера из тачке A у тачку X лоптица у једном фрејму пређе пут једнак растојању између те две тачке. Обележимо ту вредност са v (ако хоћемо да се лоптица креће глатко, број фрејмова у секунди треба да буде већи, а то треба да буде нека мала вредност). Поставља се питање колико по хоризонтали и колико по вертикали треба да се помери лоптица. Троуглови AXxX и ACB су слични. Зато се дужине AXx и XxX које представљају хоризонтално и вертикално померање могу израчунати на основу дужине AX која је једнака v, дужине AB која се може израчунати Питагорином теоремом као растојање између тачке А и B чије су нам координате познате, дужине AC која је једнака разлици између x координата тачака A и B и дужне BC која је разлика између њихових y координата. Важи да је AXx:AX=AC:AB, као и да је XXx:AX=BC:AB одакле се израчунавају координате непознате тачке X.

../_images/pratim_misa_koordinate.png
34
 
1
import random, math
2
import pygame as pg
3
import pygamebg
4
5
(sirina, visina) = (250, 250)  # otvaramo prozor
6
prozor = pygamebg.open_window(sirina, visina, "Лоптица прати миша")
7
8
# rastojanje između dve date tačke (zadate parovima koordinata)
9
def rastojanje(A, B):
10
    (xa, ya) = A
11
    (xb, yb) = ???
12
    return math.sqrt(???**2 + ???**2)
13
14
(x, y) = (???, ???)   # pozicija loptice - inicijalno u centru prozora
15
16
def crtaj():
17
    # crtamo zelenu lopticu na beloj pozadini
18
    prozor.fill(???)
19
    pg.draw.circle(prozor, ???, ???, 10)
20
21
def novi_frejm():
22
    global x, y
23
    (xm, ym) = ???                    # koordinate pozicije miša
24
    d = rastojanje((x, y), (xm, ym))  # rastojanje tačke od miša
25
    v = 2                             # brzina kretanja loptice
26
    if d < v:                         # ako je loptica dovoljno blizu miša pomera
27
        (x, y) = ???                  #    pomera se tačno na poziciju miša
28
    else:                             # u suprotnom
29
        x = x + v * (xm - x) / d      #    pomera se malo u smeru ka mišu
30
        ???
31
    crtaj()
32
33
pygamebg.frame_loop(50, novi_frejm)
34

(pratim_misa)