Advertisement
Guest User

Untitled

a guest
Jan 24th, 2017
85
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.41 KB | None | 0 0
  1. >># The "new" section creates new objects that spawn into the game, such as the player's character.
  2. def new(self):
  3. # Start a new game
  4. # Sets player's starting score to 0.
  5. self.score = 0
  6. # We add a sprite group
  7. self.all_sprites = pg.sprite.Group()
  8. # A platforms group
  9. self.platforms = pg.sprite.Group()
  10. # A powerups group
  11. self.powerups = pg.sprite.Group()
  12. # A players group
  13. self.player = Player(self)
  14. >for plat in PLATFORM_LIST:
  15. # The next line takes the list platform on the settings page, and explodes it, gathering each variable from inside the list (this is just a shorter way of coding it)
  16. Platform(self, *plat)
  17.  
  18.  
  19. # Implements music into the game:
  20. # The following line means that the music file is queued up and ready to play.
  21. pg.mixer.music.load(path.join(self.sound_dir, 'gba1complete.ogg'))
  22. self.run()
  23.  
  24. # The next run function is the start of my game loop.
  25. def run(self):
  26. # Game Loop
  27. #Plays music:
  28. #music.play() would normally only play the music track once, however there is a loop option. The -1 value means infinitely loop the track, which is what I want to happen.
  29. pg.mixer.music.play(loops=-1)
  30. self.playing = True
  31. while self.playing:
  32. # This will start the clock when the player starts playing
  33. self.clock.tick(FPS)
  34. self.events()
  35. self.update()
  36. self.draw()
  37. #Music ends, fadeout instead of stop (milliseconds)
  38. pg.mixer.music.fadeout(3000)
  39. def update(self):
  40. # Game Loop - Update
  41. self.all_sprites.update()
  42. # The following initiates a collision check for the player's character:
  43. # Checks if player hits a platform - only if falling (y velocity is above 0)
  44. if self.player.vel.y > 0:
  45. hits = pg.sprite.spritecollide(self.player, self.platforms, False)
  46. if hits:
  47. # Line below says that we are only going to snap to the platform if our feet are higher than the platform.
  48. # REVISIT
  49. # REVISIT
  50. # REVISIT
  51. # REVISIT
  52. # REVISIT
  53. # The following mini section explains how I prevented overlapping snaps causing problems.
  54. lowest = hits[0]
  55. # We then compare the other hits
  56. for hit in hits:
  57. # See if any are lower than the first:
  58. if hit.rect.bottom > lowest.rect.centery:
  59. lowest = hit
  60. if self.player.pos.x < lowest.rect.right + 10 and
  61. self.player.pos.x > lowest.rect.left -10:
  62.  
  63. if self.player.pos.y < lowest.rect.centery:
  64. # If the player has collided with an object, then we want the player to stop falling in the y direction at that point.
  65. self.player.pos.y = lowest.rect.top
  66. # The next line sets the character's velocity to 0, so they do not carry on falling through the object at all. This allows us to run along it also.
  67. self.player.vel.y = 0
  68. self.player.jumping = False
  69. # If the player reaches right 1/4 of the screen
  70. if self.player.rect.right >= WIDTH -400 :
  71. # The next line moves the camera as the player moves (by the same velocity)
  72. self.player.pos.x -= (self.player.vel.x)
  73. # Next few lines move all of the platforms in the platform list on the settings page.
  74. for plat in self.platforms:
  75. # The next line means that the platforms stay behind once the player has moved.
  76. plat.rect.x -= (self.player.vel.x)
  77.  
  78. # The next iteration loop is very similar to the previous one, however it works for the left side of the screen.
  79. if self.player.rect.right <= WIDTH -700 :
  80. # Here we set our boundary to the left (WIDTH - 700).
  81. self.player.pos.x -= (self.player.vel.x)
  82. # Then we move the platforms forwards, so we can retrace our steps in a level.
  83. for plat in self.platforms:
  84. plat.rect.x -= (self.player.vel.x)
  85. if plat.rect.right <= WIDTH - 10000:
  86. plat.kill()
  87.  
  88. # If the player dies:
  89. # If the player hits the bottom of the screen:
  90. if self.player.rect.bottom > HEIGHT:
  91. # Next loop scrolls platforms upwards when player falls off the map to make the game more realistic.
  92. for sprite in self.all_sprites:
  93. # We do not want to scroll the platforms at a constant speed, as this is not realistic, however we want to set a max number, and using the max function here means we pick the max number between the player's vel and 10.
  94. sprite.rect.y -= max(self.player.vel.y, 10)
  95. # The next two lines kill all sprites when they reache the bottom of the screen.
  96. if sprite.rect.bottom < 0:
  97. sprite.kill()
  98. # The next line ends the game when the legnth of the platforms is zero, as we have gotten rid of them all.
  99. if len(self.platforms) == 0:
  100. # The next line lets the game know that the player's character is dead, and therefore ends the game session.
  101. self.playing = False
  102.  
  103. def events(self):
  104. # Game Loop - events
  105. for event in pg.event.get():
  106. # check for closing window
  107. if event.type == pg.QUIT:
  108. if self.playing:
  109. self.playing = False
  110. self.running = False
  111. # Below is an IF loop that determines if the player's character should be jumping or not.
  112. if event.type == pg.KEYDOWN:
  113. # First we establish that a key is being pressed, and then identify if it is the spacebar (or jump button)
  114. if event.key == pg.K_SPACE:
  115. self.player.jump()
  116.  
  117.  
  118.  
  119. def draw(self):
  120. # Game Loop - draw
  121. self.screen.fill(CYAN)
  122. self.all_sprites.draw(self.screen)
  123. self.draw_text(str(self.score), 22, BLACK, WIDTH / 2, 15)
  124. # *after* drawing everything, flip the display
  125. pg.display.flip()
  126.  
  127. def show_start_screen(self):
  128. # game splash/start screen
  129. #Loads music again, can use a different track
  130. pg.mixer.music.load(path.join(self.sound_dir, 'gba1complete.ogg'))
  131. pg.mixer.music.play(loops=-1)
  132. # Fill the start screen background colour as brown to match our survival theme
  133. self.screen.fill(BROWN)
  134. # We display our string for 'TITLE', then choose font size, colour and choose where to display it on the screen.
  135. self.draw_text(TITLE, 48, WHITE, WIDTH / 2, HEIGHT / 4)
  136. # We display some information on how to play the game to the user
  137. self.draw_text("A and D Keys to move, Spacebar to jump!", 24, WHITE, WIDTH /2, HEIGHT / 2)
  138. # We tell the user how to initiate the game
  139. self.draw_text("Press any key to play", 24, WHITE, WIDTH / 2, HEIGHT * 3 / 4)
  140. # We display the high score on the starting screen:
  141. self.draw_text("High Score: " + str(self.highscore), 22, BROWN, WIDTH / 2, 15)
  142.  
  143. # We flip the display so that the user actually sees this taking place
  144. pg.display.flip()
  145. self.wait_for_key()
  146. # This time I want to music to stop immediately.
  147. pg.mixer.music.stop
  148.  
  149. def show_go_screen(self):
  150. # game over/continue
  151. if not self.running:
  152. # Return meaning end the function
  153. return
  154. # music
  155. pg.mixer.music.load(path.join(self.sound_dir, 'gba1complete.ogg'))
  156. pg.mixer.music.play(loops=-1)
  157. # Choose a background colour for the end screen
  158. self.screen.fill(BROWN)
  159. # Display game over
  160. self.draw_text("Game Over", 48, WHITE, WIDTH / 2, HEIGHT / 4)
  161. # Display the users score
  162. self.draw_text("Score: " + str(self.score), 24, WHITE, WIDTH /2, HEIGHT / 2)
  163. # Tell them how to restart the game
  164. self.draw_text("Press any key to play again", 24, WHITE, WIDTH / 2, HEIGHT * 3 / 4)
  165. # The following small section of code determines what message the player recieves - whether the player gets congratulated or commiserations.
  166. if self.score > self.highscore:
  167. self.highscore = self.score
  168. # The following line explains to the player that they have just got a new high score:
  169. self.draw_text("New High Score!", 22, BROWN, WIDTH / 2, HEIGHT / 2 + 40)
  170. with open(path.join(self.dir, HS_FILE), 'w') as f:
  171. # Then we write over the high score file and save it as a string because it is a text file.
  172. f.write(str(self.score))
  173. # Following line shows what happens if the player does not get a high score (displays current high score).
  174. else:
  175. self.draw_text("High Score: " + str(self.highscore), 22, BROWN, WIDTH / 2, HEIGHT / 2 + 40)
  176. # Enable the user to see this
  177. pg.display.flip()
  178. # Tells the program to stop and waits for the player to input a key to continue
  179. self.wait_for_key()
  180.  
  181. pg.mixer.music.stop
  182.  
  183. # The following method can be used in both show_start_screen and show_go_screen (end screen) to make the game wait for the player to press a key.
  184. def wait_for_key(self):
  185. # We set a variable to true.
  186. waiting = True
  187. # Then we create a while loop so that we can choose when the game waits and when the game continues.
  188. while waiting:
  189. # The next line chooses to run the start/end screen at the chosen FPS. We have defined FPS in the settings page so I will use this.
  190. self.clock.tick(FPS)
  191. for event in pg.event.get():
  192. if event.type == pg.QUIT:
  193. # To leave this screen when the player presses QUIT, we end our loop
  194. waiting = False
  195. # Then because we want our whole program to end, we also need to set running to false.
  196. self.running = False
  197. # Any other key on the keyboard
  198. if event.type == pg.KEYUP:
  199. waiting = False
  200.  
  201. #The following method shows the text in my game.
  202. def draw_text(self, text, size, colour, x, y):
  203. # The next line gets the font object.
  204. font = pg.font.Font(self.font_name, size)
  205. # Next we render a surface for the font to be displayed on.
  206. # The 'True' value is my choice of whether to use anti-aliasing or not, I chose true as I believe it will make my game look smoother.
  207. text_surface = font.render(text, True, colour)
  208. # Then we generate a rectangle to help us generate it on the screen.
  209. text_rect = text_surface.get_rect()
  210. # Next we place it
  211. text_rect.midtop = (x, y)
  212. # Then we blit it onto the screen
  213. self.screen.blit(text_surface, text_rect)
  214. >g = Game()
  215. g.show_start_screen()
  216. while g.running:
  217. g.new()
  218. g.show_go_screen()
  219. pg.quit()
  220.  
  221. >import pygame as pg
  222. from Settings import *
  223. # This allows pygame to access vectors.
  224. vec = pg.math.Vector2
  225.  
  226. # Technically this is not a sprite, but it is another class to define so:
  227. class Spritesheet:
  228. # Utility class for loading and parsing (reading through the data file, understanding what it means) spritesheets
  229. # We will only need to pass it the filename
  230. def __init__(self, filename):
  231. # Here we load the spritesheet's filename and convert it
  232. self.spritesheet = pg.image.load(filename).convert()
  233.  
  234. # The following function lets us pick an image from the spritesheet.
  235. def get_image(self, x, y, width, height):
  236. # First we make a surface to put the image on:
  237. image = pg.Surface((width, height))
  238. # image.blit - Blit it onto this image # (self.spritesheet, - We take this spritesheet
  239. #(0, 0), - Blit it at this location # (x, y, width, height)) - Choose this chunk
  240. image.blit(self.spritesheet, (0, 0), (x, y, width, height))
  241. # Then we return the image
  242. # Below I will scale my image so that the character is the correct size for the game, as initially it was far too large.
  243. # The double slash rounds the number to the nearest integer, so there are no errors.
  244. image = pg.transform.scale(image, (width // 2, height // 2))
  245. return image
  246. # The following section creates the image/character model e.g. size etc.
  247. class Player(pg.sprite.Sprite):
  248. # The use of 'game' in the parameter below means that the player knows about the variables from the 'main page'.
  249. def __init__(self, game):
  250. # Adds the player class to the group.
  251. self.groups = game.all_sprites
  252. # Here we set up the Sprite object.
  253. pg.sprite.Sprite.__init__(self, self.groups)
  254. # The line below is a 'copy' or a referance that the player class can use so that it knows about the game.
  255. self.game = game
  256. # The following line lets the game know whether the player is walking.
  257. self.walking = False
  258. # The following line lets the game know whether the player is jumping.
  259. self.jumping = False
  260. # The following line asks the game what frame is currently playing.
  261. self.current_frame = 0
  262. # The following variable keeps track of what time we made the last change, as each frame would be too fast, (60 per second!)
  263. self.last_update = 0
  264. # We choose for the player's image to be at the forefront, rather than the background.
  265. # The load_images method is called shortly after this section of code.
  266. self.load_images()
  267. self.image = self.standing_frames[0]
  268. # The line below removes the unwanted border around the player's character.
  269. self.image.set_colorkey(BLACK)
  270. self.rect = self.image.get_rect()
  271. # For example, the next line determines where the center of the rectangle that we have just created is, so that the game knows how to affect movement/hitboxes for the player's character.
  272. self.rect.center = (WIDTH / 2, HEIGHT /2)
  273. self.pos = vec(WIDTH / 2, HEIGHT / 2)
  274. self.vel = vec(0, 0)
  275. self.acc = vec(0, 0)
  276.  
  277. # The following method load_images allows me to load all of the frames that are used for the character's animation.
  278. def load_images(self):
  279. # I start with the two standing frames:
  280. self.standing_frames = [self.game.spritesheet.get_image(614, 1063, 120, 191),
  281. self.game.spritesheet.get_image(690, 406, 120, 201)]
  282. for frame in self.standing_frames:
  283. frame.set_colorkey(BLACK)
  284. # Now I am going to assign my two walking frames for walking right:
  285. self.walk_frames_r = [self.game.spritesheet.get_image(678, 860, 120, 201),
  286. self.game.spritesheet.get_image(692, 1458, 120, 207)]
  287. # Now walk frames for the left direction:
  288. self.walk_frames_l = []
  289. # Now we will append the right ones to the left facing lists, and flip them:
  290. for frame in self.walk_frames_r:
  291. frame.set_colorkey(BLACK)
  292. # Here the true and false represent whether I want a horizontal flip and then a vertical flip.
  293. self.walk_frames_l.append(pg.transform.flip(frame, True, False))
  294. # Now the jumping frame:
  295. self.jump_frame = self.game.spritesheet.get_image(382, 763, 150, 181)
  296. self.jump_frame.set_colorkey(BLACK)
  297.  
  298. # The following is a jump function that allows the player to gain velocity in the upwards direction.
  299. def jump(self):
  300. # The line below makes the character collide with the platform, however there is no drawing so the player doesn't see this.
  301. self.rect.x += 1
  302. # The next line initiates the collision, as we have done before. We collide the character with the game's platforms.
  303. hits = pg.sprite.spritecollide(self, self.game.platforms, False)
  304. # The following line means that our character is moved back up 3 spaces. The player never sees this because no drawing of it is done.
  305. self.rect.x -= 3
  306. # The next few lines mean that if there is collision, we can jump.
  307. if hits:
  308. # Now we play the jump sound at the same time as jumping:
  309. self.game.jump_sound.play()
  310.  
  311.  
  312. # The value below is the strength of the jump.
  313. self.vel.y = -PLAYER_JUMP
  314.  
  315. # The next section creates player movement. E.g. when certain keys are pressed, the character moves in the corresponding direction.
  316. def update(self):
  317. # The following method animates and handles which frame we want to use:
  318. self.animate()
  319.  
  320. # Below I have set vertical acceleration (gravity) to the variable PLAYER_GRAV, which can be found in the Settings page, allowing the character to fall.
  321. self.acc = vec(0, PLAYER_GRAV)
  322. keys = pg.key.get_pressed()
  323. # Here, if the left key is pressed, the player will move left and so on.
  324. if keys[pg.K_a]:
  325. self.acc.x = -PLAYER_ACC
  326. if keys[pg.K_d]:
  327. self.acc.x = PLAYER_ACC
  328.  
  329. # Applies friction by reducing acceleration
  330. # By adding .x after self.acc and self.vel, gravity is allowed to work properly as we can speed up faster in the y direction.
  331. self.acc.x += self.vel.x * PLAYER_FRICTION
  332. # Equations of motion
  333. self.vel += self.acc
  334. # The following two lines mean that if we are moving less than 0.1 of a pixel per tick, the player's velocity will get set to 0. This is so that our walking animations stop when we are standing still.
  335. if abs(self.vel.x) < 0.1:
  336. # Velocity is set to 0.
  337. self.vel.x = 0
  338. self.pos += self.vel + 0.5 * self.acc
  339. #Wrap around the sides of the screen
  340. if self.pos.x > WIDTH:
  341. self.pos.x = 0
  342. if self.pos.x < 0:
  343. self.pos.x = WIDTH
  344.  
  345. # The next line lets the game know that I want the center of the player's character to be considered the center of the screen.
  346. self.rect.midbottom = self.pos
  347.  
  348. # The recently referred to animate method is used:
  349. def animate(self):
  350. # Find out how many ticks have occured since the game was opened:
  351. now = pg.time.get_ticks()
  352.  
  353. # The following small section determines if the player is standing still or not.
  354. # Is the player still?
  355. if self.vel.x != 0:
  356. # If they are not still, then walking is true.
  357. self.walking = True
  358. else:
  359. # If they are still, then walking is false.
  360. self.walking = False
  361.  
  362. # Show Walk Animation:
  363. if self.walking:
  364. # here we set the frequency of the occuring updates (milliseconds)
  365. if now - self.last_update > 100:
  366. # We call for an update
  367. self.last_update = now
  368. # We almost copy what we used for the update loop below
  369. self.current_frame = (self.current_frame + 1) % len(self.walk_frames_l)
  370. # We set the bottom of the sprite to the right location whilst we are walking
  371. bottom = self.rect.bottom
  372. # Before we set the image for the next frame, we decide if we are walking left or right:
  373. if self.vel.x > 0:
  374. # If our velocity is more than 0, we are clearly moving right
  375. self.image = self.walk_frames_r[self.current_frame]
  376. else:
  377. # If our velocity is less than 0, we are clearly moving left
  378. self.image = self.walk_frames_l[self.current_frame]
  379. # We request our new rectangle to find the bottom of the character with
  380. self.rect = self.image.get_rect()
  381. # We then set the bottom of the character's hitbox again.
  382. self.rect.bottom = bottom
  383.  
  384. # If the player is idle, we want to display the standing frame:
  385. if not self.jumping and not self.walking:
  386. # The following is in milliseconds, and determines the time lapse since the last update:
  387. if now - self.last_update > 280:
  388. # We call for an update to occur now:
  389. self.last_update = now
  390. # Now we change the current frame.
  391. self.current_frame = (self.current_frame + 1) % len(self.standing_frames)
  392. # The bottom variable holds where the bottom of our player's rectangle needs to be.
  393. bottom = self.rect.bottom
  394. self.image = self.standing_frames[self.current_frame]
  395. # the following line gets the new rectangle for the new frame we switched to.
  396. self.rect = self.image.get_rect()
  397. # the next line keeps the 'bottom' variable that we had for the last frame.
  398. self.rect.bottom = bottom
  399.  
  400. # The next class defines all of the platforms in the game.
  401. class Platform(pg.sprite.Sprite):
  402. # The next line shows how when we want to create a new platform object, we will give it a x and a y coordinate, along with a width and a height.
  403. def __init__(self, game, x, y):
  404. # Adds the platform class to the group.
  405. self.groups = game.all_sprites, game.platforms
  406. pg.sprite.Sprite.__init__(self, self.groups)
  407. self.game = game
  408. # First, we create the image.
  409. self.image = pg.Surface((w, h))
  410. # Hext, we choose a colour for the platform.
  411. self.image.fill(BROWN)
  412. # We make it a rectangular shape.
  413. self.rect = self.image.get_rect()
  414. # Then we place it at it's predetermined coordinates.
  415. self.rect.x = x
  416. self.rect.y = y
  417.  
  418. #Powerups class
  419. class Pow(pg.sprite.Sprite):
  420. # I pass the class 'self', 'game' and 'plat'.
  421. def __init__(self, game, plat):
  422. # I create my list of groups:
  423. self.groups = game.all_sprites, game.powerups
  424. # I then initialise them (including groups):
  425. pg.sprite.Sprite.__init__(self, self.groups)
  426. # The following line allows me to use 'game'
  427. self.game = game
  428. # The following line allows me to use 'plat'
  429. self.plat = plat
  430. # Now we need different types of platforms.
  431. # The first type I am creating is called 'boost', it will shoot the player upwards a litte bit.
  432. self.type = choice(['boost'])
  433. # This is the art that will be used for my 'boost' powerup.
  434. self.image = self.game.spritesheet.get_image(820, 1805, 71, 70)
  435. self.image.set_colorkey(BLACK)
  436. self.rect = self.image.get_rect()
  437. # The following line sets the powerup's location to the center of the platform.
  438. self.rect.centerx = self.plat.rect.centerx
  439.  
  440. self.rect.bottom = self.plat.rect.top - 5
  441.  
  442.  
  443. def update(self):
  444.  
  445. self.rect.bottom = self.plat.rect.top -5
  446.  
  447. if not self.game.platforms.has(self.plat):
  448. # If this loop returns false, we will delete the powerup as well.
  449. self.kill()
  450.  
  451. >TITLE = "Survival Game"
  452. WIDTH = 1000
  453. HEIGHT = 800
  454. FPS = 60
  455.  
  456. HS_FILE = "highscore.txt"
  457.  
  458.  
  459. PLAYER_ACC = 0.5
  460. PLAYER_FRICTION = -0.12
  461.  
  462.  
  463. PLAYER_GRAV = 0.3
  464. PLAYER_JUMP = 10
  465. FONT_NAME = 'Echelon'
  466. SPRITESHEET = "spritesheet_jumper.png"
  467.  
  468. # Starting platforms
  469. # The following list includes all the platforms I am going to be using in my game, and each platform takes in four values each. The x and y coordinates, and also the height and width of the platforms themselves.
  470. # (x, y, Width, Height)
  471. PLATFORM_LIST = [
  472. # Floor platforms
  473. (0, HEIGHT - 40, WIDTH + 500, 40),
  474. (2200, HEIGHT - 40, WIDTH + 100, 40),
  475. (4000, HEIGHT - 40, WIDTH + 100, 40),
  476. (6000, HEIGHT - 40, WIDTH + 100, 40),
  477.  
  478. # Starting 3 platforms
  479. (650, HEIGHT - 125, WIDTH - 600, 20),
  480. (650, HEIGHT - 250, WIDTH - 600, 20),
  481. (650, HEIGHT - 375, WIDTH - 600, 20),
  482. # Middle Layer of short platforms
  483. (1100, HEIGHT - 250, WIDTH - 800, 30),
  484. (1500, HEIGHT - 250, WIDTH - 800, 30),
  485. (2000, HEIGHT - 250, WIDTH - 800, 30),
  486. (2500, HEIGHT - 250, WIDTH - 800, 30),
  487. (3000, HEIGHT - 250, WIDTH - 800, 30),
  488. (3500, HEIGHT - 250, WIDTH - 800, 30),
  489.  
  490. # Lower Layer of short platforms
  491. (1175, HEIGHT - 180, WIDTH - 800, 30),
  492. (1575, HEIGHT - 180, WIDTH - 800, 30),
  493. (2075, HEIGHT - 180, WIDTH - 800, 30),
  494. (2575, HEIGHT - 180, WIDTH - 800, 30),
  495. (3075, HEIGHT - 180, WIDTH - 800, 30),
  496. (3575, HEIGHT - 180, WIDTH - 800, 30),
  497.  
  498. # Upper Layer of short platforms
  499. (1150, HEIGHT - 320, WIDTH - 800, 30),
  500. (1550, HEIGHT - 320, WIDTH - 800, 30),
  501. (2050, HEIGHT - 320, WIDTH - 800, 30),
  502. (2550, HEIGHT - 320, WIDTH - 800, 30),
  503. (3050, HEIGHT - 320, WIDTH - 800, 30),
  504. (3550, HEIGHT - 320, WIDTH - 800, 30),
  505.  
  506. # In between platforms (Lowest)
  507. (1250, HEIGHT - 115, WIDTH - 800, 30),
  508. (1750, HEIGHT - 115, WIDTH - 800, 30),
  509. (2250, HEIGHT - 115, WIDTH - 800, 30),
  510. (2750, HEIGHT - 115, WIDTH - 800, 30),
  511. (3250, HEIGHT - 115, WIDTH - 800, 30),
  512. (3750, HEIGHT - 115, WIDTH - 800, 30)
  513.  
  514. ]
  515.  
  516.  
  517. WHITE = (255, 255, 255)
  518. BLACK = (0, 0, 0)
  519. RED = (255, 0, 0)
  520. GREEN = (0, 255, 0)
  521. BLUE = (0, 0, 255)
  522. YELLOW = (255, 255, 0)
  523. CYAN = (0, 255, 255)
  524. BROWN = (200, 140, 101)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement