int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x8 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // we need a complex surface system with a primary and backbuffer // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; // set the backbuffer count field to 1, use 2 for triple buffering ddsd.dwBackBufferCount = 1; // request a complex, flippable ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); // now query for attached surface from the primary surface // this line is needed by the call ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; // get the attached back buffer surface if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback))) return(0); // build up the palette data array for (int color=1; color < 255; color++) { // fill with random RGB values palette[color].peRed = rand()%256; palette[color].peGreen = rand()%256; palette[color].peBlue = rand()%256; // set flags field to PC_NOCOLLAPSE palette[color].peFlags = PC_NOCOLLAPSE; } // end for color // now fill in entry 0 and 255 with black and white palette[0].peRed = 0; palette[0].peGreen = 0; palette[0].peBlue = 0; palette[0].peFlags = PC_NOCOLLAPSE; palette[255].peRed = 255; palette[255].peGreen = 255; palette[255].peBlue = 255; palette[255].peFlags = PC_NOCOLLAPSE; // create the palette object if (FAILED(lpdd->CreatePalette(DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, palette,&lpddpal, NULL))) return(0); // finally attach the palette to the primary surface if (FAILED(lpddsprimary->SetPalette(lpddpal))) return(0); // set clipper up on back buffer since that's where well clip RECT screen_rect= {0,0,SCREEN_WIDTH-1,SCREEN_HEIGHT-1}; lpddclipper = DDraw_Attach_Clipper(lpddsback,1,&screen_rect); // load the 8-bit image if (!Load_Bitmap_File(&bitmap,"alley8.bmp")) return(0); // load it's palette into directdraw if (FAILED(lpddpal->SetEntries(0,0,MAX_COLORS_PALETTE,bitmap.palette))) return(0); // clean the surfaces DDraw_Fill_Surface(lpddsprimary,0); DDraw_Fill_Surface(lpddsback,0); // create the buffer to hold the background lpddsbackground = DDraw_Create_Surface(640,480,0,-1); // copy the background bitmap image to the background surface // lock the surface lpddsbackground->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL); // get video pointer to primary surfce UCHAR *image_buffer = (UCHAR *)ddsd.lpSurface; // test if memory is linear if (ddsd.lPitch == SCREEN_WIDTH) { // copy memory from double buffer to primary buffer memcpy((void *)image_buffer, (void *)bitmap.buffer, SCREEN_WIDTH*SCREEN_HEIGHT); } // end if else { // non-linear // make copy of source and destination addresses UCHAR *dest_ptr = image_buffer; UCHAR *src_ptr = bitmap.buffer; // memory is non-linear, copy line by line for (int y=0; y < SCREEN_HEIGHT; y++) { // copy line memcpy((void *)dest_ptr, (void *)src_ptr, SCREEN_WIDTH); // advance pointers to next line dest_ptr+=ddsd.lPitch; src_ptr +=SCREEN_WIDTH; } // end for } // end else // now unlock the primary surface if (FAILED(lpddsbackground->Unlock(NULL))) return(0); // unload the bitmap file, we no longer need it Unload_Bitmap_File(&bitmap); // seed random number generator srand(GetTickCount()); // initialize all the aliens (in real life do this in a loop or function) // alien on level 1 of complex aliens[0].x = rand()%SCREEN_WIDTH; aliens[0].y = 116 - 72; aliens[0].velocity = 2+rand()%4; aliens[0].current_frame = 0; aliens[0].counter = 0; aliens[0].width = 72; // set real size aliens[0].height = 80; aliens[0].scale = ((float)(1+rand()%20))/10; // scale from 0.1 to 2.0 // fix up feet so they still contact floor aliens[0].y+=(72 - aliens[0].scale*72); // alien on level 2 of complex aliens[1].x = rand()%SCREEN_WIDTH; aliens[1].y = 246 - 72; aliens[1].velocity = 2+rand()%4; aliens[1].current_frame = 0; aliens[1].counter = 0; aliens[1].width = 72; // set real size aliens[1].height = 80; aliens[1].scale = ((float)(1+rand()%20))/10; // scale from 0.1 to 2.0 // fix up feet so they still contact floor aliens[1].y+=(72 - aliens[1].scale*72); // alien on level 3 of complex aliens[2].x = rand()%SCREEN_WIDTH; aliens[2].y = 382 - 72; aliens[2].velocity = 2+rand()%4; aliens[2].current_frame = 0; aliens[2].counter = 0; aliens[2].width = 72; // set real size aliens[2].height = 80; aliens[2].scale = ((float)(1+rand()%20))/10; // scale from 0.1 to 2.0 // fix up feet so they still contact floor aliens[2].y+=(72 - aliens[2].scale*72); // now load the bitmap containing the alien imagery // then scan the images out into the surfaces of alien[0] // and copy then into the other two, be careful of reference counts! // load the 8-bit image if (!Load_Bitmap_File(&bitmap,"dedsp0.bmp")) return(0); // create each surface and load bits for (int index = 0; index < 3; index++) { // create surface to hold image aliens[0].frames[index] = DDraw_Create_Surface(72,80,0); // now load bits... Scan_Image_Bitmap(&bitmap, // bitmap file to scan image data from aliens[0].frames[index], // surface to hold data index, 0); // cell to scan image from } // end for index // unload the bitmap file, we no longer need it Unload_Bitmap_File(&bitmap); // now for the tricky part. There is no need to create more surfaces with the same // data, so I'm going to copy the surface pointers member for member to each alien // however, be careful, since the reference counts do NOT go up, you still only need // to release() each surface once! for (index = 0; index < 3; index++) aliens[1].frames[index] = aliens[2].frames[index] = aliens[0].frames[index]; // return success or failure or your own return code here return(1); } // end Game_Init
//jpg版本 IDirectDrawSurface7 * cls_sprite_surface::getSpriteSurfaceJPG(IDirectDrawSurface7 * lpdds,char * srcname,char * spritename,\ LPCSTR szJpg,int frame_num,bool debugflag){ //IDirectDrawSurface7 * templpdds; int loaded=0; //往素材队列放结构对象 int current_index=this->get_max_sprite_surface(0); JPEGINFO jinf; if (!loaded) LoadJPEG(FROM_FILE,szJpg,&lpdds,lpdd,jinf); //if (!loaded) // lpdds=DDLoadBitmap(lpdd,szBitmap); //往精灵画面数组递增1个元素 if(current_index==1000){ MessageBox(hwnd,"already have 100 sprite surfaces!","bug",MB_OK); } else{//如果是-1就是第一次了,加上就是下标0 // char buf[30]; // sprintf(buf,"当前最大画面管理器元素下标%d",current_index); // MessageBox(hwnd,buf,"",MB_OK); this->sprite_surface[current_index+1].used=1; this->sprite_surface[current_index+1].lpddsrc=lpdds; this->sprite_surface[current_index+1].srcname=srcname; this->sprite_surface[current_index+1].sprite_numframe=frame_num; //this->sprite_surface[current_index+1].used=1; } this->sfmgrtemp->sprite_group_name=spritename; this->sfmgrtemp->source_pic_name=szJpg; this->sfmgrtemp->lpdds=lpdds; int hasaname=0;//是不是已经有了组名 //查询szJpg JPEG图的长宽信息。 //HBITMAP hbm; //BITMAP bm; // LoadImage has some added functionality in Windows 95 that allows // you to load a bitmap from a file on disk. // hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, 0, 0, // LR_LOADFROMFILE|LR_CREATEDIBSECTION); // if (hbm == NULL){ // MessageBox(this->hwnd,"无法获取位图句柄","bug",MB_OK); // return NULL;// // } // GetObject(hbm, sizeof(bm), &bm); // get size of bitmap //创建指定数量的精灵动作画面 //int width=bm.bmWidth/frame_num;//横向依次读取n个精灵 int width=jinf.width; //alertme((int)bm.bmWidth); //alertme(frame_num); //alertme(width); //int height=bm.bmHeight; int height=jinf.height; //照搬windows GMP的精灵结构sprite,我把他封装到了我的SPRITE_SURFACE结构里了,再加2个成员以判断每一帧的长宽 this->sprite_surface[0].spritename=spritename; int i=current_index+1; this->sprite_surface[i].sprite.current_frame=0; this->sprite_surface[i].used=1; this->sprite_surface[i].sprite.x=0; this->sprite_surface[i].sprite.y=0; //this->sprite_surface[i].used=1; //必须加1,但创建画面的时候不要,不知道为什么?否则右面1像素显示不出! this->sprite_surface[i].sprite.theframe_width=width;//之后可以去修改,比如动作游戏,先默认为切出来的大小。 this->sprite_surface[i].sprite.theframe_height=height; //alertme(width); for (int j=0;j<frame_num;j++){ this->sprite_surface[i].sprite.frames[j]=DDraw_Create_Surface(width,height,3,1);//标记3是指使用系统内存 } //然后读入位图到各个精灵动作画面 RECT DestRect;RECT SrcRect; DestRect.top=0;DestRect.left=0;DestRect.right=width;DestRect.bottom=height; for (j=0;j<frame_num;j++){ //alertme("j是"); //alertme(j); SrcRect.top=0; SrcRect.left=0+j*width; //alertme("SrcRect.left是"); //alertme(SrcRect.left); SrcRect.right=SrcRect.left+width; //alertme("SrcRect.right是"); //alertme(SrcRect.right); SrcRect.bottom=height; //alertme("SrcRect.bottom是"); //alertme(SrcRect.bottom); if(FAILED(this->sprite_surface[i].sprite.frames[j]->Blt(&DestRect, // pointer to dest RECT lpdds, // pointer to source surface &SrcRect, // pointer to source RECT DDBLT_WAIT, &ddbltfx)))// pointer to DDBLTFX holding info { MessageBox(this->hwnd,"copy sprite surface failed!","info",MB_OK); } } //删除GDI对象 // if(!DeleteObject(hbm)){ // MessageBox(hwnd,"删除位图对象失败","",MB_OK); // } return sprite_surface[current_index+1].lpddsrc; }
IDirectDrawSurface7 * cls_sprite_surface::getSpriteSurface(IDirectDrawSurface7 * lpdds,char * srcname,char * spritename,\ LPCSTR szBitmap,int frame_num,bool debugflag){ //IDirectDrawSurface7 * templpdds; int loaded=0; //往素材队列放结构对象 int current_index=this->get_max_sprite_surface(0); #if 0 //查询画面管理列表,如果已经载入了,更新对应数据 this->iter=this->sprite_handler_list.begin(); while(iter!=this->sprite_handler_list.end()){ if ((*iter)->source_pic_name==szBitmap){ // MessageBox(hwnd,"loaded!","info",MB_OK); loaded=1; return (*iter)->lpdds;//如果读入了直接返回画面 break; } ++iter; } #endif if (!loaded) lpdds=DDLoadBitmap(lpdd,szBitmap); //往精灵画面数组递增1个元素 if(current_index==1000){ MessageBox(hwnd,"already have 100 sprite surfaces!","bug",MB_OK); } else{//如果是-1就是第一次了,加上就是下标0 // char buf[30]; // sprintf(buf,"当前最大画面管理器元素下标%d",current_index); // MessageBox(hwnd,buf,"",MB_OK); this->sprite_surface[current_index+1].used=1; this->sprite_surface[current_index+1].lpddsrc=lpdds; this->sprite_surface[current_index+1].srcname=srcname; this->sprite_surface[current_index+1].sprite_numframe=frame_num; //this->sprite_surface[current_index+1].used=1; } this->sfmgrtemp->sprite_group_name=spritename; this->sfmgrtemp->source_pic_name=szBitmap; this->sfmgrtemp->lpdds=lpdds; int hasaname=0;//是不是已经有了组名 #if 0 char itoabuf[6]; itoa(current_index+1,itoabuf,10); this->sfmgrtemp->sprite_surface_array_indexes=itoabuf;//?? /* char buf[20]; sprintf(buf,"%s", this->sfmgrtemp->sprite_surface_array_indexes); MessageBox(this->hwnd,buf,"the info",MB_OK);*/ //往画面管理链表里添加1个节点,如果之前有节点的组名和当前spritename是一样的,就更新成这样1|2 //list<SF_MGR * >::iterator iter; iter=this->sprite_handler_list.begin(); while(iter!=this->sprite_handler_list.end()){ if((*iter)->sprite_group_name==spritename){ std::string a,b; a=(*iter)->sprite_surface_array_indexes; itoa(current_index+1,itoabuf,10); b=itoabuf; a+="|"; a+=b; (*iter)->sprite_surface_array_indexes=(LPCSTR)a.c_str(); hasaname=1; break; } ++iter; } if(!hasaname) this->sprite_handler_list.push_back(sfmgrtemp); #endif //查询szBitmap位图的长宽信息。 HBITMAP hbm; BITMAP bm; // LoadImage has some added functionality in Windows 95 that allows // you to load a bitmap from a file on disk. hbm = (HBITMAP)LoadImage(NULL, szBitmap, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE|LR_CREATEDIBSECTION); if (hbm == NULL){ MessageBox(this->hwnd,"无法获取位图句柄","bug",MB_OK); return NULL;// } GetObject(hbm, sizeof(bm), &bm); // get size of bitmap //创建指定数量的精灵动作画面 int width=bm.bmWidth/frame_num;//横向依次读取n个精灵 //alertme((int)bm.bmWidth); //alertme(frame_num); //alertme(width); int height=bm.bmHeight; //照搬windows GMP的精灵结构sprite,我把他封装到了我的SPRITE_SURFACE结构里了,再加2个成员以判断每一帧的长宽 this->sprite_surface[0].spritename=spritename; int i=current_index+1; this->sprite_surface[i].sprite.current_frame=0; this->sprite_surface[i].used=1; this->sprite_surface[i].sprite.x=0; this->sprite_surface[i].sprite.y=0; //this->sprite_surface[i].used=1; //必须加1,但创建画面的时候不要,不知道为什么?否则右面1像素显示不出! this->sprite_surface[i].sprite.theframe_width=width;//之后可以去修改,比如动作游戏,先默认为切出来的大小。 this->sprite_surface[i].sprite.theframe_height=height; #if 0 if (debugflag){//debug alertme(i); this->sprite_surface[i].sprite.theframe_width=44; this->sprite_surface[i].sprite.theframe_height=38; } #endif for (int j=0;j<frame_num;j++){ this->sprite_surface[i].sprite.frames[j]=DDraw_Create_Surface(width,height,3,1);//标记3是指使用系统内存 } #if 0 if (debugflag) alertme(i);//debug if (debugflag){//debug alertme(this->sprite_surface[i].sprite.theframe_width); alertme(width); alertme(this->sprite_surface[i].sprite.theframe_height); alertme(height); //this->sprite_surface[i].sprite.theframe_width=44; //this->sprite_surface[i].sprite.theframe_height=38; } #endif //然后读入位图到各个精灵动作画面 RECT DestRect;RECT SrcRect; DestRect.top=0;DestRect.left=0;DestRect.right=width;DestRect.bottom=height; for (j=0;j<frame_num;j++){ //alertme("j是"); //alertme(j); SrcRect.top=0; SrcRect.left=0+j*width; //alertme("SrcRect.left是"); //alertme(SrcRect.left); SrcRect.right=SrcRect.left+width; //alertme("SrcRect.right是"); //alertme(SrcRect.right); SrcRect.bottom=height; //alertme("SrcRect.bottom是"); //alertme(SrcRect.bottom); if(FAILED(this->sprite_surface[i].sprite.frames[j]->Blt(&DestRect, // pointer to dest RECT lpdds, // pointer to source surface &SrcRect, // pointer to source RECT DDBLT_WAIT, &ddbltfx)))// pointer to DDBLTFX holding info { MessageBox(this->hwnd,"copy sprite surface failed!","info",MB_OK); } } //删除GDI对象 if(!DeleteObject(hbm)){ MessageBox(hwnd,"删除位图对象失败","",MB_OK); } return sprite_surface[current_index+1].lpddsrc; }
int Game_Init(void *parms = NULL, int num_parms = 0) { // this is called once after the initial window is created and // before the main event loop is entered, do all your initialization // here // create IDirectDraw interface 7.0 object and test for error if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL))) return(0); // set cooperation to full screen if (FAILED(lpdd->SetCooperativeLevel(main_window_handle, DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT))) return(0); // set display mode to 640x480x24 if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0))) return(0); // clear ddsd and set size DDRAW_INIT_STRUCT(ddsd); // enable valid fields ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; ddsd.dwBackBufferCount = 1; // // request primary surface ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_COMPLEX | DDSCAPS_FLIP; // create the primary surface if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL))) return(0); ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER; if(FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback))) return 0; // 把主屏和缓冲屏都填充为黑色初始化 DDraw_Fill_Surface(lpddsprimary, _RGB32BIT(0, 0,0,0)); DDraw_Fill_Surface(lpddsback, _RGB32BIT(0, 0,0,0)); // load the 24-bit image char* bmp_wc = "WarCraft24.bmp"; char* bmp_b8 = "bitmap8b.bmp"; char* bmp_b24 = "bitmap24.bmp"; char* bmp_b24e = "bitmap24_edit.bmp"; char* bmp_mo24 = "mosaic-600x.bmp"; char* bmp_ni24 = "nightelf-640x.bmp"; char* bmp_alley24 = "alley8_24bit.bmp"; // 载入背景图片 if (!Load_Bitmap_File(&bitmap, bmp_ni24)) return(0); // 创建背景表面、但实际上不是直接用背景表面来显示的、而是拷贝去缓冲表面和人物动作混合 // 后才一次性打到显示表面 // 这里头两个参数是指在屏幕的高和宽、第二个是指表面建立的地点、0指在显存建立、其它表示在 // 系统内存建立、当然速度自然是在显存建立快了、最后一个参数是是否设置为色彩键、这里设定为-1 // 也就是不设定任何色彩过滤、因为这个是背景表面、所以不需要任何透明的色彩键 lpddsbackground = DDraw_Create_Surface(640,480,0,-1); // 把bmp的内容拷贝至缓冲表面中 Bmp2Surface(lpddsbackground, SCREEN_WIDTH, SCREEN_HEIGHT); // 从现在开始创建人物动作了 if (!Load_Bitmap_File(&bitmap, "Dedsp0_24bit.bmp")) return(0); // seed random number generator // GetTickCount是一个系统启动至今的毫秒数、 // 配合srandg来产生一个随机数 srand(GetTickCount()); // initialize all the aliens // alien on level 1 of complex // //系统在调用rand()之前都会自动调用srand(),如果用户在rand()之前曾调用过srand()给参数seed指定了一个值, //那么rand()就会将seed的值作为产生伪随机数的初始值; //而如果用户在rand()前没有调用过srand(),那么rand()就会自动调用srand(1),即系统默认将1作为伪随机数的初始值。 //所以前面要调用一次srand来确保以下调用rand()的值会产生不同 // aliens[0].x = rand()%SCREEN_WIDTH; aliens[0].y = 116 - 72; aliens[0].velocity = 2+rand()%4; aliens[0].current_frame = 0; aliens[0].counter = 0; // alien on level 2 of complex aliens[1].x = rand()%SCREEN_WIDTH; aliens[1].y = 246 - 72; aliens[1].velocity = 2+rand()%4; aliens[1].current_frame = 0; aliens[1].counter = 0; // alien on level 3 of complex aliens[2].x = rand()%SCREEN_WIDTH; aliens[2].y = 382 - 72; aliens[2].velocity = 2+rand()%4; aliens[2].current_frame = 0; aliens[2].counter = 0; // now load the bitmap containing the alien imagery // then scan the images out into the surfaces of alien[0] // and copy then into the other two, be careful of reference counts! // 现在开始载入人物的动画帧图片了 if (!Load_Bitmap_File(&bitmap,"Dedsp0_24bit.bmp")) return(0); // create each surface and load bits // 初始化异形0号的三个动作帧表面、 // 其实、所有的异形动作帧表面都一样的、所以没有必要为每个异形都创建相应的动作帧、 // 所以其它异形的动作帧都指向这个异形0号的动作帧就可以了 for (int index = 0; index < 3; index++) { // create surface to hold image aliens[0].frames[index] = DDraw_Create_Surface(72,80,0); // now load bits... Scan_Image_Bitmap(&bitmap, // bitmap file to scan image data from aliens[0].frames[index], // surface to hold data index, 0); // cell to scan image from } // end for index // unload the bitmap file, we no longer need it Unload_Bitmap_File(&bitmap); // now for the tricky part. There is no need to create more surfaces with the same // data, so I'm going to copy the surface pointers member for member to each alien // however, be careful, since the reference counts do NOT go up, you still only need // to release() each surface once! for (index = 0; index < 3; index++) aliens[1].frames[index] = aliens[2].frames[index] = aliens[0].frames[index]; // return success or failure or your own return code here return(1); } // end Game_Init