0
votes

Right now my game works as so: My sprite can move right or left, jump and shoot fireballs (bullets). However, once my sprite walks past the limit of my background surface, it goes off-screen. So I want to make the background move along with my sprite. As soon as my player sprite moves about 50 pixels towards the edges of the screen, the background moves too. How do I create this with Pygame? I've found quite an amount of sources which shows you how to do this but with a plain colour background. But my background is an image I load into the game, so I would like to learn how to do so with an image as background. How to make it repeat once the sprite comes near the limit of both sides. I separated my codes into 3 different files: a Main.py, settings.py and Sprite1.py. Here's Main.py:

import pygame
import os
import sys
import time
from pygame import mixer
from Sprite1 import *
from settings import *

'''
Setup
'''
pygame.init()

clock = pygame.time.Clock()

pygame.mixer.music.load('.\\sounds\\Fairy.mp3')
pygame.mixer.music.play(-1, 0.0)

all_sprites = pygame.sprite.Group()
player = Player(all_sprites)

player.rect.x = 50
player.rect.y = 500




showStartScreen(surface)

'''
Main loop
'''

main = True

while main == True:

    background = pygame.image.load(os.path.join('images', 'Bg.png'))
    surface.blit(background, (0,0))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
            main = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT or event.key == ord('a'):
                player.control(-steps,0)

            if event.key == pygame.K_RIGHT or event.key == ord('d'):
                player.control(steps,0)

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == ord('a'):
                player.control(steps,0)

            if event.key == pygame.K_RIGHT or event.key == ord('d'):
                player.control(-steps,0)

    keys = pygame.key.get_pressed()
    if not(isJump):
        if keys[pygame.K_UP]:
            isJump = True
    else:
        if jumpCount >= -10:
            player.rect.y -= (jumpCount * abs(jumpCount)) * 1
            jumpCount -= 2
        else:
            jumpCount = 10
            isJump = False

    # dt = time since last tick in milliseconds.
    dt = clock.tick(60) / 1000
    all_sprites.update(dt)
    player.update(dt)
    all_sprites.draw(surface) #refresh player position
    pygame.display.flip()

Here's settings.py:

import pygame
isJump = False
jumpCount = 10
width = 960
height = 720
fps = 40        # frame rate
#ani = 4        # animation cycles
pygame.display.set_caption('B.S.G.')
surface = pygame.display.set_mode((width, height))
PLAYER_ACC = 0.5
PLAYER_FRICTION = -0.12
PLAYER_GRAV = 0.8
PLAYER_JUMP = 20
PLAYER_LAYER = 2
PLATFORM_LAYER = 1

steps = 10      # how fast to move

And here's Sprite1.py:

import pygame
import sys
import os
import time
from pygame import mixer
from pygame.locals import *
from settings import *
vec = pygame.math.Vector2

def showStartScreen(surface):
    show = True
    while (show == True):
        background = pygame.image.load(os.path.join('images', 'Starting_scr.png'))
        # rect = surface.get_rect()
        surface.blit(background, (0,0))
        pygame.display.flip()
        for event in pygame.event.get():
            if event.type == pygame.MOUSEBUTTONDOWN:
                show = False

class Player(pygame.sprite.Sprite):
    def __init__(self, all_sprites):
        pygame.sprite.Sprite.__init__(self)
        self.movex = 0
        self.movey = 0
        self.frame = 0
        self.health = 10
        self.jumping = False
        self.images = []
        self.imagesleft = []
        self.imagesright = []
        self.direction = "right"
        self.alpha = (0,0,0)
        self.ani = 4 # animation cycles
        self.all_sprites = all_sprites
        self.add(self.all_sprites)
        self.bullet_timer = .1

        for i in range(1,5):
            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            img.convert_alpha()
            img.set_colorkey(self.alpha)
            self.imagesright.append(img)
            self.image = self.imagesright[0]
            self.rect  = self.image.get_rect()

        for i in range(1,5):
            img = pygame.image.load(os.path.join('images','hero' + str(i) + '.png')).convert()
            img = pygame.transform.flip(img, True, False)
            img.convert_alpha()
            img.set_colorkey(self.alpha)
            self.imagesleft.append(img)
            self.image = self.imagesleft[0]
            self.rect  = self.image.get_rect()

    def control(self,x,y):
        '''
        control player movement
        '''
        self.movex += x
        self.movey -= y

    def update(self, dt):
        '''
        Update sprite position
        '''
        self.rect.x = self.rect.x + self.movex
        self.rect.y = self.rect.y + self.movey

        # moving left
        if self.movex < 0:
            self.frame += 1
            if self.frame > 3*self.ani:
                self.frame = 0
            self.image = self.imagesleft[self.frame//self.ani]
            self.direction = "left"

        # moving right
        if self.movex > 0:
            self.frame += 1
            if self.frame > 3*self.ani:
                self.frame = 0
            self.image = self.imagesright[self.frame//self.ani]
            self.direction = "right"

        #enemy_hit_list = pygame.sprite.spritecollide(self,enemy_list, False)
        #for enemy in enemy_hit_list:
            #self.health -= 1
            #print(self.health)

        keys = pygame.key.get_pressed()
        if keys[pygame.K_SPACE]:
            self.bullet_timer -= dt  # Subtract the time since the last tick.

        if self.bullet_timer <= 0:
            self.bullet_timer = 100  # Bullet ready.
            if keys:  # Left mouse button.
                # Create a new bullet instance and add it to the groups.
                if self.direction == "right":
                    Bullet([self.rect.x + self.image.get_width(), self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
                else:
                    Bullet([self.rect.x, self.rect.y + self.image.get_height()/2], self.direction, self.all_sprites)
                self.bullet_timer = .1  # Reset the timer.


class Bullet(pygame.sprite.Sprite):

    IMAGE = None
    FLIPPED_IMAGE = None

    def __init__(self, pos, direction, *sprite_groups):
        super().__init__(*sprite_groups)

        # cache images
        if not Bullet.IMAGE:
            Bullet.IMAGE = pygame.image.load(os.path.join('images','fireball.png'))
            Bullet.FLIPPED_IMAGE = pygame.transform.flip(Bullet.IMAGE, True, False)

        if direction == "right":
            self.vel = pygame.math.Vector2(750, 0)
            self.image = Bullet.IMAGE
        else:
            self.vel = pygame.math.Vector2(-750, 0)
            self.image = Bullet.FLIPPED_IMAGE

        self.pos = pygame.math.Vector2(pos)
        self.rect  = self.image.get_rect(center=pos)

    def update(self, dt):
        # Add the velocity to the position vector to move the sprite
        self.pos += self.vel * dt
        self.rect.center = self.pos  # Update the rect pos.
        if not pygame.display.get_surface().get_rect().colliderect(self.rect):
            self.kill()

I'm open to any suggestions. Thanks beforehand!

1
This is a pretty neat little tutorial that seems to answer your question: youtube.com/watch?v=US3HSusUBeIAirSquid
@JeffH Thank you for your time. I watched the video but it teaches how to make a continuously scrolling background but that's not what I wish to do for my game. What I would like to learn is how to make the screen move if my sprite goes to the sides on command. Like if say I press my right arrow key, my sprite will move towards the right but it goes out of the screen. I would like that the background moves once the sprite reaches somewhere near the edge. And the same with the left side.M3lon_sauc3

1 Answers

1
votes

Here's how I would approach this...

  1. set up a scrolling background as in the tutorial and make sure you can get that working OK by moving the background back & forth instead of the player (just freeze the player's x coordinate in the center and move the background with your left/right keys.

  2. Add some constants into your settings for an edge buffer (the number of x-increments you want the player to avoid the boundaries by

  3. AFTER you get the key input (left or right) set up a conditional statement. For this, you will have to access the player's x-coordinate and compare it to the buffer. Well, either 0+buffer or width-buffer actually and then based on those cases either move the player or the background. See if you can get that working.

  4. Then, you will realize that when you move the background, you are moving the frame of reference for everything else, meaning things like the fireball, so if you are moving the background left or right, you will need to apply those updates to the other objects as well so it looks correct.

If yer stuck, make those updates to code above & message me back in a comment.