动画是利用人类的视觉特点被创造出来的艺术品。图像在不同的时间和位置出现可以产生一定的视觉特效。SDL程序可以制作动画。想要制作出动画的效果,就需要把握好单位时间内出现
动画是利用人类的视觉特点被创造出来的艺术品。图像在不同的时间和位置出现可以产生一定的视觉特效。SDL程序可以制作动画。想要制作出动画的效果,就需要把握好单位时间内出现的图片数量这一个因素。一般来说,一秒24帧可以得到流畅的动画场景。那么两张图像的时间间隔保持约为41666 microseconds.
下面例子中的GIF图片是GifCam.exe截屏制成。
- 制作一个简单动画:
红色的圆圈不断扩大,周而复始。整个窗口在一段时间后自动关闭。
可以使用alarm函数可以实现“计时”,或者SDL_GetTicks判断时间再终止。想要之前所画的圆消失,可以用不同的颜色再画一次,将其抹去。
#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.shexport 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 <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.shexport 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 更新:
注意,矩形小球图片需要保证小球和矩形图片边界保留一定的白色空间,不然你很可能得到这样的效果:
当然,可以自己添加类似于下面的函数,解决这个问题,不过存在闪烁的副作用。
SDL_FillRect(screen,Rec,color); /* sweep past the trace before */
SDL_UpdateRect(screen, 0, 0, 0, 0);
}