From 8540af47c6ce3e5bbcf305ccba4dcaca1102bdf9 Mon Sep 17 00:00:00 2001 From: SteephenG Date: Tue, 22 Oct 2024 20:16:45 +0200 Subject: [PATCH 1/4] comit1 --- .vscode/settings.json | 2 +- Python/11 Dades/A Llistes.ipynb | 38 +++++++++++++++---- .../B Llistes avan\303\247ades.ipynb" | 2 +- 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index f13778cf..05ac892c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "workbench.colorTheme": "Default Light+", + "workbench.colorTheme": "Default Dark Modern", "notebook.lineNumbers": "on", "files.encoding": "utf8", "java.inlayHints.parameterNames.enabled": "none", diff --git a/Python/11 Dades/A Llistes.ipynb b/Python/11 Dades/A Llistes.ipynb index 91ffaf60..2247d633 100644 --- a/Python/11 Dades/A Llistes.ipynb +++ b/Python/11 Dades/A Llistes.ipynb @@ -525,9 +525,19 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "El producte a la posicó 1 és: ['Escombra', 5.49]\n", + "El nom del producte a la posicó 1 és: Escombra\n", + "El preu del producte a la posicó 1 és: 5.49\n" + ] + } + ], "source": [ "# Exemple d'accedir a les posicions d'una matriu:\n", "productes = [\n", @@ -549,9 +559,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "El producte 'Fregona' costa 10.99 €\n", + "El producte 'Escombra' costa 5.49 €\n", + "El producte 'Galleda' costa 8.95 €\n", + "El producte 'Drap' costa 2.99 €\n", + "El producte 'Fregall' costa 6.75 €\n", + "Suma total: 35.17\n", + "Mitjana: 7.03\n" + ] + } + ], "source": [ "# Exemple d'escriure una elements d'una matriu\n", "productes = [\n", @@ -602,7 +626,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -774,7 +798,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.12.3" }, "orig_nbformat": 4 }, diff --git "a/Python/11 Dades/B Llistes avan\303\247ades.ipynb" "b/Python/11 Dades/B Llistes avan\303\247ades.ipynb" index eeb8e844..f9acc424 100644 --- "a/Python/11 Dades/B Llistes avan\303\247ades.ipynb" +++ "b/Python/11 Dades/B Llistes avan\303\247ades.ipynb" @@ -378,7 +378,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.5" + "version": "3.12.3" }, "orig_nbformat": 4 }, From ba75535af494191eedb43c4045fe99724751c72c Mon Sep 17 00:00:00 2001 From: SteephenG Date: Thu, 24 Oct 2024 17:50:52 +0200 Subject: [PATCH 2/4] a --- Python/04 Funcions/Teoria.ipynb | 2 +- Python/06 Control de fluxe (if else)/Teoria.ipynb | 2 +- Python/08 Bucles (while for)/A while.ipynb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Python/04 Funcions/Teoria.ipynb b/Python/04 Funcions/Teoria.ipynb index bfb52184..4f85b171 100644 --- a/Python/04 Funcions/Teoria.ipynb +++ b/Python/04 Funcions/Teoria.ipynb @@ -757,7 +757,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.12.3" }, "orig_nbformat": 4 }, diff --git a/Python/06 Control de fluxe (if else)/Teoria.ipynb b/Python/06 Control de fluxe (if else)/Teoria.ipynb index 69877ca4..6a0389af 100644 --- a/Python/06 Control de fluxe (if else)/Teoria.ipynb +++ b/Python/06 Control de fluxe (if else)/Teoria.ipynb @@ -460,7 +460,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.12.3" }, "orig_nbformat": 4 }, diff --git a/Python/08 Bucles (while for)/A while.ipynb b/Python/08 Bucles (while for)/A while.ipynb index f88f9dce..db99dd0c 100644 --- a/Python/08 Bucles (while for)/A while.ipynb +++ b/Python/08 Bucles (while for)/A while.ipynb @@ -353,7 +353,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.6" + "version": "3.12.3" }, "orig_nbformat": 4 }, From daef323e0fb48be85face9d2408b342d8908e939 Mon Sep 17 00:00:00 2001 From: SteephenG Date: Mon, 28 Oct 2024 19:00:28 +0100 Subject: [PATCH 3/4] main --- Python/50 Dibuix/Teoria.ipynb | 2 +- Python/50 Dibuix/exemple003.py | 5 +- Python/50 Dibuix/exercici_matriu_sgd.py | 74 +++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 Python/50 Dibuix/exercici_matriu_sgd.py diff --git a/Python/50 Dibuix/Teoria.ipynb b/Python/50 Dibuix/Teoria.ipynb index 7d8a7dce..4dbd472d 100644 --- a/Python/50 Dibuix/Teoria.ipynb +++ b/Python/50 Dibuix/Teoria.ipynb @@ -1 +1 @@ -{"cells":[{"cell_type":"markdown","metadata":{},"source":["
\n","
\n","

© Albert Palacios Jiménez, 2023

\n","
\n","
\n"," \"Logo\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{"id":"qDQPPM3dtsAZ"},"source":["# Dibuix\n","\n","Molts llenguatges de programació tenen eines o llibreries, per obrir finestres, fer-hi dibuixos o mostrar-hi imatges.\n","\n","Per poder fer anar aquestes eines, calen coneixements bàsics de programació: variables, funcions, condicions, bucles, ...\n","\n","En Python hi ha moltes llibreries, però una de les més senzilles és **pyGame**.\n","\n","Instal·lació:\n","```bash\n","pip install pygame\n","pip install ipykernel -U --user --force-reinstall\n","```\n","\n","A macOS i linux amb *brew*:\n","```bash\n","python3 -m pip install pygame --break-system-package\n","python3 -m pip install ipykernel -U --user --force-reinstall --break-system-package\n","```"]},{"cell_type":"markdown","metadata":{},"source":["## Finestres i aplicacions\n","\n","Per poder dibuixar, primer necessitem una finestra d'aplicació.\n","\n","```python\n","screen = pygame.display.set_mode((640, 480))\n","pygame.display.set_caption('Window Title')\n","```\n","\n","Però un cop tenim la finestra, s'ha de definir què fer amb ella. És a dir, el **bucle de l'aplicació**\n","\n","```python\n","def main():\n"," is_looping = True\n","\n"," while is_looping:\n"," is_looping = app_events()\n"," app_run()\n"," app_draw()\n","\n"," clock.tick(30) # Limitar a 30 FPS\n","\n"," # Fora del bucle, tancar l'aplicació\n"," pygame.quit()\n"," sys.exit()\n","```"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 000"]},{"cell_type":"code","execution_count":4,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","import math\n","import os\n","os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = \"hide\"\n","import pygame\n","import sys\n","\n","# Definir colors\n","WHITE = (255, 255, 255)\n","BLACK = (0, 0, 0)\n","RED = (255, 0, 0)\n","GREEN = (0, 255, 0)\n","BLUE = (0, 0, 255)\n","PURPLE = (128, 0, 128)\n","ORANGE = (255, 165, 0) \n","\n","pygame.init()\n","clock = pygame.time.Clock()\n","\n","# Definir la finestra\n","screen = pygame.display.set_mode((640, 480))\n","pygame.display.set_caption('Window Title')\n","\n","# Bucle de l'aplicació\n","def main():\n"," is_looping = True\n","\n"," while is_looping:\n"," is_looping = app_events()\n"," app_run()\n"," app_draw()\n","\n"," clock.tick(60) # Limitar a 60 FPS\n","\n"," # Fora del bucle, tancar l'aplicació\n"," pygame.quit()\n"," sys.exit()\n","\n","# Gestionar events\n","def app_events():\n"," for event in pygame.event.get():\n"," if event.type == pygame.QUIT: # Botó tancar finestra\n"," return False\n"," return True\n","\n","# Fer càlculs\n","def app_run():\n"," pass\n","\n","# Dibuixar\n","def app_draw():\n"," \n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Escriure un text de prova\n"," font = pygame.font.SysFont(\"Arial\", 55)\n"," text = font.render('Hello World!', True, BLACK)\n"," screen.blit(text, (50, 50))\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","\n","if __name__ == \"__main__\":\n"," main()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple000.py')"]},{"cell_type":"code","execution_count":6,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple000.py')"]},{"cell_type":"markdown","metadata":{},"source":["# Dibuix\n","\n","Un cop tenim definida la finesta, i el bucle de l'aplciació, ja es poden dibuixar cosses al a funció **app_draw**\n","\n","```python\n","def app_draw():\n"," \n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Escriure un text de prova\n"," font = pygame.font.SysFont(\"Arial\", 55)\n"," text = font.render('Hello World!', True, BLACK)\n"," screen.blit(text, (50, 200))\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"]},{"cell_type":"markdown","metadata":{},"source":["## Ordre de dibuix (canvas)\n","\n","Normalment les llibreries de dibuix funcionen com un quadre *(canvas)*, són una superfície a la que vas dibuixant. I el què dibuixes últim, queda per damunt de tot el què ja has dibuixat.\n","\n","
\n","
\"\"\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{},"source":["## Eix de coordenades\n","\n","Indiquem a quina posició volem dibuixar a través de coordenades X,Y.\n","\n","A **pygame** les coordenades són **\"top/left\"**, el què vol dir que el 0,0 de la finestra és la posició de dalt a l'equerra.\n","\n","A l'exemple de la imatge, les coordenades són (x = 80, y = 50):\n","\n","
\n","
\"\"\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{},"source":["## Dibuix basic\n","\n","Pygame proporciona diverses funcions per dibuixar formes bàsiques:\n","```python\n","# Una línia entre dos punts.\n","pygame.draw.line(screen, color, start_pos, end_pos, width)\n","\n","# Un rectangle \n","pygame.draw.rect(screen, color, pygame.Rect(x, y, width, height))\n","\n","# Un cercle\n","pygame.draw.circle(screen, GREEN, (x, y), radius)\n","\n","# Una el·lipse dins d'un rectangle delimitador.\n","pygame.draw.ellipse(screen, color, pygame.Rect(x, y, width, height))\n","\n","# Un arc dins d'un rectangle delimitador.\n","pygame.draw.arc(screen, color, pygame.Rect(x, y, width, height), start_angle, end_angle, width)\n","\n","# Un polígon connectant una sèrie de punts.\n","pygame.draw.polygon(screen, color, [(x1, y1), (x2, y2), (x3, y3)], width)\n","\n","# Una sèrie de línies connectades entre diversos punts.\n","pygame.draw.lines(screen, color, closed, point_list, width)\n","```\n"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 001\n","\n","Dibuix de formes bàsiques, fixar-se en com s'escriuen les coordenades i en l'ordre de dibuix."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple001.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":19,"metadata":{},"outputs":[],"source":["# Fer anar el codi d'exemple\n","import utils; utils.run_code('./exemple001.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 000\n","\n","Modifica la funció **app_draw** de l'arxiu **\"./exercici000.py\"** per fer el següent dibuix, a partir de dos bucles **for**\n","\n","**Nota**: La mida de gruix de la línia és 5\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":29,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici000.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Colors\n","\n","**pyGame** permet fer dibuixos amb colors RGB (Red, Green Blue)\n","\n","Els colors són **tuples** de tres paràmetres entre 0 i 255, on:\n","\n","- El primer valor representa el vermell (Red)\n","- El segon valor representa el verd (Green)\n","- El tercer valor representa el blau (Blue)\n","\n","Així, els colors clàssics són:\n","\n"," WHITE = (255, 255, 255) \n"," BLACK = (0, 0, 0) \n"," RED = (255, 0, 0) \n"," GREEN = (0, 255, 0) \n"," BLUE = (0, 0, 255) \n"," YELLOW = (255, 255, 0) \n"," CYAN = (0, 255, 255) \n"," MAGENTA = (255, 0, 255) \n"," ORANGE = (255, 165, 0) \n"," PURPLE = (128, 0, 128) \n"," PINK = (255, 192, 203) \n"," GRAY = (128, 128, 128) \n"," BROWN = (165, 42, 42) \n"," NAVY = (0, 0, 128) \n"," TEAL = (0, 128, 128) \n"," LIME = (0, 255, 0) \n"," INDIGO = (75, 0, 130) \n"," VIOLET = (238, 130, 238)\n"]},{"cell_type":"markdown","metadata":{},"source":["## Relleus i Emplenats\n","\n","Hi ha dos modes de dibuix:\n","\n","- Emplenat (**fill**): És el color o patró que omple l’interior d'una forma. Per exemple, si dibuixes un cercle i l'emplenes de color blau, tot l'interior del cercle serà blau.\n","\n","- Relleu (**stroke**): És el contorn o línia exterior de la forma, que pot tenir un color i gruix diferents. Si dibuixes un cercle amb relleu vermell de 5 píxels, el contorn del cercle serà vermell amb una amplada de 5 píxels, però l'interior pot estar buit o emplenat d’un altre color.\n","\n","Aquestes propietats permeten que una forma tingui un aspecte amb un interior (emplenat) diferent del seu contorn (relleu)"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple002.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":58,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple002.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 001\n","\n","Al codi **\"exercici001.py\"**, modifica la funció **app_draw** per fer el següent dibuix:\n","\n","**Nota**: Per dibuixar l'arc taronja, fer servir la següent informació:\n","\n","- Coordenades: x = 400, y = 250\n","- Mida: ample = 200, alt = 100\n","- Angle inicial: math.radians(45)\n","- Angle final: math.radians(180)\n","- Gruix: 5\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":26,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici001.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Texts\n","\n","Per dibuixar un text cal seguir els següents passos:\n","\n","- Definir un estil de font\n","- Definir un text (si es pot, fora del bucle)\n","- Dibuixar el text (dins del bucle)\n","\n","**Nota:** Com que l'estil de font, i el text són variables, millor posar-les fora del bucle de l'aplicació."]},{"cell_type":"markdown","metadata":{},"source":["## Imatges\n","\n","Per dibuixar imatges cal\n","\n","- Carregar la imatge en una variable\n","- Dibuixar la imatge (dins del bucle)\n","\n","**Nota**: Quan es carrega la imatge se li pot canviar la mida, amb *pygame.transform.scale*"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple003.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":125,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple003.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events, lògica i dibuix\n","\n","Cal entendre que quan fem aplicacions gràfiques, el bucle de l'aplicació es divideix en parts:\n","\n","- **Obtenció d'events**: és a dir la informació que rep l'aplicació\n","\n","- **Càlculs lògics**: els que defineixen l'estat de l'aplicació, i modifiquen les variables\n","\n","- **Dibuix**: a partir dels càlculs anteriors dibuixar el què correspon\n","\n","**Important**: Separar la lògica dels càlculs de les instruccions de dibuix, permet que les instruccions que s'envien a la **tarjeta gràfica** estiguin més optimitzades, i l'aplicació funcioni més ràpid. \n","\n","Quan es posa codi per calcular la lògica dins de la funció de dibuix, les instruccions que s'envien a la tarja gràfica queden fragmentades, i no es poden optimitzar."]},{"cell_type":"markdown","metadata":{},"source":["## Animacions \n","\n","Les animacions permeten canviar el valor d'una variable en el temps, per tal de fer efectes de moviment o de canvi d'estat.\n","\n","Per tal que les animacions siguin coherents en tots els equips (sempre triguin el mateix), no canviarem els valors de les animacions en funció dels cops que hem dibuixat sinó **en funció del temps** que triquem a dibuixar."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (comprovar si l'usuari vol tancar l'aplicació per sortir del bucle)\n","import utils; utils.show_code('./exemple004.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (comprovar si l'usuari vol tancar l'aplicació per sortir del bucle)\n","import utils; utils.show_code('./exemple004.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":49,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (canviar el valor de la variable posició X)\n","import utils; utils.run_code('./exemple004.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 002\n","\n","La següent funció, dona una posició X,Y al perímetre d'un cercle a partir dels paràmetres:\n","\n","- Centre del cercle (x, y)\n","- Radi del cercle\n","- Angle (en graus)"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["import math\n","\n","def posicio_perimetre_cercle(center, radi, angle_graus):\n"," angle_radians = math.radians(angle_graus) # Convertir l'angle a radians\n"," x = center[0] + radi * math.cos(angle_radians) # Coordenada X\n"," y = center[1] + radi * math.sin(angle_radians) # Coordenada Y\n"," return x, y"]},{"cell_type":"markdown","metadata":{},"source":["Al codi **\"exercici002.py\"**, fes l'animació d'una linia que dóna voltes relatives a un cercle:\n","\n","**Nota**: Fes que la velocitat a la que canvia el valor de l'angle sigui de *50 * delta_time*\n","\n","
\n","\n","
\n","
"]},{"cell_type":"code","execution_count":57,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici002.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events de teclat\n","\n","Els events són **missatges que el programa rep quan passa alguna cosa**, normalment quan l'usuari interacciona amb l'aplicació a través del mouse o el teclat.\n","\n","Hi ha molts tipus d'events: de la finestra, del mouse, del teclat, ...\n","\n","Amb la informació dels events, podem modificar variables del nostre codi (i conseqüentment modificar el dibuix)"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 005\n","\n","Els **events de teclat** ens avisen quan s'apreta o s'allibera una tecla. Cal tenir en compte:\n","\n","- Múltiples tecles poden estar apretades al mateix temps\n","- Hi ha tecles de modificació com *control*, *alt*, *command* ... que canvien el comportament de les tecles\n","\n","No s'ha de confondre l'**event d'apretar o aixecar** una tecla:\n","\n","- pygame.KEYDOWN\n","- pygame.KEYUP\n","\n","Amb les **tecles** 'amunt' i 'avall'\n","\n","- pygame.K_UP\n","- pygame.K_DOWN"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":67,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple005.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 003\n","\n","Al codi **\"exercici003.py\"**, arregla l'exemple anterior perquè el quadre taronja no surti mai dels limits del quadre blau.\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":70,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici003.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events de ratolí\n","\n","Al igual que el teclat els events de ratolí ens avisen de:\n","\n","- La posició del mouse\n","- Si s'apreta algún botó del ratolí\n","- Si s'allibera algún botó del ratolí"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":108,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple006.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 004\n","\n","Al codi **\"exercici004.py\"**, arregla l'exemple anterior perquè l'ull dret estigui dins dels seus limits"]},{"cell_type":"code","execution_count":107,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici004.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Botons del ratolí apretats o alliberats\n","\n","Al igual que amb el teclat, es produeix un event quan s'apreta o allibera un botó del ratolí.\n","\n","Amb aquest event, podem saber les coordenades on s'ha fet 'click'."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":127,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple007.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Arrossegar objectes\n","\n","Per arrossegar s'han de seguir diversos passos:\n","\n","- Capturar els events de botons de mouse\n","- Comprovar si es fa click a sobre d'un objecte o a fora\n","- Apuntar la diferència entre la posició on es fa click i l'origen de dibuix de l'objecte\n","- Moure l'objecte amb el ratolí (segons la diferència anterior)\n","- Alliberar l'arrosegament quan s'allibera el botó del ratolí\n","\n","**Nota:** Per guardar la diferència entre la posició on s'ha fet click i l'origen del dibuix, tenim una variable **\"drag_offset\"**\n","\n"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":128,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple008.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 005\n","\n","Al codi **\"exercici005.py\"**, modifica l'exemple anterior per tal que quan els dos poligons estàn sobreposats i a més s'estàn arrossegant, es dibuixin tots dos de color taronja."]},{"cell_type":"code","execution_count":129,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici005.py')"]}],"metadata":{"colab":{"authorship_tag":"ABX9TyPVbRvc9ZXjdvEcZF7RaE6C","provenance":[],"toc_visible":true},"kernelspec":{"display_name":"Python 3","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.5"}},"nbformat":4,"nbformat_minor":0} +{"cells":[{"cell_type":"markdown","metadata":{},"source":["
\n","
\n","

© Albert Palacios Jiménez, 2023

\n","
\n","
\n"," \"Logo\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{"id":"qDQPPM3dtsAZ"},"source":["# Dibuix\n","\n","Molts llenguatges de programació tenen eines o llibreries, per obrir finestres, fer-hi dibuixos o mostrar-hi imatges.\n","\n","Per poder fer anar aquestes eines, calen coneixements bàsics de programació: variables, funcions, condicions, bucles, ...\n","\n","En Python hi ha moltes llibreries, però una de les més senzilles és **pyGame**.\n","\n","Instal·lació:\n","```bash\n","pip install pygame\n","pip install ipykernel -U --user --force-reinstall\n","```\n","\n","A macOS i linux amb *brew*:\n","```bash\n","python3 -m pip install pygame --break-system-package\n","python3 -m pip install ipykernel -U --user --force-reinstall --break-system-package\n","```"]},{"cell_type":"markdown","metadata":{},"source":["## Finestres i aplicacions\n","\n","Per poder dibuixar, primer necessitem una finestra d'aplicació.\n","\n","```python\n","screen = pygame.display.set_mode((640, 480))\n","pygame.display.set_caption('Window Title')\n","```\n","\n","Però un cop tenim la finestra, s'ha de definir què fer amb ella. És a dir, el **bucle de l'aplicació**\n","\n","```python\n","def main():\n"," is_looping = True\n","\n"," while is_looping:\n"," is_looping = app_events()\n"," app_run()\n"," app_draw()\n","\n"," clock.tick(30) # Limitar a 30 FPS\n","\n"," # Fora del bucle, tancar l'aplicació\n"," pygame.quit()\n"," sys.exit()\n","```"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 000"]},{"cell_type":"code","execution_count":3,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","import math\n","import os\n","os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = \"hide\"\n","import pygame\n","import sys\n","\n","# Definir colors\n","WHITE = (255, 255, 255)\n","BLACK = (0, 0, 0)\n","RED = (255, 0, 0)\n","GREEN = (0, 255, 0)\n","BLUE = (0, 0, 255)\n","PURPLE = (128, 0, 128)\n","ORANGE = (255, 165, 0) \n","\n","pygame.init()\n","clock = pygame.time.Clock()\n","\n","# Definir la finestra\n","screen = pygame.display.set_mode((640, 480))\n","pygame.display.set_caption('Window Title')\n","\n","# Bucle de l'aplicació\n","def main():\n"," is_looping = True\n","\n"," while is_looping:\n"," is_looping = app_events()\n"," app_run()\n"," app_draw()\n","\n"," clock.tick(60) # Limitar a 60 FPS\n","\n"," # Fora del bucle, tancar l'aplicació\n"," pygame.quit()\n"," sys.exit()\n","\n","# Gestionar events\n","def app_events():\n"," for event in pygame.event.get():\n"," if event.type == pygame.QUIT: # Botó tancar finestra\n"," return False\n"," return True\n","\n","# Fer càlculs\n","def app_run():\n"," pass\n","\n","# Dibuixar\n","def app_draw():\n"," \n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Escriure un text de prova\n"," font = pygame.font.SysFont(\"Arial\", 55)\n"," text = font.render('Hello World!', True, BLACK)\n"," screen.blit(text, (50, 50))\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","\n","if __name__ == \"__main__\":\n"," main()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple000.py')"]},{"cell_type":"code","execution_count":37,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple000.py')"]},{"cell_type":"markdown","metadata":{},"source":["# Dibuix\n","\n","Un cop tenim definida la finesta, i el bucle de l'aplciació, ja es poden dibuixar cosses al a funció **app_draw**\n","\n","```python\n","def app_draw():\n"," \n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Escriure un text de prova\n"," font = pygame.font.SysFont(\"Arial\", 55)\n"," text = font.render('Hello World!', True, BLACK)\n"," screen.blit(text, (50, 200))\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"]},{"cell_type":"markdown","metadata":{},"source":["## Ordre de dibuix (canvas)\n","\n","Normalment les llibreries de dibuix funcionen com un quadre *(canvas)*, són una superfície a la que vas dibuixant. I el què dibuixes últim, queda per damunt de tot el què ja has dibuixat.\n","\n","
\n","
\"\"\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{},"source":["## Eix de coordenades\n","\n","Indiquem a quina posició volem dibuixar a través de coordenades X,Y.\n","\n","A **pygame** les coordenades són **\"top/left\"**, el què vol dir que el 0,0 de la finestra és la posició de dalt a l'equerra.\n","\n","A l'exemple de la imatge, les coordenades són (x = 80, y = 50):\n","\n","
\n","
\"\"\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{},"source":["## Dibuix basic\n","\n","Pygame proporciona diverses funcions per dibuixar formes bàsiques:\n","```python\n","# Una línia entre dos punts.\n","pygame.draw.line(screen, color, start_pos, end_pos, width)\n","\n","# Un rectangle \n","pygame.draw.rect(screen, color, pygame.Rect(x, y, width, height))\n","\n","# Un cercle\n","pygame.draw.circle(screen, GREEN, (x, y), radius)\n","\n","# Una el·lipse dins d'un rectangle delimitador.\n","pygame.draw.ellipse(screen, color, pygame.Rect(x, y, width, height))\n","\n","# Un arc dins d'un rectangle delimitador.\n","pygame.draw.arc(screen, color, pygame.Rect(x, y, width, height), start_angle, end_angle, width)\n","\n","# Un polígon connectant una sèrie de punts.\n","pygame.draw.polygon(screen, color, [(x1, y1), (x2, y2), (x3, y3)], width)\n","\n","# Una sèrie de línies connectades entre diversos punts.\n","pygame.draw.lines(screen, color, closed, point_list, width)\n","```\n"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 001\n","\n","Dibuix de formes bàsiques, fixar-se en com s'escriuen les coordenades i en l'ordre de dibuix."]},{"cell_type":"code","execution_count":40,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_draw():\n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Dibuixar la graella de coordenades (llibreria utils)\n"," utils.draw_grid(pygame, screen, 50)\n","\n"," # Dibuixar un rectangle vermell a la posició (150, 200) de mida (75, 100)\n"," pygame.draw.rect(screen, RED, pygame.Rect(150, 200, 75, 100))\n","\n"," # Dibuixar un cercle verd a la posició (100, 150) de radi 10\n"," pygame.draw.circle(screen, GREEN, (100, 150), 50)\n","\n"," # Dibuixar una linia des de l'origen del rectangle fins al centre del cercle\n"," pygame.draw.line(screen, BLUE, (150, 200), (100, 150), 5)\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple001.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":41,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar el codi d'exemple\n","import utils; utils.run_code('./exemple001.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 000\n","\n","Modifica la funció **app_draw** de l'arxiu **\"./exercici000.py\"** per fer el següent dibuix, a partir de dos bucles **for**\n","\n","**Nota**: La mida de gruix de la línia és 5\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":8,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici000.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Colors\n","\n","**pyGame** permet fer dibuixos amb colors RGB (Red, Green Blue)\n","\n","Els colors són **tuples** de tres paràmetres entre 0 i 255, on:\n","\n","- El primer valor representa el vermell (Red)\n","- El segon valor representa el verd (Green)\n","- El tercer valor representa el blau (Blue)\n","\n","Així, els colors clàssics són:\n","\n"," WHITE = (255, 255, 255) \n"," BLACK = (0, 0, 0) \n"," RED = (255, 0, 0) \n"," GREEN = (0, 255, 0) \n"," BLUE = (0, 0, 255) \n"," YELLOW = (255, 255, 0) \n"," CYAN = (0, 255, 255) \n"," MAGENTA = (255, 0, 255) \n"," ORANGE = (255, 165, 0) \n"," PURPLE = (128, 0, 128) \n"," PINK = (255, 192, 203) \n"," GRAY = (128, 128, 128) \n"," BROWN = (165, 42, 42) \n"," NAVY = (0, 0, 128) \n"," TEAL = (0, 128, 128) \n"," LIME = (0, 255, 0) \n"," INDIGO = (75, 0, 130) \n"," VIOLET = (238, 130, 238)\n"]},{"cell_type":"markdown","metadata":{},"source":["## Relleus i Emplenats\n","\n","Hi ha dos modes de dibuix:\n","\n","- Emplenat (**fill**): És el color o patró que omple l’interior d'una forma. Per exemple, si dibuixes un cercle i l'emplenes de color blau, tot l'interior del cercle serà blau.\n","\n","- Relleu (**stroke**): És el contorn o línia exterior de la forma, que pot tenir un color i gruix diferents. Si dibuixes un cercle amb relleu vermell de 5 píxels, el contorn del cercle serà vermell amb una amplada de 5 píxels, però l'interior pot estar buit o emplenat d’un altre color.\n","\n","Aquestes propietats permeten que una forma tingui un aspecte amb un interior (emplenat) diferent del seu contorn (relleu)"]},{"cell_type":"code","execution_count":10,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_draw():\n"," \n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Dibuixar la graella\n"," utils.draw_grid(pygame, screen, 50)\n","\n"," # Primer quadrat: emplenat taronja amb relleu blau\n"," pygame.draw.rect(screen, ORANGE, (50, 50, 100, 100)) # Emplenat\n"," pygame.draw.rect(screen, BLUE, (50, 50, 100, 100), 5) # Relleu\n","\n"," # Segon quadrat: només emplenat taronja\n"," pygame.draw.rect(screen, ORANGE, (200, 50, 100, 100)) # Emplenat\n","\n"," # Tercer quadrat: només relleu blau\n"," pygame.draw.rect(screen, BLUE, (350, 50, 100, 100), 5) # Relleu\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple002.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":42,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple002.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 001\n","\n","Al codi **\"exercici001.py\"**, modifica la funció **app_draw** per fer el següent dibuix:\n","\n","**Nota**: Per dibuixar l'arc taronja, fer servir la següent informació:\n","\n","- Coordenades: x = 400, y = 250\n","- Mida: ample = 200, alt = 100\n","- Angle inicial: math.radians(45)\n","- Angle final: math.radians(180)\n","- Gruix: 5\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":12,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici001.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Texts\n","\n","Per dibuixar un text cal seguir els següents passos:\n","\n","- Definir un estil de font\n","- Definir un text (si es pot, fora del bucle)\n","- Dibuixar el text (dins del bucle)\n","\n","**Nota:** Com que l'estil de font, i el text són variables, millor posar-les fora del bucle de l'aplicació."]},{"cell_type":"markdown","metadata":{},"source":["## Imatges\n","\n","Per dibuixar imatges cal\n","\n","- Carregar la imatge en una variable\n","- Dibuixar la imatge (dins del bucle)\n","\n","**Nota**: Quan es carrega la imatge se li pot canviar la mida, amb *pygame.transform.scale*"]},{"cell_type":"code","execution_count":46,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_draw():\n"," \n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Dibuixar la graella\n"," utils.draw_grid(pygame, screen, 50)\n","\n"," # Text\n"," screen.blit(text, (50, 50))\n","\n"," # Imatge\n"," screen.blit(image, (400, 50))\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple003.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":48,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple003.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events, lògica i dibuix\n","\n","Cal entendre que quan fem aplicacions gràfiques, el bucle de l'aplicació es divideix en parts:\n","\n","- **Obtenció d'events**: és a dir la informació que rep l'aplicació\n","\n","- **Càlculs lògics**: els que defineixen l'estat de l'aplicació, i modifiquen les variables\n","\n","- **Dibuix**: a partir dels càlculs anteriors dibuixar el què correspon\n","\n","**Important**: Separar la lògica dels càlculs de les instruccions de dibuix, permet que les instruccions que s'envien a la **tarjeta gràfica** estiguin més optimitzades, i l'aplicació funcioni més ràpid. \n","\n","Quan es posa codi per calcular la lògica dins de la funció de dibuix, les instruccions que s'envien a la tarja gràfica queden fragmentades, i no es poden optimitzar."]},{"cell_type":"markdown","metadata":{},"source":["## Animacions \n","\n","Les animacions permeten canviar el valor d'una variable en el temps, per tal de fer efectes de moviment o de canvi d'estat.\n","\n","Per tal que les animacions siguin coherents en tots els equips (sempre triguin el mateix), no canviarem els valors de les animacions en funció dels cops que hem dibuixat sinó **en funció del temps** que triquem a dibuixar."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (comprovar si l'usuari vol tancar l'aplicació per sortir del bucle)\n","import utils; utils.show_code('./exemple004.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (comprovar si l'usuari vol tancar l'aplicació per sortir del bucle)\n","import utils; utils.show_code('./exemple004.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":49,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (canviar el valor de la variable posició X)\n","import utils; utils.run_code('./exemple004.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 002\n","\n","La següent funció, dona una posició X,Y al perímetre d'un cercle a partir dels paràmetres:\n","\n","- Centre del cercle (x, y)\n","- Radi del cercle\n","- Angle (en graus)"]},{"cell_type":"code","execution_count":16,"metadata":{},"outputs":[],"source":["import math\n","\n","def posicio_perimetre_cercle(center, radi, angle_graus):\n"," angle_radians = math.radians(angle_graus) # Convertir l'angle a radians\n"," x = center[0] + radi * math.cos(angle_radians) # Coordenada X\n"," y = center[1] + radi * math.sin(angle_radians) # Coordenada Y\n"," return x, y"]},{"cell_type":"markdown","metadata":{},"source":["Al codi **\"exercici002.py\"**, fes l'animació d'una linia que dóna voltes relatives a un cercle:\n","\n","**Nota**: Fes que la velocitat a la que canvia el valor de l'angle sigui de *50 * delta_time*\n","\n","
\n","\n","
\n","
"]},{"cell_type":"code","execution_count":15,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici002.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events de teclat\n","\n","Els events són **missatges que el programa rep quan passa alguna cosa**, normalment quan l'usuari interacciona amb l'aplicació a través del mouse o el teclat.\n","\n","Hi ha molts tipus d'events: de la finestra, del mouse, del teclat, ...\n","\n","Amb la informació dels events, podem modificar variables del nostre codi (i conseqüentment modificar el dibuix)"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 005\n","\n","Els **events de teclat** ens avisen quan s'apreta o s'allibera una tecla. Cal tenir en compte:\n","\n","- Múltiples tecles poden estar apretades al mateix temps\n","- Hi ha tecles de modificació com *control*, *alt*, *command* ... que canvien el comportament de les tecles\n","\n","No s'ha de confondre l'**event d'apretar o aixecar** una tecla:\n","\n","- pygame.KEYDOWN\n","- pygame.KEYUP\n","\n","Amb les **tecles** 'amunt' i 'avall'\n","\n","- pygame.K_UP\n","- pygame.K_DOWN"]},{"cell_type":"code","execution_count":17,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_events():\n"," global dir_x, dir_y\n","\n"," for event in pygame.event.get():\n"," if event.type == pygame.QUIT: # Botó tancar finestra\n"," return False\n"," elif event.type == pygame.KEYDOWN: # Tecla premuda\n"," if event.key == pygame.K_UP:\n"," dir_y = 'up'\n"," elif event.key == pygame.K_DOWN:\n"," dir_y = 'down'\n"," elif event.key == pygame.K_LEFT:\n"," dir_x = 'left'\n"," elif event.key == pygame.K_RIGHT:\n"," dir_x = 'right'\n"," elif event.type == pygame.KEYUP: # Tecla alliberada\n"," if event.key == pygame.K_UP:\n"," if dir_y == 'up':\n"," dir_y = 'none'\n"," elif event.key == pygame.K_DOWN:\n"," if dir_y == 'down':\n"," dir_y = 'none'\n"," elif event.key == pygame.K_LEFT:\n"," if dir_x == 'left':\n"," dir_x = 'none'\n"," elif event.key == pygame.K_RIGHT:\n"," if dir_x == 'right':\n"," dir_x = 'none'\n"," return True\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_events')"]},{"cell_type":"code","execution_count":18,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_run():\n"," global dir_x, dir_y, pos_x, pos_y\n","\n"," delta_time = clock.get_time() / 1000.0 # Convertir a segons\n"," \n"," speed = 50 # píxels per segon\n"," displacement = speed * delta_time\n","\n"," if (dir_x == \"right\"):\n"," pos_x = pos_x + displacement\n"," if (pos_x > 200):\n"," pos_x = 200\n"," elif (dir_x == \"left\"):\n"," pos_x = pos_x - displacement\n"," if (pos_x < 100):\n"," pos_x = 100\n","\n"," if (dir_y == \"down\"):\n"," pos_y = pos_y + displacement\n"," if (pos_y > 200):\n"," pos_y = 200\n"," elif (dir_y == \"up\"):\n"," pos_y = pos_y - displacement\n"," if (pos_y < 100):\n"," pos_y = 100\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_run')"]},{"cell_type":"code","execution_count":20,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_draw():\n"," global pos_x, pos_y\n","\n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Dibuixar la graella\n"," utils.draw_grid(pygame, screen, 50)\n","\n"," # Draw limits\n"," pygame.draw.rect(screen, BLUE, pygame.Rect(100, 100, 100, 100), 2)\n","\n"," # Draw moving object\n"," pygame.draw.rect(screen, ORANGE, pygame.Rect(pos_x, pos_y, 15, 15))\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":21,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple005.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 003\n","\n","Al codi **\"exercici003.py\"**, arregla l'exemple anterior perquè el quadre taronja no surti mai dels limits del quadre blau.\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":22,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici003.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events de ratolí\n","\n","Al igual que el teclat els events de ratolí ens avisen de:\n","\n","- La posició del mouse\n","- Si s'apreta algún botó del ratolí\n","- Si s'allibera algún botó del ratolí"]},{"cell_type":"code","execution_count":23,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_events():\n"," global mouse_pos\n"," mouse_inside = pygame.mouse.get_focused() # El ratolí està dins de la finestra?\n","\n"," for event in pygame.event.get():\n"," if event.type == pygame.QUIT: # Botó tancar finestra\n"," return False\n"," elif event.type == pygame.MOUSEMOTION:\n"," if mouse_inside:\n"," mouse_pos[\"x\"] = event.pos[0]\n"," mouse_pos[\"y\"] = event.pos[1]\n"," else:\n"," mouse_pos[\"x\"] = -1\n"," mouse_pos[\"y\"] = -1\n"," return True\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_events')"]},{"cell_type":"code","execution_count":24,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_run():\n"," global mouse_pos, eye_left, eye_right\n","\n"," eye_left[\"x\"] = mouse_pos[\"x\"] - 10\n"," if (eye_left[\"x\"] < 250):\n"," eye_left[\"x\"] = 250\n"," elif (eye_left[\"x\"] > 280):\n"," eye_left[\"x\"] = 280\n","\n"," eye_left[\"y\"] = mouse_pos[\"y\"] - 10\n"," if (eye_left[\"y\"] < 150):\n"," eye_left[\"y\"] = 150\n"," elif (eye_left[\"y\"] > 205):\n"," eye_left[\"y\"] = 205\n","\n"," eye_right[\"x\"] = mouse_pos[\"x\"] - 10\n"," eye_right[\"y\"] = mouse_pos[\"y\"] - 10\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_run')"]},{"cell_type":"code","execution_count":25,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_draw():\n"," global eye_left, eye_left\n","\n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Dibuixar la graella\n"," utils.draw_grid(pygame, screen, 50)\n","\n"," # Draw face\n"," pygame.draw.ellipse(screen, ORANGE, pygame.Rect(175, 50, 300, 400))\n","\n"," # Draw nose\n"," pygame.draw.arc(screen, GRAY, pygame.Rect(300, 275, 50, 25), math.radians(0), math.radians(180), 5)\n","\n"," # Draw smile\n"," pygame.draw.arc(screen, RED, pygame.Rect(250, 300, 150, 100), math.radians(180), math.radians(0), 5)\n","\n"," # Draw eyes back\n"," pygame.draw.rect(screen, WHITE, pygame.Rect(250, 150, 50, 75))\n"," pygame.draw.rect(screen, WHITE, pygame.Rect(350, 150, 50, 75))\n","\n"," # Draw eyes\n"," pygame.draw.rect(screen, BLACK, pygame.Rect(eye_left[\"x\"], eye_left[\"y\"], 20, 20))\n"," pygame.draw.rect(screen, BLACK, pygame.Rect(eye_right[\"x\"], eye_right[\"y\"], 20, 20))\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":26,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple006.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 004\n","\n","Al codi **\"exercici004.py\"**, arregla l'exemple anterior perquè l'ull dret estigui dins dels seus limits"]},{"cell_type":"code","execution_count":27,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici004.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Botons del ratolí apretats o alliberats\n","\n","Al igual que amb el teclat, es produeix un event quan s'apreta o allibera un botó del ratolí.\n","\n","Amb aquest event, podem saber les coordenades on s'ha fet 'click'."]},{"cell_type":"code","execution_count":28,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_events():\n"," global mouse_pos, mouse_down\n"," mouse_inside = pygame.mouse.get_focused() # El ratolí està dins de la finestra?\n","\n"," for event in pygame.event.get():\n"," if event.type == pygame.QUIT: # Botó tancar finestra\n"," return False\n"," elif event.type == pygame.MOUSEMOTION:\n"," if mouse_inside:\n"," mouse_pos[\"x\"] = event.pos[0]\n"," mouse_pos[\"y\"] = event.pos[1]\n"," else:\n"," mouse_pos[\"x\"] = -1\n"," mouse_pos[\"y\"] = -1\n"," elif event.type == pygame.MOUSEBUTTONDOWN:\n"," mouse_down = True\n"," elif event.type == pygame.MOUSEBUTTONUP:\n"," mouse_down = False\n"," return True\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_events')"]},{"cell_type":"code","execution_count":29,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_run():\n"," global mouse_pos, mouse_down, square_clicked, circle_clicked\n","\n"," if mouse_down:\n"," if (mouse_pos[\"x\"] > 100 and \n"," mouse_pos[\"y\"] > 150 and \n"," mouse_pos[\"x\"] < (100 + 200) and\n"," mouse_pos[\"y\"] < (150 + 50)):\n"," square_clicked = True\n","\n"," center = { \"x\": 400, \"y\": 175 }\n"," if is_point_in_circle(mouse_pos, center, 50):\n"," circle_clicked = True\n","\n"," else:\n"," square_clicked = False\n"," circle_clicked = False\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_run')"]},{"cell_type":"code","execution_count":30,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_draw():\n"," global square_clicked, circle_clicked\n","\n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Dibuixar la graella\n"," utils.draw_grid(pygame, screen, 50)\n","\n"," # Dibuixar text d'ajuda\n"," font = pygame.font.SysFont(\"Arial\", 24)\n"," text = font.render('Fes click als objectes', True, BLACK)\n"," screen.blit(text, (50, 50))\n","\n"," # Quadre i cercle\n"," color = BLACK\n"," if square_clicked:\n"," color = BLUE\n"," pygame.draw.rect(screen, color, pygame.Rect(100, 150, 200, 50))\n","\n"," color = BLACK\n"," if circle_clicked:\n"," color = GREEN\n"," pygame.draw.circle(screen, color, (400, 175), 50)\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":31,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple007.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Arrossegar objectes\n","\n","Per arrossegar s'han de seguir diversos passos:\n","\n","- Capturar els events de botons de mouse\n","- Comprovar si es fa click a sobre d'un objecte o a fora\n","- Apuntar la diferència entre la posició on es fa click i l'origen de dibuix de l'objecte\n","- Moure l'objecte amb el ratolí (segons la diferència anterior)\n","- Alliberar l'arrosegament quan s'allibera el botó del ratolí\n","\n","**Nota:** Per guardar la diferència entre la posició on s'ha fet click i l'origen del dibuix, tenim una variable **\"drag_offset\"**\n","\n"]},{"cell_type":"code","execution_count":32,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_events():\n"," global mouse_pos, mouse_down\n"," mouse_inside = pygame.mouse.get_focused() # El ratolí està dins de la finestra?\n","\n"," for event in pygame.event.get():\n"," if event.type == pygame.QUIT: # Botó tancar finestra\n"," return False\n"," elif event.type == pygame.MOUSEMOTION:\n"," if mouse_inside:\n"," mouse_pos[\"x\"], mouse_pos[\"y\"] = event.pos\n"," elif event.type == pygame.MOUSEBUTTONDOWN:\n"," mouse_down = True\n"," elif event.type == pygame.MOUSEBUTTONUP:\n"," mouse_down = False\n"," return True\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_events')"]},{"cell_type":"code","execution_count":33,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_run():\n"," global rectangle_pos, circle_center, square_dragging, circle_dragging, drag_offset\n","\n"," # Inici de l'arrossegament en fer clic dins del rectangle o cercle\n"," if mouse_down:\n"," if not square_dragging and not circle_dragging: # Només detecta al començar l'arrossegament\n"," if rectangle_pos.collidepoint(mouse_pos[\"x\"], mouse_pos[\"y\"]):\n"," square_dragging = True\n"," drag_offset[\"x\"] = mouse_pos[\"x\"] - rectangle_pos.x\n"," drag_offset[\"y\"] = mouse_pos[\"y\"] - rectangle_pos.y\n"," elif is_point_in_circle(mouse_pos, circle_center, circle_radius):\n"," circle_dragging = True\n"," drag_offset[\"x\"] = mouse_pos[\"x\"] - circle_center[\"x\"]\n"," drag_offset[\"y\"] = mouse_pos[\"y\"] - circle_center[\"y\"]\n"," else:\n"," # Alliberar l'arrossegament quan s'aixeca el ratolí\n"," square_dragging = False\n"," circle_dragging = False\n","\n"," # Actualitza la posició del rectangle si es fa \"drag\"\n"," if square_dragging:\n"," rectangle_pos.x = mouse_pos[\"x\"] - drag_offset[\"x\"]\n"," rectangle_pos.y = mouse_pos[\"y\"] - drag_offset[\"y\"]\n","\n"," # Actualitza la posició del cercle si es fa \"drag\"\n"," if circle_dragging:\n"," circle_center[\"x\"] = mouse_pos[\"x\"] - drag_offset[\"x\"]\n"," circle_center[\"y\"] = mouse_pos[\"y\"] - drag_offset[\"y\"]\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_run')"]},{"cell_type":"code","execution_count":34,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_draw():\n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Dibuixar la graella\n"," utils.draw_grid(pygame, screen, 50)\n","\n"," # Dibuixar el rectangle\n"," rectangle_color = BLUE if square_dragging else BLACK\n"," pygame.draw.rect(screen, rectangle_color, rectangle_pos)\n","\n"," # Dibuixar el cercle\n"," circle_color = GREEN if circle_dragging else BLACK\n"," pygame.draw.circle(screen, circle_color, (circle_center[\"x\"], circle_center[\"y\"]), circle_radius)\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":36,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple008.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 005\n","\n","Al codi **\"exercici005.py\"**, modifica l'exemple anterior per tal que quan els dos poligons estàn sobreposats i a més s'estàn arrossegant, es dibuixin tots dos de color taronja."]},{"cell_type":"code","execution_count":129,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici005.py')"]}],"metadata":{"colab":{"authorship_tag":"ABX9TyPVbRvc9ZXjdvEcZF7RaE6C","provenance":[],"toc_visible":true},"kernelspec":{"display_name":"Python 3","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.3"}},"nbformat":4,"nbformat_minor":0} diff --git a/Python/50 Dibuix/exemple003.py b/Python/50 Dibuix/exemple003.py index ef9ac490..197d3826 100644 --- a/Python/50 Dibuix/exemple003.py +++ b/Python/50 Dibuix/exemple003.py @@ -25,10 +25,7 @@ def main(): global font, text, image - is_looping = True - - # Definir el text - font = pygame.font.SysFont("Arial", 55) + is_looping = Truetext = font.render('Hello Arial!', True, BLACK) text = font.render('Hello Arial!', True, BLACK) # Carregar la imatge diff --git a/Python/50 Dibuix/exercici_matriu_sgd.py b/Python/50 Dibuix/exercici_matriu_sgd.py new file mode 100644 index 00000000..8d7cdede --- /dev/null +++ b/Python/50 Dibuix/exercici_matriu_sgd.py @@ -0,0 +1,74 @@ +import math +import os +os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide" +import pygame +import sys +import utils +import random + +# Definir colors +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +RED = (255, 0, 0) +GREEN = (0, 255, 0) +BLUE = (0, 0, 255) +PURPLE = (128, 0, 128) +ORANGE = (255, 165, 0) + +pygame.init() +clock = pygame.time.Clock() + +font = pygame.font.SysFont("Arial", 55) +#Matriz +matriz = [[str(random.randint(1,9)) for _ in range(10)] for _ in range(10)] + + +# Definir la finestra +screen = pygame.display.set_mode((640, 480)) +pygame.display.set_caption('Window Title') + +# Bucle de l'aplicació +def main(): + is_looping = True + + while is_looping: + is_looping = app_events() + app_run() + app_draw() + + clock.tick(60) # Limitar a 60 FPS + + # Fora del bucle, tancar l'aplicació + pygame.quit() + sys.exit() + +# Gestionar events +def app_events(): + for event in pygame.event.get(): + if event.type == pygame.QUIT: # Botó tancar finestra + return False + return True + +# Fer càlculs +def app_run(): + pass + +# Dibuixar +def app_draw(): + # Pintar el fons de blanc + screen.fill(WHITE) + + # Dibuixar la graella de coordenades (llibreria utils) + utils.draw_grid(pygame, screen, 50) + + # Actualitzar el dibuix a la finestra + pygame.display.update() + + text = font.render('Hello Arial!', True, BLACK) + + #Mostrar Texto + screen.blit(text, (50, 50)) + +if __name__ == "__main__": + main() + From 1e2adaeffcba3add338552ccff5b57d08342629e Mon Sep 17 00:00:00 2001 From: SteephenG Date: Thu, 7 Nov 2024 16:23:55 +0100 Subject: [PATCH 4/4] mainS --- Python/50 Dibuix/Teoria.ipynb | 2 +- .../Ejercicio0_pygame_Steephen_Garcia.py | 71 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) create mode 100644 Python/52 Deures D0/Ejercicio0_pygame_Steephen_Garcia.py diff --git a/Python/50 Dibuix/Teoria.ipynb b/Python/50 Dibuix/Teoria.ipynb index 90791ec9..061a603c 100644 --- a/Python/50 Dibuix/Teoria.ipynb +++ b/Python/50 Dibuix/Teoria.ipynb @@ -1 +1 @@ -{"cells":[{"cell_type":"markdown","metadata":{},"source":["
\n","
\n","

© Albert Palacios Jiménez, 2023

\n","
\n","
\n"," \"Logo\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{"id":"qDQPPM3dtsAZ"},"source":["# Dibuix\n","\n","Molts llenguatges de programació tenen eines o llibreries, per obrir finestres, fer-hi dibuixos o mostrar-hi imatges.\n","\n","Per poder fer anar aquestes eines, calen coneixements bàsics de programació: variables, funcions, condicions, bucles, ...\n","\n","En Python hi ha moltes llibreries, però una de les més senzilles és **pyGame**.\n","\n","Instal·lació:\n","```bash\n","pip install pygame\n","pip install ipykernel -U --user --force-reinstall\n","```\n","\n","A Linux:\n","```bash\n","sudo apt install install python3-pygame\n","```\n","\n","A macOS amb *brew* o també a Linux:\n","```bash\n","python3 -m pip install pygame --break-system-package\n","python3 -m pip install ipykernel -U --user --force-reinstall --break-system-package\n","```"]},{"cell_type":"markdown","metadata":{},"source":["## Finestres i aplicacions\n","\n","Per poder dibuixar, primer necessitem una finestra d'aplicació.\n","\n","```python\n","screen = pygame.display.set_mode((640, 480))\n","pygame.display.set_caption('Window Title')\n","```\n","\n","Però un cop tenim la finestra, s'ha de definir què fer amb ella. És a dir, el **bucle de l'aplicació**\n","\n","```python\n","def main():\n"," is_looping = True\n","\n"," while is_looping:\n"," is_looping = app_events()\n"," app_run()\n"," app_draw()\n","\n"," clock.tick(30) # Limitar a 30 FPS\n","\n"," # Fora del bucle, tancar l'aplicació\n"," pygame.quit()\n"," sys.exit()\n","```"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 000"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple000.py')"]},{"cell_type":"code","execution_count":7,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple000.py')"]},{"cell_type":"markdown","metadata":{},"source":["# Dibuix\n","\n","Un cop tenim definida la finesta, i el bucle de l'aplciació, ja es poden dibuixar cosses al a funció **app_draw**\n","\n","```python\n","def app_draw():\n"," \n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Escriure un text de prova\n"," font = pygame.font.SysFont(\"Arial\", 55)\n"," text = font.render('Hello World!', True, BLACK)\n"," screen.blit(text, (50, 200))\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"]},{"cell_type":"markdown","metadata":{},"source":["## Ordre de dibuix (canvas)\n","\n","Normalment les llibreries de dibuix funcionen com un quadre *(canvas)*, són una superfície a la que vas dibuixant. I el què dibuixes últim, queda per damunt de tot el què ja has dibuixat.\n","\n","
\n","
\"\"\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{},"source":["## Eix de coordenades\n","\n","Indiquem a quina posició volem dibuixar a través de coordenades X,Y.\n","\n","A **pygame** les coordenades són **\"top/left\"**, el què vol dir que el 0,0 de la finestra és la posició de dalt a l'equerra.\n","\n","A l'exemple de la imatge, les coordenades són (x = 80, y = 50):\n","\n","
\n","
\"\"\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{},"source":["## Dibuix basic\n","\n","Pygame proporciona diverses funcions per dibuixar formes bàsiques:\n","```python\n","# Una línia entre dos punts.\n","pygame.draw.line(screen, color, start_pos, end_pos, width)\n","\n","# Un rectangle \n","pygame.draw.rect(screen, color, (x, y, width, height))\n","\n","# Un cercle\n","pygame.draw.circle(screen, GREEN, (x, y), radius)\n","\n","# Una el·lipse dins d'un rectangle delimitador.\n","pygame.draw.ellipse(screen, color, (x, y, width, height))\n","\n","# Un arc dins d'un rectangle delimitador.\n","pygame.draw.arc(screen, color, (x, y, width, height), start_angle, end_angle, width)\n","\n","# Un polígon connectant una sèrie de punts.\n","pygame.draw.polygon(screen, color, [(x1, y1), (x2, y2), (x3, y3)], width)\n","\n","# Una sèrie de línies connectades entre diversos punts.\n","pygame.draw.lines(screen, color, closed, point_list, width)\n","```\n"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 001\n","\n","Dibuix de formes bàsiques, fixar-se en com s'escriuen les coordenades i en l'ordre de dibuix."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple001.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":19,"metadata":{},"outputs":[],"source":["# Fer anar el codi d'exemple\n","import utils; utils.run_code('./exemple001.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 000\n","\n","Modifica la funció **app_draw** de l'arxiu **\"./exercici000.py\"** per fer el següent dibuix, a partir de dos bucles **for**\n","\n","**Nota**: La mida de gruix de la línia és 5\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":29,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici000.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Colors\n","\n","**pyGame** permet fer dibuixos amb colors RGB (Red, Green Blue)\n","\n","Els colors són **tuples** de tres paràmetres entre 0 i 255, on:\n","\n","- El primer valor representa el vermell (Red)\n","- El segon valor representa el verd (Green)\n","- El tercer valor representa el blau (Blue)\n","\n","Així, els colors clàssics són:\n","\n"," WHITE = (255, 255, 255) \n"," BLACK = (0, 0, 0) \n"," RED = (255, 0, 0) \n"," GREEN = (0, 255, 0) \n"," BLUE = (0, 0, 255) \n"," YELLOW = (255, 255, 0) \n"," CYAN = (0, 255, 255) \n"," MAGENTA = (255, 0, 255) \n"," ORANGE = (255, 165, 0) \n"," PURPLE = (128, 0, 128) \n"," PINK = (255, 192, 203) \n"," GRAY = (128, 128, 128) \n"," BROWN = (165, 42, 42) \n"," NAVY = (0, 0, 128) \n"," TEAL = (0, 128, 128) \n"," LIME = (0, 255, 0) \n"," INDIGO = (75, 0, 130) \n"," VIOLET = (238, 130, 238)\n"]},{"cell_type":"markdown","metadata":{},"source":["## Relleus i Emplenats\n","\n","Hi ha dos modes de dibuix:\n","\n","- Emplenat (**fill**): És el color o patró que omple l’interior d'una forma. Per exemple, si dibuixes un cercle i l'emplenes de color blau, tot l'interior del cercle serà blau.\n","\n","- Relleu (**stroke**): És el contorn o línia exterior de la forma, que pot tenir un color i gruix diferents. Si dibuixes un cercle amb relleu vermell de 5 píxels, el contorn del cercle serà vermell amb una amplada de 5 píxels, però l'interior pot estar buit o emplenat d’un altre color.\n","\n","Aquestes propietats permeten que una forma tingui un aspecte amb un interior (emplenat) diferent del seu contorn (relleu)"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple002.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":58,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple002.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 001\n","\n","Al codi **\"exercici001.py\"**, modifica la funció **app_draw** per fer el següent dibuix:\n","\n","**Nota**: Per dibuixar l'arc taronja, fer servir la següent informació:\n","\n","- Coordenades: x = 400, y = 250\n","- Mida: ample = 200, alt = 100\n","- Angle inicial: math.radians(45)\n","- Angle final: math.radians(180)\n","- Gruix: 5\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":26,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici001.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Texts\n","\n","Per dibuixar un text cal seguir els següents passos:\n","\n","- Definir un estil de font\n","- Definir un text (si es pot, fora del bucle)\n","- Dibuixar el text (dins del bucle)\n","\n","**Nota:** Com que l'estil de font, i el text són variables, millor posar-les fora del bucle de l'aplicació."]},{"cell_type":"markdown","metadata":{},"source":["## Imatges\n","\n","Per dibuixar imatges cal\n","\n","- Carregar la imatge en una variable\n","- Dibuixar la imatge (dins del bucle)\n","\n","**Nota**: Quan es carrega la imatge se li pot canviar la mida, amb *pygame.transform.smoothscale*"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple003.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":58,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple003.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events, lògica i dibuix\n","\n","Cal entendre que quan fem aplicacions gràfiques, el bucle de l'aplicació es divideix en parts:\n","\n","- **Obtenció d'events**: és a dir la informació que rep l'aplicació\n","\n","- **Càlculs lògics**: els que defineixen l'estat de l'aplicació, i modifiquen les variables\n","\n","- **Dibuix**: a partir dels càlculs anteriors dibuixar el què correspon\n","\n","**Important**: Separar la lògica dels càlculs de les instruccions de dibuix, permet que les instruccions que s'envien a la **tarjeta gràfica** estiguin més optimitzades, i l'aplicació funcioni més ràpid. \n","\n","Quan es posa codi per calcular la lògica dins de la funció de dibuix, les instruccions que s'envien a la tarja gràfica queden fragmentades, i no es poden optimitzar."]},{"cell_type":"markdown","metadata":{},"source":["## Animacions \n","\n","Les animacions permeten canviar el valor d'una variable en el temps, per tal de fer efectes de moviment o de canvi d'estat.\n","\n","Per tal que les animacions siguin coherents en tots els equips (sempre triguin el mateix), no canviarem els valors de les animacions en funció dels cops que hem dibuixat sinó **en funció del temps** que triquem a dibuixar."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (comprovar si l'usuari vol tancar l'aplicació per sortir del bucle)\n","import utils; utils.show_code('./exemple004.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (comprovar si l'usuari vol tancar l'aplicació per sortir del bucle)\n","import utils; utils.show_code('./exemple004.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":49,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (canviar el valor de la variable posició X)\n","import utils; utils.run_code('./exemple004.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 002\n","\n","La següent funció, dona una posició X,Y al perímetre d'un cercle a partir dels paràmetres:\n","\n","- Centre del cercle {\"x\": x, \"y\": y}\n","- Radi del cercle\n","- Angle (en graus)"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["import utils\n","\n","utils.point_on_circle(center, radius, angle_degrees)"]},{"cell_type":"markdown","metadata":{},"source":["Al codi **\"exercici002.py\"**, fes l'animació d'una linia que dóna voltes relatives a un cercle:\n","\n","**Nota**: Fes que la velocitat sigui: *50 * delta_time*\n","\n","
\n","\n","
\n","
"]},{"cell_type":"code","execution_count":4,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici002.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events de teclat\n","\n","Els events són **missatges que el programa rep quan passa alguna cosa**, normalment quan l'usuari interacciona amb l'aplicació a través del mouse o el teclat.\n","\n","Hi ha molts tipus d'events: de la finestra, del mouse, del teclat, ...\n","\n","Amb la informació dels events, podem modificar variables del nostre codi (i conseqüentment modificar el dibuix)"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 005\n","\n","Els **events de teclat** ens avisen quan s'apreta o s'allibera una tecla. Cal tenir en compte:\n","\n","- Múltiples tecles poden estar apretades al mateix temps\n","- Hi ha tecles de modificació com *control*, *alt*, *command* ... que canvien el comportament de les tecles\n","\n","No s'ha de confondre l'**event d'apretar o aixecar** una tecla:\n","\n","- pygame.KEYDOWN\n","- pygame.KEYUP\n","\n","Amb les **tecles** 'amunt' i 'avall'\n","\n","- pygame.K_UP\n","- pygame.K_DOWN"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":67,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple005.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 003\n","\n","Al codi **\"exercici003.py\"**, arregla l'exemple anterior perquè el quadre taronja no surti mai dels limits del quadre blau.\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":70,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici003.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events de ratolí\n","\n","Al igual que el teclat els events de ratolí ens avisen de:\n","\n","- La posició del mouse\n","- Si s'apreta algún botó del ratolí\n","- Si s'allibera algún botó del ratolí"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":108,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple006.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 004\n","\n","Al codi **\"exercici004.py\"**, arregla l'exemple anterior perquè l'ull dret estigui dins dels seus limits"]},{"cell_type":"code","execution_count":107,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici004.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Botons del ratolí apretats o alliberats\n","\n","Al igual que amb el teclat, es produeix un event quan s'apreta o allibera un botó del ratolí.\n","\n","Amb aquest event, podem saber les coordenades on s'ha fet 'click'."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":132,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple007.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Arrossegar objectes\n","\n","Per arrossegar s'han de seguir diversos passos:\n","\n","- Capturar els events de botons de mouse\n","- Comprovar si es fa click a sobre d'un objecte o a fora\n","- Apuntar la diferència entre la posició on es fa click i l'origen de dibuix de l'objecte\n","- Moure l'objecte amb el ratolí (segons la diferència anterior)\n","- Alliberar l'arrosegament quan s'allibera el botó del ratolí\n","\n","**Nota:** Per guardar la diferència entre la posició on s'ha fet click i l'origen del dibuix, tenim una variable **\"drag_offset\"**\n","\n"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":133,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple008.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 005\n","\n","Al codi **\"exercici005.py\"**, modifica l'exemple anterior per tal que quan els dos poligons estàn sobreposats i a més s'estàn arrossegant, es dibuixin tots dos de color taronja."]},{"cell_type":"code","execution_count":130,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici005.py')"]}],"metadata":{"colab":{"authorship_tag":"ABX9TyPVbRvc9ZXjdvEcZF7RaE6C","provenance":[],"toc_visible":true},"kernelspec":{"display_name":"Python 3","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.5"}},"nbformat":4,"nbformat_minor":0} +{"cells":[{"cell_type":"markdown","metadata":{},"source":["
\n","
\n","

© Albert Palacios Jiménez, 2023

\n","
\n","
\n"," \"Logo\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{"id":"qDQPPM3dtsAZ"},"source":["# Dibuix\n","\n","Molts llenguatges de programació tenen eines o llibreries, per obrir finestres, fer-hi dibuixos o mostrar-hi imatges.\n","\n","Per poder fer anar aquestes eines, calen coneixements bàsics de programació: variables, funcions, condicions, bucles, ...\n","\n","En Python hi ha moltes llibreries, però una de les més senzilles és **pyGame**.\n","\n","Instal·lació:\n","```bash\n","pip install pygame\n","pip install ipykernel -U --user --force-reinstall\n","```\n","\n","A Linux:\n","```bash\n","sudo apt install install python3-pygame\n","```\n","\n","A macOS amb *brew* o també a Linux:\n","```bash\n","python3 -m pip install pygame --break-system-package\n","python3 -m pip install ipykernel -U --user --force-reinstall --break-system-package\n","```"]},{"cell_type":"markdown","metadata":{},"source":["## Finestres i aplicacions\n","\n","Per poder dibuixar, primer necessitem una finestra d'aplicació.\n","\n","```python\n","screen = pygame.display.set_mode((640, 480))\n","pygame.display.set_caption('Window Title')\n","```\n","\n","Però un cop tenim la finestra, s'ha de definir què fer amb ella. És a dir, el **bucle de l'aplicació**\n","\n","```python\n","def main():\n"," is_looping = True\n","\n"," while is_looping:\n"," is_looping = app_events()\n"," app_run()\n"," app_draw()\n","\n"," clock.tick(30) # Limitar a 30 FPS\n","\n"," # Fora del bucle, tancar l'aplicació\n"," pygame.quit()\n"," sys.exit()\n","```"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 000"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple000.py')"]},{"cell_type":"code","execution_count":7,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple000.py')"]},{"cell_type":"markdown","metadata":{},"source":["# Dibuix\n","\n","Un cop tenim definida la finesta, i el bucle de l'aplciació, ja es poden dibuixar cosses al a funció **app_draw**\n","\n","```python\n","def app_draw():\n"," \n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Escriure un text de prova\n"," font = pygame.font.SysFont(\"Arial\", 55)\n"," text = font.render('Hello World!', True, BLACK)\n"," screen.blit(text, (50, 200))\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"]},{"cell_type":"markdown","metadata":{},"source":["## Ordre de dibuix (canvas)\n","\n","Normalment les llibreries de dibuix funcionen com un quadre *(canvas)*, són una superfície a la que vas dibuixant. I el què dibuixes últim, queda per damunt de tot el què ja has dibuixat.\n","\n","
\n","
\"\"\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{},"source":["## Eix de coordenades\n","\n","Indiquem a quina posició volem dibuixar a través de coordenades X,Y.\n","\n","A **pygame** les coordenades són **\"top/left\"**, el què vol dir que el 0,0 de la finestra és la posició de dalt a l'equerra.\n","\n","A l'exemple de la imatge, les coordenades són (x = 80, y = 50):\n","\n","
\n","
\"\"\n","
\n","
\n","
"]},{"cell_type":"markdown","metadata":{},"source":["## Dibuix basic\n","\n","Pygame proporciona diverses funcions per dibuixar formes bàsiques:\n","```python\n","# Una línia entre dos punts.\n","pygame.draw.line(screen, color, start_pos, end_pos, width)\n","\n","# Un rectangle \n","pygame.draw.rect(screen, color, (x, y, width, height))\n","\n","# Un cercle\n","pygame.draw.circle(screen, GREEN, (x, y), radius)\n","\n","# Una el·lipse dins d'un rectangle delimitador.\n","pygame.draw.ellipse(screen, color, (x, y, width, height))\n","\n","# Un arc dins d'un rectangle delimitador.\n","pygame.draw.arc(screen, color, (x, y, width, height), start_angle, end_angle, width)\n","\n","# Un polígon connectant una sèrie de punts.\n","pygame.draw.polygon(screen, color, [(x1, y1), (x2, y2), (x3, y3)], width)\n","\n","# Una sèrie de línies connectades entre diversos punts.\n","pygame.draw.lines(screen, color, closed, point_list, width)\n","```\n"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 001\n","\n","Dibuix de formes bàsiques, fixar-se en com s'escriuen les coordenades i en l'ordre de dibuix."]},{"cell_type":"code","execution_count":1,"metadata":{},"outputs":[{"data":{"text/markdown":["```python\n","def app_draw():\n"," # Pintar el fons de blanc\n"," screen.fill(WHITE)\n","\n"," # Dibuixar la graella de coordenades (llibreria utils)\n"," utils.draw_grid(pygame, screen, 50)\n","\n"," # Dibuixar un rectangle vermell a la posició (150, 200) de mida (75, 100)\n"," pygame.draw.rect(screen, RED, (150, 200, 75, 100))\n","\n"," # Dibuixar un cercle verd a la posició (100, 150) de radi 10\n"," pygame.draw.circle(screen, GREEN, (100, 150), 50)\n","\n"," # Dibuixar una linia des de l'origen del rectangle fins al centre del cercle\n"," pygame.draw.line(screen, BLUE, (150, 200), (100, 150), 5)\n","\n"," # Actualitzar el dibuix a la finestra\n"," pygame.display.update()\n","```"],"text/plain":[""]},"metadata":{},"output_type":"display_data"}],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple001.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":3,"metadata":{},"outputs":[{"name":"stderr","output_type":"stream","text":[":488: RuntimeWarning: Your system is avx2 capable but pygame was not built with support for it. The performance of some of your blits could be adversely affected. Consider enabling compile time detection with environment variables like PYGAME_DETECT_AVX2=1 if you are compiling without cross compilation.\n"]}],"source":["# Fer anar el codi d'exemple\n","import utils; utils.run_code('./exemple001.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 000\n","\n","Modifica la funció **app_draw** de l'arxiu **\"./exercici000.py\"** per fer el següent dibuix, a partir de dos bucles **for**\n","\n","**Nota**: La mida de gruix de la línia és 5\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":29,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici000.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Colors\n","\n","**pyGame** permet fer dibuixos amb colors RGB (Red, Green Blue)\n","\n","Els colors són **tuples** de tres paràmetres entre 0 i 255, on:\n","\n","- El primer valor representa el vermell (Red)\n","- El segon valor representa el verd (Green)\n","- El tercer valor representa el blau (Blue)\n","\n","Així, els colors clàssics són:\n","\n"," WHITE = (255, 255, 255) \n"," BLACK = (0, 0, 0) \n"," RED = (255, 0, 0) \n"," GREEN = (0, 255, 0) \n"," BLUE = (0, 0, 255) \n"," YELLOW = (255, 255, 0) \n"," CYAN = (0, 255, 255) \n"," MAGENTA = (255, 0, 255) \n"," ORANGE = (255, 165, 0) \n"," PURPLE = (128, 0, 128) \n"," PINK = (255, 192, 203) \n"," GRAY = (128, 128, 128) \n"," BROWN = (165, 42, 42) \n"," NAVY = (0, 0, 128) \n"," TEAL = (0, 128, 128) \n"," LIME = (0, 255, 0) \n"," INDIGO = (75, 0, 130) \n"," VIOLET = (238, 130, 238)\n"]},{"cell_type":"markdown","metadata":{},"source":["## Relleus i Emplenats\n","\n","Hi ha dos modes de dibuix:\n","\n","- Emplenat (**fill**): És el color o patró que omple l’interior d'una forma. Per exemple, si dibuixes un cercle i l'emplenes de color blau, tot l'interior del cercle serà blau.\n","\n","- Relleu (**stroke**): És el contorn o línia exterior de la forma, que pot tenir un color i gruix diferents. Si dibuixes un cercle amb relleu vermell de 5 píxels, el contorn del cercle serà vermell amb una amplada de 5 píxels, però l'interior pot estar buit o emplenat d’un altre color.\n","\n","Aquestes propietats permeten que una forma tingui un aspecte amb un interior (emplenat) diferent del seu contorn (relleu)"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple002.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":58,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple002.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 001\n","\n","Al codi **\"exercici001.py\"**, modifica la funció **app_draw** per fer el següent dibuix:\n","\n","**Nota**: Per dibuixar l'arc taronja, fer servir la següent informació:\n","\n","- Coordenades: x = 400, y = 250\n","- Mida: ample = 200, alt = 100\n","- Angle inicial: math.radians(45)\n","- Angle final: math.radians(180)\n","- Gruix: 5\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":26,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici001.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Texts\n","\n","Per dibuixar un text cal seguir els següents passos:\n","\n","- Definir un estil de font\n","- Definir un text (si es pot, fora del bucle)\n","- Dibuixar el text (dins del bucle)\n","\n","**Nota:** Com que l'estil de font, i el text són variables, millor posar-les fora del bucle de l'aplicació."]},{"cell_type":"markdown","metadata":{},"source":["## Imatges\n","\n","Per dibuixar imatges cal\n","\n","- Carregar la imatge en una variable\n","- Dibuixar la imatge (dins del bucle)\n","\n","**Nota**: Quan es carrega la imatge se li pot canviar la mida, amb *pygame.transform.smoothscale*"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple003.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":58,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple003.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events, lògica i dibuix\n","\n","Cal entendre que quan fem aplicacions gràfiques, el bucle de l'aplicació es divideix en parts:\n","\n","- **Obtenció d'events**: és a dir la informació que rep l'aplicació\n","\n","- **Càlculs lògics**: els que defineixen l'estat de l'aplicació, i modifiquen les variables\n","\n","- **Dibuix**: a partir dels càlculs anteriors dibuixar el què correspon\n","\n","**Important**: Separar la lògica dels càlculs de les instruccions de dibuix, permet que les instruccions que s'envien a la **tarjeta gràfica** estiguin més optimitzades, i l'aplicació funcioni més ràpid. \n","\n","Quan es posa codi per calcular la lògica dins de la funció de dibuix, les instruccions que s'envien a la tarja gràfica queden fragmentades, i no es poden optimitzar."]},{"cell_type":"markdown","metadata":{},"source":["## Animacions \n","\n","Les animacions permeten canviar el valor d'una variable en el temps, per tal de fer efectes de moviment o de canvi d'estat.\n","\n","Per tal que les animacions siguin coherents en tots els equips (sempre triguin el mateix), no canviarem els valors de les animacions en funció dels cops que hem dibuixat sinó **en funció del temps** que triquem a dibuixar."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (comprovar si l'usuari vol tancar l'aplicació per sortir del bucle)\n","import utils; utils.show_code('./exemple004.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (comprovar si l'usuari vol tancar l'aplicació per sortir del bucle)\n","import utils; utils.show_code('./exemple004.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":49,"metadata":{},"outputs":[],"source":["# Codi de l'exemple (canviar el valor de la variable posició X)\n","import utils; utils.run_code('./exemple004.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 002\n","\n","La següent funció, dona una posició X,Y al perímetre d'un cercle a partir dels paràmetres:\n","\n","- Centre del cercle {\"x\": x, \"y\": y}\n","- Radi del cercle\n","- Angle (en graus)"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["import utils\n","\n","utils.point_on_circle(center, radius, angle_degrees)"]},{"cell_type":"markdown","metadata":{},"source":["Al codi **\"exercici002.py\"**, fes l'animació d'una linia que dóna voltes relatives a un cercle:\n","\n","**Nota**: Fes que la velocitat sigui: *50 * delta_time*\n","\n","
\n","\n","
\n","
"]},{"cell_type":"code","execution_count":4,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici002.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events de teclat\n","\n","Els events són **missatges que el programa rep quan passa alguna cosa**, normalment quan l'usuari interacciona amb l'aplicació a través del mouse o el teclat.\n","\n","Hi ha molts tipus d'events: de la finestra, del mouse, del teclat, ...\n","\n","Amb la informació dels events, podem modificar variables del nostre codi (i conseqüentment modificar el dibuix)"]},{"cell_type":"markdown","metadata":{},"source":["### Exemple 005\n","\n","Els **events de teclat** ens avisen quan s'apreta o s'allibera una tecla. Cal tenir en compte:\n","\n","- Múltiples tecles poden estar apretades al mateix temps\n","- Hi ha tecles de modificació com *control*, *alt*, *command* ... que canvien el comportament de les tecles\n","\n","No s'ha de confondre l'**event d'apretar o aixecar** una tecla:\n","\n","- pygame.KEYDOWN\n","- pygame.KEYUP\n","\n","Amb les **tecles** 'amunt' i 'avall'\n","\n","- pygame.K_UP\n","- pygame.K_DOWN"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple005.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":67,"metadata":{},"outputs":[],"source":["# Fer anar l'exemple\n","import utils; utils.run_code('./exemple005.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 003\n","\n","Al codi **\"exercici003.py\"**, arregla l'exemple anterior perquè el quadre taronja no surti mai dels limits del quadre blau.\n","\n","
\n","
\"\"\n","
\n","
"]},{"cell_type":"code","execution_count":70,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici003.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Events de ratolí\n","\n","Al igual que el teclat els events de ratolí ens avisen de:\n","\n","- La posició del mouse\n","- Si s'apreta algún botó del ratolí\n","- Si s'allibera algún botó del ratolí"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple006.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":108,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple006.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 004\n","\n","Al codi **\"exercici004.py\"**, arregla l'exemple anterior perquè l'ull dret estigui dins dels seus limits"]},{"cell_type":"code","execution_count":107,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici004.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Botons del ratolí apretats o alliberats\n","\n","Al igual que amb el teclat, es produeix un event quan s'apreta o allibera un botó del ratolí.\n","\n","Amb aquest event, podem saber les coordenades on s'ha fet 'click'."]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple007.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":132,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple007.py')"]},{"cell_type":"markdown","metadata":{},"source":["## Arrossegar objectes\n","\n","Per arrossegar s'han de seguir diversos passos:\n","\n","- Capturar els events de botons de mouse\n","- Comprovar si es fa click a sobre d'un objecte o a fora\n","- Apuntar la diferència entre la posició on es fa click i l'origen de dibuix de l'objecte\n","- Moure l'objecte amb el ratolí (segons la diferència anterior)\n","- Alliberar l'arrosegament quan s'allibera el botó del ratolí\n","\n","**Nota:** Per guardar la diferència entre la posició on s'ha fet click i l'origen del dibuix, tenim una variable **\"drag_offset\"**\n","\n"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_events')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_run')"]},{"cell_type":"code","execution_count":null,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.show_code('./exemple008.py', function_name='app_draw')"]},{"cell_type":"code","execution_count":133,"metadata":{},"outputs":[],"source":["# Codi de l'exemple\n","import utils; utils.run_code('./exemple008.py')"]},{"cell_type":"markdown","metadata":{},"source":["### Exercici 005\n","\n","Al codi **\"exercici005.py\"**, modifica l'exemple anterior per tal que quan els dos poligons estàn sobreposats i a més s'estàn arrossegant, es dibuixin tots dos de color taronja."]},{"cell_type":"code","execution_count":130,"metadata":{},"outputs":[],"source":["# Fer anar el codi de l'exercici\n","import utils; utils.run_code('./exercici005.py')"]}],"metadata":{"colab":{"authorship_tag":"ABX9TyPVbRvc9ZXjdvEcZF7RaE6C","provenance":[],"toc_visible":true},"kernelspec":{"display_name":"Python 3","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.12.3"}},"nbformat":4,"nbformat_minor":0} diff --git a/Python/52 Deures D0/Ejercicio0_pygame_Steephen_Garcia.py b/Python/52 Deures D0/Ejercicio0_pygame_Steephen_Garcia.py new file mode 100644 index 00000000..e6b6a59b --- /dev/null +++ b/Python/52 Deures D0/Ejercicio0_pygame_Steephen_Garcia.py @@ -0,0 +1,71 @@ +###Ejercicio 0### +import math +import os +os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide" +import pygame +import sys +import utils + +# Definir colors +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +GRAY = (200, 200, 200) +PINK = (255, 105, 180) +GREEN = (0, 255, 0) +BLUE = (0, 0, 255) +RED = (255, 0, 0) + +pygame.init() +clock = pygame.time.Clock() + +# Definir la finestra +screen = pygame.display.set_mode((640, 480)) +pygame.display.set_caption('Window Title') + +# Bucle de l'aplicació +def main(): + is_looping = True + + while is_looping: + is_looping = app_events() + app_run() + app_draw() + + clock.tick(60) # Limitar a 60 FPS + + # Fora del bucle, tancar l'aplicació + pygame.quit() + sys.exit() + +# Gestionar events +def app_events(): + for event in pygame.event.get(): + if event.type == pygame.QUIT: # Botó tancar finestra + return False + return True + +# Fer càlculs +def app_run(): + pass + +# Dibuixar +def app_draw(): + screen.fill(WHITE) + utils.draw_grid(pygame, screen, 50) + + #Cuadrado rosa + pygame.draw.rect(screen, PINK, (150, 200, 50, 50), 5) + + #Triangulo verde + pygame.draw.polygon(screen, GREEN, [(275, 200), (275 - 28, 248), (275 + 28, 248)], 5) + + #Cruz Azul + pygame.draw.line(screen, BLUE, (350, 200), (400, 250), 6) + pygame.draw.line(screen, BLUE, (350, 250), (400, 200), 6) + + #Redonda roja + pygame.draw.circle(screen, RED, (475, 225), 25, 5) + + pygame.display.update() +if __name__ == "__main__": + main() \ No newline at end of file