|
| 1 | +from goopylib.imports import * # imports everything (* means everything) from goopylib |
| 2 | +import random |
| 3 | + |
| 4 | +# Makes a square window with title as 'Snake Game', and width and height of 600 |
| 5 | +window = Window(title="Snake Game", width=600, height=600, icon="WindowIcon.ico") |
| 6 | + |
| 7 | +# Alternates values between 0 and 1 and colours the rectangles in the grid according to its value |
| 8 | +# if colour_value is 0, then the rectangle is light |
| 9 | +# if colour_value is 1, then the rectangle is dark |
| 10 | +colour_value = 0 |
| 11 | + |
| 12 | +for x in range(20): # for each square on the x axis, do the y for loop |
| 13 | + # there are 21 squares on the y-axis to make it an even number, the 21st layer of squares is hidden |
| 14 | + # because it is outside the window |
| 15 | + for y in range(21): # for each square on the y axis, do whatever is inside this for loop |
| 16 | + |
| 17 | + # Scale the value of x and y (which go from 0-19) by 30 so that they go from 0-570 |
| 18 | + x_pos = x * 30 # the size of each square is 30 pixels |
| 19 | + y_pos = y * 30 # multiplying the x and y value by 30 gives us the start position of each square |
| 20 | + |
| 21 | + # 0 -> 0 |
| 22 | + # 1 -> 30 |
| 23 | + # 2 -> 60 |
| 24 | + # ... |
| 25 | + |
| 26 | + # If colour_value is 0, the square is light |
| 27 | + # If colour_value is 1, the square is dark |
| 28 | + |
| 29 | + # The square_colour variable is used to keep a track of which colour the rectangle is |
| 30 | + |
| 31 | + # flips the value of colour_value between 0 & 1 so that a square of an alternating colour is created each time |
| 32 | + if colour_value == 0: # if colour_value is 0, flip the value to 1 |
| 33 | + colour_value = 1 |
| 34 | + square_colour = DARK_NAVY_BLUE |
| 35 | + |
| 36 | + elif colour_value == 1: # if colour_value is 1, flip the value to 0 |
| 37 | + colour_value = 0 |
| 38 | + square_colour = DARKER_NAVY_BLUE |
| 39 | + |
| 40 | + # Makes the rectangles at the x_pos and y_pos which square_colour as the colour and no outline |
| 41 | + Rectangle([x_pos, y_pos], [x_pos + 30, y_pos + 30], fill=square_colour, outline_width=0).draw(window) |
| 42 | + |
| 43 | +# ---------------------------------------------------------------------------------------------------------------------- |
| 44 | +# Title & Subtitle Part |
| 45 | + |
| 46 | +title = Text([300, 100], "SNAKE GAME", font_colour=WHITE, font_size=40, font_face="courier new", font_style="bold").draw(window) |
| 47 | +subtitle = Text([300, 150], "Click to Start", font_colour=WHITE, font_size=15, font_face="courier new", font_style="bold").draw(window) |
| 48 | + |
| 49 | +window.get_left_mouse_click() # waits until the user clicks the window |
| 50 | + |
| 51 | +title.destroy() |
| 52 | + |
| 53 | +subtitle.glide_y(-100, time=0.5, easing=py_ease_sin_out) |
| 54 | +subtitle.set_text("Score: 0") |
| 55 | +score = 0 |
| 56 | + |
| 57 | +snake_directions = ["0", "0", "0"] # List of the directions of each block in the snake, the head has a direction 'right' |
| 58 | + |
| 59 | +# right right 0 |
| 60 | +# right right right |
| 61 | + |
| 62 | +snake_squares = [Rectangle([150, 300], [180, 330], fill=LIGHTISH_BLUE, outline_width=0, layer=1).draw(window), |
| 63 | + Rectangle([150, 300], [180, 330], fill=LIGHTISH_BLUE, outline_width=0, layer=1).draw(window), |
| 64 | + Rectangle([150, 300], [180, 330], fill=LIGHTISH_BLUE, outline_width=0, layer=1).draw(window)] |
| 65 | + |
| 66 | +# [x, y] |
| 67 | +apple_position = [random.randint(0, 19) * 30 + 15, random.randint(0, 19) * 30 + 15] |
| 68 | +# between [0, 0] and [19, 19] |
| 69 | +apple = Circle(apple_position, 10, fill=LIGHTISH_RED).draw(window) |
| 70 | +apple.animate_blinking(0.2) # blinks the apple at a rate of 0.2 seconds |
| 71 | + |
| 72 | +apple_eaten = False |
| 73 | + |
| 74 | +# the mainloop |
| 75 | +while window.is_open(): |
| 76 | + window.update() |
| 77 | + update(6) # runs the loop at a rate of 4 frames per second (FPS) |
| 78 | + |
| 79 | + # WASD and Left, Down, Right, Up |
| 80 | + |
| 81 | + key_pressed = window.check_key_press() |
| 82 | + |
| 83 | + snake_directions.pop() # removes the last value in the list |
| 84 | + |
| 85 | + new_dir = snake_directions[0] # sets the default value of new_dir to the direction of the head |
| 86 | + if (key_pressed == "Right" or key_pressed == "d") and new_dir != "left": |
| 87 | + new_dir = "right" |
| 88 | + elif (key_pressed == "Left" or key_pressed == "a") and new_dir != "right": |
| 89 | + new_dir = "left" |
| 90 | + elif (key_pressed == "Up" or key_pressed == "w") and new_dir != "down": |
| 91 | + new_dir = "up" |
| 92 | + elif (key_pressed == "Down" or key_pressed == "s") and new_dir != "up": |
| 93 | + new_dir = "down" |
| 94 | + |
| 95 | + snake_directions.insert(0, new_dir) |
| 96 | + |
| 97 | + position = snake_squares[0].get_anchor() # get_anchor() returns the position of an object |
| 98 | + # position = [x, y] |
| 99 | + |
| 100 | + if position == apple_position: # checks if the snake position is equal to the apple position |
| 101 | + apple_position = [random.randint(0, 19) * 30 + 15, random.randint(0, 19) * 30 + 15] # gets a new apple position |
| 102 | + apple.move_to_point(apple_position) # moves the apple to the new position |
| 103 | + |
| 104 | + score = score + 1 # increments the score by 1 every time the snake eats an apple |
| 105 | + subtitle.set_text(f"Score: {score}") |
| 106 | + |
| 107 | + snake_directions.append("0") # adds an extra 0 direction to the end of the list |
| 108 | + new_square = Rectangle([150, 300], [180, 330], fill=LIGHTISH_BLUE, outline_width=0, layer=1).draw(window) |
| 109 | + new_square.move_to_point(snake_squares[-1].get_anchor()) |
| 110 | + snake_squares.append(new_square) # adds a copy of the tail square to the snake_square list |
| 111 | + |
| 112 | + apple_eaten = True |
| 113 | + |
| 114 | + # len(...) gives the length of the list |
| 115 | + for x in range(0, len(snake_squares)): # x goes 0, then 1, then 2, etc. |
| 116 | + |
| 117 | + if snake_directions[x] == "right": |
| 118 | + snake_squares[x].move_x(30) |
| 119 | + |
| 120 | + elif snake_directions[x] == "left": |
| 121 | + snake_squares[x].move_x(-30) |
| 122 | + |
| 123 | + elif snake_directions[x] == "up": |
| 124 | + snake_squares[x].move_y(-30) |
| 125 | + |
| 126 | + elif snake_directions[x] == "down": |
| 127 | + snake_squares[x].move_y(30) |
| 128 | + |
| 129 | + touching_self = False |
| 130 | + if apple_eaten: |
| 131 | + # list slicing [1:] -> returns all the values from the list from the first index to the last |
| 132 | + for square in snake_squares[1:]: # goes through each square in the snake except the head |
| 133 | + if square.get_anchor() == position: # checks if the head's position is the same as the other square |
| 134 | + touching_self = True |
| 135 | + |
| 136 | + # position[0] is the x value and position[1] is the y value |
| 137 | + if touching_self or (position[0] < 0) or (position[1] < 0) or (position[0] > 600) or (position[1] > 600): |
| 138 | + |
| 139 | + # the snake has hit the boundary, it dies |
| 140 | + |
| 141 | + # destroys the snake |
| 142 | + for square in snake_squares: # go through each value in snake_squares, and call the variable 'square' |
| 143 | + square.destroy() # remove the square |
| 144 | + window.update() # update the window so that it can remove the square |
| 145 | + time.sleep(0.1) # wait for 0.1 seconds |
| 146 | + |
| 147 | + # score and game over text |
| 148 | + |
| 149 | + title = Text([300, -100], "GAME OVER", font_colour=WHITE, font_size=40, font_face="courier new", font_style="bold").draw(window) |
| 150 | + subtitle.glide_y(100, time=0.5, easing=py_ease_sin_out) |
| 151 | + title.glide_y(200, time=0.5, easing=py_ease_sin_out) |
| 152 | + |
| 153 | + apple.destroy() |
| 154 | + |
| 155 | + while window.is_open(): |
| 156 | + window.update() |
0 commit comments