snes mode 7 effect ( mario kart ) by Cliff Mellangard 3DEGS20th 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. 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# |