Matematika, náhoda a kolize
Tato stránka popisuje číselné funkce, generátor náhodných čísel s počáteční hodnotou a kolizní metody třídy Sprite. Ani jeden z pomocných modulů nevyžaduje inicializaci enginu. Signatury najdeš v /cs/reference/.
picogame_math
Sekce “picogame_math”picogame_math nabízí funkce clamp, lerp, approach a wrap, výpočty s 2D vektory a trigonometrii vyjádřenou v otáčkách. Funkce končící na _t používají pro celou otáčku interval [0,1), což se hodí pro uložený směr nebo míření. Modul také převzal vektorové funkce ze staršího picogame_vec.
API:
clamp(v, lo, hi)- omezívna interval[lo, hi], například pro pozici na obrazovce nebo počet životů.mid(a, b, c)- vrátí medián tří hodnot; pokud je prostředním argumentem omezovaná hodnota, chová se podobně jakoclamp.lerp(a, b, t)- lineární interpolacea + (b-a)*t. Opakované volání s malýmtvytváří plynulé přibližování.inv_lerp(a, b, v)- inverzelerp: kde ležívv[a,b]jako0..1. Vrátí0.0, pokuda == b.remap(v, a, b, c, d)- převedevz rozsahu[a,b]na[c,d]. Pokuda == b, vrátíc.sgn(x)- znaménko jako-1,0nebo1.approach(v, target, step)- posunevktargetnejvýše ostep, bez překročení cíle. Hodí se pro zrychlování a zpomalování.wrap(v, lo, hi)- zabalívdo polootevřeného rozsahu[lo, hi). Degenerované nebo obrácené rozsahy vrátílo(žádné dělení nulou, nikdy mimo rozsah).sin_t(turns)/cos_t(turns)- sinus/kosinus úhlu v OTÁČKÁCH (1.0= celý kruh). Kladná hodnota je po směru hodinových ručiček na obrazovce s osou y dolů.atan2_t(dy, dx)- úhel vektoru(dx, dy)v otáčkách, normalizovaný do0..1. Použij na míření.length(dx, dy)- velikost vektoru.distance(x1, y1, x2, y2)- vzdálenost mezi dvěma body.normalize(dx, dy)- jednotkový vektor; pro vstup nulové délky vrátí(0.0, 0.0).angle_rad(dx, dy)- úhel v RADIÁNECH (surovýatan2);from_angle_rad(a, mag=1.0)- vektor délkymagpod radiánovým úhlema.TAU- konstanta2*pi, kterou interně používá trigonometrie s_t.
Příklad otočení lodi a tahu ve směru její přídě:
import picogame_math as m
ang = 0.0 # heading, in turns 0..1TURN = 0.01ang = (ang + TURN) % 1.0 # rotate rightdx, dy = m.sin_t(ang), -m.cos_t(ang) # nose-up directionvx += dx * 0.25vy += dy * 0.25sp = m.length(vx, vy) # current speedx = m.clamp(x, 8, W - 8) # udrží objekt na obrazovcepicogame_rand
Sekce “picogame_rand”Tento generátor xorshift32 podporuje vážený výběr, zamíchání seznamu na místě a losovací sáček. Pevná počáteční hodnota vytváří opakovatelnou posloupnost pro záznamy hry, testy nebo generování úrovní. Rand() bez argumentu použije aktuální čas. Bag v každém zamíchaném cyklu vydá každou položku jednou, takže omezuje dlouhé série stejného výsledku.
Rand(seed=None):
Rand(1234)použije pevnou počáteční hodnotu;Rand()ji odvodí z hodin. Hodnota0se interně nahradí, protože z ní xorshift nemůže začít.seed(s)- nastaví novou počáteční hodnotu existujícího generátoru.below(n)- celé číslo v0 .. n-1. Vrátí0, pokudn <= 0.randint(a, b)- celé číslo va .. bvčetně. VyhodíValueError, pokudb < a.random()- float v[0.0, 1.0).chance(p)-Trues pravděpodobnostíp(kdepje0..1).choice(seq)- jeden prvek zeseq. VyhodíValueErroru prázdné sekvence.shuffle(lst)- zamíchálstalgoritmem Fisher–Yates přímo v původním seznamu a vrátíNone.weighted(weights)- vrátí index0..len-1vybraný úměrně kweights. VyhodíValueError, pokud je součet<= 0. Bez řízení šňůr (nezávislé tahy).
Bag(items, rng):
- Losovací sáček neboli „7-bag“ vydá každou položku jednou za cyklus v zamíchaném pořadí. Pro herní dílky nebo výskyt objektů tak nevznikají dlouhé série ani období bez určité položky.
next()- vrátí další položku, na začátku každého cyklu automaticky zamíchá. VyhodíValueErrorpři konstrukci, pokud jeitemsprázdné.
Příklad jednoho generátoru a losovacího sáčku:
import picogame_rand
rng = picogame_rand.Rand(0x1234) # seeded -> reproduciblex = rng.randint(40, W - 40) # 40 .. W-40 inclusiveif rng.chance(0.25): spawn_powerup(x)kind = rng.weighted([5, 3, 1]) # index 0 most likelybag = picogame_rand.Bag([0, 1, 2, 3, 4, 5, 6], rng)piece = bag.next() # každá hodnota jednou za cyklusKolize spritů
Sekce “Kolize spritů”Každý Sprite nabízí kolizi obdélníků a test vzdálenosti středů. Metody pracují s vykreslenými hranicemi po započtení kotevního bodu, měřítka a rotace a nealokují návratový objekt. overlaps() použij pro průnik spritů nebo obdélníků, near() pro kruhový test vzdálenosti.
API (metody na každém Sprite):
a.overlaps(b, inset=0)- testuje včetně dotyku překryv osově zarovnaných obdélníků.bmůže být jinýSprite, bod(x, y)nebo obdélník(x1, y1, x2, y2). Parametrinsetzmenší kolizní obdélník prvního spritu o N pixelů na každé straně. Vracíbool.a.near(b, r)- kruhový test: je střed tohoto spritu dorpx od středub? Používá kvadrát vzdálenosti, takže žádnýsqrt.bmůže býtSpritenebo bod(x, y).
Obdélníky a středy vycházejí z vykreslené plochy spritu, včetně kotevního bodu, měřítka a rotace. Kotevní body popisuje /cs/scene-format/.
Pro dva vypočtené obdélníky bez spritů použij pg.collide(x1, y1, x2, y2, ax1, ay1[, ax2, ay2]). U zdí a terénu v mřížce se dotazuj na vlastnosti přes picogame_tiles místo testování každé dlaždice.
Příklad kruhové kolize střel s kameny a obdélníkové kolize hráče:
for b in bullets: for r in rocks: if b.visible and b.near(r, 18): # kruhový test bez odmocniny kill(b, r)
if player.overlaps(enemy): # překryv obdélníků se započtením kotev take_damage()
if not ship.overlaps((0, 0, W, H)): # mimo obrazovku? odeber ho pool.free(ship)