-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpush the box.py
183 lines (140 loc) · 12.9 KB
/
push the box.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
import tkinter as tk
from config import *
root = tk.Tk()
root.title( "Push the Box") # sets the title of the window
canvas = tk.Canvas(root, width = WIDTH, height = HEIGHT) # defines the canvas
canvas.pack() # packs the canvas
class Game:
def __init__(self):
self.walls_coords = [] # empty list where all the wall coords will be stored as tuples after reading from level.txt
# variables for all images
self.img_wall = tk.PhotoImage(file = "textures\wall.png")
self.img_player_neutral = tk.PhotoImage(file = "textures\player_neutral.png")
self.img_player_up = tk.PhotoImage(file = "textures\player_up.png")
self.img_player_down = tk.PhotoImage(file = "textures\player_down.png")
self.img_player_left = tk.PhotoImage(file = "textures\player_left.png")
self.img_player_right = tk.PhotoImage(file = "textures\player_right.png")
self.img_box = tk.PhotoImage(file = "textures\\box.png")
self.img_win_location_off = tk.PhotoImage(file = "textures\win_location_off.png")
self.img_win_location_on = tk.PhotoImage(file = "textures\win_location_on.png")
# all x and y values for both player and the box storing how much had player and the box deviated from their starting position
# after reset, player and box will be moved the opposite direction of these values to be at the start again
self.x_player_change = 0
self.y_player_change = 0
self.x_box_change = 0
self.y_box_change = 0
def process_level(self): # this function will read through level.txt, process the information and draw walls, player, box and winning location on the spot where they belong
self.level_layout = open("level.txt", "r", encoding = "UTF-8") # the program opens level.txt
# helping variables to calculate the distance of a certain wall tile
self.x_counter = 0
self.y_counter = 0
for self.y_level in self.level_layout: # reads through the every line in level.txt
self.y_level = self.y_level.strip() # strips it so it's the correct format
for self.x_level in self.y_level: # reads through every character in the specific line
if self.x_level == "#": # if the character is "#" -> it is a wall
self.x_wall = int(WIDTH/2) + ((self.x_counter - 7) * TILE_SIZE) # specifies, where the wall should be on the x axis by multiplying the counter value by TILE_SIZE so it would be placed in a grid
self.y_wall = int(HEIGHT/2) + ((self.y_counter - 7) * TILE_SIZE) # and the same for the y axis
self.wall = canvas.create_image(self.x_wall - PLAYER_SIZE, self.y_wall - PLAYER_SIZE,anchor = tk.NW, image = self.img_wall) # creates the wall on the position it should appear in the grid
self.walls_coords.append((self.x_wall - PLAYER_SIZE, self.y_wall - PLAYER_SIZE)) # appends the wall coords as a tuple to a list walls_coords (this is for checking collisions later)
elif self.x_level == "P": # if the character is "P" -> it is the player
self.x_player = int(WIDTH/2) + int(((self.x_counter - 7) * TILE_SIZE)) # does exactly the same for the player for both x...
self.y_player = int(HEIGHT/2) + int(((self.y_counter - 7) * TILE_SIZE)) # ...and y axes
self.player = canvas.create_image(self.x_player - PLAYER_SIZE, self.y_player - PLAYER_SIZE, anchor = tk.NW, image = self.img_player_neutral) # creates the player
elif self.x_level == "B": # if character is "B" -> it is the box
self.x_box = int(WIDTH/2) + int(((self.x_counter - 7) * TILE_SIZE))
self.y_box = int(HEIGHT/2) + int(((self.y_counter - 7) * TILE_SIZE))
self.x_box_start = self.x_box
self.y_box_start = self.y_box
self.box = canvas.create_image(self.x_box - PLAYER_SIZE, self.y_box - PLAYER_SIZE, anchor = tk.NW, image = self.img_box) # creates the box
elif self.x_level == "W": # if the character is "W" -> winning location
self.x_win_location = int(WIDTH/2) + int(((self.x_counter - 7) * TILE_SIZE))
self.y_win_location = int(HEIGHT/2) + int(((self.y_counter - 7) * TILE_SIZE))
self.win_location = canvas.create_image(self.x_win_location - PLAYER_SIZE, self.y_win_location - PLAYER_SIZE, anchor = tk.NW, image = self.img_win_location_off)
self.x_counter += 1
self.x_counter = 0
self.y_counter += 1
self.level_layout.close() # the text file closes so it would not create any further problems
def draw_controls(self): # this function will draw controls
self.win_text = canvas.create_text(100, 50, text = "", fill = "black", font = "Helvetica 20 bold") # empty text, that will later change to "YOU WIN!" after the player finishes the level
self.controls_text_title = canvas.create_text(TILE_SIZE, HEIGHT - 6*TILE_SIZE, text = "CONTROLS:", anchor = tk.NW, fill = "black", font = "Helvetica 20 bold") # title to display controls
self.controls_text = canvas.create_text(TILE_SIZE, HEIGHT - 5*TILE_SIZE, text = "W - up\nA - left\nS - down\nD - right\n\nR - reset", anchor = tk.NW, fill = "black", font = "Helvetica 18 bold") # text to display controls
def actions(self, event): # this function stores all the actions, that are bound
self.x, self.y = 0, 0 # the x and y values to determine how much will the player move, if a key is pressed, but it is not for movement, the player and box will move 0px in x and y direction
if event.char == "w": # if the pressed key is W
if ((canvas.coords(self.player)[0], canvas.coords(self.player)[1] - TILE_SIZE) in self.walls_coords) or (canvas.coords(self.player)[0] == canvas.coords(self.win_location)[0] and canvas.coords(self.player)[1] - TILE_SIZE == canvas.coords(self.win_location)[1]): # checks if player's x1; y1 is equal to any tuple in the walls_list, if the output is True, this means the player is in colision with a wall and cannot move this way, same is done for winning location
pass # if collision is detected, the player doesn't move and x, y will still be equal to 0
else: # if the collision is not detected
self.y = -TILE_SIZE # the player can move upwards
self.y_player_change += self.y # adds the changed y value to y_player_change to be later used in reset
if (canvas.coords(self.player)[1] - canvas.coords(self.box)[1]) == 40 and (canvas.coords(self.player)[0] - canvas.coords(self.box)[0]) == 0: # checks collision with the box, this checks if the box and player are in valid position to be moved
if (canvas.coords(self.box)[0], canvas.coords(self.box)[1] - TILE_SIZE) in self.walls_coords: # if the box collides with the wall
self.y_player_change -= self.y # it reverts the player movement so it would not count even if the player doesn't move
self.y = 0 # neither the player not box move upwards
else:
canvas.move(self.box, self.x, self.y) # if no collision is detected, the box will move upwards
self.y_box_change += self.y # box change is counted into the change to be later used in reset
canvas.itemconfig(self.player, image = self.img_player_up)
elif event.char == "a": # if te pressed key is A
# the program, will do exactly the same process as before, but instead of calculating movement upwards, it will do it for the left side
if ((canvas.coords(self.player)[0] - TILE_SIZE, canvas.coords(self.player)[1]) in self.walls_coords) or (canvas.coords(self.player)[0] - TILE_SIZE == canvas.coords(self.win_location)[0] and canvas.coords(self.player)[1] == canvas.coords(self.win_location)[1]): # wall collision
pass
else:
self.x = -TILE_SIZE
self.x_player_change +=self.x
if (canvas.coords(self.player)[0] - canvas.coords(self.box)[0]) == 40 and (canvas.coords(self.player)[1] - canvas.coords(self.box)[1]) == 0: # box movement
if (canvas.coords(self.box)[0] - TILE_SIZE, canvas.coords(self.box)[1]) in self.walls_coords:
self.x_player_change -= self.x
self.x = 0
else:
canvas.move(self.box, self.x, self.y)
self.x_box_change += self.x
canvas.itemconfig(self.player, image = self.img_player_left)
elif event.char == "s": # if the pressed key is S
# calculating downward movements
if ((canvas.coords(self.player)[0], canvas.coords(self.player)[1] + TILE_SIZE) in self.walls_coords) or (canvas.coords(self.player)[0] == canvas.coords(self.win_location)[0] and canvas.coords(self.player)[1] + TILE_SIZE == canvas.coords(self.win_location)[1]): # wall collision
pass
else:
self.y = TILE_SIZE
self.y_player_change += self.y
if (canvas.coords(self.player)[1] - canvas.coords(self.box)[1]) == -40 and (canvas.coords(self.player)[0] - canvas.coords(self.box)[0]) == 0: # box movement
if (canvas.coords(self.box)[0], canvas.coords(self.box)[1] + TILE_SIZE) in self.walls_coords:
self.y_player_change -= self.y
self.y = 0
else:
canvas.move(self.box, self.x, self.y)
self.y_box_change += self.y
canvas.itemconfig(self.player, image = self.img_player_down)
elif event.char == "d": # if the pressed key is D
# movements for the right side
if ((canvas.coords(self.player)[0] + TILE_SIZE, canvas.coords(self.player)[1]) in self.walls_coords) or (canvas.coords(self.player)[0] + TILE_SIZE == canvas.coords(self.win_location)[0] and canvas.coords(self.player)[1] == canvas.coords(self.win_location)[1]): # wall collision
pass
else:
self.x = TILE_SIZE
self.x_player_change += self.x
if (canvas.coords(self.player)[0] - canvas.coords(self.box)[0]) == -40 and (canvas.coords(self.player)[1] - canvas.coords(self.box)[1]) == 0: # box movement
if (canvas.coords(self.box)[0] + TILE_SIZE, canvas.coords(self.box)[1]) in self.walls_coords:
self.x_player_change -= self.x
self.x = 0
else:
canvas.move(self.box, self.x, self.y)
self.x_box_change += self.x
canvas.itemconfig(self.player, image = self.img_player_right)
elif event.char == "r": # if the player pressed R
canvas.move(self.player, -self.x_player_change, -self.y_player_change) # the player will be moved in reversed directions of the calculated deviations from starting
self.x_player_change = 0 # the x and y changes are then changed back to 0 and the new calculation can begin after the player moves again
self.y_player_change = 0
canvas.itemconfig(self.player, image = self.img_player_neutral)
canvas.move(self.box, -self.x_box_change, -self.y_box_change) # same is done for the box as well
self.x_box_change = 0
self.y_box_change = 0
canvas.itemconfig(self.win_text, text = "") # the win text is changed to empty string, this only has impact when the player already won
canvas.itemconfig(self.win_location, image = self.img_win_location_off) # win location image is changed to it's off variant
if (canvas.coords(self.box)[0] == canvas.coords(self.win_location)[0]) and (canvas.coords(self.box)[1] == canvas.coords(self.win_location)[1]): # this checks if the x1; y1 of the box and x1; y1 of the winning location matches, if yes, the palyer has won
canvas.itemconfig(self.win_text, text = "YOU WIN!") # empty text will be changed to "YOU WIN!"
canvas.itemconfig(self.win_location, image = self.img_win_location_on) # image of win location is changed to fit the box outline, meaning, the level victory
canvas.move(self.player, self.x, self.y) # this moves the player in the wanted direction, if W, A, S nor D was pressed, the player will move 0px, which means it will not move
game = Game() # stores Game() into an object
game.process_level() # processes the text file and draws the level
game.draw_controls() # displays the controls on the screen
canvas.bind_all("<Key>", game.actions) # if any key is pressed, the actions function will be called to determine what to do, or if actually do anything at all
root.mainloop() # mainloop for the entire window