FreeBASIC SDL图形功能
SDL - Simple DirectMedia Layer 是完整的跨平台系统,有自己的窗口、直接捕获键盘、鼠标和游戏操纵杆的事件,直接操作音频和CDROM,在其surface上可使用gfx, openGL和direct3D绘图。Window3.0时代,各种应用程序在Pharlap、DJPP、4GW支持下均突破了常规内存进入了保护模式,因此那个时期是SDL突破性发展的时机,非常多的游戏程序用SDL做支撑(gtk/iup/libui有的功能sdl没有,而sdl有的能力其它的则没有),是开发游戏和工厂流程化应用绘图的优秀工具。C#, Lua, Rust, hollywood, beaflang, Ocamel, Python, 等众多语言有它的封装, Github上的最新稳定版是 2.30.1 , 三天前还在更新。
Github上各平台使用的SDL
游戏:wildfire 野火
DOSBOX: DOS simulator
Humble Bundle 各种游戏
valve 众多游戏
FreeBASIC 完美支持 SDL, 需要安装如下 .so 库文件(SDL, SDL2 二个版本)
#freebasic SDL
sudo apt install libsdl2-dev
sudo apt install libsdl2-ttf-dev
sudo apt install libsdl2-net-dev
sudo apt install libsdl2-mixer-dev
sudo apt install libsdl2-image-dev
sudo apt install libsdl2-gfx-dev
sudo apt install libsdl1.2-dev
sudo apt install libsdl-console-dev
sudo apt install libsdl-mixer1.2-dev
sudo apt install libsdl-gfx1.2-dev
sudo apt install libsdl-net1.2-dev
sudo apt install libsdl-pango-dev
sudo apt install libsdl-sge-dev
sudo apt install libsdl-sound1.2-dev
示例一:放三个图文件:free.jpg, basic.gif, horse.tga
SDL库可读取的的图形文件种类繁多,此示例是在原示例基础上修改的,读取 gif, tga, jpg三种格式的文件。程序首选获取SDL的版本号,初始化 sdl, 作为三个sdl surface装入图形文件并返回图形指针,然后在不同位置放置它们,最后flip显示它们。
' SDL_image example written by Edmond Leung (leung.edmond@gmail.com)
'
' free.jpg, basic.gif and horse.tga are taken from the official freeBasic
' website.#include "SDL\SDL.bi"
#include "SDL\SDL_image.bi"declare sub blitImage _(byval img as SDL_Surface ptr, byval x as integer, byval y as integer)dim shared video as SDL_Surface ptrdim freeImg as SDL_Surface ptr, basicImg as SDL_Surface ptr, horseImg as SDL_Surface ptrdim version as const SDL_version ptrversion = IMG_Linked_Version()' display the version number of the SDL_image being usedprint "Using SDL_image version number: "; SDL_VERSIONNUM(version->major, _version->minor, version->patch)' initialise sdl with video supportif (SDL_Init(SDL_INIT_VIDEO) < 0) thenprint "Couldn't initialise SDL: "; *SDL_GetError()end if' check to see if the images are in the correct formatsif (IMG_isJPG(SDL_RWFromFile("data/free.jpg", "rb")) = 0) thenprint "The image (free.jpg) is not a jpg file."end ifif (IMG_isGIF(SDL_RWFromFile("data/basic.gif", "rb")) = 0) thenprint "The image (basic.gif) is not a gif file."end if' set the video mode to 1024x768x32bppvideo = SDL_SetVideoMode(1024, 768, 32, SDL_HWSURFACE or SDL_DOUBLEBUF)if (video = NULL) thenprint "Couldn't set video mode: "; *SDL_GetError()end if' load the images into an SDL_RWops structuredim freeRw as SDL_RWops ptr, basicRw as SDL_RWops ptrfreeRw = SDL_RWFromFile("data/free.jpg", "rb")basicRw = SDL_RWFromFile("data/basic.gif", "rb")' load the images onto an SDL_Surface using three different functions available' in the SDL_image libraryfreeImg = IMG_LoadJPG_RW(freeRw)horseImg = IMG_Load("data/horse.tga")basicImg = IMG_LoadTyped_RW(basicRw, 1, "gif")dim done as integerdone = 0do while (done = 0)dim event as SDL_Eventdo while (SDL_PollEvent(@event))if (event.type = SDL_QUIT_) then done = 1if (event.type = SDL_KEYDOWN) thenif (event.key.keysym.sym = SDLK_ESCAPE) then done = 1 end ifloopdim destrect as SDL_Rectdestrect.w = video->wdestrect.h = video->h' clear the screen with the colour whiteSDL_FillRect(video, @destrect, SDL_MapRGB(video->format, 255, 255, 255))' draw the images onto the screenblitImage freeImg, 170, 205blitImage horseImg, 345, 330 blitImage freeImg, 445, 335 blitImage basicImg, 450, 360 blitImage freeImg, 650, 215 blitImage basicImg, 650, 240 blitImage freeImg, 150, 455 blitImage basicImg, 150, 480 SDL_Flip(video)loopSDL_Quit' sub-routine used to help with blitting the images onto the screen
sub blitImage _(byval img as SDL_Surface ptr, byval x as integer, byval y as integer)dim dest as SDL_Rectdest.x = xdest.y = ySDL_BlitSurface(img, NULL, video, @dest)
end sub
示例二:对网络的支持,访问百度站点并取得首页面前部分内容(对于现代编程,这好像是非常基本的能力)。
''
'' simple http get example using the SDL_net library
''#include once "SDL/SDL_net.bi"const RECVBUFFLEN = 8192
const NEWLINE = !"\r\n"
'const DEFAULT_HOST = "www.freebasic.net"
const DEFAULT_HOST = "www.baidu.com"declare sub gethostandpath( byref src as string, byref hostname as string, byref path as string )'' globalsdim hostname as stringdim path as stringgethostandpath command, hostname, pathif( len( hostname ) = 0 ) thenhostname = DEFAULT_HOSTend if'' initif( SDLNet_Init <> 0 ) thenprint "Error: SDLNet_Init failed"end 1end if'' resolvedim ip as IPAddressdim socket as TCPSocketif( SDLNet_ResolveHost( @ip, hostname, 80 ) <> 0 ) thenprint "Error: SDLNet_ResolveHost failed"end 1end if'' opensocket = SDLNet_TCP_Open( @ip )if( socket = 0 ) thenprint "Error: SDLNet_TCP_Open failed"end 1end if'' send HTTP requestdim sendbuffer as stringsendBuffer = "GET /" + path + " HTTP/1.0" + NEWLINE + _"Host: " + hostname + NEWLINE + _"Connection: close" + NEWLINE + _"User-Agent: GetHTTP 0.0" + NEWLINE + _NEWLINEif( SDLNet_TCP_Send( socket, strptr( sendbuffer ), len( sendbuffer ) ) < len( sendbuffer ) ) thenprint "Error: SDLNet_TCP_Send failed"end 1end if'' receive til connection is closeddim recvbuffer as zstring * RECVBUFFLEN+1dim bytes as integerdo bytes = SDLNet_TCP_Recv( socket, strptr( recvbuffer ), RECVBUFFLEN )if( bytes <= 0 ) thenexit doend if'' add the null-terminatorrecvbuffer[bytes] = 0'' print it as stringprint recvbuffer;loopprint'' close socketSDLNet_TCP_Close( socket )'' quitSDLNet_Quit'':::::
sub gethostandpath( byref src as string, byref hostname as string, byref path as string )dim p as integerp = instr( src, " " )if( p = 0 or p = len( src ) ) thenhostname = trim( src )path = ""elsehostname = trim( left( src, p-1 ) )path = trim( mid( src, p+1 ) )end ifend sub
示例三:SDL 对 gfx 的支持。画任意线条,非常经典的dos年代的一款demo
''
'' simple http get example using the SDL_net library
''#include once "SDL/SDL_net.bi"const RECVBUFFLEN = 8192
const NEWLINE = !"\r\n"
'const DEFAULT_HOST = "www.freebasic.net"
const DEFAULT_HOST = "www.baidu.com"declare sub gethostandpath( byref src as string, byref hostname as string, byref path as string )'' globalsdim hostname as stringdim path as stringgethostandpath command, hostname, pathif( len( hostname ) = 0 ) thenhostname = DEFAULT_HOSTend if'' initif( SDLNet_Init <> 0 ) thenprint "Error: SDLNet_Init failed"end 1end if'' resolvedim ip as IPAddressdim socket as TCPSocketif( SDLNet_ResolveHost( @ip, hostname, 80 ) <> 0 ) thenprint "Error: SDLNet_ResolveHost failed"end 1end if'' opensocket = SDLNet_TCP_Open( @ip )if( socket = 0 ) thenprint "Error: SDLNet_TCP_Open failed"end 1end if'' send HTTP requestdim sendbuffer as stringsendBuffer = "GET /" + path + " HTTP/1.0" + NEWLINE + _"Host: " + hostname + NEWLINE + _"Connection: close" + NEWLINE + _"User-Agent: GetHTTP 0.0" + NEWLINE + _NEWLINEif( SDLNet_TCP_Send( socket, strptr( sendbuffer ), len( sendbuffer ) ) < len( sendbuffer ) ) thenprint "Error: SDLNet_TCP_Send failed"end 1end if'' receive til connection is closeddim recvbuffer as zstring * RECVBUFFLEN+1dim bytes as integerdo bytes = SDLNet_TCP_Recv( socket, strptr( recvbuffer ), RECVBUFFLEN )if( bytes <= 0 ) thenexit doend if'' add the null-terminatorrecvbuffer[bytes] = 0'' print it as stringprint recvbuffer;loopprint'' close socketSDLNet_TCP_Close( socket )'' quitSDLNet_Quit'':::::
sub gethostandpath( byref src as string, byref hostname as string, byref path as string )dim p as integerp = instr( src, " " )if( p = 0 or p = len( src ) ) thenhostname = trim( src )path = ""elsehostname = trim( left( src, p-1 ) )path = trim( mid( src, p+1 ) )end ifend sub
示例四:SDL 对open_GL的支持。简单的三角形, 颜色glColor3f 后面带3个float参数; glVertext3f, 顶点描述后面带3个float参数。
''
'' gltest.bas - freeBASIC opengl example, using GLUT for simplicity
'' by Blitz
''
'' Opengl code ported from nehe's gl tutorials
''#include once "GL/gl.bi"
#include once "GL/glu.bi"
#include once "GL/glut.bi"''
declare sub doMain ( )
declare sub doShutdown ( )'''' Entry point''doMain'' ::::::::::::
'' name: doRender
'' desc: Is called by glut to render scene
''
'' ::::::::::::
sub doRender cdeclstatic rtri as singlestatic rqud as singleglClear GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BITglPushMatrixglLoadIdentityglTranslatef -1.5, 0.0, -6.0glRotatef rtri, 0, 1, 0glBegin GL_TRIANGLESglColor3f 1.0, 0.0, 0.0 '' RedglVertex3f 0.0, 1.0, 0.0 '' Top Of Triangle Front)glColor3f 0.0, 1.0, 0.0 '' GreenglVertex3f -1.0,-1.0, 1.0 '' Left Of Triangle Front)glColor3f 0.0, 0.0, 1.0 '' BlueglVertex3f 1.0,-1.0, 1.0 '' Right Of Triangle Front)glColor3f 1.0, 0.0, 0.0 '' RedglVertex3f 0.0, 1.0, 0.0 '' Top Of Triangle Right)glColor3f 0.0, 0.0, 1.0 '' BlueglVertex3f 1.0,-1.0, 1.0 '' Left Of Triangle Right)glColor3f 0.0, 1.0, 0.0 '' GreenglVertex3f 1.0,-1.0,-1.0 '' Right Of Triangle Right)glColor3f 1.0, 0.0, 0.0 '' RedglVertex3f 0.0, 1.0, 0.0 '' Top Of Triangle Back)glColor3f 0.0, 1.0, 0.0 '' GreenglVertex3f 1.0,-1.0,-1.0 '' Left Of Triangle Back)glColor3f 0.0, 0.0, 1.0 '' BlueglVertex3f -1.0,-1.0,-1.0 '' Right Of Triangle Back)glColor3f 1.0, 0.0, 0.0 '' RedglVertex3f 0.0, 1.0, 0.0 '' Top Of Triangle Left)glColor3f 0.0, 0.0, 1.0 '' BlueglVertex3f -1.0,-1.0,-1.0 '' Left Of Triangle Left)glColor3f 0.0, 1.0, 0.0 '' GreenglVertex3f -1.0,-1.0, 1.0 '' Right Of Triangle Left)glEndglColor3f 0.5, 0.5, 1.0glLoadIdentity glTranslatef -1.5, 0.0, -6.0glTranslatef 3.0,0.0,0.0 glRotatef rqud, 1.0, 0.0, 0.0glBegin GL_QUADSglVertex3f -1.0, 1.0, 0.0glVertex3f 1.0, 1.0, 0.0glVertex3f 1.0,-1.0, 0.0glVertex3f -1.0,-1.0, 0.0glEnd glPopMatrix glutSwapBuffersrtri = rtri + 2.0rqud = rqud + 1.5end sub'' ::::::::::::
'' name: doInput
'' desc: Handles input
''
'' ::::::::::::
sub doInput CDECL ( byval kbcode as unsigned byte, _byval mousex as integer, _byval mousey as integer )if ( kbcode = 27 ) thendoShutdownend 0end ifend sub'' ::::::::::::
'' name: doInitGL
'' desc: Inits OpenGL
''
'' ::::::::::::
sub doInitGLdim i as integerdim lightAmb(3) as singledim lightDif(3) as singledim lightPos(3) as single'''' Rendering stuff''glShadeModel GL_SMOOTHglClearColor 0.0, 0.0, 0.0, 0.5glClearDepth 1.0glEnable GL_DEPTH_TESTglDepthFunc GL_LEQUALglEnable GL_COLOR_MATERIALglHint GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST'''' Light setup ( not used at the moment )''for i = 0 to 3lightAmb(i) = 0.5lightDif(i) = 1.0lightPos(i) = 0.0next ilightAmb(3) = 1.0lightPos(2) = 2.0lightPos(3) = 1.0 glLightfv GL_LIGHT1, GL_AMBIENT, @lightAmb(0)glLightfv GL_LIGHT1, GL_DIFFUSE, @lightDif(0)glLightfv GL_LIGHT1, GL_POSITION,@lightPos(0)glEnable GL_LIGHT1'''' Blending ( not used at the moment )''glColor4f 1.0, 1.0, 1.0, 0.5glBlendFunc GL_SRC_ALPHA, GL_ONEend sub'' ::::::::::::
'' name: doReshapeGL
'' desc: Reshapes GL window
''
'' ::::::::::::
sub doReshapeGL CDECL ( byval w as integer, _byval h as integer )glViewport 0, 0, w, h glMatrixMode GL_PROJECTIONglLoadIdentityif ( h = 0 ) thengluPerspective 80/2, w, 1.0, 5000.0 elsegluPerspective 80/2, w / h, 1.0, 5000.0end ifglMatrixMode GL_MODELVIEWglLoadIdentityend sub'':::::
sub initGLUT'''' Setup glut''glutInit 1, strptr( " " ) glutInitWindowPosition 0, 0glutInitWindowSize 640, 480glutInitDisplayMode GLUT_RGBA or GLUT_DOUBLE or GLUT_DEPTHglutCreateWindow "FreeBASIC OpenGL example"doInitGLglutDisplayFunc @doRenderglutIdleFunc @doRenderglutReshapeFunc CAST(Any PTR, @doReshapeGL)glutKeyboardFunc CAST(Any PTR, @doInput)end sub'':::::
sub doInit'''' Init GLUT''initGLUT end sub'':::::
sub shutdownGLUT'' GLUT shutdown will be done automatically by atexit()end sub'':::::
sub doShutdown'''' GLUT''shutdownGLUTend sub'' ::::::::::::
'' name: doMain
'' desc: Main routine
''
'' ::::::::::::
sub doMain'''' ''doInit''''''glutMainLoopend sub
SDL 对鼠标、键盘、joysticker的响应都比较好。以前研究鼠标鉴相时拆过几个滚球鼠标,通过串口可以读取字节形式的位置信息,游戏操纵杆还没拆过,有时间了拆解一个研究一下它的button和位置实现,估计和早期原理图有很多不同。SDL内容太多,先熟悉它的功能和应用领域,没有做更深入的学习,以后用的话还要多补补课。