Monday, April 20, 2015

Player movement and a second video!

Now it is time for me to expand the game a little further than a menu screen. In the following video, I use object-oriented programming to create a player object, which appears as a simplistic blue space ship on the screen, and I write event handles to allow the player to move the ship with the arrow keys. (Note: I recommend that you watch the video in full-screen.)

Edit: I realize that you may be interested in seeing the code separately:


import os, pygame, sys
from pygame.locals import *

if not pygame.font: print('Warning, fonts disabled')
if not pygame.mixer: print('Warning, sound disabled')

UP = 0
RIGHT = 1
DOWN = 2
LEFT = 3

MENU_SCREEN = 0
GAME_SCREEN = 1
LOAD_SCREEN = 2

class GameObject:
    def __init__(self, image, size, speed, x, y, rot):
        self.image = image
        self.size = size
        self.speed = speed
        self.pos = image.get_rect().move(x,y)
        self.rot = rot
        
    def move(self,surface,direction):
        if direction == UP:
            self.pos = self.pos.move(0,-1)
        if direction == RIGHT:
            self.pos = self.pos.move(1,0)
        if direction == DOWN:
            self.pos = self.pos.move(0,1)
        if direction == LEFT:
            self.pos = self.pos.move(-1,0)
        if self.pos.right > surface.get_size()[0]:
            self.pos.left = 0
        if self.pos.top < 0:
            self.pos.bottom = surface.get_size()[1]

#Initialize screen
pygame.init()
DISPLAY_SURFACE = pygame.display.set_mode((960, 540),RESIZABLE)
pygame.display.set_caption('Space Shooter!') #I'll think of a more creative name later.

screen_indicator = MENU_SCREEN

size = DISPLAY_SURFACE.get_size()
width = size[0]
height = size[1]

title = pygame.Rect(((width/16)+1, (height/8)+1, 7*width/8, height/4))
menu1 = pygame.Rect(((width/4)+1, (height/2)+1, 2*width/4, height/10))
menu2 = pygame.Rect(((width/4)+1, (height/2)+1+(3*height/20), 2*width/4, height/10))
menu3 = pygame.Rect(((width/4)+1, (height/2)+1+(6*height/20), 2*width/4, height/10))

#Draws dark blue rectangles.
pygame.draw.rect(DISPLAY_SURFACE, (0,0,150), menu1)
pygame.draw.rect(DISPLAY_SURFACE, (0,0,150), menu2)
pygame.draw.rect(DISPLAY_SURFACE, (0,0,150), menu3)

#Draws blue ovals on top of the rectangles.
pygame.draw.ellipse(DISPLAY_SURFACE, (0,0,150), title)
pygame.draw.ellipse(DISPLAY_SURFACE, (0,0,255), menu1)
pygame.draw.ellipse(DISPLAY_SURFACE, (0,0,255), menu2)
pygame.draw.ellipse(DISPLAY_SURFACE, (0,0,255), menu3)

#pygame.font.Font takes in a font name and an integer for its size.
#Free Sans Bold comes with Pygame (Sweigart 2012 p. 30).
font_title = pygame.font.Font('freesansbold.ttf', 64)
font_menu = pygame.font.Font('freesansbold.ttf', 32)

#Creates and draws the text.
surface_title = font_title.render('SPACE SHOOTER!', True, (0,255,0))
rect_title = surface_title.get_rect(center=(width/2,(height/4)+3)) #get_rect() is my favorite Pygame function.
surface_new_game = font_menu.render('NEW GAME', True, (0,0,0))
rect_new_game = surface_new_game.get_rect(center=(width/2,(height/2)+(height/20)+3))
surface_load_game = font_menu.render('LOAD GAME', True, (0,0,0))
rect_load_game = surface_load_game.get_rect(center=(width/2,(height/2)+(4*height/20)+3))
surface_exit = font_menu.render('EXIT', True, (0,0,0))
rect_exit = surface_exit.get_rect(center=(width/2,(height/2)+(7*height/20)+3))

background = pygame.image.load('background.png').convert() #http://www.pygame.org/docs/tut/MoveIt.html
player = pygame.image.load('player.png').convert_alpha() #player.png is in the same folder as this module, which is C:\Python32 for me.
p = GameObject(player, 100, 1, 400, 400, 1)

while True: #main game loop
    for event in pygame.event.get():
        if screen_indicator == MENU_SCREEN:
            DISPLAY_SURFACE.blit(surface_title, rect_title)
            DISPLAY_SURFACE.blit(surface_new_game, rect_new_game)
            DISPLAY_SURFACE.blit(surface_load_game, rect_load_game)
            DISPLAY_SURFACE.blit(surface_exit, rect_exit)
            if event.type == VIDEORESIZE:
                #This line creates a new display in order to clear the screen.
                #I figured this out myself, so if you know of a better way to do this, let me know.
                DISPLAY_SURFACE = pygame.display.set_mode((event.w, event.h),RESIZABLE)

                width = event.w
                height = event.h

                #Creates the rectangle objects that will be behind the title and menu buttons.
                title = pygame.Rect(((width/16)+1, (height/8)+1, 7*width/8, height/4))
                menu1 = pygame.Rect(((width/4)+1, (height/2)+1, 2*width/4, height/10))
                menu2 = pygame.Rect(((width/4)+1, (height/2)+1+(3*height/20), 2*width/4, height/10))
                menu3 = pygame.Rect(((width/4)+1, (height/2)+1+(6*height/20), 2*width/4, height/10))

                #Draws dark blue rectangles.
                pygame.draw.rect(DISPLAY_SURFACE, (0,0,150), menu1)
                pygame.draw.rect(DISPLAY_SURFACE, (0,0,150), menu2)
                pygame.draw.rect(DISPLAY_SURFACE, (0,0,150), menu3)

                #Draws blue ovals on top of the rectangles.
                pygame.draw.ellipse(DISPLAY_SURFACE, (0,0,150), title)
                pygame.draw.ellipse(DISPLAY_SURFACE, (0,0,255), menu1)
                pygame.draw.ellipse(DISPLAY_SURFACE, (0,0,255), menu2)
                pygame.draw.ellipse(DISPLAY_SURFACE, (0,0,255), menu3)

                #Creates and draws the text.
                rect_title = surface_title.get_rect(center=(width/2,(height/4)+3)) #get_rect() is my favorite Pygame function.
                rect_new_game = surface_new_game.get_rect(center=(width/2,(height/2)+(height/20)+3))
                rect_load_game = surface_load_game.get_rect(center=(width/2,(height/2)+(4*height/20)+3))
                rect_exit = surface_exit.get_rect(center=(width/2,(height/2)+(7*height/20)+3))

            #When you let go of the left mouse button in the area of a button, the button does something.
            if event.type == MOUSEBUTTONUP:
                if event.button == 1:
                    if (menu1.left < event.pos[0] < menu1.right) and (menu1.top < event.pos[1] < menu1.bottom):
                        screen_indicator = GAME_SCREEN
                        DISPLAY_SURFACE = pygame.display.set_mode((width, height),RESIZABLE)
                    if (menu2.left < event.pos[0] < menu2.right) and (menu2.top < event.pos[1] < menu2.bottom):
                        print("LOAD GAME") #Placeholder
                    if (menu3.left < event.pos[0] < menu3.right) and (menu3.top < event.pos[1] < menu3.bottom):
                        pygame.event.post(pygame.event.Event(QUIT)) #Exits the game

            #When you mouse-over a button, the text turns green.
            if event.type == MOUSEMOTION:
                if (menu1.left < event.pos[0] < menu1.right) and (menu1.top < event.pos[1] < menu1.bottom):
                    surface_new_game = font_menu.render('NEW GAME', True, (0,255,0))
                else:
                    surface_new_game = font_menu.render('NEW GAME', True, (0,0,0))
                if (menu2.left < event.pos[0] < menu2.right) and (menu2.top < event.pos[1] < menu2.bottom):
                    surface_load_game = font_menu.render('LOAD GAME', True, (0,255,0))
                else:
                    surface_load_game = font_menu.render('LOAD GAME', True, (0,0,0))
                if (menu3.left < event.pos[0] < menu3.right) and (menu3.top < event.pos[1] < menu3.bottom):
                    surface_exit = font_menu.render('EXIT', True, (0,255,0))
                else:
                    surface_exit = font_menu.render('EXIT', True, (0,0,0))           
        if screen_indicator == GAME_SCREEN:
            DISPLAY_SURFACE.blit(background, (0, 0))
            #For now, the controls are built-in.  Later controls will be changeable via a settings menu.
            if event.type == KEYDOWN:
                while pygame.event.peek(KEYUP) == False:
                    print(event.key)
                    if event.key == 273:
                        DISPLAY_SURFACE.blit(background, (0, 0))
                        p.move(DISPLAY_SURFACE,UP)
                        DISPLAY_SURFACE.blit(p.image, p.pos)
                        pygame.display.update()
                        pygame.time.delay(2)
                    if event.key == 275:
                        DISPLAY_SURFACE.blit(background, (0, 0))
                        p.move(DISPLAY_SURFACE,RIGHT)
                        DISPLAY_SURFACE.blit(p.image, p.pos)
                        pygame.display.update()
                        pygame.time.delay(2)
                    if event.key == 274:
                        DISPLAY_SURFACE.blit(background, (0, 0))
                        p.move(DISPLAY_SURFACE,DOWN)
                        DISPLAY_SURFACE.blit(p.image, p.pos)
                        pygame.display.update()
                        pygame.time.delay(2)
                    if event.key == 276:
                        DISPLAY_SURFACE.blit(background, (0, 0))
                        p.move(DISPLAY_SURFACE,LEFT)
                        DISPLAY_SURFACE.blit(p.image, p.pos)
                        pygame.display.update()
                        pygame.time.delay(2)
            DISPLAY_SURFACE.blit(p.image, p.pos)
            if event.type == VIDEORESIZE:
                DISPLAY_SURFACE = pygame.display.set_mode((event.w, event.h),RESIZABLE)
                DISPLAY_SURFACE.blit(background, (0, 0))

        if event.type == QUIT:
            pygame.quit()
            sys.exit()            
        pygame.display.update()

No comments:

Post a Comment