Simple ЯTS G∆me Dεsign & CΘding Simple ЯTS G∆me Dsign & Cding OpenEdition e Copyright â 23 by CzƠBab ζ All rights reserved June 6th, 2003 © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding Chapter I: Introduction Why did I write this book ? Trong thời điểm tại, có nhiều bạn trẻ hướng quan tâm vào thiết kế lập trình game, phải cơng nhận điều chơi game hấp dẫn, chơi game làm cịn hấp dẫn nhiều, cho dù trò chơi dở ẹc Trên diễn đàn tin học Internet đầy rẫy topic kiểu “Lập trình game với ” “Ai giúp em lập trình game nào”, tất quan tâm đến mục đích “Làm để viết nên game ?” Những ý kiến xoay quanh vấn đề đa dạng, nói khó có mà nói…dễ có Với kinh nghiệm trình độ tại, tơi cơng nhận điều khó, khơng phải q khó bạn biết đặt mục tiêu vừa tầm tìm cách tiếp cận Nếu hi vọng viết game tương đương với Quake Warcraft – sản phẩm tập thể chuyên nghiệp xây dựng thời gian dài - q viển vơng, bạn hạ thấp mục tiêu xuống chút làm game đơn giản kiểu bắn tăng hay Mario, IQ game cho trẻ em trước khơng q khó bạn biết lập trình Cá nhân tơi dường nhận thức điều có số thành công nhỏ việc thiết kế lập trình game Trong thời điểm tơi nghỉ ôn thi định dành thời gian ngắn để viết sách này, sách tơi trình bày cách đầy đủ q trình tơi thiết kế viết mã cho game RTS đơn giản (được lược bỏ nhiều tính ví dụ chơi mạng) nhằm giúp bạn hiểu phần trình “ziết game gia” Hi vọng sách giúp bạn trình thiết kế viết game Chúc tất bạn thành công dự án viết game What is RTS game ? RTS – Realtime Strategy - Thể loại game chiến thuật thời gian thực mà khởi đầu với dòng game Dune, Command & Conquer Westwood Studio nhanh chóng trở thành dịng © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding game ăn khách toàn giới Việt Nam Thời điểm phát triển dòng trò chơi dường chững lại, khơng có nhiều tiến vượt bậc thời điểm Starcraft (Blizzard Entertainment) đời mà xuất game lai tạp với thể loại khác (Warcraft III thể loại Roleplay Strategy) nên dường dòng game dần nhường bước cho dòng game ăn khách khác Nhưng cá nhân ôm ước vọng xây dựng game RTS ăn vào bối cảnh lịch sử Việt Nam đem lại cho người chơi nhiều cải tiến quan trọng cách chơi (He he, cải tiến quan trọng nha, khơng nói đâu, lúc làm xong sẽ…nói, hì hì) How this book will help you Cuốn sách viết lại trình thiết kế, viết mã – dĩ nhiên thích tương đối cụ thể – cho game RTS thiết kế đơn giản tối đa Bên cạnh tơi đưa số kinh nghiệm cá nhân có q trình làm việc nhằm giúp bạn hiểu phần cơng việc thiết kế lập trình game (Khơng chun nghiệp) Cịn sách giúp bạn tuỳ thuộc vào bạn, mà bạn thuộc hàng cao thủ bít hết rùi bạn dumb đọc chẳng hiểu dĩ nhiên chẳng giúp bạn đâu Tơi cố gắng giải thích cặn kẽ nhằm giúp bạn hiểu chương trình làm việc Tất cịn lại phụ thuộc vào bạn Readers requirements Trong sách này, sử dụng ngôn ngữ Delphi để viết chương trình Nhưng thực tế hồn tồn lập trình khơng sử dụng đến component không sử dụng đến Window API mà thông qua thư viện xây dựng riêng nên gần bạn cần biết Object Pascal hiểu mã chương trình làm việc nào, cố gắng viết mã cách chân phương – khơng tối ưu, tơi có thời gian wé - nhằm mục đích để người cảm thấy dễ hiểu chuyển sang ngơn ngữ khác, theo tính tốn tơi chương trình chuyển sang ngơn ngữ lập trình bậc cao thơng dụng VB, C, C++, C# Java Về mặt đồ hoạ không sử dụng hệ thống 3D phức tạp mà thiết kế với hệ thống 2D sprite animation đơn giản, chắn đa số bạn hiểu kĩ thuật thô sơ Mã nguồn liệu game cung cấp kèm theo đầy đủ, bạn cần biên dịch lại chạy System & Software requirements • • • • • Hệ thống PIII 500Mhz, 64MB RAM, card hình 8MB, hình hỗ trợ chế độ phân giải 800x600x16bit màu, có card sound (Thực tế tơi chưa chạy thử máy có cấu hình yếu nên khơng rõ có chạy hay khơng) Windows 95, 98, 98SE, NT, 2000 XP DirectX 8.1 trở lên Biên dịch Borland Delphi Borland Delphi Nếu bạn cần chỉnh sửa liệu game cần thêm trình soạn thảo ảnh (Photoshop, ACD FotoCanvas…) Misc • Tơi viết sách chủ yếu hướng đến bạn gần chưa biết lập trình game có dụng ý chia sẻ chút kiến thức ỏi thân, q trình biên tập có chút sơ sót mong bạn lượng thứ, sách làm bạn cảm thấy hứng thú muốn trao đổi thêm với tơi bạn liên lạc qua địa e-mail kimngan2508@yahoo.com (Đây địa mirror thôi, đừng bomb tui nha, he he) qua YIM: kimngan2508 © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding • Cuốn sách tơi viết hồn tồn khơng nhằm mục đích thương mại, tồn mã nguồn chương trình sách phân phối miễn phí, tơi khơng chấp nhận hành vi kinh doanh dựa tập sách chương trình Đối với chương trình, bạn tuỳ nghi sử dụng, nâng cấp, cần để record ghi nâng cấp từ chương trình CrazyBabe Nhưng tơi nghĩ bạn nên viết lại hồn tồn (nếu muốn làm game thực sự) chương trình khơng tốt • Trong chương trình, ngại thiết kế hình ảnh âm nên tơi mượn tạm hình ảnh âm loạt game Starcraft nhà sản xuất Blizzard Entertainment (Hì hì, chả bít nên khơng bị kiện) © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding Chapter II: Game Design Design a very simple RTS game Như nói trước đây, tơi viết sách khoảng thời gian ngắn (Chỉ bốn ngày viết mã viết tài liệu) nên đối tượng game tơi sử dụng phải tương đối đơn giản (Do lí hạn chế thời gian trình độ nữa, hì hì…) Ở tơi thiết kế game thể loại RTS 2D tính hạn chế Tơi xây dựng game hồn tồn khơng hỗ trợ chế độ multiplayer, hi vọng thời gian đến tơi có thời gian để nâng cấp game lên hỗ trợ chế độ Và loại bỏ số yếu tố mà cho đơn giản chế độ menu, chọn đồ, loại quân… mà nhảy vào chương trình load đồ mặc định chạy đồ trận chiến kết thúc bạn chán wá ngồi – he he - tức quan tâm đến chế độ battle trị chơi mà thơi, bỏ qua tất yếu tố khác Một game RTS xoay quanh số yếu tố sau: chế khai thác tài nguyên, chế sinh sản đơn vị quân, tính đơn vị quân cách chúng cơng, kiểu địa hình yếu tố quan trọng Game thiết kế sơ sau: • Thể loại chiến tranh khơng gian - Starwars lun, chiến chưa ? :) • Khơng có địa hình, loại bỏ bớt yếu tố phức tạp cho địa hình Cái nhằm để dễ lập trình • Game gồm hai loại đơn vị tàu mẹ tàu Tàu mẹ trung tâm đảm nhận việc xây dựng tàu con, lưu giữ tài nguyên… Tàu đảm nhận nhiều nhiệm vụ khác tuần tiễu, cơng, khai thác… • Các đơn vị tàu có tính di chuyển, công, tuần tiễu, khai thác, xây tàu • Hệ thống phím tắt cố định (Tơi bỏ qua việc xây dựng hệ thống menu điều khiển) • Hệ thống xây dựng game 2D © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding Sơ vậy, tính khác tơi nghĩ bạn thêm vào đơn giản hiểu chương trình Nếu muốn nâng cấp game thành 3D tơi nghĩ làm Dưới screen shot từ game này: Game programming environment Các bạn trao đổi với lập trình game thường trao đổi với vấn đề cụ tỉ vẽ DirectX hay OpenGL, làm để lấy sprite vẽ sprite hiệu ứng nào…thiết nghĩ thứ q lặt vặt – dĩ nhiên khơng nói đến chuyện thiết kế engine 3D lớn rùi – Trong lập trình game này, tơi sử dụng thư viện AvenusHelper thiết kế nhằm giảm tối đa công việc bạn cần thực thi chi tiết với hệ thống khởi tạo đồ hoạ, đọc ảnh vẽ ảnh hiệu ứng đơn giản add, sub, mul…Ở bạn cần ý đến việc làm game chạy được, unit xử lý nào, máy tính chơi sao, kiện xử lý nào…mà Nếu cần quan tâm đến chi tiết làm để thực hiệu ứng alpha blend chẳng hạn bàn sau - tập sách khác © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding Chapter III: Game Coding Chương đơn giản thích mã nguồn chương trình Dưới mã nguồn đơn vị Game, thành phần chương trình { Tơi đặt định nghĩa nhằm chương trình chạy chế độ tồn hình hay chế độ cửa sổ } {$Define FullScreen} { Định nghĩa nhằm xác định chương trình có hỗ trợ âm hay không } {$Define SoundPlaying} UNIT Game; INTERFACE { Ở khai báo đơn vị mà chương trình sử dụng } USES Windows, MMSystem, SysUtils, Math, FireStormDLL, AvenusHelperDLL; CONST { ScrWidth x ScrHeight định nghĩa kích thước cửa sổ độ phân giải chế độ tồn hình Chú ý chương trình chế độ cửa sổ tức biên dịch khơng có thị FullScreen kích thước tuỳ ý, chương trình chạy chế độ tồn hình kích thước độ phân giải phải hình hỗ trợ thường độ phân giải thông dụng là: 640x480, 800x600, 1024x768, 1152x864, 1280x1024… © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding } ScrWidth ScrHeight { = 1024; = 768; Caption xâu định nghĩa tên cửa sổ chương trình tạo } Caption = 'Simple RTS Game Demo [C]CrazyBabe.2003'; { MaxUnit số định nghĩa số lượng unit lớn mà chương trình hỗ trợ xử lý, số tui đặt đại zậy mà xử lý thực tế (chương trình hồn tồn khơng tối ưu) cần khoảng 4000 P4 tui die hard lun không cần phải thử máy cấu hình yếu đâu :> } MaxUnit = 8000; { DataPath đường dẫn đến thư mục chứa liệu chương trình } DataPath = 'Data\'; { ShipsSettingDir đường dẫn đến thư mục chứa file liệu loại tàu game } ShipsSettingDir = 'ShipsSetting\'; { ScrollSpeed tốc độ di chuyển minimap game, tơi đặt biến số nhằm mục đích thay đổi tốc độ phần tui chưa viết, bạn tự thêm vào nha } ScrollSpeed : Word = 15; { MoveFarLeng, TooNearLeng, AroundLeng số độ lớn giới hạn ví dụ giới hạn tàu gần nhau… } MoveFarLeng = 10; TooNearLeng = 3; AroundLeng = 100; { ScreenUpDate khoảng thời gian (phần nghìn giây) mà chương trình thực thi cập nhật lại hình Với giá trị 33 chương trình cập nhật khoảng 28-30 lần giây UnitUpDate khoảng thời gian mà chương trình thực xử lý cho đơn vị, với giá trị 10 chương trình xử lý đơn vị trung bình khoảng 70 lần giây InputUpDate, MiniMapUpDate khoảng thời gian chương trình thực cập nhật bàn phím, chuột… cập nhật lại minimap (Bản đồ con) MoneyTime khoảng thời gian chương trình thêm xiền cho phe } ScreenUpdate : LongWord = 33; UnitUpdate : LongWord = 10; InputUpdate : LongWord = 10; MiniMapUpdate : LongWord = 10; MoneyTime : LongWord = 120000; { DefaultMoney số xiền game cho phe lần “cấp phát” } DefaultMoney = 10000; { PanelSizeX, PanelSizeY kích thước Panel thể thông tin đơn vị chọn MiniMapSizeX, MiniMapSizeY kích thước đồ nhỏ hiển thị hình © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding } PanelSizeX PanelSizeY MiniMapSizeX MiniMapSizeY = = = = 700; 80; 200; 200; { Cứ sau khoảng FrameRateForFindTarget frame chương trình thực tìm kiếm mục tiêu cho đơn vị khơng có lệnh } FrameRateForFindTarget = 40; TYPE { Định nghĩa kiểu để đánh số đơn vị game } TUnitCount = MaxUnit; { Định nghĩa kiểu toạ độ nguyên toạ độ thực } TRPoint = Record X,Y : Single; End; TPoint = Record X,Y : Integer; End; { Định nghĩa số hướng đơn vị xoay 32 hướng Số hướng nhiều đơn vị xoay mịn, xây dựng với 3D khơng cần đến định nghĩa số hướng mà cần lưu lại góc nhìn đơn vị Hic, chóng mẹt wé… } THeading = ( H01,H02,H03,H04, H05,H06,H07,H08, H09,H10,H11,H12, H13,H14,H15,H16, H17,H18,H19,H20, H21,H22,H23,H24, H25,H26,H27,H28, H29,H30,H31,H32); { Định nghĩa số kiểu tàu có game, hik, bạn bịa tên ok… } TSpaceShip = ( NoneShip, FirePlanet, SupperBattleShip, BattleCruiseAmon, BattleCruiseBaton, CooNok, Scout, Interceptor, Carrier, MiniMissile, EvelMissile, MileMissile, Burn ); { © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding WaitTimeForMove:=_TurnWait*20; End Else //Turn ship ? If CurrentHeadHead then Begin CurrentHead:=HeadNear(CurrentHead,Head); WaitTimeForMove:=_TurnWait; End Else Begin For Z:=1 to _Speed Begin _Heading:=UnitGetBestHeading(UnitNum); Pos.X:=Pos.X+Moving[_Heading,1]; Pos.Y:=Pos.Y+Moving[_Heading,2]; End; WaitTimeForMove:=_Wait; End; End; End; PROCEDURE TGame.ProceedUnitAttackP(UnitNum : TUnitCount); Var _Heading : THeading; Z : Integer; Begin With GameUnits[UnitNum], UnitsProperty[Typer] Begin If WaitTimeForMove>0 then Begin Dec(WaitTimeForMove); Exit; End; If UnitGetNextCmd(UnitNum) then Exit; If GameUnits[UnitTarget].HitPoint0 then Begin Dec(WaitTimeForMove); Exit; End; If UnitGetNextCmd(UnitNum) then Exit; If GameUnits[UnitTarget].HitPoint0 then Begin Dec(WaitTimeForMove); Exit; End; If UnitGetNextCmd(UnitNum) then Exit; If UnitCloseToTarget(UnitNum,MoveFarLeng) then Begin If UnitGetNextCmd(UnitNum) then Else UnitCmd:=NoCmd; End Else //Turn ship ? If CurrentHeadHead then Begin CurrentHead:=HeadNear(CurrentHead,Head); WaitTimeForMove:=_TurnWait; End Else Begin For Z:=1 to _Speed Begin _Heading:=UnitGetBestHeading(UnitNum); Pos.X:=Pos.X+Moving[_Heading,1]; Pos.Y:=Pos.Y+Moving[_Heading,2]; End; If IsFrameToFindTarget then Begin Num:=UnitFindTarget(UnitNum); If NumLow(TUnitCount) then Begin UnitCmd:=NoCmd; UnitSetAttackMove(UnitNum,Num); Exit; End; End; WaitTimeForMove:=_Wait; //Increase unit frame If CurrentFrame< _ShipAni.Move[CurrentHead].NumFrames-1 then Inc(CurrentFrame) Else CurrentFrame:=0; End; End; End; PROCEDURE TGame.ProceedUnitPatrol(UnitNum : TUnitCount); Var _Heading : THeading; Z : Integer; Num : TUnitCount; Begin © CrazyBabe 2003 K-Outertainment™ Trang 51 Simple ЯTS G∆me Dεsign & CΘding With GameUnits[UnitNum], UnitsProperty[Typer] Begin If WaitTimeForMove>0 then Begin Dec(WaitTimeForMove); Exit; End; If UnitGetNextCmd(UnitNum) then Exit; If UnitCloseToTarget(UnitNum,MoveFarLeng) then Begin If UnitGetNextCmd(UnitNum) then Else Begin Dest:=PatrolStart; PatrolStart:=PatrolDest; PatrolDest:=Dest; UnitPointToTarget(UnitNum); End; End Else //Turn ship ? If CurrentHeadHead then Begin CurrentHead:=HeadNear(CurrentHead,Head); WaitTimeForMove:=_TurnWait; End Else Begin For Z:=1 to _Speed Begin _Heading:=UnitGetBestHeading(UnitNum); Pos.X:=Pos.X+Moving[_Heading,1]; Pos.Y:=Pos.Y+Moving[_Heading,2]; End; If IsFrameToFindTarget then Begin Num:=UnitFindTarget(UnitNum); If NumLow(TUnitCount) then Begin UnitCmd:=NoCmd; UnitSetAttackPatrol(UnitNum,Num); Exit; End; End; WaitTimeForMove:=_Wait; //Increase unit frame If CurrentFrame< _ShipAni.Move[CurrentHead].NumFrames-1 then Inc(CurrentFrame) Else CurrentFrame:=0; End; End; End; PROCEDURE TGame.ProceedUnitBurning(UnitNum : TUnitCount); Begin //When unit burning, unit nothing else burning ! With GameUnits[UnitNum], UnitsProperty[Typer] Begin If WaitTimeForMove>0 then Begin Dec(WaitTimeForMove); Exit; © CrazyBabe 2003 K-Outertainment™ Trang 52 Simple ЯTS G∆me Dεsign & CΘding End; WaitTimeForMove:=_Wait; //Increase unit frame If CurrentFrame0) and (_DrawLevel=DrawLevel) then Begin RenderUnits(Z); End; End; PROCEDURE TGame.RenderUnits(UnitNum : TUnitCount); Var X,Y,X1,Y1,X2,Y2, SprNum,Effects : Integer; Visible : Boolean; Begin With GameUnits[UnitNum], UnitsProperty[Typer] If HitPoint>0 then Begin //Unit visible ? Visible:=UnitVisible(UnitNum); //Drawing unit X:=Round(Pos.X)-GameWorld.ViewPos.X; Y:=Round(Pos.Y)-GameWorld.ViewPos.Y; If Visible then Case Typer of FirePlanet : © CrazyBabe 2003 K-Outertainment™ Trang 53 Simple ЯTS G∆me Dεsign & CΘding Begin ImageRenderEffect(X-GetImageWidth(GlobeImageNum) ShR 1, Y-GetImageHeight(GlobeImageNum) ShR 1, GlobeImageNum,EffectSrcAlpha); ImageRenderEffectColor(X-GetImageWidth(FlareImageNum) ShR 1, Y-GetImageHeight(FlareImageNum) ShR 1, TransparentLevel ShL 16+ TransparentLevel ShR 8+ TransparentLevel, FlareImageNum,EffectAdd); End; Else Begin //Unit is selection ? If UnitGroup and 128=128 then Begin Rect(X-_Size2,Y-_Size2, X+_Size2,Y+_Size2,Green,EffectNone); TextOut(X-_Size2,Y-_Size2, Format('HP: %d/%d',[HitPoint,_HitPoint]),White); End; Case UnitCmd of NoCmd, CmdFire, CmdMove, CmdAttack, CmdAttackP, CmdAttackT, CmdAttackM, CmdPatrol, CmdBurn : Begin SprNum:=_ShipAni.Move[CurrentHead] Ani[CurrentFrame].FramePos; Case _ShipAni.Move[CurrentHead] Ani[CurrentFrame].FrameStyle of 02 : Effects:=EffectAdd; Else Effects:=EffectSrcAlpha; End; ImageRenderEffect(X-GetImageWidth(_Images[SprNum]) ShR 1, Y-GetImageHeight(_Images[SprNum]) ShR 1, _Images[SprNum],Effects); End; End; End; End; If ShowDebug then Begin If UnitCmd in [CmdMove,CmdAttack,CmdAttackP, CmdAttackT,CmdAttackM,CmdPatrol] then Begin TextOut(X,Y,HeadingName[CurrentHead], White,EffectNone); X1:=Round(Pos.X)-GameWorld.ViewPos.X; Y1:=Round(Pos.Y)-GameWorld.ViewPos.Y; X2:=Round(Dest.X)-GameWorld.ViewPos.X; Y2:=Round(Dest.Y)-GameWorld.ViewPos.Y; Line(X1,Y1,X2,Y2,White,EffectNone); End; End; RenderBuffer; © CrazyBabe 2003 K-Outertainment™ Trang 54 Simple ЯTS G∆me Dεsign & CΘding End; End; PROCEDURE TGame.RenderInfos; Var Tick : LongWord; Begin Case MouseCommand of MouseSelection : Begin Rect(SelectStart.X,SelectStart.Y, SelectEnd.X,SelectEnd.Y, White,EffectNone); End; End; If ShowFPS then Begin Tick:=MMSystem.TimeGetTime-GameStart; If Tick0 then Begin TextOut(0,40,Format('UFPS : %0.2f',[GameFrame/Tick*1000]),White); TextOut(0,60,Format('SFPS : %0.2f',[GameScreenFrame/Tick*1000]),White); TextOut(0,80,Format('Unit used : %d',[UnitCounting]),White); End; End; //Show mini map ? If MiniMapVisible then Begin Bar(MiniMapPosX-1,MiniMapPosY-1, MiniMapPosX+MiniMapSizeX+1, MiniMapPosY+MiniMapSizeY+1, Gray,EffectAdd); ImageRenderEffect(MiniMapPosX,MiniMapPosY, MiniMapImage,EffectAdd); End; //Show command panel ? If CommandPanelVisible then Begin Bar(PanelPosX-1,PanelPosY-1, PanelPosX+PanelSizeX+1, PanelPosY+PanelSizeY+1, BlueGray,EffectAdd); If FirstUnitSelectLow(TUnitCount) then Begin With GameUnits[FirstUnitSelect], UnitsProperty[Typer] Begin TextOut(PanelPosX,PanelPosY, ShipName[Typer],White); TextOut(PanelPosX,PanelPosY+20, Format('HP: %d/%d',[HitPoint,_HitPoint]),White); TextOut(PanelPosX,PanelPosY+40, Format('Damage: %d Speed: %d', [_Damage,_Speed]),White); TextOut(PanelPosX,PanelPosY+60, Format('Range: %d Gun: %s', [_AttackRange,GunName[_Gun]]),White); If _ShipCanCreateLow(TSpaceShip) then Begin If CreationCounting=0 then Begin TextOut(PanelPosX+400,PanelPosY, Format('Press C to create %s', [ShipName[_ShipCanCreate]]),White); © CrazyBabe 2003 K-Outertainment™ Trang 55 Simple ЯTS G∆me Dεsign & CΘding End Else Begin TextOut(PanelPosX+400,PanelPosY, Format('Create %s: %d/%d', [ShipName[_ShipCanCreate], CreationCounting, UnitsProperty[_ShipCanCreate] _BuildTime]),White); End; End; End; End; End; //Show player's money and units counting TextOut(0,0,Format('Money: %d Units: %d', [GamePlayers[HumanControl].Money, GamePlayers[HumanControl].CountUnit]),White); End; PROCEDURE TGame.RenderScene; Begin If GameTime-LastGameScreenTime>ScreenUpdate then Begin LastGameScreenTime:=GameTime; Inc(GameScreenFrame); BeginRender; RenderWorld; RenderUnits; RenderInfos; EndRender; End; End; FUNCTION TGame.GetShipTyper(Name : String) : TSpaceShip; Var Z : TSpaceShip; Begin For Z:=Low(TSpaceShip) to High(TSpaceShip) If ShipName[Z]=Name then Begin Result:=Z; Exit; End; Result:=Low(TSpaceShip); End; FUNCTION TGame.GetPlayer(Name : String) : TPlayer; Var Z : TPlayer; Begin For Z:=Low(TPlayer) to High(TPlayer) If PlayerName[Z]=Name then Begin Result:=Z; Exit; End; Result:=Low(TPlayer); End; FUNCTION TGame.GetHeading(Name : String) : THeading; Var Z : THeading; Begin For Z:=Low(THeading) to © CrazyBabe 2003 K-Outertainment™ Trang 56 Simple ЯTS G∆me Dεsign & CΘding High(THeading) If HeadingName[Z]=Name then Begin Result:=Z; Exit; End; Result:=Low(THeading); End; FUNCTION TGame.GetGun(Name : String) : TGun; Var Z : TGun; Begin For Z:=Low(TGun) to High(TGun) If GunName[Z]=Name then Begin Result:=Z; Exit; End; Result:=Low(TGun); End; END © CrazyBabe 2003 K-Outertainment™ Trang 57 Simple ЯTS G∆me Dεsign & CΘding Chapter IV: Sumary Final ? Như có game RTS (xạo) khơng hồn chỉnh Với game mà tung “thị trường” cầm là…chít thảm, he he Nhưng hi vọng với code bạn hiểu sơ sơ việc viết mã cho game phân rã Với game chưa thể gọi game RTS, thời gian phát triển q nên chứa đầy lỗi Như công việc bạn sửa lỗi nâng cấp khung Với chương trình này, tơi chưa comment cách đầy đủ thiếu thời gian, tơi nghĩ bạn hiểu cách viết tơi dễ hiểu Nếu không hiểu rõ lắm, mail cho tôi, tơi dành thời gian thích rõ ràng Upgrade Mặc dù không test nhiều tui chắn chương trình chứa số lỗi sau: • Có lúc kéo chuột để chọn qn lại khơng (Kì chưa ?) • Có lúc đặt lệnh (khơng nhớ lệnh gì) unit lại chạy chỗ khác (Kì ?) • ….Chắc cịn nhìu lỗi tui chưa tìm ra… Cơng việc bạn sửa lỗi tối ưu hố chương trình Cạnh tơi nghĩ chương trình cịn cần nâng cấp số tính sau: • Mặc dù đặt lệnh cho nhóm qn (Move, Patrol…) tơi cố tình đặt cho vị trí đích lệnh lệch chút, chắn có trường hợp unit nằm đè rít rịt lên (hic) Bạn cần thêm tính tự “dãn” cho đơn vị Gợi ý: Hix, kiểm soát số lượng unit bị coi “chồng nhau” ? Có thể cách thực thi chậm • Tồn đơn vị đồ bị nhìn thấy (?) tức chương trình chưa tính đến “fog of war” Gợi ý: cập nhật theo thời gian MiniMap, unit © CrazyBabe 2003 K-Outertainment™ Trang 58 Simple ЯTS G∆me Dεsign & CΘding • • • • • tầm nhìn đơn vị thuộc phe người chơi đánh dấu lại Vấn đề phải viết hàm cho nhanh (hix) Các đơn vị game giới hạn sinh loại qn khơng, tính nâng cấp thành cho phép chọn loại quân sinh Bạn cần thêm list loại quân sinh vào liệu đặc tính unit game, sau xây dựng hệ thống menu cho game để người chơi lựa chọn tính sinh qn Các tính di chuyển, cơng cần hiển thị rõ ràng thông qua hệ thống menu Trong game chưa có khai thác tài nguyên, thêm cơng việc khiến game có tính cạnh tranh hơn, khó tính tốn AI cho máy nhiều game thường giảm nhẹ quan tâm đến vấn đề (?) Nâng cấp tính AI: Hiện game hồn tồn chưa có AI, đơn vị quân máy đơn giản sinh quân ầm ầm rùi chạy toán loạn quanh đồ Bạn nên xây dựng modun cho phép máy điều khiển quân tập trung lại rùi “lùng giết” quân người chơi hiệu Hoàn thiện tính âm game Game cần xây dựng modun quản lý âm riêng, thực thi âm gọi nên có thơng số vị trí, kiểu âm thanh… nhằm xác định độ to nhỏ loại bỏ bớt âm loại gọi liên tục, ví dụ đám tàu bắn tên lửa chẳng hạn, modun phát 2/3 âm bắn mà đạt hiệu tương đương ….Tiếp tục tùy ý bạn….Hix, cơng việc cịn nhìu phía trước hix hix… Dưới screen shot từ game RTS tơi phát triển: © CrazyBabe 2003 K-Outertainment™ Trang 59 Simple ЯTS G∆me Dεsign & CΘding Reference AvenusHelper • Định nghĩa kiểu: o TBitDepth: Kiểu độ sâu màu hình BD16Bit: Độ sâu màu 16bit BD32Bit: Độ sâu màu 32bit o TImageFormat: Kiểu format ảnh FormatR3G3B2: Ảnh 8bit (Red 3bit, Green 3bit, Blue 2bit) FormatX4R4G4B4: Ảnh 16bit (Mask 4bit, Red 4bit, Green 4bit, Blue 4bit) FormatA4R4G4B4: Ảnh 16bit (Alpha 4bit, Red 4bit, Green 4bit, Blue 4bit) FormatA8R3G3B2: Ảnh 16bit (Alpha 8bit, Red 3bit, Green 3bit, Blue 2bit) FormatR5G6B5: Ảnh 16bit (Red 5bit, Green 6bit, Blue 5bit) FormatX1R5G5B5: Ảnh 16bit (Mask 1bit, Red 5bit, Green 5bit, Blue 5bit) FormatA1R5G5B5:Ảnh 16bit (Alpha 1bit, Red 5bit, Green 5bit, Blue 5bit) FormatX8R8G8B8: Ảnh 32bit (Mask 8bit, Red 8bit, Green 8bit, Blue 8bit) FormatA8R8G8B8:Ảnh 32bit (Alpha 8bit, Red 8bit, Green 8bit, Blue 8bit) • Định nghĩa hằng: o EffectNone: Vẽ khơng hiệu ứng o EffectAdd: Vẽ kiểu cộng o EffectSrcAlpha: Vẽ theo kênh alpha ảnh, áp dụng với ảnh có kênh alpha o EffectSrcAlphaAdd: Vẽ kiểu cộng theo kênh alpha ảnh, áp dụng với ảnh có kênh alpha o EffectMul: Vẽ theo kiểu nhân o EffectSrcColor: Vẽ sử dụng màu source kênh alpha o EffectSrcColorAdd: Vẽ kiểu cộng, sử dụng màu source kênh alpha o EffectInvSrcColor: Vẽ với giá trị màu nguồn đảo ngược o EffectInvSrcAlpha: Vẽ với giá trị kênh alpha đảo ngược © CrazyBabe 2003 K-Outertainment™ Trang 60 Simple ЯTS G∆me Dεsign & CΘding o o o o o o o o • EffectInvSrcMask: Vẽ với giá trị mask đảo ngược EffectBlend1, EffectBlend2, EffectBlend3, EffectBlend4: Các kiểu hiệu ứng blend ảnh thử nghiệm EffectShadow: Vẽ bóng EffectBlendColor: Vẽ blend với màu nguồn EffectBlendColorAlphaChannel: Vẽ blend sử dụng kênh alpha EffectAddDiffuse, EffectDiffuseAlpha: Vẽ khuếch tán với kênh alpha EffectMirror, EffectFlip: Vẽ lật hình, hiệu ứng kết hợp với hiệu ứng Các số Key_# số định nghĩa số hiệu phím, bạn dễ dàng đốn đại diện cho phím nào, tơi khơng thích dài Các hàm, lệnh: o Hàm CreateWindow(Width,Height : Integer;Title : PChar) : Boolean Tạo cửa sổ kích thước Width x Height có caption Title Hàm trả true tạo thành công, trả false không tạo cửa sổ o Hàm CreateFullScreen(Width,Height : Integer;ScreenDepth : TBitDepth;Title : PChar) : Boolean Khởi tạo chế độ hình Width x Height độ sâu màu ScreenDepth có caption Title Hàm trả true khởi tạo thành công, trả false không khởi tạo chế độ o Lệnh DestroyScreen Huỷ cửa sổ/chế độ tạo trước đó, sau gọi lệnh tất hàm vẽ, lấy phím… sinh lỗi chương trình huỷ handle quản lý tất dịch vụ o Hàm EventMessage : Boolean Kiểm tra events, trả false xuất event Quit o Lệnh LoadFont(FileName : String;SizeX,SizeY,Width,Height,TransColor : LongWord) Đọc font chữ từ file ảnh FileName o Lệnh TextOut(X,Y : Integer;Text : String;Color : LongWord) Viết xâu Text hình, toạ độ [X,Y], màu Color o Lệnh TextOut(X,Y : Integer;Text : String;Color : LongWord;Effect : Integer) Viết xâu Text hình, toạ độ [X,Y], màu Color Hiệu ứng Effect o Hàm CreateImage(SizeX,SizeY : Integer;Format : TImageFormat) : Integer Tạo ảnh có kích thước SizeX x SizeY với format Format Số trả số hiệu ảnh tạo o Hàm LoadImage(FileName : String;Format : TImageFormat) : Integer Đọc ảnh từ FileName, ảnh đọc vào với format Format Hỗ trợ định dạng ảnh JPEG, PNG, BMP Số trả số hiệu ảnh đọc o Hàm SetAlphaMask(ImageNum,TransparentColor : Integer) : Integer Đặt kênh Alpha cho tất điểm ảnh có màu Transparent Chỉ hỗ trợ format ảnh FormatA1R5G5B5 o Hàm GetImageWidth(ImageNum : Integer) : Integer Lấy độ rộng ảnh số hiệu ImageNum o Hàm GetImageHeight(ImageNum : Integer) : Integer Lấy độ cao ảnh số hiệu ImageNum o Hàm ImageLock(ImageNum : Integer) : Integer © CrazyBabe 2003 K-Outertainment™ Trang 61 Simple ЯTS G∆me Dεsign & CΘding Lock ảnh số hiệu ImageNum Hàm ImageUnLock(ImageNum : Integer) : Integer UnLock ảnh số hiệu ImageNum o Lệnh ImageClear(ImageNum : Integer;Color : Cardinal) Xoá ảnh ImageNum màu Color o Lệnh ImagePutPixel(ImageNum,X,Y : Integer;Color : Cardinal) Vẽ điểm ảnh màu Color toạ độ [X,Y] ảnh ImageNum o Hàm ImageGetPixel(ImageNum,X,Y : Integer) : Cardinal Lấy màu điểm ảnh Color toạ độ [X,Y] ảnh ImageNum o Lệnh ImageLine(ImageNum,X1,Y1,X2,Y2 : Integer;Color : Cardinal) Vẽ đường thẳng màu Color từ [X1,Y1] đến [X2,Y2] ảnh ImageNum o Lệnh ImageRect(ImageNum,X1,Y1,X2,Y2 : Integer;Color : Cardinal) Vẽ hình chữ nhật màu Color từ [X1,Y1] đến [X2,Y2] ảnh ImageNum o Lệnh ImageFillRect(ImageNum,X1,Y1,X2,Y2 : Integer;Color : Cardinal) Tơ hình chữ nhật màu Color từ [X1,Y1] đến [X2,Y2] ảnh ImageNum o Lệnh BeginRender Bắt đầu vẽ scene (xoá buffer, xoá render buffer) o Lệnh EndRender Kết thúc vẽ scene o Lệnh ClearScreen(Color : Cardinal) Xoá hình màu Color o Hàm RenderBuffer : Integer Dựng tồn hình render buffer o Lệnh SetClipRect(X1,Y1,X2,Y2 : Integer) Đặt clip rect o Lệnh Rect(X1,Y1,X2,Y2 : Integer;Color : Cardinal;Effect : Integer) Vẽ hình chữ nhật o Lệnh Bar(X1,Y1,X2,Y2 : Integer;Color : Cardinal;Effect : Integer) Tơ hình chữ nhật o Lệnh Line(X1,Y1,X2,Y2 : Integer;Color : Cardinal;Effect : Integer) Vẽ đường thẳng o Lệnh SmoothLine(X1,Y1,X2,Y2 : Integer;Color : Cardinal) Vẽ đường thẳng smooth (mịn) o Hàm ImageRenderEffect(XPos,YPos,Pattern,Effect : Integer) : Boolean Dựng ảnh Pattern vị trí [XPos, YPos] với hiệu ứng Effect o Hàm ImageRenderEffect(X1,Y1,X2,Y2,Pattern,Effect : Integer) : Boolean Dựng ảnh Pattern thành hình chữ nhật [X1,Y1,X2,Y2] với hiệu ứng Effect o Hàm ImageRenderEffect(XPos,YPos,Scale,Pattern,Effect : Integer) : Boolean Dựng ảnh Pattern vị trí [XPos, YPos] với hiệu ứng Effect Tỉ lệ zoom Scale/256 o Hàm ImageRenderEffectColor(XPos,YPos : Integer;Color : Cardinal;Pattern,Effect : Integer) : Boolean Dựng ảnh Pattern vị trí [XPos, YPos] với hiệu ứng Effect Màu áp Color o Hàm ImageRenderEffectColor(X1,Y1,X2,Y2 : Integer;Color : Cardinal;Pattern,Effect : Integer) : Boolean Dựng ảnh Pattern thành hình chữ nhật [X1,Y1,X2,Y2] với hiệu ứng Effect Màu áp Color o © CrazyBabe 2003 K-Outertainment™ Trang 62 Simple ЯTS G∆me Dεsign & CΘding o Hàm ImageRenderEffectColor(XPos,YPos : Integer;C1,C2,C3,C4 : LongWord;Pattern,Effect : Integer) : Boolean Dựng ảnh Pattern vị trí [XPos, YPos] với hiệu ứng Effect Màu áp bốn góc C1, C2, C3, C4 o Hàm ImageRenderEffectColor(XPos,YPos,Scale : Integer;Color : Cardinal;Pattern,Effect : Integer) : Boolean Dựng ảnh Pattern vị trí [XPos, YPos] với hiệu ứng Effect Tỉ lệ zoom Scale/256 Màu áp Color o Lệnh GetInputStatus Cập nhật input (Trạng thái mouse, keyboard…) o Hàm KeyDown(Key : Byte) : Boolean Kiểm tra phím Key có bị nhấn hay khơng ? o Hàm KeyPress(Key : Byte) : Boolean Kiểm tra phím Key có bị gõ hay không ? o Hàm MouseFirstClickL : Boolean Click chuột trái ? o Hàm MouseFirstClickR : Boolean Click chuột phải ? o Hàm MouseFirstClickM : Boolean Click chuột ? o Hàm MouseReleasedL : Boolean Thả chuột trái ? o Hàm MouseReleasedR : Boolean Thả chuột phải ? o Hàm MouseReleasedM : Boolean Thả chuột ? o Hàm MouseHoldL : Boolean Nhấn chuột trái ? o Hàm MouseHoldR : Boolean Nhấn chuột phải ? o Hàm MouseHoldM : Boolean Nhấn chuột ? o Hàm MouseX : Integer Toạ độ X chuột o Hàm MouseY : Integer Toạ độ Y chuột o Hàm CreateSound(FileName : String;Loop : Boolean) : Integer Tạo handle cho sound FileName Trả handle quản lý sound o Lệnh SoundPlay(Slot : Integer) Chơi sound số hiệu slot o Lệnh SoundPause(Slot : Integer) Tạm dừng sound số hiệu slot o Lệnh SoundStop(Slot : Integer) Dừng sound số hiệu slot o Lệnh SoundSetVolume(Slot : Integer;Value : Byte) Đặt cường độ âm cho Slot o Hàm SoundGetVolume(Slot : Integer) : Byte Lấy cường độ âm Slot © CrazyBabe 2003 K-Outertainment™ Trang 63 .. .Simple ЯTS G∆me Dεsign & CΘding Simple ЯTS G∆me Dεsign & Cding OpenEdition e Copyright â 23 by CzƠBab All rights reserved June 6th, 2003 © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me. .. khởi đầu với dòng game Dune, Command & Conquer Westwood Studio nhanh chóng trở thành dịng © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding game ăn khách toàn giới Việt... bít nên khơng bị kiện) © CrazyBabe 2003 K-Outertainment™ Trang Simple ЯTS G∆me Dεsign & CΘding Chapter II: Game Design Design a very simple RTS game Như nói trước đây, tơi viết sách khoảng thời