2016-12-24 9 views
0

Я работаю над игрой, в которой игрок должен собирать монеты, присаживаясь на сундуки. Однако, если они три раза приземлятся на один сундук, он удалит сундук, который там, и введет бандит на свое место, - который сбросит свои монеты обратно до нуля (эта часть не включена в код, предоставляемый по мере его запуска правильно).Удаление изображения с холста tkinter на основе его координат

try: 
    import tkinter as tk 
    from tkinter import ttk  
except ImportError: 
    import Tkinter as tk 
    from Tkinter import ttk 

import random 
from collections import Counter 

CELL_WIDTH = 50 
CELL_HEIGHT = 50 
rows = 8 
columns = 8 
bandit_number = 5 
chest_number = 10 
moves = 0 
coins = 0 
chests_visited =() 

def create_grid(): 
    game_frame.pack() 
    game_grid.pack() 
    data = {} 
    for col in range(columns): 
     for row in range(rows): 
      x1 = col * CELL_WIDTH 
      y1 = row * CELL_HEIGHT 
      x2 = x1 + CELL_WIDTH 
      y2 = y1 + CELL_HEIGHT 
      data[row, col] = game_grid.create_rectangle(x1, y1, x2, y2, 
                 fill="green", 
                 tags="rect") 
    return data 
def create_chests(chest_image): 
    global chest_dict 
    chest_dict = {} 
    for i in range(chest_number): 

     while True: 
      row = random.randint(0, rows-1) 
      col = random.randint(0, columns-1) 
      if (row,col) not in chest_dict: 
       break 
     x1 = col * CELL_WIDTH + 24 
     y1 = row * CELL_HEIGHT - 26 
     x2 = x1 + CELL_WIDTH 
     y2 = y1 + CELL_HEIGHT 
     chest_dict[row,col] = game_grid.create_image(x1, y1, image=chest_image, 
                tags="chest") 
    return chest_dict 

def create_bandits(bandit_image): 
    global bandit_dict 
    bandit_dict = {} 
    for i in range(bandit_number): 
     while True: 
      row = random.randint(0, rows-1) 
      col = random.randint(0, columns-1) 
      if (row,col) not in bandit_dict: 
       break    
     x = col * CELL_WIDTH + 22 
     y = row * CELL_HEIGHT - 22 
     x2 = x + CELL_WIDTH 
     y2 = y + CELL_HEIGHT 
     bandit_dict[row,col] = game_grid.create_image(x, y, image=bandit_image) 
    return bandit_dict 
def position_player(player_image): 
    global arrow 
    arrow = game_grid.create_image(26, 375, image=player_image) 
    display_widgets() 
    return arrow 
def display_widgets(): 
    global move_entry_x, move_entry_y, help_lbl 
    help_lbl = tk.Label(game_grid, text="Enter the x value in the first entry"+ 
         " and the y value in the second." + '\n' + 
         "Use negatives to move left and down.") 
    game_grid.create_window(200, 420, window=help_lbl) 
    move_entry_x = tk.Entry(game_grid) 
    game_grid.create_window(70, 450, window=move_entry_x) 
    move_entry_y = tk.Entry(game_grid) 
    game_grid.create_window(200, 450, window=move_entry_y) 
    enter_btn = ttk.Button(game_grid, text="Enter", command=check_move) 
    game_grid.create_window(305, 450, window=enter_btn) 

def check_move(): 
    global help_lbl 
    if (
     move_entry_x.get()[0] == "-" or 
     move_entry_y.get()[0] == "-" 
     ): 
     try: 
      if (
       int(move_entry_x.get()[1])*CELL_WIDTH < 26 or 
       int(move_entry_x.get()[1])*CELL_WIDTH > int(rows)*CELL_WIDTH 
       ): 
       print("Illegal move! Enter a different value") 
      elif (
       int(move_entry_y.get()[1])*CELL_WIDTH < 26 or 
       int(move_entry_y.get()[1])*CELL_WIDTH > int(rows)*CELL_HEIGHT 
       ): 
       print("Illegal move! Enter a different value") 
      else: 
       move_player(arrow) 
     except ValueError: 
      print("Please enter a number!") 
    else: 
     try: 
      if (
       int(move_entry_x.get())*CELL_WIDTH < 26 or 
       int(move_entry_x.get())*CELL_WIDTH > int(rows)*CELL_WIDTH 
       ): 
       print("Illegal move! Enter a different value") 
      elif (
       int(move_entry_y.get())*CELL_WIDTH < 26 or 
       int(move_entry_y.get())*CELL_WIDTH > int(rows)*CELL_HEIGHT 
       ): 
       print("Illegal move! Enter a different value") 
      else: 
       move_player(arrow) 
     except ValueError: 
      print("Please enter a number!") 

def move_player(arrow): 
    global move_entry_x, move_entry_y, help_lbl, moves 
    x_move = move_entry_x.get() 
    y_move = move_entry_y.get() 
    x = int(x_move)*CELL_WIDTH 
    y = int(y_move)*CELL_HEIGHT 
    game_grid.move(arrow, x, -y) 
    moves += 1 
    print("Moves = "+str(moves)) 
    check_position(arrow, chest_dict) 

def check_position(arrow, chest_dict): 
    global coins, arrow_coords, chests_visited 
    arrow_coords = game_grid.coords(arrow) 
    for i in chest_dict: 
     chest_coords = game_grid.coords(chest_dict[i]) 
     if (
      int(arrow_coords[0])-2 in chest_coords and 
      int(arrow_coords[1])-1 in chest_coords 
     ): 
      coins += 10 
      chests_visited += tuple(arrow_coords) 
      print("Chests visited: "+str(chests_visited)) 
    check_chests() 
    return arrow, chest_dict 
def check_chests(): 
    global chests_visited, chest_dict, bandit_dict 
    cnt = Counter(chests_visited) 
    if (
     [k for k, v in cnt.items() if v == 3] 
     ): 
     game_grid.create_image(arrow_coords[0],arrow_coords[1], 
           image=bandit_image) 
     print("bandit_time")  
window = tk.Tk() 

game_frame = tk.Frame(window) 
game_grid = tk.Canvas(game_frame, width=500, height=500, borderwidth=0, 
         highlightthickness=0) 
game_grid.itemconfig("rect", fill="green") 

bandit_image = tk.PhotoImage(file="Bandit.png") 
chest_image = tk.PhotoImage(file="Treasure Chest.png") 
player_image = tk.PhotoImage(file="Arrow.png") 

rects = create_grid() 
bandits = create_bandits(bandit_image) 
chests = create_chests(chest_image) 
player = position_player(player_image) 
window.mainloop() 

Я знаю, что вы можете использовать canvas.delete(item_id), чтобы удалить объект, учитывая, что она была определена, но моя проблема заключается в том, что, так как я создал свои объекты со словарем, они не имеют конкретные имена, которые я мог бы использовать, и я хотел бы знать, как я могу удалить объект из холста на основе его координат, а не его имени.

Кроме того, поскольку я использую изображения, в соответствии с ответами, которые я нашел, формат должен быть GIF, но я могу использовать формат PNG, и он все еще отлично работает, но когда я пытаюсь моя игра на другом устройстве, я получаю ожидаемую ошибку. Для этого есть причина?

+0

'Tkinter', как по умолчанию работает только с' GIF' (и еще один формат). Для работы с PNG вам нужен модуль 'PIL' или' pillow': http://effbot.org/tkinterbook/photoimage.htm. Конечно, PIL/pillow' может использовать некоторые внешние библиотеки, и если у устройства нет этих библиотек, то событие 'PIL/pillow' не может помочь. – furas

+0

'canvas.delete (data [row, col])' или 'canvas.delet (chest_dict [row, col])' – furas

+0

@furas Я пошел дальше, но предлагаемое вами решение заставляет мою программу всегда предполагать, что сундук всегда 7-й строке и столбце, что дает мне «ключевую ошибку». Есть идеи? – Ernxst

ответ

0

С помощью furas, я нашел решение:

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

x1 = col * CELL_WIDTH + 24 Потому и y1 = row * CELL_HEIGHT - 26 где x1 координаты х и y 1 представляет собой координату, уравнения для строки и столбца должны быть (x1 - 24)/CELL_WIDTH = col и (y1 + 26)/CELL_HEIGHT = row.

Затем вы заменили координаты x и y, используя arrow_coords[0] и arrow_coords[1]. А чтобы получить конкретную строку и столбец из chest_dict, вы бы тогда вокруг него до ближайшего целого числа, и он удалит эту специфическую грудь из холста:

game_grid.delete(chest_dict[int(round(int(arrow_coords[0]-24)/50, 0)), 
          int(round(int(arrow_coords[1]+26)/50, 0))])