2D Camera + ViewPort + SetOrigin

BlitzMax Forums/BlitzMax Beginners Area/2D Camera + ViewPort + SetOrigin

blackwater(Posted 2012) [#1]
Hi all. I'm working with Blitzmax again after a long hiatus and need to revisit a few issues that I was never able to wrap my head around. In my future game I'm currently setting the groundwork for, I'm going to have a map much larger than what can fit on the screen.

For starters I'm working on an editor to create the game world and will need to be able to scroll around the level, placing various sprites.

So let's say my game world is 5000p x 5000p. The only way to move around is using SetOrigin, correct? I just discovered that the SetOrigin command takes inverted numbers. For example, to move 100 pixels to the right on the X axis, I actually have to put in -100 for X in SetOrigin, is that right? So in any direction, I have to add or subtract in the opposite direction that I'm really going?

Assuming that's the case (hopefully someone will confirm), how do I keep track of where I am in the actual game world? Do I just keep a global X and Y variable? So if my Origin is -500 for X, my global X variable will actually be 500? Is there a better way of doing this?

So that brings me to my second point, SetViewPort. The way I understand it, as long as my ViewPort matches my where I am in the game world, it will only draw that portion of it. I can have another function drawing a 1000 sprites but BM will only draw the ones within the viewport boundry?

Using the above example, if my xorigin (the adjusted one) is 500, I would SetViewPort for 500 (and Y, width, and height to match my screen), it's going to save a ton of memory, processing, etc by only drawing that part of my world?

Hopefully I wasn't too long winded :) If anyone can shed some light on this, confirm what I said or point me in a new direction it would be greatly appreciated, thanks!


Midimaster(Posted 2012) [#2]
That's right. Your player moves in real coordinates to f.e. X=2000,Y=1200. This depends not on any SetOrigin() or SetViewport(): All actors, enemies, buildings and the player have the real world coordinates. So you can check collisions, etc...

The SetOrigin() can be set independent as you need it. You can set it to center the player:
SetOrigin -Player.X-ScreenWidth()/2, -Player.Y-ScreenHeight()/2

will show the screen from X=1600 to x=2400

or to jump with the camera to the end of your world:
SetOrigin -5000+ScreenWidth(), -5000+ScreenHeight()

will show the screen from X=4200 to X=5000

or fly over the scenery:
Step=step+1
SetOrigin 2000, -step

will show moving Y from (Y=0 to Y=600) to (Y=1 to Y=601) ...to (Y=4400 to Y=5000)

The ViewPort for all this is always ....
0,0,ScreenWidth(),Screenheight()

...which already cares about scenery outside of the visible window will not be drawn.
So ,there is no need to react on SetOrigin(). You only need SetViewPort, if you want to restrict areas inside the visible screen.


blackwater(Posted 2012) [#3]
That's awesome, thanks. One more question for this topic, what is the best way to keep track of where the screen is in the game world? Should I just keep a global variable X and Y, and adjust that normally the same time I adjust SetOrigin? Or is there a better, more accepted way?

Last edited 2012


Midimaster(Posted 2012) [#4]
yes, I would do it this way too.

....
' case screen to the player:
    ScreenXoff%=Player.X-ScreenWidth()/2
    ScreenYoff%=Player.Y-ScreenHeight()/2
'case else...
....
Function DrawAll()
     SetOrigin -ScreenOffX, -ScreenOffY
     ...