View
219
Download
0
Category
Preview:
Citation preview
1
Scrolling and Panning
CIS 487/587
Bruce R. Maxim
UM-Dearborn
2
How do you get the background to move as viewpoint changes?
• Page scrolling engines blit each off screen image onto the display as it is needed
[0][0]
[max X][max Y]
Page 0
Page 4 Page 5 Page 6 Page 7
Page 1 Page 2 Page 3
Display [Page 1]
3
LaMothe Examples
4
BOB Animation
#include <ddraw.h> // directX includes
#include "T3DLIB1.H" // include the library header
// demo globals
BOB skelaton; // the player skelaton
// animation sequences for bob
int skelaton_anims[8][4] = { {0,1,0,2},
{0+4,1+4,0+4,2+4},
{0+8,1+8,0+8,2+8},
{0+12,1+12,0+12,2+12},
{0+16,1+16,0+16,2+16},
{0+20,1+20,0+20,2+20},
{0+24,1+24,0+24,2+24},
{0+28,1+28,0+28,2+28}, };
5
Game_Init( )// initialize directdraw
DDraw_Init(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP);
// load in each page of the scrolling background
for (index = 0; index<3; index++)
{
// build up file name
sprintf(filename,"LANDSCAPE%d.BMP",index+1);
// load the background
Load_Bitmap_File(&bitmap8bit, filename);
// create and load the reactor bitmap image
Create_Bitmap(&landscape[index], 0,0, 640, 480);
Load_Image_Bitmap(&landscape[index],&bitmap8bit,0,0,
BITMAP_EXTRACT_MODE_ABS);
Unload_Bitmap_File(&bitmap8bit);
} // end for index
// set the palette to background image palette
Set_Palette(bitmap8bit.palette);
6
Game_Init( )// load in all the frames for the skelaton!!!if (!Create_BOB(&skelaton,0,0,72,74,32, // 56x72 BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_ANIM,DDSCAPS_SYSTEMMEMORY)) return(0);// load the frames in 8 directions, 4 frames each each set of frames has a walk// and a fire, frame sets are loaded in counter clockwise order looking down// from a birds eye view or the x-z planefor (int direction = 0; direction < 8; direction++){ // build up file name sprintf(filename,"QUENSP%d.BMP",direction); // skelsp // load in new bitmap file Load_Bitmap_File(&bitmap8bit,filename); Load_Frame_BOB(&skelaton,&bitmap8bit,0+direction*4,0,0,BITMAP_EXTRACT_MODE_CELL); Load_Frame_BOB(&skelaton,&bitmap8bit,1+direction*4,1,0,BITMAP_EXTRACT_MODE_CELL); Load_Frame_BOB(&skelaton,&bitmap8bit,2+direction*4,2,0,BITMAP_EXTRACT_MODE_CELL); Load_Frame_BOB(&skelaton,&bitmap8bit,3+direction*4,0,1,BITMAP_EXTRACT_MODE_CELL); // unload the bitmap file Unload_Bitmap_File(&bitmap8bit); // set the animation sequences for skelaton Load_Animation_BOB(&skelaton,direction,4,skelaton_anims[direction]); } // end for direction
7
Game_Init( )
// set up stating state of skelaton
Set_Animation_BOB(&skelaton, 0);
Set_Anim_Speed_BOB(&skelaton, 4);
Set_Vel_BOB(&skelaton, 0,0);
Set_Pos_BOB(&skelaton, 16, 256); // right above the floor
// set clipping rectangle to screen extents so mouse cursor
// doens't mess up at edges
RECT screen_rect = {0,0,screen_width,screen_height};
lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);
// hide the mouse
ShowCursor(FALSE);
8
Handling Terrain and Scrolling
// global declarations
// default screen size
#define SCREEN_WIDTH 640 // size of screen
#define SCREEN_HEIGHT 480
#define SCREEN_BPP 8 // bits per pixel
#define START_GLOW_COLOR 152 // starting color index to glow
#define END_GLOW_COLOR 159 // ending color index to glow
#define FLOOR_COLOR 116
9
Game_Main( )// test direction of motion
if (KEY_DOWN(VK_RIGHT))
{
// move skelaton
skelaton.x+=2;
dx=2; dy=0;
// set motion flag
player_moving = 1;
// check animation needs to change
if (skelaton.curr_animation != SKELATON_EAST)
Set_Animation_BOB(&skelaton,SKELATON_EAST);
} // end if
10
Game_Main( )else
if (KEY_DOWN(VK_LEFT))
{
// move skelaton
skelaton.x-=2;
dx=-2; dy=0;
// set motion flag
player_moving = 1;
// check animation needs to change
if (skelaton.curr_animation != SKELATON_WEST)
Set_Animation_BOB(&skelaton,SKELATON_WEST);
} // end if
11
Game_Main( )// apply downward gravity to player, so player follows terrain
skelaton.y+=1;// only animate if player is movingif (player_moving){ Animate_BOB(&skelaton);} // end if// lock surface, so we can scan itDDraw_Lock_Back_Surface();// call the color scanner with FLOOR_COLOR, the color of the glowing floor// try to center the scan on the feet of the player, make sure feet stay// in contact with floorwhile(Color_Scan(skelaton.x+16, skelaton.y+24, skelaton.x+skelaton.width-32, skelaton.y+skelaton.height-12,
FLOOR_COLOR, FLOOR_COLOR, back_buffer,back_lpitch)){ // push the skelaton upward, to keep it on the floor skelaton.y -= 1; } // end while // done, so unlockDDraw_Unlock_Back_Surface();
12
Game_Main( )// draw the skelaton
Draw_BOB(&skelaton, lpddsback);
// this performs the animation for the glowing rock
static int glow_count = 0;
// increment action counter and test
if (++glow_count > 5)
{
// rotate the colors
Rotate_Colors(152,159);
// reset the counter
glow_count = 0;
} // end if
// animate the floor
glow.peGreen = rand()%256;
Set_Palette_Entry(FLOOR_COLOR, &glow);
13
Game_Main( )// test for page flip right
if (skelaton.x > SCREEN_WIDTH - (skelaton.width >> 1))
{
// bump back regardless
skelaton.x-=dx;
// test for page flip
if (curr_page < 2)
{
// scroll to next page to right
curr_page++;
// reset character to left edge of screen
skelaton.x = -(skelaton.width >> 1);
} // end if
} // end if
14
Game_Main( )
else // page flip right?
if (skelaton.x < -(skelaton.width >> 1))
{
// bump back regardless
skelaton.x=-(skelaton.width >> 1);
// test for page flip
if (curr_page > 0)
{
// scroll to next page to left
curr_page--;
// reset character to right edge of screen
skelaton.x = SCREEN_WIDTH - (skelaton.width >> 1);
} // end if
} // end if
// flip the surfaces
DDraw_Flip();
// sync to 30 fps
Wait_Clock(30);
15
BOB Functions
• Several functions defined to make blitting faster by using DirectDraw surfaces– Create_BOB– Destroy_BOB– Draw_BOB– Load_BOB– Animate_BOB
• Drawing BOB’s off screen is more efficient than using secondary memory since they are on flippable pages
16
BOB Process
• Set up DirectDraw
• Load 256-color map
• Create blank BOB
• Load image into BOB
• Draw BOB
• Destroy BOB when finished
17
Smooth Scrolling
• One way to achieve smooth scrolling would be creating a “huge” DirectDraw offscreen surface and use the blitter to display a sliding portion of it
blitter backbuffer
primary
18
Smooth Scrolling
• Another approach is to use lots of homogeneous (and small) tiles that can be fit together like building blocks
• You might also decide to create an index to help you decide which tile to display
19
Tiling
| 3 3 9 8 |
world [4][4] = | 1 6 6 0 |
| 3 5 9 7 |
| 4 6 7 9 |
0
1
2
3
4
pic
Viewport contains clipped and rendered bitmaps
20
Tiling Demo
• Uses 9 bit maps for tiles (textures)
• World is 21 by 31
• Most of the work is done in Game_Init( ) and Game_Main( )
21
GlobalsBOB textures; // texture memory
int world_x = 0, world_y = 0; // current position of viewing window
// use an array of string pointers, could have used an characters '0' - '9‘
// represent bitmaps 0-9 in some texture memory
char *world[21] =
{
"111111111111111111111111111111",
"100000000000000000000000000001",
"100002222220000000000000077701",
"100002222223333333333000077701",
"100002222227777777773000070001",
…
"100000666666666666666666600001",
"100000800000000000000000800001",
"100000800000000000000000800001",
"100000000000000000000000000001",
"111111111111111111111111111111",
};
22
Game_Init( )// initialize directdrawDDraw_Init(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP);// load in texture mapsLoad_Bitmap_File(&bitmap8bit, "SCROLLTEXTURES.BMP");// set the palette to background image paletteSet_Palette(bitmap8bit.palette);// create the texture bobif (!Create_BOB(&textures,0,0,64,64,10, BOB_ATTR_VISIBLE | BOB_ATTR_MULTI_FRAME,DDSCAPS_SYSTEMMEMORY)) return(0);// load each texture bitmap into the texture BOB objectfor (index = 0; index < NUM_TEXTURES; index++) Load_Frame_BOB(&textures,&bitmap8bit,index,index%4,index/4, BITMAP_EXTRACT_MODE_CELL); // unload the texture map bitmapUnload_Bitmap_File(&bitmap8bit);// set clipping rectangle to screen extent so mouse cursordoens't mess up at edgesRECT screen_rect = {0,0,screen_width,screen_height-32}; // 32 pixels at the bottom for controlslpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);
23
Game_Main( )// clear the drawing surface
// check for movement (scrolling)
// compute starting map indices by dividing position by size of cell
start_map_x = world_x/64; // use >> 6 for speed, but this is clearer
start_map_y = world_y/64;
// compute end of map rectangle for best cast i.e. aligned on 64x64 boundary
end_map_x = start_map_x + 10 - 1;
end_map_y = start_map_y + 7 - 1;
// now compute number of pixels in x,y we are within the tile
offset_x = -(world_x % 64);
offset_y = -(world_y % 64);
// adjust end_map_x,y for offsets
if (offset_x)
end_map_x++;
if (offset_y)
end_map_y++;
24
Game_Main( )int texture_x = offset_x; // set starting position of first upper lh textureint texture_y = offset_y; // draw the current windowfor (index_y = start_map_y; index_y <= end_map_y; index_y++){ for (index_x = start_map_x; index_x <= end_map_x; index_x++) { textures.x = texture_x; // set position to blit textures.y = texture_y; textures.curr_frame = world[index_y][index_x] - '0'; // set frame // draw the texture Draw_BOB(&textures,lpddsback); // update texture position texture_x += 64; } // end for map_x // reset x postion, update y texture_x = offset_x; texture_y += 64;} // end for map_y
25
Enormous Sparse Worlds
• What happens with huge worlds and objects that are far apart?
• If most of the world has a common simple background (e.g. black for space shooter) you might try sparse matrix techniques
• For each sector of space, you might have a list of viewable objects stored with their coordinates
• You then position and display each BOB when the viewport overlaps its sector coordinates
26
Sparse Worlds
• Most of the work will be done in Game_Init( ) and Game_Main( )
• Here is the global world declaration
// demo globalsBOB generator, // the generator BOB alien, // a little alien ship BOB beacon; // a beacon BOB int world_x = 0, // current position of viewing window world_y = 0; SPARSE_OBJ world[NUM_OBJECTS_UNIVERSE]; // world consists of 256 objects placed in a 10x10 universe
27
Game_Init( )// load in the generator bob image
Load_Bitmap_File(&bitmap8bit, "GENS4.BMP");// set the palette to the palette of the generatorsSet_Palette(bitmap8bit.palette);// create the generator bobif (!Create_BOB(&generator,0,0,72,84,4, BOB_ATTR_VISIBLE |
BOB_ATTR_MULTI_FRAME,DDSCAPS_SYSTEMMEMORY)) return(0);// load each bitmap into the generator BOB objectfor (index = 0; index < 4; index++) Load_Frame_BOB(&generator,&bitmap8bit,index,index%4,index/4, BITMAP_EXTRACT_MODE_CELL); // set up stating state of bobSet_Animation_BOB(&generator, 0);Set_Anim_Speed_BOB(&generator, 4);// unload the map bitmapUnload_Bitmap_File(&bitmap8bit);
28
Game_Init( )// load in the alien bob imageLoad_Bitmap_File(&bitmap8bit, "ALIENS0.BMP"); // create the alien bobif (!Create_BOB(&alien,0,0,56,30,8, BOB_ATTR_VISIBLE |
BOB_ATTR_MULTI_FRAME,DDSCAPS_SYSTEMMEMORY)) return(0);// load each bitmap into the alien BOB objectfor (index = 0; index < 8; index++) Load_Frame_BOB(&alien,&bitmap8bit,index,index%5,index/5, BITMAP_EXTRACT_MODE_CELL); // set up stating state of bobSet_Animation_BOB(&alien, 0);Set_Anim_Speed_BOB(&alien, 4);// unload the bitmapUnload_Bitmap_File(&bitmap8bit);
29
Game_Init( )
// set clipping rectangle to screen extents
RECT screen_rect = {0,0,screen_width,screen_height};
lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect);
// hide the mouse
ShowCursor(FALSE);
// now generate the sparse universe
for (index = 0; index < NUM_OBJECTS_UNIVERSE; index++)
{
// set random position
world[index].x = rand()%MAX_UNIVERSE_X;
world[index].y = rand()%MAX_UNIVERSE_Y;
// set type
world[index].type = rand()%3; // 0, 1, 2 generator, alien, beacon
} // end for index
30
Game_Main( )BOB_PTR object_ptr; // the object that is going to be rendered// check of user is trying to exit// start the timing clock// clear the drawing surface // check for movement (scrolling)// based on current world position which defines the viewport, i.e,// world_x, world_y to world_x+640-1, world_y+480-1, scan the object// list determine any object in that region translate it to screen// coords and render it // compute extents based on width,height x1 = x0 + width - 1; y1 = y0 + height - 1; // do trivial clip// animate all the bobsAnimate_BOB(&generator);Animate_BOB(&beacon);Animate_BOB(&alien);
Recommended