I am trying to create a doom-like app using tkinter, but my walls doesnt have the right color. this is my code:
part of the code which is doing the job:
color = "#D3D3D3" # Default wall color is light gray
if hit:
for wx, wy, width, height, wall_color in self.map_data:
if wx <= target_x <= wx + width and wy <= target_y <= wy + height:
color = wall_color
break
Function with the code:
def draw_3d_view(self):
"""Draw the 3D view on the main canvas."""
self.main_canvas.delete("all")
fov = math.pi / 3 # Field of view (60 degrees)
num_rays = int(self.main_canvas['width']) # Number of rays should match canvas width
max_depth = 800
half_fov = fov / 2
angle_step = fov / num_rays
screen_width = int(self.main_canvas['width'])
screen_height = int(self.main_canvas['height'])
ray_angle = self.player.angle - half_fov
for ray in range(num_rays):
depth = 0
hit = False
# Cast ray
for depth in range(1, max_depth):
target_x = self.player.x + depth * math.cos(ray_angle)
target_y = self.player.y + depth * math.sin(ray_angle)
if self.check_collision(target_x, target_y):
hit = True
break
if not hit:
depth = max_depth # If no hit, set depth to max depth for drawing faraway wall
# Calculate wall height based on depth, with a scaling factor to make walls appear taller
scaling_factor = 10 # Adjust this factor to make walls taller or shorter
wall_height = (screen_height / (depth * math.cos(ray_angle - self.player.angle) + 0.0001)) * scaling_factor
start_y = screen_height / 2 - wall_height / 2
end_y = screen_height / 2 + wall_height / 2
# Determine wall color
color = "#D3D3D3" # Default wall color is light gray
if hit:
for wx, wy, width, height, wall_color in self.map_data:
if wx <= target_x <= wx + width and wy <= target_y <= wy + height:
color = wall_color
break
# Draw the vertical line for this ray
self.main_canvas.create_line(ray, start_y, ray, end_y, fill=color)
# Move to the next ray angle
ray_angle += angle_step
# Ensure the view is updated
self.update_idletasks()
Full code:
import tkinter as tk
import gui
import math
class Player:
def __init__(self, x=0, y=0, size=10, angle=0):
self.x = x
self.y = y
self.speed = 10
self.size = size
self.color = "#000000"
self.angle = angle # Direction the player is facing
def update_angle(self):
if self.angle > 360:
self.angle = 0
if self.angle < 0:
self.angle = 360
class Doom(tk.Tk):
def __init__(self):
super().__init__()
self.title("Doom Main Window")
self.geometry("1280x720")
self.attributes("-fullscreen", True)
self.bind("<F11>", self.toggle_fullscreen) # Press F11 to toggle fullscreen
# Create the main window canvas
self.main_canvas = gui.create_canvas(self)
self.main_drawer = gui.TkDrawUtils(self.main_canvas)
# Create the map view window
self.map_window = tk.Toplevel(self)
self.map_window.title("Doom Map View")
self.map_window.geometry("640x365")
self.map_canvas = gui.create_canvas(self.map_window)
self.map_drawer = gui.TkDrawUtils(self.map_canvas)
# Initialize player position
self.player = Player(x=50, y=50) # Set initial player position
self.player_speed = self.player.speed
# Example map data
self.map_data = [
# (x, y, width, height, color)
# Rooms
(10, 10, 200, 120, "#FF0000"), # Red Room
(240, 10, 200, 120, "#00FF00"), # Green Room
(460, 10, 140, 120, "#FFC0CB"), # Pink Room
(10, 160, 120, 200, "#0000FF"), # Blue Room
(160, 160, 120, 200, "#FFFF00"), # Yellow Room
(300, 160, 140, 200, "#FF00FF"), # Magenta Room
(460, 160, 140, 200, "#00FFFF"), # Cyan Room
# Corridors
(120, 60, 120, 20, "#FF0000"), # Red Corridor
(360, 60, 20, 100, "#00FF00"), # Green Corridor
(440, 80, 20, 20, "#FFC0CB"), # Pink Corridor
(120, 180, 40, 20, "#0000FF"), # Blue Corridor
(280, 280, 20, 20, "#FFFF00"), # Yellow Corridor
(440, 200, 20, 20, "#FF00FF"), # Magenta Corridor
(540, 130, 20, 40, "#00FFFF") # Cyan Corridor
]
# Draw the map and player
self.draw_map()
self.refresh()
self.update_view()
# Bind keys to movement functions
self.bind_keys()
def bind_keys(self):
self.bind("<w>", self.move_up)
self.bind("<s>", self.move_down)
self.bind("<a>", self.move_left)
self.bind("<d>", self.move_right)
self.map_window.bind("<w>", self.move_up)
self.map_window.bind("<s>", self.move_down)
self.map_window.bind("<a>", self.move_left)
self.map_window.bind("<d>", self.move_right)
self.bind("<Left>", self.angle_left)
self.bind("<Right>", self.angle_right)
self.map_window.bind("<Left>", self.angle_left)
self.map_window.bind("<Right>", self.angle_right)
def angle_left(self, event=None):
self.player.angle -= 1
self.player.update_angle() # Ensure angle is within valid range
self.refresh()
def angle_right(self, event=None):
self.player.angle += 1
self.player.update_angle() # Ensure angle is within valid range
self.refresh()
def move_up(self, event=None):
"""Move the player forward in the direction they are facing."""
# Calculate new position based on the player's angle
new_x = self.player.x + self.player_speed * math.cos(math.radians(self.player.angle))
new_y = self.player.y + self.player_speed * math.sin(math.radians(self.player.angle))
if not self.check_collision(new_x, new_y):
self.player.x = new_x
self.player.y = new_y
self.update_view()
def move_down(self, event=None):
"""Move the player backward from the direction they are facing."""
# Calculate new position based on the player's angle
new_x = self.player.x - self.player_speed * math.cos(math.radians(self.player.angle))
new_y = self.player.y - self.player_speed * math.sin(math.radians(self.player.angle))
if not self.check_collision(new_x, new_y):
self.player.x = new_x
self.player.y = new_y
self.update_view()
def move_left(self, event=None):
"""Move the player left relative to their facing direction."""
# Calculate new position perpendicular to the player's angle (left direction)
angle_rad = math.radians(self.player.angle)
new_x = self.player.x + self.player_speed * math.sin(angle_rad)
new_y = self.player.y - self.player_speed * math.cos(angle_rad)
if not self.check_collision(new_x, new_y):
self.player.x = new_x
self.player.y = new_y
self.update_view()
def move_right(self, event=None):
"""Move the player right relative to their facing direction."""
# Calculate new position perpendicular to the player's angle (right direction)
angle_rad = math.radians(self.player.angle)
new_x = self.player.x - self.player_speed * math.sin(angle_rad)
new_y = self.player.y + self.player_speed * math.cos(angle_rad)
if not self.check_collision(new_x, new_y):
self.player.x = new_x
self.player.y = new_y
self.update_view()
def update_view(self):
"""Update both the 2D map and the 3D view."""
self.draw_map()
self.draw_3d_view()
self.update()
self.update_idletasks()
def check_collision(self, x, y):
"""Check if the player collides with any walls or corridors."""
player_size = self.player.size
player_rect = (x, y, x + player_size, y + player_size) # Define player rectangle
for (wx, wy, width, height, color) in self.map_data:
wall_rect = (wx, wy, wx + width, wy + height) # Define wall rectangle
# Check if rectangles overlap
if (player_rect[0] < wall_rect[2] and player_rect[2] > wall_rect[0] and
player_rect[1] < wall_rect[3] and player_rect[3] > wall_rect[1]):
return False
return True
def draw_map(self):
"""Draw walls and player on the map canvas based on the map data."""
# Clear previous drawings
self.map_canvas.delete("all")
# Draw walls
for (x, y, width, height, color) in self.map_data:
self.map_drawer.draw_filled_rectangle(x, y, width, height, color)
# Draw player
player_size = self.player.size
player_color = self.player.color
self.map_drawer.draw_filled_rectangle(self.player.x, self.player.y, player_size, player_size, player_color)
def draw_3d_view(self):
"""Draw the 3D view on the main canvas."""
self.main_canvas.delete("all")
fov = math.pi / 3 # Field of view (60 degrees)
num_rays = int(self.main_canvas['width']) # Number of rays should match canvas width
max_depth = 800
half_fov = fov / 2
angle_step = fov / num_rays
screen_width = int(self.main_canvas['width'])
screen_height = int(self.main_canvas['height'])
ray_angle = self.player.angle - half_fov
for ray in range(num_rays):
depth = 0
hit = False
# Cast ray
for depth in range(1, max_depth):
target_x = self.player.x + depth * math.cos(ray_angle)
target_y = self.player.y + depth * math.sin(ray_angle)
if self.check_collision(target_x, target_y):
hit = True
break
if not hit:
depth = max_depth # If no hit, set depth to max depth for drawing faraway wall
# Calculate wall height based on depth, with a scaling factor to make walls appear taller
scaling_factor = 10 # Adjust this factor to make walls taller or shorter
wall_height = (screen_height / (depth * math.cos(ray_angle - self.player.angle) + 0.0001)) * scaling_factor
start_y = screen_height / 2 - wall_height / 2
end_y = screen_height / 2 + wall_height / 2
# Determine wall color
color = "#D3D3D3" # Default wall color is light gray
if hit:
for wx, wy, width, height, wall_color in self.map_data:
if wx <= target_x <= wx + width and wy <= target_y <= wy + height:
color = wall_color
break
# Draw the vertical line for this ray
self.main_canvas.create_line(ray, start_y, ray, end_y, fill=color)
# Move to the next ray angle
ray_angle += angle_step
# Ensure the view is updated
self.update_idletasks()
def toggle_fullscreen(self, event=None):
"""Toggle fullscreen mode."""
current_state = self.attributes("-fullscreen")
self.attributes("-fullscreen", not current_state)
if not current_state:
self.update_idletasks()
def refresh(self):
self.player.update_angle()
self.update_idletasks()
self.update()
self.update_view()
if __name__ == '__main__':
app = Doom()
app.mainloop()
I tried chatGPT but that bot is just stupid. I tried it with the color of the room you are at but it doesnt look right.