From a342db5ce1b4a51ebddc8797e8d80d77ca715a51 Mon Sep 17 00:00:00 2001 From: jannikvlk Date: Mon, 13 Dec 2021 15:46:52 +0100 Subject: [PATCH 1/9] Testdatei hochladen --- .idea/.gitignore | 3 + .../inspectionProfiles/profiles_settings.xml | 6 + .idea/modules.xml | 8 ++ .idea/snake-1.iml | 8 ++ .idea/vcs.xml | 6 + Pipfile | 2 +- Pipfile.lock | 105 ++++++++++-------- test | 0 8 files changed, 93 insertions(+), 45 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/inspectionProfiles/profiles_settings.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/snake-1.iml create mode 100644 .idea/vcs.xml create mode 100644 test diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..eaf91e2 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..105ce2d --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..7c6e735 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/snake-1.iml b/.idea/snake-1.iml new file mode 100644 index 0000000..d9e6024 --- /dev/null +++ b/.idea/snake-1.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..9661ac7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Pipfile b/Pipfile index e657dcc..e8d47a9 100644 --- a/Pipfile +++ b/Pipfile @@ -9,4 +9,4 @@ verify_ssl = true pygame = "*" [requires] -python_version = "3.9" +python_version = "3.10" diff --git a/Pipfile.lock b/Pipfile.lock index ee91f48..11aed56 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,11 +1,11 @@ { "_meta": { "hash": { - "sha256": "cdf596c2d353636ac79e464434d67c35deb7dbfbb40070019ca172b2afa30fff" + "sha256": "8367b3cf5b264019fbf1fa9a895626b8349cabeb3fc4d21326594cb54409afb4" }, "pipfile-spec": 6, "requires": { - "python_version": "3.9" + "python_version": "3.10" }, "sources": [ { @@ -18,50 +18,67 @@ "default": { "pygame": { "hashes": [ - "sha256:0571dde0277483f5060c8ee43cbfd8df5776b12505e3948eee241c8ce9b93371", - "sha256:07ed57062be4bb9741f57dab1751d95574c091c9958ed7e39cdb246d50903283", - "sha256:107d5f82f471baee4b9522a691cb320dd52dbf329ed7a0e9ab25f75cd3caf890", - "sha256:10ca736eecedadf492ba1191f9fa3a5e6f30db2b9f8882b3ee7706d5a89c14e0", - "sha256:19357c826ab94f9ae5b4ec5cb752cc806cfc29ea32cf7bdaacb65fa2615607e8", - "sha256:21475405bcdeb20b8a796a3da6704ebb816e06b29749dd64ff619e80816b7932", - "sha256:2d9b0a66034fed390ee367a549435853502c9d4fe82ac0fa3a520f0ad5648e6e", - "sha256:30eb5c7adb0b3362024cec2c461be6978fbfc99c3bca974e438b1b540cd09438", - "sha256:3270cbcff40ca2b5622a145346298a33285c91b6d50097e0b85123d9a2bc7c9b", - "sha256:328d70d40bc9a6defb9f330f5e7f3d0726af1e7c2308ebca582e69480db2950d", - "sha256:3b31d088129977885f72037c55cfa1140e9bcf3468e68b46141f6cc2b33d456b", - "sha256:3c2676b4fd278d632037eacd3b0524ce1a592c048e8e5eb5830475f83585cb3a", - "sha256:44f3ff8224d7cb998642400371c685005c8316b55e87794cbf1f6407b88ec424", - "sha256:49c2f58559c1fbf4ba258e4b141578ccb0e83da3d4f823894f6171a8f0d594ed", - "sha256:4d3135a1f8c76c3fff1ef8b7a51e4c6523748e9bdbd7bca6daa69790ce0e798a", - "sha256:4f41252dfa1e8bb95f2ea51fba710827dde9820a535623d002a65621bafe7e3f", - "sha256:5aeeb6659a7fe7760a78e449566553ae8c949ae29dd907a8eb4171fa0a274c16", - "sha256:5afc34f0af0cec09a20b6bb09090054fac5169ab01909e01b06e7e0752ab0153", - "sha256:5f057e5aa4c383fcf18560dcae2c5593e37e3fc941083a0a00a17f7cf25ee522", - "sha256:72625dc949c6d08ba7ce7c37a33163bb498d90ca0d7e626db3cfbf486df4db1d", - "sha256:7ea518d8eeb072c77c16977cdee3c59d9fffa750ed9c7c9c533ba520b6b08af7", - "sha256:81510ffb1c31a3827c6be047b1926d81caf36dc734564ca0e14903d6bce60c6f", - "sha256:845385caf99f8d941607791c60e560d24b4a35c70eef0b01c30cfde0b913ff92", - "sha256:898874521a9be1f9dbc5b036a9755803287c2664e335afd3e10963f7f4ccb853", - "sha256:8b1e7b63f47aafcdd8849933b206778747ef1802bd3d526aca45ed77141e4001", - "sha256:9aead3f2eed90260136b201f398965900c5335c974bb7b47c381d98e39284018", - "sha256:9de559462aaa68c40bb7625dcd587584b4eb85c4208528dc97b9ee7254945294", - "sha256:9f48277de1daa83fd58a722b2e3423201b5eb39842227f32702fb78e4bba5a71", - "sha256:9fd0691c4fe58b932674bb6a91d2808790e8269c3183ef16052f13e1c602ac00", - "sha256:a4e35d89b6754941e82df1ce980a1c370943d3c076938d94ed1e48165dd6a11b", - "sha256:ad230911d61f448c09886d3c92b2eae44ca7530babe9c48e74e02a0622ce2d34", - "sha256:b812285d23b5644c643a6ae30553a772f935f47f61826660b108b8727936384b", - "sha256:bf833c853a0568738ee5d88e1345c17bf3e8db626c36fb895327a35bb1827b0b", - "sha256:c188ce4bf1544f2758e8b651f4349a0f3dc441e09d8ab7c4863db1ae8f084a32", - "sha256:d8059084ce54b2c3d7b2c8bacd5f6490db849b2d2d6e7368c160b08504c87e73", - "sha256:e72cdc97a49509ca2298350c2c3a0ac26bc8e943ce003a7d245df42e91439d5d", - "sha256:eab18df58dcc8512f1b694f7218146828d7e3dd3f4e73bfd6942a11810293fd5", - "sha256:ece424c83a575c2e0ba25815871458d3bbade46d76b7997236fb51a0251229ab", - "sha256:ed80b40da839d60f4c03915bb3638e3c96ea8c30e689d0cc309b7597d82cc217", - "sha256:fd5ee0f42d59a290c049f91894e0739f62c2908e7edc028ffb847a105e68bfc3", - "sha256:fd6acd09d2a0fd3f616b18f977f399ed3dd95e2d6754f115837f026d19d62e10" + "sha256:0227728f2ef751fac43b89f4bcc5c65ce39c855b2a3391ddf2e6024dd667e6bd", + "sha256:02a26b3be6cc478f18f4efa506ee5a585f68350857ac5e68e187301e943e3d6d", + "sha256:0d2f80b501aacd74a660d4422793ea1cd4e209bee385aac18d0a07bd671511ee", + "sha256:15d4e42214f93d8c60120e16b690ad03da7f0b3b66f75db8966bccf8c66c4690", + "sha256:232e51104db0e573221660d172af8e6fc2c0fda183c5dbf2aa52170f29aa9ec9", + "sha256:2bfefabe78bda7a1bfba253cbe2131038402ce2b32e4218feeba6431fe429abb", + "sha256:32cb64627c2eb5c4c067ffe614e08ccb8987d096100d225e070dddce05725b63", + "sha256:3804476fab6ec7230aa817ee5c3b378ba956321fdd5f91f51c97452c588869d2", + "sha256:38b5a43ab02c162501e62b857ff2cb128076b0786dd4e1d8bea63db8326f9da1", + "sha256:3d5a76fa826202182d989e8399fca0c3c163fbb4f8ece773e77955a7a62cbed3", + "sha256:472b81ba6b61ffe5879ac3d0da2e5cb235e0e4da471ad4038f013a7710ab53ab", + "sha256:49e5fb589a86169aa95b83d3429ee034799792374e13dbc0da83091d86365a4b", + "sha256:4ab5aba8677d135b94c4714e8256efdfffefc164f354a4d05b846588caf43b99", + "sha256:4eff1db92d53dc2e49ed832dd6c76530e1e2b5954eef091f6af41b41d2d5c3ac", + "sha256:4f73058569573af12c8181e032745f11d85f0799510965d938b1f16c7f13afcb", + "sha256:53c6fa767e3eef52d403eda5d032e48b6040ccce03fbd64af2f71843168118da", + "sha256:594234050b50b57c538842155dc3095c9d4f994266325adb4dd008aee526157f", + "sha256:59a5461ef317e4d233d1bb5ce63311ccad3e911a652bda159d3922351050158c", + "sha256:5a3edc8211d0cf39d1e4d7ded1a0727c53aeb21205963f184199521708bbb05c", + "sha256:5d36d530a8994c5bb8889816981f82b7942d8ec7651ca1d922d01302c1feecd2", + "sha256:5eb3dede55d005adea8504f8c9230b9dc2c84c1c728efe93a9718fa1af824dc8", + "sha256:646e871ff5ab7f933cde5ea2bff7b6cd74d7369f43e84a291baebe00bb9a8f6f", + "sha256:64ec45215c2cfc4051bb0f58d26aee3b50a39b1b0a2e6fe8417bb352a6443aad", + "sha256:692fe4498c353d663d45d05354fb47c9f6bf324d10b53844b9ed7f60e6c8cefa", + "sha256:6efa3fa472acb97c784224b59a89e80da6231f0dbf54df8442ffa3352c0534d6", + "sha256:70a11eec9bae6e8970c5bc4b3d0908eb2c42d4bd4ed488e41e49774b7cb41f57", + "sha256:7281366b4ebd7f16eac8ec6a6e2adb4c729beda178ea82637d9981e93dd40c9b", + "sha256:7a305dcf44f03a8dd7baefb97dc24949d7e719fd686cd3211121639aec4ce464", + "sha256:847b4bc22edb1d77c992b5d56b19e1ab52e14687adb8bc3ed12a8a98fbd7e1ff", + "sha256:85844714f82a5379100825473b1a7b24192b4a944aed3128da9386e26adc3bed", + "sha256:86c66b917afc6330a91ac8c7169c36c77ec536578d1d7724644d41f904e2d146", + "sha256:88a2dabe617e6173003b65762c636947719da3e2d881a4ea47298e8d70886386", + "sha256:9284e76923777c21b8bea19d8528be9cd62d0915139ed3c3cde6c43f849466f5", + "sha256:987c0d5fcd7737c31b35df06f78932c48eeff2c97473001e224fdebd3292b2db", + "sha256:9a81d057a7dea95850e44118f141a892fde93c938ccb08fbc5dd7f1a26c2f1fe", + "sha256:9b2ad10ffaa226ca40ae229143b0a118426aff42e2459b626d355846c59a765d", + "sha256:a0842458b49257ab539b7b6622a242cabcddcb61178b8ae074aaceb890be75b6", + "sha256:a0ab3e4763e0cebf08c55154f4167cdae3683674604a71e1437123225f2a9b36", + "sha256:ada3d33e7e6907d5c3bf771dc58c47ee6994a1e28fed55e4f8f8b817367beb8f", + "sha256:add546fcbf8954f00647f5e7d595ab9389f6a7542a99fc5dca514e14fd799773", + "sha256:b0e405fdde643f14d60c2dd140f110a5a38f588396a8b61a1a86374f25cba589", + "sha256:b0e96c0f68f6bb88da216765920c6dbc55ae83e70435d8ebac87d271fc058646", + "sha256:b400edd7391972e75b4243113089d6ea10b032e1306e8721efabb36d33c2d0f2", + "sha256:b545634f96132af1d31dcb873cf03a9c4a5654ae39d9ee126db0b2eba2806788", + "sha256:ba5bf655c892bbf4a9bafb4fcbc4c71023cc9a65f0cae0f3eba09a11018a858e", + "sha256:bb55368d455ab9518b97febd33a8d417988397b019c9408993be034e0b5a7db6", + "sha256:c1eb91198fc47c2e4fdc19c544b5d94534a70fd877f5c342228feb05e9fc4bef", + "sha256:c28c6f764aa03a0245db12346f1da327c6f49bcc20e53aefec6eed57e4fbe1ce", + "sha256:c6ee571995527e779b46cafee7ebef2dceb1a9c375143828e019293ff0efa167", + "sha256:c84a93e6d33dafce9e25080ac557342333e15ef7e378ba84cb6181c52a8fd663", + "sha256:d4061ac4e81bb36ec8f0a7027582c1c4dd32a939882e008165627103cb0b3985", + "sha256:d5c62fbdb30082f7e1dcfa253da48e7b4be7342d275b34b2efa51f6cffc5942b", + "sha256:e533f4bf9dc1a91cfd608b9bfb028c6a92383e731c502660933f0f9b812045a6", + "sha256:e9368c105a8bccc8adfe7fd7fa5220d2b6c03979a3a57a8178c42f6fa9914ebc", + "sha256:f628f9f26c8dadf72fabc9ae0ce5fe7f60d76be71a3407abc756b4d1fd030fa0", + "sha256:f8379052cfbc278b11e31bc97f2e7f5998959c50837c4d54f4e424a541e0c5d9", + "sha256:fad7b5351931cb68d19d7ecc0b21021fe23237d8fba8c455b5af4a79e1c7c536", + "sha256:fdd488daa4ad33748d5ea806e311bfe01b9cc506def5288400072fcd66d226cf" ], "index": "pypi", - "version": "==2.0.1" + "version": "==2.1.0" } }, "develop": {} diff --git a/test b/test new file mode 100644 index 0000000..e69de29 From aab083f83d3f7ac6f6ae5af362786932dc90df00 Mon Sep 17 00:00:00 2001 From: jannikvlk Date: Mon, 13 Dec 2021 16:43:04 +0100 Subject: [PATCH 2/9] draw Bricks finished --- .idea/misc.xml | 4 ++++ snake.py | 43 ++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 .idea/misc.xml diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..2bb9140 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/snake.py b/snake.py index 4be7cbc..9a52087 100644 --- a/snake.py +++ b/snake.py @@ -1,11 +1,40 @@ import pygame import random from typing import Optional, List, Tuple +import time TILE_SIZE = 20 + # TODO: Spielklassen +class Item: + def __init__(self, x: int, y: int) -> None: + self._x = x + self._y = y + + def occupies(self, x: int, y: int) -> bool: + if x == self._x and y == self._y: + return True + return False + + def __repr__(self): + return f'x = {self._x}, y = {self._y}' + + +class Brick(Item): + def __init__(self, x: int, y: int) -> None: + super().__init__(x, y) + + def draw(self, surface: pygame.Surface) -> None: + pygame.draw.rect(surface, + (230, 230, 230), + [TILE_SIZE * self._x, + TILE_SIZE * self._y, + TILE_SIZE, + TILE_SIZE] + ) + def main(): width = 20 @@ -22,11 +51,23 @@ def main(): # TODO: Spielobjekte anlegen + # defines a wall on the outer coordinates of the field + wall = [ + Brick(x, y) + for x in range(width) + for y in range(height) + if x == 0 or x == width - 1 or y == 0 or y == height - 1 + ] + + # TODO zusätzliche Steine im innern erstellen + # wall.append(Brick(7,7)) + running = True while running: screen.fill((20, 20, 20)) - # TODO: Mauer zeichnen + for brick in wall: + brick.draw(screen) for event in pygame.event.get(): if event.type == pygame.QUIT: From 5a6a0dd8dc475fb55818306ecc5d714d6f821c3c Mon Sep 17 00:00:00 2001 From: jannikvlk Date: Mon, 13 Dec 2021 17:45:05 +0100 Subject: [PATCH 3/9] Snacke moves and crashes --- snake.py | 99 +++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 88 insertions(+), 11 deletions(-) diff --git a/snake.py b/snake.py index 9a52087..acd69f8 100644 --- a/snake.py +++ b/snake.py @@ -4,6 +4,13 @@ import time TILE_SIZE = 20 +SNAKE_HEAD = (50, 205, 50) +SNAKE_BODY = (40, 195, 40) + +RIGHT = (1, 0) +LEFT = (-1, 0) +UP = (0, -1) +DOWN = (0, 1) # TODO: Spielklassen @@ -13,11 +20,13 @@ def __init__(self, x: int, y: int) -> None: self._x = x self._y = y + # returns whether both given coordinates match with the objects coordinates def occupies(self, x: int, y: int) -> bool: if x == self._x and y == self._y: return True return False + # returns a string that represents this object of item with the two attributes x and y def __repr__(self): return f'x = {self._x}, y = {self._y}' @@ -36,6 +45,76 @@ def draw(self, surface: pygame.Surface) -> None: ) +class Snake: + def __init__(self, x: int, y: int) -> None: + self._occupies = [(x, y)] + self._direction = tuple[int, int] + self._grow = 0 + + self.set_direction(RIGHT) + self.grow(3) + + def get_head(self) -> Tuple[int, int]: + return self._occupies[0] + + def occupies(self, x: int, y: int) -> bool: + print('check occupied') + for coordinate in self._occupies: + print(coordinate, x, y) + + if x == coordinate[0] and y == coordinate[1]: + return True + return False + + def draw(self, surface: pygame.Surface) -> None: + + for ind, part in enumerate(self._occupies): + if ind != 0: + color = SNAKE_BODY + else: + color = SNAKE_HEAD + + pygame.draw.rect(surface, + color, + [TILE_SIZE * part[0], + TILE_SIZE * part[1], + TILE_SIZE, + TILE_SIZE] + ) + + def set_direction(self, direction: tuple[int, int]) -> None: + if direction == RIGHT or direction == LEFT or direction == UP or direction == DOWN: + self._direction = direction + else: + raise Exception('Wrong direction') + + # The snake can only grow 1 field per tick -> grow can only be 1 or 0 to prevent errors + def grow(self, g: int) -> None: + if g > 0: + self._grow = 1 + + # TODO weitere Body teile hinzufügen? Nein? + + def step(self, forbidden: list[Item]) -> bool: + new_field = (self._occupies[0][0] + self._direction[0], self._occupies[0][1] + self._direction[1]) + + for forbidden_field in forbidden: + print(f'{new_field} ?= {forbidden_field}') + if forbidden_field.occupies(new_field[0], new_field[1]): + return False + + if self.occupies(new_field[0], new_field[1]): + return False + + self._occupies.insert(0, new_field) + if self._grow == 0: + self._occupies.pop() + else: + self._grow = 0 + + return True + + def main(): width = 20 height = 15 @@ -59,6 +138,7 @@ def main(): if x == 0 or x == width - 1 or y == 0 or y == height - 1 ] + snake = Snake(width // 2, height // 2) # TODO zusätzliche Steine im innern erstellen # wall.append(Brick(7,7)) @@ -66,6 +146,7 @@ def main(): while running: screen.fill((20, 20, 20)) + # draws every brick in wall on 'screen' for brick in wall: brick.draw(screen) @@ -76,24 +157,20 @@ def main(): break elif event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: - # TODO: Richtung aendern: nach links - pass + snake.set_direction(LEFT) elif event.key == pygame.K_RIGHT: - # TODO: Richtung aendern: nach rechts - pass + snake.set_direction(RIGHT) elif event.key == pygame.K_UP: - # TODO: Richtung aendern: nach oben - pass + snake.set_direction(UP) elif event.key == pygame.K_DOWN: - # TODO: Richtung aendern: nach unten - pass + snake.set_direction(DOWN) if not running: break - # TODO: Schlange bewegen - - # TODO: Schlange zeichnen + running = snake.step(wall) + print(running) + snake.draw(screen) # TODO: Ueberpruefen, ob die Kirsche erreicht wurde, falls ja, wachsen und Kirsche bewegen. From ef7ac0080c3d83d7bf4954093661c2370e152d76 Mon Sep 17 00:00:00 2001 From: jannikvlk Date: Mon, 13 Dec 2021 18:38:00 +0100 Subject: [PATCH 4/9] Everything works, except for cherry that sometimes dissapears --- snake.py | 65 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 56 insertions(+), 9 deletions(-) diff --git a/snake.py b/snake.py index acd69f8..3050172 100644 --- a/snake.py +++ b/snake.py @@ -1,11 +1,14 @@ import pygame import random -from typing import Optional, List, Tuple +from typing import Optional, List, Tuple, Type import time TILE_SIZE = 20 -SNAKE_HEAD = (50, 205, 50) -SNAKE_BODY = (40, 195, 40) +SNAKE_HEAD_COLOR = (60, 215, 60) +SNAKE_BODY_COLOR = (40, 195, 40) +BRICK_COLOR = 200, 200, 200 +CHERRY_COLOR = (200, 0, 0) +BACKGROUND_COLOR = (30, 30, 30) RIGHT = (1, 0) LEFT = (-1, 0) @@ -37,7 +40,7 @@ def __init__(self, x: int, y: int) -> None: def draw(self, surface: pygame.Surface) -> None: pygame.draw.rect(surface, - (230, 230, 230), + BRICK_COLOR, [TILE_SIZE * self._x, TILE_SIZE * self._y, TILE_SIZE, @@ -45,13 +48,48 @@ def draw(self, surface: pygame.Surface) -> None: ) +class Cherry(Item): + def __init__(self) -> None: + super().__init__(0, 0) + + def draw(self, surface: pygame.Surface) -> None: + pygame.draw.rect(surface, + CHERRY_COLOR, + [TILE_SIZE * self._x, + TILE_SIZE * self._y, + TILE_SIZE, + TILE_SIZE] + ) + + def move(self, snake, wall: list[tuple[int, int]], width: int, height: int, ) -> None: + occupied = True + + while occupied: + x = random.randint(0, width) + y = random.randint(0, height) + if snake.occupies(x, y): + occupied = True + else: + for brick in wall: + if brick.occupies(x, y): + occupied = True + break + else: + occupied = False + + self._x = x + self._y = y + + class Snake: def __init__(self, x: int, y: int) -> None: self._occupies = [(x, y)] self._direction = tuple[int, int] + self._grow = 0 + self._last_direction = RIGHT + self.set_direction(self._last_direction) - self.set_direction(RIGHT) self.grow(3) def get_head(self) -> Tuple[int, int]: @@ -70,9 +108,9 @@ def draw(self, surface: pygame.Surface) -> None: for ind, part in enumerate(self._occupies): if ind != 0: - color = SNAKE_BODY + color = SNAKE_BODY_COLOR else: - color = SNAKE_HEAD + color = SNAKE_HEAD_COLOR pygame.draw.rect(surface, color, @@ -84,7 +122,9 @@ def draw(self, surface: pygame.Surface) -> None: def set_direction(self, direction: tuple[int, int]) -> None: if direction == RIGHT or direction == LEFT or direction == UP or direction == DOWN: - self._direction = direction + if self._last_direction != (direction[0] * -1, direction[1] * -1): + self._direction = direction + else: raise Exception('Wrong direction') @@ -112,6 +152,7 @@ def step(self, forbidden: list[Item]) -> bool: else: self._grow = 0 + self._last_direction = self._direction return True @@ -137,8 +178,10 @@ def main(): for y in range(height) if x == 0 or x == width - 1 or y == 0 or y == height - 1 ] - + cherry = Cherry() snake = Snake(width // 2, height // 2) + + cherry.move(snake, wall, width, height) # TODO zusätzliche Steine im innern erstellen # wall.append(Brick(7,7)) @@ -171,8 +214,12 @@ def main(): running = snake.step(wall) print(running) snake.draw(screen) + cherry.draw(screen) # TODO: Ueberpruefen, ob die Kirsche erreicht wurde, falls ja, wachsen und Kirsche bewegen. + if cherry.occupies(snake.get_head()[0], snake.get_head()[1]): + snake.grow(1) + cherry.move(snake, wall, width, height) # TODO: Kirsche zeichnen From ddff9376f77fdce282817341242d2eceff50c9ba Mon Sep 17 00:00:00 2001 From: jannikvlk Date: Mon, 13 Dec 2021 23:59:44 +0100 Subject: [PATCH 5/9] Everything works. No Optional Features --- snake.py | 194 +++++++++++++++++++++++++++++++------------------------ 1 file changed, 109 insertions(+), 85 deletions(-) diff --git a/snake.py b/snake.py index 3050172..65eab3e 100644 --- a/snake.py +++ b/snake.py @@ -3,12 +3,14 @@ from typing import Optional, List, Tuple, Type import time -TILE_SIZE = 20 +TILE_SIZE = 30 + +# The color and direction values are saved in variables for easy access SNAKE_HEAD_COLOR = (60, 215, 60) SNAKE_BODY_COLOR = (40, 195, 40) -BRICK_COLOR = 200, 200, 200 +BRICK_COLOR = (200, 200, 200) CHERRY_COLOR = (200, 0, 0) -BACKGROUND_COLOR = (30, 30, 30) +BACKGROUND_COLOR = (70, 70, 70) RIGHT = (1, 0) LEFT = (-1, 0) @@ -16,8 +18,7 @@ DOWN = (0, 1) -# TODO: Spielklassen - +# Item defines a class for objects with x and y coordinates and a method to check if they occupy a given coordinate. class Item: def __init__(self, x: int, y: int) -> None: self._x = x @@ -29,16 +30,16 @@ def occupies(self, x: int, y: int) -> bool: return True return False - # returns a string that represents this object of item with the two attributes x and y - def __repr__(self): - return f'x = {self._x}, y = {self._y}' - +# Brick defines a class for objects that represent walls. +# They inherit from Item and have a method to draw themselves on the given surface. class Brick(Item): def __init__(self, x: int, y: int) -> None: super().__init__(x, y) def draw(self, surface: pygame.Surface) -> None: + # x and y have to be multiplied with Tile_size so that the scaling is properly done + # and every object on the field appears in the according size. pygame.draw.rect(surface, BRICK_COLOR, [TILE_SIZE * self._x, @@ -48,117 +49,141 @@ def draw(self, surface: pygame.Surface) -> None: ) -class Cherry(Item): - def __init__(self) -> None: - super().__init__(0, 0) - - def draw(self, surface: pygame.Surface) -> None: - pygame.draw.rect(surface, - CHERRY_COLOR, - [TILE_SIZE * self._x, - TILE_SIZE * self._y, - TILE_SIZE, - TILE_SIZE] - ) - - def move(self, snake, wall: list[tuple[int, int]], width: int, height: int, ) -> None: - occupied = True - - while occupied: - x = random.randint(0, width) - y = random.randint(0, height) - if snake.occupies(x, y): - occupied = True - else: - for brick in wall: - if brick.occupies(x, y): - occupied = True - break - else: - occupied = False - - self._x = x - self._y = y - +# Cherry is a class that defines objects that represent cherrys. +# They inherit from Item and have a method to draw themselves on the given surface. +# They can also move to a random position that is not preoccupied by a wall or the snake. +# Snake defines objects that represent snakes. class Snake: def __init__(self, x: int, y: int) -> None: + # _occupies stores the positions (x and y coordinates) of every snake part self._occupies = [(x, y)] + # _direction stores the direction the snake is headed, represented by x and y vectors. e.g. (1,0) means right self._direction = tuple[int, int] - + # _grow stores whether the snake still needs to grow a part because it ate a cherry. self._grow = 0 + # _last_direction stores the direction before the last direction change + # to ensure the snake doesn't turn 180° at once because this would lead to a crash that is not intended self._last_direction = RIGHT - self.set_direction(self._last_direction) + # _direction and grow are now set by the corresponding method. + self.set_direction(self._last_direction) self.grow(3) + # get_head returns the position (x and y) of the head of the snake. def get_head(self) -> Tuple[int, int]: return self._occupies[0] + # occupies checks if one of the snake parts occupies a given position on the field. def occupies(self, x: int, y: int) -> bool: - print('check occupied') for coordinate in self._occupies: - print(coordinate, x, y) - if x == coordinate[0] and y == coordinate[1]: return True return False + # draw draws the whole snake on the given surface. + # It differentiates between the head and body parts through color and shape def draw(self, surface: pygame.Surface) -> None: for ind, part in enumerate(self._occupies): - if ind != 0: - color = SNAKE_BODY_COLOR + if ind == 0: + pygame.draw.ellipse(surface, + SNAKE_HEAD_COLOR, + [TILE_SIZE * part[0], + TILE_SIZE * part[1], + TILE_SIZE, + TILE_SIZE] + ) else: - color = SNAKE_HEAD_COLOR - - pygame.draw.rect(surface, - color, - [TILE_SIZE * part[0], - TILE_SIZE * part[1], - TILE_SIZE, - TILE_SIZE] - ) - + pygame.draw.rect(surface, + SNAKE_BODY_COLOR, + [TILE_SIZE * part[0], + TILE_SIZE * part[1], + TILE_SIZE, + TILE_SIZE] + ) + + # set_direction receives a direction and checks if it is a valid direction. If not it raises an exception. + # It also compares to the last direction and if the new direction is the complete opposite + # it doesn't update the direction because this would lead to a non-intended crash. def set_direction(self, direction: tuple[int, int]) -> None: - if direction == RIGHT or direction == LEFT or direction == UP or direction == DOWN: - if self._last_direction != (direction[0] * -1, direction[1] * -1): - self._direction = direction - - else: - raise Exception('Wrong direction') + if ((direction == RIGHT or direction == LEFT or direction == UP or direction == DOWN) and + self._last_direction != (direction[0] * -1, direction[1] * -1)): + self._direction = direction - # The snake can only grow 1 field per tick -> grow can only be 1 or 0 to prevent errors + # The grow method adds a number to grow but not if this number is less than 1 def grow(self, g: int) -> None: if g > 0: - self._grow = 1 - - # TODO weitere Body teile hinzufügen? Nein? + self._grow += g + else: + # just to make sure that it resets if something goes wrong + self._grow = 0 + # step calculates with the head position and the direction the field the snake will now land on + # and checks whether this might lead to a crash or not and updates the game accordingly def step(self, forbidden: list[Item]) -> bool: - new_field = (self._occupies[0][0] + self._direction[0], self._occupies[0][1] + self._direction[1]) + new_field = (self.get_head()[0] + self._direction[0], self.get_head()[1] + self._direction[1]) + # forbidden fields are normally walls. for forbidden_field in forbidden: - print(f'{new_field} ?= {forbidden_field}') if forbidden_field.occupies(new_field[0], new_field[1]): return False + # This checks whether the snake already occupies the position and would bite itself if self.occupies(new_field[0], new_field[1]): return False + # This ensures the snake grows if necessary and also that it moves forward. self._occupies.insert(0, new_field) - if self._grow == 0: + if self._grow <= 0: self._occupies.pop() else: - self._grow = 0 + self._grow -= 1 + # The now last direction is saved. self._last_direction = self._direction return True -def main(): - width = 20 - height = 15 +class Cherry(Item): + def __init__(self) -> None: + super().__init__(0, 0) + + def draw(self, surface: pygame.Surface) -> None: + pygame.draw.ellipse(surface, + CHERRY_COLOR, + [TILE_SIZE * self._x, + TILE_SIZE * self._y, + TILE_SIZE, + TILE_SIZE] + ) + + def move(self, snake: Type[Snake], wall: list[tuple[int, int]], width: int, height: int, ) -> None: + occupied = True + # The loop generates random positions on the board + # as long as the cherry can't be placed on the generated position. + # If it can be placed there, because the position isn't occupied by a snake part or a brick + # it sets this position as new position. + while occupied: + x = random.randrange(0, width) + y = random.randrange(0, height) + if snake.occupies(x, y): + occupied = True + else: + for brick in wall: + if brick.occupies(x, y): + occupied = True + break + else: + occupied = False + + self._x = x + self._y = y + + +def main() -> None: + width = 30 + height = 20 speed = 7 pygame.init() @@ -169,9 +194,8 @@ def main(): clock = pygame.time.Clock() - # TODO: Spielobjekte anlegen - - # defines a wall on the outer coordinates of the field + # defines a wall on the outer coordinates of the field, a cherry + # and a snake positioned in the approximated field center wall = [ Brick(x, y) for x in range(width) @@ -181,9 +205,8 @@ def main(): cherry = Cherry() snake = Snake(width // 2, height // 2) + # To place the cherry on the field it needs to move once. cherry.move(snake, wall, width, height) - # TODO zusätzliche Steine im innern erstellen - # wall.append(Brick(7,7)) running = True while running: @@ -212,16 +235,17 @@ def main(): break running = snake.step(wall) - print(running) + + # update the snake's new position on the field snake.draw(screen) - cherry.draw(screen) - # TODO: Ueberpruefen, ob die Kirsche erreicht wurde, falls ja, wachsen und Kirsche bewegen. + # check if the Snake hits a cherry and if yes grow the snake and move the cherry. if cherry.occupies(snake.get_head()[0], snake.get_head()[1]): - snake.grow(1) + snake.grow(2) cherry.move(snake, wall, width, height) - # TODO: Kirsche zeichnen + # update the cherry's new position on the field + cherry.draw(screen) pygame.display.flip() clock.tick(speed) From 4ed1383706f6760e2a8fcf7cc54301d12fa81232 Mon Sep 17 00:00:00 2001 From: jannikvlk Date: Sun, 26 Dec 2021 11:18:02 +0100 Subject: [PATCH 6/9] Loosing Message with custom Font --- ressources/Elronmonospace.ttf | Bin 0 -> 31232 bytes snake.py | 23 ++++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 ressources/Elronmonospace.ttf diff --git a/ressources/Elronmonospace.ttf b/ressources/Elronmonospace.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c4b5f2acb87ee8c93e1f046ca1ca27c80bab01f2 GIT binary patch literal 31232 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 L`_G+|4?_MIaOSxN literal 0 HcmV?d00001 diff --git a/snake.py b/snake.py index 65eab3e..fcf8d07 100644 --- a/snake.py +++ b/snake.py @@ -1,7 +1,7 @@ -import pygame import random -from typing import Optional, List, Tuple, Type -import time +from typing import Tuple, Type + +import pygame TILE_SIZE = 30 @@ -250,6 +250,23 @@ def main() -> None: pygame.display.flip() clock.tick(speed) + font = pygame.font.SysFont('ressources/Elronmonospace.ttf', TILE_SIZE*3) + + # render text + message = font.render("You Loose!", 5, (200, 50, 50)) + message_w = message.get_width() + message_h = message.get_height() + screen.blit(message, (TILE_SIZE * width / 2 - message_w / 2, TILE_SIZE * height / 2 - message_h / 2)) + pygame.display.flip() + # If the game is finished the game doesn't quit imediately. It waits for the user to close the window. + waiting_to_quit = True + while waiting_to_quit: + for event in pygame.event.get(): + if event.type == pygame.QUIT: + # Spiel beenden + waiting_to_quit = False + break + pygame.display.quit() pygame.quit() From f0784c0434e1c6e65737257e47bf203d3d91fd5c Mon Sep 17 00:00:00 2001 From: jannikvlk Date: Sun, 26 Dec 2021 11:19:34 +0100 Subject: [PATCH 7/9] Added some comments --- snake.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/snake.py b/snake.py index fcf8d07..ea9c2ae 100644 --- a/snake.py +++ b/snake.py @@ -250,14 +250,17 @@ def main() -> None: pygame.display.flip() clock.tick(speed) - font = pygame.font.SysFont('ressources/Elronmonospace.ttf', TILE_SIZE*3) + font = pygame.font.SysFont('ressources/Elronmonospace.ttf', TILE_SIZE * 3) - # render text + # render loosing message message = font.render("You Loose!", 5, (200, 50, 50)) message_w = message.get_width() message_h = message.get_height() + + # place text in the middle of the screen screen.blit(message, (TILE_SIZE * width / 2 - message_w / 2, TILE_SIZE * height / 2 - message_h / 2)) pygame.display.flip() + # If the game is finished the game doesn't quit imediately. It waits for the user to close the window. waiting_to_quit = True while waiting_to_quit: From 50426e4ed48874a21c7fbc40e91e0a3b8533334a Mon Sep 17 00:00:00 2001 From: jannikvlk Date: Sun, 26 Dec 2021 11:23:41 +0100 Subject: [PATCH 8/9] Removed unnecessary files --- README.md | 2 -- test | 0 2 files changed, 2 deletions(-) delete mode 100644 README.md delete mode 100644 test diff --git a/README.md b/README.md deleted file mode 100644 index a1ecfac..0000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Snake -Vorlage für eine Übungsaufgabe \ No newline at end of file diff --git a/test b/test deleted file mode 100644 index e69de29..0000000 From 28061937dee5ef7452b49069b8ba1677b7af02d9 Mon Sep 17 00:00:00 2001 From: jannikvlk Date: Sun, 26 Dec 2021 12:03:16 +0100 Subject: [PATCH 9/9] Fixed Warnings --- snake.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/snake.py b/snake.py index ea9c2ae..e2904fe 100644 --- a/snake.py +++ b/snake.py @@ -1,5 +1,5 @@ import random -from typing import Tuple, Type +from typing import Tuple import pygame @@ -59,15 +59,14 @@ def __init__(self, x: int, y: int) -> None: # _occupies stores the positions (x and y coordinates) of every snake part self._occupies = [(x, y)] # _direction stores the direction the snake is headed, represented by x and y vectors. e.g. (1,0) means right - self._direction = tuple[int, int] - # _grow stores whether the snake still needs to grow a part because it ate a cherry. + self._direction = RIGHT + # _grow stores whether the snake still needs to grow aa part because it ate a cherry. self._grow = 0 # _last_direction stores the direction before the last direction change # to ensure the snake doesn't turn 180° at once because this would lead to a crash that is not intended - self._last_direction = RIGHT + self._last_direction = self._direction - # _direction and grow are now set by the corresponding method. - self.set_direction(self._last_direction) + # grow is now set by the corresponding method. self.grow(3) # get_head returns the position (x and y) of the head of the snake. @@ -158,12 +157,13 @@ def draw(self, surface: pygame.Surface) -> None: TILE_SIZE] ) - def move(self, snake: Type[Snake], wall: list[tuple[int, int]], width: int, height: int, ) -> None: + def move(self, snake: Snake, wall: list[Brick], width: int, height: int, ) -> None: occupied = True # The loop generates random positions on the board # as long as the cherry can't be placed on the generated position. # If it can be placed there, because the position isn't occupied by a snake part or a brick # it sets this position as new position. + x, y = 0, 0 while occupied: x = random.randrange(0, width) y = random.randrange(0, height) @@ -253,7 +253,7 @@ def main() -> None: font = pygame.font.SysFont('ressources/Elronmonospace.ttf', TILE_SIZE * 3) # render loosing message - message = font.render("You Loose!", 5, (200, 50, 50)) + message = font.render("You Loose!", True, (200, 50, 50)) message_w = message.get_width() message_h = message.get_height()