lunes, 7 de julio de 2014

First game with graphics, part 3

After an unplanned abscence, finally I'll show you how to control an image on screen with the mouse.

This example is actually very similar to the last one. I added a generous amount of whitespace in order to clearly read each function and each class.



import pygame


#These two constants refer to the ball's initial position
# and radius. The radius will be useful to position the center
# of the ball on the tip of the mouse pointer. I'll expand on
# this later.

STARTING_POINT = (340,250)
BALL_RADIUS = 12


class Ball:


    def __init__(self,imageFile,position_arg):

        self.image = pygame.image.load(imageFile)
        pygame.Surface.convert(self.image)
        self.position = position_arg


# The ball class no longer needs a "move" function,
# since the ball will only change position according to
# the mouse position.


    def set_position(self,position_arg):

        self.position = position_arg



class AssetManager:

    def load_ball(self,imageFile,position):
        return Ball(imageFile,position)




class InputManager:


    def check_events(self):

        for event in pygame.event.get():

            if event.type == pygame.QUIT:

                game.running = False




    def process_input(self,ball):

        mouse = pygame.mouse.get_pressed()

# This variable, mousePos, could just be the tuple returned by pygame.mouse.get_pos(), which is the position of the mouse pointer in the 'x' and 'y' axis, respectively. If we passed pygame.mouse.get_pos() directly to ball.set_position(), then we'd move the ball by its top-left corner, which looks kind of weird. To move the ball by its center, we just substract the ball's radius to both positions.

        mousePos = ( (pygame.mouse.get_pos()[0] - BALL_RADIUS) , (pygame.mouse.get_pos()[1] - BALL_RADIUS) )


        if mouse[0]:
          
            ball.set_position(mousePos)    




class Game:



    def __init__(self,resolution,caption):


        self.screen = pygame.display.set_mode(resolution)
        pygame.display.set_caption(caption)
        self.clock = pygame.time.Clock()
        self.running = True
        self.gray = (220,220,220)



    def draw_screen(self,ball):

        self.screen.fill(self.gray)
        self.screen.blit(ball.image,ball.position)
        pygame.display.flip()



    def main_loop(self,framerate,assets):

        ball = assets.load_ball('ball2.png',STARTING_POINT)

        while self.running:

            self.clock.tick(framerate)
            input_manager.check_events()
            input_manager.process_input(ball)

            self.draw_screen(ball)

        pygame.quit()



assets = AssetManager()
input_manager = InputManager()
game = Game((800,600),"Game")
game.main_loop(60,assets)

In the next post, I'll describe the actual idea for the game, and I'll add some functionality.

Until then, take care!

2 comentarios:

  1. If you start using the pygame.Rect class it will greatly simplify many things (now and in the future). With rects you could just assign the mouse position directly to the center of the rect (rather than need to do ugly adjustments)

    Also once you get into collision and hopefully using the pygame.sprite.Sprite class, using rects won't be optional.


    Take a look here for an example of moving using relative mouse movement:
    https://github.com/Mekire/meks-pygame-samples/blob/master/drag_text.py


    Also I have to say, my opinion might not necessarily match that of a fresh beginner, but the way you are using white space makes things less readable, not more.

    -Mek

    ResponderEliminar
  2. Thanks for the tip, Sean. I confess I've been avoiding the use of Sprite, Rect and convert(), and other useful tools because I haven't studied them yet. I thought I could go on without them for a little longer, but I didn't realize that they'll help me avoid those "ugly adjustments".

    I'll check that whitespace issue. I thought I was being clear...

    ResponderEliminar