• Advertisement

Recommended Posts

I was looking for a library to make a server/clients program.  I was thinking there would be easy tutorials for Javascript or Java.  What I ran across that is interesting is a Python tutorial for teens that looks pretty easy.     https://www.raywenderlich.com/38732/multiplayer-game-programming-for-teens-with-python

I don't know too much about Python though and I am wondering if the language is worthwhileIs it supported?  Also, I am interested in the possible use of a relational database, of which I found :  PostgreSQL.

If you know Python could you please give me a recommendation.  Its future, use, popularity, IDE, Database suggested?  From what I see it looks like an understandable language.

One of the highly recommended IDEs called Pycharm has no database support, so I stopped here and thought I'd bring it up in this forum.

 

I'm interested in any free versions too,

EDIT: Pygame is a download needed :   https://www.raywenderlich.com/24252/beginning-game-programming-for-teens-with-python

Thank you; maybe you have alternate suggestions?

Josheir

Edited by Josheir

Share this post


Link to post
Share on other sites
Advertisement

Yes.  Python is one of the main languages that runs the internet.  It is widely support.  It is worthwhile to be familiar with and a joy to use to program in.

The Python standard library has support for RDBMs and key-value databases.  I can't recommend an IDE (because I don't recommend using an IDE) but the one that ships with Python itself is IDLE.

Share this post


Link to post
Share on other sites

Yep, python is a great language. It’s very popular and some huge projects use it (Eve online, i think). 

You can also write bindings for it in C or C++. 

As for an IDE, there are plenty out there. Both Eclipse and Visual Studio have python plug-ins. 

It can also make you fly

Share this post


Link to post
Share on other sites
On ‎2‎/‎2‎/‎2018 at 10:09 PM, Xinzhen Chen said:

I agree with Bregma and ChaosEngine. Besides, i'd like to recommand VSCode as your Python IDE, which is the future of code editor IMO.

 

Do you have any suggestions for extensions for VSCode ?  Lint, or anything else great for a beginner?

Thank you,

Josheir

Share this post


Link to post
Share on other sites

In my experience, particularly considering you are learning, you are going to use the Python reference documentation more intensely than an IDE; I wouldn't bother with linters and the like. 

Within the official reference documentation, which on Windows comes conveniently compiled in a CHM help file, I recommend:

  • The first few chapters of "The Python Tutorial" as a gentle tutorial.
  • "The Python Language Reference" for fundamental and theoretical concepts (e.g. name lookup rules) and syntax doubts
  • "The Python Standard Library" for how to do something specific; it includes "Built-in Functions" and "Built-in Types", covering the core of the language, and many chapters about specific standard library modules.
  • "What's new in Python" for the embedded PEPs. Thanks to their purpose of convincing the community to adopt them, Python Enhancement Proposals provide a very focused description of new language and library features in a formal and detailed but readable style.

Share this post


Link to post
Share on other sites

As Python (but eg Lua too) is a dynamic language, it's quite impossible to decide on semantics of some code until runtime. Checkers can catch a few things but not everything.

If you still want linters, there is pylint (https://www.pylint.org/) which is mostly checking PEP8, the defacto-standard code style. There is also pyflakes (https://pypi.python.org/pypi/pyflakes) which is more oriented to finding real errors.

pypi.python.org is btw a useful resource for random packages that you might need, pretty much anything you need already exists.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Advertisement
  • Advertisement
  • Popular Tags

  • Advertisement
  • Popular Now

  • Similar Content

    • By Arthev
      Hey folks, new here
      I've decided to take the advice in this article.
      So any comments and criticisms on my pong clone would be appreciated!
      Written using Python 3 and Pygame.
      Github repo: available here.
      Thanks!
      import pygame import random import colour_constants import time import json import math from pathlib import Path SCREEN_SIZE = (640, 480) BALL_DIAMETER = 32 MAX_FPS = 60 PADDLE_SIZE = (16, 64) PADDLE_VEL = 10 HORIZONTAL_BAR = (SCREEN_SIZE[0], PADDLE_SIZE[0]) RECENT_HIT_RESET = 20 BLACK = colour_constants.DISPLAYBLACK PUREBLACK = colour_constants.PUREBLACK #Easy access for colorkeying SETTINGS_PATH = "config_pong.cfg" GAME_INTENSIFYING_CONSTANT = 1.08 COLOUR = colour_constants.APPLE2 player_one_up = pygame.K_q player_one_down = pygame.K_a player_two_up = pygame.K_o player_two_down = pygame.K_l points_per_game = 5 pygame.mixer.pre_init(44100, -16, 2, 2048) pygame.init() screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32) font = pygame.font.SysFont("Mono", 32) try: bounce_sound = pygame.mixer.Sound('bounce.wav') score_sound = pygame.mixer.Sound('score.wav') paddle_sound = pygame.mixer.Sound('paddle_bounce.wav') menu_sound = pygame.mixer.Sound('menu.wav') except: raise UserWarning("Couldn't load sound files.") class Play_Background: def __init__(self): self.surface = pygame.Surface(SCREEN_SIZE) self.surface.fill(BLACK) self.surface = self.surface.convert() pygame.draw.rect(self.surface, COLOUR, (0, 0, HORIZONTAL_BAR[0], HORIZONTAL_BAR[1])) pygame.draw.rect(self.surface, COLOUR, (0, SCREEN_SIZE[1] - HORIZONTAL_BAR[1], HORIZONTAL_BAR[0], HORIZONTAL_BAR[1])) pygame.draw.line(self.surface, COLOUR, (SCREEN_SIZE[0]//2, 0), (SCREEN_SIZE[0]//2, SCREEN_SIZE[1])) def draw(self) -> None: screen.blit( self.surface, (0, 0) ) class vector2: def __init__(self, x, y): self.x = x self.y = y def get_magnitude(self): return math.sqrt(self.x**2 + self.y**2) def normalize(self): magnitude = self.get_magnitude() self.x /= magnitude self.y /= magnitude def __add__(self, rhs): return vector2(self.x + rhs.x, self.y + rhs.y) def __mul__(self, scalar): return vector2(self.x * scalar, self.y * scalar) class Paddle: def __init__(self, side, player, up_button=None, down_button=None): if side == "left": self.pos = vector2(SCREEN_SIZE[0]//40, SCREEN_SIZE[1]//2 - PADDLE_SIZE[1]//2) elif side == "right": self.pos = vector2(SCREEN_SIZE[0] - PADDLE_SIZE[0] - SCREEN_SIZE[0]//40, SCREEN_SIZE[1]//2 - PADDLE_SIZE[1]//2) else: raise ValueError("Illegal 'side' argument sent to Paddle.__init__:", side) if player and (up_button == None or up_button == None): raise ValueError("Illegal combination of player and buttons sent to Paddle.__init__. None buttons make no sense for player == True") self.side = side self.player = player self.up_button = up_button self.down_button = down_button self.vel = vector2(0, 0) #No initial movement. self.surface = pygame.Surface( (PADDLE_SIZE[0], PADDLE_SIZE[1]) ) self.surface.fill(COLOUR) self.surface = self.surface.convert() self.score = 0 if not player: self.wait_to_calculate = 0 if not player: self.last_ball_dir = "left" if not player: self.expected_pos = 0 def calculate_expected_pos(self, ball): posVec = vector2(ball.pos.x + BALL_DIAMETER//2, ball.pos.y + BALL_DIAMETER//2) velVec = vector2(ball.vel.x, ball.vel.y) while True: timer = 1/(MAX_FPS) posVec.x += velVec.x * timer posVec.y += velVec.y * timer #Pseudo_horizontal_bar_check_and_adjustment if posVec.y - BALL_DIAMETER//2 < HORIZONTAL_BAR[1]: velVec.y *= -1 posVec.y = HORIZONTAL_BAR[1] + BALL_DIAMETER//2 elif posVec.y + BALL_DIAMETER//2 > SCREEN_SIZE[1] - HORIZONTAL_BAR[1]: velVec.y *= -1 posVec.y = SCREEN_SIZE[1] - BALL_DIAMETER//2 - HORIZONTAL_BAR[1] #Now for the bounce from the left side, if any if posVec.x - BALL_DIAMETER//2 < 0: posVec.x = BALL_DIAMETER//2 velVec.x *= -1 #And finally, handling for when found the expected pos if posVec.x + BALL_DIAMETER//2 > SCREEN_SIZE[0] - PADDLE_SIZE[0]: return posVec def calculate_expected_drift(self, case): yVel = self.vel.y yPos = self.pos.y while yVel > 5: yVel -= yVel / (MAX_FPS * 1.3) #movesim yPos += yVel * 1/MAX_FPS if yPos < HORIZONTAL_BAR[1]: yVel *= -0.75 yPos = HORIZONTAL_BAR[1] elif yPos + PADDLE_SIZE[1] > SCREEN_SIZE[1] - HORIZONTAL_BAR[1]: yVel *= -0.75 yPos = SCREEN_SIZE[1] - PADDLE_SIZE[1] - HORIZONTAL_BAR[1] if yPos + PADDLE_SIZE[1]//3 - self.expected_pos.y > PADDLE_SIZE[1]//4: return "under" elif (yPos + PADDLE_SIZE[1] - PADDLE_SIZE[1]//3) - self.expected_pos.y < -PADDLE_SIZE[1]//4: return "over" else: return "drift" def move(self, time_passed, ball) -> None: #Accelerate if self.player: pressed_keys = pygame.key.get_pressed() if pressed_keys[self.up_button]: self.vel.y -= PADDLE_VEL elif pressed_keys[self.down_button]: self.vel.y += PADDLE_VEL else: self.vel.y -= self.vel.y / (MAX_FPS * 1.3) #Found experimentally else: if self.expected_pos == 0: self.expected_pos = self.calculate_expected_pos(ball) if ball.vel.x > 0: self.last_ball_dir = "right" if self.wait_to_calculate > 0: self.wait_to_calculate -= 1 else: self.expected_pos = self.calculate_expected_pos(ball) self.wait_to_calculate = RECENT_HIT_RESET//2 elif ball.vel.x < 0: if self.last_ball_dir == "right": self.last_ball_dir = "left" self.expected_pos = self.calculate_expected_pos(ball) self.wait_to_calculate = 0 probable_drift = self.calculate_expected_drift("larger") #expected_pos y is larger than self y if probable_drift == "under": self.vel.y -= PADDLE_VEL elif probable_drift == "over": self.vel.y += PADDLE_VEL else: if abs(self.pos.y + PADDLE_SIZE[1]//2 - self.expected_pos.y) > PADDLE_SIZE[1]: if self.pos.y + PADDLE_SIZE[1]//2 > self.expected_pos.y: self.vel.y -= PADDLE_VEL else: self.vel.y += PADDLE_VEL self.vel.y -= self.vel.y / (MAX_FPS * 1.3) #Move self.pos.y += self.vel.y * time_passed if self.pos.y < HORIZONTAL_BAR[1] or self.pos.y + PADDLE_SIZE[1] > SCREEN_SIZE[1] - HORIZONTAL_BAR[1]: paddle_sound.play() self.vel.y *= -0.75 if self.pos.y < HORIZONTAL_BAR[1]: self.pos.y = HORIZONTAL_BAR[1] else: self.pos.y = SCREEN_SIZE[1] - PADDLE_SIZE[1] - HORIZONTAL_BAR[1] def draw(self) -> None: screen.blit(self.surface, (self.pos.x, self.pos.y)) class Ball: def reset(self) -> None: self.last_hit = None self.pos = vector2(SCREEN_SIZE[0]//2, SCREEN_SIZE[1]//2) self.vel = vector2(SCREEN_SIZE[0] * random.random(), SCREEN_SIZE[1] * random.random()) if random.random() < 0.5: self.vel.x *= -1 if random.random() < 0.5: self.vel.y *= -1 if abs(self.vel.x) < SCREEN_SIZE[0] * 0.1: self.reset() def __init__(self): self.pos = None self.vel = None self.surface = pygame.Surface( (BALL_DIAMETER, BALL_DIAMETER) ) self.surface.set_colorkey(PUREBLACK) pygame.draw.circle( self.surface, COLOUR, (BALL_DIAMETER//2, BALL_DIAMETER//2), BALL_DIAMETER//2) self.surface = self.surface.convert_alpha() self.last_hit = None self.reset() def horizontal_bar_check_and_adjustment(self) -> None: if self.pos.y < HORIZONTAL_BAR[1] or self.pos.y + BALL_DIAMETER > SCREEN_SIZE[1] - HORIZONTAL_BAR[1]: self.vel.y *= -1 bounce_sound.play() if self.pos.y < HORIZONTAL_BAR[1]: self.pos.y = HORIZONTAL_BAR[1] else: self.pos.y = SCREEN_SIZE[1] - BALL_DIAMETER - HORIZONTAL_BAR[1] def score_check(self) -> str: #Can also return None! if self.pos.x + BALL_DIAMETER < 0: return "right" elif self.pos.x > SCREEN_SIZE[0]: return "left" else: return None def simple_collision_check(self, paddles) -> Paddle: #Can also return None! left = paddles[0] right = paddles[1] if self.pos.x + BALL_DIAMETER < right.pos.x and self.pos.x > left.pos.x + PADDLE_SIZE[0]: return None #If we progress below here, a hit might happen... since the ball isn't *between* the paddles! if self.pos.x + BALL_DIAMETER > right.pos.x: #Ball might have hit the right paddle. if self.pos.y > right.pos.y + PADDLE_SIZE[1]: return None elif self.pos.y + BALL_DIAMETER < right.pos.y: return None else: return right else: #Ball might have hit the left paddle. if self.pos.y > left.pos.y + PADDLE_SIZE[1]: return None elif self.pos.y + BALL_DIAMETER < left.pos.y: return None else: return left def collision_handling(self, paddle) -> None: steps = PADDLE_SIZE[1]//2 + BALL_DIAMETER//2 extreme = 1.12 #arcsin(0.9) = 1.12 hit = self.pos.y + BALL_DIAMETER//2 - (paddle.pos.y + PADDLE_SIZE[1]//2) w = extreme/steps*hit newVec = 0 #This is a unit vector, hehe. if paddle.side == "left": newVec = vector2(-math.cos(w), -math.sin(w)) else: newVec = vector2(math.cos(w), -math.sin(w)) magnitude = self.vel.get_magnitude() * GAME_INTENSIFYING_CONSTANT * -1 self.vel.normalize() newVec = newVec + self.vel #The two vectors can be scalar multiplied by some percentage for different admixtures. newVec.normalize() newVec = newVec * magnitude self.vel = newVec def move(self, time_passed, paddles) -> None: self.pos.x += self.vel.x * time_passed self.pos.y += self.vel.y * time_passed self.horizontal_bar_check_and_adjustment() quick_collision = self.simple_collision_check(paddles) #quick_collision will contain a paddle - or None. if quick_collision: if quick_collision.side != self.last_hit: bounce_sound.play() self.last_hit = quick_collision.side self.collision_handling(quick_collision) def draw(self) -> None: screen.blit(self.surface, (self.pos.x, self.pos.y)) class Scoredrawer: def __init__(self): self.left = 0 self.right = 0 def draw(self, left, right): #Idea for improved performance: Check whether there's a change to a score and then only rendering if so. left_text = font.render(str(left), False, COLOUR).convert_alpha() right_text = font.render(str(right), False, COLOUR).convert_alpha() y_offset = HORIZONTAL_BAR[1] * 1.5 screen.blit(left_text, (SCREEN_SIZE[0]//2 - 32 - left_text.get_width(), y_offset)) screen.blit(right_text, (SCREEN_SIZE[0]//2 + 32, y_offset)) def display_winner(winner) -> None: winner_text = font.render( winner.capitalize() + " has won!", False, COLOUR).convert_alpha() screen.blit(winner_text, (SCREEN_SIZE[0]//2 - winner_text.get_width()//2, SCREEN_SIZE[1]//2 - winner_text.get_height()//2)) pygame.display.update() while True: for event in pygame.event.get(): if event.type == pygame.constants.QUIT: exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: exit() elif event.key == pygame.K_RETURN: return def play(win_score: int, two_player_mode: bool) -> str: #returns 'left' or 'right' depending on which player won clock = pygame.time.Clock() background = Play_Background() scoredrawer = Scoredrawer() ball = Ball() paddle1 = Paddle(side="left", player=True, up_button=player_one_up, down_button=player_one_down) paddle2 = Paddle(side="right", player=two_player_mode, up_button=player_two_up, down_button=player_two_down) paddles = [paddle1, paddle2] #Left side must go in paddles[0], right side in paddles[1]. while True: for event in pygame.event.get(): if event.type == pygame.constants.QUIT: exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: exit() time_passed = clock.tick(MAX_FPS) / 1000.0 #time_passed is in seconds background.draw() ball.move(time_passed, paddles) for paddle in paddles: paddle.move(time_passed, ball) scorer = ball.score_check() #Either "left", "right" or None if scorer: score_sound.play() if scorer == "left": paddles[0].score += 1 if paddles[0].score >= win_score: display_winner(scorer) return else: paddles[1].score += 1 if paddles[1].score >= win_score: display_winner(scorer) return ball.reset() scoredrawer.draw(paddles[0].score, paddles[1].score) ball.draw() for paddle in paddles: paddle.draw() pygame.display.update() def display_intro() -> None: display_font = pygame.font.SysFont("mono", SCREEN_SIZE[0]//6) display_text = display_font.render("PongyPong", False, COLOUR, BLACK).convert() display_font2 = pygame.font.SysFont("mono", SCREEN_SIZE[0]//18) display_text2 = display_font2.render("by: Arthur", False, COLOUR, BLACK).convert() for i in range(256): screen.fill(BLACK) display_text.set_alpha(i) screen.blit(display_text, (SCREEN_SIZE[0]//2 - display_text.get_width()//2, SCREEN_SIZE[1]//2 - display_text.get_height())) pygame.display.update() time.sleep(1/100) for i in range(256): display_text2.set_alpha(i) screen.blit(display_text2, (SCREEN_SIZE[0]//2, SCREEN_SIZE[1]//2)) pygame.display.update() time.sleep(1/200) time.sleep(0.25) def settings_menu() -> None: def save_settings(dummy): current_settings = {'COLOUR':COLOUR, 'player_one_up':player_one_up, 'player_one_down':player_one_down, 'player_two_up':player_two_up, 'player_two_down':player_two_down, 'points_per_game':points_per_game} with open(SETTINGS_PATH, 'w') as settings_file: json.dump(current_settings, settings_file) def set_key(var): press_message = font.render( "Press the desired key...", False, COLOUR).convert_alpha() screen.blit(press_message, (SCREEN_SIZE[0]//2 - press_message.get_width()//2, SCREEN_SIZE[1] - font.get_linesize() * 1.5)) pygame.display.update() pygame.event.clear() while True: for event in pygame.event.get(): if event.type == pygame.constants.QUIT: exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: exit() if event.key != pygame.K_RETURN: menu_sound.play() globals()[var] = event.key return selection = 0 options = [{'Text': 'Points Per Game: ', 'func': lambda x: None, 'var': 'points_per_game', 'extradraw': ['arrows', 'value']}, {'Text': 'Colour', 'func': lambda x: None, 'var': 'COLOUR', 'extradraw':'arrows'}, {'Text': 'Player One Up: ', 'func': set_key, 'var': 'player_one_up', 'extradraw':'button'}, {'Text': 'Player One Down: ', 'func': set_key, 'var': 'player_one_down', 'extradraw':'button'}, {'Text': 'Player Two Up: ', 'func': set_key, 'var': 'player_two_up', 'extradraw':'button'}, {'Text': 'Player Two Down: ', 'func': set_key, 'var':'player_two_down', 'extradraw':'button'}, {'Text': 'Save Settings', 'func': save_settings, 'var': 'return', 'extradraw': None}] colour_options = [colour_constants.AMBER, colour_constants.LTAMBER, colour_constants.GREEN1, colour_constants.APPLE1, colour_constants.GREEN2, colour_constants.APPLE2, colour_constants.GREEN3] colour_selection = 0 for i, colour in enumerate(colour_options): if colour == COLOUR: colour_selection = i blinker = True while True: for event in pygame.event.get(): if event.type == pygame.constants.QUIT: exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: exit() elif event.key == pygame.K_RETURN: menu_sound.play() options[selection]['func'](options[selection]['var']) if options[selection]['var'] == 'return': return elif event.key in [pygame.K_DOWN, player_one_down, player_two_down]: menu_sound.play() if selection == len(options) - 1: selection = 0 else: selection += 1 elif event.key in [pygame.K_UP, player_one_up, player_two_up]: menu_sound.play() if selection == 0: selection = len(options) - 1 else: selection -= 1 elif event.key == pygame.K_RIGHT: var = options[selection]['var'] if var == 'COLOUR': menu_sound.play() if colour_selection == len(colour_options) -1: colour_selection = 0 else: colour_selection += 1 globals()[var] = colour_options[colour_selection] elif var == 'points_per_game': menu_sound.play() globals()[var] += 1 elif event.key == pygame.K_LEFT: var = options[selection]['var'] if var == 'COLOUR': menu_sound.play() if colour_selection == 0: colour_selection = len(colour_options) - 1 else: colour_selection -= 1 globals()[var] = colour_options[colour_selection] if var == 'points_per_game': menu_sound.play() globals()[var] = max(1, points_per_game - 1) screen.fill(BLACK) DIV = 32 for i in range(len(options)): if i == selection: blinker = not blinker if blinker: continue text = font.render(options[i]['Text'], False, COLOUR).convert_alpha() screen.blit(text, (SCREEN_SIZE[0]//2 - text.get_width()//2, SCREEN_SIZE[1]//DIV + font.get_linesize() * 1.5 * i)) extradraw = options[i]['extradraw'] if extradraw == 'arrows' or (type(extradraw) == list and 'arrows' in extradraw): h = text.get_height() * 0.75 // 1 arrowsurface = pygame.Surface( (h, h) ) arrowsurface.fill(BLACK) pygame.draw.polygon(arrowsurface, COLOUR, ( (0, h//2), (h//2 - h//8, h//4), (h//2 - h//8, 3*h//4) ) ) pygame.draw.polygon(arrowsurface, COLOUR, ( (h, h//2), (h//2 + h//8, h//4), (h//2 + h//8, 3*h//4) ) ) arrowsurface.convert() screen.blit(arrowsurface, (SCREEN_SIZE[0]//2 - text.get_width()//2 - arrowsurface.get_width() - 2, SCREEN_SIZE[1]//DIV + font.get_linesize() * 1.5 * i + h//8)) if extradraw == 'value' or (type(extradraw) == list and 'value' in extradraw): valuesurface = font.render( str(globals()[options[i]['var']]), False, COLOUR).convert_alpha() screen.blit(valuesurface, (SCREEN_SIZE[0]//2 + text.get_width()//2 + 2, SCREEN_SIZE[1]//DIV + font.get_linesize() * 1.5 * i)) if extradraw == 'button' or (type(extradraw) == list and 'button' in extradraw): buttonsurface = font.render( pygame.key.name(globals()[options[i]['var']]), False, COLOUR).convert_alpha() screen.blit(buttonsurface, (SCREEN_SIZE[0]//2 + text.get_width()//2 + 2, SCREEN_SIZE[1]//DIV + font.get_linesize() * 1.5 * i)) pygame.display.update() def main_menu() -> None: def one_player_mode(): play(points_per_game, False) def two_player_mode(): play(points_per_game, True) selection = 0 options = [{'Text': '1-Player', 'func': one_player_mode}, {'Text': '2-Player', 'func': two_player_mode}, {'Text': 'Settings', 'func': settings_menu}, {'Text': 'Exit', 'func': exit}] blinker = True while True: for event in pygame.event.get(): if event.type == pygame.constants.QUIT: exit() elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: exit() elif event.key == pygame.K_RETURN: menu_sound.play() options[selection]['func']() elif event.key in [pygame.K_DOWN, player_one_down, player_two_down]: menu_sound.play() if selection == len(options) - 1: selection = 0 else: selection += 1 elif event.key in [pygame.K_UP, player_one_up, player_two_up]: menu_sound.play() if selection == 0: selection = len(options) - 1 else: selection -= 1 screen.fill(BLACK) pseudopaddle = pygame.Surface( (PADDLE_SIZE[0]//2, PADDLE_SIZE[1]//2) ) pseudopaddle.fill(COLOUR) pseudopaddle = pseudopaddle.convert() screen.blit(pseudopaddle, (SCREEN_SIZE[0]//2 - PADDLE_SIZE[1], SCREEN_SIZE[1]//10 - PADDLE_SIZE[0]//2)) screen.blit(pseudopaddle, (SCREEN_SIZE[0]//2 + PADDLE_SIZE[1], SCREEN_SIZE[1]//10 + PADDLE_SIZE[0]//2)) pseudoball = pygame.Surface( (BALL_DIAMETER//2, BALL_DIAMETER//2) ) pseudoball.fill(BLACK) pygame.draw.circle( pseudoball, COLOUR, (BALL_DIAMETER//4, BALL_DIAMETER//4), BALL_DIAMETER//4) pseudoball = pseudoball.convert() screen.blit(pseudoball, (SCREEN_SIZE[0]//2 + BALL_DIAMETER//4, SCREEN_SIZE[1]//10 - BALL_DIAMETER//4)) for i in range(len(options)): if i == selection: blinker = not blinker if blinker: continue text = font.render(options[i]['Text'], False, COLOUR).convert_alpha() screen.blit(text, (SCREEN_SIZE[0]//2 - text.get_width()//2, SCREEN_SIZE[1]//4 + font.get_linesize() * 2 * i)) pygame.display.update() def load_settings() -> None: settings_path = Path(SETTINGS_PATH) if settings_path.is_file(): with open(SETTINGS_PATH, 'r') as settings_file: settings = json.load(settings_file) for item in settings: globals()[item] = settings[item] else: default_settings = {'COLOUR':COLOUR, 'player_one_up':player_one_up, 'player_one_down':player_one_down, 'player_two_up':player_two_up, 'player_two_down':player_two_down, 'points_per_game':points_per_game} with open(SETTINGS_PATH, 'w') as settings_file: json.dump(default_settings, settings_file) if __name__ == '__main__': load_settings() display_intro() main_menu()  
    • By Tazbird
      Additional game play from my 2018 Missile Command Challenge Submission
    • By Tazbird
      The ending screen from my 2018 Missile Command Challenge submission
    • By Tazbird
      Game play from my 2018 Missile Command Challenge Submission
  • Advertisement