⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gamedev_net - the simple directmedia layer from a win32 perspective, part 2 sdl video.htm

📁 游戏开发数据结构Data Structures for Game Programmers The Goodies Directory contains all sorts of stuff. For
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<B>#include &lt;stdlib.h&gt;
#include &lt;memory.h&gt;
</B>
enum {
  SCREENWIDTH = 512,
  SCREENHEIGHT = 384,
  SCREENBPP = 0,
  SCREENFLAGS = SDL_ANYFORMAT
} ;

<B>void SetPixel ( SDL_Surface* pSurface , int x , int y , SDL_Color color ) ;
SDL_Color GetPixel ( SDL_Surface* pSurface , int x , int y ) ;
</B>int main( int argc, char* argv[] )
{
  //initialize systems
  SDL_Init ( SDL_INIT_VIDEO ) ;

  //set our at exit function
  atexit ( SDL_Quit ) ;

  //create a window
  SDL_Surface* pSurface = SDL_SetVideoMode ( SCREENWIDTH , SCREENHEIGHT ,
                                             SCREENBPP , SCREENFLAGS ) ;

  //declare event variable
  SDL_Event event ;

  //message pump
  for ( ; ; )
  {
    //look for an event
    if ( SDL_PollEvent ( &amp;event ) )
    {
      //an event was found
      if ( event.type == SDL_QUIT ) break ;
    }

<B>    //pick a random color
    SDL_Color color ;
    color.r = rand ( ) % 256 ;
    color.g = rand ( ) % 256 ;
    color.b = rand ( ) % 256 ;

    //lock the surface
    SDL_LockSurface ( pSurface ) ;

    //plot pixel at random location
    SetPixel ( pSurface , rand ( ) % SCREENWIDTH , rand ( ) % SCREENHEIGHT , color ) ;

    //unlock surface
    SDL_UnlockSurface ( pSurface ) ;

    //update surface
    SDL_UpdateRect ( pSurface , 0 , 0 , 0 , 0 ) ;
</B>  }//end of message pump

  //done
  return ( 0 ) ;
}
<B>void SetPixel ( SDL_Surface* pSurface , int x , int y , SDL_Color color ) 
{
  //convert color
  Uint32 col = SDL_MapRGB ( pSurface-&gt;format , color.r , color.g , color.b ) ;

  //determine position
  char* pPosition = ( char* ) pSurface-&gt;pixels ;

  //offset by y
  pPosition += ( pSurface-&gt;pitch * y ) ;

  //offset by x
  pPosition += ( pSurface-&gt;format-&gt;BytesPerPixel * x ) ;

  //copy pixel data
  memcpy ( pPosition , &amp;col , pSurface-&gt;format-&gt;BytesPerPixel ) ;
}
SDL_Color GetPixel ( SDL_Surface* pSurface , int x , int y ) 
{
  SDL_Color color ;
  Uint32 col = 0 ;

  //determine position
  char* pPosition = ( char* ) pSurface-&gt;pixels ;

  //offset by y
  pPosition += ( pSurface-&gt;pitch * y ) ;

  //offset by x
  pPosition += ( pSurface-&gt;format-&gt;BytesPerPixel * x ) ;

  //copy pixel data
  memcpy ( &amp;col , pPosition , pSurface-&gt;format-&gt;BytesPerPixel ) ;

  //convert color
  SDL_GetRGB ( col , pSurface-&gt;format , &amp;color.r , &amp;color.g , &amp;color.b ) ;
  return ( color ) ;
}
</B></PRE></BLOCKQUOTE>
<P>Again, the code in bold is the code that has been added to the basic shell 
application. This example starts placing dots of random colors onto the window. 
When it runs, it looks somewhat like figure 2.</P>
<P class=maintext-2 align=center><IMG height=409 
src="GameDev_net - The Simple DirectMedia Layer from a WIN32 Perspective, Part 2 SDL Video_files/02-02.jpg" 
width=518> <BR><B>Figure 2: Random Pixels Demo</B></P>
<P>Once you can plot a pixel, you can do just about anything, including drawing 
lines, circles, rectangular frames, and so on. Doing all of that stuff is 
naturally beyond the scope of this article. I get you as far as plotting 
pixels.</P>
<H2>Blitting</H2>
<P>The primary use of SDL_Surfaces is not to fill rectangles nor to plot pixels. 
The main task is to copy rectangular sections from one surface to another, much 
like GDI's BitBlt function and DirectDraw's Blt or BltFast function. The 
function for doing that is SDL_BlitSurface.</P>
<BLOCKQUOTE><PRE class=code>int SDL_BlitSurface(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
</PRE></BLOCKQUOTE>
<P>This function takes four parameters, the source surface, a source rectangle, 
a destination surface, and a destination rectangle. It returns 0 if everything 
is OK, and -1 if there was a problem. If the pointers to either rectangle are 
NULL, then the entire surface is assumed to be the source or destination area. 
Naturally, you need two surfaces in order to perform a blit, although you can 
use the same for both source and destination, at least in theory. The 
documentation warns that you should not call SDL_BlitSurface on a surface that 
is locked. So, time (already) for another quick example: the Amazing Bouncing 
Ball Demo of Death(tm)!</P>
<P>Start yourself a new project, name it SDLBouncingBall or something just as 
clever, and place the following code into main.cpp. Also, make a small bitmap 
that is 32x32 pixels in size, draw a circle in it, and save it as ball.bmp.</P>
<BLOCKQUOTE><PRE class=code>#include "SDL.h"

enum {
  SCREENWIDTH = 512,
  SCREENHEIGHT = 384,
  SCREENBPP = 0,
  SCREENFLAGS = SDL_ANYFORMAT
} ;

int main( int argc, char* argv[] )
{
  //initialize systems
  SDL_Init ( SDL_INIT_VIDEO ) ;

  //set our at exit function
  atexit ( SDL_Quit ) ;

  //create a window
  SDL_Surface* pSurface = SDL_SetVideoMode ( SCREENWIDTH , SCREENHEIGHT ,
                                             SCREENBPP , SCREENFLAGS ) ;
<B>  //load bitmap
  SDL_Surface* pBitmap = SDL_LoadBMP ( "ball.bmp" ) ;

  //source and destination rectangles
  SDL_Rect rcSrc , rcDst ;
  rcSrc.w = pBitmap-&gt;w ;
  rcSrc.h = pBitmap-&gt;h ;
  rcSrc.x = 0 ;
  rcSrc.y = 0 ;
  rcDst = rcSrc ;

  //movement rate
  int dx = 2 , dy = 2 ;

</B>  //declare event variable
  SDL_Event event ;

  //message pump
  for ( ; ; )
  {
    //look for an event
    if ( SDL_PollEvent ( &amp;event ) )
    {
      //an event was found
      if ( event.type == SDL_QUIT ) break ;
    }
<B>    //clear the screen
    SDL_FillRect ( pSurface , NULL , 0 ) ;

    //place the ball
    SDL_BlitSurface ( pBitmap , &amp;rcSrc , pSurface , &amp;rcDst ) ;

    //move the ball
    rcDst.x += dx ;
    rcDst.y += dy ;

    //check for bounces
    if ( rcDst.x == 0 || rcDst.x == SCREENWIDTH - rcDst.w ) dx = -dx ;
    if ( rcDst.y == 0 || rcDst.y == SCREENHEIGHT - rcDst.h ) dy = -dy ;

    //update the screen
    SDL_UpdateRect ( pSurface , 0 , 0 , 0 , 0 ) ;
</B>  }//end of message pump

  //done
  return ( 0 ) ;
}
</PRE></BLOCKQUOTE>
<P>And if you run the application, you'll see whatever image you made for your 
ball bounce slowly around the window. Its not a particularly mind-boggling 
example, but it does adequately demonstrate SDL_BlitSurface. Plus it's 
hypnotic.... you are getting sleepy... sleeeeeepy....</P>
<P>Anyway. That's the simple blit demo. As we go along, this stuff just keeps 
getting easier. Figure 3 shows what this program looks like.</P>
<P class=maintext-2 align=center><IMG height=409 
src="GameDev_net - The Simple DirectMedia Layer from a WIN32 Perspective, Part 2 SDL Video_files/02-03.jpg" 
width=518> <BR><B>Figure 3: Bouncing Ball Demo</B></P>
<P>Just a quick note before we move on. When using the SDL_BlitSurface function, 
the contents of the SDL_Rect pointed to by dstrect can change if the destination 
rectangle is clipped, so often it is a good idea to make a copy of the 
destination rectangle prior to blitting, unless you absolutely know that the 
destination rectangle lies entirely withing the destination surface.</P>
<H2>Color Keys</H2>
<P>And now we come to the issue of transparency. In GDI, in order to make 
transparency work, you either need to use bitmasks, or else use the 
TransparentBlt function, which doesn't work on all versions of Windows. In 
DirectDraw, you have to set up a DDCOLORKEY for a surface that uses one, and you 
have to pass particular flags when using the Blt or BltFast function.</P>
<P>In SDL, setting up a transparent color is really easy. Unlike DirectDraw, you 
can only have one (1) transparent color for an SDL surface (of course, it's not 
like DirectDraw had widespread support for transparent color spaces, but I 
digress). In any case, a single color is usually enough for transparency anyway. 
Once a color key has been set for a surface, it is used whenever that surface is 
the source surface in a blit operation (which is nice, because then you don't 
have to remember which surfaces have color keys).</P>
<P>The function for setting the color key of a surface is called 
SDL_SetColorKey.</P>
<BLOCKQUOTE><PRE class=code>int SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
</PRE></BLOCKQUOTE>
<P>This function takes three parameters: a pointer to a surface, a flag, and a 
key (the color, in the surfaces native pixel format). It returns an int, 0 if 
successful, and -1 if there is an error.</P>
<P>If flag contiains SDL_SRCCOLORKEY, then the value in key becomes the new 
transparent color key. If flag contains 0, any color key is cleared. You can 
retrieve the color key from the surface's pixel format, e.g. 
pSurface-&gt;format-&gt;colorkey.</P>
<P>Remember that key is in the native pixel format of the surface, and so if 
working with SDL_Color variables, you'll need to convert it with SDL_MapRGB.</P>
<P>No example for color keys, as their use is fairly obvious.</P>
<H2>Clipping Rectangles</H2>
<P>As a final topic, I'm going to show you how to set up a clipping rectangle 
for a surface. A clipping rectangle is the equivalent of an HRGN selected into 
an HDC in GDI, or an IDirectDrawClipper object attached to an IDirectDrawSurface 
object with SetClipper. Compared to their GDI or DirectDraw counterparts, the 
SDL clipping rectangle is not nearly as powerful or flexible. You can only have 
a single clipping rectangle at a time. For most purposes, that's enough. For 
times when it is not, you'll just have to get creative.</P>
<P>A clipping rectangle is just that: a rectangular area ( as described by an 
SDL_Rect variable) to which all destination blits are confined. Pixel plotting 
is unaffected by the clipping rectangle, as it directly accesses the pixel data 
of the surface. To set up a clipping rectangle for a surface, the function is 
SDL_SetClipRect.</P>
<BLOCKQUOTE><PRE class=code>void SDL_SetClipRect(SDL_Surface *surface, SDL_Rect *rect);
</PRE></BLOCKQUOTE>
<P>This function returns no value. It takes two parameters, a pointer to a 
surface (for which you are setting the clipping rectangle), and a pointer to an 
SDL_Rect structure (which contains the new clipping rectangle). If you pass NULL 
for rect, you will set the clipping area to the size of the entire surface.</P>
<P>To examine the contents of the clipping rectangle, you can either look at the 
clip_rect member of the SDL_Surface structure, or you can use SDL_GetClipRect, 
which has the same parameter list as SDL_SetClipRect, except that the current 
clipping rectangle is instead read into the variable pointed to by rect.</P>
<P>No example for clipping rectangles, as their use is fairly obvious.</P>
<H1>Summary</H1>
<P>We haven't totally exhausted the video system of SDL yet. There is still 
quite a bit more, but you've now been exposed to the basics. The functions shown 
in this article will be the ones most oft-used, although there are certainly 
some interesting aspects of some of the other functions, and later in the 
series, we shall return once again to the video subsystem. For now, this shall 
suffice.</P>
<P>Next Time: Events</P>
<P>Ernest S. Pazera</P>
<P><A href="mailto:ernestpazera@hotmail.com">ernestpazera@hotmail.com</A></P>
<P>Sources: SDL Documentation</P>
<P align=center><B><A 
href="http://www.gamedev.net/community/forums/topic.asp?key=featart&amp;uid=1603&amp;forum_id=35&amp;Topic_Title=The+Simple+DirectMedia+Layer+from+a+WIN32+Perspective%2C+Part+2%3A+SDL+Video">Discuss 
this article in the forums</A></B></P>
<P><BR><SPAN class=maintext-2>Date this article was posted to GameDev.net: 
<B>12/17/2001</B> <BR>(Note that this date does not necessarily correspond to 
the date the article was written)</SPAN> 
<P align=center>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -