What to i mean by "2d world coordinates to camera coordinates"? Well... Yknow how in 3d DBPro apps, you position your objects in the world, and then you move your camera around? Why not place your 2d objects in the world, and then move your camera around?
Here's some code that does that. Basically, here's what you do:
1. Take all the units with their world coordinates
2. Translate all those points so that the camera is at 0,0
3. Rotate all those points so that the camera has 0 rotation
4. Divide those units by the scale factor (units per screen width) to get Screen widths, and add half a screen width to that.
5. Multiply that by pixels per screen width, and you have coordinates of any object in world coordinates, on the screen!
Rotation and translation:
x'=cos(-camtheta)*(x-camx)-sin(-camtheta)*(y-camy)
y'=sin(-camtheta)*(x-camx)+cos(-camtheta)*(y-camy)
Throw in unit conversion...
x'=width*((cos(-camtheta)*(x-camx)-sin(-camtheta)*(y-camy))/scale)+0.5*width
y'=width*((sin(-camtheta)*(x-camx)+cos(-camtheta)*(y-camy))/scale)+0.5*height
where (camx,camy) is the camera's position, camtheta is the camera's rotation, (x,y) is the object's position, and width and height are the width and height of the screen in pixels.
here's some code implementing that:
`INITIATE T3H TYPES!!!
type plvector
x as float `x position
y as float `y position
r as float `rotation
s as float `size
endtype
type spr
imagenum as integer `the image to be displayed
spritenum as integer `the number of the DBPro sprite
exist as boolean `whether or not the DBPro sprite exists
s as float `the unit's size in world units
endtype
type unit
w as plvector `w for World coordinates
l as plvector `l for Local coordinates
v as spr `v for Visual variables
endtype
sync on
sync rate 30
`the global and important arrays
global objnum as integer `the number of objects
global camera as plvector `the cameras position and rotation
global width as integer
width = screen width() `the width of the screen
global height as integer
height = screen height() `the height of the screen
dim object(0) as unit `an array to store the data of all the objects in.
camera.x=0
camera.y=0
camera.r=0
camera.s=20 `the screen will be twenty world units wide
for a=1 to 50
create_unit(0,0,rnd(200)-100,rnd(200)-100,rnd(360),rnd(19)+1)
Next
do
cls
movecam((upkey()-downkey())/5.0)
turncam(rightkey()-leftkey())
inc camera.s,-mousemovez()/100.0
if camera.s<1 then camera.s=1
update_units()
showunits()
text 0,0,"camx: "+str$(camera.x)
text 0,16,"camy: "+str$(camera.y)
text 0,32,"cams: "+str$(camera.s)
text 0,48,"camr: "+str$(camera.r)
text 0,64,"FPS: "+str$(screen fps())
sync
Loop
function create_unit(spritenum,imagenum,x,y,rotation,size)
array insert at bottom object(0)
inc objnum
object(objnum).w.x=x
object(objnum).w.y=y
object(objnum).w.r=rotation
object(objnum).w.s=size
Endfunction
function movecam(distance as float)
inc camera.x, cos(camera.r-90)*distance
inc camera.y, sin(camera.r-90)*distance
Endfunction
function turncam(angleval as float)
inc camera.r,angleval
Endfunction
function update_units()
for a=1 to objnum
s#=sin(-camera.r)
c#=cos(-camera.r)
`Go rotation matrices and unit conversion!!!
`Basically, you take the world coordinates, then translate them by the negative camera coordinates
`then rotate them by negative camera coordinates. Then you divide it by the camera scaling
`which is in units per screen width (giving you a result in screen widths), then, you add half
`a screen width to that (because the screen x/y positions are only positive, while the world
`x/y camera positions are in the middle of the camera). After that, you multiply that by
`pixels/screen width, and you have yerself some local coordinates! Fortunately, this can be
`summed up all into one nice (arguably) little (arguably) line.
`x'=width*((c#*(x-camx)-s#*(y-camy))/scale)+0.5*width
`y'=width*((s#*(x-camx)+c#*(y-camy))/scale)+0.5*height
r#=c#*(object(a).w.x-camera.x)-s#*(object(a).w.y-camera.y)
object(a).l.x=width*(r#/camera.s)+0.5*width
r#=s#*(object(a).w.x-camera.x)+c#*(object(a).w.y-camera.y)
object(a).l.y=width*(r#/camera.s)+0.5*height
object(a).l.r=object(a).w.r-camera.r `the object isn't still at world rotation!
object(a).l.s=object(a).w.s/(camera.s*2)*width `it needs to be resized too.
Next
Endfunction
function showunits()
for a=1 to objnum
`if object(a).l.x>0 then if object(a).l.y>0 then if object(a).l.x<width then if object(a).l.y<height
`show position
dot object(a).l.x,object(a).l.y
` show size
circle object(a).l.x,object(a).l.y,object(a).l.s
`show rotation
line object(a).l.x,object(a).l.y,object(a).l.x+cos(object(a).l.r)*object(a).l.s,object(a).l.y+sin(object(a).l.r)*object(a).l.s
`endif
Next
Endfunction
This is meh first working app using matrices, woopoo!