2013-03-09 99 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

相关问题