Javascript Typescript:can';t从另一个模块调用函数
我目前的项目是一个简单的多人游戏。客户端和服务器都是用Typescript编写的。客户端只处理输入并渲染游戏,所有逻辑都在服务器端实现 服务器代码使用nodejs执行,结构如下Javascript Typescript:can';t从另一个模块调用函数,javascript,typescript,Javascript,Typescript,我目前的项目是一个简单的多人游戏。客户端和服务器都是用Typescript编写的。客户端只处理输入并渲染游戏,所有逻辑都在服务器端实现 服务器代码使用nodejs执行,结构如下 main.ts包含一个express服务器,为html文件提供客户端脚本。此外,它还设置socket.io,创建一个新的游戏实例,并为每个连接的套接字创建一个新的Player实例 game.ts导出类game和Player。游戏实际上只是所有重要数据的容器。它存储所有玩家的列表和所有游戏对象的列表Game实现方法req
- main.ts包含一个express服务器,为html文件提供客户端脚本。此外,它还设置socket.io,创建一个新的游戏实例,并为每个连接的套接字创建一个新的
实例Player
- game.ts导出类
和game
。Player
游戏实际上只是所有重要数据的容器。它存储所有玩家的列表和所有游戏对象的列表
实现方法Game
,该方法检查是否可能生成新的游戏对象。类requestSpawn(…)
只是socket.io套接字的包装器。它处理传入和传出的消息。如果客户端试图生成游戏对象,则会向服务器发送一条消息,并到达Player
实例中存储的套接字。Player
实例然后调用Player
来尝试生成所需的requestSpawn
GameObject
- GameObjects.ts导出接口
和此接口的各种实现GameObject
Player
实例接收消息并在其Game
实例上调用requestSpawn
Game
实例在正确位置创建正确类型的新GameObject
,并将其添加到GameObjects
GameObject
现在应该更新了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) {
}
}
现在,工厂实例的update方法的第一次调用生成一个robot,之后工厂“休眠”。机器人在更新方法中什么也不做
我想引导大家注意两行代码:
-在requestSpawn
方法中,GameObject
立即更新为deltaTime=1
这意味着,在一个工厂诞生之后,机器人也应该诞生。但事实并非如此。我在requestSpawn
方法中添加了console.log
调用。它成功地打印了“只是试图更新一个工厂”,但是,什么也没有发生。
所以我认为update方法工作不正常,并在那里添加了一个console.log
调用。这是工厂
更新
方法的第一行,应该打印“更新工厂”。但这永远不会发生
我真的很困惑。应该调用该方法,但它不是。虽然它是公开的,但我认为问题可能与访问权有关。这是第二行代码,我想指出:
-在工厂的构造函数中,我注释掉了对this.update(1)
的调用
我认为至少自己的构造函数应该能够调用update方法。确实如此。当此行未注释掉时,将调用一次update。然后,工厂尝试生成一个新机器人,并在其游戏实例上调用requestSpawn()
。因此,将创建一个新机器人,并向所有客户端发送一条SpawnMessage
。机器人甚至出现在客户端的浏览器选项卡中
因此,显然没有调用该方法。一切正常,消息解析、工厂更新和机器人创建都是正确的。唯一的问题是,Game
中的所有更新调用都不会执行。出了什么问题?您已经发布了很多代码,可能还有其他问题,但至少有一个问题是您缺少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());
}
…因此总是创建一个机器人
,它在其更新()方法中不跟踪任何内容。(如果您尝试创建一个工厂
,您会成功,但随后会通过将一个新的机器人
分配给同一个varo
来立即覆盖它)
考虑这个简化的例子:
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'
()是的,这很有效。多么令人尴尬的错误。谢谢你找到它