from tkinter import * from random import randrange as rand from random import uniform as uni from math import radians, cos, sin, atan2, sqrt def obroc(x, y, sx, sy, a_stopnie): a_rad = radians(a_stopnie) x_nowy = (x - sx) * cos(a_rad) - (y - sy) * sin(a_rad) + sx y_nowy = (x - sx) * sin(a_rad) + (y - sy) * cos(a_rad) + sy return x_nowy, y_nowy def klawisz_wcisniety(event): key = event.keysym.lower() if key in wcisniete_klawisze: wcisniete_klawisze[key] = True def klawisz_puszczony(event): key = event.keysym.lower() if key in wcisniete_klawisze: wcisniete_klawisze[key] = False def gluwna(): global czekaj_scala, przeladowanie rusz() strzal() aktu_pociski() skala() asteroidy_ruch() sprawdz_kolizje_statku() sprawdz_kolizje_asteroid_i_pociskow() odlamki_ruch() czekaj_scala -= 1 przeladowanie -= 1 root.after(16, gluwna) def asteroidy_ruch(): for a in range(len(asteroidy)): ast = asteroidy[a] xp = uni(-0.01, 0.01) ast["dx"] += xp yp = uni(-0.01, 0.01) ast["dy"] += yp canvas.move(ast["id"], ast["dx"], ast["dy"]) if ast["dziury"]: for dz in ast["dziury"]: canvas.move(dz["id1"], ast["dx"], ast["dy"]) canvas.move(dz["id2"], ast["dx"], ast["dy"]) dz["x"] += ast["dx"] dz["y"] += ast["dy"] def sprawdz_kolizje_statku(): global v, mapa_x, mapa_y if v == 0: return cx = srodek_ekranu_x cy = srodek_ekranu_y promien_statku = 25 for k in asteroidy: kordy_ast = canvas.coords(k["id"]) if len(kordy_ast) < 4: continue kx_srodek = (kordy_ast[0] + kordy_ast[2]) / 2 ky_srodek = (kordy_ast[1] + kordy_ast[3]) / 2 r_asteroidy = k["r"] odleglosc = sqrt((cx - kx_srodek) ** 2 + (cy - ky_srodek) ** 2) min_odleglosc = promien_statku + r_asteroidy if odleglosc < min_odleglosc: nakladanie = min_odleglosc - odleglosc kat = atan2(cy - ky_srodek, cx - kx_srodek) dx = nakladanie * cos(kat) dy = nakladanie * sin(kat) canvas.move("gwiazdy", dx, dy) canvas.move(koniec_mapy, dx, dy) mapa_x -= dx mapa_y -= dy v = 0 wcisniete_klawisze["w"] = False break def odlamki_ruch(): if odlamki: for odlamek in odlamki: canvas.move(odlamek["id"], odlamek["dx"], odlamek["dy"]) def sprawdz_kolizje_asteroid_i_pociskow(): for ast in asteroidy: kordy_ast = canvas.coords(ast["id"]) if not kordy_ast: continue srx = (kordy_ast[0] + kordy_ast[2]) / 2 sry = (kordy_ast[1] + kordy_ast[3]) / 2 r_ast = ast["r"] for zast in asteroidy: if ast["id"] == zast["id"]: continue kordy_zast = canvas.coords(zast["id"]) if not kordy_zast: continue srxz = (kordy_zast[0] + kordy_zast[2]) / 2 sryz = (kordy_zast[1] + kordy_zast[3]) / 2 r_zast = zast["r"] odleglosc = sqrt((srx - srxz) ** 2 + (sry - sryz) ** 2) min_odleglosc = r_ast + r_zast # print(f"Sprawdzam asteroidę {ast["id"]}. Liczba dziur: {len(ast["dziury"])}") if odleglosc < min_odleglosc: ast["dx"] = -ast["dx"] ast["dy"] = -ast["dy"] zast["dx"] = -zast["dx"] zast["dy"] = -zast["dy"] canvas.move(ast["id"], ast["dx"], ast["dy"]) if ast["dziury"]: for dz in ast["dziury"]: canvas.move(dz["id1"], ast["dx"], ast["dy"]) canvas.move(dz["id2"], ast["dx"], ast["dy"]) dz["x"] += ast["dx"] dz["y"] += ast["dy"] # print("xx") if len(kordy_ast) >= 4: kx_srodek = (kordy_ast[0] + kordy_ast[2]) / 2 ky_srodek = (kordy_ast[1] + kordy_ast[3]) / 2 r_ast = ast["r"] for p in range(len(pociski) - 1, -1, -1): po = pociski[p] pos1 = canvas.coords(po["id1"]) pos2 = canvas.coords(po["id2"]) if not pos1 or not pos2: continue pos_x = (pos1[0] + pos1[2] + pos2[0] + pos2[2]) / 4 pos_y = (pos1[1] + pos1[3] + pos2[1] + pos2[3]) / 4 rpos = po["r"] odleglosc = sqrt((pos_x - kx_srodek) ** 2 + (pos_y - ky_srodek) ** 2) if odleglosc < r_ast + rpos: prze = 2 * po["rr"] + uni(0.0, 1.0) canvas.move(po["id1"], po["dx"] * prze, po["dy"] * prze) canvas.move(po["id2"], po["dx"] * prze, po["dy"] * prze) pos1 = canvas.coords(po["id1"]) pos2 = canvas.coords(po["id2"]) if pos1 and pos2: p1_srodek_x = (pos1[0] + pos1[2]) / 2 p1_srodek_y = (pos1[1] + pos1[3]) / 2 p2_srodek_x = (pos2[0] + pos2[2]) / 2 p2_srodek_y = (pos2[1] + pos2[3]) / 2 pos_x = (p1_srodek_x + p2_srodek_x) / 2 pos_y = (p1_srodek_y + p2_srodek_y) / 2 dz1 = canvas.create_oval(p1_srodek_x - po["rr"], p1_srodek_y - po["rr"], p1_srodek_x + po["rr"], p1_srodek_y + po["rr"], fill=kolory[po["zestaw"]][po["kolor"] - 1], outline=kolory[po["zestaw"]][po["kolor"]], tags="gwiazdy") dz2 = canvas.create_oval(p2_srodek_x - po["rr"], p2_srodek_y - po["rr"], p2_srodek_x + po["rr"], p2_srodek_y + po["rr"], fill=kolory[po["zestaw"]][po["kolor"] - 1], outline=kolory[po["zestaw"]][po["kolor"]], tags="gwiazdy") ast["dziury"].append({"id1": dz1, "id2": dz2, "x": pos_x, "y": pos_y}) for odla in range(10): odlamek1 = canvas.create_oval(p1_srodek_x - po["rr"], p1_srodek_y - po["rr"], p1_srodek_x + po["rr"], p1_srodek_y + po["rr"], fill=f"grey{rand(20, 30)}", outline="", tags="gwiazdy") odlamki.append({"id": odlamek1, "dx": uni(-1.0, 1.0), "dy": uni(-1.0, 1.0)}) root.after(1000, lambda od=odlamek1: canvas.delete(od)) odlamek2 = canvas.create_oval(p2_srodek_x - po["rr"], p2_srodek_y - po["rr"], p2_srodek_x + po["rr"], p2_srodek_y + po["rr"], fill=f"grey{rand(20, 30)}", outline="", tags="gwiazdy") odlamki.append({"id": odlamek2, "dx": uni(-1.0, 1.0), "dy": uni(-1.0, 1.0)}) root.after(1000, lambda od=odlamek2: canvas.delete(od)) root.after(600, lambda d1=dz1: canvas.itemconfig(d1, fill=f"grey{rand(10, 30)}", outline="")) root.after(600, lambda d2=dz2: canvas.itemconfig(d2, fill=f"grey{rand(10, 30)}", outline="")) # print("Dziura dodana pomyślnie!") canvas.delete(po["id1"]) canvas.delete(po["id2"]) pociski.pop(p) # print("x") def bok(lewo): global srodek_ekranu_x, srodek_ekranu_y, obroc_o, statek_bazowy if lewo: r = 3 x, y = obroc(statek_bazowy[2], statek_bazowy[3], srodek_ekranu_x, srodek_ekranu_y, obroc_o) s2 = canvas.create_oval(x - r, y - r, x + r, y + r, fill="#000000", outline="", tags="gwiazdy") for i in range(50): wartosc_rgb = int((49 - i) * (255 / 49)) he = f"{wartosc_rgb:02X}" kolor = f"#0000{he}" root.after(i * 6, lambda k=kolor: canvas.itemconfig(s2, fill=k)) root.after(300, lambda: canvas.delete(s2)) canvas.tag_lower(s2) else: r = 3 x, y = obroc(statek_bazowy[6], statek_bazowy[7], srodek_ekranu_x, srodek_ekranu_y, obroc_o) s2 = canvas.create_oval(x - r, y - r, x + r, y + r, fill="#000000", outline="", tags="gwiazdy") for i in range(50): wartosc_rgb = int((49 - i) * (255 / 49)) he = f"{wartosc_rgb:02X}" kolor = f"#0000{he}" root.after(i * 6, lambda k=kolor: canvas.itemconfig(s2, fill=k)) root.after(300, lambda: canvas.delete(s2)) canvas.tag_lower(s2) def skala(): global czekaj_scala if wcisniete_klawisze["q"] and wiel_pocis.get() >= 1 and czekaj_scala <= 0: wiel_pocis.set(wiel_pocis.get() - 1) czekaj_scala = 20 if wcisniete_klawisze["e"] and wiel_pocis.get() < 6 and czekaj_scala <= 0: wiel_pocis.set(wiel_pocis.get() + 1) czekaj_scala = 20 def rusz(): global wcisniete_klawisze, mapa_y, mapa_x, obroc_o, probrotowa, v a_rad = radians(obroc_o) dx = v * sin(a_rad) dy = v * cos(a_rad) if wcisniete_klawisze["a"]: probrotowa -= 0.1 bok(True) if wcisniete_klawisze["d"]: probrotowa += 0.1 bok(False) if probrotowa < 0: probrotowa += 0.03 if probrotowa > 0: probrotowa -= 0.03 obroc_o += probrotowa if -1500 < mapa_x + dx < 3600 and -800 < mapa_y - dy < 1800: canvas.move("gwiazdy", -dx, dy) canvas.move("pociski", -dx, dy) canvas.move(koniec_mapy, -dx, dy) mapa_x += dx mapa_y -= dy if wcisniete_klawisze["w"] and v < 5: v += 0.05 if wcisniete_klawisze["s"] and v > -2: v -= 0.05 nowe_punkty = [] for i in range(0, len(statek_bazowy), 2): bx = statek_bazowy[i] by = statek_bazowy[i + 1] nx, ny = obroc(bx, by, srodek_ekranu_x, srodek_ekranu_y, obroc_o) nowe_punkty.extend([nx, ny]) canvas.coords(statek, *nowe_punkty) nowe_punkty = [] for i in range(0, len(lewe_bazowe), 2): bx = lewe_bazowe[i] by = lewe_bazowe[i + 1] nx, ny = obroc(bx, by, srodek_ekranu_x, srodek_ekranu_y, obroc_o) nowe_punkty.extend([nx, ny]) canvas.coords(lewe_dzialo, *nowe_punkty) nowe_punkty = [] for i in range(0, len(prawe_bazowe), 2): bx = prawe_bazowe[i] by = prawe_bazowe[i + 1] nx, ny = obroc(bx, by, srodek_ekranu_x, srodek_ekranu_y, obroc_o) nowe_punkty.extend([nx, ny]) canvas.coords(prawe_dzialo, *nowe_punkty) if wcisniete_klawisze["w"] or wcisniete_klawisze["s"]: r = 6 s1 = canvas.create_oval(srodek_ekranu_x - r, srodek_ekranu_y - r, srodek_ekranu_x + r, srodek_ekranu_y + r, fill="#000000", outline="", tags="gwiazdy") for i in range(50): wartosc_rgb = int((49 - i) * (255 / 49)) he = f"{wartosc_rgb:02X}" kolor = f"#{he}0000" root.after(i * 24, lambda k=kolor: canvas.itemconfig(s1, fill=k)) root.after(1200, lambda: canvas.delete(s1)) canvas.tag_lower(s1) def strzal(): global srodek_ekranu_x, srodek_ekranu_y, obroc_o, v, przeladowanie if wcisniete_klawisze["space"] and przeladowanie <= 0: r = wiel_pocis.get() kolor = kolory[int(kol_pocis.get() - 1)][rand(0, len(kolory[int(kol_pocis.get() - 1)]))] xl, yl = obroc(lewe_bazowe[2], lewe_bazowe[3], srodek_ekranu_x, srodek_ekranu_y, obroc_o) xp, yp = obroc(prawe_bazowe[2], prawe_bazowe[3], srodek_ekranu_x, srodek_ekranu_y, obroc_o) s3 = canvas.create_oval(xl - r, yl - r, xl + r, yl + r, fill=kolor, outline="", tags="pociski") s4 = canvas.create_oval(xp - r, yp - r, xp + r, yp + r, fill=kolor, outline="", tags="pociski") kat_rad = radians(obroc_o) predkosc_pocisku = v + 8 - wiel_pocis.get() przeladowanie = wiel_pocis.get() ** 2.5 vx = predkosc_pocisku * sin(kat_rad) + uni(-0.1, 0.1) vy = -predkosc_pocisku * cos(kat_rad) + uni(-0.1, 0.1) # print(kolory[int(kol_pocis.get())]) pociski.append({"id1": s3, "id2": s4, "dx": vx, "dy": vy, "r": 2 * r + 14, "rr": r, "zestaw": kol_pocis.get() - 1, "kolor": kolory[int(kol_pocis.get()) - 1].index(kolor)}) r_blysk = wiel_pocis.get() * 2 s5 = canvas.create_oval(xl - r_blysk, yl - r_blysk, xl + r_blysk, yl + r_blysk, fill="yellow", outline="red", tags="pociski") s6 = canvas.create_oval(xp - r_blysk, yp - r_blysk, xp + r_blysk, yp + r_blysk, fill="yellow", outline="red", tags="pociski") root.after(rand(30, 60), lambda w6=s6: canvas.delete(w6)) root.after(rand(30, 60), lambda w5=s5: canvas.delete(w5)) def aktu_pociski(): global pociski aktywne_pociski = [] for p in pociski: wspolrzedne = canvas.coords(p["id1"]) if not wspolrzedne: continue if wspolrzedne[0] < -2000 or wspolrzedne[0] > 4000 or wspolrzedne[1] < -1500 or wspolrzedne[1] > 2500: canvas.delete(p["id1"]) canvas.delete(p["id2"]) continue canvas.move(p["id1"], p["dx"], p["dy"]) canvas.move(p["id2"], p["dx"], p["dy"]) aktywne_pociski.append(p) pociski = aktywne_pociski root = Tk() root.geometry("1000x700") root.attributes("-fullscreen", True) canvas = Canvas(root, bg="black", highlightthickness=0) canvas.pack(fill="both", expand=True) koniec_mapy = canvas.create_rectangle(-1900, -1000, 3800, 2000, fill="", outline="red", width=5) for i in range(1000): x = rand(-1900, 3800) y = rand(-1000, 2000) r = 2 g = canvas.create_oval(x, y, x + r, y + r, fill="white", outline="", tags="gwiazdy") wcisniete_klawisze = {"w": False, "s": False, "a": False, "d": False, "space": False, "q": False, "e": False} root.update() x_w = canvas.winfo_width() y_w = canvas.winfo_height() srodek_ekranu_x = x_w / 2 srodek_ekranu_y = y_w / 2 mapa_x = srodek_ekranu_x mapa_y = srodek_ekranu_y x = 20 y = 30 statek_bazowy = [srodek_ekranu_x, srodek_ekranu_y - y, srodek_ekranu_x + x, srodek_ekranu_y + y, srodek_ekranu_x, srodek_ekranu_y, srodek_ekranu_x - x, srodek_ekranu_y + y] statek = canvas.create_polygon(*statek_bazowy, fill="lightblue", outline="") lewe_bazowe = [srodek_ekranu_x - 7, srodek_ekranu_y + 5, srodek_ekranu_x - 7, srodek_ekranu_y - y + 10] lewe_dzialo = canvas.create_line(*lewe_bazowe, fill="lightblue", width=3) prawe_bazowe = [srodek_ekranu_x + 7, srodek_ekranu_y + 5, srodek_ekranu_x + 7, srodek_ekranu_y - y + 10] prawe_dzialo = canvas.create_line(*prawe_bazowe, fill="lightblue", width=3) przeladowanie = 10 pociski = [] wiel_pocis = Scale(root, from_=1, to=6, orient=HORIZONTAL, length=200, width=20, bg="grey30", fg="#ffffff", troughcolor="#4a90e2", activebackground="#ff9900", label="Wielkość pocisków: < q | e >", highlightthickness=0, bd=2) wiel_pocis.place(x=0, y=0) wiel_pocis.set(1) czekaj_scala = 10 kolory = [["red", "yellow", "gold", "orange", "red3"], ["green", "limegreen", "forestgreen", "darkgreen", "lawngreen"], ["blue", "blue2", "DeepSkyBlue3", "RoyalBlue3", "mediumblue"], ["grey20", "grey18", "grey16", "grey14", "grey12", "grey10"]] kol_pocis = Scale(root, from_=1, to=len(kolory), showvalue=False, tickinterval=1, orient=HORIZONTAL, length=200, width=20, bg="grey30", fg="#ffffff", troughcolor="#4a90e2", activebackground="#ff9900", label="Kolor pocisków: zestaw: ", highlightthickness=0, bd=2) kol_pocis.place(x=0, y=68) kol_pocis.set(1) obroc_o = 0 probrotowa = 0 v = 0 odlamki = [] asteroidy = [] for i in range(rand(40, 80)): x = rand(-1900, 3800) y = rand(-1000, 2000) r = rand(10, 50) g = canvas.create_oval(x - r, y - r, x + r, y + r, fill=f"grey{rand(20, 31)}", outline="", tags=("gwiazdy", "asteroidy")) asteroidy.append({"id": g, "r": r, "dx": 0, "dy": 0, "dziury": []}) root.bind("", klawisz_wcisniety) root.bind("", klawisz_puszczony) root.bind("", lambda event: root.destroy()) gluwna() root.mainloop()