Create the spaceship in Rock Sweeper

In this chapter we are going to create two spaceships, one in front and one at the back. The first thing we need to do here is to create a spritesheet as shown below.

spritesheet
spritesheet

The spritesheet above consists of a spaceship with the width and height of 32px at spritesheet’s coordinate (0,0) as well as a rock (16px x 16px) at coordinate (32,0) and background image at the spritesheet’s coordinate of (0, 32). Import the above spritesheet into the project folder.

The next thing we need to do is to import the previous Vector2D module into our game project folder so we can use it later.

Then we will import the previous GameSprite module into our project as well then change a few lines of script.

import pygame
from pygame.locals import *
from vector2d import Vector2D

class GameSprite(pygame.sprite.Sprite):

    # Constructor. Pass in the image file
    # and it's width and height and position on the spritesheet
    def __init__(self, image, width, height, pos):
        # Call the parent class (Sprite) constructor
        pygame.sprite.Sprite.__init__(self)
        
        #register the width and height of the sprite
        self.width = width
        self.height = height
        #use the radius to detect overlap
        self.radius = self.width/4

        # Create the spritesheet surface from the image file
        self.sprite = pygame.image.load(image).convert_alpha()
        
        #the rectangle object uses in clipping
        self.clip_rect = Rect((pos.x, pos.y), (self.width, self.height))
        
        self.sprite.set_clip(self.clip_rect) # clip a portion of the spritesheet with the rectangle object
        self.image = self.sprite.subsurface(self.sprite.get_clip()) #create sprite surface
        
        self.pos = Vector2D(0,0) #initialize the original position of the sprite 
        
        #initialize the id of sprite
        self.entity_id = 0
        
    def updatePosition(self, pos): 
        pass

Next we will create a subclass for the ship based on the GameSprite module above.

from game_sprite import GameSprite
from pygame.locals import *

class ShipSprite(GameSprite):
    
    # Constructor. Pass in the image file
    # and it's width and height and the position on the spritesheet
    def __init__(self, image, width, height, pos):
        # Call the parent class constructor
        GameSprite.__init__(self, image, width, height, pos)
        
    def updatePosition(self, pos): 
        
        #make sure the ship stays within the boundry of the screen
        if(pos.x - self.width/2 < 0):
            pos.x = self.width/2
        elif(pos.x + self.width/2 >= 550):
            pos.x = 550 - self.width/2
        
        self.rect = Rect(pos.x - self.width/2, pos.y - self.height/2, self.width, self.height) #self.rect will be called by group

Next add a few lines of script into the World module which we have created previously.

from pygame.locals import *
from pygame.sprite import Group

class World(object):
    
    def __init__(self, maintile, background_coordinate, screen_size):
        
        #main spritesheet surface
        self.spritesheet = maintile
        
        #game entities dict to store all the game entities
        self.entities = {}
        
        #create a ship group
        self.ship_group = Group()
        
        #initialize the id of the first entity
        self.entity_id = 0
        
        #the rectangle object uses in clipping the background area
        self.clip_rect = Rect(background_coordinate, screen_size)
        self.spritesheet.set_clip(self.clip_rect) # clip a portion of the spritesheet with that rectangle object
        self.background = self.spritesheet.subsurface(self.spritesheet.get_clip()) #create the background surface 
       
    def render(self, surface):
         
        surface.blit(self.background, (0,0)) #blit the background to the pygame screen
        self.ship_group.draw(surface) #blit the ships to the pygame screen
        
    def addEntity(self, entity):
        self.entities[self.entity_id] = entity
        entity.entity_id = self.entity_id
        self.ship_group.add(entity)
        self.entity_id += 1
        
    def updateShipPosition(self, ship_one_pos, ship_two_pos):
        self.entities[0].updatePosition(ship_one_pos)
        self.entities[1].updatePosition(ship_two_pos)

Finally run the main module…

#!/usr/bin/env python

import pygame
from pygame.locals import *
from sys import exit
from world import World
from vector2d import Vector2D
from ship_sprite import ShipSprite

maintile = 'maintile.png' #spritesheet file

SCREEN_SIZE = (550, 550) 
BACKGROUND_COORDINATE = (0, 32)

screen_w, screen_h = SCREEN_SIZE

pygame.init()

screen = pygame.display.set_mode(SCREEN_SIZE, 0, 32)
pygame.display.set_caption("Rock Sweeper")

spritesheet = pygame.image.load(maintile).convert_alpha() #spritesheet surface object

pygame.display.set_icon(spritesheet) #use the entire spritesheet surface as the window icon

world = World(spritesheet, BACKGROUND_COORDINATE, SCREEN_SIZE) #initialize the World object

clock = pygame.time.Clock() # initialize the clock object
game_speed = 70. # game speed per second

#width and height of the ship
w, h = 32, 32

#ship sprite left top position within maintile
pos = Vector2D(0, 0)

#create the first ship and add to group
ship_one = ShipSprite(maintile, w, h, pos)
ship_one.pos = Vector2D(screen_w/2-w, screen_h-h-h-h-h) 
world.addEntity(ship_one)

#create the second ship and add to group
ship_two = ShipSprite(maintile, w, h, pos)
ship_two.pos = Vector2D(screen_w/2-w-w, screen_h-h-h-h)
world.addEntity(ship_two)

while True:
   
    for event in pygame.event.get():
        
        if event.type == QUIT:
            exit()  
    
    #reset the speed to zero for both sjips
    v = Vector2D(0.0, 0.0)
    v1 = Vector2D(0.0, 0.0)
            
    pressed_keys = pygame.key.get_pressed() # get all the keys from key-press events 
        
    if pressed_keys[K_LEFT]: 
        v = Vector2D(-1., 0.) # move the top ship one unit to the left
        v1 = Vector2D(1., 0.) # move the bottom ship one unit to the right
        
    elif pressed_keys[K_RIGHT]:
        v = Vector2D(1., 0.) # move the top ship one unit to the right
        v1 = Vector2D(-1., 0.) # move the bottom ship one unit to the left
    
    world.updateShipPosition(ship_one.pos, ship_two.pos)
    world.render(screen) #render the game background and all the game entities 
    
    time_passed = clock.tick() #delta time for each frame
    time_passed_seconds = time_passed / 1000.0
    
    #re-adjust the position for both ships
    ship_one.pos+= v * game_speed * time_passed_seconds  
    ship_two.pos+= v1 * game_speed * time_passed_seconds
    
    pygame.display.flip()

One thing to take note here is that the world object will be used to control all the game entities as well as the background from here onward.