import time import glob import os import json import pyglet from Units.knight import Knight from Effects.order_click import OrderClick class IsometricGame: def __init__(self, width, height, data): self.width = width self.height = height self.cell_width = 132 self.cell_height = 66 self.cell_selected = (0, 0) self.view_offset_x = 800 self.view_offset_y = 500 self.last_trigger_time = 0 self.min_interval = 0.5 # Minimum interval in seconds self.effects = [] # Create a window with a specific size and title self.window = pyglet.window.Window(width=1920, height=1080, caption='Campo di Battaglia RTS Isometrico') self.batch = pyglet.graphics.Batch() @self.window.event def on_draw(): self.window.clear() self.draw_battlefield() @self.window.event def on_mouse_scroll(x, y, scroll_x, scroll_y): # Adjust the view offset based on the scroll direction self.view_offset_y += scroll_y * 70 # Adjust the multiplier as needed self.editor_mode = False self.input_lock = False files = sorted(glob.glob("Tiles/**/*.png", recursive=True)) self.tiles = {os.path.splitext(os.path.basename(file))[0]: pyglet.image.load(file) for file in files} # self.battlefield = [[Cell(walkable = True, tile=self.tiles["landscapeTiles_067"] ) for x in range(self.width)] for y in range(self.height)] # use data to create the battlefield def create_sprite(tile, x, y): print(x, y) x,y= self.iso_transform(x, y) print(x, y) return pyglet.sprite.Sprite(tile, y=y, x=x) self.battlefield = [[Cell(walkable = not data[row][column], sprite=create_sprite(tile=self.tiles["landscapeTiles_067"], y=(self.height-row), x=(self.width-column)) if not data[row][column] else create_sprite(tile=self.tiles["landscapeTiles_066"], y=(self.height-row), x=(self.width-column)) ) for column in range(self.width)] for row in range(self.height)] # Crea lo sprite del tile, aggiungilo al batch (e al gruppo, se usato) # sprite = pyglet.sprite.Sprite(img=tile_image, x=x, y=y, batch=batch) # tile_sprites.append(sprite) # self.canvas.pack() # self.menu = Menu(self.canvas, tearoff=0) # self.window.bind('', self.on_key_press) # self.canvas.bind('', self.on_canvas_click) # self.canvas.bind('', self.on_canvas_right_click) # self.canvas.bind('', self.on_canvas_double_right_click) # self.canvas.bind('', self.calculate_coordinates) #self.knight = Knight(self, (1,1)) self.draw_battlefield() def calculate_coordinates(self, event): if self.input_lock: return # Get the mouse coordinates mouse_x = event.x mouse_y = event.y iso_x, iso_y = self.inv_iso_transform(mouse_x, mouse_y) self.cell_selected = (iso_x, iso_y) def get_direction(self, initial_coord, surrounding_coord): # Calcola la differenza tra le coordinate delta_x = surrounding_coord[0] - initial_coord[0] delta_y = surrounding_coord[1] - initial_coord[1] # Determina la direzione basandosi sulla differenza if delta_x == -1 and delta_y == 1: return 2 # Sud-Ovest elif delta_x == -1 and delta_y == 0: return 3 # Ovest elif delta_x == -1 and delta_y == -1: return 4 # Nord-Ovest elif delta_x == 0 and delta_y == -1: return 5 # Nord elif delta_x == 1 and delta_y == -1: return 6 # Nord-Est elif delta_x == 1 and delta_y == 0: return 7 # Est elif delta_x == 1 and delta_y == 1: return 8 # Sud-Est elif delta_x == 0 and delta_y == 1: return 1 # Sud else: return 1 def find_neighbors(self, coordinates): """ Find and return the cells adjacent to the cell at position (coordinates). Adjacent cells are those directly above, below, left, right, and all four diagonally adjacent cells. """ neighbors = [] x_coord, y_coord = coordinates # Check all eight possible directions for delta_x in [-1, 0, 1]: for delta_y in [-1, 0, 1]: new_x, new_y = x_coord + delta_x, y_coord + delta_y # Skip the cell itself if delta_x == 0 and delta_y == 0: continue # Check if the new coordinates are within the battlefield if 0 <= new_x < self.width and 0 <= new_y < self.height: neighbors.append((new_x, new_y)) return neighbors def get_closest_neighbor(self, neighbors_list, target_position): """ Find and return the neighbor cell in the neighbors_list closest to the target position. """ # If there are no neighbors, return None if not neighbors_list: return None # Calculate the distance between the target position and each neighbor distances = [abs(((neighbor[0] - target_position[0])**2 + (neighbor[1] - target_position[1])**2)**0.5) for neighbor in neighbors_list] # Find the index of the smallest distance min_distance_index = distances.index(min(distances)) # Return the neighbor corresponding to the smallest distance return neighbors_list[min_distance_index] def iso_transform(self, x, y): screen_x = (x-y)*self.cell_width/2 + self.view_offset_x screen_y = (x+y)*self.cell_height/2 + self.view_offset_y return screen_x, screen_y def inv_iso_transform(self, screen_x, screen_y): x = ((screen_x - self.view_offset_x) / (self.cell_width / 2) + (screen_y - self.view_offset_y) / (self.cell_height / 2)) / 2 y = ((screen_y - self.view_offset_y) / (self.cell_height / 2) - (screen_x - self.view_offset_x) / (self.cell_width / 2)) / 2 return int(x), int(y) def get_distance(self, position1, position2): x1, y1 = position1 x2, y2 = position2 return abs(((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5) def draw_battlefield(self): for y, row in list(enumerate(self.battlefield)): for x, cell in list(enumerate(row)): cell.sprite.draw() #self.canvas.create_image(screen_x, screen_y+45+offset, image=cell.tile, tags="cell") def draw_units(self): gif, screen_x, screen_y = self.knight.ai() # Calcola la posizione e l'animazione del cavaliere gif.x = screen_x - self.cell_width/2 gif.y = screen_y + height*3 gif.draw() #self.canvas.create_image(screen_x, screen_y+35, image=gif.next_frame(), tags="unit") # Disegna il cavaliere def draw_effects(self): # Pulisce gli effetti precedenti prima di ridisegnare self.canvas.delete("effect") self.canvas.delete("sel-cell") # Disegna gli effetti for effect in self.effects: if not effect.next_frame(self.canvas): self.effects.remove(effect) # Disegna il rettangolo di selezione cell_width = self.cell_width - 8 cell_height = self.cell_height - 4 x, y = self.iso_transform(*self.cell_selected) def draw_line(self, start, end): self.canvas.create_line(start[0], start[1], end[0], end[1], fill='red', tags="sel-cell", width=2) draw_line(self, (x, y), (x+cell_width/2, y+cell_height/2)) draw_line(self, (x+cell_width/2, y+cell_height/2), (x, y+cell_height)) draw_line(self, (x, y+cell_height), (x-cell_width/2, y+cell_height/2)) draw_line(self, (x-cell_width/2, y+cell_height/2), (x, y)) if self.editor_mode: self.canvas.create_text(55,15, text="EDITOR MODE", tags="effect", fill="blue") def on_key_press(self, event): current_time = time.time() step = 30 # Distanza dello spostamento ad ogni pressione dei tasti if current_time - self.last_trigger_time >= self.min_interval: # Check if the last trigger time is greater than the minimum interval if event.keysym == 'Up': self.view_offset_y += step elif event.keysym == 'Down': self.view_offset_y -= step elif event.keysym == 'Left': self.view_offset_x += step elif event.keysym == 'Right': self.view_offset_x -= step elif event.keysym == 'q': cell_x, cell_y = self.inv_iso_transform(event.x, event.y) self.battlefield[cell_y][cell_x].elevation -= 1 elif event.keysym == 'e': cell_x, cell_y = self.inv_iso_transform(event.x, event.y) self.battlefield[cell_y][cell_x].elevation += 1 elif event.keysym == '1': tiles_list = self.tiles.keys() self.input_lock = True for key, tile in enumerate(tiles_list): self.menu.add_command(label=tile, command=lambda vars=(tile, key) : self.set_tile(*vars)) self.menu.post(event.x_root, event.y_root) elif event.keysym == 'w': # Se si preme il tasto 'w' si cambia la walkability della cella cell_x, cell_y = self.inv_iso_transform(event.x, event.y) self.battlefield[cell_y][cell_x].walkable ^= True elif event.keysym == 'a': # Se si preme il tasto 'a' si cambia l'offset della cella cell_x, cell_y = self.inv_iso_transform(event.x, event.y) self.battlefield[cell_y][cell_x].offset += 9 elif event.keysym == 'd': # Se si preme il tasto 'd' si cambia l'offset della cella cell_x, cell_y = self.inv_iso_transform(event.x, event.y) self.battlefield[cell_y][cell_x].offset -= 11 elif event.keysym == '5': # Handle '5' key press pass elif event.keysym == 'Tab': # Handle tab key press self.editor_mode ^= True self.draw_battlefield() self.draw_units() self.draw_effects() self.last_trigger_time = current_time def on_canvas_click(self, event): # calculate the clicked cell's coordinates cell_x, cell_y = self.inv_iso_transform(event.x, event.y) self.battlefield[cell_y][cell_x].walkable ^= True self.draw_battlefield() self.draw_units() def on_canvas_right_click(self, event): # calculate the clicked cell's coordinates cell_x, cell_y = self.inv_iso_transform(event.x, event.y) self.effects.append(OrderClick(self.iso_transform(cell_x, cell_y),color="lightblue")) if 0 <= cell_x < self.width and 0 <= cell_y < self.height: self.knight.move_to((cell_x, cell_y)) def on_canvas_double_right_click(self, event): # calculate the clicked cell's coordinates cell_x, cell_y = self.inv_iso_transform(event.x, event.y) self.effects.append(OrderClick(self.iso_transform(cell_x, cell_y),color="darkblue")) if 0 <= cell_x < self.width and 0 <= cell_y < self.height: self.knight.run_to((cell_x, cell_y)) def set_tile(self, name, pos): # Handle option 1 selection self.input_lock = False print(f'You selected option {name}') cell_x, cell_y = self.cell_selected if 0 <= cell_x < self.width and 0 <= cell_y < self.height: self.battlefield[cell_y][cell_x].tile = self.tiles[name] self.draw_battlefield() def run(self): self.update() self.window.mainloop() class Cell: def __init__(self, walkable=False, sprite=None, elevation=0, offset=0): self.sprite = sprite self.walkable = walkable self.elevation = elevation if __name__ == "__main__": with open('maze.json', 'r') as file: data = json.load(file) # data is a boolean matrix, find dmensions width = len(data[0]) height = len(data) game = IsometricGame(width=width, height=height, data=data) pyglet.app.run()