30
1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

Embed Size (px)

Citation preview

Page 1: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

1

Scrolling and Panning

CIS 487/587

Bruce R. Maxim

UM-Dearborn

Page 2: 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]

Page 3: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

3

LaMothe Examples

Page 4: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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}, };

Page 5: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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);

Page 6: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 7: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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);

Page 8: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 9: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 10: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 11: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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();

Page 12: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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);

Page 13: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 14: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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);

Page 15: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 16: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

16

BOB Process

• Set up DirectDraw

• Load 256-color map

• Create blank BOB

• Load image into BOB

• Draw BOB

• Destroy BOB when finished

Page 17: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 18: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 19: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 20: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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( )

Page 21: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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", 

};

Page 22: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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);

Page 23: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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++;

Page 24: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 25: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 26: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 27: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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);

Page 28: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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);

Page 29: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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

Page 30: 1 Scrolling and Panning CIS 487/587 Bruce R. Maxim UM-Dearborn

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);