diff --git a/.idea/misc.xml b/.idea/misc.xml index a0f56f8..d37d1d2 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/img/tree.png b/img/tree.png new file mode 100644 index 0000000..a56c6b5 Binary files /dev/null and b/img/tree.png differ diff --git a/main.py b/main.py index dc03ae8..b5a5730 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,424 @@ import pygame +pygame.init() +# Game Constants +Ucelu = False + +SCREENX = 500 +SCREENY = 500 + +# SCREEN = pygame.display.set_mode([600, 600]) +# screen = pygame.display.set_mode((SCREENX, SCREENY)) +SCREEN = pygame.display.set_mode([600,650]) +pygame.display.set_caption('Inteligenty Traktor') + +# COLORS +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +RED = (255, 0, 0) +GREEN = (0, 255, 0, 0) +BLUE = (0, 0, 255) +GREY = (128, 128, 128) + +CLOCK = pygame.time.Clock() +FPS = 300 +DELAY = 100 + +GRIDX = 10 +GRIDY = 10 + + +obstacleObjects = {} # Store the obstacle objects (Blocks on the path) from Obstacle class +gridObjects = {} # Store grid-box objects from Grid Class +gridObstacle = {} # Store the grid:obstacle pair stuck together +boxObjects = {} +boxes = 1 +obstacles = 1 + + +# BFS Variables +startNode = 0 +goalNode = 0 +graph = dict() +pathFound = [] # Store the path in a list box index to draw on later + +class BFS: + # Finds a suitable path from point A to point B using Breadth-First-Search Algorithm + def __init__(self, graph, start, goal): + self.graph = graph + self.start = start + self.goal = goal + + def solve(self): + print('Start\n\n') + print(self.graph) + print('\n\n') + # keep track of explored nodes + explored = [] + + # keep track of all paths to be checked + queue = [[self.start]] + + # return path if start is goal + if self.start == self.goal: + return 'That was easy. Start == Goal' + + # keep looping until all possible paths are explored + while queue: + # pop the first path from the queue + path = queue.pop(0) + # get the last node from the path + node = path[-1] + + if node not in explored: + neighbors = self.graph[node] + # go through all neighbor nodes + # push it into the queue + for neighbor in neighbors: + new_path = list(path) + new_path.append(neighbor) + queue.append(new_path) + + if neighbor == self.goal: + return new_path + + # mark node as explored + explored.append(node) + + # in case there is no path + return "path not accessible" +class Grid(object): + def __init__(self, x, y, sx, sy): + self.x = x + self.y = y + self.sx = sx + self.sy = sy + self.width = 1 + def draw(self): + pygame.draw.rect(SCREEN, BLACK, (self.x, self.y, self.sx, self.sy), self.width) + +class Box(object): + def __init__(self, x, y, sx, sy, color): + self.x = x + self.y = y + self.sx = sx + self.sy = sy + self.color = color + + def draw(self): + pygame.draw.rect(SCREEN, self.color, pygame.Rect(self.x, self.y, self.sx, self.sy)) + +class Obstacle(object): + def __init__(self, mouseObj): + self.mseX = mouseObj[0] + self.mseY = mouseObj[1] + + for grid in gridObjects: + g = getGridBoxes(grid) + self.x = g.x + self.y = g.y + self.sx = g.sx + self.sy = g.sy + if self.mseX > self.x and self.mseX < self.x + self.sx: + if self.mseY > self.y and self.mseY < self.y + self.sy: + self.posX = self.x + self.posY = self.y + self.gridBox = grid + + def draw(self): + # pygame.draw.rect(SCREEN, GREY, pygame.Rect(self.posX, self.posY, self.sx, self.sy)) + SCREEN.blit(imgTree, (self.posX, self.posY)) +def getGridBoxes(grid_box): + return gridObjects[grid_box] +def drawGrid(sizex,sizey): + spaceX = SCREENX // sizex + spaceY = SCREENY // sizey + width = 2 + + counter = 1 + for i in range(sizex): + for j in range(sizey): + # g = Grid(i*spaceX, j*spaceY, spaceX, spaceY) + g = Grid(50 + i*50, 50 + j*50, spaceX, spaceY) + gridObjects[counter] = g + counter += 1 +def generateGraph(row,col): + # This function generates a graph based on the gridObjects instantiated! + sample_graph = {'A':['B','C','E'], + 'B':['A','D','E'], + 'C':['A','F','G'], + 'D':['B'], + 'E':['A','B','D'], + 'F':['C'], + 'G':['C'] + } + + miniG = {} + for grid in range(len(gridObjects)): + grid += 1 # Synchronize index + mod = grid % col # Used to check the Top and Bottom Grid Boxes! + gN = grid - 1 + gS = grid + 1 + gE = grid + col + gW = grid - col + + + # CHECK THE NEIGHBORS TO THE GRID-BOXES, ACCOUNTING FOR THE EXTREME GRID-BOXES(BORDERS) + if mod == 0: # 5,10,15,20,25 - You can't go south from here (Bottom Boxes) + if grid > col: # Away from the Left Border of the Screen + if grid > (col*row)-col: # You are on the Right Border of the screen - You can't go East + miniG[grid] = [gN, gW] + else: # Away from the Right Border of the Screen - You can go East + miniG[grid] = [gN, gE, gW] + else: # You are on the Left Edge of the screen - You can't go West + miniG[grid] = [gN, gE] + + elif mod == 1: # 6,11,16,21 :> You can't go North from here (Top Boxes) + if grid > col: # Away from the Left Border of the Screen + if grid > (col*row)-col: # You are on the Right Border of the screen - You can't go East + miniG[grid] = [gS, gW] + else: # Away from the Right Border of the Screen - You can go east + miniG[grid] = [gS, gE, gW] + else: # You are on the Left Edge of the screen - You can't go West + miniG[grid] = [gS, gE] + + else: # All the rest (Not Top or Bottom Boxes) - You can go North or South + if grid > col: # Away from the Left Border of the Screen + if grid > (col*row)-col: # You are on the Right Border of the screen - You can't go East + miniG[grid] = [gN, gS, gW] + else: # Away from the Right Border of the Screen - You can go East + miniG[grid] = [gN, gS, gE, gW] + else: # You are on the Left Edge of the screen - You can't go West + miniG[grid] = [gN, gS, gE] + + + # FILTER OUT OBSTACLES FROM THE GRAPH + miniG2 = {} + for grid in range(len(gridObjects)): + grid += 1 + if grid not in gridObstacle: + # gridObjects.remove(grid) # Dict object has no attribute : 'remove' + # HACK + miniG2[grid] = miniG[grid] # Created a new dictionary that stored the values required + # IN-DEPTH FILTER - Filter out obstacles from the neighbors-list + for neigbor in miniG2[grid]: + if neigbor in gridObstacle: + miniG2[grid].remove(neigbor) + + + # Filtering again as the first Filter block didn't clear out everything + # Filtering through the neighbors + for grid in miniG2: + for item in miniG2[grid]: + if item in gridObstacle: + miniG2[grid].remove(item) + + + + + return miniG2 + + +def drawGraph(pathF, Ucelu): + #Draws the path given the path-list + print(pathF) + if Ucelu == False: + for grid in pathF: + g = gridObjects[grid] # Get the grid-box object mentioned in the path + x = g.x + y = g.y + sx = g.sx + sy = g.sy + # pygame.draw.rect(SCREEN, GREEN, pygame.Rect(x, y, sx, sy)) + player.x = x/50 - 1 + player.y =y/50 - 1 + + # ----------------------------- + i = 0 + while i < len(T): + j = 0 + while j < len(T[i]): + #color = (255, 255, 255, 0) + if T[i][j].isWet == 0: + # a = 1 + color = (160, 80, 40, 0) + else: + # a = 1 + color = (50, 25, 0, 0) + + #Covers 'player' on the way + pygame.draw.rect(SCREEN, color, pygame.Rect(50 + 50 * i, 50 + 50 * j, 50, 50)) + if T[i][j].plantType == 1: + SCREEN.blit(imgWheat, (50 + 50 * i, 50 + 50 * j)) + if T[i][j].plantType == 2: + SCREEN.blit(imgCarrot, (50 + 50 * i, 50 + 50 * j)) + if T[i][j].plantType == 3: + SCREEN.blit(imgCabbage, (50 + 50 * i, 50 + 50 * j)) + if T[i][j].plantType == 4: + SCREEN.blit(imgTree, (50 + 50 * i, 50 + 50 * j)) + + j = j + 1 + i = i + 1 + + # Render the trees + for obs in obstacleObjects: + obstacleObjects[obs].draw() + + for bx in boxObjects: + boxObjects[bx].draw() + + i = 0 + while i < len(T)+1: + pygame.draw.line(SCREEN, (0, 0, 0), (50 + i * 50, 50), (50 + i * 50, 50 + len(T) * 50), 1) + pygame.draw.line(SCREEN, (0, 0, 0), (50, 50 + i * 50), (50 + len(T) * 50, 50 + i * 50), 1) + i = i + 1 + + tmpImg = pygame.transform.rotate(imgPlayer, player.rotation) + if player.rotation == 180: + tmpImg = pygame.transform.flip(tmpImg, True, True) + tmpImg = pygame.transform.flip(tmpImg, True, False) + + #player is seen on the way + SCREEN.blit(tmpImg, (55 + 50 * player.x, 55 + 50 * player.y)) + + # -------------------------------------- + + # tmpImg = pygame.transform.rotate(imgPlayer, player.rotation) + # # if flip: + # # if flip == True: + # if player.rotation == 180: + # tmpImg = pygame.transform.flip(tmpImg, True, True) + # tmpImg = pygame.transform.flip(tmpImg, True, False) + # + # SCREEN.blit(tmpImg, (55 + 50 * player.x, 55 + 50 * player.y)) + + pygame.display.update() + pygame.time.wait(300) + #SCREEN.fill((WHITE)) + # pygame.time.wait(50) + # pygame.draw.rect(SCREEN, WHITE, pygame.Rect(x, y, sx, sy)) + Ucelu = True +def UIHandler(mouseObj, Ucelu): + # drawGrid(GRIDX, GRIDY) + drawGrid(10,10) + + for grid in gridObjects: + gridObjects[grid].draw() + + for bx in boxObjects: + boxObjects[bx].draw() + + for obs in obstacleObjects: + obstacleObjects[obs].draw() + + if pathFound: + if Ucelu == False: + drawGraph(pathFound, Ucelu) + Ucelu = True + +def eventHandler(kbdObj,mouseObj, Ucelu): + global boxes + global obstacles + global startNode + global goalNode + global pathFound + + + # If Key_f is pressed, set goal node + if kbdObj[pygame.K_f]: + gBox = getGridBoxes(int(len(gridObjects))) + # gBox = getGridBoxes() + + x = mouseObj[0] + y = mouseObj[1] + # x = gBox.x + # y = gBox.y + sx = gBox.sx + sy = gBox.sy + # ---------------------------------------- + mseX = mouseObj[0] + mseY = mouseObj[1] + + for grid in gridObjects: + g = getGridBoxes(grid) + x = g.x + y = g.y + sx = g.sx + sy = g.sy + if mseX > x and mseX < x + sx: + if mseY > y and mseY < y + sy: + posX = x + posY = y + gridBox = grid + + # SCREEN.blit(imgTree, (posX, posY)) + + # --------------------------------------- + bo = Box(posX, posY, sx, sy, BLUE) + boxObjects[boxes] = bo + # boxes += 1 + boxes = 1 + # goalNode = GRIDX*GRIDX + # goalNode = (10 * (x + 1) + (y + 1) - 10) + goalNode = (10 * (posX/50 ) + (posY/50) - 10) + + # goalNode = (x/sx) * (y/sy) + # Delay to avoid multiple spawning of objects + pygame.time.wait(DELAY) + # If Key_x is pressed, spawn tree + if kbdObj[pygame.K_x]: + obs = Obstacle(mouseObj) + obstacleObjects[obstacles] = obs + # print(obs.gridBox) + obstacles += 1 + # print(obstacleObjects) + gridObstacle[obs.gridBox] = obstacles + # Delay to avoid multiple spawning of objects + pygame.time.wait(DELAY) + + + # if Key_SPACE is pressed, start the magic + if kbdObj[pygame.K_SPACE]: + gBox = getGridBoxes(1) + + x = gBox.x + y = gBox.y + sx = gBox.sx + sy = gBox.sy + + x = (player.x +1) * 50 + y = (player.y +1) * 50 + + # tmpImg = pygame.transform.rotate(imgPlayer, player.rotation) + # SCREEN.blit(tmpImg, (50 + 50 * player.x, 50 + 50 * player.y)) + # pygame.display.update() + + #when on it keeps flashing - among others + #bo = Box(x, y, sx, sy, RED) + #boxObjects[boxes] = bo + + # boxes += 1 + boxes = 1 + startNode = (10 * (player.x + 1) + (player.y + 1) - 10) + # startNode = (((player.x + 1)*10 - 9) * (player.y + 1) ) + # startNode = 2 + + # tmpImg = pygame.transform.rotate(imgPlayer, player.rotation) + # SCREEN.blit(tmpImg, (55 + 50 * player.x, 55 + 50 * player.y)) + # pygame.display.update() + + # Delay to avoid multiple spawning of objects + #pygame.time.wait(DELAY) + + graph = generateGraph(GRIDY,GRIDX) + bfs = BFS(graph, startNode, goalNode) + # print(bfs.solve()) + pathFound = bfs.solve() + + # Delay to avoid multiple spawning of objects + pygame.time.wait(DELAY) + #With it it keeps going, if without it turns off + Ucelu = False class Field: def __init__(self, fieldType, plantType, isWet, wetTime, isFertilized, fertilizedTime): @@ -39,18 +458,25 @@ T = [[Field(1,0,0,0,0,0),Field(0,0,1,0,0,0),Field(1,1,1,0,0,0),Field(1,2,0,0,0,0 [Field(1,0,0,0,0,0),Field(0,0,1,0,0,0),Field(1,1,1,0,0,0),Field(1,2,0,0,0,0),Field(0,3,1,0,0,0),Field(0,0,0,0,0,0),Field(0,0,0,0,0,0),Field(1,0,1,0,0,0),Field(1,0,0,0,0,0),Field(1,0,1,0,0,0)], [Field(1,0,0,0,0,0),Field(0,0,1,0,0,0),Field(1,1,1,0,0,0),Field(1,2,0,0,0,0),Field(0,3,1,0,0,0),Field(0,0,0,0,0,0),Field(0,0,0,0,0,0),Field(1,0,1,0,0,0),Field(1,0,0,0,0,0),Field(1,0,1,0,0,0)]] -pygame.init() +#pygame.init() player = Player() -screen = pygame.display.set_mode([600, 600]) +# player.x = 2 +# player.y = 2 + +#screen = pygame.display.set_mode([600, 600]) running = True -clock = pygame.time.Clock() +# clock = pygame.time.Clock() + + +SCREEN.fill((WHITE)) while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False + if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: if player.x > 0: @@ -65,42 +491,118 @@ while running: if player.y < 9: player.y = player.y + 1 - screen.fill((175, 255, 50)) + # Aga start lewo prawo, naprzód + if event.key == pygame.K_a: + player.rotation = (player.rotation + 90) % 360 + + if event.key == pygame.K_d: + player.rotation = (player.rotation - 90) % 360 + + if event.key == pygame.K_w: + if player.rotation == 0: + if player.x < 9: + player.x = player.x + 1 + + if player.rotation == 180: + if player.x > 0: + player.x = player.x - 1 + + if player.rotation == 270: + if player.y < 9: + player.y = player.y + 1 + + if player.rotation == 90: + if player.y > 0: + player.y = player.y - 1 + # left, right, forward + + # if it's not here, it leaves a trail WELL NOT ANYMORE + #SCREEN.fill((WHITE)) + kbd = pygame.key.get_pressed() + # kbd = event.key() + mse = pygame.mouse.get_pos() + + # SCREEN.fill((WHITE)) + Ucelu = False + UIHandler(mse, Ucelu) + eventHandler(kbd, mse, Ucelu) + pygame.display.update() + # CLOCK.tick(FPS) + + #screen.fill((175, 255, 50, 0)) + #screen.fill((WHITE)) imgWheat = pygame.image.load('img/wheat.png') imgCarrot = pygame.image.load('img/carrot.png') imgCabbage = pygame.image.load('img/cabbage.png') imgPlayer = pygame.image.load('img/player.png') + imgTree = pygame.image.load('img/tree.png') i = 0 while i < len(T): j = 0 while j < len(T[i]): - color = (0, 0, 0) + # color = (255, 255, 255, 0) if T[i][j].isWet == 0: - color = (160, 80, 40) + # a = 1 + color = (160, 80, 40, 0) else: - color = (50, 25, 0) - pygame.draw.rect(screen, color, pygame.Rect(50 + 50 * i, 50 + 50 * j, 50, 50)) + # a = 1 + color = (50, 25, 0, 0) + #colour from the beginning + pygame.draw.rect(SCREEN, color, pygame.Rect(50 + 50 * i, 50 + 50 * j, 50, 50)) if T[i][j].plantType == 1: - screen.blit(imgWheat, (50 + 50 * i, 50 + 50 * j)) + SCREEN.blit(imgWheat, (50 + 50 * i, 50 + 50 * j)) if T[i][j].plantType == 2: - screen.blit(imgCarrot, (50 + 50 * i, 50 + 50 * j)) + SCREEN.blit(imgCarrot, (50 + 50 * i, 50 + 50 * j)) if T[i][j].plantType == 3: - screen.blit(imgCabbage, (50 + 50 * i, 50 + 50 * j)) + SCREEN.blit(imgCabbage, (50 + 50 * i, 50 + 50 * j)) + if T[i][j].plantType == 4: + SCREEN.blit(imgTree, (50 + 50 * i, 50 + 50 * j)) + + j = j + 1 i = i + 1 i = 0 while i < len(T)+1: - pygame.draw.line(screen, (0, 0, 0), (50 + i * 50, 50), (50 + i * 50, 50 + len(T) * 50), 5) - pygame.draw.line(screen, (0, 0, 0), (50, 50 + i * 50), (50 + len(T) * 50, 50 + i * 50), 5) + pygame.draw.line(SCREEN, (0, 0, 0), (50 + i * 50, 50), (50 + i * 50, 50 + len(T) * 50), 1) + pygame.draw.line(SCREEN, (0, 0, 0), (50, 50 + i * 50), (50 + len(T) * 50, 50 + i * 50), 1) i = i + 1 tmpImg = pygame.transform.rotate(imgPlayer, player.rotation) - screen.blit(tmpImg, (55 + 50 * player.x, 55 + 50 * player.y)) - pygame.display.flip() -# clock.tick(30) + if player.rotation == 180: + tmpImg = pygame.transform.flip(tmpImg, True, True) + tmpImg = pygame.transform.flip(tmpImg, True, False) + + #player seen at the beginning + SCREEN.blit(tmpImg, (55 + 50 * player.x, 55 + 50 * player.y)) + + # set Start Node where the Player is located + # gBox = getGridBoxes(1) + # x = gBox.x + # y = gBox.y + # sx = gBox.sx + # sy = gBox.sy + # bo = Box(x, y, sx, sy, RED) + # boxObjects[boxes] = bo + # boxes += 1 + # startNode = 1 + # # Delay to avoid multiple spawning of objects + # pygame.time.wait(DELAY) + + font = pygame.font.SysFont('comicsans', 18) + label = font.render('f- punkt końcowy, x- drzewa, spacja- uruchomienie', 1, (0, 0, 0)) + label1 = font.render('strzałki-ręczne poruszanie traktorem,', 1, (0, 0, 0)) + label2 = font.render('a- obrót w lewo, d- w prawo, w-ruch naprzód', 1, (0, 0, 0)) + SCREEN.blit(label, (10, 570)) + SCREEN.blit(label1, (10, 590)) + SCREEN.blit(label2, (10, 610)) + + # pygame.display.flip() + + pygame.display.update() + CLOCK.tick(FPS) # Done! Time to quit. -pygame.quit() +pygame.quit() \ No newline at end of file