【FOL】第三周

来源:http://www.cnblogs.com/crymm/archive/2016/07/01/5634274.html
-Advertisement-
Play Games

這周還是在改自己的這個框架,被多線程折騰了兩天,最終無奈放棄在游戲啟動時調用引擎進行圖片相關資源的初始化,當然進展還是不錯的。 嗯,下麵還是以流水的方式繼續記錄一下本周完成的工作: 1、調通了客戶端與lua的相互調用,用的是verysimple這個第三方庫(跨平臺的庫)。這邊遇到一個坑,特此記錄。 ...


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

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

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控制項。好吧,就這樣吧。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、搭建定時任務quartz 本來是打算把定時任務放入後臺管理中,這樣目前沒問題,但是弱後期加入許可權管理-shiro,那麼肯定有衝突的,原因是最新版的shiro會使用quartz-1.6版本,而最新的quartz已經到了2.3 有人索性把quartz版本降到了1.6,這樣就沒問題,我想這樣不好,2. ...
  • 從c++轉到java,初學struts,竟然碰到一個因寫錯單詞而造成的錯誤,structs --> struts ...
  • 這是個對於讀寫鎖中級剖析文章, 會自己實現讀寫鎖的細節.歡迎用到自己的項目中. ...
  • 在 HttpRequest 對象中,屬性 GET 和 POST 得到的都是 django.http.QueryDict 所創建的實例。這是一個 django 自定義的類似字典的類,用來處理同一個鍵帶多個值的情況。 在 python 原始的字典中,當一個鍵出現多個值的時候會發生衝突,只保留最後一個值。 ...
  • 一、過濾器 過濾器就是向web應用程式的請求和和響應添加功能的組件。過濾器能夠實現客戶端和目標資源之間的交互信息進行篩選和過濾,最終保留有效的數據信息。 二、過濾器的生命周期 2.1 實例化。 web容器複製創建過濾器的實例來完成過濾器的實例化,只會實例化一次。 2.2 初始化。 在進行過濾工作前會 ...
  • 一、servlet的概念 Servlet是一種獨立與平臺和協議的伺服器端java應用程式,通過Servlet可以生成動態web頁面,同時使用Servlet還可以在伺服器端對客戶的請求進行處理,控製程序的執行。 Servlet的主要作用就是互動式的瀏覽和更新數據,並生成動態的頁面內容展示。 1. 服務 ...
  • 題目:輸入兩個鏈表,找出它們的第一個公共節點。鏈表的定義如下: 思路1:採用蠻力的方法:在第一個鏈表上順序遍歷每個節點,每遍歷到一個節點的時候,在第二個鏈表上順序遍歷每個節點。如果第二個鏈表上的節點和第一個鏈表上的節點一樣,就說明兩個鏈表在節點上重合,於是就找到了公共的節點。而通常蠻力並不是好的方法 ...
  • HTTP 應用的信息是通過 請求報文 和 響應報文 傳遞的,關於更多的相關知識,可以閱讀《HTTP權威指南》獲得。 其中 請求報文 由客戶端發送,其中包含和許多的信息,而 django 將這些信息封裝成了 HttpRequest 對象,該對象由 HttpRequest 類創建。每一個請求都會生成一個 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...