- ///
- int Scan_Image_Bitmap(BITMAP_FILE_PTR bitmap, //位图文件扫描图像的数据来源
- LPDIRECTDRAWSURFACE7 lpdds, // 锁定表面用的
- int cx, int cy) // 扫描图像的位置
- {
- // this function extracts a bitmap out of a bitmap file
- UCHAR *source_ptr, // working pointers
- *dest_ptr;
- DDSURFACEDESC2 ddsd; // direct draw surface description
- // get the addr to destination surface memory
- // set size of the structure
- ddsd.dwSize = sizeof(ddsd);
- // lock the display surface
- lpdds->Lock(NULL,
- &ddsd,
- DDLOCK_WAIT | DDLOCK_SURFACEMEMORYPTR,
- NULL);
- // 计算开始扫描的位置
- cx = cx*(ddsd.dwWidth*4) ;
- cy = cy*(ddsd.dwHeight*4) ;
- //ddsd.dwWidth 以像素计算的表面 宽度
- //ddsd.dwHeight 以像素计算的表面 高度
- //表面占用字节= 宽*高*位深度占用字节
- //8位=1字节 16位=2字节 32位=4字节
- // 提取位图数据
- source_ptr = bitmap->buffer + cy*bitmap->bitmapinfoheader.biWidth+cx;
- //bitmap->buffer 指向位图数据的指针 等于数据开始的位置
- //bitmap->bitmapinfoheader.biWidth 位图的宽度,单位是像素,但缓冲区的定位是字节
- //32位图 每像素占用4字节
- //
- //
- // assign a pointer to the memory surface for manipulation
- dest_ptr = (UCHAR *)ddsd.lpSurface;
- for (int index_y=0; index_y < ddsd.dwHeight*4; index_y++)
- {
- // 复制下一行的数据到 目的地
- memcpy(dest_ptr, source_ptr, ddsd.dwWidth*4);//32位下每像素占4字节 gwidth = ddsd.dwWidth*4;
- // advance pointers
- dest_ptr += (ddsd.lPitch); // 显示模式的水平内存艰巨,即每行的字节数 32位下等于ddsd.dwWidth*4
- source_ptr += bitmap->bitmapinfoheader.biWidth*4;//32位下每像素占4字节
- //bitmap->bitmapinfoheader.biWidth 位图的宽度,单位是像素,
- } // end for index_y
- // unlock the surface
- lpdds->Unlock(NULL);
- // return success
- return(1);
- } // end Scan_Image_Bitmap
- ///
- ///
- LRESULT CALLBACK WindowProc(HWND hwnd,
- UINT msg,
- WPARAM wparam,
- LPARAM lparam)
- {
- // this is the main message handler of the system
- PAINTSTRUCT ps; // used in WM_PAINT
- HDC hdc; // handle to a device context
- char buffer[80]; // used to print strings
- // what is the message
- switch(msg)
- {
- case WM_CREATE:
- {
- // do initialization stuff here
- // return success
- return(0);
- } break;
- case WM_PAINT:
- {
- // simply validate the window
- hdc = BeginPaint(hwnd,&ps);
- // end painting
- EndPaint(hwnd,&ps);
- // return success
- return(0);
- } break;
- case WM_DESTROY:
- {
- // kill the application, this sends a WM_QUIT message
- PostQuitMessage(0);
- // return success
- return(0);
- } break;
- default:break;
- } // end switch
- // process any messages that we didn't take care of
- return (DefWindowProc(hwnd, msg, wparam, lparam));
- } // end WinProc
- ///
- int Draw_Text_GDI(char *text, int x,int y,COLORREF color, LPDIRECTDRAWSURFACE7 lpdds)
- {
- // this function draws the sent text on the sent surface
- // using color index as the color in the palette
- HDC xdc; // the working dc
- // get the dc from surface
- if (FAILED(lpdds->GetDC(&xdc)))
- return(0);
- // set the colors for the text up
- SetTextColor(xdc,color);
- // set background mode to transparent so black isn't copied
- SetBkMode(xdc, TRANSPARENT);
- // draw the text a
- TextOut(xdc,x,y,text,strlen(text));
- // release the dc
- lpdds->ReleaseDC(xdc);
- // return success
- return(1);
- } // end Draw_Text_GDI
- ///
- int Game_Main(void *parms = NULL, int num_parms = 0)
- {
- // 这是主循环的游戏,做所有你在这里处理
- // 查找适当的步行序列
- static int animation_seq[4] = {0,1,0,2};
- //开火序列
- static int animation_fire[4] ={0,1,2,1};
- //火球
- static int frie=6;
- int index; // 步行循环变量
- // 确保这不是再次执行
- if (window_closed)
- return(0);
- // 如果用户按下ESC 则立即发送 WM_CLOSE 关闭游戏
- if (KEYDOWN(VK_ESCAPE))
- {
- PostMessage(main_window_handle,WM_CLOSE,0,0);
- window_closed = 1;
- } // end if
- // 从后备缓冲中复制背景
- DDraw_Draw_Surface(lpddsbackground,0,0, SCREEN_WIDTH,SCREEN_HEIGHT, lpddsback,0);
- //自动控制
- for (index=0; index < 2; index++)
- {
- // 向右移动每个对象在给定速度
- aliens[index].x++; // =aliens[index].velocity;
- //测试是否进入屏幕的边缘,设置循环
- if (aliens[index].x > SCREEN_WIDTH)
- aliens[index].x = -40;//位移出屏幕外半个身位,重新进入时不突然
- // 机器人前进
- //aliens[index].velocity 移动速度
- if (++aliens[index].counter >= (8 - aliens[index].velocity)) // aliens[index].velocity=2+0到3 即 2-5 8-2=6 8-5=3
- {
- //aliens[index].counter 动画占用时间
- //复位 counter
- aliens[index].counter = 0;
- // 前进到下一帧
- if (++aliens[index].current_frame > 3)
- aliens[index].current_frame = 0;
- }// end if
- } // end for index
- std::list
::iterator iter=aliens_amm.begin();//指向容器第一个元素 - for(iter=aliens_amm.begin();iter!=aliens_amm.end();)
- {
- if(iter->life==true)
- iter->x+=iter->velocity;
- if (iter->x > SCREEN_WIDTH )
- {
- iter->x = -40;//位移出屏幕外半个身位,重新进入时不突然
- iter->life=false;
- if(iter!=aliens_amm.end())
- iter=aliens_amm.erase(iter);
- //aliens_amm.pop_front();//删除最先发射的×××
- }
- else iter++;
- }
- if((KEYDOWN(65)|KEYDOWN(97))) //按下A开火
- {
- if(++aliens[2].counter_animation_fire>=5) // 开火动画时间
- {
- //复位计数器
- aliens[2].counter_animation_fire=0;//动画时间为0
- //前进到下一帧
- if (++aliens[2].current_animation_fire_frames>3)//当前帧大于3
- {
- aliens[2].current_animation_fire_frames=0;
- //动态插入×××链
- aa.life=true;
- aa.x=aliens[2].x + 40;
- aa.y=aliens[2].y+5;
- aa.velocity=6;
- aliens_amm.push_back(aa);
- }
- }
- DDraw_Draw_Surface( aliens[2].animation_fire_frames[ animation_fire [ aliens[2].current_animation_fire_frames ] ], // 要画的源表面
- aliens[2].x, aliens[2].y, // 要绘制的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要画的目标表面
- //设置弹药数据
- for(iter=aliens_amm.begin();iter!=aliens_amm.end();iter++)
- {
- //画出所有弹药
- DDraw_Draw_Surface( aliens[2].fire_frames, // 要画的源表面
- iter->x, iter->y, // 要绘制的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要画的目标表面
- }
- }//end if
- else if ( KEYDOWN(VK_RIGHT) )//向右移动
- {
- aliens[2].x++;
- //测试是否进入屏幕的边缘,设置循环
- if(aliens[2].x>SCREEN_WIDTH)
- aliens[2].x=-40;
- if (++aliens[2].counter >=(8-aliens[2].velocity)) // aliens[index].velocity=2+0到3 即 2-5 8-2=6 8-5=3
- {
- //复位计数器
- aliens[2].counter=0;//动画时间为0
- //前进到下一帧
- if (++aliens[2].current_frame>3)//当前帧大于3
- aliens[2].current_frame=0;
- }//end if
- // 画手动控制的机器人
- DDraw_Draw_Surface( aliens[2].frames[ animation_seq [ aliens[2].current_frame ] ], // 要画的源表面
- aliens[2].x, aliens[2].y, // 要绘制的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要画的目标表面
- /*
- *LPDIRECTDRAWSURFACE7 frames[3]; 主表面接口绘图
- *aliens[index].frames[ index]三帧的动画完整步行周期
- *animation_seq[index] = {0,1,0,2};
- *aliens[index].current_frame]// 当前帧的动画
- */
- }
- else
- { //当没有按下开火或者移动指令
- // 画手动控制的机器人
- DDraw_Draw_Surface( aliens[2].frames[ animation_seq [ aliens[2].current_frame ] ], // 要画的源表面
- aliens[2].x, aliens[2].y, // 要绘制的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要画的目标表面
- }
- for(iter=aliens_amm.begin();iter!=aliens_amm.end();iter++)
- {
- if(iter->life==true)
- {
- //弹药
- DDraw_Draw_Surface( aliens[2].fire_frames, // 要画的源表面
- iter->x, iter->y, // 要绘制的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要画的目标表面
- }
- }
- // 画出1.2行的机器人
- for (index=0; index < 2; index++)
- {
- // 画对象
- DDraw_Draw_Surface( aliens[index].frames[ animation_seq [ aliens[index].current_frame ] ], // 要画的源表面
- aliens[index].x, aliens[index].y, // 要绘制的位置
- 74,82,// 源表面的尺寸
- lpddsback);// 要画的目标表面
- /*
- *LPDIRECTDRAWSURFACE7 frames[3]; 主表面接口绘图
- *aliens[index].frames[ index]三帧的动画完整步行周期
- *animation_seq[index] = {0,1,0,2};
- *aliens[index].current_frame]// 当前帧的动画
- */
- } // end for index
- //开火动画 按下A或者a
- // 将主表面与后备缓冲表面切换 注意,调用前要确保主表面和后备缓冲表面都必须 被解锁
- while (FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT)));
- // wait a sec
- Sleep(30);
- // return success or failure or your own return code here
- return(1);
- } // end Game_Main
- 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
- int index;
- // 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 640x480x32
- 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;
- // 获取后备缓冲区的指针
- if (FAILED(lpddsprimary->GetAttachedSurface(&ddsd.ddsCaps, &lpddsback)))
- 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);
- // 读取位图
- if (!Load_Bitmap_File(&bitmap,ALLEY))
- return(0);
- // 清空表面
- DDraw_Fill_Surface(lpddsprimary,0);
- DDraw_Fill_Surface(lpddsback,0);
- // create the buffer to hold the background
- lpddsbackground = DDraw_Create_Surface(640,480,0);
- // copy the background bitmap p_w_picpath to the background surface
- // 锁定表面
- lpddsbackground->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);
- //获取主表面的显示指针
- UCHAR *p_w_picpath_buffer = (UCHAR *)ddsd.lpSurface;
- // 如果内存是线性的
- if (ddsd.lPitch == (SCREEN_WIDTH*4)) //32 位下每像素4字节 640X4
- {
- // copy memory from double buffer to primary buffer
- memcpy((void *)p_w_picpath_buffer, (void *)bitmap.buffer, SCREEN_WIDTH*SCREEN_HEIGHT*4);
- } // end if
- else
- { // non-linear
- // make copy of source and destination addresses
- UCHAR *dest_ptr = p_w_picpath_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*4);
- // 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
- // 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;
- // 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].current_animation_fire_frames=0;
- aliens[2].counter = 0;
- aliens[2].counter_animation_fire=0;
- //初始化弹药
- // 现在加载包含外星人的位图
- // 然后扫描图像到 alien[0]的表面
- // 然后负责到另外2个那里, 但要小心引用计数!
- // 读取32位图
- if (!Load_Bitmap_File(&bitmap,DEDSP))
- return(0);
- // 生成动画每帧的表面
- for ( index = 0; index < 3; index++)
- {
- // 创建存储图像的表面
- aliens[0].frames[index] = DDraw_Create_Surface(74,82,DDSCAPS_VIDEOMEMORY); //DDSCAPS_VIDEOMEMORY 创建在显存中
- // 加载位图
- Scan_Image_Bitmap(&bitmap, // 要加载的位图文件数据来源
- aliens[0].frames[index], // 保存数据的表面
- index, 0); // 扫描图像的单元 x,y 实际扫描是X*74 即一格图
- } // end for index
- //生成开火动画每帧的表面
- for ( index = 0; index < 3; index++)
- {
- // 创建存储图像的表面
- aliens[2].animation_fire_frames[index] = DDraw_Create_Surface(74,82,DDSCAPS_VIDEOMEMORY); //DDSCAPS_VIDEOMEMORY 创建在显存中
- // 加载位图
- Scan_Image_Bitmap(&bitmap, // 要加载的位图文件数据来源
- aliens[2].animation_fire_frames[index], // 保存数据的表面
- index, 1); // 扫描图像的单元 x,y坐标 实际扫描是X*74 即一格图 y*82
- } // end for index
- //生成存储火球×××的表面
- // 创建存储图像的表面
- aliens[2].fire_frames = DDraw_Create_Surface(74,82,DDSCAPS_VIDEOMEMORY); //DDSCAPS_VIDEOMEMORY 创建在显存中
- // 加载位图
- Scan_Image_Bitmap(&bitmap, // 要加载的位图文件数据来源
- aliens[2].fire_frames, // 保存数据的表面
- 3, 1); // 扫描图像的单元 x,y坐标 实际扫描是X*74 即一格图 y*82
- // 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