SDL:绘制半透明矩形

时间:2013-11-24 12:29:01

标签: perl sdl alpha

我无法弄清楚如何在屏幕表面上绘制半透明的红色矩形。 这是我到目前为止的代码:

#!/usr/bin/perl

use SDL;
use SDL::Video;
use SDL::Surface;
use SDL::Rect;

# the size of the window box or the screen resolution if fullscreen
my $screen_width   = 800;
my $screen_height  = 600;

SDL::init(SDL_INIT_VIDEO);

# setting video mode
my $screen_surface = SDL::Video::set_video_mode($screen_width, $screen_height, 32, SDL_ANYFORMAT|SDL_SRCALPHA);

# drawing something somewhere
my $mapped_color = SDL::Video::map_RGBA($screen_surface->format(), 255, 0, 0, 128); #should be half-transparent, I suppose?

SDL::Video::fill_rect($screen_surface, 
SDL::Rect->new($screen_width / 4, $screen_height / 4, 
               $screen_width / 2, $screen_height / 2), $mapped_color);

# update an area on the screen so its visible
SDL::Video::update_rect($screen_surface, 0, 0, $screen_width, $screen_height);

sleep(5); # just to have time to see it

它导致黑色背景上的红色不透明矩形,这不是我想要实现的。

1 个答案:

答案 0 :(得分:3)

您不能将SDL_FillRect用于透明度。该函数将使用值color覆盖曲面。把它想象成一个“memset”。

来自docs的引用:如果颜色值包含alpha值,则目标只是“填充”该alpha信息,不会发生混合。

使用SDL_BlitSurface获得透明度。首先创建一个纹理,用颜色填充然后再用blit。

我为练习做了一个小测试案例:

#include <SDL.h>

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

SDL_Surface* CreateSurface( int width , int height )
{
    uint32_t rmask , gmask , bmask , amask ;

    /* SDL interprets each pixel as a 32-bit number, so our masks must depend
       on the endianness (byte order) of the machine */
    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
        rmask = 0xff000000;
        gmask = 0x00ff0000;
        bmask = 0x0000ff00;
        amask = 0x000000ff;
    #else
        rmask = 0x000000ff;
        gmask = 0x0000ff00;
        bmask = 0x00ff0000;
        amask = 0xff000000;
    #endif

    SDL_Surface* surface = SDL_CreateRGBSurface( 0 , width , height , 32 , rmask , gmask , bmask , amask ) ;
    if( surface == NULL ) 
    {
        ( void )fprintf(stderr, "CreateRGBSurface failed: %s\n", SDL_GetError() );
        exit(1);
    }

return surface ;
}

void Quit( void )
{
    SDL_Quit() ;
    exit(0) ;
}


int main(int argc, char *argv[])
{
    ( void )argc ;
    ( void )argv ;

    int init = !( SDL_Init( SDL_INIT_EVERYTHING ) );
    if( !init )
        Quit() ;


    SDL_Surface* screen = SDL_SetVideoMode( 800 , 600 , 32 , 0 ) ;
    if( !screen )
        Quit() ;

    int run = true ;

    while( run )
    {

        SDL_Event event ;
        while( SDL_PollEvent( &event ) )
        {
            switch( event.type )
            {
                case SDL_QUIT:
                    run = false ;
                    break;
            }
        }

        SDL_Surface* s = CreateSurface( 300 ,300 ) ;
        ( void )SDL_FillRect( s , NULL , 0xAA0000FF ) ;


        SDL_Rect rect = { 100 , 100 } ;
        ( void )SDL_BlitSurface( s , NULL , screen , &rect ) ;

        rect.x = 200 ;
        rect.y = 200 ;
        ( void )SDL_FillRect( s , NULL , 0x440000FF ) ;
        ( void )SDL_BlitSurface( s , NULL , screen , &rect ) ;

        SDL_FreeSurface( s ) ; 

        ( void )SDL_Flip( screen ) ;
        SDL_Delay( 15 ) ;

        ( void )SDL_FillRect( screen , NULL , 0x00FFFF ) ;  
    }

    Quit() ;

    return 0;
}