from tkinter import * from random import randrange as rand from tkinter import ttk from tkinter import messagebox from PIL import ImageTk, Image from noise import pnoise2 from random import uniform as uni from math import radians, cos, sin, atan2, sqrt, pi, degrees from tkinter import PhotoImage import os def pobierz_obrazek_jednostki(nazwa): plik = f"{nazwa} min.png" if plik not in obrazki_jednostek: try: obrazki_jednostek[plik] = PhotoImage(file=plik) except Exception as e: print("Brak obrazka:", plik, e) return None return obrazki_jednostek[plik] def zawsze(): global jednostki for j in jednostki: if j["linia"]["nazwa"] is not None: canvas.itemconfig(j["linia"]["nazwa"], dashoffset=j["linia"]["prze"]) j["linia"]["prze"] += 1 if j["linia"]["prze"] >= j["linia"]["dash"]["kropka"] + j["linia"]["dash"]["przerwa"]: j["linia"]["prze"] = 0 root.after(60, zawsze) def animuj(krok): ANIMACJA_KROKI = 100 if krok >= ANIMACJA_KROKI: global koniec_planowania for j in jednostki: j["x"] = j["cel_x"] j["y"] = j["cel_y"] j["linia"]["nazwa"] = None j["linia"]["prze"] = 0 koniec_planowania = True canvas.delete("linie") return for j in jednostki: dx = (j["cel_x"] - j["x"]) / (ANIMACJA_KROKI - krok) dy = (j["cel_y"] - j["y"]) / (ANIMACJA_KROKI - krok) canvas.move(j["sprite"], dx, dy) j["x"] += dx j["y"] += dy if "kat_docelowy" in j: roznica = j["kat_docelowy"] - j["kat"] if abs(roznica) > 180: if roznica > 0: roznica -= 360 else: roznica += 360 j["kat"] += roznica * 0.01 obrocony = j["img_org"].rotate( -j["kat"], expand=True, resample=Image.Resampling.BICUBIC ) j["img_tk"] = ImageTk.PhotoImage(obrocony) canvas.itemconfig( j["sprite"], image=j["img_tk"] ) root.after(15, lambda: animuj(krok + 1)) def zmien_predkosc(*args): if not jednostki: return global BONUS_RUCHU global aktualna_strona global wybrana_jednostka nowy_bonus = int( predkosc_ruchu.get().replace("x", "") ) BONUS_RUCHU = nowy_bonus for j in jednostki: dane = pobierz_dane_pojazdu(j["nazwa"]) j["ruch"] = int( dane["ruch"] * mnoznik_ruchu * BONUS_RUCHU ) j["wykonal_ruch"] = False j["cel_x"] = j["x"] j["cel_y"] = j["y"] wybrana_jednostka = None aktualna_strona = "USA" canvas.delete("plan") if jednostki: lbl_aktywny_pojazd.config( text="Wybierz jednostkę USA" ) global zasieg_podglad if zasieg_podglad: canvas.delete(zasieg_podglad) zasieg_podglad = None def pobierz_dane_pojazdu(nazwa): BAZA_POJAZDOW = {p["naz"]: p for p in pojazdy} return BAZA_POJAZDOW.get(nazwa) def strona_pojazdu(nazwa): if nazwa in usa: return "USA" elif nazwa in IIIRzesza: return "GER" return None def check_collision(x1, y1, x2, y2): for ux1, uy1, ux2, uy2 in placed_units: if not ( x2 + ODSTEP < ux1 or x1 - ODSTEP > ux2 or y2 + ODSTEP < uy1 or y1 - ODSTEP > uy2 ): return True return False def update_ghost(event): global ghost if not pojazdy_do_ustawienia: return nazwa = pojazdy_do_ustawienia[0] dane = pobierz_dane_pojazdu(nazwa) size_x = dane["sze"] * SKALA_JEDNOSTKI size_y = dane["wys"] * SKALA_JEDNOSTKI strona = strona_pojazdu(nazwa) kolor = "lime" w = canvas.winfo_width() granica_usa = w * 0.125 granica_ger = w * 0.875 if strona == "USA" and event.x > granica_usa: kolor = "red" if strona == "GER" and event.x < granica_ger: kolor = "red" if ghost: canvas.delete(ghost) ghost = canvas.create_rectangle( event.x - size_x // 2, event.y - size_y // 2, event.x + size_x // 2, event.y + size_y // 2, outline=kolor, fill="", width=3 ) def ustaw_pojazd(event): global pojazdy_do_ustawienia, aktualny_plan, kolejka_planowania, mnoznik_ruchu if not pojazdy_do_ustawienia: return nazwa = pojazdy_do_ustawienia[0] dane = pobierz_dane_pojazdu(nazwa) size_x = dane["sze"] * SKALA_JEDNOSTKI size_y = dane["wys"] * SKALA_JEDNOSTKI strona = strona_pojazdu(nazwa) w = canvas.winfo_width() granica_usa = w * 0.125 granica_ger = w * 0.875 if strona == "USA" and event.x > granica_usa: messagebox.showwarning( "RTS", "USA można ustawiać tylko w lewej strefie!" ) return if strona == "GER" and event.x < granica_ger: messagebox.showwarning( "RTS", "III Rzesza może być ustawiana tylko w prawej strefie!" ) return x1 = event.x - size_x // 2 y1 = event.y - size_y // 2 x2 = event.x + size_x // 2 y2 = event.y + size_y // 2 if check_collision(x1, y1, x2, y2): messagebox.showwarning("RTS", "Kolizja!") return placed_units.append((x1, y1, x2, y2)) try: nazwa_pliku = f"{nazwa} min.png" # {nazwa} #print(nazwa_pliku) img_org = Image.open(nazwa_pliku) except: nazwa_pliku = f"obraz_tk_3.png" img_org = Image.open(nazwa_pliku) img_org.thumbnail( (size_x, size_y), Image.Resampling.LANCZOS ) img_tk = ImageTk.PhotoImage(img_org) sprite = canvas.create_image( event.x, event.y, image=img_tk ) if strona == "USA": obrocony = img_org.rotate( 180, expand=True, resample=Image.Resampling.BICUBIC ) img_tk = ImageTk.PhotoImage(obrocony) canvas.itemconfig( sprite, image=img_tk ) jednostki.append({ "nazwa": nazwa, "strona": strona, "x": event.x, "y": event.y, "cel_x": event.x, "cel_y": event.y, "sprite": sprite, "img_org": img_org, "img_tk": img_tk, "kat": 0 if strona == "GER" else 180, "hp": 100, "wykonal_ruch": False, "ruch": int( dane["ruch"] * mnoznik_ruchu * BONUS_RUCHU ), "linia": {"nazwa": None, "dash": {"kropka": None, "przerwa": None}, "prze": 0} }) pojazdy_do_ustawienia.pop(0) if pojazdy_do_ustawienia: lbl_aktywny_pojazd.config(text=f"Ustaw: {pojazdy_do_ustawienia[0]}") else: messagebox.showinfo( "RTS", "Wszystkie jednostki rozmieszczone. Rozpoczyna się planowanie." ) aktualny_plan = 0 kolejka_planowania.clear() canvas.bind("", planowanie) lbl_aktywny_pojazd.config( text="Ustaw jednoske USA" ) def generuj_mape_noise(): bazowe_x = canvas.winfo_toplevel().winfo_screenwidth() bazowe_y = canvas.winfo_toplevel().winfo_screenheight() x_w = bazowe_x y_w = bazowe_y wybor = jakosc_mapy.get() if "Bardzo wysoka" in wybor: pixel = 1 skala = 0.0133 elif "Wysoka" in wybor: pixel = 2 skala = 0.0266 elif "Preferowana" in wybor: pixel = 3 skala = 0.04 elif "Niska" in wybor: pixel = 4 skala = 0.0533 else: pixel = 5 skala = 0.0666 rozmiar = rozmiar_mapy.get() if rozmiar == "Mała": pixel *= 2 skala /= 2 elif rozmiar == "Średnia": pass elif rozmiar == "Duża": pixel = max(1, round(pixel * 0.75)) skala /= 0.75 else: # Ogromna pixel = max(1, round(pixel * 0.5)) skala *= 2 max_y = y_w // pixel seed_x = uni(0, 1000) seed_y = uni(0, 1000) # print(f"Seed: {seed_x, seed_y}") for x in range(x_w // pixel): for y in range(max_y): szum = pnoise2(seed_x + x * skala, seed_y + y * skala, octaves=3) val = (szum + 1) / 2 v = val g_start = 122 g_end = 160 if v < 0.28: r, g, b = "00", "00", "FF" elif v <= 0.30: procent = (v - 0.28) / 0.02 wygladzenie = (1.0 - cos(procent * pi)) / 2.0 r_val = int(wygladzenie * 255) g_val = int(wygladzenie * 255) b_val = int((1.0 - wygladzenie) * 255) r = f"{max(0, min(255, r_val)):02X}" g = f"{max(0, min(255, g_val)):02X}" b = f"{max(0, min(255, b_val)):02X}" elif v <= 0.33: procent = (v - 0.30) / 0.03 wygladzenie = (1.0 - cos(procent * pi)) / 2.0 r_val = int((1.0 - wygladzenie) * 255) g_val = int(255 - wygladzenie * (255 - g_start)) r = f"{max(0, min(255, r_val)):02X}" g = f"{max(0, min(255, g_val)):02X}" b = "00" else: r = "00" b = "00" procent_g = (v - 0.33) / (1.0 - 0.33) wartosc_g = int(g_start + procent_g * (g_end - g_start)) g = f"{max(g_start, min(g_end, wartosc_g)):02X}" kolor = f"#{r}{g}{b}" canvas.create_rectangle(x * pixel, y * pixel, (x + 1) * pixel, (y + 1) * pixel, fill=kolor, outline="") def rysuj_pojazdy(): pixel = 1 x_w = canvas.winfo_toplevel().winfo_screenwidth() y_w = canvas.winfo_toplevel().winfo_screenheight() if len(usa) > 0: dzielnik_usa = (len(usa) - 1) if len(usa) > 1 else 1 u = int(y_w / (dzielnik_usa + 1)) for c in kolejnosc_pojazdow: if c in usa: canvas.create_rectangle( 15, u - 7, 30, u + 8, fill="black", ) if len(usa) > 1: u += int(y_w / (len(usa) + 1)) if len(IIIRzesza) > 0: dzielnik_rzesza = (len(IIIRzesza) - 1) if len(IIIRzesza) > 1 else 1 I = int(y_w / (dzielnik_rzesza + 1)) for c in kolejnosc_pojazdow: if c in IIIRzesza: canvas.create_rectangle( x_w - 30, I - 7, x_w - 15, I + 8, fill="black", outline="", ) if len(IIIRzesza) > 1: I += int(y_w / (len(IIIRzesza) + 1)) def start(): global SKALA_JEDNOSTKI, mnoznik_ruchu, BONUS_RUCHU canvas.master.update_idletasks() canvas.delete("all") if rozmiar_mapy.get() == "Mała": SKALA_JEDNOSTKI = 6 mnoznik_ruchu = 1.3 elif rozmiar_mapy.get() == "Średnia": SKALA_JEDNOSTKI = 5 mnoznik_ruchu = 1.0 elif rozmiar_mapy.get() == "Duża": SKALA_JEDNOSTKI = 4 mnoznik_ruchu = 0.7 else: SKALA_JEDNOSTKI = 3 mnoznik_ruchu = 0.3 SKALA_JEDNOSTKI *= 3 BONUS_RUCHU = int( predkosc_ruchu.get().replace("x", "") ) for j in jednostki: j["ruch"] = int(j["ruch"] * mnoznik_ruchu) generuj_mape_noise() if pojazdy_do_ustawienia: lbl_aktywny_pojazd.config(text=f"Ustaw: {pojazdy_do_ustawienia[0]}") canvas.bind("", ustaw_pojazd) zawsze() # --- INICJALIZACJA UTWORZENIA OKNA I BAZY DANYCH --- root = Tk() root.geometry("1000x700") root.attributes("-fullscreen", True) root.update() root.update_idletasks() kwadraty_lewe = ["LVT", "M3 St.", "M3 GMC", "M3 Lee", "M4A3", "M15 CGMC", "M22"] kwadraty_prawa = ["sd.KFz.222", "sd.KFz.251-9", "Pz.IIIF", "Pz.IIIC", "A7V", "Stug IIIb", "Beutepanzer IV"] zmienne_lewa = [] zmienne_prawa = [] baza_podgladu = { "M3 St.": { "foto": "M3.png", "lista": "Nr 1: M3 Stuart\nZasięg: 500m | Damage: 35 | Kierunek: Obrotowy | Ilość: 1\nHP: 200\nPrędkość: 58 km/h\nOpis: Amerykański lekki czołg, niezwykle szybki i zwrotny na polu bitwy.\nCiekawostka: Brytyjskie załogi nazywały go czule 'Honey' ze względu na płynną jazdę." }, "M22": { "foto": "M22.png", "lista": "Nr 2: M22 Locust\nZasięg: 450m | Damage: 30 | Kierunek: Obrotowy | Ilość: 1\nHP: 160\nPrędkość: 64 km/h\nOpis: Ultra lekki czołg zaprojektowany specjalnie z myślą o transporcie drogą powietrzną przez szybowce.\nCiekawostka: Aby zmieścił się pod szybowcem Hamilcar, trzeba było demontować mu wieżę na czas lotu." }, "sd.KFz.222": { "foto": "sd.KFz.222.png", "lista": "Nr 3: sd.KFz.222\nZasięg: 500m | Damage: 25 | Kierunek: Obrotowy | Ilość: 1\nHP: 100\nPrędkość: 80 km/h\nOpis: Lekki czterokołowy pojazd opancerzony, wykorzystywany przez Wehrmacht do szybkiego zwiadu.\nCiekawostka: Posiadał charakterystyczną drucianą siatkę nad wieżą chroniącą przed granatami ręcznymi." }, "M3 GMC": { "foto": "M3 GMC.png", "lista": "Nr 4: M3 GMC\nZasięg: 700m | Damage: 75 | Kierunek: Przód | Ilość: 1\nHP: 120\nPrędkość: 70 km/h\nOpis: Samobieżne działo przeciwpancerne zbudowane na bazie podwozia typu Halftrack.\nCiekawostka: Był kluczową bronią USA w walkach z czołgami Rommla w Afryce Północnej." }, "M15 CGMC": { "foto": "M15 CGMC.png", "lista": "Nr 5: M15 CGMC\nZasięg: 800m | Damage: 30 | Kierunek: Obrotowy | Ilość: 3\nHP: 140\nPrędkość: 65 km/h\nOpis: Samobieżne działo przeciwlotnicze wyposażone w automatyczną armatę i dwa karabiny maszynowe.\nCiekawostka: Jego siła ognia była tak duża, że często używano go do niszczenia piechoty wroga." }, "sd.KFz.251-9": { "foto": "sd.KFz.251-9.png", "lista": "Nr 6: sd.KFz.251-9\nZasięg: 550m | Damage: 50 | Kierunek: Przód (Wąski) | Ilość: 1\nHP: 160\nPrędkość: 50 km/h\nOpis: Półgąsienicowy transporter opancerzony wyposażony w krótkolufowe działo 7,5 cm KwK 37 L/24.\nCiekawostka: Ze względu na charakterystyczny kształt krótkiej, grubej lufy, niemieccy żołnierze nazywali ten pojazd 'Stummel' (Kikut)." }, "Pz.IIIF": { "foto": "Pz.IIIF.png", "lista": "Nr 7: Pz.IIIF\nZasięg: 600m | Damage: 45 | Kierunek: Obrotowy | Ilość: 1\nHP: 320\nPrędkość: 35 km/h\nOpis: Niemiecki czołg średni, wersja Ausf. F otrzymała ulepszone chłodzenie i armatę 50mm KwK 38.\nCiekawostka: Był kręgosłupem dywizji pancernych podczas początkowej fazy ataku na Związek Radziecki." }, "Pz.IIIC": { "foto": "Pz.IIIC.png", "lista": "Nr 8: Pz.IIIC\nZasięg: 450m | Damage: 20 | Kierunek: Obrotowy | Ilość: 1\nHP: 250\nPrędkość: 40 km/h\nOpis: Wczesna, rzadka wersja Panzer III o skomplikowanym zawieszeniu złożonym z 8 małych kół jezdnych.\nCiekawostka: Wyprodukowano zaledwie kilkadziesiąt sztuk, zanim system zawieszenia zmieniono na drążki skrętne." }, "M3 Lee": { "foto": "M3 Lee.png", "lista": "Nr 9: M3 Lee\nZasięg: 600m | Damage: 55 | Kierunek: Boczny + Obrotowy | Ilość: 2\nHP: 300\nPrędkość: 38 km/h\nOpis: Czołg średni o nietypowej konstrukcji z głównym działem zamontowanym w kadłubie.\nCiekawostka: Posiadał tak wysoką sylwetkę, że załogi nazywały go 'katedrą na gąsienicach'." }, "LVT": { "foto": "LVT.png", "lista": "Nr 10: LVT\nZasięg: 400m | Damage: 40 | Kierunek: Przód | Ilość: 1\nHP: 150\nPrędkość: 40 km/h\nOpis: Amfibijny pojazd gąsienicowy używany do operacji desantowych na Pacyfiku.\nCiekawostka: Początkowo został zaprojektowany jako cywilny pojazd ratunkowy na Florydzie." }, "M4A3": { "foto": "M4A3.png", "lista": "Nr 11: M4A3 Sherman\nZasięg: 650m | Damage: 60 | Kierunek: Obrotowy | Ilość: 1\nHP: 400\nPrędkość: 45 km/h\nOpis: Kultowa wersja amerykańskiego czołgu średniego wyposażona w ulepszony silnik Ford GAA.\nCiekawostka: Wersje te stały się bazą dla słynnych czołgów 'Easy Eight' z nowym zawieszeniem HVSS." }, "Stug IIIb": { "foto": "Stug IIIb.png", "lista": "Nr 12: Stug IIIb\nZasięg: 580m | Damage: 65 | Kierunek: Przód (Wąski) | Ilość: 1\nHP: 350\nPrędkość: 40 km/h\nOpis: Działo szturmowe pozbawione obrotowej wieży, zaprojektowane do bezpośredniego wspierania piechoty.\nCiekawostka: Z powodu braku wieży był tańszy w produkcji niż czołgi, stając się najskuteczniejszą bronią pancerną Niemiec." }, "Beutepanzer IV": { "foto": "Beutepanzer IV.png", "lista": "Nr 13: Beutepanzer IV\nZasięg: 450m | Damage: 60 | Kierunek: Boki i Przód | Ilość: 2\nHP: 450\nPrędkość: 6 km/h\nOpis: Brytyjski czołg ciężki Mark IV zdobyty podczas I wojny światowej, przebudowany i wcielony do armii niemieckiej.\nCiekawostka: Niemcy zamontowali w nim własne działa 5,7 cm oraz zmienili układ chłodzenia, tworząc z niego ruchomą fortecę." }, "A7V": { "foto": "A7V.png", "lista": "Nr 14: A7V\nZasięg: 550m | Damage: 70 | Kierunek: Przód i Boki | Ilość: 6\nHP: 500\nPrędkość: 15 km/h\nOpis: Konstrukcja wzorowana na jedynym niemieckim czołgu z okresu I Wojny Światowej (A7V).\nCiekawostka: Do obsługi tego giganta w wersji bojowej wymagana była monstrualna załoga licząca aż 18 osób." } } kolejnosc_pojazdow = [ "M3 St.", "M22", "sd.KFz.222", "M3 GMC", "M15 CGMC", "sd.KFz.251-9", "Pz.IIIF", "Pz.IIIC", "M3 Lee", "LVT", "M4A3", "Stug IIIb", "Beutepanzer IV", "A7V" ] pojazdy = [ # ==================== USA (Po kolei numerycznie) ==================== {"naz": "M3 St.", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 120}, {"naz": "M22", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 140}, {"naz": "M3 GMC", "x": 0, "y": 0, "wys": 2, "sze": 4, "ruch": 110}, {"naz": "M15 CGMC", "x": 0, "y": 0, "wys": 2, "sze": 4, "ruch": 100}, {"naz": "M3 Lee", "x": 0, "y": 0, "wys": 3, "sze": 3, "ruch": 80}, {"naz": "LVT", "x": 0, "y": 0, "wys": 3, "sze": 4, "ruch": 70}, {"naz": "M4A3", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 90}, {"naz": "sd.KFz.222", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 130}, {"naz": "sd.KFz.251-9", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 100}, {"naz": "Pz.IIIF", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 95}, {"naz": "Pz.IIIC", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 105}, {"naz": "Stug IIIb", "x": 0, "y": 0, "wys": 2, "sze": 4, "ruch": 70}, {"naz": "Beutepanzer IV", "x": 0, "y": 0, "wys": 3, "sze": 4, "ruch": 40}, {"naz": "A7V", "x": 0, "y": 0, "wys": 4, "sze": 6, "ruch": 30}, ] zaladowane_obrazki = {} obrazki_jednostek = {} zasieg_podglad = None # --- INTERFEJS I LOGIKA WYBORU --- def sprawdz_limit(strona, zmienna_kliknieta): lista_zmiennych = [para[0] for para in (zmienne_lewa if strona == "USA" else zmienne_prawa)] zaznaczone_count = sum(z.get() for z in lista_zmiennych) if zaznaczone_count > 4: zmienna_kliknieta.set(False) messagebox.showwarning("Limit", f"Możesz wybrać maksymalnie 4 elementy w {strona}") def pokaz_podglad(event, nazwa_opcji): dane = baza_podgladu.get(nazwa_opcji, {"lista": "Brak opisu", "foto": ""}) lbl_tekstowy.config(text=dane["lista"]) lbl_tekstowy.place(relx=0.5, rely=0.35, anchor="center") # lbl_graficzny.place(x=500, y=300) lbl_graficzny.config(bd=2, relief="solid") try: nazwa_pliku = f"{nazwa_opcji}.png" if nazwa_pliku not in zaladowane_obrazki: zaladowane_obrazki[nazwa_pliku] = PhotoImage(file=nazwa_pliku) img = zaladowane_obrazki[nazwa_pliku] lbl_graficzny.config(image=img) lbl_graficzny.image = img except Exception as e: print(e) lbl_graficzny.config(image="", text="[ Podgląd Obrazka ]", bg="lightgray") # root.update_idletasks() # print(lbl_graficzny.image,dane["foto"],lbl_graficzny.winfo_ismapped()) lbl_graficzny.place(relx=0.5, rely=0.60, anchor="center") def ukryj_podglad(event): lbl_tekstowy.place_forget() lbl_graficzny.place_forget() aktualny_plan = 0 kolejka_planowania = [] wybrana_jednostka = None aktualna_strona = "USA" def planowanie(event): global wybrana_jednostka, aktualna_strona, koniec_planowania, zasieg_podglad if koniec_planowania: klikniete = canvas.find_overlapping( event.x, event.y, event.x, event.y ) if wybrana_jednostka is None: for j in jednostki: if j["sprite"] in klikniete: if j["strona"] != aktualna_strona: return if j["wykonal_ruch"]: return wybrana_jednostka = j global zasieg_podglad if zasieg_podglad: canvas.delete(zasieg_podglad) r = j["ruch"] zasieg_podglad = canvas.create_oval( j["x"] - r, j["y"] - r, j["x"] + r, j["y"] + r, fill="chartreuse3", stipple="gray50", activestipple="gray12", outline="forestgreen", width=2 ) lbl_aktywny_pojazd.config( text=f"Wybierz cel dla {j['nazwa']}" ) return else: dx = event.x - wybrana_jednostka["x"] dy = event.y - wybrana_jednostka["y"] wybrana_jednostka["kat_docelowy"] = degrees( atan2(dy, dx) )+180 odleglosc = (dx * dx + dy * dy) ** 0.5 if odleglosc > wybrana_jednostka["ruch"]: skala = wybrana_jednostka["ruch"] / odleglosc event_x = int(wybrana_jednostka["x"] + dx * skala) event_y = int(wybrana_jednostka["y"] + dy * skala) else: event_x = event.x event_y = event.y wybrana_jednostka["cel_x"] = event_x wybrana_jednostka["cel_y"] = event_y wybrana_jednostka["wykonal_ruch"] = True canvas.delete("plan") for j in jednostki: if j["wykonal_ruch"]: #canvas.delete("linie") if j["linia"]["nazwa"] is None: j["linia"]["dash"]["kropka"] = 10 j["linia"]["dash"]["przerwa"] = 8 j["linia"]["nazwa"] = canvas.create_line( j["cel_x"], j["cel_y"], j["x"], j["y"], fill="gold", dash=(j["linia"]["dash"]["kropka"], j["linia"]["dash"]["przerwa"]), width=2, dashoffset=0, capstyle="round", tags="linie") wybrana_jednostka = None if zasieg_podglad: canvas.delete(zasieg_podglad) zasieg_podglad = None aktualna_strona = ( "GER" if aktualna_strona == "USA" else "USA" ) lbl_aktywny_pojazd.config( text=f"Wybierz jednostkę {aktualna_strona}" ) if all(j["wykonal_ruch"] for j in jednostki): canvas.delete("plan") koniec_planowania = False animuj(0) for j in jednostki: j["wykonal_ruch"] = False aktualna_strona = "USA" lbl_aktywny_pojazd.config( text="Wybierz jednostkę USA" ) kontener = Frame(root) kontener.pack(pady=20, expand=True, fill="both") lbl_tekstowy = Label(root, text="", font=("Arial", 11), bg="#f0f0f0", bd=2, relief="groove", padx=10, pady=10) lbl_graficzny = Label(root, text="") koniec_planowania = True kolumna_lewa = Frame(kontener) kolumna_lewa.pack(side="left", expand=True, padx=20) Label(kolumna_lewa, text="USA", font=("Arial", 12, "bold")).pack(pady=10) for txt_kwadrat in kwadraty_lewe: wiersz = Frame(kolumna_lewa) wiersz.pack(pady=4, anchor="w") stan = BooleanVar() zmienne_lewa.append((stan, txt_kwadrat)) chk = Checkbutton( wiersz, text=txt_kwadrat, variable=stan, indicatoron=False, width=18, selectcolor="lightblue", command=lambda s=stan: sprawdz_limit("USA", s) ) chk.pack(side="left") chk.bind("", lambda event, nazwa=txt_kwadrat: pokaz_podglad(event, nazwa)) chk.bind("", ukryj_podglad) kolumna_prawa = Frame(kontener) kolumna_prawa.pack(side="right", expand=True, padx=20) Label(kolumna_prawa, text="III Rzesza", font=("Arial", 12, "bold")).pack(pady=10) for txt_kwadrat in kwadraty_prawa: wiersz = Frame(kolumna_prawa) wiersz.pack(pady=4, anchor="w") stan = BooleanVar() zmienne_prawa.append((stan, txt_kwadrat)) chk = Checkbutton( wiersz, text=txt_kwadrat, variable=stan, indicatoron=False, width=18, selectcolor="lightgreen", command=lambda s=stan: sprawdz_limit("GER", s) ) chk.pack(side="left") chk.bind("", lambda event, nazwa=txt_kwadrat: pokaz_podglad(event, nazwa)) chk.bind("", ukryj_podglad) canvas = Canvas(root, bg="white", highlightthickness=0) usa = [] IIIRzesza = [] def zatwierdz(): global usa, IIIRzesza, pojazdy_do_ustawienia if tryb_gry.get() == "PvAI": messagebox.showinfo( "PvAI", "AI Wkrótce dostępne!" ) return usa = [nazwa for stan, nazwa in zmienne_lewa if stan.get()] IIIRzesza = [nazwa for stan, nazwa in zmienne_prawa if stan.get()] pojazdy_do_ustawienia = usa + IIIRzesza if not usa or not IIIRzesza: messagebox.showwarning("Brak wyboru", "Musisz wybrać przynajmniej jeden pojazd w USA i w III Rzeszy, aby rozpocząć!") return decyzja = messagebox.askokcancel("Potwierdzenie", "Czy chcesz wygenerować mapę z wybranymi jednostkami?") if decyzja: do_ukrycia = [kontener, btn_koniec, lbl_tekstowy, lbl_graficzny, tryb, pvp, pvai, jakosc, menu_jakosci, rozmiar, menu_rozmiaru] for widget in do_ukrycia: widget.pack_forget() lbl_tekstowy.place_forget() lbl_graficzny.place_forget() canvas.pack(fill="both", expand=True) lbl_aktywny_pojazd.pack(pady=5) lbl_aktywny_pojazd.config(text=f"Ustaw: {pojazdy_do_ustawienia[0]}") root.update() start() jakosc = Label(root, text="Jakość mapy", font=("Arial", 11, "bold")) rozmiar = Label(root, text="Rozmiar mapy", font=("Arial", 11, "bold")) jakosc_mapy = StringVar(value="Preferowana") rozmiar_mapy = StringVar(value="Średnia") opcje_jakosci = [ "Bardzo wysoka", "Wysoka", "Preferowana", "Niska", "Bardzo niska" ] opcje_rozmiaru = [ "Mała", "Średnia", "Duża", "Ogromna" ] menu_jakosci = OptionMenu(root, jakosc_mapy, *opcje_jakosci) menu_rozmiaru = OptionMenu(root, rozmiar_mapy, *opcje_rozmiaru) tryb_gry = StringVar(value="PvP") tryb = Label(root, text="Tryb gry", font=("Arial", 11, "bold")) pvp = Radiobutton( root, text="PvP", variable=tryb_gry, value="PvP" ) pvai = Radiobutton( root, text="PvAI", variable=tryb_gry, value="PvAI" ) jakosc.pack() menu_jakosci.pack() rozmiar.pack() menu_rozmiaru.pack() mnoznik_ruchu = 0 tryb.pack() pvp.pack() pvai.pack() btn_koniec = Button(root, text="Zatwierdź wybór", command=zatwierdz, bg="gold", font=("Arial", 10, "bold")) btn_koniec.pack(pady=20) aktualny_pojazd = None pojazdy_do_ustawienia = [] placed_units = [] ghost = None jednostki = [] kolej_tury = [] ODSTEP = 15 SKALA_JEDNOSTKI = 10 lbl_aktywny_pojazd = Label(root, text="Kliknij, aby rozpocząć ustawianie", font=("Arial", 12, "bold")) aktualny_index = 0 BONUS_RUCHU = 1 opcje_predkosci = [ "x1", "x2", "x3", "x4", "x5" ] predkosc_ruchu = StringVar(value="x1") predkosc_ruchu.trace_add("write", zmien_predkosc) menu_predkosci = OptionMenu( root, predkosc_ruchu, *opcje_predkosci ) Label(root, text="Zasięg ruchu").pack() menu_predkosci.pack() canvas.bind("", ustaw_pojazd) canvas.bind("", update_ghost) root.bind("", lambda event: root.destroy()) root.mainloop()