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

📄 cityscreen.pas

📁 类似文明的游戏源代码。
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{$INCLUDE switches}

unit CityScreen;

interface

uses
  Protocol,ClientTools,Term,ScreenTools,IsoEngine,PVSB,BaseWin,

  Windows,Messages,SysUtils,Classes,Graphics,Controls,Forms,ExtCtrls,ButtonA,
  ButtonB, ButtonBase;

const
{modes}
mSupp=1; mImp=2;

type
  TCityDlg = class(TBaseDlg)
    Timer1: TTimer;
    BuyBtn: TButtonB;
    CloseBtn: TButtonA;
    SupportBtn: TButtonB;
    BuiltBtn: TButtonB;
    procedure FormCreate(Sender:TObject);
    procedure FormDestroy(Sender:TObject);
    procedure FormMouseDown(Sender:TObject;Button:TMouseButton;
      Shift:TShiftState;x,y:integer);
    procedure BuyClick(Sender:TObject);
    procedure CloseBtnClick(Sender:TObject);
    procedure FormShow(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure Timer1Timer(Sender: TObject);
    procedure SupportBtnClick(Sender: TObject);
    procedure BuiltBtnClick(Sender: TObject);
    procedure FormPaint(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: word;
      Shift: TShiftState);
  public
    Mode,cix,cLoc,Happened: integer;
    CloseAction: (None, Restore, RestoreAutoTurn);
    ProdHint: boolean;
    procedure ShowNow;
    procedure OffscreenPaint; override;
  private
    c: TCity;
    Report:TCityReport;
    cOwner,cGov,
    emix{EnemyModel Index},
    BlinkTime,nDisplay,CityAge:integer;
    imix:array[0..15] of integer;
    sb:TPVScrollbar;
    CityAreaInfo: TCityAreaInfo;
    OuterCityTex, InnerCityTex: TTexture;
    AreaMap: TIsoMap;
    EventSoundEnabled: boolean;
    procedure InitDisplay;
    procedure ChooseProject;
    procedure OffscreenUpdate;
    procedure OnScroll(var m:TMessage); message WM_VSCROLL;
  end;

var
  CityDlg:TCityDlg;

implementation

uses
  Select,Messg,MessgEx,Help,Inp;

{$R *.DFM}

const
xArea=24; yArea=41;
xView=232; yView=286;
xFood=325; yFood=277;
xProd=13; yProd=277;
xTrade=325; yTrade=44;
xMessage=24; yMessage=38;
xImp=49;{7} yImp=207; ImpPitch=64;
xSupp=49;{7} ySupp=207; SuppPitch=64;

var
ImpSorted: array[0..nImp-1] of integer;

procedure TCityDlg.FormCreate(Sender:TObject);
begin
inherited;
WideBottom:=true;
FullCaption:=false;
TexOverride:=true;
CaptionLeft:=140;
CreatePVSB(sb,Handle,243,ClientWidth-SideFrame,243+64);
AreaMap:=TIsoMap.Create;
AreaMap.SetOutput(offscreen);
AreaMap.SetPaintBounds(xArea,yArea,xArea+8*33,yArea+8*16);
Mode:=mImp;
ProdHint:=false;
EventSoundEnabled:=false;
InnerHeight:=ClientHeight-2*WideFrame;
InitButtons(self);
InitWindowRegion;
end;

procedure TCityDlg.FormDestroy(Sender:TObject);
begin
AreaMap.Free;
end;

procedure TCityDlg.CloseBtnClick(Sender:TObject);
begin
Close
end;

procedure TCityDlg.FormKeyDown(Sender: TObject; var Key: word;
  Shift: TShiftState);
begin
if Key=13 then Close;
end;

procedure TCityDlg.InitDisplay;
var
Cnt,i: integer;
begin
Cnt:=0;
if Mode=mImp then
  begin
  nDisplay:=(InnerWidth-xImp-GetSystemMetrics(SM_CXVSCROLL)+ImpPitch-58) div ImpPitch;
  for i:=0 to nImp-1 do if c.Built[i]=1 then inc(Cnt);
  end
else
  begin
  nDisplay:=(InnerWidth-xSupp-GetSystemMetrics(SM_CXVSCROLL)) div 64;
  for i:=0 to MyRO.nUn-1 do
    if (MyUn[i].Loc>=0) and (MyUn[i].Home=cix) then inc(Cnt);
  end;
if Cnt>0 then InitPVSB(sb,(Cnt+nDisplay-1) div nDisplay-1,1)
else InitPVSB(sb,0,1);
end;

procedure TCityDlg.OnScroll(var m:TMessage);
begin
if ProcessPVSB(sb,m) then
  begin OffscreenPaint; SmartInvalidate; Update end;
end;

procedure TCityDlg.OffscreenPaint;

  procedure FillBar(Cap: string; x,y,pos,Growth,max,Kind: integer);
  var
  s: string;
  begin
  if Growth>0 then
    PaintProgressBar(offscreen.Canvas,Kind,x-3,y,pos*110 div max,
      (Growth*110 +max div 2) div max,110,OuterCityTex)
  else PaintProgressBar(offscreen.Canvas,Kind,x-3,y,pos*110 div max,
    (Growth*110 -max div 2) div max,110,OuterCityTex);
  with offscreen.Canvas do
    begin
    RisedTextOut(offscreen.Canvas,x-6,y-20,Cap);
    s:=Format('%d/%d',[pos,max]);
    RisedTextOut(offscreen.Canvas,x+128,y-7,s);
    end
  end;

  procedure DisorderBar(x,y: integer);
  var
  s: string;
  begin
  DarkGradient(offscreen.Canvas,x-6,y+1,212,3);
  if cGov=gAnarchy then s:=Phrases.Lookup('GOVERNMENT',gAnarchy)
  else if c.Flags and chCaptured<>0 then
    s:=Phrases.Lookup('CITYEVENTS',13)
  else s:=Phrases.Lookup('CITYEVENTS',0);
  RisedTextOut(offscreen.Canvas,x-2,y,s)
  end;

  procedure CaptionBar(dst:TBitmap;x,y:integer;Kind:integer; Cap:string;
    val: integer);
  var
  s:string;
  begin
  with dst.Canvas do
    begin
    font.color:=OuterCityTex.clTextLight;
    if Kind>=0 then
      begin
      LightGradient(dst.Canvas,x-6,y+1,16,
        GrExt[HGrSystem].Data.Canvas.Pixels[187,115+kind]);
      LightGradient(dst.Canvas,x-6+17,y+1,212-17,OuterCityTex.clTextShade);
      Sprite(dst,HGrSystem,x-3,y+4,10,10,66+Kind mod 11 *11,
        115+Kind div 11 *11);
      TextOut(x+15,y,Cap)
      end
    else
      begin
      LightGradient(dst.Canvas,x-6,y+1,212,OuterCityTex.clTextShade);
      TextOut(x-2,y,Cap);
      end;
    s:=IntToStr(val);
    TextOut(x+170+32-TextWidth(s),y,s);
    end
  end;

  procedure PaintResources(x,y,Loc:integer);
  var
  d,i,Total,xGr:integer;
  TileInfo:TTileInfo;
  rare: boolean;
  begin
  if Server(sGetCityTileInfo,me,Loc,TileInfo)<>eOk then
    begin assert(cix<0); exit end;
  Total:=TileInfo.Food+TileInfo.Prod+TileInfo.Trade;
  rare:=MyMap[Loc] and $06000000>0;
  if rare then inc(Total);
  if Total>1 then d:=22 div (Total-1);
  if d<1 then d:=1;
  if d>4 then d:=4;
  for i:=0 to Total-1 do
    begin
    if rare and (i=Total-1) then xGr:=66+110
    else if i>=TileInfo.Food+TileInfo.Prod then xGr:=66+44
    else if i>=TileInfo.Prod then xGr:=66
    else xGr:=66+22;
    Sprite(offscreen,HGrSystem,x+28+d*(2*i+1-Total),y+11,10,10,xGr,115);
    end
  end;

var
line: integer;

  procedure CheckMessage(Flag: integer);
  var
  i, test: integer;
  s: string;
  begin
  if Happened and Flag<>0 then
    begin
    i:=0;
    test:=1;
    while test<Flag do begin inc(i); inc(test,test) end;

    if EventSoundEnabled then
      begin
      if Flag=chProduction then
        begin
        if c.Project0 and cpImp<>0 then
          begin
          if c.Project0 and cpIndex>=28 then // wonders have already extra message with sound
            if not Play('IMP_SPECIAL',c.Project0 and cpIndex) then
              Play('IMP_STD')
          end
        else Play('UNIT_STD');
        EventSoundEnabled:=false;
        end
      else if Play('CITYEVENTS',i) then
        EventSoundEnabled:=false;
      end;

    s:=Phrases.Lookup('CITYEVENTS',i);
    if Flag=chNoGrowthWarning then
      if c.Built[imAqueduct]=0 then
        s:=Format(s,[Phrases.Lookup('IMPROVEMENTS',imAqueduct)])
      else s:=Format(s,[Phrases.Lookup('IMPROVEMENTS',imSewer)]);
    RisedTextOut(offscreen.Canvas,xMessage,yMessage+16*line,s);
    inc(line)
    end
  end;

var
x,xGr,i,i1,j,d,dx,dy,mov0,PrCost,Cnt,Loc1,FreeSupp,TerrOwner,Paintiix: integer;
PrName:string;
UnitInfo: TUnitInfo;
Disorder,TestDeployed: boolean;
begin
inherited;
if cix>=0 then c:=MyCity[cix];

with offscreen.Canvas do
  begin
  Font.Assign(UniFont[ftSmall]);
  Fill(offscreen.Canvas,0,0,InnerWidth,yArea-2,0,0,InnerCityTex);
  Fill(offscreen.Canvas,0,yArea-2,xArea-1,132,0,0,InnerCityTex);
  Fill(offscreen.Canvas,xArea+265,yArea-2,xTrade-xArea-278,132,0,0,InnerCityTex);
  Fill(offscreen.Canvas,0,yArea+130,xTrade-13,yImp-yArea-130,0,0,InnerCityTex);
  Fill(offscreen.Canvas,0,yImp,InnerWidth,yProd-yImp-6,0,0,InnerCityTex);
  Fill(offscreen.Canvas,xTrade-12,yArea-2,InnerWidth-xTrade+11,yImp-yArea+1,0,0,OuterCityTex);
  Fill(offscreen.Canvas,1,yProd-5,InnerWidth-2,InnerHeight-yProd+4,0,0,OuterCityTex);
  Frame(offscreen.Canvas,xArea-1,yArea-1,xArea+8*33,yArea+8*16,InnerCityTex.clBevelShade,InnerCityTex.clBevelLight);
  RFrame(offscreen.Canvas,xArea-2,yArea-2,xArea+8*33+1,yArea+8*16+1,InnerCityTex.clBevelShade,InnerCityTex.clBevelLight);
  Frame(offscreen.Canvas,xTrade-13,yTrade-6,InnerWidth-1,yTrade+102,OuterCityTex.clBevelLight,OuterCityTex.clBevelShade);
  Frame(offscreen.Canvas,xTrade-13,yTrade+103,InnerWidth-1,yTrade+162,OuterCityTex.clBevelLight,OuterCityTex.clBevelShade);
  Frame(offscreen.Canvas,xProd-13,yProd-6,xFood-14,InnerHeight-1,OuterCityTex.clBevelLight,OuterCityTex.clBevelShade);
  Frame(offscreen.Canvas,xFood-13,yFood-6,InnerWidth-1,InnerHeight-1,OuterCityTex.clBevelLight,OuterCityTex.clBevelShade);
  AreaMap.Paint(xArea,yArea-16,dLoc(c.Loc,-3,-3),7,7,c.Loc,cOwner);
  end;

for dy:=-3 to 3 do for dx:=-3 to 3 do
  if ((dx+dy) and 1=0) and (dx*dx*dy*dy<81) then
    begin
    Loc1:=dLoc(c.Loc,dx,dy);
    if (CityAreaInfo.Available[(dy+3) shl 2+(dx+3) shr 1] in [faNotAvailable,faTreaty])
      and (MyMap[Loc1] and fCity=0) then
      Sprite(offscreen,HGrTerrain,xArea+99+33*dx,yArea+48+16*dy,64,32,391,496);
    if (1 shl((dy+3) shl 2+(dx+3) shr 1) and c.Tiles<>0) then
      PaintResources(xArea+99+33*dx,yArea+48+16*dy,Loc1);
    end;
Report.HypoTiles:=-1;
Report.HypoTax:=-1;
Report.HypoLux:=-1;
if cix>=0 then Server(sGetCityReport,me,cix,Report) // own city
else Server(sGetEnemyCityReport,me,cLoc,Report); // enemy city
Disorder:= (Report.Working-Report.Happy>c.Size div 2)
  or (cGov=gAnarchy) or (c.Flags and chCaptured<>0);

i:=Report.FoodRep-Report.Eaten; // growth
// if (i>2) and (cGov=gDespotism) then i:=2;
if (cGov=gLybertarianism) or Disorder then
  i:=0; {no growth}
FillBar(Phrases.Lookup('STORAGE'),xFood+4,yFood+83,c.Food,i,Report.Storage,1);

Sprite(offscreen,HGrSystem,InnerWidth div 2 -2,0,5,3,75,16);
if c.Size>1 then d:=400 div(c.Size-1);
if d>28 then d:=28;
for i:=c.Size-1 downto 0 do
  begin
  if i<c.Size-Report.Working then xGr:=57+i and 1*28
  else if i<c.Size-Report.Working+Report.Happy then xGr:=1+i and 1 *28
  else xGr:=113+i and 1 *28; {i and 1=male/female}
  BitBlt(offscreen.Canvas.Handle,InnerWidth div 2+1 -(d*(c.Size-1)+27) div 2 +i*d,5,
    27,30,GrExt[HGrSystem].Mask.Canvas.Handle,xGr,171{+CityAge*31!!!},SRCAND); {shadow}
  Sprite(offscreen,HGrSystem,InnerWidth div 2 -(d*(c.Size-1)+27) div 2 +i*d,4,27,30,xGr,171{+CityAge*31!!!});
  end;

if c.Project and cpImp=0 then
  PrName:=Tribe[cOwner].ModelName[c.Project and cpIndex]
else PrName:=Phrases.Lookup('IMPROVEMENTS',c.Project and cpIndex);
PrCost:=Report.ProdCost;

CaptionBar(offscreen,xFood,yFood,0,Phrases.Lookup('FOOD'),Report.FoodRep);
CountBar(offscreen,xFood,yFood+19,0,Phrases.Lookup('DEMAND'),Report.Eaten,OuterCityTex);
if Report.FoodRep>=Report.Eaten then
  if Disorder then DisorderBar(xFood,yFood+38)
  else if (cGov=gLybertarianism)
    or (c.Size>=NeedAqueductSize) and (Report.FoodRep<Report.Eaten+2) then
    CountBar(offscreen,xFood,yFood+38,6,Phrases.Lookup('PROFIT'),
      Report.FoodRep-Report.Eaten,OuterCityTex)
  else CountBar(offscreen,xFood,yFood+38,0,Phrases.Lookup('SURPLUS'),
    Report.FoodRep-Report.Eaten,OuterCityTex)
else CountBar(offscreen,xFood,yFood+38,1,Phrases.Lookup('LACK'),
  Report.Eaten-Report.FoodRep,OuterCityTex);

CaptionBar(offscreen,xProd,yProd,2,Phrases.Lookup('MATERIAL'),Report.ProdRep);
if not Disorder then
  CountBar(offscreen,xProd,yProd+19,2,Phrases.Lookup('SUPPORT'),
    Report.Support,OuterCityTex);
if Report.ProdRep>=Report.Support then
  if Disorder then DisorderBar(xProd,yProd+38)
  else if c.Project and (cpImp+cpIndex)=cpImp+imTrGoods then
    CountBar(offscreen,xProd,yProd+38,6,Phrases.Lookup('PROFIT'),
      Report.ProdRep-Report.Support,OuterCityTex)
  else CountBar(offscreen,xProd,yProd+38,2,Phrases.Lookup('PROD'),
    Report.ProdRep-Report.Support,OuterCityTex)
else CountBar(offscreen,xProd,yProd+38,3,Phrases.Lookup('LACK'),
  Report.Support-Report.ProdRep,OuterCityTex);

if Report.Trade>0 then
  begin
  CaptionBar(offscreen,xTrade,yTrade,4,Phrases.Lookup('TRADE'),Report.Trade);
  CountBar(offscreen,xTrade,yTrade+19,5,Phrases.Lookup('CORR'),Report.Corruption,OuterCityTex);
  if Disorder then DisorderBar(xTrade,yTrade+48)
  else
    begin
    CountBar(offscreen,xTrade,yTrade+57,12,Phrases.Lookup('SCIENCE'),Report.Science,OuterCityTex);
    CountBar(offscreen,xTrade,yTrade+38,6,Phrases.Lookup('TAX'),Report.Tax,OuterCityTex);
    end;
  CountBar(offscreen,xTrade,yTrade+76,8,Phrases.Lookup('LUX'),Report.Lux,OuterCityTex);
  end;

if (c.Pollution>0) or (Report.PollRep>0) then
  begin
  CaptionBar(offscreen,xTrade,yTrade+109,-1,Phrases.Lookup('POLL'),Report.PollRep);
  FillBar(Phrases.Lookup('DUMP'),xTrade+4,yTrade+148,c.Pollution,Report.PollRep,
    MaxPollution,3);
  end;

if c.Project and (cpImp+cpIndex)<>cpImp+imTrGoods then with offscreen.Canvas do
  begin
  if TextWidth(PrName)>171 then
    begin
    repeat Delete(PrName,Length(PrName),1) until TextWidth(PrName)<=171;
    PrName:=PrName+'.'
    end;
  i:=Report.ProdRep-Report.Support;
  if i<0 then i:=0;
  if Disorder then i:=0; {disorder}
  FillBar(PrName,xProd+4,yProd+83,c.Prod,i,PrCost,4);
  end;

for i:=0 to nDisplay-1 do imix[i]:=-1;
Cnt:=0;
if Mode=mImp then
  begin
  for i:=0 to nImp-1 do if c.Built[ImpSorted[i]]=1 then
    begin
    i1:=ImpSorted[i];
    if (Cnt>=nDisplay*sb.si.npos) and (Cnt<nDisplay*(sb.si.npos+1)) then
      begin
      imix[Cnt-nDisplay*sb.si.npos]:=i1;
      x:=(Cnt-nDisplay*sb.si.npos)*ImpPitch+xImp;
      FrameImage(offscreen.Canvas,BigImp,x,yImp+8,xSizeBig,ySizeBig,
        i1 mod 7*xSizeBig, (i1+SystemIconLines*7) div 7*ySizeBig,
        (cix>=0) and (ClientMode<scContact));
      if Imp[i1].Maint>0 then
        begin
        if Imp[i1].Maint>1 then
          begin d:=26 div(Imp[i1].Maint-1);if d>11 then d:=11 end;
        for j:=0 to Imp[i1].Maint-1 do
          Sprite(offscreen,HGrSystem,x+d*j,yImp+52,10,10,132,115);
        end
      end;
    inc(Cnt);
    end;
  end
else {if mode=mSupp then}
  begin
  case cGov of
    gAnarchy: FreeSupp:=9999;
    gDespotism,gFundamentalism: FreeSupp:=c.Size;
    gMonarchy,gCommunism: FreeSupp:=c.Size div 2;
    gRepublic,gDemocracy,gLybertarianism: FreeSupp:=0;
    end;

  for i:=0 to MyRO.nUn-1 do if (MyUn[i].Loc>=0) and (MyUn[i].Home=cix) then
    with MyModel[MyUn[i].mix] do
      begin
      if (Cnt>=nDisplay*sb.si.npos) and (Cnt<nDisplay*(sb.si.npos+1)) then
        begin // unit visible in display
        imix[Cnt-nDisplay*sb.si.npos]:=i;
        x:=(Cnt-nDisplay*sb.si.npos)*64+xSupp;
        MakeUnitInfo(me,MyUn[i],UnitInfo);
        NoMap.SetOutput(offscreen);
        NoMap.PaintUnit(x,ySupp+2,UnitInfo,MyUn[i].Status);

⌨️ 快捷键说明

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