支持HW团队,就支付宝领取下面的红包吧! (打开支付宝就能领取!er1OEj73Uj), (打开支付宝收索“516503473”), 你领取消费,HW有奖励。红包使用无条件限制,有条件请注意是不是有病毒。

Login or Sign up | Validate
| Search

博主:初学MPEG

初学MPEG 本博客-采用Python的web框架Django与Mysql数据库,致力于对Python、Django的了解 与研究
Django技术QQ群:XXXXXXX
Python技术QQ群:XXXXXXX

Category

Keywords

本站最新博文

友情链接  

[转]SDL 裁剪图片

类别:游戏 状态:游客可见,可回,会员可关联(没审核) 阅读:5137 评论:0 时间:May 12, 2013, 12:40 p.m.
关键字:and Blitting Clip SDL Sheets Sprite

来源:
http://www.cppblog.com/lf426/archive/2008/03/20/44935.html
http://www.cppblog.com/lf426/archive/2008/03/20/44937.html
作者:龙飞

1.裁剪精灵图片

这两天下雨,所以就暂停了寻春的步伐,多写了点教程。绵阳的春天是美丽的,大家学习和写程序之余,还是应该多看看大自然。给大家推荐我拍的风景照啦,呵呵。http://picasaweb.google.com/firefly.cao
因为不想多上传图片,所以我的例子中的图片文件直接就用Lazy Foo's教程中的附件了。相关资源,大家可以在这里下载:Clip Blitting and Sprite Sheets

1.1:什么是精灵?

如果有很多很多的图片,不想发布游戏的时候包含n多小小的图片文件,那么可以考虑把小图片都画在一张大图上,然后“抠”下来用,不也是很方便吗?这张大图就叫精灵图(Sprite sheet)。每一个抠下来的图片就叫精灵啦。
精灵只是一种技巧,需要的知识,我们前面都已经学习过了。我们稍微修改一下类,就可以很好的演示这个技术实现。

1.2:填充背景的颜色

int SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);

这个函数是往一个指定surface的指定矩形区域中填充指定的颜色。如果指定矩形区域为空指针,则填充整个surface。值得注意的是,SDL_Surface结构中包含矩形区域的只读成员数据是clip_rect。我们为ScreenSurface类增加一个方法,默认填充黑色。

class ScreenSurface
{
private:
        //
public:
        //
        void fillColor(Uint8 r = 0, Uint8 g = 0, Uint8 b = 0) const;
};

实现为:

void ScreenSurface::fillColor(Uint8 r, Uint8 g, Uint8 b) const
{
        if ( SDL_FillRect(pScreen, 0, SDL_MapRGB(pScreen->format, r, g, b)) < 0 )
                throw ErrorInfo(SDL_GetError());
}

1.3:思路

我们先创建一个ScreenSurface对象,并将其填充为白色作为背景。装载精灵图之后,先抠掉精灵图的背景色,然后按照区域,分4次将4个图片小精灵blit到背景上。非常简单!需要说明的是,我修改了局部blit()方法偏移值的默认参数值。因为在之前的章节中,局部blit()主要用于blit部分背景将背景“搽干净”,需要将偏移设为非零;而我们现在使用这个方法的主要目的是抠精灵图片,如果偏移非零的话就会把设定范围之外的图像也抠过来,而这不是我们希望发生的。下节给出完整源代码。 

2、裁剪精灵图片的完整源代码

//UVi Soft (2008)
//Long Fei (lf426), E-mail: zbln426@163.com

//FileName: SurfaceClass.h

#ifndef SURFACE_CLASS_H
#define SURFACE_CLASS_H

#include <iostream>
#include <string>
#include "SDL/SDL.h"
#include "SDL/SDL_image.h"

class ScreenSurface
{
private:
        static int screenNum;
        int width;
        int height;
        int bpp;
        Uint32 flags;
        SDL_Surface* pScreen;
public:
        ScreenSurface();
        ScreenSurface(int w, int h, int b = 0, Uint32 f = 0);
        ~ScreenSurface();
        SDL_Surface* point() const;
        void flip() const;
        void fillColor(Uint8 r = 0, Uint8 g = 0, Uint8 b = 0) const;
};

class DisplaySurface
{
private:
        std::string fileName;
        SDL_Surface* pSurface;
        SDL_Surface* pScreen;
public:
        DisplaySurface(const std::string& file_name, const ScreenSurface& screen);
        ~DisplaySurface();
        SDL_Surface* point() const;
        void blit() const;
        void blit(int at_x, int at_y) const;
        void blit(int at_x, int at_y,
                int from_x, int from_y, int w, int h,
                int delta_x = 0, int delta_y = 0) const;
        void colorKey(Uint8 r = 0, Uint8 g = 0xFF, Uint8 b = 0xFF, Uint32 flag = SDL_SRCCOLORKEY);
};

class ErrorInfo
{
private:
        std::string info;
public:
        ErrorInfo():info("Unknown ERROR!")
        {}
        ErrorInfo(const char* c_str)
        {
                info = std::string(c_str);
        }
        ErrorInfo(const std::string& str):info(str)
        {}
        void show() const
        {
                std::cerr << info << std::endl;
        }
};

#endif
//UVi Soft (2008)
//Long Fei (lf426), E-mail: zbln426@163.com

#include "SurfaceClass.h"

//VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
//class ScreenSurface

int ScreenSurface::screenNum = 0;

ScreenSurface::ScreenSurface()
        : width(640), height(480), bpp(32), flags(0)
{
        if ( screenNum > 0 )
                throw ErrorInfo("DONOT create more than ONE screen!");
        if ( SDL_Init(SDL_INIT_VIDEO < 0 ) )
                throw ErrorInfo(SDL_GetError());
        pScreen = SDL_SetVideoMode(width, height, bpp, flags);
        screenNum++;
}

ScreenSurface::ScreenSurface(int w, int h, int b, Uint32 f)
        : width(w), height(h), bpp(b), flags(f)
{
        if ( screenNum > 0 )
                throw ErrorInfo("DONOT create more than ONE screen!");
        if ( SDL_Init(SDL_INIT_VIDEO < 0 ) )
                throw ErrorInfo(SDL_GetError());
        pScreen = SDL_SetVideoMode(width, height, bpp, flags);
        screenNum++;
}

ScreenSurface::~ScreenSurface()
{
        SDL_Quit();
}

SDL_Surface* ScreenSurface::point() const
{
        return pScreen;
}

void ScreenSurface::flip() const
{
        if ( SDL_Flip(pScreen) < 0 )
                throw ErrorInfo(SDL_GetError());
}


void ScreenSurface::fillColor(Uint8 r, Uint8 g, Uint8 b) const
{
        if ( SDL_FillRect(pScreen, 0, SDL_MapRGB(pScreen->format, r, g, b)) < 0 )
                throw ErrorInfo(SDL_GetError());
}

//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

//VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
//class DisplaySurface

DisplaySurface::DisplaySurface(const std::string& file_name, const ScreenSurface& screen)
        : fileName(file_name)
{
        SDL_Surface* pSurfaceTemp = IMG_Load(file_name.c_str());
        if ( pSurfaceTemp == 0 )
                throw ErrorInfo(SDL_GetError());
        pSurface = SDL_DisplayFormat(pSurfaceTemp);
        if ( pSurface == 0 )
                throw ErrorInfo(SDL_GetError());
        SDL_FreeSurface(pSurfaceTemp);
        pScreen = screen.point();
}

DisplaySurface::~DisplaySurface()
{
        SDL_FreeSurface(pSurface);
}

SDL_Surface* DisplaySurface::point() const
{
        return pSurface;
}

void DisplaySurface::blit() const
{
        if ( SDL_BlitSurface(pSurface, 0, pScreen, 0) < 0 )
                throw ErrorInfo(SDL_GetError());
}


void DisplaySurface::blit(int at_x, int at_y) const
{
        SDL_Rect offset;
        offset.x = at_x;
        offset.y = at_y;

        if ( SDL_BlitSurface(pSurface, 0, pScreen, &offset) < 0 )
                throw ErrorInfo(SDL_GetError());
}

void DisplaySurface::blit(int at_x, int at_y,
        int from_x, int from_y, int w, int h,
        int delta_x, int delta_y) const
{
        SDL_Rect offset;
        offset.x = at_x - delta_x;
        offset.y = at_y - delta_y;

        SDL_Rect dest;
        dest.x = from_x - delta_x;
        dest.y = from_y - delta_y;
        dest.w = w + delta_x*2;
        dest.h = h + delta_y*2;

        if ( SDL_BlitSurface(pSurface, &dest, pScreen, &offset) < 0 )
                throw ErrorInfo(SDL_GetError());
}

void DisplaySurface::colorKey(Uint8 r, Uint8 g, Uint8 b, Uint32 flag)
{
        Uint32 colorkey = SDL_MapRGB(pSurface->format, r, g, b);
        if ( SDL_SetColorKey(pSurface, flag, colorkey ) < 0 )
                throw ErrorInfo(SDL_GetError());
}

//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
#ifdef WIN32
#ifdef _DEBUG
#pragma comment (lib, "SDLd")
#pragma comment (lib, "SDLmaind")
#pragma comment (lib, "SDL_imaged")
#else
#pragma comment (lib, "SDL")
#pragma comment (lib, "SDLmain")
#pragma comment (lib, "SDL_image")
#endif
#endif /* WIN32 */

//UVi Soft (2008)
//Long Fei (lf426), E-mail: zbln426@163.com

#include "SurfaceClass.h"

int game(int argc, char* argv[]);
int main(int argc ,char* argv[])
{
        int mainRtn = 0;
        try
        {
                mainRtn = game(argc, argv);
        }
        catch ( const ErrorInfo& info )
        {
                info.show();
                return -1;
        }

        return mainRtn;
}

int game(int argc ,char* argv[])
{
        //Create a SDL screen.
        const int SCREEN_WIDTH = 640;
        const int SCREEN_HEIGHT = 480;
        ScreenSurface screen(SCREEN_WIDTH, SCREEN_HEIGHT);
        //Fill background with white.(default is black)
        screen.fillColor(0xFF, 0xFF, 0xFF);

        //Load a sprite pic, and colorkey.(default color: R=0,G=0xFF,B=0xFF)
        DisplaySurface sprite("dots.png", screen);
        sprite.colorKey();

        //the 4 dots's coordinate.
        int atX[4] = {0, 540, 0, 540};
        int atY[4] = {0, 0, 380, 380};
        //the 4 dots's clip coordinate.
        int fromX[4] = {0, 100, 0 ,100};
        int fromY[4] = {0, 0, 100, 100};
        //dots's size.
        const int IMG_WIDTH = 100;
        const int IMG_HEIGHT = 100;
        //clip dots.
        for ( int i = 0; i < 4; i++ )
                sprite.blit(atX[i], atY[i], fromX[i], fromY[i], IMG_WIDTH, IMG_HEIGHT);
        //Draw dots and screen.
        screen.flip();

        //press ESC or click X to quit.
        bool gameOver = false;
        SDL_Event gameEvent;
        while( gameOver == false )
        {
                while ( SDL_PollEvent(&gameEvent) != 0 )
                {
                        if ( gameEvent.type == SDL_QUIT )
                        {
                                gameOver = true;
                        }
                        if ( gameEvent.type == SDL_KEYUP )
                        {
                                if ( gameEvent.key.keysym.sym == SDLK_ESCAPE )
                                {
                                        gameOver = true;
                                }
                        }
                }
        }
        return 0;
}

 

文件名 大小 时间 会员 费用 操作
VS2010工程.rar(精华) 5K685B May 12, 2013, 1:03 p.m. 初学MPEG 积分:0
荣誉:0
会币:0
下载
 
 
操作:

Please Login (or Sign Up) to leave a comment