SDL简单动画

论坛 期权论坛 脚本     
匿名技术用户   2020-12-22 17:13   11   0

动画是利用人类的视觉特点被创造出来的艺术品。图像在不同的时间和位置出现可以产生一定的视觉特效。SDL程序可以制作动画。想要制作出动画的效果,就需要把握好单位时间内出现的图片数量这一个因素。一般来说,一秒24帧可以得到流畅的动画场景。那么两张图像的时间间隔保持约为41666 microseconds.
下面例子中的GIF图片是GifCam.exe截屏制成。

  • 制作一个简单动画:
    红色的圆圈不断扩大,周而复始。整个窗口在一段时间后自动关闭。
    可以使用alarm函数可以实现“计时”,或者SDL_GetTicks判断时间再终止。想要之前所画的圆消失,可以用不同的颜色再画一次,将其抹去。
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <string.h>
#include <math.h>
#include <SDL_draw.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(){
    SDL_Surface *screen = SDL_SetVideoMode(240,240,16,SDL_SWSURFACE);
    if(screen == NULL){
        fprintf(stderr,"SDL_SetVideoMode error %s\n",SDL_GetError());
        exit(1);
    }   
    if(SDL_Init(SDL_INIT_VIDEO) < 0){
        fprintf(stderr,"SDL_INIT_VIDEO error %s\n",SDL_GetError());
        exit(1);
    }
    atexit(SDL_Quit);
    int us = 41666*2;   
    while(1){
        if(SDL_GetTicks()>10000) exit(0);
        int r;
        for(r=0;r<=80;r+=10){
            Draw_Circle(screen,120,120,r,SDL_MapRGB(screen->format,255,0,0));
            SDL_UpdateRect(screen,0,0,0,0);
            Draw_Circle(screen,120,120,r-10,SDL_MapRGB(screen->format,0,0,0));
            SDL_UpdateRect(screen,0,0,0,0);
            usleep(us);
        }
        Draw_Circle(screen,120,120,r-10,SDL_MapRGB(screen->format,0,0,0));
        SDL_UpdateRect(screen,0,0,0,0);
        usleep(us);
    }
    return 0;
}

编译运行:

edemon@ubuntu1:~/workspace$ cat draw_circle.sh
export CFLAGS="`sdl-config --cflags` -I/home/edemon/SDL_draw-1.2.13/include"
export LIBS="`sdl-config --libs` /home/edemon/SDL_draw-1.2.13/src/.libs/libSDL_draw.a"
gcc -o draw_circle draw_circle.c -Wall $CFLAGS $LIBS -lm
edemon@ubuntu1:~/workspace$ ./draw_cricle

这里写图片描述

  • 制作动画:红色的小球在方块范围内不断运动,碰到边界则反弹。当用户敲击任意键后程序结束。
    制作一个小球的bmp位图图片,背景是白色。然后用SDL_FillRect函数将屏幕背景也变成白色。在41666us的时间间隔下不断更新自己的位置。
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <string.h>
#include <math.h>
#include <SDL_draw.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

SDL_Surface *image;
void handler(){
    SDL_FreeSurface(image);
    exit(0);
}
int main(){
    SDL_Surface *screen = SDL_SetVideoMode(340,340,16,SDL_SWSURFACE);
    unsigned int color;
    SDL_Event event;
    image = SDL_LoadBMP("ball.bmp");
    if(screen == NULL){
        fprintf(stderr,"SDL_SetVideoMode error %s\n",SDL_GetError());
        exit(1);
    }   
    if(image == NULL){
        fprintf(stderr,"SDL_LoadBMP error %s\n",SDL_GetError());
        exit(1);
    }
    if(SDL_Init(SDL_INIT_VIDEO) < 0){
        fprintf(stderr,"SDL_INIT_VIDEO error %s\n",SDL_GetError());
        exit(1);
    }
    color = SDL_MapRGB(screen->format,255,255,255);
    atexit(SDL_Quit);
    SDL_Rect rect;
    rect.x = 100;
    rect.y = 70;
    rect.w = image->w;
    rect.h = image->h;
    SDL_FillRect(screen,NULL,color);
    SDL_BlitSurface(image,NULL,screen,&rect);
    SDL_UpdateRect(screen,0,0,0,0);
    int rightleft = 1, updown = 1;  // for rightleft, 1 means right, 0 means left; for updown, 1 means down, 0 means up.
    int speed = 4;
    while(1){
        if(SDL_PollEvent(&event) && event.type == SDL_KEYDOWN) handler();
        usleep(41666);
        if(rightleft){
            if(rect.x+rect.w+speed<screen->w){
                rect.x+=speed;
            }   
            else {
                rect.x-=speed;
                rightleft = 0;
            }
        }
        else {
            if(rect.x-speed>0){
                rect.x-=speed;
            }
            else {
                rect.x+=speed;
                rightleft = 1;
            }
        }

        if(updown){
            if(rect.y+rect.h+speed<screen->h){
                rect.y+=speed;
            }
            else {
                rect.y-=speed;
                updown = 0;
            }
        }
        else {
            if(rect.y-speed>0){
                rect.y-=speed;
            }
            else {
                rect.y+=speed;
                updown = 1;
            }
        }
        SDL_BlitSurface(image,NULL,screen,&rect);
        SDL_Flip(screen);
    }
    //SDL_Delay(5000);
    return 0;
}

编译执行:

edemon@ubuntu1:~/workspace$ cat move.sh
export CFLAGS="`sdl-config --cflags` -I/home/edemon/SDL_draw-1.2.13/include"
export LIBS="`sdl-config --libs` /home/edemon/SDL_draw-1.2.13/src/.libs/libSDL_draw.a"
gcc -o move move.c -Wall $CFLAGS $LIBS -lm
edemon@ubuntu1:~/workspace$ ./move

这里写图片描述
———————————————————————-
17.04.17 更新:
注意,矩形小球图片需要保证小球和矩形图片边界保留一定的白色空间,不然你很可能得到这样的效果:

这里写图片描述
当然,可以自己添加类似于下面的函数,解决这个问题,不过存在闪烁的副作用。

void deleteRec(SDL_Rect *Rec){
    SDL_FillRect(screen,Rec,color);     /* sweep past the trace before */
    SDL_UpdateRect(screen, 0, 0, 0, 0);
}
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:7942463
帖子:1588486
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP