2015-04-17 4 views
0

Я пытаюсь создать простую игру. Я хочу случайным образом создать «бомбы», и игроку нужно щелкнуть его, прежде чем он взорвется. Прямо сейчас я действительно изо всех сил стараюсь сделать так, чтобы моя программа могла зарегистрировать координаты кликов и определить, нажали ли вы на бомбу или пропустили. У кого-нибудь есть указатели/подсказки для продвижения вперед?Как я могу обнаружить объект, если он был нажат?

Вот что у меня есть.

Моя бомба Класс:

from graphics import * 
import time 


class Bomb(object): 

    def __init__(self, location, radius, window): 
     self.circle = Circle(location, radius) 
     self.circle.draw(window) 
     self.circle.setFill("black") 
     self.start_time = time.time() 


    def update(self): 
     if time.time() - self.start_time > 3.0: 
      self.circle.setFill("blue") 

    def ready_to_explode(self): 
     if time.time() - self.start_time > 3.0: 
      return True 

    def is_clicked(self): 
     #use x y coordinates of click and determine if the distance between this point and center of circle is <or> than radius? 

    def explode(self): 
     self.circle.setFill("pink") 


    def defuse(self): 
     self.circle.setFill("green") 

Моя основная программа:

from graphics import * 
import time 
import random 
from bomb import Bomb 


window = GraphWin("Click-click-BOOM! *", 400, 400) 

event_text = Text(Point(100, 100), "events") 
event_text.draw(window) 

time_text = Text(Point(100, 200), "time info") 
time_text.draw(window) 


def keyboard_callback(event): 
    event_text.setText(event.char) 
    if "q" == event.char: 
     global quit 
     quit = True 


def click_callback(event): 
    click_output = "button1 click at " 
    click_output += "<" + str(event.x) + ", " + str(event.y) + ">" 
    event_text.setText(click_output) 

window.bind_all("<Key>", keyboard_callback) 
window.bind_all("<Button-1>", click_callback) 

start_time = time.time() 
last_time = start_time 

quit = False 

bombs = [] 
bomb_to_add = Bomb(Point(random.randint(1, 400), random.randint(1, 400)), 25, window) 
bombs.append(bomb_to_add) 


frames = 0 
while not quit: 
    for bomb in bombs: 
     bomb.update() 
     if bomb.is_clicked(): 
      bomb.defuse() 

window.close() 
exit() 
+0

Что это за 'графический' импорт? – KSFT

+0

@KSFT: Когда это выглядит как домашнее задание, и его просто называют «графикой» без каких-либо уточнений, обычно это [вещь Джона Зелля] (http://mcsp.wartburg.edu/zelle/python/graphics/graphics/index.html), который завершает TkInter с помощью некоторых простых примитивов рисования фигуры. (И спрашивающий никогда не знает, откуда он, потому что их учитель обычно отдавал их им, не сообщая им ...) – abarnert

+0

@KSFT Это простая объектно-ориентированная графическая библиотека. Здесь я получил свой круг, а также GraphWn. Должен ли я опубликовать его также? – Courtney

ответ

1

Я считаю, что у вас есть две проблемы решить.

Во-первых, вы звоните window.bind_all("<Button-1>", click_callback). Это не метод graphics, это метод Tkinter. (Tkinter это окна-и-низкоуровневые-графическая библиотека, которая graphics использует под одеялом, это часть стандартной библиотеки Python.)

Это должно означает, что каждый раз, когда пользователь нажимает кнопку мыши в любом месте ваше окно, вызывается функция click_callback. Вы можете увидеть, будет ли получать вызов, скажем, добавив print('click_callback got called') в начале функции.


Но это выглядит, как вы используете свой собственный цикл ручной кадр здесь:

while not quit: 
    for bomb in bombs: 
     bomb.update() 
     if bomb.is_clicked(): 
      bomb.defuse() 

Вы можете сделать это с Tkinter до тех пор, как вы водите его основной цикл из вашего цикла. Каждый кадр, вы хотите сказать ему, чтобы проверить и событий процесса один раз, не навсегда, который я думаю, выглядит следующим образом:

while not quit: 
    window.mainloop(1) 
    for bomb in bombs: 
     bomb.update() 
     if bomb.is_clicked(): 
      bomb.defuse() 

Но это не может быть правильным, и это не упоминается в основном документы, так вам, возможно, придется немного поработать.

Если вам действительно нужна ручная петля, вы, вероятно, действительно не хотите Tkinter и graphics, вы хотите PyGame.


Но есть другой способ решить эту проблему: просто дайте Tkinter запустить свой цикл событий (я думаю graphics заботится об этом за вас волшебным образом, если вы не получите в своем роде), и попросить Tkinter в планируйте свои вещи для запуска. Как это:.

def do_frame(): 
    if quit: 
     window.quit() # may be wrong... 
    for bomb in bombs: 
     bomb.update() 
     if bomb.is_clicked(): 
      bomb.defuse() 
    window.after(100, do_frame) 
window.after(100, do_frame) 

Это последняя строка означает «Как близко к 100мсу теперь, как вы можете, позвонить do_frame

Затем внутри do_frame, вы делаете все вещи вы делали каждый раз через петлю , и закончите, попросив Tkinter снова позвонить do_frame еще раз в 100 мс.

Единственное, что вам нужно изменить, это то, что вы не можете просто упасть с конца программы, когда quit истинно, поэтому вам, вероятно, придется явным образом вызываю метод quit, возможно, на window.

Это не может дать вам точное время. Итак, все, что, скажем, перемещает определенное количество пикселей/кадров, будет идти быстрее и медленнее. Если вы хотите, чтобы вместо этого перемещалось определенное количество пикселей в секунду, вы должны проверить время и посмотреть, сколько времени прошло с момента последнего вызова do_frame и отрегулировать пиксели.

Но это намного проще и более идиоматично для Tkinter.


После того, как вы решите этот, так или иначе, то ваш click_callback должен начать получать называется.

Но его зовут окно , а не круг или другие графические виджеты.

Насколько я знаю, библиотека graphics не имеет никаких функций для тестирования на удар (определение того, в каком объекте находится мышь). Итак, вы должны вручную просмотреть свои объекты и посмотреть, кто должен получить клик, а затем вручную вызвать какой-либо метод на этом объекте. (Кроме того, если вам нужны координаты по центру или углу объекта, вместо основного окна их нужно вручную преобразовать.)

Это проще с помощью красивой спрайт-библиотеки (опять же, один в PyGame), но это не , что трудно сделать сами, особенно если вы не беспокоитесь об эффективности. (Назад, когда это было трудной проблемой, консоль для видеоигр была примерно в 10000 раз медленнее, чем ваш телефон сегодня.)

Смежные вопросы