2D Parralax Scrolling

Anything related in any way to game development as a whole is welcome here. Tell us about your game, grace us with your project, show us your new YouTube video, etc.

Moderator: PC Supremacists

User avatar
Big Grizzle
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 61
Joined: Wed Sep 02, 2009 1:07 pm
Current Project: 2d side scrolling shooter.
Favorite Gaming Platforms: The SNES rules all!!! Super Aleste baby!
Programming Language of Choice: Python
Location: London, UK
Contact:

2D Parralax Scrolling

Post by Big Grizzle »

Feeling a tad inspired. I uploaded my first youtube video that didn't involve me playing Tetris.

It's a proof of concept bit of code for creating 2d parralax scrolling.

<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/mVdMCNE_8xA&hl ... ram><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/mVdMCNE_8xA&hl=en&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>[/youtube]

For those interested the code is here.

Code: Select all

import pygame

class BG_Item(pygame.sprite.Sprite):
    def __init__(self,size=(64,64),position=(0,0),colour=(0,0,0),velocity=(0,0)):
        ## Call the __init__ function from the inherited class
        pygame.sprite.Sprite.__init__(self)

        ## Save a rect of the screen.
        self.screen = pygame.display.get_surface().get_rect()

        ## Create a surface to draw upon.
        self.obj = pygame.Surface(size)
        ## Fill in the surface with a colour
        self.obj.fill(colour)

        ## Create a rect from the size of our surface.
        self.rect = self.obj.get_rect()
        
        ## Set the position of our rect on the display
        self.rect.x = position[0]
        self.rect.y = position[1]

        ## Create a variable for the old position of our rect.
        ## We will use this to fill it in with the background colour/details.
        self.old_rect = (0,0,0,0)
        
        ##Set the speed at which the Surface scrolls
        self.velocity = velocity

    def update(self,amount):
        self.old = self.rect       
	self.rect = self.rect.move(amount)
        if (self.rect.x + self.rect.width) <= 0:
        	self.rect.x = self.rect.width + 400
				
RESOLUTION = (400,300)

pygame.init()
screen = pygame.display.set_mode(RESOLUTION,pygame.DOUBLEBUF)
pygame.key.set_repeat(1,1)
sky = BG_Item(RESOLUTION,(0,0),(0,0,200))
sun = BG_Item((48,48),(320,16),(200,200,0),(-1,0))
ground = BG_Item((400,64),(0,236),(0,230,0),(0,0))
cloud1 = BG_Item((32,16),(368,32),(240,240,240),(-3,0))
cloud2 = BG_Item((64,32),(232,64),(240,240,240),(-4,0))
cloud3 = BG_Item((128,64),(96,128),(240,240,240),(-5,0))
back_building1 = BG_Item((128,64),(0,180),(180,180,180),(-2,0))
back_building2 = BG_Item((128,96),(142,180-32),(180,180,180),(-2,0))
building1 = BG_Item((160,96),(0,204),(50,50,50),(-7,0))
building2 = BG_Item((160,128),(200,172),(50,50,50),(-7,0))
building3 = BG_Item((160,160),(380 ,300-160),(50,50,50),(-7,0))
objects = [
    sky,sun,
    ground,
    back_building1,
    back_building2,
    
    cloud1,
    cloud2,
    cloud3,
    
    building1,
    building2,
    building3,
    ]

def blit_to_screen():
	for object in objects:
		screen.blit(object.obj,object.rect)

def move_all():
	for object in objects:
		object.update(object.velocity)
		
blit_to_screen()
pygame.display.update()
clock = pygame.time.Clock()
while True:
	for event in pygame.event.get():
		if event.type == pygame.KEYDOWN:
			if pygame.key.get_pressed()[pygame.K_LEFT]:
				move_all()
				blit_to_screen()
			
			clock.tick(30)
			pygame.display.update()    
I welcome any constructive criticism on how I could have done it better.
"Simplicity is the ultimate sophistication." - Leonardo da Vinci
http://caveofgrizzle.blogspot.com/
User avatar
hurstshifter
ES Beta Backer
ES Beta Backer
Posts: 713
Joined: Mon Jun 08, 2009 8:33 pm
Favorite Gaming Platforms: SNES
Programming Language of Choice: C/++
Location: Boston, MA
Contact:

Re: 2D Parralax Scrolling

Post by hurstshifter »

I was actually considering messing around with some parallax scrolling after stumbling across a similar video earlier this week. Well done.
"Time is an illusion. Lunchtime, doubly so."
http://www.thenerdnight.com
User avatar
Big Grizzle
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 61
Joined: Wed Sep 02, 2009 1:07 pm
Current Project: 2d side scrolling shooter.
Favorite Gaming Platforms: The SNES rules all!!! Super Aleste baby!
Programming Language of Choice: Python
Location: London, UK
Contact:

Re: 2D Parralax Scrolling

Post by Big Grizzle »

Cheers dude.

Just been tinkering with adding a sprite.

<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/5iqmTNyefkQ&hl ... ram><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/5iqmTNyefkQ&hl=en&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>[/youtube]

Having trouble with keeping the player on screen. At the moment it checks the sprites (x,y) coordinates against the main screen's and changes the velocity to push the sprite back onto the screen. This makes it very jumpy when right up against the edges.

Code is here for anyone who gives a crap...

Code: Select all

import pygame

class Player(pygame.sprite.Sprite):
    def __init__(self,position):
        pygame.sprite.Sprite.__init__(self)
        self.screen = pygame.display.get_surface().get_rect()
        self.surface = pygame.image.load("ship1.png").convert()
        self.surface.set_colorkey((255,0,255))
        self.rect = self.surface.get_rect()
        self.old = self.rect
        self.position = position
        self.rect.x = position[0]
        self.rect.y = position[1]
        self.speed = [0,0]
        print self.rect

    def fly(self):
        self.old = self.rect
        self.rect = self.rect.move(self.speed)
        ## Standard 4-way
        if pygame.key.get_pressed()[pygame.K_LEFT]:
            self.speed = [-7,0]
        if pygame.key.get_pressed()[pygame.K_RIGHT]:
            self.speed = [7,0]
        if pygame.key.get_pressed()[pygame.K_DOWN]:
            self.speed = [0,7]
        if pygame.key.get_pressed()[pygame.K_UP]:
            self.speed = [0,-7]
        ## Diagonal left
        if pygame.key.get_pressed()[pygame.K_LEFT] and pygame.key.get_pressed()[pygame.K_DOWN]:
            self.speed = [-7,7]
        if pygame.key.get_pressed()[pygame.K_LEFT] and pygame.key.get_pressed()[pygame.K_UP]:
            self.speed = [-7,-7]
        ## Diagonal right
        if pygame.key.get_pressed()[pygame.K_RIGHT] and pygame.key.get_pressed()[pygame.K_DOWN]:
            self.speed = [7,7]
        if pygame.key.get_pressed()[pygame.K_RIGHT] and pygame.key.get_pressed()[pygame.K_UP]:
            self.speed = [7,-7]
        print "Position = ", self.rect.x,self.rect.y
        print "Speed = ", self.speed

    def onScreen(self):
        ## NEEDS TUNING ##
        ## Check we are on the screen 
        if self.rect.x < 1:
            self.speed[0] = 6 
            print "Off left side of screen"
        if self.rect.y < 1:
            self.speed[1] = 6
            print "Off top side of screen"
        if self.rect.x + self.rect.width > self.screen.width:
            self.speed[0] = -6
            print "Off right side of screen"
        if self.rect.y + self.rect.height > self.screen.height:
            self.speed[1] = -6
            print "Off bottom side of screen"
        
    def resetSpeed(self):
        """Called from main game loop on KEYUP event to stop other keys moving the ship"""
        self.speed = [0,0]

    def shoot(self):
        """Called from main game loop on KEYDOWN event to fire guns"""
        if pygame.key.get_pressed()[pygame.K_x]:
            print "SHOOTING AT YA!"
    def missile(self):
        """Called from main game loop on KEYDOWN event to fire missiles"""
        if pygame.key.get_pressed()[pygame.K_z]:
            print "HERE COME THE MISSILES!"
    def deathRay(self):
        """Called from main game loop on KEYDOWN event to fire death ray"""
        if pygame.key.get_pressed()[pygame.K_d]:
            print "DEATH RAY! ZZZzzzZZZzzzZZZzzz DEATH RAY!"
            
class BG_Item(pygame.sprite.Sprite):
    def __init__(self,size=(64,64),position=(0,0),colour=(0,0,0),velocity=(0,0)):
        ## Call the __init__ function from the inherited class
        pygame.sprite.Sprite.__init__(self)

        ## Save a rect of the screen.
        self.screen = pygame.display.get_surface().get_rect()

        ## Create a surface to draw upon.
        self.surface = pygame.Surface(size)
        ## Fill in the surface with a colour
        self.surface.fill(colour)

        ## Create a rect from the size of our surface.
        self.rect = self.surface.get_rect()
        
        ## Set the position of our rect on the display
        self.rect.x = position[0]
        self.rect.y = position[1]

        ## Create a variable for the old position of our rect.
        ## We will use this to fill it in with the background colour/details.
        self.old_rect = (0,0,0,0)
        
        ##Set the speed at which the Surface scrolls
        self.speed = velocity
        print self, "BG_Item initialised - OK"

    def update(self,amount):
        self.old = self.rect       
        self.rect = self.rect.move(amount)
        if (self.rect.x + self.rect.width) <= 0:
            self.rect.x = self.rect.width + 400
                
RESOLUTION = (400,300)

pygame.init()
screen = pygame.display.set_mode(RESOLUTION,pygame.DOUBLEBUF)
pygame.key.set_repeat(1,1)

sky = BG_Item(RESOLUTION,(0,0),(0,0,200))
sun = BG_Item((48,48),(320,16),(200,200,0),(-1,0))
ground = BG_Item((400,64),(0,236),(0,230,0),(0,0))
cloud1 = BG_Item((32,16),(368,32),(240,240,240),(-3,0))
cloud2 = BG_Item((64,32),(232,64),(240,240,240),(-4,0))
cloud3 = BG_Item((128,64),(96,128),(240,240,240),(-5,0))
back_building1 = BG_Item((128,64),(0,180),(180,180,180),(-2,0))
back_building2 = BG_Item((128,96),(142,180-32),(180,180,180),(-2,0))
back_building3 = BG_Item((128,96),(142+128+16,180-32),(180,180,180),(-2,0))
building1 = BG_Item((160,96),(0,204),(50,50,50),(-7,0))
building2 = BG_Item((160,128),(200,172),(50,50,50),(-7,0))
building3 = BG_Item((160,160),(380 ,300-160),(50,50,50),(-7,0))

ship = Player((1,120))

objects = [
    sky,sun,
    ground,
    back_building1,
    back_building2,
    back_building3,    
    cloud1,
    cloud2,
    cloud3,
    
    building1,
    building2,
    building3,
    ship
    ]

def blit_to_screen():
    for obj in objects:
        screen.blit(obj.surface,obj.rect)

def move_all():
    for obj in objects:
        obj.update(obj.speed)
        
blit_to_screen()
pygame.display.update()
clock = pygame.time.Clock()
while True:

    for event in pygame.event.get():
        if event.type == pygame.KEYDOWN:
            ship.fly()
            ship.onScreen()
            ship.shoot()
            ship.missile()
            ship.deathRay()
        if event.type == pygame.KEYUP:
            ship.resetSpeed()
    move_all()
    blit_to_screen()
    clock.tick(30)
    pygame.display.update()    
It could do with a bit of cleaning up as it was just a copy, paste and tweak job from two seperate source files.
"Simplicity is the ultimate sophistication." - Leonardo da Vinci
http://caveofgrizzle.blogspot.com/
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: 2D Parralax Scrolling

Post by dandymcgee »

Big Grizzle wrote: Having trouble with keeping the player on screen. At the moment it checks the sprites (x,y) coordinates against the main screen's and changes the velocity to push the sprite back onto the screen. This makes it very jumpy when right up against the edges.
Just check for edge of screen collision before you update the screen, if you collide change it back before you draw anything and you should never see the jumping effect.
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
User avatar
Bakkon
Chaos Rift Junior
Chaos Rift Junior
Posts: 384
Joined: Wed May 20, 2009 2:38 pm
Programming Language of Choice: C++
Location: Indiana

Re: 2D Parralax Scrolling

Post by Bakkon »

Yeah, directly modify the position to snap it back into the screen bounds. If you only change the velocity, if leaves a game tick to draw before it updates it back onto the screen.
User avatar
Big Grizzle
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 61
Joined: Wed Sep 02, 2009 1:07 pm
Current Project: 2d side scrolling shooter.
Favorite Gaming Platforms: The SNES rules all!!! Super Aleste baby!
Programming Language of Choice: Python
Location: London, UK
Contact:

Re: 2D Parralax Scrolling

Post by Big Grizzle »

Thanks Bakkon. I figured it out and that is exactly what I did. However I have introduced a new feature(BUG!) when the ship is travelling diagonally to the corner of the screen. If I release one of the direction keys the ship zooms off the screen until a keyup/keydown event. It is probably the flow of my game loop or something. I'll work it out eventually though.

Making a game is much more fun than when I made an income tax/national insurance calculator with Python and wxPython.
"Simplicity is the ultimate sophistication." - Leonardo da Vinci
http://caveofgrizzle.blogspot.com/
User avatar
Big Grizzle
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 61
Joined: Wed Sep 02, 2009 1:07 pm
Current Project: 2d side scrolling shooter.
Favorite Gaming Platforms: The SNES rules all!!! Super Aleste baby!
Programming Language of Choice: Python
Location: London, UK
Contact:

Re: 2D Parralax Scrolling

Post by Big Grizzle »

Slowly, but surely!

Unfortunately the combination of CamStudio, a couple thousand sprites being updated and then a Youtube conversion completely butt fucked any quality out of the video.

<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/44W3z5lU8rI&hl ... ram><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/44W3z5lU8rI&hl=en&fs=1&" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object>[/youtube]
"Simplicity is the ultimate sophistication." - Leonardo da Vinci
http://caveofgrizzle.blogspot.com/
User avatar
trufun202
Game Developer
Game Developer
Posts: 1105
Joined: Sun Sep 21, 2008 12:27 am
Location: Dallas, TX
Contact:

Re: 2D Parralax Scrolling

Post by trufun202 »

Dude, nice! The gameplay looks really smooth, and I like how you already have weapon upgrades in there.

Mowing down all of those enemies is just asking for a badass particle effect. ;)
-Chris

YouTube | Twitter | Rad Raygun

“REAL ARTISTS SHIP” - Steve Jobs
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: 2D Parralax Scrolling

Post by dandymcgee »

Lookin' good!
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
User avatar
MarauderIIC
Respected Programmer
Respected Programmer
Posts: 3406
Joined: Sat Jul 10, 2004 3:05 pm
Location: Maryland, USA

Re: 2D Parralax Scrolling

Post by MarauderIIC »

Neat. I liked the city theme better though :D
I realized the moment I fell into the fissure that the book would not be destroyed as I had planned.
User avatar
Big Grizzle
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 61
Joined: Wed Sep 02, 2009 1:07 pm
Current Project: 2d side scrolling shooter.
Favorite Gaming Platforms: The SNES rules all!!! Super Aleste baby!
Programming Language of Choice: Python
Location: London, UK
Contact:

Re: 2D Parralax Scrolling

Post by Big Grizzle »

Thanks for the kind words. Still so much to do.

A particle effect?....Hmmmmm. Gives me an idea.

BTW...the city scape is still being used.
"Simplicity is the ultimate sophistication." - Leonardo da Vinci
http://caveofgrizzle.blogspot.com/
User avatar
Bakkon
Chaos Rift Junior
Chaos Rift Junior
Posts: 384
Joined: Wed May 20, 2009 2:38 pm
Programming Language of Choice: C++
Location: Indiana

Re: 2D Parralax Scrolling

Post by Bakkon »

Big Grizzle wrote: A particle effect?....Hmmmmm. Gives me an idea.
The way you're firing bullets is already a variant of a particle effect. Just have to modify the way they move and die off. ;)
User avatar
MarauderIIC
Respected Programmer
Respected Programmer
Posts: 3406
Joined: Sat Jul 10, 2004 3:05 pm
Location: Maryland, USA

Re: 2D Parralax Scrolling

Post by MarauderIIC »

So, using the cityscape, can you have stuff scroll by in front of the player? That way you can have the player fly through a building (this would be awesome), as well as have him fly between buildings.
I realized the moment I fell into the fissure that the book would not be destroyed as I had planned.
User avatar
Big Grizzle
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 61
Joined: Wed Sep 02, 2009 1:07 pm
Current Project: 2d side scrolling shooter.
Favorite Gaming Platforms: The SNES rules all!!! Super Aleste baby!
Programming Language of Choice: Python
Location: London, UK
Contact:

Re: 2D Parralax Scrolling

Post by Big Grizzle »

Yes. That is entirely possible. I could also have clouds rendered with an alpha value that will be rendered over the player to give the impression that you are flying through them.

Each star is basically a sprite. I have at the moment 4 layers of them scrolling at diffferent speeds to give the illusion of depth. Just like the cityscape. I can also do a fake rotating effect by moving the bottom layers in the opposite direction of the closer layers.

My plan at the moment is to start in space at the edge of the solar system and progress towards Earth using the planets as background sprites. Upon reaching Earth the player is going to go into the atmosphere and end up over a city. This way I also get to have an asteroid segement. :)

That said I have just spent the last two days trying to get the frame rate back up above 30 frames due to a combination of too many stars (I had about 1600) and a weird bug in my collision detection that was allowing certain bullets to pass through the enemies.
"Simplicity is the ultimate sophistication." - Leonardo da Vinci
http://caveofgrizzle.blogspot.com/
User avatar
eatcomics
ES Beta Backer
ES Beta Backer
Posts: 2528
Joined: Sat Mar 08, 2008 7:52 pm
Location: Illinois

Re: 2D Parralax Scrolling

Post by eatcomics »

This game sounds great but I can't watch the videos, I'm on an iPod but I will definitely watch later :)
Image
Post Reply