Игра Пушка на python. Очередная модификация

from random import randrange as rnd, choice
from tkinter import *
import math
import time

root = Tk()
fr = Frame(root)
root.geometry('800x600+600+100')
canv = Canvas(root, bg = 'white')
canv.pack(fill=BOTH,expand=1)

colors = ['blue','green','red','brown']

class ball():
    def __init__(self, balls, x=40,y=450):
        self.x = x
        self.y = y
        self.r = 8
        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
        self.balls = balls
        self.bum_time = 100
        self.bum_on = 0
        self.surprize = 0
        self.surprize_time = 0
        
    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
        if self.bum_on and self.nature:
            self.bum_time -= 1
            if self.bum_time <= 0:
                self.bum()
        if not self.nature:
            self.live -= 0.1
            if self.r > 0.1:
                self.r -= 0.1
            else:
                self.kill()
            self.vy += 0.2
            if self.live < 0:
                self.kill()
        if self.surprize:
            self.surprize_time += 1
            if self.surprize_time > 13:
                self.surprize_time  = 0
                self.fire()
                
        
            
    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.8*self.v*math.cos(an_res)
            vy2 = 0.8*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.points += 1
            
    def kill(self):
        canv.delete(self.id)
        #canv.delete(self.id_points)
        try:
            self.balls.pop(self.balls.index(self))
        except:
            pass
            
    def fire(self):
        n = 5
        for z in range(1,n+1):
            new_ball = ball(self.balls)
            new_ball.r = 5
            v = 5+rnd(5)
            an = z*2*math.pi/n+rnd(-2,3)/7
            new_ball.vx = v*math.cos(an)
            new_ball.vy = v*math.sin(an)
            new_ball.x = self.x + new_ball.vx*3
            new_ball.y = self.y + new_ball.vy*3
            new_ball.nature = 0
            new_ball.points = 1
            new_ball.live = rnd(10)+30
            new_ball.color = choice(colors)
            self.balls += [new_ball]
            
    def bum(self):
        self.fire()
        self.kill()
        

class gun():
    def __init__(self):
        self.f2_power = 10
        self.f2_on = 0
        self.on = 1
        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')
        
        self.balls = []
        self.bullet = 0
        self.targets = []
        self.walls = []
        
    def fire2_start(self,event):
        self.f2_on = 1

    def stop(self):
        self.f2_on = 0
        self.on = 0

    def fire2_end(self,event):
        self.bullet += 1
        new_ball = ball(self.balls)
        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
        if not rnd(12):
            new_ball.surprize = 1
        self.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):
        for b in self.balls[::-1]:
            if b.nature:
                b.bum()
                break

        
class target():
    def __init__(self, targets):
        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)
        self.change_color = 0
        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)
        self.targets = targets
        
    def hit(self, points = 1):
        self.live -= points
        canv.itemconfig(self.id_live,text=self.live)
        canv.itemconfig(self.id, fill = 'orange')
        self.change_color = 10
        if self.live < 1:
            self.kill()
        
    def kill(self):
        self.targets.pop(self.targets.index(self))
        canv.delete(self.id)
        canv.delete(self.id_live)
        
g1 = gun()

while 1:
    balls = g1.balls
    targets = g1.targets
    walls = g1.walls
    g1.on = 1
    for z in range(rnd(3,7)):
        targets += [target(targets)]

    for z in range(rnd(1,8)):
        walls += [target(walls)]
        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()
            for w in walls:
                if b.hittest(w):
                    b.ricochet(w)

            for b_test in balls:
                if b != b_test and b.hittest(b_test):
                    if b.nature:
                        b_test.ricochet(b)
                        if b_test.nature:
                            b.ricochet(b_test)
                            b_test.bum()
                    
            for t in targets:
                if b.hittest(t):
                    b.kill()
                    t.hit(b.points)
                    g1.points += 1
                    canv.itemconfig(g1.id_points, text = g1.points)
                    
        if not targets and g1.on:
            canv.bind('<Button-1>','')
            canv.bind('<ButtonRelease-1>','')
            g1.stop()
            canv.itemconfig(result, text = 'Вы уничтожили все цели за ' + str(g1.bullet) + ' выстрелов')
            for b in balls:
                b.bum_time = 20 
                b.bum_on = 1
                
        for t in targets:
            if t.change_color <= 0:
                canv.itemconfig(t.id, fill = t.color)
            else:
                t.change_color -= 1
        canv.update()
        
        t = 0.008 - (len(balls)-5)*0.0001
        t = max (t,0)
        time.sleep(t)
        g1.targetting()
        g1.power_up()
    canv.update()
    time.sleep(0.1)
    canv.delete(result)

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *