⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 basicelectric.dpr

📁 Delphi7编程80例(完全版)
💻 DPR
📖 第 1 页 / 共 2 页
字号:
program basicElectric;

uses
  Windows,MMSystem,Messages,OpenGL,SysUtils;


const
  APP_TITLE = 'OpenGL小游戏_源自Jan Horn';
  FPS_TIMER = 1;                     // 计算每秒的帧数
  FPS_INTERVAL = 1000;               // 每秒计算一次帧数
  STEPS = 32;

var
  h_Wnd  : HWND;                     // 全局窗口句柄
  h_DC   : HDC;                      // 全局设备环境变量
  h_RC   : HGLRC;                    // OpenGL渲染设备变量
  SndHandle : THandle;               // 声音设备
  keys : Array[0..255] of Boolean;   // 处理击键事件
  FPSCount : Integer = 0;            //每秒帧数的计算器
  ElapsedTime : Integer;             //帧与帧之间的间隔
  background : glUint;               //Opengl材质变量
  SparkCount : Integer;              //闪电次数
  y : Array[0..STEPS] of glFloat;    //闪电的y和z轴的位置

{$R sound.res}

 procedure SwapRGB(data : Pointer; Size : Integer);
 asm       //将位图格式从BGR转化为RGB
  mov ebx, eax
  mov ecx, size

  @@loop :
  mov al,[ebx+0]
  mov ah,[ebx+2]
  mov [ebx+2],al
  mov [ebx+0],ah
  add ebx,3
  dec ecx
  jnz @@loop
end;

// 加载位图
procedure LoadBitmap(Filename: String; out Width: Cardinal; out Height: Cardinal; out pData: Pointer);
var
  FileHeader: TBITMAPFILEHEADER;
  InfoHeader: TBITMAPINFOHEADER;
  Palette: array of RGBQUAD;
  BitmapFile: THandle;
  BitmapLength: LongWord;
  PaletteLength: LongWord;
  ReadBytes: LongWord;
begin
  BitmapFile := CreateFile(PChar(Filename), GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
  if (BitmapFile = INVALID_HANDLE_VALUE) then begin
    MessageBox(0, PChar('打开错误' + Filename), PChar('错误提示1'), MB_OK);
    Exit;
  end;
  // 获取位图头信息
  ReadFile(BitmapFile, FileHeader, SizeOf(FileHeader), ReadBytes, nil);
  ReadFile(BitmapFile, InfoHeader, SizeOf(InfoHeader), ReadBytes, nil);
  //获取调色板信息
  PaletteLength := InfoHeader.biClrUsed;
  SetLength(Palette, PaletteLength);
  ReadFile(BitmapFile, Palette, PaletteLength, ReadBytes, nil);
  if (ReadBytes <> PaletteLength) then begin
    MessageBox(0, PChar('读取调色板错误'), PChar('错误提示2'), MB_OK);
    Exit;
  end;
  Width := InfoHeader.biWidth;
  Height := InfoHeader.biHeight;
  BitmapLength := InfoHeader.biSizeImage;
  if BitmapLength = 0 then
    BitmapLength := Width * Height * InfoHeader.biBitCount Div 8;
  // 获取真实象素数据
  GetMem(pData, BitmapLength);
  ReadFile(BitmapFile, pData^, BitmapLength, ReadBytes, nil);
  if (ReadBytes <> BitmapLength) then begin
    MessageBox(0, PChar('位图文件数据读取错误'), PChar('错误提示3'), MB_OK);
    Exit;
  end;
  CloseHandle(BitmapFile);
  SwapRGB(pData, Width*Height);  // 位图信息保存为BGR模式,而不是RGB模式
end;

//加载BMP材质
function LoadTexture(Filename: String; var Texture: GLuint): Boolean;
var
  pData: Pointer;
  Width: LongWord;
  Height: LongWord;
begin
  pData :=nil;
  LoadBitmap(Filename, Width, Height, pData);
  if (Assigned(pData)) then
    Result := True
  else
  begin
    Result := False;
    MessageBox(0, PChar('不能打开文件:' + filename), '加载材质', MB_OK);
    Halt(1);
  end;
  glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);  //材质和对象背景混合
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  gluBuild2DMipmaps(GL_TEXTURE_2D, 3, Width, Height, GL_RGB, GL_UNSIGNED_BYTE, pData);
end;

procedure glDraw();   //绘制真实场景
var I, J : Integer;
    rnd  : glFloat;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);    // 清除屏幕和深度缓冲区
  glLoadIdentity();                                       // 重新设置视图
  glTranslatef(0.0, 0.0, -3);
  // 画背景
  glEnable(GL_TEXTURE_2D);
  glDisable(GL_BLEND);
  glColor3f(Random(10)/10,0.5,1);    //场景颜色不断变化
  glBegin(GL_QUADS);
    glTexCoord(0, 0); glVertex(-4, -4, -5);
    glTexCoord(1, 0); glVertex( 4, -4, -5);
    glTexCoord(1, 1); glVertex( 4,  4, -5);
    glTexCoord(0, 1); glVertex(-4,  4, -5);
  glEnd;
  glrotate(ElapsedTime/40, 0, 1, 0);  // 旋转场景
  for I :=1 to STEPS-2 do      // 计算新的Y坐标
  begin
    y[I] :=y[I] + 0.1*(random-0.5);
    if y[I] > y[I-1] + 0.075 then y[I] :=y[I-1]+0.075;
    if y[I] < y[I-1] - 0.075 then y[I] :=y[I-1]-0.075;
    if y[I] > y[I+1] + 0.075 then y[I] :=y[I+1]+0.075;
    if y[I] < y[I+1] - 0.075 then y[I] :=y[I+1]-0.075;
    if y[I] >  0.5 then y[I] :=0.5;
    if y[I] < -0.5 then y[I] :=-0.5;
  end;
  // 绘制闪电
  glDisable(GL_TEXTURE_2D);
  glEnable(GL_BLEND);
  glColor3f(Random(10)/10, Random(10)/20+0.3, 0.6); //闪电颜色不断变化
  for I :=1 to SparkCount do
  begin
    glBegin(GL_TRIANGLE_STRIP);
    for J :=0 to STEPS-1 do
    begin
      rnd :=0.04*(Random-0.5);
      glVertex3f(-1 + 2*J/STEPS + rnd, -0.01 + y[J] + rnd, rnd);
      glVertex3f(-1 + 2*J/STEPS + rnd, +0.01 + y[J] + rnd, rnd);
    end;
    glEnd();
  end;
end;

procedure glInit(); //初始化Opengl
begin
  glClearColor(0.0, 0.0, 0.0, 0.0); 	     // 指定Opengl背景颜色
  glShadeModel(GL_SMOOTH);                 // 指定平滑颜色阴影
  glClearDepth(1.0);                       // 深度缓冲设置
  glEnable(GL_DEPTH_TEST);                 // 激活深度缓冲
  glDepthFunc(GL_LESS);		                 //指定深度测试类型
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);   //实际视角计算
  glEnable(GL_TEXTURE_2D);                 // 激活材质映射
  LoadTexture('background.bmp', background); //可以加载自定义位图文件
  //使闪电的起点和终点都指向0
  SparkCount :=16;
  y[0] :=0.0;
  y[STEPS-1] :=0.0;
end;

procedure glResizeWnd(Width, Height : Integer);  //处理窗口事件
begin
  if (Height = 0) then
    Height := 1;
  glViewport(0, 0, Width, Height);    // 设置OpenGL视口
  glMatrixMode(GL_PROJECTION);        // 改变工程的矩阵模式
  glLoadIdentity();                   // 重新设置视图
  gluPerspective(45.0, Width/Height, 1.0, 100.0);  //进行视角计算
  glMatrixMode(GL_MODELVIEW);         // 返回模型视图矩阵
  glLoadIdentity();                   // 重新设置视图
end;


//处理键盘信息
procedure ProcessKeys;
begin
  if Keys[VK_ADD] then       //处理"+"键
  begin
    Inc(SparkCount);
    Keys[VK_ADD] :=FALSE;
  end;
  if Keys[VK_SUBTRACT] then //处理"-"键
  begin
    Dec(SparkCount);
    if SparkCount < 1 then
      SparkCount :=1;
    Keys[VK_SUBTRACT] :=FALSE;
  end;
end;

//处理程序信息
function WndProc(hWnd: HWND; Msg: UINT;  wParam: WPARAM;  lParam: LPARAM): LRESULT; stdcall;
begin
  case (Msg) of
    WM_CLOSE:        //程序关闭
      begin
        PostQuitMessage(0);
        Result := 0
      end;
    WM_KEYDOWN:       // 处理"↓"键
      begin
        keys[wParam] := True;
        Result := 0;
      end;
    WM_KEYUP:         // 处理"↑"键
      begin
        keys[wParam] := False;
        Result := 0;
      end;
    WM_SIZE:          // 重新设置窗口大小
      begin
        glResizeWnd(LOWORD(lParam),HIWORD(lParam));
        Result := 0;
      end;
    WM_TIMER :                     // 设置定时器
      begin
        if wParam = FPS_TIMER then
        begin
          FPSCount :=Round(FPSCount * 1000/FPS_INTERVAL);   // 计算帧数
          SetWindowText(h_Wnd, PChar(APP_TITLE + ',[' + IntToStr(FPSCount) + ' 帧/秒],线程=' + intToStr(SparkCount)));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -