2013-03-09 101 views
0

我目前的項目是一個簡單的多人遊戲。客戶端和服務器都是用Typescript編寫的。客戶端只處理輸入並呈現遊戲,所有邏輯都在服務器端實現。Typescript:不能從另一個模塊調用函數

服務器代碼與執行的NodeJS和結構類似這樣

  • main.ts包含一個明確的服務器和服務與客戶端腳本的HTML文件。此外,它設置socket.io,創建一個新的Game實例,併爲每個連接的套接字創建一個新實例Player

  • game.ts導出類GamePlayerGame實際上只是所有重要數據的容器。它存儲所有玩家的列表以及所有gameObjects的列表。 Game實現方法requestSpawn(...),該方法檢查是否可以產生新的gameObject。類Player只是一個socket.io套接字的包裝。它處理傳入和傳出的消息。如果客戶端嘗試產生GameObject,則會向服務器發送消息併到達存儲在Player實例中的套接字。然後Player實例調用requestSpawn嘗試產生期望的GameObject

  • GameObjects.ts導出接口GameObject和此接口的各種實現。

遊戲運行是這樣的:

  1. 一個人的HTML畫布
  2. 一個新的「REQUESTSPAWN」信息打包發送到
  3. 一個Player實例接收服務器內點擊消息並在其實例上調用requestSpawnGame
  4. Game實例創建一個新的GameObject的正確類型在正確的位置並將其添加到列表GameObjects
  5. 現在應更新此新的GameObject

這不是。 下面是相關代碼:

game.ts

import go = module("GameObjects"); 
import util = module("Utilities"); 

//... 

export class Game { 
    private players: Player[]; 
    public gameObjects:go.GameObject[]; 
    private gameObjectCounter: number; 

    constructor() { 
     this.players = []; 
     this.gameObjectCounter = 0; 
     this.gameObjects = []; 
     var prev = Date.now(); 
     var deltaTime = Date.now() - prev; 
     setInterval(() =>{ deltaTime = Date.now() - prev; prev = Date.now(); this.update(deltaTime); }, 200); 
    } 

    broadcast(msg: Message) { 
     this.players.forEach((player) => { player.send(msg); }); 
    } 

    requestSpawn(msg:RequestSpawnMessage, clientID:number): bool { 
     var pos = new util.Vector2(msg.x, msg.y);   
     var o: go.GameObject; 
     switch (msg.tag) { 
      case UID.FACTORY:           
       o = new go.Factory(pos.clone(), this.players[clientID], this.newGameObject()); 
      case UID.ROBOT: 
       o = new go.Robot(pos.clone(), this.players[clientID], this.newGameObject()); 
     } 
     this.broadcast(new SpawnMessage(msg.tag, o.id, clientID, pos.x, pos.y)); 
     this.gameObjects.push(o); 
     console.log(this.gameObjects); 
     o.update(1); 
     console.log("tried to update the factory"); 
     return true; 
    } 

    update(deltaTime){ 
     this.gameObjects.forEach((object) =>{object.update(deltaTime); }); 
    } 

    addPlayer(socket: Socket) {   
     var player = new Player(this, socket, this.players.length); 
     this.players.push(player); 
    } 
    newGameObject() : number { 
     return this.gameObjectCounter++; 
    } 
} 

GameObjects.ts

export import util = module("Utilities"); 
export import s = module("server"); 
export import g = module("game"); 

export interface GameObject{ 
    tag: g.UID; 
    id:number; 
    player: g.Player; 
    clientId: number; 
    pos:util.Vector2; 
    getPos():util.Vector2; 
    setPos(newPos:util.Vector2); 
    // !TODO how to make that const? 
    boundingBox: util.Rectangle; 
    update(deltaTime:number); 
} 

export class Factory implements GameObject { 
    tag: g.UID; 
    id: number; 
    player: g.Player; 
    clientId: number; 
    server: s.Server; 
    //variables for handling the delay between spawning robots 
    private current_time: number; 
    public delay: number; 
    boundingBox: util.Rectangle; 

    public static dimensions = new util.Vector2(30, 30); 
    constructor(pos: util.Vector2, player:g.Player, id: number) { 
     this.pos = pos; 
     this.tag = g.UID.FACTORY; 
     this.player = player; 
     this.clientId = this.player.getID(); 
     this.current_time = 0; 
     this.delay = 1; 
     this.id = id; 
     this.boundingBox = new util.Rectangle(pos, Factory.dimensions.x, Factory.dimensions.y); 
     console.log("just created a factory"); 
     //this.update(1); 
    } 

    pos: util.Vector2; 
    getPos() { return this.pos; } 
    setPos(pos: util.Vector2) { this.pos = pos; } 

    public once = true; 
    //check if it's time to create a new robot 
    public update(deltaTime: number) { 
     console.log("updating a factory"); 

     //this code will produce a robot just once, this is handy for development, since there's not so much waiting time 
     if (this.once) { this.player.requestSpawn(g.UID.ROBOT, this.pos.x, this.pos.y); console.log("just spawned a robot"); } 
     this.once = false; 
     /*this.current_time += deltaTime/1000; 
     if (this.current_time > this.delay*(Factory.count+1)/(Mine.count+1)) { 
      this.current_time = 0; 
      this.spawnRobot(); 
     }*/ 
    } 
} 


//this will be the fighting robot meant to destroy enemy factories 
export class Robot implements GameObject{ 
    tag: g.UID; 
    id: number; 
    player:g.Player; 
    clientId: number; 
    game: g.Game; 
    boundingBox: util.Rectangle; 
    // ! TODO constants should have capital letters. 
    public static radius = 15; 
    constructor(pos:util.Vector2,player:g.Player,id:number){ 
     this.tag = g.UID.ROBOT; 
     this.player=player; 
     this.clientId = this.player.getID(); 
     this.boundingBox = new util.Rectangle(pos, Robot.radius, Robot.radius); 
    } 

    pos:util.Vector2; 
    getPos(){return this.pos;} 
    setPos(pos:util.Vector2){this.pos=pos;} 

    //now the robot is moved by keyboard input but soon it will check the gameObjects array and search for the closest enemy, 
    //in order to attack it 
    public update(deltaTime: number) { 

    } 
} 

眼下工廠實例的更新方法的第一次調用產生一個機器人,在此之後,工廠「睡覺」。機器人在他們的更新方法中什麼都不做。

我想帶領你的眼睛上的兩行代碼: - 在requestSpawn方法GameObject用的DeltaTime立即更新= 1

這意味着,產卵後出廠直接,機器人應也會產生。但是這並沒有發生。我在requestSpawn方法中添加了一個console.log調用。它成功地打印「只是試圖更新工廠」,但是,沒有任何反應。 所以我認爲更新方法不能正常工作,並且在那裏也添加了一個console.log調用。這是Factory'supdate方法的第一行,應打印「更新工廠」。但那從來沒有發生過。

我真的很困惑。該方法應該被調用,但不是。雖然它是公開的,但我認爲這個問題可能與訪問權限有關。因此,這是代碼的第二行,我想指出: - 在Factory的構造函數中,我已經註釋掉了對this.update(1)的調用。

我想,至少自己的構造函數應該能夠調用更新方法。它的確是。當這一行沒有被註釋掉時,更新被調用一次。工廠然後試圖產生一個新的機器人,並在Game的實例上調用requestSpawn()。因此,創建了一個新的機器人,並向所有客戶發送一個新機器人。機器人甚至出現在客戶端的瀏覽器選項卡中。

因此很明顯,該方法沒有被調用。一切工作正常,消息解析,工廠更新和機器人創建是正確的。唯一的問題是沒有執行從Game內更新的所有呼叫。什麼地方出了錯 ?

回答

2

你已經張貼了大量的代碼,並可能有其他的問題,但至少有一個是你缺少你的switch語句中break ...

switch (msg.tag) { 
     case UID.FACTORY:           
      o = new go.Factory(pos.clone(), this.players[clientID], this.newGameObject()); 
     case UID.ROBOT: 
      o = new go.Robot(pos.clone(), this.players[clientID], this.newGameObject()); 
} 

...,因此始終創建一個Robot,它的update()方法中沒有任何記錄。 (如果您嘗試創建Factory,則表示您成功,但通過將新的Robot分配給相同的var o,立即覆蓋該表。

考慮這個簡單的例子:

interface GameObject { 
    update():void; 
} 

class Factory implements GameObject { 
    update():void { 
     console.log("Factory"); 
    } 
} 

class Robot implements GameObject { 
    update():void { 
     console.log("Robot"); 
    } 
} 

class Test { 

    private o:GameObject; 

    constructor(index:number){ 
     switch(index){ 
      case 1: 
       this.o = new Factory(); 
      case 2: 
       this.o = new Robot(); 
     } 
     this.o.update(); 
    } 
} 

class BreakTest { 

    private o:GameObject; 

    constructor(index:number){ 
     switch(index){ 
      case 1: 
       this.o = new Factory(); 
       break; 
      case 2: 
       this.o = new Robot(); 
       break; // Not necessary in final case, but good form IMO. 
     } 
     this.o.update(); 
    } 
} 

var t = new Test(1);  // Traces 'Robot' 
var tt = new Test(2);  // Traces 'Robot' 

var b = new BreakTest(1); // Traces 'Factory' 
var bt = new BreakTest(2); // Traces 'Robot' 

Ref

+0

是的,這工作。多麼令人尷尬的錯誤。謝謝你找到它 – lhk 2013-03-10 20:17:22

相關問題