I am working on a game where the player has to collect coins by landing on chests. However, if they land on the same chest three times, it will delete the chest that is there and will insert a bandit in its place - which will reset their coins back to zero (this part is not included in the code provided as it runs correctly).
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()
I know you can use canvas.delete(item_id)
to remove an object, given that it has been defined but my problem is that since I created my objects with a dictionary, they do not have specific names which I could use and I would like to know how I can delete an object from a canvas based on what it's coordinates are rather than it's name.
Also, as a side note, since I am using images, according to answers I have found on , the format has to be GIF, but I am able to use the PNG format and it still works fine but when I try my game on a different device, I get the expected error. Is there a reason for this?
With the help of furas, I have found a solution:
Since each chest has its own unique row and column, you can refer to an individual chest using its row and column, meaning we must find out what that row and column could be.
Because
x1 = col * CELL_WIDTH + 24
andy1 = row * CELL_HEIGHT - 26
where x1 is the x coordinate and y1 is the y coordinate, the equations for the row and column must be(x1 - 24) / CELL_WIDTH = col
and(y1 + 26) / CELL_HEIGHT = row
.You would then substitute for the x and y coordinates using
arrow_coords[0]
andarrow_coords[1]
. And to get the specific row and column from thechest_dict
, you would then round it to the nearest whole number and it will delete that specific chest from the canvas: