Thực hành:
Thực hành vẽ một hình cơ bản chuyển động theo một quỹ đạo cho trước
- Yêu cầu SV chuẩn bị:
Đọc c ác phần tương ứng trong chương 7 của [1] và chương 6 của tài liệu [4].
Đọc c ác phần tương ứng trong tài liệu [5].
Chú ý nghe giảng.
Tích cực tham gia phát biểu ý kiến
Bài giảng 7: Lập trình nhân vật nâng cao
Tiết thứ: 17-20 Tuần thứ: 6+7
- Mục đích, yêu cầu:
• Nắm được các kỹ thuật xây dựng nhân vật nâng cao.
• Nắm được nguyên lý xây dựng nhân vật hoạt hình.
• Nắm được cách kết nối nhiều nhân vật.
- Hình thức tổ chức dạy học: Lý thuyết, thực hành, tự học, tự nghiên cứu
- Thời gian: Lý thuyết: 4t; Thực hành: 3t; Tự học, tự nghiên cứu: 8t
- Địa điểm: Giảng đường do P2 phân công.
- Nội dung chính:
Lý thuyết:
Here is what this chapter covers:
7.1 Animated Sprites
The sprites you have seen thus far were handled somewhat haphazardly, in that no real structure was available for keeping track of these sprites. They have simply been loaded using load bitmap and then drawn using draw sprite, with little else in the way of control or handling. To really be able to work with animated sprites in a highly complex game, you need a framework for drawing, erasing, and moving these sprites, and for detecting collisions.
7.2 Drawing an Animated Sprite
Figure 7.1
The animated cat sprite.
Figure 7.2
The AnimSprite program shows how you can do basic sprite animation.
#include
#include
#include
#define WHITE makecol(255,255,255)
#define BLACK makecol(0,0,0)
BITMAP *kitty[7];
char s[20];
int curframe=0, framedelay=5, framecount=0;
int x=100, y=200, n;
int main(void)
{
//initialize the program
allegro init();
install keyboard();
install timer();
set color depth(16);
set gfx mode(GFX AUTODETECT WINDOWED, 640, 480, 0, 0);
textout ex(screen, font, "AnimSprite Program (ESC to quit)",
0, 0, WHITE, 0);
//load the animated sprite
for (n=0; n<6; n++)
{
sprintf(s,"cat%d.bmp",n+1);
kitty[n] = load bitmap(s, NULL);
}
//main loop
while(!keypressed())
{
//erase the sprite
rectfill(screen, x, y, x+kitty[0]->w, y+kitty[0]->h, BLACK);
//update the position
x += 5;
if (x > SCREEN W - kitty[0]->w)
x = 0;
//update the frame
if (framecount++ > framedelay)
{
framecount = 0;
curframe++;
if (curframe > 5)
curframe = 0;
}
acquire screen();
//draw the sprite
draw sprite(screen, kitty[curframe], x, y);
//display logistics
textprintf ex(screen, font, 0, 20, WHITE, 0,
"Sprite X,Y: %3d,%3d", x, y);
textprintf ex(screen, font, 0, 40, WHITE, 0,
"Frame,Count,Delay: %2d,%2d,%2d",
curframe, framecount, framedelay);
release screen();
rest(10);
}
allegro exit();
return 0;
}
END OF MAIN()
7.3 Creating a Sprite Handler
Now that you have a basic—if a bit rushed—concept of sprite animation, I’d like
to walk you through the creation of a sprite handler and a sample program with
which to test it. Now you’ll take the animation code from the last few pages and
encapsulate it into a struct. The actual bitmap images for the sprite are stored
separately from the sprite struct because it is more flexible that way.
In addition to those few animation variables seen in AnimSprite, a full-blown
animated sprite handler needs to track several more variables. Here is the struct:
typedef struct SPRITE
{
int x,y;
int width,height;
int xspeed,yspeed;
int xdelay,ydelay;
int xcount,ycount;
int curframe,maxframe,animdir;
int framecount,framedelay;
}SPRITE;
7.4 The SpriteHandler Program
#include
#include
#include
#define BLACK makecol(0,0,0)
#define WHITE makecol(255,255,255)
//define the sprite structure
typedef struct SPRITE
{
int x,y;
int width,height;
Animated Sprites 323
int xspeed,yspeed;
int xdelay,ydelay;
int xcount,ycount;
int curframe,maxframe,animdir;
int framecount,framedelay;
}SPRITE;
//sprite variables
BITMAP *ballimg[16];
SPRITE theball;
SPRITE *ball = &theball;
//support variables
char s[20];
int n;
void erasesprite(BITMAP *dest, SPRITE *spr)
{
//erase the sprite using BLACK color fill
rectfill(dest, spr->x, spr->y, spr->x + spr->width,
spr->y + spr->height, BLACK);
}
void updatesprite(SPRITE *spr)
{
//update x position
if (++spr->xcount > spr->xdelay)
{
spr->xcount = 0;
spr->x += spr->xspeed;
}
//update y position
if (++spr->ycount > spr->ydelay)
{
spr->ycount = 0;
spr->y += spr->yspeed;
}
//update frame based on animdir
if (++spr->framecount > spr->framedelay)
{
spr->framecount = 0;
if (spr->animdir == -1)
{
if (--spr->curframe < 0)
spr->curframe = spr->maxframe;
}
else if (spr->animdir == 1)
{
if (++spr->curframe > spr->maxframe)
spr->curframe = 0;
}
}
}
void bouncesprite(SPRITE *spr)
{
//simple screen bouncing behavior
if (spr->x < 0)
{
spr->x = 0;
spr->xspeed = rand() % 2 + 4;
spr->animdir *= -1;
}
Animated Sprites 325
else if (spr->x > SCREEN W - spr->width)
{
spr->x = SCREEN W - spr->width;
spr->xspeed = rand() % 2 - 6;
spr->animdir *= -1;
}
if (spr->y < 40)
{
spr->y = 40;
spr->yspeed = rand() % 2 + 4;
spr->animdir *= -1;
}
else if (spr->y > SCREEN H - spr->height)
{
spr->y = SCREEN H - spr->height;
spr->yspeed = rand() % 2 - 6;
spr->animdir *= -1;
}
}
int main(void)
{
//initialize
allegro init();
set color depth(16);
set gfx mode(GFX AUTODETECT WINDOWED, 640, 480, 0, 0);
install keyboard();
install timer();
srand(time(NULL));
textout ex(screen, font, "SpriteHandler Program (ESC to quit)",
0, 0, WHITE, 0);
//load sprite images
for (n=0; n<16; n++)
{
sprintf(s,"ball%d.bmp",n+1);
ballimg[n] = load bitmap(s, NULL);
}
//initialize the sprite with lots of randomness
ball->x = rand() % (SCREEN W - ballimg[0]->w);
ball->y = rand() % (SCREEN H - ballimg[0]->h);
ball->width = ballimg[0]->w;
ball->height = ballimg[0]->h;
ball->xdelay = rand() % 2 + 1;
ball->ydelay = rand() % 2 + 1;
ball->xcount = 0;
ball->ycount = 0;
ball->xspeed = rand() % 2 + 4;
ball->yspeed = rand() % 2 + 4;
ball->curframe = 0;
ball->maxframe = 15;
ball->framecount = 0;
ball->framedelay = rand() % 3 + 1;
ball->animdir = 1;
//game loop
while (!key[KEY ESC])
{
erasesprite(screen, ball);
//perform standard position/frame update
updatesprite(ball);
//now do something with the sprite--a basic screen bouncer
bouncesprite(ball);
//lock the screen
acquire screen();
//draw the ball sprite
draw sprite(screen, ballimg[ball->curframe], ball->x, ball->y);
//display some logistics
textprintf ex(screen, font, 0, 20, WHITE, 0,
"x,y,xspeed,yspeed: %2d,%2d,%2d,%2d",
ball->x, ball->y, ball->xspeed, ball->yspeed);
textprintf ex(screen, font, 0, 30, WHITE, 0,
"xcount,ycount,framecount,animdir: %2d,%2d,%2d,%2d",
ball->xcount, ball->ycount, ball->framecount,
ball->animdir);
//unlock the screen
release screen();
rest(10);
}
Animated Sprites 327
for (n=0; n<15; n++)
destroy bitmap(ballimg[n]);
allegro exit();
return 0;
}
END OF MAIN()
7.5.Grabbing Sprite Frames from an Image
Thus, you have a basic sprite handler and now you need a function to grab an animation sequence out of a tiled image.
Figure 7.4
This bitmap image contains 32 frames of an animated sphere used as a sprite. Courtesy of Edgar Ibarra.
Now that you have the basic algorithm, here’s a full function for grabbing a single frame out of an image by passing the width, height, column, and frame number:
BITMAP *grabframe(BITMAP *source,
int width, int height,
int startx, int starty,
int columns, int frame)
{
BITMAP *temp = create bitmap(width,height);
int x = startx + (frame % columns) * width;
int y = starty + (frame / columns) * height;
blit(source,temp,x,y,0,0,width,height);
return temp;
}
7.5 Multiple Animated Sprites
Instead of a single sprite struct there is an array of sprite structs, and the code throughout the program has been modified to use the array. To initialize all of these sprites, you need to use a loop and make sure each pointer is pointing to each of the sprite structs.
//initialize the sprite
for (n=0; n
{
sprites[n] = &thesprites[n];
sprites[n]->x = rand() % (SCREEN W - spriteimg[0]->w);
sprites[n]->y = rand() % (SCREEN H - spriteimg[0]->h);
sprites[n]->width = spriteimg[0]->w;
sprites[n]->height = spriteimg[0]->h;
sprites[n]->xdelay = rand() % 3 + 1;
sprites[n]->ydelay = rand() % 3 + 1;
sprites[n]->xcount = 0;
sprites[n]->ycount = 0;
sprites[n]->xspeed = rand() % 8 - 5;
sprites[n]->yspeed = rand() % 8 - 5;
sprites[n]->curframe = rand() % 64;
sprites[n]->maxframe = 63;
sprites[n]->framecount = 0;
sprites[n]->framedelay = rand() % 5 + 1;
sprites[n]->animdir = rand() % 3 - 1;
}
Chia sẻ với bạn bè của bạn: |