tanks/statki.py
2026-06-13 13:48:15 +02:00

414 lines
16 KiB
Python

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("<KeyPress>", klawisz_wcisniety)
root.bind("<KeyRelease>", klawisz_puszczony)
root.bind("<Escape>", lambda event: root.destroy())
gluwna()
root.mainloop()