I decided to make a 2d camera that could be used "plug and play", without much if any work to integrate it into your program. Basically, you tell the camera whether to move up and down, or zoom in and out, and it (using eye pleasing velocity/friction/acceleration methods) supplies you with this function:
cs_transformPointToScreen(x as float, y as float)
which returns (in a UDT global vector2 "ret") the new coordinates on the screen
The best thing about this is the self-contained camera code. If you had a tech demo or a little project using cs_transformPointToScreen (I would assume anyone in a serious project would take the time to write their own, better stuff
), you could easily change the transformation code to include translation or other transformations to your heart's content.
`set display mode 1280,800,32
`one U stands for one world unit
type vec2
x as float
y as float
endtype
global ret as vec2
dim arrgh(1000) as vec2
sync rate 60
d3d_init
cs_init()
for n=0 to 1000
arrgh(n).x=sNormInv(rnd(10000)/10000.0)*30
arrgh(n).y=sNormInv(rnd(10000)/10000.0)*30
next
do
cls
cs_Update()
cs_ZoomIn(mousemoveZ()*.001)
cs_Strafe(upkey()-downkey(),rightkey()-leftkey())
for n=0 to 1000
cs_transformPointToSCreen(arrgh(n).x,arrgh(n).y)
d3d_circle ret.x,ret.y,cs_linScale(1),0
//print ret.x
//print ret.y
next n
//print cs_zoom
sync
loop
function cs_ZoomIn(n as float)
inc cs_zoomVel,n
endfunction
function cs_Update()
cs_zoom=2^cs_zoomVal
if cs_Vel.x>cs_MaxVel.x/cs_zoom then cs_Vel.x=cs_MaxVel.x/cs_zoom
if cs_Vel.y>cs_MaxVel.y/cs_zoom then cs_Vel.y=cs_MaxVel.y/cs_zoom
if cs_Vel.x<-cs_MaxVel.x/cs_zoom then cs_Vel.x=-cs_MaxVel.x/cs_zoom
if cs_Vel.y<-cs_MaxVel.y/cs_zoom then cs_Vel.y=-cs_MaxVel.y/cs_zoom
cs_zoomVel=cs_zoomVel*cs_zoomFric
inc cs_Pos.x,cs_Vel.x
inc cs_Pos.y,cs_Vel.y
cs_Vel.x=cs_Vel.x*cs_Fric.x
cs_Vel.y=cs_Vel.y*cs_Fric.x
inc cs_zoomVal, cs_zoomVel
cs_zoomVel=cs_zoomVel*cs_zoomFric
endfunction
function cs_strafe(up as integer, right as integer)
inc cs_Vel.x,cs_Acc.x*right/cs_zoom
inc cs_Vel.y,cs_Acc.y*up/cs_zoom
endfunction
function cs_LinScale(p as float)
a as float
a=cs_PPU*p*cs_zoom
endfunction a
function cs_init()
global cs_PPU as float
global cs_zoom as float
global cs_zoomVal as float `camera_zoom=2^zoomVal
global cs_Pos as vec2
global cs_Vel as vec2
global cs_Acc as vec2
global cs_MaxVel as vec2
global cs_Fric as vec2
global cs_zoomVel as float
global cs_zoomFric as float
cs_PPU=100 `base pixels per world unit (when camera_zoom=0)
cs_zoom=1 `higher zoom is... well, more zoom. Everything looks BIGGGERRRRR!!!!
cs_zoomVal=0 `camera zoom is exponential, this value is linear (easier to control). cs_zoom=2^cs_zoomVal
`Actual PPU = PPU*cs_zoom=PPU*2^cs_zoomVal
`basically, when camera_zoom is zero, there are screen width()/PPU world units on screen.
`when cs_zoomVal = 1, there is half a world unit on the screen (when PPU=screen width())
`when cs_zoomVal =-1, there are two world units on screen. (when PPU=screen width())
`so, taking camera zoom into account:
`world units on screen = screen width()*2^(-camera_zoom)*1/PPU
`0 camera zoom would have every world unit on the screen, and infinite camera zoom would have zero world units on screen.
cs_Pos.x=0.0 `the position of the CENTER of the camera
cs_Pos.y=0.0
cs_Vel.x=0.0 `the velocity of the camera
cs_Vel.y=0.0
cs_Acc.x=.1 `acceleration when the arrow keys are pressed
cs_Acc.y=.1
cs_MaxVel.x=.2 `maximum velocity
cs_MaxVel.y=.2
cs_Fric.x=.9 `"friction" on the camera... but not actually friction. cameraVel=cameraVel*camFric each frame
cs_Fric.y=.9
cs_zoomVel=0
cs_zoomFric=.7
endfunction
function cs_transformPointToScreen(x as float, y as float)
width=screen width()
height=screen height()
ret.x=((x-cs_Pos.x)*(cs_PPU*cs_zoom))+0.5*width
ret.y=-((y-cs_Pos.y)*(cs_PPU*cs_zoom))+0.5*height
`translate the point so that the camera is the origin, scale correctly
`negate the y value part so up on your screen is positive world coords.
`add half the screen width/height because camera_x/y represents the center of the camera, not the top left or whatever.
endfunction
Function SNormInv(p as float)
q as float
r as float
A1 as float
A2 as float
A3 as float
A4 as float
A5 as float
A6 as float
B1 as float
B2 as float
B3 as float
B4 as float
B5 as float
C1 as float
C2 as float
C3 as float
C4 as float
C5 as float
C6 as float
D1 as float
D2 as float
D3 as float
D4 as float
P_LOW as float
P_HIGH as float
`Coefficients in rational approximations.
A1= -39.69683
A2= 220.9461
A3= -275.9285
A4= 138.3578
A5= -30.66480
A6= 2.506628
B1= -54.47610
B2= 161.5858
B3= -155.6990
B4= 66.80131
B5= -13.28068
C1= -0.007785
C2= -0.322396
C3= -2.400758
C4= -2.549733
C5= 4.374664
C6= 2.938164
D1= 0.007784696
D2= 0.3224671
D3= 2.445134
D4= 3.754409
P_LOW= 0.02425
P_HIGH=1-P_LOW
if p>0 and p<P_LOW
`Rational approximation for lower region.
q = Sqrt(-2*Log(p))
ret#=(((((C1*q+C2)*q+C3)*q+C4)*q+C5)*q+C6)/((((D1*q+D2)*q+D3)*q+D4)*q+1)
exitfunction ret#
endif
If p>=P_LOW and p<=P_HIGH
`Rational approximation for central region.
q=p-0.5
r=q*q
ret#=(((((A1*r+A2)*r+A3)*r+A4)*r+A5)*r+A6)*q/(((((B1*r+B2)*r+B3)*r+B4)*r+B5)*r+1)
exitfunction ret#
endif
if p> _HIGH and p<1
`Rational approximation for upper region.
q = Sqrt(-2*Log(1-p))
ret#=-(((((C1*q+C2)*q+C3)*q+C4)*q+C5)*q+C6)/((((D1*q+D2)*q+D3)*q+D4)*q+1)
exitfunction ret#
endif
endfunction 0.0
Is't life, I ask, is't even prudence, to bore thyself and bore thy students?