P1 2021/22 - 12 Bitka - resitev Starc Aljaz v2¶
Warning
Ta resitev deluje, a je napacna, saj ne uporablja koncepta objektnega programiranja (kar je celoten point naloge)
from typing import List, Tuple
import risar
import random
import itertools
import time
from PyQt5.QtWidgets import QMessageBox
def rnd_num (start: int|float, end: int|float, disallowed: List[Tuple[int|float, int|float]]):
while True:
num = random.uniform(start, end)
# check if generated number is in any disallowed range
for rng in disallowed:
# if it is, just break the loop and generete a new number
if (rng[0] < num < rng[1]):
break
else:
# number is not in any disallowed ranges!
# we return it :)
return num
def rnd_ladja (x = None, y = None, r = None, barva = None, sirina = 1):
if not x:
x, _ = risar.nakljucne_koordinate()
if not y:
_, y = risar.nakljucne_koordinate()
if not r:
r = random.randint(2, 20)
if not barva:
barva = risar.nakljucna_barva()
return risar.krog(x=x, y=y, r=r, barva=barva, sirina=sirina)
def do_they_collide (x1, y1, r1, x2, y2, r2):
distSq = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
radSumSq = (r1 + r2) * (r1 + r2);
return distSq <= radSumSq
def fade_krog (krog, alpha):
brush = krog.pen().color().lighter()
brush.setAlpha(alpha)
krog.setBrush(brush)
def nova_explozija (x, y, r, barva, lifetime_ms = 4000, sirina = 1):
expl = risar.krog(x=x, y=y, r=r, barva=barva, sirina=sirina)
el = {
"l": expl,
"type": "explosion",
"x": x,
"y": y,
"r": r,
"exploded_at": time.time(),
"lifetime_ms": lifetime_ms
}
return el
def run_simulation (ladij=20, za_uniciti=10, pixel_per_cycle=1, cycle_delay=.0025, ladja_radij=10, miska_radij=30, explozija_radij=30, explozija_trajanje_ms=4000):
risar.pobrisi()
QMessageBox.information(None, "Zacetek igre", "Skupaj ladij: %i - uniciti vsaj %i" % (ladij, za_uniciti))
# Lista "objekti" vsebuje entitete kot so ladje ter explozije
ladje = []
explozije = []
# Kreiraj ladje ter jih dodaj v listo entitet
for _ in range(ladij):
barva = risar.nakljucna_barva()
ladje.append({
"l": rnd_ladja(r=ladja_radij, barva=barva),
"barva": barva,
"r": ladja_radij,
"move_x": rnd_num(-1, 1, [(-.6, .6)]),
"move_y": rnd_num(-1, 1, [(-.6, .6)]),
"type": "ship"
})
# Kreiraj misko, edina entiteta, ki ni dodana v listo 'objekti'
miska_barva = risar.nakljucna_barva()
miska_krog = risar.krog(*risar.miska(), r=miska_radij, barva=miska_barva, sirina=1)
# Zazenemo "main event loop?"
while True:
# Ce miska se ni bila kliknjena (ob kliku se krog odstrani)
if miska_krog is not None:
# premaknemo krog na trenutno pozicijo miske
x, y = risar.miska()
miska_krog.setPos(x, y)
# in ce je slucajno ravno kliknjena
if risar.klik():
# dodamo explozijo v listo 'objekti'
explozije.append(nova_explozija(x=x, y=y, r=explozija_radij, barva=miska_barva, lifetime_ms=explozija_trajanje_ms))
# ter odstranimo miskin krog
risar.odstrani(miska_krog)
miska_krog = None
# ce je miska klinjena
# ter ni vec nobenih eksplozij
elif explozije == [] or ladje == []:
# je poiskus spodletel
if len(ladje) > za_uniciti:
QMessageBox.information(None, "Igra spodletela!", "Skupaj ladij: %i - za uniciti: %i - uniciti %i" % (ladij, za_uniciti, ladij - len(ladje)))
return False
else:
QMessageBox.information(None, "Zmaga!", "Skupaj ladij: %i - za uniciti: %i - unicenih %i" % (ladij, za_uniciti, ladij - len(ladje)))
return True
for objekt, obj_i in zip(ladje, itertools.count()):
x = objekt["l"].x()
y = objekt["l"].y()
r = objekt["r"]
o_left = x - r <= 0
o_right = x + r >= risar.maxx
o_top = y - r <= 0
o_bottom = y + r >= risar.maxy
# levi del kroga je izven okna, desni se ni
if (o_left and not o_right): objekt["move_x"] = abs(objekt["move_x"])
# desni del kroga je izven okna, levi se ni
if (not o_left and o_right): objekt["move_x"] = 0 - abs(objekt["move_x"])
# spodnji del kroga je izven okna, zgornji se ni
if (not o_bottom and o_top): objekt["move_y"] = abs(objekt["move_x"])
# spodnji del kroga je izven okna, zgornji se ni
if (o_bottom and not o_top): objekt["move_y"] = 0 - abs(objekt["move_y"])
# premaknemo ladjo
objekt["l"].setPos(
objekt["l"].x() + objekt["move_x"] * pixel_per_cycle,
objekt["l"].y() + objekt["move_y"] * pixel_per_cycle
)
# preveri ce se je ladja zadela v explozijo
for e in explozije:
if e["type"] == "explosion" and do_they_collide(x, y, objekt["r"], e["x"], e["y"], e["r"]):
explozije.append(nova_explozija(x, y, explozija_radij, barva=objekt["barva"], lifetime_ms=explozija_trajanje_ms))
risar.odstrani(objekt["l"])
del ladje[obj_i]
break
# odstranimo / fade-amo explozije
for objekt, obj_i in zip(explozije, itertools.count()):
time_alive_ms = (time.time() - objekt["exploded_at"]) * 1000
# Ali obstaja vec casa kot lahko?
if time_alive_ms < objekt["lifetime_ms"]:
time_out_of_total = time_alive_ms / objekt["lifetime_ms"]
alpha = 250 - 250 * time_out_of_total
fade_krog(objekt["l"], int(alpha))
else:
# odstrani in nadaljuj zanko po ostalih objektih
risar.odstrani(objekt["l"])
del explozije[obj_i]
risar.cakaj(cycle_delay)
stopnje = [
(30, 10),
(30, 12),
(28, 12),
(28, 14),
(26, 14),
(26, 16),
(24, 16),
(24, 18),
(22, 18),
(22, 20)
]
for ladij, za_uniciti in stopnje:
run_simulation(ladij=ladij, za_uniciti=za_uniciti)
Zadnja posodobitev:
May 7, 2022