unit sankaku1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  dddd,  ddddut, ddraw, Ddidex, Menus;

type
  TForm1 = class(TForm)
    DDDD1: TDDDD;
    Joy: TDDIDEX;
    MainMenu1: TMainMenu;
    S1: TMenuItem;
    W1: TMenuItem;
    F1: TMenuItem;
    procedure FormCreate(Sender: TObject);
    procedure DDDD1Init(Sender: TObject; fNeedChange: Boolean);
    procedure DDDD1Restore(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word;
      Shift: TShiftState);
    procedure W1Click(Sender: TObject);
    procedure F1Click(Sender: TObject);
    procedure DDDD1ChangeDisplayMode(Sender: TObject);
  private
    { Private 宣言 }
    procedure AppIdle(Sender: TObject; var Done: Boolean);
    procedure Fire;
    procedure MoveBullet;
    procedure MoveStar;
  public
    { Public 宣言 }
    Surf:TDDDDSurface;  //使用するサーフェス
    PATH:String;        //アプリの起動されたディレクトリ
    Spr:TDDDDSprite;    //スプライトオブジェクト
    Timer:Integer;      //時間管理用
    FirstDepth:Integer; //起動時の画面の色数
    prevB:Boolean;      //一フレーム前にパッドのボタンが押された
  end;

var
  Form1: TForm1;

implementation

const
  bmps:Array[0..0] of String = ('sankaku1.bmp');
  S_MC = 0;
  S_TAMA=1;
  NUM_TAMA=8;
  S_STAR=S_TAMA+NUM_TAMA;
  NUM_STAR=64;

var
  tama:array[S_TAMA..S_TAMA+NUM_TAMA-1] of Boolean;
  starDy:Array[S_STAR..S_STAR+NUM_STAR-1] of Integer;

(*******************************************************************************
  ゲーム用ルーチン
*******************************************************************************)

procedure TForm1.Fire;
var
  i:Integer;
begin
  //空いている弾番号を探す
  for i:=S_TAMA to S_TAMA+NUM_TAMA-1 do begin
    if not tama[i] then begin
      tama[i]:=true;
      Spr[i].X:=Spr[S_MC].X + 16;
      Spr[i].Y:=Spr[S_MC].Y - 16;
      Spr[i].Show;
      exit;
    end;
  end;
end;

//弾を動かす
procedure TForm1.MoveBullet;
var
  i:Integer;
begin
  for i:=S_TAMA to S_TAMA+NUM_TAMA-1 do begin
    if tama[i] then begin
      Dec(Spr[i].Y,8);
      if (Timer And 1) = 0 then
        Spr[i].NextFrame;
      if Spr[i].Y < -15 then begin
        tama[i]:=False;
        Spr[i].Hide;
      end;
    end;
  end;
end;

//☆を動かす
procedure TForm1.MoveStar;
var
  i:Integer;
begin
  for i:=S_STAR to S_STAR+NUM_STAR-1 do begin
    Inc(Spr[i].y,StarDy[i]);
    if (Spr[i].y > 480) then begin
      Spr[i].y:=0;
      Spr[i].x:=Random(640);
    end;
    if (Spr[i].y mod 4) = 0 then
      Spr[i].NextFrame;
  end;
end;

(*******************************************************************************
  メインループ
*******************************************************************************)
procedure TForm1.AppIdle(Sender: TObject; var Done: Boolean);
begin
  //画面の消去
  DDDD1.Clear;

  //自機の移動
  Joy.OrScan([DI_JOY1,DI_KEYB]);
  Inc(Spr[0].X,Joy.Stick.X*4);
  Inc(Spr[0].Y,Joy.Stick.Y*4);

  //トリガ判定とファイア！
  if Joy.Buttons[DI_B1] and (not prevB) then
    Fire;
  prevB:=Joy.Buttons[DI_B1];

  //弾の移動
  MoveBullet;

  //☆の移動
  MoveStar;


  //うぇるだーん
  Spr.Update;
  DDDD1.Flip;
  Inc(Timer);

  Done:=False;
end;

(*******************************************************************************
  イベントハンドラ
*******************************************************************************)

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
  i:Integer;
begin
  Timer:=0;
  PATH:=ExtractFilePath(Application.ExeName);
  for i:=S_TAMA to NUM_TAMA+S_TAMA-1 do
    tama[i]:=False;
end;

procedure TForm1.DDDD1Init(Sender: TObject; fNeedChange: Boolean);
var
  i:Integer;
begin

  //最初の色数を覚えておく
  FirstDepth:=DDDD1.BitDepth;

  //サーフェスの初期化…一番左上のピクセルの色をカラーキーに
  Surf:=TDDDDSurface.Create(DDDD1,144,80,0);
  Surf.LoadBMP(PATH+bmps[0]);
  Surf.ColorKey:=Surf.Pixels[0,0];

  //背景を黒に
  DDDD1.BackColor:=DDDD1.FrontBuffer.ColorMatch(clBlack);

  //スプライトの初期化
  Spr:=TDDDDSprite.Create(160,64);

  //自機
  Spr.SetShape(0, Surf, Rect(0,0,48,48));
  Spr[S_MC].IShape:=0;
  Spr[S_MC].Pos:=Point(300,300);
  Spr[S_MC].Show;

  //弾(1〜8番)
  Spr.SetShape(1, Surf, Rect(0 ,48,16,64));
  Spr.SetShape(2, Surf, Rect(16,48,32,64));
  Spr.SetShape(3, Surf, Rect(32,48,48,64));
  For i:=S_TAMA to S_TAMA+NUM_TAMA-1 do begin
    Spr[i].IShape:=1;
    Spr[i].minAnim:=0;
    Spr[i].maxAnim:=2;
    Spr[i].RewindAnim:=True;
  end;

  //☆
  For i:=0 to 8 do
    Spr.SetShape(i+4, Surf, Rect( (i shl 4),64,((i+1) shl 4),80));
  For i:=S_STAR to S_STAR+NUM_STAR-1 do begin
    Spr[i].IShape:=4 + Random(3)*3;
    Spr[i].Y:=random(480);
    Spr[i].X:=random(640);
    Spr[i].minAnim:=0;
    Spr[i].maxAnim:=2;
    Spr[i].IAnim:=Random(3);
    Spr[i].Show;
    Spr[i].RewindAnim:=True;
    StarDy[i]:=Random(8)+1;
  end;

  //マウスカーソル消去
  ShowCursor(False);

  //メインループの取り付け
  Application.OnIdle:=AppIdle;

end;

procedure TForm1.DDDD1Restore(Sender: TObject);
begin
  DDDD1.ReadPalette(PATH+bmps[0]);
  DDDD1.UpdatePalette;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  Spr.Free;
end;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  if Key=VK_ESCAPE then begin
    Application.Terminate;
  end;
end;

//ウィンドウ内で動作
procedure TForm1.W1Click(Sender: TObject);
begin
  DDDD1.WindowMode(640,480);
end;

//フルスクリーンで動作
procedure TForm1.F1Click(Sender: TObject);
begin
  DDDD1.FullScreenMode(640,480,8,0, '');
end;

//画面モードを変えた場合の処置
procedure TForm1.DDDD1ChangeDisplayMode(Sender: TObject);
begin
  //画面の色数が変わった場合、カラーキー用の数値が違うことがあるのさ
  Surf.ColorKey:=Surf.Pixels[0,0];

  //クライアント領域を正しく
  ClientWidth:=640;
  ClientHeight:=480;
end;

end.
