from random import randrange as rnd, choice from tkinter import * import math import time root = Tk() fr = Frame(root) root.geometry('800x600') canv = Canvas(root, bg = 'white') canv.pack(fill=BOTH,expand=1) colors = ['blue','green','red','brown'] class ball(): def __init__(self,x=40,y=450): self.x = x self.y = y self.r = 10 self.color = choice(colors) self.points = 3 self.id = canv.create_oval(self.x-self.r, self.y-self.r, self.x+self.r, self.y+self.r, fill=self.color) self.id_points = canv.create_text(self.x,self.y,text = self.points) self.live = 200 self.nature = 1 def paint(self): canv.coords(self.id,self.x-self.r,self.y-self.r,self.x+self.r,self.y+self.r) canv.coords(self.id_points,self.x,self.y) canv.itemconfig(self.id_points,text = self.points) def move(self): if self.y <= 500: self.vy += 0.07 self.y += self.vy self.x += self.vx self.vx *= 0.999 self.v = (self.vx**2+self.vy**2)**0.5 self.an = math.atan(self.vy/self.vx) self.paint() else: if self.vx**2+self.vy**2 > 10: self.vy = -self.vy*0.7 self.vx = self.vx*0.7 self.y = 499 if self.live < 0: self.kill() else: self.live -= 1 if self.x > 780: self.vx = - self.vx/2 self.x = 779 def hittest(self,ob): if abs(ob.x - self.x) <= (self.r + ob.r) and abs(ob.y - self.y) <= (self.r + ob.r): return True else: return False def ricochet(self,w): self.v = (self.vx**2 + self.vy**2)**0.5 self.an = math.atan(self.vy/self.vx) if self.x == w.x: self.x += 1 if w.x-(self.x+self.vx): an_rad = math.atan((w.y-(self.y+self.vy))/(w.x-(self.x+self.vx))) an_res = an_rad - (self.an - an_rad ) vx2 = 0.7*self.v*math.cos(an_res) vy2 = 0.7*self.v*math.sin(an_res) if self.an > 0 and self.vx < 0 and self.vy < 0 or self.an < 0 and self.vx < 0: vx2 = -vx2 vy2 = -vy2 self.vx = -vx2 self.vy = -vy2 self.move() self.move() self.points += 1 def kill(self): global balls canv.delete(self.id) canv.delete(self.id_points) try: balls.pop(balls.index(self)) except: pass def bum(self): global balls, colors for z in range(5): new_ball = ball() new_ball.r = 5 new_ball.vx = self.vx + rnd(-5,5) new_ball.vy = self.vy - rnd(-5,5) new_ball.x = self.x new_ball.y = self.y new_ball.nature = 0 new_ball.points = 1 new_ball.live = 20 while new_ball.color == 'red': new_ball.color = choice(colors) balls += [new_ball] self.kill() class gun(): def __init__(self): self.f2_power = 10 self.f2_on = 0 self.an = 1 self.points = 0 self.id = canv.create_line(20,450,50,420,width=7, smooth = 1) self.id_points = canv.create_text(30,30,text = self.points,font = '28') def fire2_start(self,event): self.f2_on = 1 def stop(self): self.f2_on = 0 def fire2_end(self,event): global balls, bullet bullet += 1 new_ball = ball() new_ball.r += 5 self.an = math.atan((event.y-new_ball.y)/(event.x-new_ball.x)) new_ball.vx = self.f2_power*math.cos(self.an)/7 new_ball.vy = self.f2_power*math.sin(self.an)/7 balls += [new_ball] self.f2_on = 0 self.f2_power = 35 def targetting (self,event=0): if event: self.an = math.atan((event.y-450)/(event.x-20)) if self.f2_on: canv.itemconfig(self.id,fill = 'orange') else: canv.itemconfig(self.id,fill = 'black') canv.coords(self.id, 20, 450, 20 + max(self.f2_power,20) * math.cos(self.an), 450+max(self.f2_power,20) * math.sin(self.an)) def power_up(self): if self.f2_on: if self.f2_power < 100: self.f2_power += 1 canv.itemconfig(self.id,fill = 'orange') else: canv.itemconfig(self.id,fill = 'black') def bum(self, event = 0): global balls balls[-1].bum() class target(): def __init__(self): self.points = 1 x = self.x = rnd(600,780) y = self.y = rnd(300,500) r = self.r = rnd(10,40) self.live = 5 + rnd(5) color = self.color = 'red' self.id = canv.create_oval(x-r,y-r,x+r,y+r, fill = self.color) self.id_live = canv.create_text(x,y,text=self.live) def hit(self): canv.itemconfig(self.id_live,text=self.live) if self.live < 1: self.kill() def kill(self): global targets targets.pop(targets.index(self)) canv.delete(self.id) canv.delete(self.id_live) balls = [] bullet = 0 targets = [] g1 = gun() walls = [] while 1: for z in range(rnd(3,7)): targets += [target()] for z in range(rnd(1,8)): walls += [target()] walls[-1].x = rnd(200,600) walls[-1].y = rnd(100,400) walls[-1].r = rnd(20,50) canv.delete(walls[-1].id_live) canv.itemconfig(walls[-1].id, fill = 'gray', width = 0) canv.coords(walls[-1].id, walls[-1].x-walls[-1].r, walls[-1].y-walls[-1].r, walls[-1].x+walls[-1].r, walls[-1].y+walls[-1].r) canv.bind('<Button-1>',g1.fire2_start) canv.bind('<Button-3>',g1.bum) canv.bind('<ButtonRelease-1>',g1.fire2_end) canv.bind('<Motion>',g1.targetting) result = canv.create_text(400,300, text = '', font = "28") z = 0.03 while targets or balls: for b in balls: b.move() if b.nature: for w in walls: if b.hittest(w): b.ricochet(w) for b_test in balls: if b != b_test and b.nature and b_test.nature and b.hittest(b_test): b.ricochet(b_test) b_test.bum() for t in targets: if b.hittest(t): b.kill() t.hit() g1.points += 1 t.live -= b.points canv.itemconfig(g1.id_points, text = g1.points) if not targets: canv.bind('<Button-1>','') canv.bind('<ButtonRelease-1>','') g1.stop() canv.itemconfig(result, text = 'Вы уничтожили все цели за ' + str(bullet) + ' выстрелов') canv.update() time.sleep(0.01) g1.targetting() g1.power_up() canv.update() time.sleep(0.01) canv.delete(result)