from enum import Enum import random from typing import List from Interface.grid_draw import GridDraw, Colors import sys import pygame from Interface.movement import movement_key_press # window_dimensions says how many pixels window have # board_size says how many lines board have in one row def initial_draw(window_dimensions, board_size): # window name pygame.display.set_caption("AI Vacuum Cleaner") # define additional variables tile_size = window_dimensions / board_size # initialize board array newGrid = Grid(board_size, window_dimensions=window_dimensions, board_size=board_size) newGrid.add(objectOnTile(1, 1, acceptedType.PLAYER)) newGrid.add(objectOnTile(7, 8, acceptedType.ANIMAL)) newGrid.add(objectOnTile(2, 8, acceptedType.PLANT1)) newGrid.add(objectOnTile(4, 1, acceptedType.PLANT1)) newGrid.add(objectOnTile(3, 4, acceptedType.PLANT2)) newGrid.add(objectOnTile(8, 8, acceptedType.PLANT2)) newGrid.add(objectOnTile(9, 3, acceptedType.PLANT3)) player = newGrid.findFirst(acceptedType.PLAYER) newGrid.move(1, 1, 1, 2) newGrid.move(1, 2, 1, 1) # set window dimension window_width = window_dimensions window_height = window_dimensions # initialize drawer drawer = GridDraw(window_width, window_height) # rendering loop while True: drawer.start_draw() drawer.board(board_size, board_size) player = newGrid.findFirst(acceptedType.PLAYER) (x, y) = movement_key_press(board_size, player.position_x, player.position_y) newGrid.move(player.position_x, player.position_y, x, y) newGrid.render(drawer, newGrid=newGrid) drawer.end_draw() pygame.time.delay(30) # TODO wrap it all to another file that handles array rendering class acceptedType(Enum): EMPTY = "empty" PLAYER = "player" RUBBISH = "rubbish" PLANT1 = "plant1" PLANT2 = "plant2" PLANT3 = "plant3" ANIMAL = "animal" class objectOnTile: def __init__( self, position_x: int, position_y: int, type: acceptedType = acceptedType.EMPTY ): self.position_x = position_x self.position_y = position_y self.type = type # calculate position from array position to window position eg.: array_position = 0 => window_position = 50 (px) def _translate_array_to_window_position(array_position, tile_size_window) -> int: return array_position * tile_size_window + tile_size_window / 2 class Grid: def __init__(self, size_array, window_dimensions, board_size): self.array = [ [objectOnTile(i, j) for j in range(size_array)] for i in range(size_array) ] self.list: List[objectOnTile] = [] self.tile_size = window_dimensions / board_size self.board_size = board_size self.cat_last_tick = pygame.time.get_ticks() self.cat_cooldown = 1000 self.cat_velocity = 1 self.cat_busy = False #region images self.cat_front_image = pygame.transform.scale(pygame.image.load("Interface/images/cat/standing_front.png"), (self.tile_size, self.tile_size)) self.cat_back_image = pygame.transform.scale(pygame.image.load("Interface/images/cat/standing_back.png"), (self.tile_size, self.tile_size)) self.cat_left_image = pygame.transform.scale(pygame.image.load("Interface/images/cat/standing_left.png"), (self.tile_size, self.tile_size)) self.cat_right_image = pygame.transform.scale(pygame.image.load("Interface/images/cat/standing_right.png"), (self.tile_size, self.tile_size)) self.cat_current_image = self.cat_front_image self.plant1 = pygame.transform.scale(pygame.image.load("Interface/images/plants/plant1.png"), (self.tile_size + self.tile_size/4, self.tile_size + self.tile_size/4)) self.plant2 = pygame.transform.scale(pygame.image.load("Interface/images/plants/plant2.png"), (self.tile_size + self.tile_size/4, self.tile_size + self.tile_size/4)) self.plant3 = pygame.transform.scale(pygame.image.load("Interface/images/plants/plant3.png"), (self.tile_size + self.tile_size/4, self.tile_size + self.tile_size/4)) #endregion # render the array def render(self, drawer: GridDraw, newGrid): #tile_size = window_dimensions / board_size # render object with respect to type for item in self.list: if item.type == acceptedType.PLAYER: # constants for player PLAYER_RADIUS_RATIO = 3 PLAYER_COLOR = Colors.RED # position on screen render_x = _translate_array_to_window_position( item.position_x, self.tile_size ) render_y = _translate_array_to_window_position( item.position_y, self.tile_size ) # image rendering function drawer.circle( render_x, render_y, self.tile_size / PLAYER_RADIUS_RATIO, color=PLAYER_COLOR, ) if item.type == acceptedType.ANIMAL: now = pygame.time.get_ticks() #region cat random movement if now - self.cat_last_tick >= self.cat_cooldown: if self.cat_busy == False: while True: self.cat_direction = random.randint(0,3) if not((self.cat_direction == 0 and item.position_y == 0) or (self.cat_direction == 1 and item.position_x == self.board_size - 1) or (self.cat_direction == 2 and item.position_y == self.board_size - 1) or (self.cat_direction == 3 and item.position_x == 0)): break if self.cat_direction == 0: #up if self.cat_current_image == self.cat_back_image: newGrid.move(item.position_x, item.position_y, item.position_x, item.position_y - 1) self.cat_busy = False else: self.cat_busy = True self.cat_current_image = self.cat_back_image if self.cat_direction == 1: #right if self.cat_current_image == self.cat_right_image: newGrid.move(item.position_x, item.position_y, item.position_x + 1, item.position_y) self.cat_busy = False else: self.cat_busy = True self.cat_current_image = self.cat_right_image if self.cat_direction == 2: #down if self.cat_current_image == self.cat_front_image: newGrid.move(item.position_x, item.position_y, item.position_x, item.position_y + 1) self.cat_busy = False else: self.cat_busy = True self.cat_current_image = self.cat_front_image if self.cat_direction == 3: #left if self.cat_current_image == self.cat_left_image: newGrid.move(item.position_x, item.position_y, item.position_x - 1, item.position_y) self.cat_busy = False else: self.cat_busy = True self.cat_current_image = self.cat_left_image self.cat_last_tick = pygame.time.get_ticks() #endregion render_x = item.position_x * self.tile_size render_y = item.position_y * self.tile_size drawer.image(render_x, render_y, self.cat_current_image) if item.type == acceptedType.PLANT1: drawer.image((item.position_x - 0.1) * self.tile_size, (item.position_y - 0.25) * self.tile_size, self.plant1) if item.type == acceptedType.PLANT2: drawer.image((item.position_x - 0.1) * self.tile_size, (item.position_y - 0.25) * self.tile_size, self.plant2) if item.type == acceptedType.PLANT3: drawer.image((item.position_x - 0.1) * self.tile_size, (item.position_y - 0.25) * self.tile_size, self.plant3) # TODO act accordingly to other options(rubbish) # add new object on grid def add(self, newObject: objectOnTile): if ( self.array[newObject.position_x][newObject.position_y].type != acceptedType.EMPTY ): print( f"Cannot add object at ({newObject.position_x}, {newObject.position_y}): position already occupied" ) return self.array[newObject.position_x][newObject.position_y] = newObject self.list.append(newObject) # deletes object from game # untested, potentially not working def delete(self, position_x: int, position_y: int): # Find the object with the given position in the list for obj in self.list: if obj.position_x == position_x and obj.position_y == position_y: break else: # No object found with the given position print(f"No object found at ({position_x}, {position_y})") return # Remove the object from both the array and the list self.array[position_x][position_y] = objectOnTile(position_x, position_y) self.list.remove(obj) # move: update position from (start_x, start_y) to (end_x, end_y) def move(self, start_x: int, start_y: int, end_x: int, end_y: int): # no change if start_x == end_x and start_y == end_y: return #check if object moves beyond border if end_x > self.board_size - 1 or end_y > self.board_size - 1 or end_x < 0 or end_y < 0: print( f"Cannot move object beyond board" ) return # check if obj exist at starting position if self.array[start_x][start_y].type == acceptedType.EMPTY: print( f"Cannot move object at ({start_x}, {start_y}): no object on position" ) return # check if destination is empty if self.array[end_x][end_y].type != acceptedType.EMPTY: print( f"Cannot move object to ({end_x}, {end_y}): position already occupied" ) return # all OK # change position attribute in array self.array[start_x][start_y].position_x = end_x self.array[start_x][start_y].position_y = end_y # change position in array self.array[end_x][end_y] = self.array[start_x][start_y] self.array[start_x][start_y] = objectOnTile(start_x, start_y) def findFirst(self, find_type: acceptedType) -> objectOnTile: for item in self.list: if item.type == find_type: return item else: print(f"Cannot find object of type: ({find_type})!")