TGC Codebase Backup



snes mode 7 effect ( mario kart ) by Cliff Mellangard 3DEGS

20th Nov 2011 18:18
Summary

I made this for my raycaster engine and it works almost the same as mode 7 on snes.



Description

You nead an 64x64 texture for the ground.
1 image for the car.
1 image for the background.
i used an 640x480 resolution.



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    remstart
////////////////////////////////////////////////////////////////////////////////
// Fake Snes Mode 7 engine for AGK //////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/////// Open source ////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
      By
Cliff Mellangård
    Sweden

   Forum id
Cliff Mellangard 3DEGS
////////////////////////////////////////////////////////////////////////////////
Link to usefull sites. /////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
http://www.permadi.com/tutorial/raycast/index.html

http://dev.opera.com/articles/view/creating-pseudo-3d-games-with-html-5-can-1/

http://web.archive.org/web/20070101034811/http://student.kuleuven.be/~m0216922/CG/raycasting.html
////////////////////////////////////////////////////////////////////////////////
remend

SetSyncRate ( 0, 1 )
SetVirtualResolution ( 320, 240 )

   global IMG_Floor
   IMG_Floor = LoadImage ( "grass.png" )
   global IMG_Kart
   IMG_Kart = LoadImage ( "kart.png" )
   global IMG_Back
   IMG_Back = LoadImage ( "back.png" )
   // Number of rays we use
   #Constant FloornumRays 64.0
   // 60 is the field of view
   #Constant FloorRayspeed 0.9375
   #Constant Max_Floor 4000
   #Constant _FloorSize 5
   #Constant _FloorHeight 1
   #constant WorldScale 64

   type sFloor
      FL_Y as integer
   endtype

   global dim Floor_ [FloornumRays] as sFloor

   global dim _floor [Max_Floor]
   global Floor_count=0
   for t = 0 to Max_Floor
       if t = 0
          id = CreateSprite ( IMG_Floor )
          SetSpriteSize ( id , _FloorSize , _FloorHeight )
          SetSpriteUVBorder( id, 1 )
          SetSpriteAnimation ( id , 1 , 1 , 64*64 )
          SetSpritePosition ( id , -1000 , -1000 )
          SetSpriteTransparency( id , 0 )
          setspritedepth( id , 10000)
       else
          id = clonesprite( _floor[0] )
       endif
       _floor[ t ] = id
   next t

   id = CreateSprite ( IMG_Kart )
   SetSpriteSize ( id , 80 , 80 )
   SetSpritePositionByoffset ( id , 160 , 210 )

   id = CreateSprite ( IMG_Back )
   SetSpriteSize ( id , 320 , 240 )
   SetSpritePositionByoffset ( id , 160 , 120 )
   setspritedepth( id , 10000)
/////////////////////////////////////////
// Create our player ////////////////////
////////////////////////////////////////
type sPlayer
	ID as integer
    x as float
    y as float
    dir as integer
    rot as float
    speed as integer
    moveSpeed as float
    rotSpeed as float
endtype

global Player as sPlayer
// current x, y position of the player
Player.x = 160 : Player.y = 120
// the direction that the player is turning, either -1 for left or 1 for right.
Player.dir = 0
// the current angle of rotation
Player.rot = 0
// is the playing moving forward (speed = 1) or backwards (speed = -1).
Player.speed = 0
// how far (in map units) does the player move each step/update( its this number * frame time )
Player.moveSpeed = 4.0
// old ////// ( Number math.PI ) how much does the player rotate each step/update (in radians)
Player.rotSpeed = 120.0


global Draw_Priority
global GFT#

do
   GFT# = GetFrameTime()
   Check_keys ()
   Move_Player ()

   select ( Draw_Priority )

         case 0:
            RENDER_Ground(2,1,0.06,160)
         endcase

    endselect
    inc Draw_Priority
    if Draw_Priority>1 then Draw_Priority=0
print(str(screenfps()))
 Sync()
loop

function Check_keys ()

    if GetDirectionY()>0 then Player.speed=-1
    if GetDirectionY()<0 then Player.speed=1
    if GetDirectionY()=0 then Player.speed=0
    Player.dir = GetDirectionX()

endfunction

function Move_Player ()
    // player will move this far along the current direction vector
    moveStep# = player.speed * (player.moveSpeed*GFT#)
    // add rotation if player is rotating (player.dir != 0)
    player.rot = player.rot+(player.dir * (player.rotSpeed*GFT#))
    // calculate new player position with simple trigonometry
    newX# = player.x + (cos(player.rot) * moveStep#)
    newY# = player.y + (Sin(player.rot) * moveStep#)
    // Basic wall collision
    newX=newX#
    newY=newY#
    //if map [newX,newY]>0 then ExitFunction
    // set new position

    player.x = newX#
    player.y = newY#


endfunction

function RENDER_Ground( LowRes , MinPixel , Floor_Step# , View_Depth)

    OriginX# = player.x*WorldScale
    OriginY# = player.y*WorldScale
    LeftAngle# = player.rot - 30.1
    RightAngle# = player.rot + 30.1
    move# = 1.49
    skipNext=0
    FloorY = 0
    FloorX=0
    Floor_count = 0

    for t=0 to View_Depth
        if Floor_count=>Max_Floor then exit
        StartAngle# = player.rot - 30
        rayspd#=0.0
        if skipNext=0
        LeftX# = player.x + ( cos(LeftAngle#) * move#)
        LeftY# = player.y + ( sin(LeftAngle#) * move#)
        RightX# = player.x + ( cos(RightAngle#) * move#)
        RightY# = player.y + ( sin(RightAngle#) * move#)
        DotX#=LeftX#
        DotY#=LeftY#
        tx#=LeftX#-RightX#
        ty#=LeftY#-RightY#
        DotSpeed#=(sqrt ( ( tx# * tx# ) + ( ty# * ty# ) ))/FloornumRays
        DotAng#=atanfull(RightX#-LeftX#,RightY#-LeftY#)-90
        DotMove#=0.0
        for i = 1 to FloornumRays
            if Floor_count=>Max_Floor then exit
            if Floor_count<Max_Floor
               X# = DotX# + ( cos(DotAng#) * DotMove#)
               Y# = DotY# + ( sin(DotAng#) * DotMove#)
               dist=( (WorldScale / ( Distance ( OriginX# , OriginY# , X#*WorldScale , Y#*WorldScale ) *cos( 30-rayspd# )))*300 )
               FloorY = 120+((dist/2))

               StoreFloorY=FloorY

               ///////////////////////////////////////////////////
               // This stretches the sprites to cover any gapps //
               ///////////////////////////////////////////////////
               temp = Floor_ [i].FL_Y - FloorY
               Fade=dist-20
               if Fade<1 then Fade=1
               if Fade>255 then Fade=255
               Initiate_Floor_Pixel( _floor [Floor_count] , temp , X# , Y# ,FloorX , FloorY , 64 , 10031-dist , Fade ,255 )
               inc FloorX,_FloorSize
            endif
            DotMove#=DotMove#+DotSpeed#
            rayspd# = rayspd# + FloorRayspeed
            Floor_ [i].FL_Y = FloorY

         next i
         endif
         FloorX=0
         move# = move#+Floor_Step#
         inc skipNext
         if skipNext => LowRes then skipNext=0
    next t



endfunction




function Initiate_Floor_Pixel( id , Size ,x#,y#, X , Y , Texture ,depth , fade , alpha )
    SetSpriteSize ( id , _FloorSize , _FloorHeight + Size )
    setspriteposition( id , X , Y )
    setspriteframe( id , Get_Pixel(x#*Texture,y#*Texture,Texture))
    setspritedepth( id , depth )
    SetSpriteColor ( id , fade , fade , 255 , alpha )
    inc Floor_count
endfunction
/////////////////////////////////
// used to get pixel on ground //
/////////////////////////////////
function Get_Pixel( x as integer , y as integer , Scale as integer )
    // converts it to an grid grid nr
    X1 = (x+1) / (Scale)
    Y1 = (y+1) / (Scale)
    // converts it to an world position
    X2 = ( X1 * ( Scale ) )// - ( Scale / 2 )
    Y2 = ( Y1 * ( Scale ) )// - ( Scale / 2 )
    // here do we get an pixel cord inside that tile
    X3 =  ( x - X2 ) //- ( Scale / 2 ) )
    Y3 =  ( y - Y2 ) //- ( Scale / 2 ) )
    // Calculate it to an sprite frame
    if X3 < Y3 then result = ( X3 + ( Y3 * ( Scale + 1 ) ) ) - ( Scale + 1 )
    if X3 > Y3 then result = ( Y3 + ( X3 * ( Scale + 1 ) ) ) - ( Scale + 1 )
ENDFUNCTION result

function Distance (x#,y#,x2#,y2#)
    distX# = x# - x2#
    distY# = y# - y2#
    dist# = sqrt ( ( distX# * distX# ) + ( distY# * distY# ) )
endfunction dist#