?? unit2.pas
字號:
unit Unit2; //系統核心單元
interface
uses Windows, OpenGL, Graphics, SysUtils, Dialogs, Math, ExtCtrls, Classes,
Menus, Controls, Unit3;
type
ObjNames = (obj_Wall, obj_Block, obj_GridLine, obj_AidLine, obj_HighlightedAidLine, obj_SnakeBody, obj_SnakeHead, obj_IncApple, obj_DecApple, obj_Exit);
BlockStates = (bs_Empty, bs_Wall, bs_Obstacle, bs_SnakeBody, bs_IncApple, bs_DecApple, bs_Exit);
BlockType = (bt_Block, bt_AntiBlock);
GameOptionColors = array[obj_Wall..obj_Exit] of TColor;
SnakeExtraState = (se_None, se_IncApple, se_DecApple, se_Exit);
const
AppleToBlockState: array[obj_IncApple..obj_DecApple] of BlockStates = (bs_IncApple, bs_DecApple);
type
TGameOption = record
Colors: GameOptionColors; //
ColorsRGB: array[obj_Wall..obj_Exit, 1..3] of Byte;
WallColor: array[1..6, 1..3] of Byte;
WallAlpha: Byte;
ShowGrid: Boolean;
ShowAidLine: Boolean;
LightOn: Boolean;
end;
TMapCtrl = class
MapDir: string;
MapCount: Byte;
MapsName: array of string[20];
AFile: TextFile;
GeneratedMapScript: TStringList;
constructor Create;
destructor Destroy; override;
function MapFileName(idx: Byte): string;
procedure LoadMaps;
end;
TMapProperty = record
MapName: string;
MapDescription: string;
Ori_SnakeHead, OriSnakeTail: T3DPointB;
MapValue: Byte;
AppleCount: Byte;
SnakeSpeed: Byte;
AppleList: string;
UseEngineVersion: Byte;
end;
PTSnakeBody = ^TSnakeBody;
TSnakeBody = record
Pre, Next: PTSnakeBody; //分別存儲上一塊和下一個身體
OriPos: T3DPointB; //記錄這個球所在的方塊
CenterPos: T3DPoint; //記錄球心的位置
qObj: gluQuadricObj;
end;
TBlock = record
_Type: BlockType;
LeftBackBottom, RightFrontTop: T3DPointB; //左后下頂點和右上前頂點
end;
TApple = record
_Interval: Byte;
_Type: ObjNames; //只有 obj_IncApple, obj_DecApple
OriPos: T3DPointB;
CenterPos: T3DPoint;
qObj: gluQuadricObj;
Moveable: Boolean;
MoveTickCount: Byte;
end;
PTDrawEngine = ^TDrawEngine;
PTGameCtrl = ^TGameCtrl;
TDrawEngine = class //繪圖引擎
_GameCtrl: PTGameCtrl;
AppleMoveTimer: TTimer; //控制蘋果移動的時鐘控件
DrawDC: HDC;
HRC: HGLRC;
ViewWidth, ViewHeight: Word;
ViewAngleH: EyePos;
ViewAngleV: EyeHeight;
ViewAngleVMoveUp: Boolean;
ViewDistance: Byte;
ViewDistanceMoveUp: Boolean;
MapScript: TStringList; //地圖腳本
MapFileName: string;
MapProperty: TMapProperty; //地圖的一些屬性
MapSize: T3DPointB; //經常使用,把它從MapProperty中提出來
BoxCenter: T3DPoint; //場景中心
SnakeHead, SnakeTail: PTSnakeBody; //用鏈表存儲蛇身,這樣蛇的移動就可以轉化為把蛇尾的方塊移到蛇頭,速度很快
SnakeDirection: Directions;
SnakeLength: Byte;
Blocks: array of TBlock;
BlockCount: Byte;
WallLists: array[1..6] of GLuint; //繪制墻壁的glList
//將場景中的每個方塊的狀態記錄下來,可以完成碰撞檢測
BlockState: packed array[-1..MaxLength, -1..MaxLength, -1..MaxLength] of BlockStates;
NowApple: TApple;
EatAppleCount: Byte;
ExitShow: Boolean;
ExitPos: T3DPointB;
///////OpenGl
procedure IniOpenGl;
procedure IniLighting;
procedure IniScene; //場景初始化
procedure FreeOpenGl;
procedure DrawCube(p1, p2: T3DPointB; _Type: Integer = GL_QUADS); //繪制以p1為左后下頂點,p2為右前上頂點的長方體
procedure DrawSphere(Part: PTSnakeBody); //實際為繪制蛇身的一節一節
procedure SetGLColor(idx: ObjNames); //設置繪圖顏色
procedure SetEye; //設置眼睛的位置
procedure NextViewAngelV; //轉換水平視角
procedure NextViewAngelH; //轉換垂直視角
procedure ChangeFarNear;
////////////////////////////
procedure CloseMap;
procedure SnakeTurn(Turn: TurnDirection); //蛇轉向
procedure SnakeMove; //蛇移動控制過程
procedure ReadScript; //讀取腳本
procedure LoadBlocks; //讀取障礙物的位置
procedure MakeWallDrawLists; //生成繪制墻壁的glList
procedure DrawGridLine; //繪制網格線,圍繞蛇頭的,以便玩家觀察是否接近障礙物
procedure DrawAidLine(posi: T3DPointB); //繪制輔助觀察線
procedure DrawWall; //繪制墻壁
procedure CreateApple; //生成一個蘋果
procedure DrawApple; //繪制當前蘋果
procedure CreateExit; //生成出口
procedure DrawExit; //繪制出口
procedure IniBlockState; //初始化每個方塊的狀態
procedure PrepareSnake; //準備蛇的各個身體組成方塊,同時計算出蛇的初始方向
procedure DrawScene; //游戲中實時刷新場景
procedure PickApple; //吃到增長蘋果
procedure AppleMoveTimerTick(Sender: TObject);
function ReturnAnEmptyBlock: T3DPointB; //返回一個空的格子
procedure OutputGameProperties; //輸出游戲屬性到MainForm.MemoMap
procedure ShowSnakePosLengthInLabel; //輸出蛇的位置和長度信息
procedure ShowApplePos; //顯示蘋果的位置
procedure SetAppleTimeLableVisible(b: Boolean); //設置蘋果時間的Lable是否可見
procedure ShowKeyDirectors; //顯示方向鍵提示信息
constructor Create(hnd: THandle; aW, aH: Word);
destructor Destroy; override;
end;
TGameCtrl = class
_Engine: PTDrawEngine; //繪圖引擎
MoveTimer: TTimer; //控制蛇移動的Timer
NowLevelIdx: Byte;
AMapLoaded: Boolean;
GameEnd: Boolean;
GameStarted: Boolean;
GamePaused: Boolean;
/////////GameCtrl
procedure NewGame(FileName: string);
procedure Game_Start(Turn: TurnDirection);
procedure Game_End; //游戲結束
procedure Game_Pause; //游戲暫停
procedure Game_Resume; //恢復暫停的游戲
procedure Game_Restart; //重新開始游戲
procedure CloseMap;
procedure LevelPassed; //本關通過
procedure StartNextLevel; //開啟下一關
procedure MoveTimerTick(Sender: TObject);
procedure SnakeCollision(t: SnakeCollisionType); //蛇碰障礙物了
function AskIfGameEnd: Boolean; //訊問是否結束游戲
function AskNextStep(msg: string): Boolean; //訊問游戲結束后怎么辦
constructor Create;
destructor Destroy; override;
end;
function Make_3DPointB(x, y, z: Byte): T3DPointB;
procedure RGBGameColors;
procedure LoadWallColors;
procedure MakeItToSphereCenter(var P: T3DPoint);
procedure _3DPointB_To_3DPoint(var _3DPoint: T3DPoint; _3DPointB: T3DPointB);
implementation
uses Unit1;
procedure LoadWallColors;
begin
fillChar(GameOption.WallColor, sizeof(GameOption.WallColor), 0);
GameOption.WallColor[1, 1] := 255;
GameOption.WallColor[2, 1] := 255;
GameOption.WallColor[3, 2] := 255;
GameOption.WallColor[4, 2] := 255;
GameOption.WallColor[5, 3] := 255;
GameOption.WallColor[6, 3] := 255;
end;
function Make_3DPointB(x, y, z: Byte): T3DPointB;
begin
Result[1] := x;
Result[2] := y;
Result[3] := z;
end;
procedure _3DPointB_To_3DPoint(var _3DPoint: T3DPoint; _3DPointB: T3DPointB);
begin
_3DPoint[1] := _3DPointB[1];
_3DPoint[2] := _3DPointB[2];
_3DPoint[3] := _3DPointB[3];
end;
procedure RGBGameColors;
var i: ObjNames;
begin
with GameOption do
for i := obj_Wall to obj_Exit do begin
ColorsRGB[i, 1] := GetRValue(Colors[i]);
ColorsRGB[i, 2] := GetGValue(Colors[i]);
ColorsRGB[i, 3] := GetBValue(Colors[i]);
end;
end;
procedure MakeItToSphereCenter(var P: T3DPoint);
begin
P[1] := P[1] + 0.5;
P[2] := P[2] + 0.5;
P[3] := P[3] + 0.5;
end;
/////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////
constructor TMapCtrl.Create;
begin
GeneratedMapScript := TStringList.Create;
end;
destructor TMapCtrl.Destroy;
begin
GeneratedMapScript.Free;
end;
procedure TMapCtrl.LoadMaps;
var i: Byte; fn: string; s: string;
Item: TMenuItem;
begin
SetLength(MapsName, MapCount);
for i := 0 to MapCount - 1 do begin
fn := 'Map' + IntToStr(i + 1) + '.map';
AssignFile(AFile, MapDir + fn);
Reset(AFile);
Readln(AFile, s);
Readln(AFile, s);
MapsName[i] := ReadSpaceSection(s);
CloseFile(AFile);
Item := TMenuItem.Create(nil);
Item.Caption := MapsName[i] + ' @ ' + fn;
Item.Tag := i + 1;
Item.OnClick := MainForm.MapClick;
Item.AutoCheck := True;
Item.RadioItem := True;
MainForm.MenuOpenGame.Add(Item);
end;
end;
function TMapCtrl.MapFileName(idx: Byte): string;
begin
Result := MapDir + 'Map' + IntToStr(idx) + '.map';
end;
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
constructor TDrawEngine.Create(hnd: THandle; aW, aH: Word);
begin
DrawDC := GetDC(hnd);
ViewWidth := aW;
ViewHeight := aH;
MapScript := TStringList.Create;
AppleMoveTimer := TTimer.Create(nil);
AppleMoveTimer.Enabled := False;
AppleMoveTimer.Interval := 1000;
AppleMoveTimer.OnTimer := AppleMoveTimerTick;
IniOpenGl;
end;
destructor TDrawEngine.Destroy;
begin
MapScript.Free;
end;
procedure TDrawEngine.IniOpenGl;
var pfd: TPIXELFORMATDESCRIPTOR; pixelFormat: Integer;
begin
with pfd do
begin
nSize := sizeof(TPIXELFORMATDESCRIPTOR); // 此結構尺寸
nVersion := 1;
dwFlags := PFD_SUPPORT_OPENGL or PFD_DRAW_TO_WINDOW or PFD_DOUBLEBUFFER; // 使用雙緩沖區
iPixelType := PFD_TYPE_RGBA; //使用RGBA顏色空間
cColorBits := 16;
cRedBits := 0;
cRedShift := 0;
cGreenBits := 0;
cGreenShift := 0;
cBlueBits := 0;
cBlueShift := 0;
cAlphaBits := 0;
cAlphaShift := 0;
cAccumBits := 0;
cAccumRedBits := 0;
cAccumGreenBits := 0;
cAccumBlueBits := 0;
cAccumAlphaBits := 0;
cDepthBits := 16;
cStencilBits := 0;
cAuxBuffers := 0;
iLayerType := PFD_MAIN_PLANE;
bReserved := 0;
dwLayerMask := 0;
dwVisibleMask := 0;
dwDamageMask := 0;
end;
pixelFormat := ChoosePixelFormat(DrawDC, @pfd);
SetPixelFormat(DrawDC, pixelFormat, @pfd);
HRC := wglCreateContext(DrawDC);
wglMakeCurrent(DrawDC, HRC);
end;
procedure TDrawEngine.FreeOpenGl;
begin
end;
procedure TDrawEngine.CloseMap;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;
glClearColor(0, 0, 0, 1);
SwapBuffers(DrawDC);
end;
procedure TDrawEngine.IniScene;
begin
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
glLoadIdentity;
glClearColor(0, 0, 0, 1);
glViewPort(0, 0, ViewWidth, ViewHeight); //指定OpenGL在此區域內繪圖。
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST); //無論繪制的先后,讓距離遠的物體總在距離近的物體后面。
ViewAngleH := ep_Front; //正面
ViewAngleV := eh_Middle; //中間
ViewAngleVMoveUp := True; //視角先向上移動
ViewDistance := 2;
ViewDistanceMoveUp := False;
SetEye;
end;
procedure TDrawEngine.IniLighting;
var
MaterialAmbient: array[1..4] of GLfloat;
MaterialDiffuse: array[1..4] of GLfloat;
MaterialSpecular: array[1..4] of GLfloat;
AmbientLightPosition: array[1..4] of GLfloat;
LightAmbient: array[1..4] of GLfloat;
MaterialShininess: GLfloat;
begin
MaterialAmbient[1] := 0.5;
MaterialAmbient[2] := 0.8;
MaterialAmbient[3] := 0.2;
MaterialAmbient[4] := 1.0;
MaterialDiffuse[1] := 0.4;
MaterialDiffuse[2] := 0.8;
MaterialDiffuse[3] := 0.1;
MaterialDiffuse[4] := 1.0;
MaterialSpecular[1] := 1.0;
MaterialSpecular[2] := 0.5;
MaterialSpecular[3] := 0.1;
MaterialSpecular[4] := 1.0;
MaterialShininess := 40; //可設置
AmbientLightPosition[1] := 0.5;
AmbientLightPosition[2] := 1.0;
AmbientLightPosition[3] := 0;
AmbientLightPosition[4] := 0.0;
LightAmbient[1] := 0.4;
LightAmbient[2] := 0.2;
LightAmbient[3] := 0.2;
LightAmbient[4] := 1.0;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -