程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> Delphi >> 【FOL】第三周,fol第三周

【FOL】第三周,fol第三周

編輯:Delphi

【FOL】第三周,fol第三周


這周還是在改自己的這個框架,被多線程折騰了兩天,最終無奈放棄在游戲啟動時調用引擎進行圖片相關資源的初始化,當然進展還是不錯的。

嗯,下面還是以流水的方式繼續記錄一下本周完成的工作:

1、調通了客戶端與lua的相互調用,用的是verysimple這個第三方庫(跨平台的庫)。這邊遇到一個坑,特此記錄。

    我用的版本lua5.3,似乎官方已經取消了module函數,反正我在lua文件裡面直接寫“module(模塊名,package.seeall)”,require這個lua文件的時候會報錯。網上查了不少資料,據說module方法效率慢,而且極易污染全局空間,官方並不提倡使用。看來真有可能新版本把這個方法給丟棄了。反正我是沒辦法再去花時間找原因了(已經浪費了大半天時間,而且有個前輩勸我說不要用這個方法)。後來實現的代碼如下,在此特別感謝 "廣州-隨雲" 的無私幫助。

local module_notice = {}

function module_notice:open()
    client.monitor:register(1100,module_notice.OnClose);
    createScene("notice");
end

function module_notice:OnClose()
    closeScene("notice");
    client.monitor:unRegister(1100,module_notice.OnClose);
end

return module_notice
testLua('lua system running');

notice = require "script/module_notice";
notice:open();

2、關於資源的加載:本來的思路是游戲啟動時載入一個base.data的資源包,顯示一個載入界面(包含背景圖、logo、進度條、默認字體等等),然後同時開個網絡線程進行自動更新,自動更新完再開一個線程進行各種配置文件、聲音文件、腳本文件、字體文件、圖片資源文件的加載/初始化。但是前面幾個操作在線程裡面都沒有問題,就是有兩個地方無法做到:

    1)lua文件,不能統一加載到一個列表中,否則lua文件中用require函數無法正常載入。

    2)用pxl(asphyre)引擎進行圖片資源的加載及初始化,在線程裡面各種錯誤。首先,報“ECannotCreateWICImagingFactory”錯誤,加了"{$IFDEF MSWINDOWS}CoInitialize(nil);{$ENDIF}"代碼後,不再報錯了。然後在初始化圖片時,偶爾會報浮點錯誤,這個搞了一天多愣是沒解決,問了pxl的作者,他回復我在主線程初始化不會有錯(ps:這個我知道的,作者自己的游戲就是啟動的時候開了個窗口在初始化)。沒辦法了,後來整理了一下思路,最終決定在解析配置的時候進行初始化。具體實現看下面幾段代碼。

function TFOLScene.createButton(const pvParent: TFOLSprite; const pvName,
  pvRectSet, pvImageName: string; const pvMsgcode: Integer;
  const pvText: string): TFOLButton;
var
  lvRect: TIntRect;
  lvImageAry: TButtonImageAry;
begin
  lvRect:= parseRect(pvRectSet);
  gvArchiveManager.require(pvImageName, lvImageAry);

  result:= TFOLButton.Create(pvParent);
  result.ObjType:= tstUI_Button;
  result.Name:= pvName;
  result.X:= lvRect.Left;
  result.Y:= lvRect.Top;
  result.Width:= lvRect.Width;
  result.Height:= lvRect.Height;
  result.EventID:= pvMsgcode;
  result.Text:= pvText;
  result.setButtonImage(lvImageAry);
  FObjects.Add(pvName,result);
end;
procedure TFOLArchiveManager.require(const pvName: string;
  out pvOuter: TButtonImageAry);
var
  lvEnum: TFOLButtonState;
  lvSuffix, lvFullName: string;
begin
  for lvEnum:= Low(TFOLButtonState) to High(TFOLButtonState) do
  begin
    pvOuter[lvEnum]:= nil;
    lvSuffix:= gcButtonStateImageNameSuffix[lvEnum];
    lvFullName:= pvName+lvSuffix;
    pvOuter[lvEnum]:= loadImage(lvFullName, pvOuter[tbsNormal]);
  end;
end;

function TFOLArchiveManager.loadImage(const pvName: string;
  pvDefaultImage: TAtlasImage): TAtlasImage;
var
  lvIndex: Integer;
  lvStream: TStream;
begin
  result:= FEngineImages.Image[pvName];
  if not Assigned(result) then
  begin
    FGameImages.TryGetValue(pvName, lvStream);
    if Assigned(lvStream) then
    begin
      lvIndex:= FEngineImages.AddFromStream('.png',lvStream,pvName);
      result:= FEngineImages.Items[lvIndex];
    end
    else if Assigned(pvDefaultImage) then
      result:= pvDefaultImage
    else
      result:= FEngineImages.Image['globa_error'];
  end;
end;

3、實現了UI消息的轉發,下面代碼以按鈕點擊為例(代碼比較粗糙,看看知道怎麼回事就行)

{ TFOLButton }

procedure TFOLButton.render();
var
  lvButtonState: TFOLButtonState;
  lvHint: string;
begin
  lvButtonState:= tbsNormal;
  if PointInRect(Point2px(Trunc(gvEngineMouseData.X), Trunc(gvEngineMouseData.Y)),
                 IntRect(FWorldX, FWorldY,FWidth,FHeight)) then
  begin
    case gvEngineMouseData.State of
      1:
        begin
          lvButtonState:= tbsActive;
          lvHint:= 'down:' + FName;  //按鈕圖片切換到按下態,這裡可以處理長按事件
        end;
      2:
        begin
          lvButtonState:= tbsNormal;
          gvEngineMouseData.State:= 0;
          gvGameMonitor.execMsgfunc(FEventID);
          lvHint:= 'up:' + FName;    //按鈕圖片切換回常態,這裡可以觸發點擊事件並做相應處理
        end;
      3:
        begin
          lvButtonState:= tbsHover;
          lvHint:= 'move:' + FName;  //圖片切換到高亮態
        end;
      4:
        begin
          lvButtonState:= tbsNormal;
          lvHint:= 'wheel:' + FName; //一般根據WheelDelta處理一些縮放、列表滾動等事件
        end;
    end;
  end;
  gvEngineCanvas.UseImagePx(FButtonImageAry[lvButtonState], FloatRect4(0, 0, FWidth, FHeight));
  gvEngineCanvas.TexQuad(FloatRect4(FWorldX, FWorldY, FWidth, FHeight), IntColorWhite4, TBlendingEffect.Normal);
  inherited;
end;

procedure TFOLButton.setButtonImage(pvImageAry: TButtonImageAry);
var
  lvEnum: TFOLButtonState;
begin
  for lvEnum:= Low(TFOLButtonState) to High(TFOLButtonState) do
    FButtonImageAry[lvEnum]:= pvImageAry[lvEnum];
end;

monitor單元的相關代碼:

procedure TFOLGameMonitor.execMsgfunc(const pvMsgCode: Integer);
var
  lvInvokeEvent: TNotifyEvent;
  lvData: TFOLInvokeScriptFuncObject;
begin
  FEventListener.TryGetValue(1, lvInvokeEvent);
  if Assigned(lvInvokeEvent) then
  begin
    lvData:= TFOLInvokeScriptFuncObject.Create(gcExecLuaMsgFuncName);
    lvData.pushInteger(pvMsgCode);
    lvInvokeEvent(lvData);
  end;
end;

 

小結:目前基本上就是實現如下:

1、游戲啟動後,顯示一個啟動頁面(背景、logo、進度條、進度文字)

2、連接到版本服務器自動下載最新的資源文件更新(線程中,通過信號量反饋下載進度)

3、加載配置文件、聲音文件(線程中,通過信號量反饋載入進度)

4、資源載入完畢,運行app.lua,app.lua會調用客戶端函數根據傳入的ui名稱,創建一個頁面(現在是公告頁面)。

5、點擊公告頁面上的關閉按鈕,觸發notice.lua中的關閉頁面事件,調用客戶端的關閉頁面方法把此scene.visible設置為false,這樣在渲染循環裡面就不會去渲染這個頁面,達到不顯示的目的。

 

接下去應該是會考慮把主界面配置起來,同步完善一些ui控件。好吧,就這樣吧。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved