📄 unit_classes.pas
字号:
{*************************************}
{ }
{ Game: Aliens }
{ Author: arming }
{ 2005/12/5 in Seu, Nanjing }
{ http://arming.com.cn }
{ mail: xjr555@126.com }
{ }
{*************************************}
unit Unit_classes;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
StdCtrls, ExtCtrls, ImgList;
const
Img_Str_Width = 6;
Img_Str_Height = 9;
Img_Obj_Width = 16;
Img_Obj_Height = 16;
Img_Obj_Str = '!"#$%&''()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ';
Img_Str_Path = '..\images\text.bmp';
Img_Obj_Path = '..\images\object.bmp';
Img_Title_Path = '..\images\title.bmp';
Game_Timer_Interval = 50;
type
// Image String
TImgStr = class( TPersistent )
public
constructor Create( imglist: TImageList );
destructor Destroy; override;
procedure DrawString( Canvas: TCanvas; x,y,space,max_width: integer;
Str: string ); overload;
procedure DrawString( Canvas: TCanvas; x,y,space: integer;
Str: string ); overload;
procedure DrawString( Canvas: TCanvas; x,y: integer;
Str: string ); overload;
private
ImageList: TImageList;
ImgString: string;
function IndexOfChar( chr: Char ): integer;
end;
// Image Object
TImgObjIndex = ( bug1, bug2, bugl, bugr, bullet, exp1, exp2, exp3, flame1,
flame2, missile, ship );
TImgObj = class( TPersistent )
public
constructor Create( imglist: TImageList );
destructor Destroy; override;
procedure DrawObj( Canvas: TCanvas; x,y: integer; Obj: TImgObjIndex );
private
ImageList: TImageList;
end;
// Game Widget
TGameModes = ( gmShooting, gmMarching );
TGameState = ( gsIntro, gsPlaying, gsDying, gsLevelCompleted, gsGameOver );
TGameDir = ( gdLeft, gdRight, gdNone );
TGameKey = ( gkKey_Left, gkKey_Right, gkKey_Up, gkKey_Down, gkKey_Start, gkKey_Fire );
TGameWidget = class( TPersistent )
public
constructor Create( ptBox: TPaintBox );
destructor Destroy; override;
procedure updateMode( mode: TGameModes );
procedure start(); procedure stop(); procedure pause(); procedure unpause(); procedure setSpeed( speed: integer ); // speed: 20~100, default 70; function getSpeed: integer; procedure keyPressed( Key: TGameKey ); procedure keyReleased( Key: TGameKey ); procedure mouseMove( mouseX, mouseY: integer ); private
timer: TTimer;
paintBox: TPaintBox;
imgListStr, imgListObj: TImageList;
imgObj: TImgObj;
imgStr: TImgStr;
imgTitle: TImage;
m_bug: array[0..1] of TImgObjIndex;
m_bugdir: array[0..1] of TImgObjIndex;
m_explosion: array[0..2] of TImgObjIndex;
m_flame: array[0..2] of TImgObjIndex;
max_lives, max_bullets, max_missiles, max_aliens, max_stars: integer;
m_mode: TGameModes;
m_state: TGameState;
m_counter, m_alien_counter: integer;
m_level, m_score, m_lives, m_num_diving: integer;
m_player_dir: TGameDir;
m_player_x, m_player_req_x: integer;
m_bullets, m_bullets_fired, m_aliens_killed: integer;
m_bullet_x, m_bullet_y: array of integer; m_missiles: integer; m_missile_x, m_missile_y: array of integer; m_aliens: integer; m_alien_x,m_alien_y,m_alien_state,m_alien_xhome,m_alien_yhome, m_alien_statehome: array of integer; m_stars: integer; m_star_x,m_star_y,m_star_speed,m_star_size: array of integer; procedure timerTick( Sender: TObject ); procedure newLevel(); procedure updateLevel(); procedure fireBullet(); procedure deleteBullet( i: integer ); procedure fireMissile( i: integer ); procedure deleteMissile( i: integer ); procedure deleteAlien( i: integer ); procedure switchState( state: TGameState ); procedure drawIntro(); procedure drawPlaying(); procedure drawGameOver(); procedure addScore( score: integer ); procedure rePaint( flag: boolean ); end;
implementation
uses Unit_Main;
{ TImgStr }
constructor TImgStr.Create(imglist: TImageList);
begin
ImageList := imglist;
ImgString := Img_Obj_Str;
end;
destructor TImgStr.Destroy;
begin
ImageList := nil;
inherited;
end;
procedure TImgStr.DrawString(Canvas: TCanvas; x, y, space: integer;
Str: string);
var i: integer;
index: integer;
begin
for i:= 0 to Length( Str ) do
begin
index := IndexOfChar( Str[i+1] );
if index >= 0 then
ImageList.Draw( Canvas, x+i*( space + Img_Str_Width ), y,
IndexOfChar( Str[i+1] ) );
end;
end;
procedure TImgStr.DrawString(Canvas: TCanvas; x, y: integer; Str: string);
begin
DrawString( Canvas, x, y, 0, Str );
end;
procedure TImgStr.DrawString(Canvas: TCanvas; x, y, space,
max_width: integer; Str: string);
var i: integer;
index: integer;
x_pos, y_pos, line: integer;
begin
line := 1;
for i:= 0 to Length( Str ) do
begin
index := IndexOfChar( Str[i+1] );
x_pos := x+i*( space + Img_Str_Width );
y_pos := y;
if x_pos >= ( max_width + x ) then
begin
line := (x_pos - x) div max_width;
x_pos := x_pos - line * max_width;
y_pos := y + line * (Img_Str_Height + 2);
end;
if index >= 0 then
ImageList.Draw( Canvas, x_pos, y_pos,
IndexOfChar( Str[i+1] ) );
end;
end;
function TImgStr.IndexOfChar(chr: Char): integer;
var i: integer;
begin
Result := -1;
for i := 0 to Length( ImgString ) do
if UpCase( chr ) = ImgString[i+1] then
begin
Result := i;
Exit;
end;
end;
{ TImgObj }
constructor TImgObj.Create(imglist: TImageList);
begin
ImageList := imglist;
end;
destructor TImgObj.Destroy;
begin
ImageList := nil;
inherited;
end;
procedure TImgObj.DrawObj( Canvas: TCanvas; x, y: integer;
Obj: TImgObjIndex);
begin
ImageList.Draw( Canvas, x, y, integer( Obj ) );
end;
{ TGameWidget }
procedure TGameWidget.addScore(score: integer);
var old_score: integer;
begin
old_score := m_score;
m_score := m_score + score; if (m_mode = gmShooting) then begin if ((m_score mod 1000) < (old_score mod 1000)) then begin m_lives := m_lives+1; end; end else begin if ((m_score mod 2000) < (old_score mod 2000)) then m_lives := m_lives+1; end;
end;
constructor TGameWidget.Create( ptBox: TPaintBox );
begin
Randomize;
paintBox := ptBox;
timer := TTimer.Create( nil );
timer.Enabled := False;
timer.Interval := Game_Timer_Interval;
timer.OnTimer := timerTick;
{
imgTitle := TImage.Create( nil );
imgTitle.Picture.LoadFromFile( Img_Obj_Path );
//imgTitle.Picture.Graphic.SaveToStream( );
imgListObj := TImageList.Create( nil );
imgListObj.Width := Img_Obj_Width;
imgListObj.Height := Img_Obj_Height;
imgListObj.Add( imgTitle.Picture.Bitmap, nil );
imgListStr := TImageList.Create( nil );
imgListStr.Height := Img_Str_Height;
imgListStr.Width := Img_Str_Width;
imgTitle.Picture.LoadFromFile( Img_Str_Path );
imgListStr.Add( imgTitle.Picture.Bitmap, nil );
imgTitle.AutoSize := True;
imgTitle.Picture.LoadFromFile( Img_Title_Path );
}
imgListObj := frmMain.ImageList_Obj;
imgListStr := frmMain.ImageList_Str;
imgTitle := frmMain.Image_Title;
imgObj := TImgObj.Create( imgListObj );
imgStr := TImgStr.Create( imgListStr );
max_lives := 3;
max_bullets := 3;
max_missiles := 8;
max_aliens := 30;
max_stars := 20;
SetLength( m_bullet_x, max_bullets );
SetLength( m_bullet_y, max_bullets );
SetLength( m_missile_x, max_missiles );
SetLength( m_missile_y, max_missiles );
SetLength( m_alien_x, max_aliens );
SetLength( m_alien_y, max_aliens );
SetLength( m_alien_state, max_aliens );
SetLength( m_alien_xhome, max_aliens );
SetLength( m_alien_yhome, max_aliens );
SetLength( m_alien_statehome, max_aliens );
SetLength( m_star_x, max_stars );
SetLength( m_star_y, max_stars );
SetLength( m_star_speed, max_stars );
SetLength( m_star_size, max_stars );
m_bug[0] := bug1;
m_bug[1] := bug2;
m_bugdir[0] := bugl;
m_bugdir[1] := bugr;
m_explosion[0] := exp1;
m_explosion[1] := exp2;
m_explosion[2] := exp3;
m_flame[0] := flame1;
m_flame[1] := flame2;
timer.Enabled := True;
end;
procedure TGameWidget.deleteAlien(i: integer);
begin
m_aliens := m_aliens-1;
m_aliens_killed := m_aliens_killed+1; while (i < m_aliens) do begin m_alien_x[i] := m_alien_x[i + 1]; m_alien_y[i] := m_alien_y[i + 1]; m_alien_state[i] := m_alien_state[i + 1]; m_alien_xhome[i] := m_alien_xhome[i + 1]; m_alien_yhome[i] := m_alien_yhome[i + 1]; m_alien_statehome[i] := m_alien_statehome[i + 1]; i := i+1; end;
end;
procedure TGameWidget.deleteBullet(i: integer);
begin
m_bullets := m_bullets-1;
while (i < m_bullets) do begin m_bullet_x[i] := m_bullet_x[i + 1]; m_bullet_y[i] := m_bullet_y[i + 1]; i := i+1; end;
end;
procedure TGameWidget.deleteMissile(i: integer);
begin
m_missiles := m_missiles-1;
while (i < m_missiles) do begin m_missile_x[i] := m_missile_x[i + 1]; m_missile_y[i] := m_missile_y[i + 1]; i := i+1; end;
end;
destructor TGameWidget.Destroy;
begin
paintBox := nil;
timer.Enabled := False;
timer.OnTimer := nil;
timer.Free;
{
imgListObj.Free;
imgListStr.Free;
imgTitle.Free;
}
imgObj.Free;
imgStr.Free;
inherited;
end;
procedure TGameWidget.drawGameOver;
var
max_x, max_y: integer;
buffer: string;
begin
max_x := paintBox.width; max_y := paintBox.height; if( m_level > 30 ) then m_level := 30; //A for 30 level with paintBox do begin Canvas.Brush.Color := clBlack; Canvas.FillRect( paintBox.BoundsRect ); Canvas.Draw((max_x - imgTitle.Width) div 2, (100 - imgTitle.Height) div 2, imgTitle.Picture.Bitmap); imgObj.DrawObj( Canvas, 20, 100, ship ); imgObj.DrawObj( Canvas, 20, 116, m_flame[(m_counter div 15) mod 2]); buffer := Format( ' You Scored %d Points in %d Level ', [ m_score, m_level ] ) ; imgStr.DrawString ( Canvas, 50, 100, buffer);//max_x - 20, buffer); imgObj.DrawObj( Canvas, 20, 150, m_bug[(m_counter div 10) mod 2] ); buffer := Format( 'Bullers Fired: %d', [ m_bullets_fired ] ); imgStr.DrawString( Canvas, 50, 150, buffer );//max_x - 20, buffer); imgObj.DrawObj( Canvas, 20, 200, m_bugdir[(m_counter div 10) mod 2]); buffer := Format( 'Aliens Killed: %d ', [ m_aliens_killed ] ); imgStr.DrawString( Canvas, 50, 200, buffer); //max_x - 20, buffer); imgStr.DrawString( Canvas, 50, max_y - 20, // max_x - 20, 'Press Start or UP Key'); end;end;
procedure TGameWidget.drawIntro;
var
max_x, max_y: integer;
begin
max_x := paintBox.width;
max_y := paintBox.height; with paintBox do begin Canvas.TryLock; Canvas.Brush.Color := clBlack; Canvas.FillRect( paintBox.BoundsRect ); Canvas.Draw((max_x - imgTitle.Width) div 2, (100 - imgTitle.Height) div 2, imgTitle.Picture.Bitmap); imgObj.DrawObj( Canvas, 20, 100, ship ); imgObj.DrawObj( Canvas, 20, 116, m_flame[(m_counter div 15) mod 2]); imgStr.DrawString( Canvas, 50, 100, 0, max_x - 60, 'MOVE YOUR SHIP LEFT AND RIGHT USING THE CURSOR KEYS, FIRE USING SPACE'); imgObj.DrawObj( Canvas, 20, 150, m_bug[(m_counter div 10) mod 2] ); if (((m_counter div 20) mod 2) = 0) then imgObj.DrawObj( Canvas, 20, 166, missile); imgStr.DrawString( Canvas, 50, 150, 0, max_x - 60, 'THESE BUGS WILL SHOOT AT YOU'); imgObj.DrawObj( Canvas, 20, 200, m_bugdir[(m_counter div 10) mod 2]); imgStr.DrawString( Canvas, 50, 200, 0, max_x - 60, 'THESE BUGS WILL KILL YOU IF YOU TOUCH THEM'); imgStr.DrawString( Canvas, 50, max_y - 20, 0, max_x - 60, 'PRESS Start OR UP KYE'); Canvas.Unlock; end;end;
procedure TGameWidget.drawPlaying;
var
max_x, max_y, i: integer;
buffer: string;
begin
max_x := paintBox.width;
max_y := paintBox.height; with paintBox do begin Canvas.Brush.Color := clBlack; Canvas.FillRect( paintBox.BoundsRect ); // draw the stars first, so they are overwritten by all other actors for i := 0 to m_stars-1 do begin Canvas.Pixels[m_star_x[i], m_star_y[i]] := (m_star_size[i] * 8) + 128; Canvas.Pixels[m_star_x[i], m_star_y[i] + 1]:= (m_star_size[i] * 8) + 128; end; // then, draw all the other actors for i := 0 to m_bullets -1 do imgObj.DrawObj( Canvas, m_bullet_x[i], m_bullet_y[i], bullet); for i := 0 to m_missiles-1 do imgObj.DrawObj( Canvas, m_missile_x[i], m_missile_y[i], missile); for i := 0 to m_aliens-1 do if (m_alien_state[i] < 2) then imgObj.DrawObj( Canvas, m_alien_x[i], m_alien_y[i], (m_bug[(m_counter div 10) mod 2])) else if (m_alien_state[i] < 4) then imgObj.DrawObj( Canvas, m_alien_x[i], m_alien_y[i], (m_bugdir[m_alien_state[i] mod 2])) else imgObj.DrawObj( Canvas, m_alien_x[i], m_alien_y[i], (m_explosion[((m_alien_state[i] - 4) div 3) mod 3])); // draw the player last if (m_state = gsDying) then begin if (m_counter < 9) then imgObj.DrawObj( Canvas, m_player_x, max_y - 32, m_explosion[(m_counter div 3) mod 3]) else if (m_counter >= 18)and((((m_counter - 18) div 2) mod 2)<>0)and(m_lives > 1) then imgObj.DrawObj( Canvas, m_player_x, max_y - 32, ship); end else begin imgObj.DrawObj( Canvas, m_player_x, max_y - 32, ship); imgObj.DrawObj( Canvas, m_player_x, max_y - 16, m_flame[(m_counter div 15) mod 2]); end; // draw some info last if (m_state = gsLevelCompleted)and((m_counter mod 4) <>0 ) then begin if(m_level < 30) then buffer := Format( 'LEVEL %d COMPLETED', [ m_level ] ) else buffer := Format( 'THE TOP LEVEL %d COMPLETED!' , [ m_level ] ); imgStr.DrawString ( Canvas, (max_x - Length(buffer) * 7) div 2, 100, buffer);//max_x, buffer); end else if (m_state = gsDying)and((m_counter mod 4)<>0)and(m_lives > 1) then begin buffer := Format( 'YOU DIED, %d LIVES LEFT', [ m_lives - 1 ] ); imgStr.DrawString ( Canvas, (max_x - Length(buffer) * 7) div 2, 100, buffer);//max_x, buffer); end end;end;
procedure TGameWidget.fireBullet;
begin
if (m_bullets < max_bullets) then
begin
m_bullet_x[m_bullets] := m_player_x; m_bullet_y[m_bullets] := paintBox.height - 36; m_bullets := m_bullets+1; m_bullets_fired := m_bullets_fired+1; end;
end;
procedure TGameWidget.fireMissile(i: integer);
begin
if (m_missiles < max_missiles) then
begin
m_missile_x[m_missiles] := m_alien_x[i]; m_missile_y[m_missiles] := m_alien_y[i] + 16; m_missiles := m_missiles+1; end;
end;
function TGameWidget.getSpeed: integer;
begin
Result := 120 - timer.Interval;
end;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -