From 0ad9cd47c6068586b7c737757e0bbc270fa3af05 Mon Sep 17 00:00:00 2001 From: Matteo Benedetto Date: Sat, 14 Dec 2024 23:00:22 +0100 Subject: [PATCH] Aggiungi supporto per SDL e sostituisci il sistema grafico basato su Tkinter --- .env | 1 + assets/AmaticSC-Regular.ttf | Bin 0 -> 40000 bytes engine/sdl2.py | 87 ++++++++++++++++++++++++++ engine/{graphics.py => tkinter.py} | 16 +++-- rats.py | 26 ++++---- sdl2-demo.py | 78 +++++++++++++++++++++++ units/__pycache__/rat.cpython-313.pyc | Bin 9329 -> 9493 bytes units/rat.py | 16 ++--- 8 files changed, 198 insertions(+), 26 deletions(-) create mode 100644 .env create mode 100644 assets/AmaticSC-Regular.ttf create mode 100644 engine/sdl2.py rename engine/{graphics.py => tkinter.py} (79%) create mode 100644 sdl2-demo.py diff --git a/.env b/.env new file mode 100644 index 0000000..e3b97ec --- /dev/null +++ b/.env @@ -0,0 +1 @@ +SDL_VIDEODRIVER=x11 \ No newline at end of file diff --git a/assets/AmaticSC-Regular.ttf b/assets/AmaticSC-Regular.ttf new file mode 100644 index 0000000000000000000000000000000000000000..90b86df1388e52656af29644857878864561dbac GIT binary patch literal 40000 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྿Uvp%7Fp(m?A0WfR$7v4&i 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", key_callback) def load_image(self, path, transparent_color=None): image = tk.PhotoImage(file=os.path.join(os.path.dirname(__file__), "..", "assets", path)) @@ -46,5 +48,9 @@ class GameWindow: def new_cycle(self, delay, callback): self.window.after(delay, callback) - def mainloop(self): - self.window.mainloop() \ No newline at end of file + def mainloop(self, **kwargs): + kwargs["update"]() + self.window.mainloop() + + def get_image_size(self, image): + return image.width(), image.height() \ No newline at end of file diff --git a/rats.py b/rats.py index 9b4077f..da9969d 100644 --- a/rats.py +++ b/rats.py @@ -1,21 +1,19 @@ -import json -import tkinter as tk import random from units import rat import uuid import subprocess -from engine import maze, graphics +from engine import maze, sdl2 as engine class MiceMaze: def __init__(self, maze_file): self.map = maze.Map(maze_file) self.audio = True self.cell_size = 60 - self.engine = graphics.GameWindow(self.map.width, self.map.height, self.cell_size) + self.engine = engine.GameWindow(self.map.width, self.map.height, self.cell_size, "Mice!", key_callback=self.key_pressed) self.graphics_load() - self.engine.bind("", self.key_pressed) self.units = {} - self.new_rat() + for _ in range(5): + self.new_rat() def new_rat(self, position=None): if position is None: @@ -34,11 +32,11 @@ class MiceMaze: return random.choice(self._valid_positions) def draw_maze(self): - for y in range(self.map.height): - for x in range(self.map.width): - variant = random.randint(0, 3) - tile = self.grasses[variant] if self.map.matrix[y][x] else self.tunnel - self.engine.draw_image(x*self.cell_size, y*self.cell_size, tile, tag="maze", anchor="nw") + for y, row in enumerate(self.map.matrix): + for x, cell in enumerate(row): + variant = x*y % 4 + tile = self.grasses[variant] if cell else self.tunnel + self.engine.draw_image(x * self.cell_size, y * self.cell_size, tile, tag="maze") def update_maze(self): self.engine.delete_tag("unit") @@ -46,13 +44,13 @@ class MiceMaze: unit.move() unit.collisions() unit.draw() - self.engine.update_status(f"Units: {len(self.units)}") + self.engine.update_status(f"Mice: {len(self.units)}") self.engine.new_cycle(50, self.update_maze) + def run(self): self.draw_maze() - self.update_maze() - self.engine.mainloop() + self.engine.mainloop(update=self.update_maze, bg_update=self.draw_maze) def key_pressed(self, event): if event.keysym == "q": diff --git a/sdl2-demo.py b/sdl2-demo.py new file mode 100644 index 0000000..adce670 --- /dev/null +++ b/sdl2-demo.py @@ -0,0 +1,78 @@ +import sys +import sdl2 +from PIL import Image +import sdl2.sdlttf +import sdl2.ext + + +class Main: + def __init__(self): + sdl2.ext.init() + self.size = (640, 480) + self.window = sdl2.ext.Window("PySDL2 Demo", size=self.size) + self.window.show() + self.renderer = sdl2.ext.Renderer(self.window) + self.factory = sdl2.ext.SpriteFactory(renderer=self.renderer) + self.fonts = self.generate_fonts("assets/AmaticSC-Regular.ttf") + self.running = True + self.assets = self.graphics_load() + + def generate_fonts(self,font_file): + fonts = {} + for i in range(10, 70, 1): + fonts.update({i: sdl2.ext.FontManager(font_path=font_file, size=i)}) + return fonts + + def draw_text(self, text, font, position, color): + sprite = self.factory.from_text(text, fontmanager=font, color=color) + if position == "center": + sprite.position = (self.size[0] // 2 - sprite.size[0] // 2, self.size[1] // 2 - sprite.size[1] // 2) + else: + sprite.position = position + self.renderer.copy(sprite, dstrect=sprite.position) + + def draw_image(self, sprite, position): + + sprite.position = position + self.renderer.copy(sprite, dstrect=sprite.position) + + def load_image(self, path, transparent_color=None): + image = Image.open(path) + image = image.resize((image.width * 3, image.height * 3), Image.NEAREST) + if transparent_color: + image = image.convert("RGBA") + datas = image.getdata() + new_data = [] + for item in datas: + if item[:3] == transparent_color: + new_data.append((255, 255, 255, 0)) + else: + new_data.append(item) + image.putdata(new_data) + + return self.factory.from_surface(sdl2.ext.pillow_to_surface(image)) + + def run(self): + while self.running: + events = sdl2.ext.get_events() + for event in events: + if event.type == sdl2.SDL_QUIT: + self.running = False + break + self.renderer.clear() + self.draw_text("MatGames Corp.", self.fonts[50], (0, 0), sdl2.ext.Color(255, 255, 255)) + self.draw_image(self.assets["MALE"]["DOWN"], (100, 100)) + self.renderer.present() + sdl2.ext.quit() + return 0 + + def graphics_load(self): + rat_assets = {} + for sex in ["MALE", "FEMALE", "BABY"]: + rat_assets[sex] = {} + for direction in ["UP", "DOWN", "LEFT", "RIGHT"]: + rat_assets[sex][direction] = self.load_image(f"assets/Rat/BMP_{sex}_{direction}.png", transparent_color=(128, 128, 128)) + return rat_assets + +if __name__ == "__main__": + sys.exit(Main().run()) \ No newline at end of file diff --git a/units/__pycache__/rat.cpython-313.pyc b/units/__pycache__/rat.cpython-313.pyc index 9f07f18718c7d250573ef372e0857164894cf73c..ba90b4b2c7d05411352efd9efd868bcfd815e149 100644 GIT binary patch delta 2233 zcma)7O>k3H6n^g|FMVm6rp-_DpN6)ngrO}0RgfQBT4+JqLefH@U`*TBG|(pXCM^Z| z5l65v15%HGGwRr`v>U-e2NupK8;6DCH2$^o#u;SBg|b1Q4lG=F&P$`fIF5Jm<(zv? zzI*O>?>+Bs>-jCl`$l6Shoj);-uTET#uP7bJd}DIaDi9MVQm*TSWICWaV{uAMhIv+ zgC=-aI8va9{fYQM1{|6}J`N`|FBN_-dFE`+aqXEx_*L^M?}7KVi+LY>rCrUt-x6DR z|CLtpHqY0&FJ(;gj21}q2!2L{igqY9Dk~B(lJyK+ zGyK5&;cSsp+MwaM^IR7P$BmWnZPBoPJI5u3E+JF|6FTdasPQvC7~n7=WJRVY#^MD( zhB3^r<6kULYcgnC__k8GRa{qkfaCgb1@vn3@o5I5o^l z(V7-=%pJrgAoz1ivNlR9AR)1m7@ROa@Al(VFNvKW5*oN??*0zAX`TX;t_()KRv~1f z{RTDl3%N;cWZ59)sv|6n;5x%Qy7;hW4bH^sP(LSJwUqHz_{LIGpzEkbiOqB>aLr;< zXPvOoY86GCFN5on1wJT~;Gortv9s11L|jj+4ND?S*gSkLrOqyb&t`u##j6dAA}(2j z?;)(O!7^&l>(UV>rF{JxLQeFb7?H6qO}H>@2p6pu{aj=$lEKw5hyEIQeSsG3mGqvB z@Uf*F4tOm>$V=N0Lauz(e9pq+Ffli+*Ar3R!>x%D6_}sU8y^eT+3Su4FrQWZ4Rmab z3SkulT7tC*ijX|O=wO3_qKhSa2U1MYWMc8(=*)s9M$c*C=8?6Pz>J_2vREb>OQ+>b zTG7eLcp@n)#c??kO$^22a#Wj69Fk$iz6d18qDp=40&U1sD59FB6y}oE-1UxtNskHs z{9rzK*;^(wKu9~ z$lE?=b4}J?j!m!2R<61hxUv0uP4>Bt8S6F>U88nC))Fkr>0v{gsXKDR8JE|bAm2ey zhJbG-2A{i{U8;c8!&oyxgrJQe4KDZ6onAE6=G34zCx(a0sbHi4wh8XxN$!DQ5MB3N zMF<{)*udX&m58hERoTVG^UJkj;6brj+$8+Y5i-9@0C#;MxZ~FGhhb~E6HK1=COW!l zF?SHe%czB^@0+Pb&3OO*f_0NcdsoccLK|D!8{3<9MVq@qjh&l2+S$_-T~1M5Ppl^)r`cX~9&0Dm#T31| zB(=QbQ0?2c+mDk$A$ReJoQ=?g#74=+hRU%qf`bH9v)T*UA+lZ}IE?V9z(;A4;4sYi z-0E)FQIu;pe+s2KuFAyJO}#;xbPPG(*U(D;n@FZj^3bC)orV(sGW;kt`e%7vjtP7f z^-H^ns)<8KhsvYAzW*fx(f)@BrzuQu z3JzAfkNNX1er2c^FnavC6EmTu6zAS|ZDxNWnUNVI71%n0^#msg&Jnyopk85BW?EsI z%Uwwy+KRMxDAhMID6ePd(IpwuJ2?)lRi%6Ys;kPE4)OdZVZ3UdQ;qo-H3q(Je8oJ6 RKl82)LBqw{^>D$AE<| z6LI{J=qpI%5B~7S5bJ|8 zrase6EeNV|fd$|TrICf;M`Z=`LrC4s!sm7MK4VSLS<+h-z^H~Lt7p;!{Ubcb8&Kzq z;8IBq`rIjruts3oH2Qq5U6$EO*l&HNIx2ip8LlVunUU-i;}j*w5F$JTSFKLg3OB7c zSs2dQeCkiKB%K6isfAx`c~*PA&t7263D--#FjQ{Swmp`lINRlcFUvzE6_V5~b@||K zjT45;%K})ARfOu55QUK>jeM(x}~HLixBW1ZJ9r7}7J=k2%}wTe>sX4vOgiwBr? zgw30&HWj{g+_l|ydEeji&X&{LPj%dZ?<;~>;GY%uTgk#OjgE|ROfOBz#TXsrhowsq zJQV);O9)0uS0W$7oP7{*u0#J_PG4zC!2?p=3?gx-HUH8Y$@>xMaz zO%9B3!<0{?@0n=J!Ksbsdx@kM2`UkcQl7}~N#t^RK4(}+7BRRF_Ih1a>UbuVA27@V zG%|U^tY_1itPaP$wQjB0IBid&^`ivWy$y>s6e9DVXeL8R@x-{HiEctEjRv`2A>i8x z`+T77zSYxT=;^-!4u9KjRFZ|Bp- z3!3+qR#(vK&ThJ>UP;Y#?wBF9=eFB_w)K-$Q>)IcDby{$*zi@;)uwB)!phDW*DLUm ze{WkDljG!wv2vr##R-TCF%aBGl8eAkK(%r&K@|dyOCKZxFZczWPFmhb&_h5Y!#P|I zG<5}06i>wZ;xy5F#tH1S5kvUnnDj_4RU2o$Hq}2Hw5sdbtlyz7pRM<(jdRZ_YQv+l z3bkE+AQAE~tO>r#4#2~(4=w~do~8SnQj1qW%~-6MCYp=f)J=2+NAQVi4tdxFYzo!l z!!{7om~|zYi4*UHiR#d@C8RG!FwFgl{*0dEyHR=SIiUB(uxv{V=`nhj4#PLqoreXL zalkel%f*aGQOYeO<4nZICgHQl5;Fx#GGLXi^N%B!n7QZ< z*J@jvc9Q=Fa%BkfFXB2B4M)2^OeBo*ktEj>dHrpuuRE0zOekC=7jZ;E|BDj}`yZSf zr)`3_pt?RFC>Lt9Obk7z@#f+J%TY4QixV14^Tg;tCYj@OcD|Zm4Z)iPCkVC@h`toG zQ;I36$ZiN_Lt8yOk{TP**YfvJB_47;5=_@uvPJN9eYk0mv37Z~eohj?+)k5~wM;IX Slkhj^cd*!G{C5d|BH~|ch|TW+ diff --git a/units/rat.py b/units/rat.py index dc18f8c..67c1e4a 100644 --- a/units/rat.py +++ b/units/rat.py @@ -1,7 +1,7 @@ from .unit import Unit import random import uuid -from engine.graphics import GameWindow +from engine.tkinter import GameWindow # Costanti AGE_THRESHOLD = 200 @@ -22,6 +22,7 @@ class Rat(Unit): self.speed = .10 self.partial_move = 0 self.position_before = position + self.fight = True def calculate_rat_direction(self): x, y = self.position @@ -87,9 +88,9 @@ class Rat(Unit): y2 > oy1 + OVERLAP_TOLERANCE): continue if self.id in self.game.units and unit.id in self.game.units: - if self.sex == unit.sex: + if self.sex == unit.sex and self.fight: self.die(unit) - else: + elif self.sex != unit.sex: if "fuck" in dir(self): self.fuck(unit) @@ -104,6 +105,7 @@ class Rat(Unit): direction = self.calculate_rat_direction() sex = self.sex if self.age > AGE_THRESHOLD else "BABY" image = self.game.rat_assets[sex][direction] + image_size = self.game.engine.get_image_size(image) self.rat_image = image partial_x, partial_y = 0, 0 @@ -112,11 +114,11 @@ class Rat(Unit): else: partial_x = self.partial_move * self.game.cell_size * (1 if direction == "RIGHT" else -1) - x_pos = self.position_before[0] * self.game.cell_size + (self.game.cell_size - image.width()) // 2 + partial_x - y_pos = self.position_before[1] * self.game.cell_size + (self.game.cell_size - image.height()) // 2 + partial_y + x_pos = self.position_before[0] * self.game.cell_size + (self.game.cell_size - image_size[0]) // 2 + partial_x + y_pos = self.position_before[1] * self.game.cell_size + (self.game.cell_size - image_size[1]) // 2 + partial_y - self.game.engine.draw_image(x_pos, y_pos, image=image, anchor="nw", tag="unit") - self.bbox = (x_pos, y_pos, x_pos + image.width(), y_pos + image.height()) + self.game.engine.draw_image(x_pos, y_pos, image, anchor="nw", tag="unit") + self.bbox = (x_pos, y_pos, x_pos + image_size[0], y_pos + image_size[1]) self.game.engine.draw_rectangle(self.bbox[0], self.bbox[1], self.bbox[2] - self.bbox[0], self.bbox[3] - self.bbox[1], "unit") class Male(Rat):