黑客帝国中的字符雨特效

来源:互联网 发布:python字典的get方法 编辑:程序博客网 时间:2024/04/29 02:38

那天在论坛里看见篇帖子说是做黑客帝国中的字符雨特效

那个屏保我也用过,确实很酷,学了这么长时间的OPENGL,现在想想实现其实也不算太难

于是回来自己写了这个代码,本打算用3D字符来实现,但仔细一想,还是用贴图来的又快又爽

里面又引用了Textures单元(这个单元太好用了!),这次索性贴出来,想用的兄弟到我的BLOG里找吧

简单说说代码

其实就是个粒子系统,每个粒子带一个贴图,贴图是我自己画的,不过效果还凑合,我想那个屏保里的随机数的感觉,大概是用了几张贴图,然后随机的换吧

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, OPENGL, Textures;
type

  TParticle = record //粒子
    active: Boolean; //激活
    life: GLfloat; //生命期
    fade: GLfloat; //衰减
    r, g, b: GLfloat; //颜色
    x, y, z: GLfloat; //坐标
    xi, yi, zi: GLfloat; //方向和速度
  end;

  //粒子类
  TParticles = class
    ParticleSpeed: GLfloat;
    ParticleNum: Integer;
    Particle: array of TParticle;
  public
    constructor Create(Num: Integer = 100);
    destructor Destroy; override;
    procedure ParticleBorn(index: Integer);
    procedure ParticleOld(index: Integer);
    procedure ParticleDead(index: Integer);
    procedure ParticleDraw(index: Integer);
  end;

  TForm1 = class(TForm)
    procedure FormResize(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    h_RC: HGLRC;
    h_DC: HDC;
    Keys: array[0..255] of Boolean;
    Particles: TParticles;
    Texture: GLuint;
    rx, ry, rz: GLfloat;
  public
    constructor Create(Aowner: TComponent); override;
    destructor Destroy; override;
    procedure SetRCToDC();
    procedure glInit();
    procedure glResize;
    procedure glDraw;
    procedure MainLoop(Sender: TObject; var Done: Boolean);
    procedure Initparticle;
  end;

var
  Form1: TForm1;

procedure glBindTexture(Target: GLenum; Texture: GLuint); stdcall; external opengl32; //纹理绑定

implementation

{$R *.dfm}

constructor TForm1.Create(Aowner: TComponent);
begin
  inherited;
  SetRCToDC;
  Randomize;
  glInit;
  Application.OnIdle := MainLoop;
end;

destructor TForm1.Destroy;
begin
  wglMakeCurrent(0, 0);
  wglDeleteContext(h_RC);
  inherited;
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  glResize;
end;

procedure TForm1.glDraw;
var
  i: integer;
begin
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
  glLoadIdentity();
  glTranslatef(0, 0, -20);
  glRotatef(rx, 1, 0, 0);
  glRotatef(ry, 0, 1, 0);
  glRotatef(rz, 0, 0, 1);
  with Particles do
    for i := 0 to ParticleNum - 1 do
      if Particle[i].active then
        begin
          ParticleDraw(i);
          ParticleOld(i);
        end;
end;

procedure TForm1.glInit;
begin
  glShadeModel(GL_SMOOTH);
  glClearColor(0.0, 0.0, 0.0, 0.0);
  glClearDepth(1.0);
  glDisable(GL_DEPTH_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
  glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);
  glEnable(GL_TEXTURE_2D);
  LoadTexture('../Pic/01.bmp', Texture, False);
    glBindTexture(GL_TEXTURE_2D, Texture);
  Particles := TParticles.Create(200);
  Initparticle;
end;

procedure TForm1.glResize;
begin
  glViewport(0, 0, Width, Height);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  gluPerspective(45.0, Width / Height, 0, 1000);
  glMatrixMode(GL_MODELVIEW);
end;

procedure TForm1.Initparticle;
var
  i: Integer;
begin
  with Particles do
    for i := 0 to ParticleNum - 1 do
      ParticleBorn(i);
end;

procedure TForm1.MainLoop(Sender: TObject; var Done: Boolean);
begin
  Done := False;
  glDraw();
  SwapBuffers(h_DC);
  if Keys[VK_ESCAPE] then
    Close;
  if Keys[Ord('X')] then
    rx := rx + 0.1;
  if Keys[Ord('Y')] then
    ry := ry + 0.1;
  if Keys[Ord('Z')] then
    rz := rz + 0.1;

end;

procedure TForm1.SetRCToDC;
var
  pfd: TPIXELFORMATDESCRIPTOR;
  pf: Integer;
begin
  h_DC := GetDC(Handle);
  with pfd do
    begin
      nSize := SizeOf(pfd);
      nVersion := 1;
      dwFlags := PFD_DRAW_TO_WINDOW
        or PFD_SUPPORT_OPENGL
        or PFD_DOUBLEBUFFER;
      iPixelType := PFD_TYPE_RGBA;
      cColorBits := 16;
      cDepthBits := 16;
      iLayerType := PFD_MAIN_PLANE;
    end;
  pf := ChoosePixelFormat(h_DC, @pfd);
  SetPixelFormat(h_DC, pf, @pfd);
  h_RC := wglCreateContext(h_DC);
  wglMakeCurrent(h_DC, h_RC);
end;

constructor TParticles.Create(Num: Integer);
begin
  ParticleNum := Num;
  SetLength(Particle, ParticleNum);
  ParticleSpeed := 2.0;
end;

destructor TParticles.Destroy;
begin
  inherited;
end;

procedure TParticles.ParticleBorn(index: Integer);
begin
  with Particle[index] do
    begin
      active := True;
      life := 20;
      fade := Trunc(random(100)) / 1000 + 0.003;
      yi := -20;
      r := 0;
      g := 1;
      b := 0;
      x := random(50) - 25;
      y := 10;
      z := random(50) - 25;
    end;
end;

procedure TParticles.ParticleDead(index: Integer);
begin
  with Particle[index] do
    begin
      active := False;

      ParticleBorn(index);
    end;
end;

procedure TParticles.ParticleDraw(index: Integer);
begin
  with Particle[index] do
    begin
      glColor4f(r, g, b, life);
      glBegin(GL_TRIANGLE_STRIP);
      glTexCoord2d(1, 1);
      glVertex3f(x + 0.25, y + 2.5, z);
      glTexCoord2d(0, 1);
      glVertex3f(x - 0.25, y + 2.5, z);
      glTexCoord2d(1, 0);
      glVertex3f(x + 0.25, y - 2.5, z);
      glTexCoord2d(0, 0);
      glVertex3f(x - 0.25, y - 2.5, z);
      glEnd();
    end;
end;

procedure TParticles.ParticleOld(index: Integer);
begin
  with Particle[index] do
    begin
      y := y + yi / (ParticleSpeed * 1000);
      life := life - fade;
      if life < 0 then
        ParticleDead(index);
    end;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  Keys[Key] := True;
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  Keys[Key] := False;
end;

end.

加了几个控制键,ESC退出,X,Y,Z分别控制相应坐标轴的旋转

运行一下看看效果,哈,还真有点黑客帝国的感觉

旋转一下再看看

这是我那个蹩脚的纹理,哈哈

原创粉丝点击