Advertisement
Guest User

ch'tit exercice matinal en python :-D

a guest
May 14th, 2022
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.45 KB | None | 0 0
  1. import math
  2. from dataclasses import dataclass, field
  3. from enum import Enum
  4. from tkinter import Tk, Canvas, YES, BOTH
  5. from tkinter.ttk import Label
  6. from typing import Any
  7.  
  8. from numpy import array
  9. from scipy.linalg import norm
  10.  
  11.  
  12. class EntityType(Enum):
  13.     SPIDER = 0
  14.     HERO = 1
  15.  
  16.  
  17. @dataclass
  18. class Entity:
  19.     x: int
  20.     y: int
  21.     radius: int
  22.     speed: int
  23.     type: EntityType
  24.     health: int
  25.     location: array = field(init=False)  # calculated value after instance creation
  26.     new_location: array = field(init=False)  # calculated value after instance creation
  27.     circle: Any = field(init=False)
  28.  
  29.     def __post_init__(self):
  30.         self.location = array([self.x, self.y], dtype=float)
  31.  
  32.     def dist(self, other):
  33.         return norm(self.location - other.location) if isinstance(other, Entity) else norm(self.location - other)
  34.  
  35.     def move(self, target):
  36.         if isinstance(target, Entity):
  37.             u: array = target.location - self.location
  38.         else:
  39.             u: array = target - self.location
  40.         v: array = u / norm(u) if norm(u) > 0 else 0
  41.         speed: float = min(self.speed, self.dist(target))
  42.         return self.location + speed * v
  43.  
  44.  
  45. @dataclass
  46. class Game:
  47.     root: Tk = Tk()
  48.     canvas: Canvas = None
  49.     dbg_label: Label = None
  50.     hp_label: Label = None
  51.     base: array = None
  52.     spider: Entity = None
  53.     hero: Entity = None
  54.     map_width: int = None
  55.     map_height: int = None
  56.     zoom: float = None
  57.  
  58.     def populate(self):
  59.         self.spider = Entity(health=30, type=EntityType.SPIDER, x=3000, y=3000, radius=400, speed=400)
  60.         self.hero = Entity(health=math.inf, type=EntityType.HERO, x=4000, y=4000, radius=800, speed=800)
  61.  
  62.     def init_tk(self, map_width: int, map_height: int, zoom: int):
  63.         self.canvas = Canvas(width=map_width * zoom, height=map_height * zoom, bg='white')
  64.         self.zoom = zoom
  65.         self.canvas.bind("<Button-1>", self.callback)
  66.         self.canvas.pack(expand=YES, fill=BOTH)
  67.         self.base = array([0, 0])
  68.         self.dbg_label = Label(self.root, text="Hello World!")
  69.         self.dbg_label.pack(pady=20)
  70.         self.hp_label = Label(self.root)
  71.         x, y = self.spider.location
  72.         self.hp_label.place(x=x, y=y)
  73.         self.hp_label['text'] = f"{self.spider.health}"
  74.         self.hp_label.pack(pady=20)
  75.  
  76.         self.spider.circle = self.draw_circle(entity=self.spider, color='red')
  77.         self.hero.circle = self.draw_circle(entity=self.hero, color='blue')
  78.  
  79.         self.root.mainloop()
  80.  
  81.     # All of this would do better as a subclass of Canvas with specialize methods
  82.  
  83.     def draw_circle(self, entity: Entity, color: str):
  84.         # changed this to return the ID
  85.         x, y = entity.location
  86.         oval = x - entity.radius, y - entity.radius, x + entity.radius, y + entity.radius
  87.         x0, y0, x1, y1 = map(lambda x: x * self.zoom, oval)
  88.         return self.canvas.create_oval(x0, y0, x1, y1, width=1, outline=color)
  89.  
  90.     def move_circle(self, entity):
  91.         new_location = entity.move(self.base) if entity.type == EntityType.SPIDER else entity.move(self.spider)
  92.         dx, dy = map(lambda x: x * self.zoom, new_location - entity.location)
  93.         self.canvas.move(entity.circle, dx, dy)
  94.         entity.location = new_location
  95.         if entity.type == EntityType.SPIDER:
  96.             x, y = map(lambda x: x * self.zoom, entity.location)
  97.             self.hp_label.place(x=x, y=y)
  98.             self.hp_label['text'] = f"{entity.health}"
  99.             if entity.dist(self.base) > 300:
  100.                 self.dbg_label['text'] = f'distance spider to base = {round(entity.dist(self.base), 2)}'
  101.             else:
  102.                 self.dbg_label['text'] = 'GAME OVER!'
  103.         else:
  104.             if entity.dist(self.spider) <= entity.radius:
  105.                 self.spider.health -= 2
  106.                 if self.spider.health < 0:
  107.                     self.hp_label['text'] = 'GAME OVER!'
  108.         if self.dbg_label['text'] == 'GAME OVER!':
  109.             self.dbg_label['text'] = f'GAME OVER! -> distance spider to base = {round(entity.dist(self.base), 2)}'
  110.             self.canvas.unbind("<Button-1>", self.callback)
  111.  
  112.     def callback(self, event):
  113.         self.move_circle(entity=self.hero)
  114.         self.move_circle(entity=self.spider)
  115.  
  116.  
  117. if __name__ == "__main__":
  118.     MAP_WIDTH, MAP_HEIGHT = 17630, 9000
  119.     ZOOM = 0.1
  120.  
  121.     game: Game = Game()
  122.     game.populate()
  123.     game.init_tk(map_width=MAP_WIDTH, map_height=MAP_HEIGHT, zoom=ZOOM)
  124.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement