From e8bf3725fcbf6ea65efc5bbd1f7c58dbf520c838 Mon Sep 17 00:00:00 2001 From: Weranda Date: Thu, 4 May 2023 14:06:31 +0200 Subject: [PATCH] =?UTF-8?q?dodanie=20trawy=20(wi=C4=99kszy=20koszt)=20i=20?= =?UTF-8?q?porz=C4=85dek=20w=20kodzie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- __pycache__/agent.cpython-310.pyc | Bin 5966 -> 5966 bytes __pycache__/bfs.cpython-310.pyc | Bin 4695 -> 4577 bytes __pycache__/config.cpython-310.pyc | Bin 382 -> 383 bytes __pycache__/health_flower.cpython-310.pyc | Bin 991 -> 991 bytes __pycache__/map_add_ons.cpython-310.pyc | Bin 965 -> 2192 bytes __pycache__/mobs.cpython-310.pyc | Bin 0 -> 2276 bytes archer_ork.py | 29 --- bfs.py | 193 ++++++++++++++++++ config.py | 7 +- health_flower.py | 28 --- infantry_ork.py | 29 --- infantry_ork2.py | 29 --- main.py | 235 ++++------------------ map_add_ons.py | 59 +++++- mobs.py | 113 +++++++++++ sauron.py | 29 --- zdjecia/grass.png | Bin 0 -> 29487 bytes 17 files changed, 404 insertions(+), 347 deletions(-) create mode 100644 __pycache__/mobs.cpython-310.pyc delete mode 100644 archer_ork.py create mode 100644 bfs.py delete mode 100644 health_flower.py delete mode 100644 infantry_ork.py delete mode 100644 infantry_ork2.py create mode 100644 mobs.py delete mode 100644 sauron.py create mode 100644 zdjecia/grass.png diff --git a/__pycache__/agent.cpython-310.pyc b/__pycache__/agent.cpython-310.pyc index 562bc61d4b26be3dec0ced5411c101c2c863bfcb..01ab84c86068082c5a7e0dbd746015e362ed6b18 100644 GIT binary patch delta 20 acmX@7cTSHxpO=@50SKEDiuX&;@e< delta 20 acmX@7cTSHxpO=@50SH90gEn$Iivs{QQUrbg diff --git a/__pycache__/bfs.cpython-310.pyc b/__pycache__/bfs.cpython-310.pyc index db4bae0c2d167c235f243f782a911dfcc1aa149a..6fbdb95f8b79c85253395cfb62e5d4b3311e52ee 100644 GIT binary patch literal 4577 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 IAv6ag03`4tsQ>@~ delta 204 zcmey*^pA-*pO=@50SKBhgHpCmq8L(`q8L+{W0<0tqL@=yqF7Q` zqgYeeqS#WIQdy)JqS#Z|qc~DHqBv6+gBdhAUxLi>dnpGbHJM&IFf%X|0Wrf%2ao`B z5hIX75Sq*{|APcrVZ=)&AnPR~FObyay2VydnVy)NI&qaTD&FU}555WC24E&A|u&Xu&3L diff --git a/__pycache__/health_flower.cpython-310.pyc b/__pycache__/health_flower.cpython-310.pyc index d596565ec6a3fbae46893553f37454817a12daf8..3ce0c1370c6716668978f864faa06fdabde9fa35 100644 GIT binary patch delta 20 acmcc5exIE?pO=@50SJ~)3*N|mg&6=jb_I?A delta 20 acmcc5exIE?pO=@50SJV%gEn$sVFmy+V+76s diff --git a/__pycache__/map_add_ons.cpython-310.pyc b/__pycache__/map_add_ons.cpython-310.pyc index 1b7c964115001f15f3e219edeac761b7c7e79257..e0a5378d87b284bafee6b6607d81f22582432b26 100644 GIT binary patch literal 2192 zcmdT_OK&4Z5bmCr$IjTBINrP#P~ZSEB3TK6cxbiCvIG+moXB2;uq?HP>G5Q|V~^<` zv)J;D{T;|T<_~b>z|ZI#;*|5=I8oJ(6N6$v;496K;j1Yjn*Y&6Wk6%^l#JYt9BP$6esu zYtG@cNviov7?sqkRMEEsG#4KOoC9btDgYsAQBGP0r`&i>S|&Fk-BNZV4W7yXzjFSd zjqNcs`7^+TP6#6t(j{HAjLhs>U3=0fb-*=l>N(J_aO<4Hd}!Z2#~C-kcA;&+ z+@zb=R-O}BoLwK6_wSE+Hw4i7v_zvt?H(-BEJ_Z z4^x>Oh&T(Saw3rq2k;(@bgwh(P)<_^D3`IgA7_lI{F9^OL)JWM9V+^Rq9bKLi+OgY zoU<^F&N5}kJwFPSm83pzDB~)L*oD_0p9CMbzmlPl?e{+X z;NADzC;jkK5q}@HPlw4M&e}2?^4M=TkM<(rw`;=RYaX?G{($+Mv$QYw2P1I@2EtvG zuc1K;v}_cN0(Ib5GRm}KtWuA9z?A5?q-C~0-*XRp0T;ds;S$YG631O&qSc&`xwf_oXFQM9PxCfir7T~s4zEdBs z-zXnWP{M)rBVps#m)KPPlixmv=5Q+#T1UzrCif}C_v5qd57jYM1 z1E7_!H6As!l*J~JTS(fP6x&GbAlyTE1>scyWd*6s)XFUN_|Z3q4dt-JAB94oy#9Xv z_$|B8;nG(+y!u;VwIOF33Rmam!tkKdfJ0wKf>{^DwQdaspjsKPRHFQQRP0EmCJ|tza{Y&yTpZhTiMyV_a|F@$OZra delta 502 zcmZvZ%SyvQ6o%)Lq)F5Cl2%)>x~i9;v|B+Dm#*CS0Ht)&(%3d-5;rAKAHk3pNER+! z3%-GS-Dc^|xA2@=5W&Ft`2Rn1=FBjUwYNgqx2z(8&woDk6(c6@bGeMU8Oyul@;IxiTKi+}s>YjcGqv z$Vuo1$tQi?b(CBQ-04WF*j+|c0MA6WlNWYfErHRXf_)U!PCg1dNr%^|lbrFxCH|J} zzt}^|0eG$ep_39@Cypu&@VPeh=cCD3;*&`ef$RUDZ(N z@z(r}O7K>GLH|ad=e18f?^~aG&d>#Kvgt-zqxpQ!nR7hj@0(+SOvWH^{rP*9{*fW% zZ*=093eFLXkOELbC7;yrF8k6sIVDt~>PtdZm$c=!@|#jqA(o&T#I!{$0kI_2A*L^4 z8pKl6fS9p}C8<;;`Sc7{BIUfqrOzBRz)&y7F20H~~8`dUmLs$k)z|0QSz}pe~+NA{EJy{;^7VZvd+jTtqF1)|x z_nl$adtT^un^Spq1TW2!08^PsXd_IOr7f%(MrTEU{2o`EcE{yu+xM-o$Gpf5!CCMd za;?dNeh==wfymV6SzN1%Y_40D*YzUH;;Hk};}fe|s-1A@S1t{B;unubEv~g(ui1)t z!t2;gm#cnY)7r{$<>B`y73-|>$SVDC%2N@uyI~_>9i9js+jncmGJ_|peb%rYD1PR9 z5jR6OvYfyN0^9-Do8U3miMT2-;kz$fpKH{{^`Zh`h0}m;!0gL}sbmu)7f({BIkv1ZKmr+q-h? z4tt*Kw1UXSbH_B?hK`T|m|+XEG(diDPC9&c2+w%2^+L9aNoxq}2w4QAlVRU4Wn$at z?jY;cr)O6Bj4%jcD!E>92J$GHQXGvjmY9gM$=@E*eZ2zL-rF!mwBM+kTn<{&7= zjfjj-!5D7FnOf?`@{6KZ$_p?d);q)u^lnrm6JMkF#;@8!j{WQ9C|;)r3jVqtD_8U= z-b#@5IO#>~=a?dyE0ed8~jkYwu$U2mhw=TLhe>xCxh-KdFHwfijS-YiCLDMlzt zu2TWK^K})H^Mc2>qTi?qXI4*pOWRX8u)tfd5<}e#v#B!}m3}pF7w&_!p6~(Sra0 literal 0 HcmV?d00001 diff --git a/archer_ork.py b/archer_ork.py deleted file mode 100644 index 44badb0..0000000 --- a/archer_ork.py +++ /dev/null @@ -1,29 +0,0 @@ -import pygame -from config import * - -class Archer_ork(pygame.sprite.Sprite): - - - def __init__(self, game, x, y): - self.game = game - self.groups = self.game.all_sprites, self.game.archer_orks - pygame.sprite.Sprite.__init__(self, self.groups) - - self.x = x * TILE_SIZE - self.y = y * TILE_SIZE - self.width = TILE_SIZE - self.height = TILE_SIZE - - self.ARCHER_ORK_IMG = pygame.image.load("./zdjecia/ork_lucznik.png") - self.ARCHER_ORK = pygame.transform.scale(self.ARCHER_ORK_IMG,(64,64)) - - self.image = pygame.Surface([self.width, self.height]) - self.image.blit(self.ARCHER_ORK, (0,0)) - self.image.set_colorkey((0, 0, 0)) - - self.rect = self.image.get_rect() - self.rect.x = self.x - self.rect.y = self.y - - self.level = 1 - self.damage = 50*self.level \ No newline at end of file diff --git a/bfs.py b/bfs.py new file mode 100644 index 0000000..b4ae2e3 --- /dev/null +++ b/bfs.py @@ -0,0 +1,193 @@ +import pygame +from config import * +class Bfs: + + def __init__(self,game): + + self.game = game + + self.open_queue = [] + self.close_queue = [] + self.wall_cells = [] + self.enemy_cells = [] + + def bfs(self): + print("x: ", self.game.agent.x, "y: ", self.game.agent.y) + + self.open_queue.append(self.get_cell_number(self.game.agent.x,self.game.agent.y)) + # tutaj dodaje się cel agenta + goal_cell = self.get_cell_number(self.game.flower.x,self.game.flower.y) + + path = [] + processing = True + find_path = False + while processing: # główna pętla + for event in pygame.event.get(): + if event.type == pygame.QUIT: + exit() + + if len(self.open_queue) > 0 : + current_node_cell = self.open_queue.pop(0) + + if(current_node_cell in self.close_queue): + continue + + print("Aktualna kratka: ", current_node_cell) + print("Cel znajduje się na kratce: ", goal_cell) + + if (current_node_cell == goal_cell): + self.close_queue.append(current_node_cell) + found_goal_cell = current_node_cell + print("Znaleziono cel, szukanie drogi z odwiedzonych węzłów, kolejka odwiedzonych:", self.close_queue) + processing = False + find_path = True + self.game.clock.tick(2) + else: + child_node_cells = self.get_child_nodes(current_node_cell) + self.close_queue.append(current_node_cell) + print("Sąsiedzi: ", child_node_cells) + for child_node in child_node_cells: + if child_node not in self.open_queue and child_node not in self.close_queue: + self.open_queue.append(child_node) + print("Kolejka: ", self.open_queue, "\n") + else: + print("Brak nowych węzłów, kolejka: ",self. open_queue) + print("Odwiedzone : ", self.close_queue) + return self.close_queue + + dead_end_nodes = [] + while find_path: + path.append(self.close_queue[0]) + + for i in range(len(self.close_queue) -1): + from_cell = path[-1] + to_cell = self.close_queue[i+1] + + if to_cell in dead_end_nodes: + continue + + if self.verify_move(from_cell, to_cell): + path.append(to_cell) + + if path[-1] == found_goal_cell: + find_path = False + else: + dead_end_nodes.append(path[-1]) + path = [] + + print("Droga: ", path) + self.move_agent(path) + + + def get_cell_number(self,x, y): #zamienia koordynaty na numer kratki + cell_number = None + cell_number =(x // TILE_SIZE) + (NUM_ROWS * (( y// TILE_SIZE))) + return cell_number + + def get_child_nodes(self,cell_number): + children = [] + up = self.get_up_cell(cell_number) + if up is not None and up not in self.wall_cells and up not in self.enemy_cells: + children.append(up) + + right = self.get_right_cell(cell_number) + if right is not None and right not in self.wall_cells and up not in self.enemy_cells: + children.append(right) + + down = self.get_down_cell(cell_number) + if down is not None and down not in self.wall_cells and up not in self.enemy_cells: + children.append(down) + + left = self.get_left_cell(cell_number) + if left is not None and left not in self.wall_cells and up not in self.enemy_cells: + children.append(left) + + return children + + + def get_up_cell(self,cell_number): + cell_row_number = cell_number // NUM_ROWS + if (cell_row_number - 1 < 0): + return None + else: + return (cell_number - NUM_ROWS) + + def get_right_cell(self,cell_number): + cell_column_number = cell_number % NUM_ROWS + if (cell_column_number + 1 >= NUM_ROWS): + return None + else: + return (cell_number + 1) + + def get_down_cell(self,cell_number): + cell_row_number = cell_number // NUM_ROWS + if (cell_row_number + 1 >= NUM_ROWS): + return None + else: + return (cell_number + NUM_ROWS) + + def get_left_cell(self,cell_number): + cell_column_number = cell_number % NUM_ROWS + if (cell_column_number - 1 < 0): + return None + else: + return (cell_number - 1) + + def verify_move(self,from_cell, to_cell): #sprawdzenie czy ruch jest poprawny czyt. czy następna kratka to przeszkoda lub mob + if (to_cell in self.wall_cells or to_cell in self.enemy_cells): + return False + + if(from_cell + 1 == to_cell): + return True + + if(from_cell - 1 == to_cell): + return True + + if(from_cell - NUM_ROWS == to_cell): + return True + + if(from_cell + NUM_ROWS == to_cell): + return True + + return False + + def move_agent(self,path): + for cell_to_move in path: + x, y = self.get_coordinates(cell_to_move) + print("Ruch do kratki : ", cell_to_move, " z x: ", x, ", y: ", y, ", agent.x: ", self.game.agent.rect.x, ", agent.y: ", self.game.agent.rect.y) + if(self.get_cell_number(self.game.agent.x,self.game.agent.y)!=cell_to_move): + if x > self.game.agent.rect.x: + self.game.agent.direction = 0 + elif y > self.game.agent.rect.y: + self.game.agent.direction = 1 + elif x < self.game.agent.rect.x: + self.game.agent.direction = 2 + elif y < self.game.agent.rect.y: + self.game.agent.direction = 3 + if self.game.agent.direction==0: + print("DIRECTION: "+self.game.agent.AGENT_IMAGES[self.game.agent.direction]) + self.game.agent.x_change += TILE_SIZE + elif self.game.agent.direction==1: + print("DIRECTION: "+self.game.agent.AGENT_IMAGES[self.game.agent.direction]) + self.game.agent.y_change += TILE_SIZE + elif self.game.agent.direction==2: + print("DIRECTION: "+self.game.agent.AGENT_IMAGES[self.game.agent.direction]) + self.game.agent.x_change -= TILE_SIZE + elif self.game.agent.direction==3: + print("DIRECTION: "+self.game.agent.AGENT_IMAGES[self.game.agent.direction]) + self.game.agent.y_change -= TILE_SIZE + + self.game.agent.rotate() + self.game.update() + self.game.map() + + print("Położenie agenta: agent.x: ", self.game.agent.rect.x, ", agent.y: ", self.game.agent.rect.y) + self.game.clock.tick(2) + + def get_coordinates(self,cell_to_move): #zamienia numer kratki na koordynaty + cell_row_number = cell_to_move // NUM_ROWS + cell_column_number = cell_to_move % NUM_ROWS + + y = cell_row_number * TILE_SIZE + x = cell_column_number * TILE_SIZE + return x, y diff --git a/config.py b/config.py index 1398b28..ccfd4da 100644 --- a/config.py +++ b/config.py @@ -1,10 +1,9 @@ -import pygame - FRAMERATE = 30 WIDTH, HEIGHT = 832, 832 TILE_SIZE = 64 BLACK = ((0,0,0)) WHITE = ((255,255,255)) NUM_ROWS = WIDTH//TILE_SIZE -AGENT_LAYER =2 -FLOWER_LAYER = 1 \ No newline at end of file +AGENT_LAYER = 2 +FLOWER_LAYER = 1 +GRASS_LAYER = 3 \ No newline at end of file diff --git a/health_flower.py b/health_flower.py deleted file mode 100644 index 684bce1..0000000 --- a/health_flower.py +++ /dev/null @@ -1,28 +0,0 @@ -import pygame -from config import * - -class Health_flower(pygame.sprite.Sprite): - - - def __init__(self, game, x, y): - self.game = game - self.groups = self.game.flowers - pygame.sprite.Sprite.__init__(self, self.groups) - - self.x = x * TILE_SIZE - self.y = y * TILE_SIZE - self.width = TILE_SIZE - self.height = TILE_SIZE - - self.FLOWER_IMG = pygame.image.load("./zdjecia/flower.png") - self.FLOWER = pygame.transform.scale(self.FLOWER_IMG,(64,64)) - - self.image = pygame.Surface([self.width, self.height]) - self.image.blit(self.FLOWER, (0,0)) - self.image.set_colorkey((0, 0, 0)) - - self.rect = self.image.get_rect() - self.rect.x = self.x - self.rect.y = self.y - - self._layer = FLOWER_LAYER diff --git a/infantry_ork.py b/infantry_ork.py deleted file mode 100644 index e2db1ae..0000000 --- a/infantry_ork.py +++ /dev/null @@ -1,29 +0,0 @@ -import pygame -from config import * - -class Infantry_ork(pygame.sprite.Sprite): - - - def __init__(self, game, x, y): - self.game = game - self.groups = self.game.all_sprites, self.game.infantry_orks - pygame.sprite.Sprite.__init__(self, self.groups) - - self.x = x * TILE_SIZE - self.y = y * TILE_SIZE - self.width = TILE_SIZE - self.height = TILE_SIZE - - self.INFANTRY_ORK_IMG = pygame.image.load("./zdjecia/ork-piechota.png") - self.INFANTRY_ORK = pygame.transform.scale(self.INFANTRY_ORK_IMG,(64,64)) - - self.image = pygame.Surface([self.width, self.height]) - self.image.blit(self.INFANTRY_ORK, (0,0)) - self.image.set_colorkey((0, 0, 0)) - - self.rect = self.image.get_rect() - self.rect.x = self.x - self.rect.y = self.y - - self.level = 2 - self.damage = 50*self.level \ No newline at end of file diff --git a/infantry_ork2.py b/infantry_ork2.py deleted file mode 100644 index 6c6e9fc..0000000 --- a/infantry_ork2.py +++ /dev/null @@ -1,29 +0,0 @@ -import pygame -from config import * - -class Infantry_ork2(pygame.sprite.Sprite): - - - def __init__(self, game, x, y): - self.game = game - self.groups = self.game.all_sprites, self.game.infantry_orks2 - pygame.sprite.Sprite.__init__(self, self.groups) - - self.x = x * TILE_SIZE - self.y = y * TILE_SIZE - self.width = TILE_SIZE - self.height = TILE_SIZE - - self.INFANTRY_ORK2_IMG = pygame.image.load("./zdjecia/ork-piechota2.png") - self.INFANTRY_ORK2 = pygame.transform.scale(self.INFANTRY_ORK2_IMG,(64,64)) - - self.image = pygame.Surface([self.width, self.height]) - self.image.blit(self.INFANTRY_ORK2, (0,0)) - self.image.set_colorkey((0, 0, 0)) - - self.rect = self.image.get_rect() - self.rect.x = self.x - self.rect.y = self.y - - self.level = 3 - self.damage = 50*self.level \ No newline at end of file diff --git a/main.py b/main.py index 8b6bf71..435cf05 100644 --- a/main.py +++ b/main.py @@ -2,12 +2,10 @@ import pygame from config import * from agent import * from map_add_ons import * -from archer_ork import * -from infantry_ork import * -from infantry_ork2 import * -from sauron import * -from health_flower import * +from mobs import * #from unknown_mob import * #unknown mob +import random +from bfs import * class Game: @@ -26,29 +24,40 @@ class Game: pygame.display.set_caption('Gra-SI') + self.bfs = Bfs(self) + def new(self): # tworzy się nowa sesja grania self.all_sprites = pygame.sprite.LayeredUpdates() + self.rock_sprites = pygame.sprite.LayeredUpdates() + self.grass_sprites = pygame.sprite.LayeredUpdates() self.archer_orks = pygame.sprite.LayeredUpdates() self.infantry_orks = pygame.sprite.LayeredUpdates() self.infantry_orks2 = pygame.sprite.LayeredUpdates() self.sauronL = pygame.sprite.LayeredUpdates() self.flowers = pygame.sprite.LayeredUpdates() + #self.unknown_mobs = pygame.sprite.LayeredUpdates() #unknown mob self.agent = Agent(self,1,1) self.archer_ork = Archer_ork(self,10,10) - self.enemy_cells.append(self.get_cell_number(self.archer_ork.x,self.archer_ork.y)) + self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.archer_ork.x,self.archer_ork.y)) self.infantry_ork = Infantry_ork(self,10,4) - self.enemy_cells.append(self.get_cell_number(self.infantry_ork.x,self.infantry_ork.y)) + self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.infantry_ork.x,self.infantry_ork.y)) self.infantry_ork2 = Infantry_ork2(self,6,3) - self.enemy_cells.append(self.get_cell_number(self.infantry_ork2.x,self.infantry_ork2.y)) + self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.infantry_ork2.x,self.infantry_ork2.y)) self.sauron = Sauron(self, 1, 10) - self.enemy_cells.append(self.get_cell_number(self.sauron.x,self.sauron.y)) + self.bfs.enemy_cells.append(self.bfs.get_cell_number(self.sauron.x,self.sauron.y)) self.flower = Health_flower(self, 8,2) #self.unknown_mob = Unknown_mob(self,8,8) #unknown mob for y in range(5): self.rock = Rocks(self,3,y) - self.wall_cells.append(self.get_cell_number(self.rock.x,self.rock.y)) + self.bfs.wall_cells.append(self.bfs.get_cell_number(self.rock.x,self.rock.y)) + for i in range(10): + x = random.randint(0,12) + y = random.randint(0,11) + self.grass = Grass(self,x,y) + self.grass_cells.append(self.bfs.get_cell_number(self.grass.x,self.grass.y)) + def update(self): @@ -63,7 +72,7 @@ class Game: if event.type == pygame.MOUSEBUTTONDOWN: mouse_presses = pygame.mouse.get_pressed() if mouse_presses[0]: - self.bfs() + self.bfs.bfs() def map(self): # tworzenie mapy self.clock.tick(FRAMERATE) @@ -75,6 +84,7 @@ class Game: self.flowers.draw(self.SCREEN) self.all_sprites.draw(self.SCREEN) self.rock_sprites.draw(self.SCREEN) + self.grass_sprites.draw(self.SCREEN) self.SCREEN.blit(self.LVL_ICON, (340 ,780)) pygame.display.update() @@ -83,194 +93,23 @@ class Game: self.update() self.map() + grass_cells = [] + + + '''def astar(self): + + + def function(self): + + + def cost(self): + cost = 0 + while() +''' + + + # BFS ALGORITHM - - open_queue = [] - close_queue = [] - wall_cells = [] - enemy_cells = [] - - def bfs(self): - print("x: ", self.agent.x, "y: ", self.agent.y) - - self.open_queue.append(self.get_cell_number(self.agent.x,self.agent.y)) - # tutaj dodaje się cel agenta - goal_cell = self.get_cell_number(self.flower.x,self.flower.y) - - path = [] - processing = True - find_path = False - while processing: # główna pętla - for event in pygame.event.get(): - if event.type == pygame.QUIT: - exit() - - if len(self.open_queue) > 0 : - current_node_cell = self.open_queue.pop(0) - - if(current_node_cell in self.close_queue): - continue - - print("Aktualna kratka: ", current_node_cell) - print("Cel znajduje się na kratce: ", goal_cell) - - if (current_node_cell == goal_cell): - self.close_queue.append(current_node_cell) - found_goal_cell = current_node_cell - print("Znaleziono cel, szukanie drogi z odwiedzonych węzłów, kolejka odwiedzonych:", self.close_queue) - processing = False - find_path = True - self.clock.tick(2) - else: - child_node_cells = self.get_child_nodes(current_node_cell) - self.close_queue.append(current_node_cell) - print("Sąsiedzi: ", child_node_cells) - for child_node in child_node_cells: - if child_node not in self.open_queue and child_node not in self.close_queue: - self.open_queue.append(child_node) - print("Kolejka: ", self.open_queue, "\n") - else: - print("Brak nowych węzłów, kolejka: ",self. open_queue) - print("Odwiedzone : ", self.close_queue) - return self.close_queue - - dead_end_nodes = [] - while find_path: - path.append(self.close_queue[0]) - - for i in range(len(self.close_queue) -1): - from_cell = path[-1] - to_cell = self.close_queue[i+1] - - if to_cell in dead_end_nodes: - continue - - if self.verify_move(from_cell, to_cell): - path.append(to_cell) - - if path[-1] == found_goal_cell: - find_path = False - else: - dead_end_nodes.append(path[-1]) - path = [] - - print("Droga: ", path) - self.move_agent(path) - - - def get_cell_number(self,x, y): #zamienia koordynaty na numer kratki - cell_number = None - cell_number =(x // TILE_SIZE) + (NUM_ROWS * (( y// TILE_SIZE))) - return cell_number - - def get_child_nodes(self,cell_number): - children = [] - up = self.get_up_cell(cell_number) - if up is not None and up not in self.wall_cells and up not in self.enemy_cells: - children.append(up) - - right = self.get_right_cell(cell_number) - if right is not None and right not in self.wall_cells and up not in self.enemy_cells: - children.append(right) - - down = self.get_down_cell(cell_number) - if down is not None and down not in self.wall_cells and up not in self.enemy_cells: - children.append(down) - - left = self.get_left_cell(cell_number) - if left is not None and left not in self.wall_cells and up not in self.enemy_cells: - children.append(left) - - return children - - - def get_up_cell(self,cell_number): - cell_row_number = cell_number // NUM_ROWS - if (cell_row_number - 1 < 0): - return None - else: - return (cell_number - NUM_ROWS) - - def get_right_cell(self,cell_number): - cell_column_number = cell_number % NUM_ROWS - if (cell_column_number + 1 >= NUM_ROWS): - return None - else: - return (cell_number + 1) - - def get_down_cell(self,cell_number): - cell_row_number = cell_number // NUM_ROWS - if (cell_row_number + 1 >= NUM_ROWS): - return None - else: - return (cell_number + NUM_ROWS) - - def get_left_cell(self,cell_number): - cell_column_number = cell_number % NUM_ROWS - if (cell_column_number - 1 < 0): - return None - else: - return (cell_number - 1) - - def verify_move(self,from_cell, to_cell): #sprawdzenie czy ruch jest poprawny czyt. czy następna kratka to przeszkoda lub mob - if (to_cell in self.wall_cells or to_cell in self.enemy_cells): - return False - - if(from_cell + 1 == to_cell): - return True - - if(from_cell - 1 == to_cell): - return True - - if(from_cell - NUM_ROWS == to_cell): - return True - - if(from_cell + NUM_ROWS == to_cell): - return True - - return False - - def move_agent(self,path): - for cell_to_move in path: - x, y = self.get_coordinates(cell_to_move) - print("Ruch do kratki : ", cell_to_move, " z x: ", x, ", y: ", y, ", agent.x: ", self.agent.rect.x, ", agent.y: ", self.agent.rect.y) - if(self.get_cell_number(self.agent.x,self.agent.y)!=cell_to_move): - if x > self.agent.rect.x: - self.agent.direction = 0 - elif y > self.agent.rect.y: - self.agent.direction = 1 - elif x < self.agent.rect.x: - self.agent.direction = 2 - elif y < self.agent.rect.y: - self.agent.direction = 3 - if self.agent.direction==0: - print("DIRECTION: "+self.agent.AGENT_IMAGES[self.agent.direction]) - self.agent.x_change += TILE_SIZE - elif self.agent.direction==1: - print("DIRECTION: "+self.agent.AGENT_IMAGES[self.agent.direction]) - self.agent.y_change += TILE_SIZE - elif self.agent.direction==2: - print("DIRECTION: "+self.agent.AGENT_IMAGES[self.agent.direction]) - self.agent.x_change -= TILE_SIZE - elif self.agent.direction==3: - print("DIRECTION: "+self.agent.AGENT_IMAGES[self.agent.direction]) - self.agent.y_change -= TILE_SIZE - - self.agent.rotate() - self.update() - self.map() - - print("Położenie agenta: agent.x: ", self.agent.rect.x, ", agent.y: ", self.agent.rect.y) - self.clock.tick(2) - - def get_coordinates(self,cell_to_move): #zamienia numer kratki na koordynaty - cell_row_number = cell_to_move // NUM_ROWS - cell_column_number = cell_to_move % NUM_ROWS - - y = cell_row_number * TILE_SIZE - x = cell_column_number * TILE_SIZE - return x, y - g = Game() g.new() diff --git a/map_add_ons.py b/map_add_ons.py index 7a2c052..a2e01a2 100644 --- a/map_add_ons.py +++ b/map_add_ons.py @@ -5,7 +5,8 @@ class Rocks(pygame.sprite.Sprite): def __init__(self,game,x,y): self.game = game - self.groups = self.game.all_sprites, self.game.rock_sprites + self.groups = self.game.rock_sprites + pygame.sprite.Sprite.__init__(self, self.groups) self.x = x * TILE_SIZE @@ -23,4 +24,60 @@ class Rocks(pygame.sprite.Sprite): self.rect = self.image.get_rect() self.rect.x = self.x self.rect.y = self.y + + + +class Grass(pygame.sprite.Sprite): + + def __init__(self,game,x,y): + self.game = game + self.groups = self.game.grass_sprites + pygame.sprite.Sprite.__init__(self, self.groups) + + self.x = x * TILE_SIZE + self.y = y * TILE_SIZE + self.width = TILE_SIZE + self.height = TILE_SIZE + + self.GRASS_PNG = pygame.image.load("./zdjecia/grass.png") + self.GRASS = pygame.transform.scale(self.GRASS_PNG,(64,64)) + + self.image = pygame.Surface([self.width, self.height]) + self.image.blit(self.GRASS,(0,0)) + self.image.set_colorkey((0, 0, 0)) + + self.rect = self.image.get_rect() + self.rect.x = self.x + self.rect.y = self.y + + self.cost = 10 + + self._layer = GRASS_LAYER + +class Health_flower(pygame.sprite.Sprite): + + + def __init__(self, game, x, y): + self.game = game + self.groups = self.game.flowers, + pygame.sprite.Sprite.__init__(self, self.groups) + + self.x = x * TILE_SIZE + self.y = y * TILE_SIZE + self.width = TILE_SIZE + self.height = TILE_SIZE + + self.FLOWER_IMG = pygame.image.load("./zdjecia/flower.png") + self.FLOWER = pygame.transform.scale(self.FLOWER_IMG,(64,64)) + + self.image = pygame.Surface([self.width, self.height]) + self.image.blit(self.FLOWER, (0,0)) + self.image.set_colorkey((0, 0, 0)) + + self.rect = self.image.get_rect() + self.rect.x = self.x + self.rect.y = self.y + + self._layer = FLOWER_LAYER + diff --git a/mobs.py b/mobs.py new file mode 100644 index 0000000..c5b53c5 --- /dev/null +++ b/mobs.py @@ -0,0 +1,113 @@ +import pygame +from config import * + +class Archer_ork(pygame.sprite.Sprite): + + + def __init__(self, game, x, y): + self.game = game + self.groups = self.game.all_sprites, self.game.archer_orks + pygame.sprite.Sprite.__init__(self, self.groups) + + self.x = x * TILE_SIZE + self.y = y * TILE_SIZE + self.width = TILE_SIZE + self.height = TILE_SIZE + + self.ARCHER_ORK_IMG = pygame.image.load("./zdjecia/ork_lucznik.png") + self.ARCHER_ORK = pygame.transform.scale(self.ARCHER_ORK_IMG,(64,64)) + + self.image = pygame.Surface([self.width, self.height]) + self.image.blit(self.ARCHER_ORK, (0,0)) + self.image.set_colorkey((0, 0, 0)) + + self.rect = self.image.get_rect() + self.rect.x = self.x + self.rect.y = self.y + + self.level = 1 + self.damage = 50*self.level + +class Infantry_ork(pygame.sprite.Sprite): + + + def __init__(self, game, x, y): + self.game = game + self.groups = self.game.all_sprites, self.game.infantry_orks + pygame.sprite.Sprite.__init__(self, self.groups) + + self.x = x * TILE_SIZE + self.y = y * TILE_SIZE + self.width = TILE_SIZE + self.height = TILE_SIZE + + self.INFANTRY_ORK_IMG = pygame.image.load("./zdjecia/ork-piechota.png") + self.INFANTRY_ORK = pygame.transform.scale(self.INFANTRY_ORK_IMG,(64,64)) + + self.image = pygame.Surface([self.width, self.height]) + self.image.blit(self.INFANTRY_ORK, (0,0)) + self.image.set_colorkey((0, 0, 0)) + + self.rect = self.image.get_rect() + self.rect.x = self.x + self.rect.y = self.y + + self.level = 2 + self.damage = 50*self.level + + +class Infantry_ork2(pygame.sprite.Sprite): + + + def __init__(self, game, x, y): + self.game = game + self.groups = self.game.all_sprites, self.game.infantry_orks2 + pygame.sprite.Sprite.__init__(self, self.groups) + + self.x = x * TILE_SIZE + self.y = y * TILE_SIZE + self.width = TILE_SIZE + self.height = TILE_SIZE + + self.INFANTRY_ORK2_IMG = pygame.image.load("./zdjecia/ork-piechota2.png") + self.INFANTRY_ORK2 = pygame.transform.scale(self.INFANTRY_ORK2_IMG,(64,64)) + + self.image = pygame.Surface([self.width, self.height]) + self.image.blit(self.INFANTRY_ORK2, (0,0)) + self.image.set_colorkey((0, 0, 0)) + + self.rect = self.image.get_rect() + self.rect.x = self.x + self.rect.y = self.y + + self.level = 3 + self.damage = 50*self.level + + +class Sauron(pygame.sprite.Sprite): + + + def __init__(self, game, x, y): + self.game = game + self.groups = self.game.all_sprites, self.game.sauronL + pygame.sprite.Sprite.__init__(self, self.groups) + + self.x = x * TILE_SIZE + self.y = y * TILE_SIZE + self.width = TILE_SIZE + self.height = TILE_SIZE + + self.SAURON_IMG = pygame.image.load("./zdjecia/sauron.png") + self.SAURON = pygame.transform.scale(self.SAURON_IMG,(64,64)) + + self.image = pygame.Surface([self.width, self.height]) + self.image.blit(self.SAURON, (0,0)) + self.image.set_colorkey((0, 0, 0)) + + self.rect = self.image.get_rect() + self.rect.x = self.x + self.rect.y = self.y + + self.level = 4 + self.damage = 50*self.level + \ No newline at end of file diff --git a/sauron.py b/sauron.py deleted file mode 100644 index e5d9c07..0000000 --- a/sauron.py +++ /dev/null @@ -1,29 +0,0 @@ -import pygame -from config import * - -class Sauron(pygame.sprite.Sprite): - - - def __init__(self, game, x, y): - self.game = game - self.groups = self.game.all_sprites, self.game.sauronL - pygame.sprite.Sprite.__init__(self, self.groups) - - self.x = x * TILE_SIZE - self.y = y * TILE_SIZE - self.width = TILE_SIZE - self.height = TILE_SIZE - - self.SAURON_IMG = pygame.image.load("./zdjecia/sauron.png") - self.SAURON = pygame.transform.scale(self.SAURON_IMG,(64,64)) - - self.image = pygame.Surface([self.width, self.height]) - self.image.blit(self.SAURON, (0,0)) - self.image.set_colorkey((0, 0, 0)) - - self.rect = self.image.get_rect() - self.rect.x = self.x - self.rect.y = self.y - - self.level = 4 - self.damage = 50*self.level \ No newline at end of file diff --git a/zdjecia/grass.png b/zdjecia/grass.png new file mode 100644 index 0000000000000000000000000000000000000000..ea278123f8320ca5a06f32c6fac185d9f5c4f58b GIT binary patch literal 29487 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 literal 0 HcmV?d00001