Заготовка: выстрелы, переход хода есть, нужно доделать определение попадания (с использованием уже имеющегося hittest)
Также нужно сделать препятствия между пушками, с рикошетом (метод для расчета рикошета готов), и добавить возможность перемещения пушек (move в пушках создан).
Для дальнейшего совершенствования игры сделать экран с горизонтальной прокруткой и прицеливанием не мышью, а с указанием силы выстрела и угла. Добавить ветер.
Добавить разрушаемый ландшафт.
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 = 70
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 jump(self):
if self.vx**2+self.vy**2 > 10:
self.vy = -self.vy*0.7
self.vx = self.vx*0.7
self.y = 499
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:
self.live -= 1
if self.live < 0:
self.bum()
#self.kill()
if self.x > 780:
self.vx = - self.vx/2
self.x = 779
elif self.x < 20:
self.vx = - self.vx/2
self.x = 21
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):
if self.nature:
self.fire()
self.kill()
class gun():
def __init__(self):
self.f2_power = 10
self.x = 400
self.y = 450
self.f2_on = 0
self.on = 1
self.an = 1
self.points = 0
self.id = canv.create_line(self.x,self.y,self.x,self.y-20,width=7, smooth = 1)
self.id_points = canv.create_text(30,30,text = self.points,font = '28')
self.bullet = 0
self.vx = 0
def fire_start(self,event):
if self.on:
self.f2_on = 1
def stop(self):
self.f2_on = 0
self.on = 0
def fire_end(self,event):
if self.on:
self.bullet += 1
new_ball = ball(self.balls)
new_ball.r += 5
new_ball.x = self.x
new_ball.y = self.y
new_ball.vx = self.f2_power*math.cos(self.an)/9
new_ball.vy = self.f2_power*math.sin(self.an)/9
if not rnd(5):
new_ball.surprize = 1
self.balls += [new_ball]
self.f2_on = 0
self.f2_power = 35
def move(self,event=0):
if event:
if event.keycode == 39 and self.vx < 4:
self.vx += 1
elif event.keycode == 37 and self.vx > -4:
self.vx -= 1
else:
self.x += self.vx
if self.x < 50:
self.x = 50
self.vx = 0
elif self.x > 750:
self.x = 750
self.vx = 0
self.aiming()
def aiming (self,event=0):
if event:
if abs(event.x - self.x) < 0.0001:
event.x += 0.1
self.an = math.atan((event.y-self.y)/(event.x-self.x))
if event.x < self.x:
self.an += math.pi
if self.f2_on:
canv.itemconfig(self.id,fill = 'orange')
else:
canv.itemconfig(self.id,fill = 'black')
canv.coords(self.id,self.x,self.y,self.x+max(self.f2_power,20)*math.cos(self.an),self.y+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
self.targets = targets
x = self.x = rnd(50,750)
y = self.y = rnd(-250,150)
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)
def paint(self):
x = self.x
y = self.y
r = self.r
canv.coords(self.id, x-r,y-r,x+r,y+r)
canv.coords(self.id_live,x,y)
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 move(self):
self.y += 0.6
self.paint()
if self.y > 450:
self.kill()
def kill(self):
self.targets.pop(self.targets.index(self))
canv.delete(self.id)
canv.delete(self.id_live)
class game():
def __init__(self):
self.moving = []
self.gamer1 = gun()
self.gamer2 = gun()
self.gamer1.x = 30
self.gamer2.x = 770
self.gamer1.balls = self.moving
self.gamer2.balls = self.moving
self.active_gamer = self.gamer1
canv.bind('<Button-1>',self.fire_start)
canv.bind('<ButtonRelease-1>',self.fire_end)
canv.bind('<Motion>',self.aiming)
root.bind('<Key>',self.move)
self.go = 1
def fire_start(self,event):
self.active_gamer.fire_start(event)
def fire_end(self,event):
self.active_gamer.fire_end(event)
self.active_gamer.stop()
def aiming(self,event):
self.active_gamer.aiming(event)
def power_up(self,event):
self.active_gamer.power_up(event)
def move(self,event):
self.active_gamer.move(event)
def round(self):
if self.active_gamer == self.gamer1:
self.active_gamer = self.gamer2
print ('g1')
else:
self.active_gamer = self.gamer1
print ('g2')
self.active_gamer.on = 1
while self.active_gamer.on or self.moving:
for m in self.moving:
m.move()
self.active_gamer.aiming()
self.active_gamer.power_up()
canv.update()
time.sleep(0.007)
game1 = game()
while 1:
game1.round()