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)