Parallax scrolling

Everything else that doesn't fall into one of the other PB categories.
Joubarbe
Enthusiast
Enthusiast
Posts: 745
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Parallax scrolling

Post by Joubarbe »

Hello,

I'm developing my own game for a while now, and it's time for me to face some challenges I had a very hard time working with. They always say that you need to be good at math to code ; well, I have a pretty decent result with a very poor knowledge in math, but when it comes to camera... Ouch!

The problem is I need something specific : a scrolling camera (through a mouse button) that can zoom (in/out on cursor) and support multiple "layers" and multiple resolutions.
The idea is to have a 2D space game with a grid (layer 1), planets (layer 2), nebulae (layer 3), stars (layer 4, which remains still).

In a nutshell, something that looks professional... And for now... :

Code: Select all

Procedure.b CheckBoundaries()
    Define mapW.l, mapH.l, returnFalse.b
    
    If currentSector <> ""
      mapW = grid\width
      mapH = grid\height
    Else
      mapW = #GalaxyBackgroundSize * 3
      mapH = #GalaxyBackgroundSize * 1.5
    EndIf
    
    If currentSector = ""
      If diffX > mapW - ScreenWidth() ; right
        diffX = mapW - ScreenWidth()
        returnFalse = 1
      ElseIf diffX < ScreenWidth() - mapW ; left
        diffX = ScreenWidth() - mapW
        returnFalse = 1
      EndIf
      If diffY > mapH - ScreenHeight() ; down
        diffY = mapH - ScreenHeight()
        returnFalse = 1
      ElseIf diffY < ScreenHeight() - mapH ; up
        diffY = ScreenHeight() - mapH
        returnFalse = 1
      EndIf
    Else
      If diffX > 0
        diffX = 0
        returnFalse = 1
      ElseIf diffX < ScreenWidth() - mapW
        diffX = ScreenWidth() - mapW
        returnFalse = 1
      EndIf  
      If diffY > 0
        diffY = 0
        returnFalse = 1
      ElseIf diffY < ScreenHeight() - mapH
        diffY = ScreenHeight() - mapH
        returnFalse = 1
      EndIf
    EndIf
    
    DoIf(returnFalse, ProcedureReturn #False)    
    ProcedureReturn #True
  EndProcedure
  
  Procedure Scrolling(force.b = #False)
    Static cursorX.l, cursorY.l, originX.l, originY.l
    
    If force
      cursorX = mouseX
      cursorY = mouseY
      originX = diffX
      originY = diffY
      diffX = originX - (cursorX - mouseX)
      diffY = originY - (cursorY - mouseY)
      CheckBoundaries()
    ElseIf rmbClicked
      cursorX = mouseX
      cursorY = mouseY
      originX = diffX
      originY = diffY
    ElseIf (rmbPushed And (cursorX <> mouseX Or cursorY <> mouseY))
      UI::blocked = #True
      diffX = originX - (cursorX - mouseX)
      diffY = originY - (cursorY - mouseY)
      DoIf(CheckBoundaries() = #False, Scrolling(#True)) ; avoid increasing offset when scrolling out of screen
    ElseIf rmbReleased
      If currentSector = ""
        UI::RegisterPlanetTooltips() ; register new diffX/diffY
      EndIf
      UI::blocked = #False
    EndIf
    
  EndProcedure

  Procedure ConvertZoomDiffXY(oldZoomRate.f, newZoomRate.f)
    diffX = ((diffX - mouseX) * newZoomRate / oldZoomRate) + mouseX
    diffY = ((diffY - mouseY) * newZoomRate / oldZoomRate) + mouseY
  EndProcedure

  Procedure CenterCamera(onGalaxy.b = #True)
    If onGalaxy
      diffX = 0
      diffY = 0
    Else
      zoomInfo\current = zoomInfo\max
      FixZooming(#True)
      diffX = (-allSectors()\statics\width + ScreenWidth()) / 2
      diffY = (-allSectors()\statics\height + ScreenHeight()) / 2 
      diffX = (-grid\width + ScreenWidth()) / 2
      diffY = (-grid\height + ScreenHeight()) / 2    
    EndIf
  EndProcedure
... looks utterly ugly!
It's a very old piece of code and I don't even understand half of it (it's useless to copy/paste the other procedures, it's even more of a mess).

So... Is there a library or something PB-friendly somewhere ? Or should I pay people who knows what they're doing instead ? :)
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Parallax scrolling

Post by Lunasole »

The layers (Z-order) should not be merged on camera, it is renderer part. In my game camera is just a viewport defining what area of world should be rendered, with implemented methods to move/pan/zoom, etc.

Thus, parallax scrolling should not depend on camera too. I think it must be implemented within renderer - you just taking camera coordinates and shifting object coordinates (and/or scaling) depending on object layer. Doesn't seems than lot of math is needed for that.
But I didn't come yet to parallax scrolling so can't bring any examples 8) From camera-related issues I'm having more attention to other problem - how to implement smooth pan/zoom to any value without any floating-point caused artifacts.
Last edited by Lunasole on Tue Mar 08, 2016 7:35 pm, edited 1 time in total.
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Parallax scrolling

Post by Lunasole »

What about "game camera libraries", I don't know any and searched previously too. I think you cannot have ready-to-use camera unless you are using completed game engine. Purebasic has Ogre3D integrated (which also can be nicely used for 2D) but I found it requiring too much work as for me, need to create the models and other stuff needed to work with 3D engine, etc.
I also looked at some 2D engines like Cocos2D and several other opensource, but I'm finding that efforts requiring to learn any of them (and its tools) goodl enough are not lesser than efforts and time you will apply to write requiring functionality by yourself, so as for me this also has no sense and it is better to learn and do by yourself.

Also there are OpenGL functions related to camera (viewport) but I don't know how useful they can be for scrolling as didn't learned them well yet.
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
Joubarbe
Enthusiast
Enthusiast
Posts: 745
Joined: Wed Sep 18, 2013 11:54 am
Location: France

Re: Parallax scrolling

Post by Joubarbe »

Yep, I know the feeling. That's why I'd only like to have a camera module. But I didn't think of taking the layers out of the camera ; it sounds pretty obvious now (especially because in my case, the zoom would only apply to the first layer) :) But the problem remains with the camera. I gave up a long time ago on smooth zooming ; always had big ugly problems ^^
Post Reply