Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Messages - nabz32

#286
Hello again,

I have opened a new branch to my rpg engine, so it can serve as jump and run engine.

Added a Box Editor / placement editor. Added simple box shadows and player shadow.
Added proper box collision routines.
finished the enemy editor / placement editor. Implemented proper hit detection routines.
added Terrain ghosting when it blocks the view to the player.
Added acceleration and mommentum to the players movement.
Added X Z rotation to the player when he stands on a slope.
Added speed gain / loss when walking on a slope.
Added controlable camera rotation.
Rewritten the event execution engine.
Added Effects ( mostly 3d plains with animated texture ).
Removed the lawn effect for now ( drops the frame rate to much on the Pandora ).
Made the whole engine compatible with maps of any size.

Working on:
Allowing boxes to move, so they can serve as platforms.

Latest videos (older to newest ):






#287
are the ceiling and floor just one plain?
Or is the depth effect archieved through fogging?
#288
I tried to modify a sprite on the run,
I loaded the sprites data with SPRITE2MEM and stored it
in an array.

On the Pandora SPRITE2MEM didn´t gave me any sprite data for my array.

Got around this by resaving the image into a file on the PC using SPRITE2MEM once
and now I am loading it everytime using openfile on the Pandora.

Anyone else had this trouble also?

Edit: Good that MEM2SPRITE works on the Pandora :good:
#289
regarding bump mapping,
could I use it to get a similar effect like the one i currently use in my jump and run,
without having to redraw my triangles twice?

Here is a pick of the effect:
https://www.dropbox.com/s/37czyqknomsyf0e/Screenshot%202014-07-27%2014.35.42.png

I never used bump maps so far
and i am eager to try it out.

// Result

I better reserve the Bump Maps for depth effects on textures,
also I occured crashes when trying to overwrite / update an object that has been drawn using a bump map.
#290
Quote from: Hark0 on 2014-Jun-17
IMHO the most difficult task of RPG game are the formula combats and balancing stats of hero, enemys, etc...

I need some help about this....

Any good tutorial ?

Had the same Problem when trying to get formulas down for this too.
My approach:
1. The player / Enemy needs basic stats that grow with EXP ( those stats can only be permamently changed )
2. Only Items can Offset the Primary stat values temporary

Code (glbasic) Select

function getPrimaryStat: i as int // i is the type of stat (ie.: 0 : strength, 1: stamina ... )

return Player.stats[ i ] + Player.equip.statOfs[ i ]
// + Player.tempEffect[ i ] for holding temporary changes that result in using an item
// (ie. strength potion )
endfunction
// you could also use getAttack as function name and return Player.attack + Player.attackOf
// so the code is better readable, however way more functions are needed then
// the Player.equip[ i ].statOfs[ i ] is the sum of all equiped items primari stat offsets.
// So making a list of stat values and corresponding stat names is important.


3. Based on those stats calculate secondary stats like attack , def 
( all the stats that can be changed temporary by equiping items )

4. Items Hold only secondary stats and offsets for primary stats

5. All those stats Items hold will be added together using a function and stored in a list for each entity that can equip items.

6. So a secondary stat like attack can be calculated like this
Code (glbasic) Select

function getSecondaryStat: i as int
return Player.equip.stats[ i ] + getPrimaryStat( i )
//return all items added attack stats + Player strength stat + item strength offset
// of course you can calculate the strength stat as a percentual value to a Max Strength value //marking 100% of strength ( 100% can be exceeded ) and multiply it with the items added attack //stats:
return Player.equip.stats[ i ] * ( getPrimaryStat( i ) ) / MaxStat[ i ] )
endfunction


7. then this secondary stat ( ie. attack ) can be used to calculate damage, based on the enemys secondary stat ( ie. defense ) , his element...

This resulted by the following needs:
-Primary stats should only be calculated each Lvl up, beacause I wanted the player to decide on his grow type almost freely ( also dependant on his class ) each level up.
-I didn´t want to limit any stat to certain item types.



#291
Just saw this today.
What a nice Arcade game,
the Tree Boss is epically animated :good:

#292
Danke für das Lob  :good:
hab mir auch richtig Mühe gegeben für den Block Editor.
Ich habe die RPG Engine verwendet und sie zu einer Jump And Run Engine gemacht
( Das Ereigniss System habe ich natürlich behalten ).
Weil ich noch ein unfertiges Jump and Run mit DBpro habe, ist das die einfachere Variante.


Hier auch ein Video von einem kleinem ersten Test auf der Pandora:
(mit dem noch nicht optimierten AlphaTesting Wert )



#293
Hat sich schon wieder erledigt,
man sollte halt die passende ALPHATESTING value zu dem angesetzten ALPHAMODE wählen,
nurnoch schnell auf der Pandora testen...
#294
Hallo, ich habe mich an shadow mapping versucht.

Dafür habe ich einfach die erstellten plains ( aus 2 Triangeln ) erneut mit anderer Textur und aktiviertem Alpha Testing über die alten noch einmal gezeichnet.

Funktioniert auch ganz gut, nur bekomme ich weiße Ränder an den nochmals gezeichneten Schatten plains.

Auf diesem Bild sollte man es gut erkennen können:
https://www.dropbox.com/s/37czyqknomsyf0e/Screenshot%202014-07-27%2014.35.42.png

Das Format der Schatten Texturen ist 64x64.

Je tiefer ich diese plains auf das Terrain lege, desto weniger fallen die Ränder auf, jedoch
brauche ich mehr Distanz zu dem Terrain in der Pandora Version, da anscheinend der Pandora Z-Buffer nicht so empfindlich ist, wie auf dem PC.



#295
sorry for being of for so Long,

I am going to write my tests at the beginning of the next month and I have gone all MU 0 Assembler since then.

The only Thing preventing me from sharing is a bug, where sometimes somehow my Offset values become the current coordinates.
I fixed this just by checking if the Offset values are to large, works on all the test, but because of this I was ashamed to post it, I will look at this closer when the Weekend sets in.

Basically it is to functions, one which holds X and Z in bounds and one for Y , I will also try to get everything into a single call.
#296
I got everything working by casting the movement values to integer values before the calculation in the intersection function.

Based on this I wrote a 3D sliding collision routine for non rotated static boxes, that works great for jump and runs.

If anyone is interested, I will share the updated Routine too.
#297
Tested it more and it seems that it dosen´t like Floating Point movement values somehow...

When
Code (glbasic) Select
mx = mx + 3 -rnd(2)
no Problems at all.
But with
Code (glbasic) Select
mx = mx + 3 - rnd(20) * 0.1
I get random passthroughs through the walls.
#298
still won´t work when used in the 3D Environment with different updated coordinates through timer based movement. :(


#299
A modified Version that seems to work
if the coordinates are always positive.

Code (glbasic) Select

CONSTANT maxBox = 5

TYPE coord
x AS float
y AS float
z AS float
ENDTYPE


TYPE cBox
xl AS float // smaller
xr AS float // greater
yd AS float // lower
yu AS float // higher
zf AS float // more near
zb AS float // more far
frict AS float
exist AS int
ENDTYPE

GLOBAL box[] AS cBox

drawSimulation()

FUNCTION drawSimulation:
LOCAL mx# AS float , my# AS float
LOCAL l1S AS coord , l1E AS coord , get AS coord
DIM box[10]
FOR i = 0 TO maxBox - 2 // fill Boxes ( 2D only for simulation )
box[i].xl = 50 * i
box[i].xr = 50 + 50 * i
box[i].yd = -50
box[i].yu = 50
box[i].zf = 50
box[i].zb = 125
box[i].exist = 1
sortCube( i )
NEXT
box[4].xl = 125
box[4].xr = 175
box[4].yd = -50
box[4].yu = 50
box[4].zf = 125
box[4].zb = 175
box[4].exist = 1
X_MAKE2D
WHILE TRUE
FOR i = 0 TO maxBox - 1
DrawCube(i)
NEXT
l1S.x = mx ; l1S.z = my
IF KEY(203 ) THEN mx = mx -3 + (RND(20)*0.1)
IF KEY(205 ) THEN mx = mx +3 - (RND(20)*0.1)
IF KEY(200 ) THEN my = my -3 + (RND(20)*0.1)
IF KEY(208 ) THEN my = my +3 - (RND(20)*0.1)
l1E.x = mx ; l1E.z = my
l1E.y = 0 ; l1S.y = 0
DRAWLINE l1S.x , l1S.z , l1E.x , l1E.z , RGB( 122 , 122 , 122 )
get = checkinters( l1S , l1E )
IF get.x > -1 AND get.z > -1
mx = get.x
my = get.z
ENDIF
SHOWSCREEN
WEND
ENDFUNCTION

FUNCTION checkinters AS coord: l1S AS coord , l1E AS coord
LOCAL cPnt AS coord , temp AS coord , tempE AS coord , cpNear AS coord , smDist# AS float , iSm AS int , l1EO AS coord , l1SO AS coord
l1SO = l1S
l1EO = l1E
FOR iG = 0 TO 1
FOR i = 0 TO maxBox - 1
iSm = -1 ; smDist = 500000.0
IF box[i].exist = 1
FOR i2 = 0 TO 3
IF i2 = 0
temp.x = box[i].xl ; temp.z = box[i].zf ; tempE.x = box[i].xr ; tempE.z = box[i].zf // face along zfront ( 0 )
ENDIF
IF i2 = 1
temp.x = box[i].xl ; temp.z = box[i].zf ; tempE.x = box[i].xl ; tempE.z = box[i].zb // face along xl ( 1 )
ENDIF
IF i2 = 2
temp.x = box[i].xr ; temp.z = box[i].zb ; tempE.x = box[i].xl ; tempE.z = box[i].zb // face along zb ( 2 )
ENDIF
IF i2 = 3
temp.x = box[i].xr ; temp.z = box[i].zb ; tempE.x = box[i].xr ; tempE.z = box[i].zf // face along xr ( 3 )
ENDIF
cPnt = intersection( l1S , l1E , temp , tempE )
IF cPnt.x > -1
IF ( ( cPnt.x - l1SO.x ) * ( cPnt.x - l1SO.x ) + ( cPnt.z - l1SO.z ) * ( cPnt.z - l1SO.z ) ) < smDist
// also check if cut point is not between two near faces of different boxes
IF pointbetweenFaces( cPnt , i2 , i ) = 0
smDist = ( ( cPnt.x - l1S.x ) * ( cPnt.x - l1S.x ) + ( cPnt.z - l1S.z ) * ( cPnt.z - l1S.z ) ) ; cpNear = cPnt ; iSm = i2
ENDIF
ENDIF
ENDIF
NEXT
IF iSm = 0 THEN l1E.z = cpNear.z - 1.0
IF iSm = 2 THEN l1E.z = cpNear.z + 1.0
IF iSm = 1 THEN l1E.x = cpNear.x - 1.0
IF iSm = 3 THEN l1E.x = cpNear.x + 1.0
ENDIF
NEXT
NEXT
RETURN l1E
ENDFUNCTION

FUNCTION pointbetweenFaces: point AS coord , side AS int , boxCh AS int
LOCAL fChS AS coord , fChE AS coord , fTChS AS coord , fTChE AS coord
IF side = 0
fTChS.z = box[boxCh].zf
ENDIF
IF side = 1
fTChS.x = box[boxCh].xl
ENDIF
IF side = 2
fTChS.z = box[boxCh].zb
ENDIF
IF side = 3
fTChS.x = box[boxCh].xr
ENDIF
fTChS.y = box[boxCh].yd ; fTChE.y = box[boxCh].yu
FOR i = 0 TO maxBox - 1
IF i <> boxCh AND box[i].exist = 1
IF side = 0 // get opposite face of another object to the checked faces direction
fChS.x = box[i].xl ; fChS.y = box[i].yd ; fChS.z = box[i].zb
fChE.x = box[i].xr ; fChE.y = box[i].yu ; fChE.z = box[i].zb
ENDIF
IF side = 1
fChS.x = box[i].xr ; fChS.y = box[i].yd ; fChS.z = box[i].zf
fChE.x = box[i].xr ; fChE.y = box[i].yu ; fChE.z = box[i].zb
ENDIF
IF side = 2
fChS.x = box[i].xl ; fChS.y = box[i].yd ; fChS.z = box[i].zf
fChE.x = box[i].xr ; fChE.y = box[i].yu ; fChE.z = box[i].zf
ENDIF
IF side = 3
fChS.x = box[i].xl ; fChS.y = box[i].yd ; fChS.z = box[i].zf
fChE.x = box[i].xl ; fChE.y = box[i].yu ; fChE.z = box[i].zb
ENDIF
IF side = 0 OR side = 2
IF ABS( fChS.z - fTChS.z ) <= 1.0
IF point.x > fChS.x AND point.x < fChE.x AND point.y > fChS.y AND point.y < fChE.y
RETURN 1
ENDIF
ENDIF
ENDIF
IF side = 1 OR side = 3
IF ABS( fChS.x - fTChS.x ) <= 1.0
IF point.z > fChS.z AND point.z < fChE.z AND point.y > fChS.y AND point.y < fChE.y
RETURN 1
ENDIF
ENDIF
ENDIF
ENDIF
NEXT
RETURN 0
ENDFUNCTION


FUNCTION intersection AS coord: l1S AS coord , l1E AS coord , l2S AS coord , l2E AS coord
LOCAL x1 AS float , y1 AS float , x2 AS float , y2 AS float , x3 AS float , y3 AS float , x4 AS float , y4 AS float  , d AS float , pre AS float
LOCAL post AS float , x AS float , y AS float
LOCAL fail AS coord , ret AS coord
fail.x = -1 ; fail.z = -1 ; fail.y = -1 // assumes that coordinates are always positive values!
x1 = l1S.x ; x2 = l1E.x ; x3 = l2S.x ; x4 = l2E.x
y1 = l1S.z ; y2 = l1E.z ; y3 = l2S.z ; y4 = l2E.z
d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
IF d = 0 THEN RETURN fail
pre = (x1*y2 - y1*x2) ; post = (x3*y4 - y3*x4)
x = ( pre * (x3 - x4) - (x1 - x2) * post ) / d
y = ( pre * (y3 - y4) - (y1 - y2) * post ) / d
IF ( x < MIN(x1, x2) OR x > MAX(x1, x2) OR x < MIN(x3, x4) OR x > MAX(x3, x4) ) THEN RETURN fail
IF ( y < MIN(y1, y2) OR y > MAX(y1, y2) OR y < MIN(y3, y4) OR y > MAX(y3, y4) ) THEN RETURN fail
ret.x = x ; ret.z = y
RETURN ret
ENDFUNCTION

FUNCTION sortCube: i AS int
IF box[i].xl > box[i].xr THEN SWAP box[i].xl , box[i].xr
IF box[i].zf > box[i].zb THEN SWAP box[i].zf , box[i].zb
IF box[i].yd > box[i].yu THEN SWAP box[i].yd , box[i].yu
ENDFUNCTION

FUNCTION DrawCube: i AS int
DRAWLINE box[i].xl , box[i].zf , box[i].xr , box[i].zf , RGB( 122 , 255 , 55 + i * 20 )
DRAWLINE box[i].xl , box[i].zf , box[i].xl , box[i].zb , RGB( 122 , 255 , 55 + i * 20 )
DRAWLINE box[i].xr , box[i].zb , box[i].xl , box[i].zb , RGB( 122 , 255 , 55 + i * 20 )
DRAWLINE box[i].xr , box[i].zb , box[i].xr , box[i].zf , RGB( 122 , 255 , 55 + i * 20 )
ENDFUNCTION


Added the Response handling in the Simulation for better testing.
#300
Hello,

I am currently writing an algorythm for sliding non tile based collision for unrotated rectangles.

Here is my testing code:

Code (glbasic) Select

CONSTANT maxBox = 5

TYPE coord
x AS float
y AS float
z AS float
ENDTYPE


TYPE cBox
xl AS int // smaller
xr AS int // greater
yd AS int // lower
yu AS int // higher
zf AS int // more near
zb AS int // more far
frict AS float
exist AS int
ENDTYPE

GLOBAL box[] AS cBox

drawSimulation()

FUNCTION drawSimulation:
LOCAL mx% , my% , b1% , b2%
LOCAL l1S AS coord , l1E AS coord , get AS coord
DIM box[10]
FOR i = 0 TO maxBox - 2 // fill Boxes ( 2D only for simulation )
box[i].xl = 50 * i
box[i].xr = 50 + 50 * i
box[i].yd = -50
box[i].yu = 50
box[i].zf = 50
box[i].zb = 125
box[i].exist = 1
sortCube( i )
NEXT
box[4].xl = 125
box[4].xr = 175
box[4].yd = -50
box[4].yu = 50
box[4].zf = 125
box[4].zb = 175
box[4].exist = 1
X_MAKE2D
WHILE TRUE
FOR i = 0 TO maxBox - 1
DrawCube(i)
NEXT
MOUSESTATE mx , my , b1 , b2
l1S.x = mx ; l1S.z = my
l1E.x = mx - 10 ; l1E.z = my - 10
l1E.y = 0 ; l1S.y = 0
DRAWLINE l1S.x , l1S.z , l1E.x , l1E.z , RGB( 122 , 122 , 122 )
get = checkinters( l1S , l1E )
SHOWSCREEN
WEND
ENDFUNCTION

FUNCTION checkinters AS coord: l1S AS coord , l1E AS coord
LOCAL cPnt AS coord , temp AS coord , tempE AS coord , cpNear AS coord , smDist# AS float , iSm AS int , l1EO AS coord , l1SO AS coord
l1SO = l1S
l1EO = l1E
FOR iG = 0 TO 1 // goes through two times, to make shure that all collisions apply correctly after the collision vector has been altered
FOR i = 0 TO maxBox - 1
iSm = -1 ; smDist = 50000.0
l1S = l1SO
IF box[i].exist = 1
FOR i2 = 0 TO 3
IF i2 = 0
temp.x = box[i].xl ; temp.z = box[i].zf ; tempE.x = box[i].xr ; tempE.z = box[i].zf // face along zfront ( 0 )
ENDIF
IF i2 = 1
temp.x = box[i].xl ; temp.z = box[i].zf ; tempE.x = box[i].xl ; tempE.z = box[i].zb // face along xl ( 1 )
ENDIF
IF i2 = 2
temp.x = box[i].xr ; temp.z = box[i].zb ; tempE.x = box[i].xl ; tempE.z = box[i].zb // face along zb ( 2 )
ENDIF
IF i2 = 3
temp.x = box[i].xr ; temp.z = box[i].zb ; tempE.x = box[i].xr ; tempE.z = box[i].zf // face along xr ( 3 )
ENDIF
cPnt = intersection( l1S , l1E , temp , tempE )
IF cPnt.x > -1
IF SQR( ( cPnt.x - l1SO.x ) * ( cPnt.x - l1SO.x ) + ( cPnt.z - l1SO.z ) * ( cPnt.z - l1SO.z ) ) < smDist
// also check if cut point is not between two near faces of different boxes
IF pointbetweenFaces( cPnt , i2 , i ) = 0
smDist = SQR( ( cPnt.x - l1SO.x ) * ( cPnt.x - l1SO.x ) + ( cPnt.z - l1SO.z ) * ( cPnt.z - l1SO.z ) ) ; cpNear = cPnt ; iSm = i2
ENDIF
ENDIF
ENDIF
NEXT
IF iSm = 0 OR iSm = 2 // here transformation of movement has to be calculated and applyed for line inters checking with the next rectangle ( by using the collision point with the smallest distance TO players old position )
l1E.z = cpNear.z // block z ( sides 0 and 2 )
ENDIF
IF iSm = 1 OR iSm = 3
l1E.x = cpNear.x // block x ( sides 1 and 3 )
ENDIF
ENDIF
NEXT
NEXT
DRAWLINE l1S.x , l1S.z , l1E.x , l1E.z , RGB(255 , 0 , 0 )
l1E.x = l1E.x - l1EO.x
l1E.z = l1E.z - l1EO.z
RETURN l1E
ENDFUNCTION

FUNCTION pointbetweenFaces: point AS coord , side AS int , boxCh // checks if the point is in a space which adjacts with another cubes face.
LOCAL fChS AS coord , fChE AS coord , fTChS AS coord , fTChE AS coord
IF side = 0
fTChS.z = box[boxCh].zf
ENDIF
IF side = 1
fTChS.x = box[boxCh].xl
ENDIF
IF side = 2
fTChS.z = box[boxCh].zb
ENDIF
IF side = 3
fTChS.x = box[boxCh].xr
ENDIF
FOR i = 0 TO maxBox - 1
IF i <> boxCh AND box[i].exist = 1
IF side = 0 // get opposite face of another object to the checked faces direction
fChS.x = box[i].xl ; fChS.y = box[i].yd ; fChS.z = box[i].zb
fChE.x = box[i].xr ; fChE.y = box[i].yu ; fChE.z = box[i].zb
IF ABS( fChS.z - fTChS.z ) <= 25
IF point.x > fChS.x AND point.x < fChE.x AND point.y >= fChS.y AND point.y <= fChE.y
RETURN 1
ENDIF
ENDIF
ENDIF
IF side = 1
fChS.x = box[i].xr ; fChS.y = box[i].yd ; fChS.z = box[i].zf
fChE.x = box[i].xr ; fChE.y = box[i].yu ; fChE.z = box[i].zb
IF ABS( fChS.x - fTChS.x ) <= 25
IF point.z > fChS.z AND point.z < fChE.z AND point.y >= fChS.y AND point.y <= fChE.y
RETURN 1
ENDIF
ENDIF
ENDIF
IF side = 2
fChS.x = box[i].xl ; fChS.y = box[i].yd ; fChS.z = box[i].zf
fChE.x = box[i].xr ; fChE.y = box[i].yu ; fChE.z = box[i].zf
IF ABS( fChS.z - fTChS.z ) <= 25
IF point.x > fChS.x AND point.x < fChE.x AND point.y >= fChS.y AND point.y <= fChE.y
RETURN 1
ENDIF
ENDIF
ENDIF
IF side = 3
fChS.x = box[i].xl ; fChS.y = box[i].yd ; fChS.z = box[i].zf
fChE.x = box[i].xl ; fChE.y = box[i].yu ; fChE.z = box[i].zb
IF ABS( fChS.x - fTChS.x ) <= 25
IF point.z > fChS.z AND point.z < fChE.z AND point.y >= fChS.y AND point.y <= fChE.y
RETURN 1
ENDIF
ENDIF
ENDIF
ENDIF
NEXT
RETURN 0
ENDFUNCTION


FUNCTION intersection AS coord: l1S AS coord , l1E AS coord , l2S AS coord , l2E AS coord // standart line line intersection point function
LOCAL x1 AS float , y1 AS float , x2 AS float , y2 AS float , x3 AS float , y3 AS float , x4 AS float , y4 AS float  , d AS float , pre AS float
LOCAL post AS float , x AS float , y AS float
LOCAL fail AS coord , ret AS coord
fail.x = -1 ; fail.z = -1 ; fail.y = -1 // assumes that coordinates are always positive values!
x1 = l1S.x ; x2 = l1E.x ; x3 = l2S.x ; x4 = l2E.x
y1 = l1S.z ; y2 = l1E.z ; y3 = l2S.z ; y4 = l2E.z // I will use z for y in the later game, y collision is a whole other story.
d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4)
IF d = 0 THEN RETURN fail
pre = (x1*y2 - y1*x2) ; post = (x3*y4 - y3*x4)
x = ( pre * (x3 - x4) - (x1 - x2) * post ) / d
y = ( pre * (y3 - y4) - (y1 - y2) * post ) / d
IF ( x < MIN(x1, x2) OR x > MAX(x1, x2) OR x < MIN(x3, x4) OR x > MAX(x3, x4) ) THEN RETURN fail
IF ( y < MIN(y1, y2) OR y > MAX(y1, y2) OR y < MIN(y3, y4) OR y > MAX(y3, y4) ) THEN RETURN fail
ret.x = x ; ret.z = y
RETURN ret
ENDFUNCTION

FUNCTION sortCube: i AS int
IF box[i].xl > box[i].xr THEN SWAP box[i].xl , box[i].xr
IF box[i].zf > box[i].zb THEN SWAP box[i].zf , box[i].zb
IF box[i].yd > box[i].yu THEN SWAP box[i].yd , box[i].yu
ENDFUNCTION

FUNCTION DrawCube: i AS int
DRAWLINE box[i].xl , box[i].zf , box[i].xr , box[i].zf , RGB( 122 , 255 , 55 + i * 20 )
DRAWLINE box[i].xl , box[i].zf , box[i].xl , box[i].zb , RGB( 122 , 255 , 55 + i * 20 )
DRAWLINE box[i].xr , box[i].zb , box[i].xl , box[i].zb , RGB( 122 , 255 , 55 + i * 20 )
DRAWLINE box[i].xr , box[i].zb , box[i].xr , box[i].zf , RGB( 122 , 255 , 55 + i * 20 )
ENDFUNCTION


My Problem is, that this won´t work when the vector starts inside or at the very edge of the cube.
So the Player will run through walls sometimes.