Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import math
- from dataclasses import dataclass, field
- from enum import Enum
- from tkinter import Tk, Canvas, YES, BOTH
- from tkinter.ttk import Label
- from typing import Any
- from numpy import array
- from scipy.linalg import norm
- class EntityType(Enum):
- SPIDER = 0
- HERO = 1
- BASE = 2
- @dataclass
- class Entity:
- x: int
- y: int
- radius: int
- speed: int
- type: EntityType
- health: int
- location: array = field(init=False) # calculated value after instance creation
- new_location: array = field(init=False) # calculated value after instance creation
- circle: Any = field(init=False)
- def __post_init__(self):
- self.location = array([self.x, self.y], dtype=float)
- def dist(self, other):
- return norm(self.location - other.location) if isinstance(other, Entity) else norm(self.location - other)
- def move(self, target):
- if isinstance(target, Entity):
- u: array = target.location - self.location
- else:
- u: array = target - self.location
- v: array = u / norm(u) if norm(u) > 0 else 0
- speed: float = min(self.speed, self.dist(target))
- return self.location + speed * v
- @dataclass
- class Game:
- root: Tk = Tk()
- canvas: Canvas = None
- dbg_label: Label = None
- hp_label: Label = None
- base: array = None
- spider: Entity = None
- hero: Entity = None
- map_width: int = None
- map_height: int = None
- reduce = None
- speed: int = field(init=False) # calculated value after instance creation
- # def __post_init__(self):
- # self.reduce = lambda x_list: map(lambda x: x * self.zoom, x_list)
- def populate(self, hp_spider: int):
- self.base = Entity(health=3, type=EntityType.BASE, x=0, y=0, radius=300, speed=0)
- self.spider = Entity(health=hp_spider, type=EntityType.SPIDER, x=3000, y=3000, radius=400, speed=400)
- self.hero = Entity(health=math.inf, type=EntityType.HERO, x=4000, y=4000, radius=800, speed=800)
- def init_tk(self, map_width: int, map_height: int, zoom: int):
- self.canvas = Canvas(width=map_width * zoom, height=map_height * zoom, bg='white')
- self.canvas.bind("<Button-1>", self.callback)
- self.canvas.pack(expand=YES, fill=BOTH)
- self.dbg_label = Label(self.root, text="Hello World!")
- self.dbg_label.pack(pady=20)
- self.hp_label = Label(self.root)
- x, y = self.spider.location
- self.hp_label.place(x=x, y=y)
- self.hp_label['text'] = f"{self.spider.health}"
- self.hp_label.pack(pady=20)
- self.reduce = lambda x_list: map(lambda x: x * zoom, x_list)
- self.base.circle = self.draw_circle(entity=self.base, color='green')
- self.spider.circle = self.draw_circle(entity=self.spider, color='red')
- self.hero.circle = self.draw_circle(entity=self.hero, color='blue')
- self.root.mainloop()
- # All of this would do better as a subclass of Canvas with specialize methods
- def draw_circle(self, entity: Entity, color: str):
- # changed this to return the ID
- x, y = entity.location
- oval = x - entity.radius, y - entity.radius, x + entity.radius, y + entity.radius
- x0, y0, x1, y1 = self.reduce(oval)
- return self.canvas.create_oval(x0, y0, x1, y1, width=1, outline=color)
- def move_circle(self, entity):
- new_location = entity.move(self.base) if entity.type == EntityType.SPIDER else entity.move(self.spider)
- dx, dy = self.reduce(new_location - entity.location)
- self.canvas.move(entity.circle, dx, dy)
- entity.location = new_location
- if entity.type == EntityType.SPIDER:
- x, y = self.reduce(entity.location)
- self.hp_label.place(x=x, y=y)
- self.hp_label['text'] = f"{entity.health}"
- if entity.dist(self.base) > 300:
- self.dbg_label['text'] = f'distance spider to base = {round(entity.dist(self.base), 2)}'
- else:
- self.dbg_label['text'] = f'SPIDER WINS! -> distance spider to base = {round(entity.dist(self.base), 2)}'
- self.canvas.unbind("<Button-1>", self.callback)
- else:
- if entity.dist(self.spider) <= entity.radius:
- self.spider.health -= 2
- if self.spider.health < 0:
- self.dbg_label['text'] = f'PLAYER WINS! -> distance spider to base = {round(entity.dist(self.base), 2)}'
- self.canvas.unbind("<Button-1>", self.callback)
- def callback(self, event):
- self.move_circle(entity=self.hero)
- self.move_circle(entity=self.spider)
- if __name__ == "__main__":
- MAP_WIDTH, MAP_HEIGHT = 17630, 9000
- mac_display_resolution = 1920, 1080
- ZOOM = 0.1
- game: Game = Game()
- print('Enter hit points for Spider: [1-30]')
- hp_spider = input()
- while not isinstance(hp_spider, int) and not 1 <= int(hp_spider) <= 30:
- print('Enter hit points for Spider: [1-30]')
- hp_spider = input()
- game.populate(hp_spider=int(hp_spider))
- game.init_tk(map_width=MAP_WIDTH, map_height=MAP_HEIGHT, zoom=ZOOM)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement