I am working on a small 2D-sidescrolling-jump-and-run-game and wanted to include portals, because I am so fascinated of the videos of portal 2.

So I tried to program a small, simple 2D-Portal-Algorithm, so that in my game characters or objects can fall into a portal and out of the other one, with their correct rotation, speed etc.
It works well so far, but doesn't look very good... just come circles and lines in my test-program.

First an image of the examplecode:
And here the code itself:
+ Code Snippetset display mode 800,600,32
sync on : sync rate 30
set window off
randomize timer()
rem Setup
global Gravity as float : Gravity = 0.5
global PortalCount as integer : PortalCount = 0
dim Portal(0) as Portaltp
type Portaltp
X as integer
Y as integer
Angle as integer
endtype
SetupPortals()
global ObjectCount as integer : ObjectCount = 0
dim Object(0) as Objecttp
type Objecttp
X as float
Y as float
Xmove as float
Ymove as float
LastPortal as dword `Timer value of portal-time
endtype
global LastObject as integer
global ObjectDelay as integer : ObjectDelay = 1000
global Object_PortalDelay as integer : Object_PortalDelay = 300
global Object_MoveX
do
cls rgb(100,100,255)
print "FPS: ", screen fps()
print "Objects: ", ObjectCount
print "Key: ", scancode()
print "Object-Move-X: ", Object_MoveX
print
print "Press 1 or 2 to move portals, rightclick to rotate."
print "Leftclick to create objects"
print "Change Object-Move-X with right/leftkey"
print "Press P to create new Portal"
CreatePortals()
ManagePortals()
DrawPortals()
CreateObjects()
ManageObjects()
DrawObjects()
rem Object-Move-x
rl = rightkey()-leftkey()
if rl <> 0
inc Object_MoveX, rl
wait 200
endif
sync
loop
function SetupPortals()
for p = 1 to 2
inc PortalCount
array insert at bottom Portal(0), p
Portal(p).X = rnd(800)
Portal(p).Y = rnd(600)
Portal(p).Angle = rnd(360)
next p
endfunction
function CreatePortals()
i$ = inkey$()
if i$ = "p"
inc PortalCount
array insert at bottom Portal(0), PortalCount
Portal(PortalCount).X = rnd(800)
Portal(PortalCount).Y = rnd(600)
Portal(PortalCount).Angle = 180
endif
endfunction
function ManagePortals()
s = scancode()-1
if s => 1 and s <= PortalCount
Portal(s).X = mousex()
Portal(s).Y = mousey()
if mouseclick()=2 then Portal(s).Angle = wrapvalue(Portal(s).Angle+mousemovex())
endif
endfunction
function DrawPortals()
ink rgb(255,128,64),0
for p = 1 to PortalCount
circle Portal(p).X, Portal(p).Y, 50
line Portal(p).X, Portal(p).Y, Portal(p).X+50*sin(Portal(p).Angle), Portal(p).Y+50*cos(Portal(p).Angle)
line Portal(p).X-50*sin(Portal(p).Angle+90), Portal(p).Y-50*cos(Portal(p).Angle+90), Portal(p).X+50*sin(Portal(p).Angle+90), Portal(p).Y+50*cos(Portal(p).Angle+90)
next p
endfunction
function CreateObjects()
if mouseclick()=1
t = timer()
if t-LastObject > ObjectDelay
LastObject = t
inc ObjectCount
array insert at bottom Object(0), ObjectCount
Object(ObjectCount).X = mousex()
Object(ObjectCount).Y = mousey()
Object(ObjectCount).Xmove = Object_MoveX
Object(ObjectCount).Ymove = 2 - rnd(40)/10.0
endif
endif
endfunction
function ManageObjects()
time = timer()
for o = 1 to ObjectCount
rem Position-Update
inc Object(o).Ymove, Gravity
inc Object(o).Y, Object(o).Ymove
inc Object(o).X, Object(o).Xmove
rem Delete if outside screen
if Object(o).Y > 700
dec ObjectCount
array delete element Object(0), o
exit
endif
rem Portal-Collision
if time-Object(o).LastPortal > Object_PortalDelay
for p = 1 to PortalCount
rem Check distance... you should change this algorithm
XDis = Object(o).X-Portal(p).X
YDis = Object(o).Y-Portal(p).Y
Dis = XDis^2+YDis^2
rem Object in Portal
if Dis < 6400 `80^2
p2 = TargetPortal(p)
Object(o).X = Portal(p2).x
Object(o).Y = Portal(p2).y
Portal_Angle = Portal(p2).Angle - Portal(p).Angle
Res_AngleAdd = Portal_Angle-180
ActAngle# = atanfull(Object(o).Xmove, Object(o).Ymove)
ResAngle# = ActAngle# + Res_AngleAdd
Speed# = sqrt(Object(o).Xmove^2+Object(o).Ymove^2)
Object(o).Xmove = Speed#*sin(ResAngle#)
Object(o).Ymove = Speed#*cos(ResAngle#)
Object(o).LastPortal = timer()
exit
endif
next p
endif
next o
endfunction
function DrawObjects()
ink 0,0
for o = 1 to ObjectCount
circle Object(o).X, Object(o).Y, 30
next o
endfunction
function TargetPortal(p)
if PortalCount = 1
r = 1
else
repeat
r = 1 + rnd(PortalCount-1)
until p <> r
endif
endfunction r
At first there are just two portals, you can position them by pressing the number key (1 or 2 in this case), and rotate them by also pressing the right mouse button and move the mouse.
Objects can be created with leftclicks, the "Object-X-Move"-Variable defines their start-direction (X-Speed).
You can create new portals by pressing 'p' and edit them with the key, whichs ascii-number is 1 higher then the portal-number (so first 10 portals on key 0-9 at the top).
Maybe it helps someone..

Looking forward to any comments, ideas etc..