diff --git a/2os._tenks.py b/2os._tenks.py index e69de29..8b878f9 100644 --- a/2os._tenks.py +++ b/2os._tenks.py @@ -0,0 +1,911 @@ +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"] + + koniec_planowania = True + 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["rect"], dx, dy) + canvas.move(j["text"], 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.15 + + 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"] + + canvas.itemconfig( + j["rect"], + outline="black", + width=1 + ) + + 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)) + + nazwa_pliku = f"{nazwa} min.png" + + img_org = Image.open(nazwa_pliku) + + img_tk = ImageTk.PhotoImage(img_org) + + sprite = canvas.create_image( + 300, + 200, + 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, + + "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 + + 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": 2, "ruch": 120}, + {"naz": "M22", "x": 0, "y": 0, "wys": 1, "sze": 2, "ruch": 140}, + {"naz": "M3 GMC", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 110}, + {"naz": "M15 CGMC", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 100}, + {"naz": "M3 Lee", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 80}, + {"naz": "LVT", "x": 0, "y": 0, "wys": 3, "sze": 3, "ruch": 70}, + {"naz": "M4A3", "x": 0, "y": 0, "wys": 2, "sze": 3, "ruch": 90}, + + {"naz": "sd.KFz.222", "x": 0, "y": 0, "wys": 1, "sze": 2, "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": 2, "ruch": 95}, + {"naz": "Pz.IIIC", "x": 0, "y": 0, "wys": 2, "sze": 2, "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["rect"] in klikniete or j["text"] in klikniete: + + if j["strona"] != aktualna_strona: + return + + if j["wykonal_ruch"]: + return + + wybrana_jednostka = j + + canvas.itemconfig( + j["rect"], + outline="yellow", + width=3 + ) + 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="green", + 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) + ) + 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"]: + if j["linia"]["nazwa"] is None: + j["linia"]["dash"]["kropka"] = rand(2, 10) + j["linia"]["dash"]["przerwa"] = rand(3, 6) + j["linia"]["nazwa"] = canvas.create_line( + j["cel_x"], + j["cel_y"], + j["x"], + j["y"], + fill="yellow", + dash=(j["linia"]["dash"]["kropka"], j["linia"]["dash"]["przerwa"]), + dashoffset=0, + capstyle="round", + tags="plan") + + canvas.itemconfig( + wybrana_jednostka["rect"], + outline="black", + width=1 + ) + + 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() diff --git a/testy.py b/testy.py index eb7e629..11ebb31 100644 --- a/testy.py +++ b/testy.py @@ -1,14 +1,49 @@ -import tkinter as tk -from tkinter import font +from tkinter import * -root = tk.Tk() -# Tworzymy okno z listą, żeby wygodnie przewijać czcionki -listbox = tk.Listbox(root, width=50, height=20) -listbox.pack(padx=10, pady=10) +root = Tk() +root.geometry("300x200") -# Sortujemy i dodajemy wszystkie dostępne nazwy czcionek -for f in sorted(font.families()): - listbox.insert(tk.END, f) - print(f) -root.mainloop() \ No newline at end of file +def aktualizuj_kolor(wartosc_z_suwaka): + v = float(wartosc_z_suwaka) + + if v > 0.4: + b = "00" + elif v < 0.38: + b = "FF" + else: + procent = (v - 0.38) / 0.02 + odwrocona_wartosc = int((1 - procent) * 255) + odwrocona_wartosc = max(0, min(255, odwrocona_wartosc)) + b = f"{odwrocona_wartosc:02X}" + if v < 0.40 or v > 0.45: + r = "00" + else: + if v <= 0.425: + procent = (v - 0.40) / 0.025 + else: + procent = (0.45 - v) / 0.025 + + wartosc_r = int(procent * 255) + wartosc_r = max(0, min(255, wartosc_r)) + + r = f"{wartosc_r:02X}" + g = "00" + if abs(v - 0.4) < 0.005: + b = "FF" + r = "FF" + g = "FF" + + kolor = f"#{r}{g}{b}" + canvas.itemconfig(c, fill=kolor) + + +canvas = Canvas(root, bg="white", highlightthickness=0, width=150, height=150) +canvas.pack(side=LEFT, padx=20) + +c = canvas.create_rectangle(20, 20, 120, 120, fill="#FF00FF") + +val = Scale(root, from_=0.0, to=1.0, resolution=0.01, command=aktualizuj_kolor) +val.pack(side=RIGHT, padx=20) + +root.mainloop()