Чтобы не замусоривать код, напишем функцию для проверки столкновения:

def bum(ball):

  if flag_coords[0] <= ball. x <= flag_coords[2] and flag_coords[1] <= ball. y <= flag_coords[3]:

  return True

  else:

  return False

Теперь будем вызывать проверку это в основном цикле:

canv. bind('<Button-1>',fire)

z = 0.03

work = 1

while work:

  for b in balls:

  b. move()

  if bum(b):

  print ('!')

  work = 0

  canv. update()

  time. sleep(0.03)

mainloop()

Но видеть «залипший экран» неинтересно. Добавим экран «конец игры»:

z = 0.03

work = 1

while work:

  for b in balls:

  b. move()

  if bum(b):

  work = 0

  canv. update()

  time. sleep(0.03)
canv. delete(ALL)

canv. create_text(400,300, text = 'Вы уничтожили цель за ' + str(bullet) + 'выстрелов',font = '28')

Неплохо, но слишком резко. Пусть долетят оставшиеся шарики:

z = 0.03

work = 1

while work or balls:

  print (len(balls))

  for b in balls:

  b. move()

  if bum(b):

  canv. bind('<Button-1>','')

  work = 0

  canv. update()

  time. sleep(0.03)

canv. bind('<Button-1>','')

Это строка лишает возможности выстрелить шариком и новых шариков больше появится не может. Остальные имеют возможность долететь. Каждый долетевший удаляется из списка и список становится все короче. Когда в списке не останется ни одного шарика – игра заканчивается и появляется надпись и результате.

НЕ нашли? Не то? Что вы ищете?

Окончательный результат + пара «пасхальных яиц»

from random import randrange as rnd, choice

from tkinter import *

import time

root = Tk()

fr = Frame(root)

root. geometry('800x600')

canv = Canvas(root, bg = 'white')

canv. pack(fill=BOTH, expand=1)

canv. create_oval(750,450,766,466,fill='orange')

canv. create_line(758,466,758,480,width=3)

flag_coords = (745,445,770,485)

bullet = 0

def bum(ball):

  if flag_coords[0] <= ball. x <= flag_coords[2] and flag_coords[1] <= ball. y <= flag_coords[3]:

  return True

  else:

  return False

class ball():

  def __init__(self):

  self. x = 20

  self. y = 450

  self. r = 10

  self. color = choice(['blue','green','red','brown'])

  self. id = canv. create_oval(self. x-self. r,self. y-self. r,self. x+self. r,self. y+self. r,fill=self. color)

  def set_coords(self):

  canv. coords(self. id, self. x-self. r,self. y-self. r,self. x+self. r,self. y+self. r)

  def move(self):

  if self. y <= 500:

  self. vy -= 1.2

  self. y -= self. vy

  self. x += self. vx

  self. vx *= 0.99

  self. set_coords()

  else:

  self. y -= self. vy

  if self. y > 800:

  balls. pop(balls. index(self))

  canv. delete(self. id)

balls = []

def fire(event):

  global balls

  global bullet

  bullet += 1

  balls += [ball()]

  balls[-1].vx = (event. x-balls[-1].x)/10

  balls[-1].vy = -(event. y-balls[-1].y)/10

def fire2(event):

  global balls

  global bullet

  bullet += 1

  balls += [ball()]

  balls[-1].r += 20

  balls[-1].vx = (event. x-balls[-1].x)/10

  balls[-1].vy = -(event. y-balls[-1].y)/10

def fire3(event):

  global balls

  global bullet

  for x in range(10):

  bullet += 1

  balls += [ball()]

  balls[-1].r = 5

  balls[-1].vx = (event. x-balls[-1].x)/10

  balls[-1].vy = -(event. y-balls[-1].y)/10+(x-10)

canv. bind('<Button-1>',fire)

canv. bind('<Button-3>',fire2)

canv. bind('<Button-2>',fire3)

z = 0.03

work = 1

while work:

  for b in balls:

  b. move()

  if bum(b):

  work = 0

  canv. update()

  time. sleep(0.03)

canv. delete(ALL)

canv. create_text(400,300, text = 'Вы уничтожили цель за ' + str(bullet) + 'выстрелов',font = '28')

mainloop()

Добавим … пушку!

from random import randrange as rnd, choice

from tkinter import *

import time

root = Tk()

fr = Frame(root)

root. geometry('800x600')

canv = Canvas(root, bg = 'white')

canv. pack(fill=BOTH, expand=1)

canv. create_oval(750,450,766,466,fill='orange')

canv. create_line(758,466,758,480,width=3)

flag_coords = (745,445,770,485)

gun = canv. create_line(20,450,50,420,width=7)

bullet = 0

def bum(ball):

  if flag_coords[0] <= ball. x <= flag_coords[2] and flag_coords[1] <= ball. y <= flag_coords[3]:

  return True

  else:

  return False

class ball():

  def __init__(self, x=40,y=450):

  self. x = x

  self. y = y

  self. r = 10

  self. color = choice(['blue','green','red','brown'])

  self. id = canv. create_oval(self. x-self. r,self. y-self. r,self. x+self. r,self. y+self. r,fill=self. color)

  def set_coords(self):

  canv. coords(self. id, self. x-self. r,self. y-self. r,self. x+self. r,self. y+self. r)

  def move(self):

  if self. y <= 500:

  self. vy -= 1.2

  self. y -= self. vy

  self. x += self. vx

  self. vx *= 0.99

  self. set_coords()

  else:

  self. y -= self. vy

  if self. y > 800:

  balls. pop(balls. index(self))

  canv. delete(self. id)

balls = []

def fire(event):

  global balls

  global bullet

  bullet += 1

  balls += [ball(canv. coords(gun)[2],canv. coords(gun)[3])]

  balls[-1].vx = (event. x-balls[-1].x)/10

  balls[-1].vy = -(event. y-balls[-1].y)/10

def fire2(event):

  global balls

  global bullet

  bullet += 1

  balls += [ball()]

  balls[-1].r += 20

  balls[-1].vx = (event. x-balls[-1].x)/10

  balls[-1].vy = -(event. y-balls[-1].y)/10

def fire3(event):

  global balls

  global bullet

  for x in range(10):

  bullet += 1

  balls += [ball()]

  balls[-1].r = 5

  balls[-1].vx = (event. x-balls[-1].x)/10

  balls[-1].vy = -(event. y-balls[-1].y)/10+(x-10)

def pointing (event):

  canv. coords(gun,20,450,20+(event. x-20)/10,450-(450-event. y)/10)

canv. bind('<Button-1>',fire)

canv. bind('<Button-3>',fire2)

canv. bind('<Button-2>',fire3)

canv. bind('<Motion>',pointing)

z = 0.03

work = 1

while work:

  for b in balls:

  b. move()

  if bum(b):

  work = 0

  canv. update()

  time. sleep(0.03)

canv. delete(ALL)

canv. create_text(400,300, text = 'Вы уничтожили цель за ' + str(bullet) + 'выстрелов',font = '28')

mainloop()

Добавим рикошет, вывод надписи сразу после уничтожения пушки, и еще кое-что:

from random import randrange as rnd, choice

from tkinter import *

import time

root = Tk()

fr = Frame(root)

root. geometry('800x600')

canv = Canvas(root, bg = 'white')

canv. pack(fill=BOTH, expand=1)

def bum(ball):

  if flag_coords[0] <= (ball. x + ball. r) and (ball. x - ball. r) <= flag_coords[2] and flag_coords[1] <= (ball. y + ball. r) and (ball. y - ball. r) <= flag_coords[3]:

  return True

  else:

  return False

class ball():

  def __init__(self, x=40,y=450):

  self. x = x

  self. y = y

  self. r = 10

  self. color = choice(['blue','green','red','brown'])

  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. live = 30

  def set_coords(self):

  canv. coords(self. id, self. x-self. r,self. y-self. r,self. x+self. r,self. y+self. r)

  def move(self):

  if self. y <= 500:

  self. vy -= 1.2

  self. y -= self. vy

  self. x += self. vx

  self. vx *= 0.99

  self. set_coords()

  else:

  if self. vx**2+self. vy**2 > 10:

  self. vy = - self. vy/2

  self. vx = self. vx/2

  self. y = 499

  if self. live < 0:

  balls. pop(balls. index(self))

  canv. delete(self. id)

  else:

  self. live -= 1

  if self. x > 780:

  self. vx = - self. vx/2

  self. x = 779

def fire(event):

  global balls

  global bullet

  bullet += 1

  balls += [ball(canv. coords(gun)[2],canv. coords(gun)[3])]

  balls[-1].vx = (event. x-balls[-1].x)/10

  balls[-1].vy = -(event. y-balls[-1].y)/10

def fire2(event):

  global balls

  global bullet

  bullet += 1

  balls += [ball()]

  balls[-1].r += 20

  balls[-1].vx = (event. x-balls[-1].x)/20

  balls[-1].vy = -(event. y-balls[-1].y)/20

def fire3(event):

  global balls

  global bullet

  for x in range(10):

  bullet += 1

  balls += [ball()]

  balls[-1].r = 5

  balls[-1].vx = (event. x-balls[-1].x)/15 + rnd(5)

  balls[-1].vy = -(event. y-balls[-1].y)/15+(x-10) + rnd(5)

def pointing (event):

  canv. coords(gun,20,450,20+(event. x-20)/10,450-(450-event. y)/10)

def new_game(event=''):

  canv. delete(ALL)

  global gun, flag_coords, bullet, balls

  canv. create_oval(750,450,766,466,fill='orange')

  canv. create_line(758,466,758,480,width=3)

  flag_coords = (745,445,770,485)

  gun = canv. create_line(20,450,50,420,width=7)

  bullet = 0

  balls = []

  canv. bind('<Button-1>',fire)

  canv. bind('<Button-3>',fire2)

  canv. bind('<Button-2>',fire3)

  canv. bind('<Motion>',pointing)

  z = 0.03

  work = 1

  while work or balls:

  for b in balls:

  b. move()

  if bum(b) and work:

  work = 0

  canv. bind('<Button-1>','')

  canv. bind('<Button-3>','')

  canv. bind('<Button-2>','')

  canv. create_text(400,300, text = 'Вы уничтожили цель за ' + str(bullet) + 'выстрелов',font = '28')

  canv. update()

  time. sleep(0.03)

  canv. delete(ALL)

  canv. create_text(400,300, text = 'Вы уничтожили цель за ' + str(bullet) + 'выстрелов',font = '28') 

  canv. bind('<Button-1>',new_game)

new_game() 

mainloop()

На это игру «Пушка» мы закончим.

Что еще можно сделать с пушкой? Немало. Позже мы вернемся к пушке и все это доделаем, а пока вы можете попробовать самостоятельно:

Сделать прицеливание с помощью удержания мыши. Дольше держишь – дальше летит.

Сделать прицеливание как в AngryBirds (как из рогатки)

Сделать мишень, которая будет появляться в случайных местах правой части экрана и находится 3-5 секунд на каждом месте.

Создать новый вид шариков: разрывные (при ударе о землю – разделяется на 8-10 мелких частей, резлетающихся в стороны)

Для каждого вида снарядов создать свой класс (см. справочник – наследование)

Добавить пушку противника. И сделать игру пошаговой

Сделать пушку перемещаемой (ограничить в дальности 50-80 точек)

Реализовать ограничение снарядов в количестве

Ограничить время хода 20 секундами и одним выстрелом

Добавить призы (как в червяках). С выбором – стрелять в противника или в приз: новый вид оружия, дальность и скорость перемещения, возможность сделать два выстрела

Добавить фоновое изображение

Создать разрушаемый рельеф

Реализовать «здоровье» в процентах. Чтобы не уничтожать с одного попадания.

Создать новый вид шарика: химическое оружие (при ударе о землю вырывается облако, причиняя кратковременный урон)

Создать «биологическое оружие» (при ударе вырывается облако, причиняя небольшой урон, но повторяющийся при каждом ходе)

Реализовать простой AI (ИИ) для  игры с компьютером

…. (продолжение следует)


Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7 8 9