{"id":6594,"date":"2020-07-23T08:17:29","date_gmt":"2020-07-23T06:17:29","guid":{"rendered":"https:\/\/pythonprogramming.altervista.org\/?p=6594"},"modified":"2020-07-23T08:17:41","modified_gmt":"2020-07-23T06:17:41","slug":"snake-version-1","status":"publish","type":"post","link":"https:\/\/pythonprogramming.altervista.org\/snake-version-1\/","title":{"rendered":"Snake version 1"},"content":{"rendered":"<p>The code of the classic Snake game. First version. Version 2 in the next post.<\/p>\n<h2>The Gameplay<\/h2>\n<p>I would like to make some smooth movements, instead of going forwand of one &#8220;cell&#8221; at the time. Maybe in the next posts we could try to do that.<\/p>\n<div style=\"width: 747px;\" class=\"wp-video\"><video class=\"wp-video-shortcode\" id=\"video-6594-1\" width=\"747\" height=\"467\" preload=\"metadata\" controls=\"controls\"><source type=\"video\/mp4\" src=\"https:\/\/pythonprogramming.altervista.org\/wp-content\/uploads\/2020\/07\/snake1.mp4?_=1\" \/><a href=\"https:\/\/pythonprogramming.altervista.org\/wp-content\/uploads\/2020\/07\/snake1.mp4\">https:\/\/pythonprogramming.altervista.org\/wp-content\/uploads\/2020\/07\/snake1.mp4<\/a><\/video><\/div>\n<h2>The code of Snake<\/h2>\n<pre class=\"lang:default decode:true \">import pygame\r\nfrom pygame import gfxdraw\r\nfrom random import randrange\r\n\r\n\r\n# Define Constants\r\n\r\nBOARD_SIZE = 20  # Size of the board, in block\r\nBLOCK_SIZE = 20  # Size of 1 block, in pixel\r\nGAME_SPEED = 8  # Game speed (Normal = 10), The bigger, the faster\r\nSIZE = (BOARD_SIZE * BLOCK_SIZE, BOARD_SIZE * BLOCK_SIZE) # 400 x 400\r\n# Surface\r\nwindow = pygame.display.set_mode(SIZE)\r\npygame.display.set_caption(\"Python Snake\")\r\nscore = 0\r\n\r\n\r\n# ============================ THE SNAKE POSITION AND BEHAVIOUR ======\r\n\r\nclass Snake():\r\n    def __init__(self):\r\n        self.starting_position()\r\n\r\n    def starting_position(self):\r\n        \"The coordinates of the start and direction are here\"\r\n\r\n        self.head = [\r\n            # self.head[0] = x = 5\r\n            int(BOARD_SIZE \/ 4),\r\n            # self.head[1] = x = 5\r\n            int(BOARD_SIZE \/ 4)]\r\n        self.body = [[self.head[0], self.head[1]],\r\n                     [self.head[0] - 1, self.head[1]],\r\n                     [self.head[0] - 2, self.head[1]]\r\n                     ]\r\n        #   [ ][ ][ ] =&gt; right\r\n        self.direction = \"RIGHT\"\r\n        # Conditions to not go in the opposite direction\r\n\r\n    def direction_to(self, direction):\r\n        \"When you hit a key in the while loop; avoid going backwards\"\r\n        opposites = [(\"RIGHT\", \"LEFT\"),(\"UP\", \"DOWN\")]\r\n        for a, z  in opposites:\r\n            if self.direction == a:\r\n                if not direction == z:\r\n                    self.direction = direction\r\n                    break\r\n            if self.direction == z:\r\n                if not direction == a:\r\n                    self.direction = direction\r\n                    break\r\n\r\n    def move(self, food_pos):\r\n        moves = {\r\n        \"RIGHT\": (0, 1),\r\n        \"LEFT\": (0, -1),\r\n        \"UP\" : (1, -1),\r\n        \"DOWN\": (1, 1)\r\n        }\r\n        for k in moves:\r\n            if self.direction == k:\r\n                self.head[moves[k][0]] += moves[k][1]\r\n\r\n        self.body.insert(0, list(self.head))\r\n        if self.head == food_pos:\r\n            return 1\r\n        else:\r\n            \"If do not eat... same size\"\r\n            self.body.pop()\r\n            return 0\r\n\r\n    def check_collision(self):\r\n        # Checks collision with border or himself\r\n\r\n        conditions = (\r\n            # x\r\n            self.head[0] &gt;= 20 or self.head[0] &lt; 0,\r\n            # y\r\n            self.head[1] &gt; 19 or self.head[1] &lt; 0,\r\n            # self\r\n            [x for x in self.body[1:] if self.head == x]\r\n        )\r\n        if any(conditions):\r\n            return 1\r\n        else:\r\n            return 0\r\n\r\n# ============================= SPAWN FOOD =======================\r\n\r\nclass FoodSpawner():\r\n    def __init__(self):\r\n        self.food_pos = self.randompos()\r\n        self.there_is_food = True\r\n\r\n    def spawn_food(self):\r\n        if self.there_is_food == False:\r\n            self.food_pos = self.randompos()\r\n            self.there_is_food = True\r\n        return self.food_pos\r\n\r\n    def set_food_on_screen(self, bool_value):\r\n        self.there_is_food = bool_value\r\n\r\n    def randompos(self):\r\n        return [randrange(1, 20), randrange(1, 20)]\r\n\r\n\r\n# ===================== DRAW HEAD, BODY and FOOD ================\r\n\r\nclass Draw:\r\n    def draw_head(pos):\r\n        pygame.draw.rect(\r\n            window,\r\n            (0, 255, 0),\r\n            pygame.Rect(\r\n                pos[0] * BLOCK_SIZE,\r\n                pos[1] * BLOCK_SIZE,\r\n                BLOCK_SIZE,\r\n                BLOCK_SIZE))\r\n\r\n    def draw_body(pos):\r\n        pygame.draw.rect(window, (0, 128, 0), pygame.Rect(pos[0] * BLOCK_SIZE, pos[1] * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))\r\n\r\n    def delete_tail(pos):\r\n        pygame.draw.rect(window, (0, 0, 0), pygame.Rect(snake.body[-1][0] * BLOCK_SIZE, snake.body[-1][1] * BLOCK_SIZE, BLOCK_SIZE, BLOCK_SIZE))\r\n\r\n    def delete_fruit(pos, food_pos):\r\n        x = food_pos[0] * BLOCK_SIZE + 10\r\n        y = food_pos[1] * BLOCK_SIZE + 10\r\n        r = 9\r\n        gfxdraw.filled_circle(window, x, y, r, (0, 0, 0))\r\n\r\n    def draw_fruit(food_pos):\r\n        gfxdraw.filled_circle(window, food_pos[0] * BLOCK_SIZE + 10, food_pos[1] * BLOCK_SIZE + 10, 9, (255, 0, 0))\r\n\r\n    def text_surface(text_to_show, x=0, y=0, middle=\"both\"):\r\n        \"It write in the middle by default, if not middle='both' middle='x'\"\r\n        text = font.render(text_to_show, 1, pygame.Color(\"Coral\"))\r\n        if middle == \"x\":\r\n            text_rect = text.get_rect(center=((SIZE[0] \/\/ 2, y)))\r\n            window.blit(text, text_rect)      \r\n        elif middle == \"both\":\r\n            text_rect = text.get_rect(center=((SIZE[0] \/\/ 2, SIZE[1] \/\/ 2)))\r\n            window.blit(text, text_rect)\r\n        else:\r\n            window.blit(text, (x, y))\r\n        pygame.display.update()\r\n\r\n\r\n# ================================= MANAGE GAME PART =================\r\n\r\nclass Game:\r\n    clock = pygame.time.Clock()\r\n    \r\n    def restart():\r\n        global GAME_SPEED\r\n\r\n        GAME_SPEED = 8\r\n        window.fill((0, 0, 0))\r\n        snake.starting_position()\r\n        Game.start()\r\n\r\n\r\n    def press_to_start():\r\n        \"Initial menu\"\r\n        global loop, snake, food\r\n        global font, size\r\n\r\n        pygame.init()\r\n        font = pygame.font.SysFont(\"Arial\", 24)\r\n        snake = Snake()\r\n        food = FoodSpawner()\r\n        Draw.text_surface(\"Python vs Snake\", y=30, middle=\"x\")\r\n        Draw.text_surface(\"Press s to start\")\r\n        while True:\r\n            event = pygame.event.wait()\r\n            if event.type == pygame.QUIT:\r\n                loop = 0\r\n                break\r\n            if event.type == pygame.KEYDOWN:\r\n                if event.key == pygame.K_ESCAPE:\r\n                    loop = 0\r\n                    break\r\n                if event.key == pygame.K_s:\r\n                    Game.restart()\r\n                    break\r\n        pygame.quit()\r\n\r\n\r\n    def start():\r\n        global GAME_SPEED, score, loop\r\n\r\n        food_pos = food.spawn_food()\r\n        loop = 1\r\n        while loop:\r\n            if pygame.event.get(pygame.QUIT):\r\n                loop = 0\r\n            pygame.event.pump()\r\n            keys = pygame.key.get_pressed()\r\n            if keys[pygame.K_ESCAPE]:\r\n                loop = 0\r\n            if keys[pygame.K_UP]:\r\n                snake.direction_to(\"UP\")\r\n            if keys[pygame.K_DOWN]:\r\n                snake.direction_to(\"DOWN\")\r\n            if keys[pygame.K_RIGHT]:\r\n                snake.direction_to(\"RIGHT\")\r\n            if keys[pygame.K_LEFT]:\r\n                snake.direction_to(\"LEFT\")\r\n            if snake.move(food_pos) == 1:\r\n                # delete_fruit(pos, food_pos)\r\n                score += 1\r\n                food.set_food_on_screen(False)\r\n                GAME_SPEED += 1\r\n                food_pos = food.spawn_food()\r\n\r\n            head = 1\r\n            for pos in snake.body:\r\n                if head == 1:\r\n                    Draw.draw_head(pos)\r\n                    head = 0\r\n                else:\r\n                    Draw.draw_body(pos)\r\n            Draw.delete_tail(pos)\r\n            Draw.draw_fruit(food_pos)\r\n\r\n            if snake.check_collision() == 1:\r\n                loop = 0\r\n                Game.press_to_start()\r\n            pygame.display.update()\r\n            Game.clock.tick(GAME_SPEED)\r\n\r\n        pygame.quit()\r\n\r\nGame.press_to_start()\r\n<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"Pygame and the classic Snake\n<a class=\"moretag\" href=\"https:\/\/pythonprogramming.altervista.org\/snake-version-1\/\"> [...]<\/a>","protected":false},"author":1,"featured_media":6596,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","footnotes":""},"categories":[191],"tags":[847,137,194,4,520],"class_list":["post-6594","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-pygame","tag-classic","tag-game","tag-pygame","tag-python","tag-snake"],"avopt_banners_inside_post":true,"avopt_banners_on_page":true,"av_copy_from":"","av_sharing_message":"","av_sharing_allowed":true,"av_sharing_on":{"fb":[],"tw":[]},"av_allow_affiliate_banner":false,"av_allow_affiliate_multi_banner":false,"av_show_affiliation_buy_button":false,"av_post_rating":true,"av_have_post_rating_value":false,"av_is_artificial_intelligence_content":false,"_links":{"self":[{"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/posts\/6594","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/comments?post=6594"}],"version-history":[{"count":1,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/posts\/6594\/revisions"}],"predecessor-version":[{"id":6597,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/posts\/6594\/revisions\/6597"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/media\/6596"}],"wp:attachment":[{"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/media?parent=6594"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/categories?post=6594"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pythonprogramming.altervista.org\/wp-json\/wp\/v2\/tags?post=6594"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}