Java流程控制问题
我正在编写一个简单的 2d 游戏引擎。我已经决定了引擎如何运行:它将由包含“事件”的对象组成,我的主游戏循环将在适当的时候触发这些“事件”。
关于结构的更多信息: 每个 GameObject 都有一个 updateEvent 方法。 objectList
是将接收更新事件的所有对象的列表。只有此列表中的对象才会由游戏循环调用其 updateEvent 方法。
我正在尝试在 GameObject 类中实现此方法(此规范是我想要实现的方法):
/**
* This method removes a GameObject from objectList. The GameObject
* should immediately stop executing code, that is, absolutely no more
* code inside update events will be executed for the removed game object.
* If necessary, control should transfer to the game loop.
* @param go The GameObject to be removed
*/
public void remove(GameObject go)
因此,如果对象尝试在更新事件内删除自身,则控制应该传回游戏引擎:
public void updateEvent() {
//object's update event
remove(this);
System.out.println("Should never reach here!");
}
这是我到目前为止所拥有的。它有效,但是我读到的关于使用异常进行流量控制的内容越多,我就越不喜欢它,所以我想看看是否有替代方案。
删除方法
public void remove(GameObject go) {
//add to removedList
//flag as removed
//throw an exception if removing self from inside an updateEvent
}
游戏循环
for(GameObject go : objectList) {
try {
if (!go.removed) {
go.updateEvent();
} else {
//object is scheduled to be removed, do nothing
}
} catch(ObjectRemovedException e) {
//control has been transferred back to the game loop
//no need to do anything here
}
}
// now remove the objects that are in removedList from objectList
2 个问题:
我是否正确地假设实现上述删除方法的立即停止部分的唯一方法是抛出自定义异常并在游戏中捕获它环形? (我知道,使用异常进行流量控制就像 goto,这很糟糕。我只是想不出另一种方法来完成我想要的事情!)
对于从列表本身中删除,它是< /em> 一个对象可以删除列表中较靠下的一个对象。目前,我在执行任何代码之前检查已删除的标志,并在每次传递结束时删除对象以避免并发修改。是否有更好的、最好是即时/非轮询的方法来执行此操作?
[编辑] 阅读您的答案后,我想我会更改方法规范。即时删除行为是我已经习惯在不同引擎中使用的行为,但你是对的,它并不真正适合 Java 的工作方式。是时候尝试用一种稍微不同的思维方法来思考了!
I am programming a simple 2d game engine. I've decided how I'd like the engine to function: it will be composed of objects containing "events" that my main game loop will trigger when appropriate.
A little more about the structure:
Every GameObject
has an updateEvent
method.objectList
is a list of all the objects that will receive update events. Only objects on this list have their updateEvent method called by the game loop.
I’m trying to implement this method in the GameObject class (This specification is what I’d like the method to achieve):
/**
* This method removes a GameObject from objectList. The GameObject
* should immediately stop executing code, that is, absolutely no more
* code inside update events will be executed for the removed game object.
* If necessary, control should transfer to the game loop.
* @param go The GameObject to be removed
*/
public void remove(GameObject go)
So if an object tries to remove itself inside of an update event, control should transfer back to the game engine:
public void updateEvent() {
//object's update event
remove(this);
System.out.println("Should never reach here!");
}
Here’s what I have so far. It works, but the more I read about using exceptions for flow control the less I like it, so I want to see if there are alternatives.
Remove Method
public void remove(GameObject go) {
//add to removedList
//flag as removed
//throw an exception if removing self from inside an updateEvent
}
Game Loop
for(GameObject go : objectList) {
try {
if (!go.removed) {
go.updateEvent();
} else {
//object is scheduled to be removed, do nothing
}
} catch(ObjectRemovedException e) {
//control has been transferred back to the game loop
//no need to do anything here
}
}
// now remove the objects that are in removedList from objectList
2 questions:
Am I correct in assuming that the only way to implement the stop-right-away part of the remove method as described above is by throwing a custom exception and catching it in the game loop? (I know, using exceptions for flow control is like goto, which is bad. I just can’t think of another way to do what I want!)
For the removal from the list itself, it is possible for one object to remove one that is farther down on the list. Currently I’m checking a removed flag before executing any code, and at the end of each pass removing the objects to avoid concurrent modification. Is there a better, preferably instant/non-polling way to do this?
[Edit]
After reading your answers, I think I'll change the method specs. The instant-remove behavior is something I’ve become used to working with in a different engine, but you’re right, it doesn’t really fit in with how Java works. Time to go try to wrap my head around a slightly different method of thinking!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我同意异常方法是根据您的规范实现删除方法的最佳方法。
但是,也许您应该重新考虑该规范。我会将 updateEvent 何时终止的决定留给实现者。使用remove() 调用终止是令人困惑的,并且需要使用异常来进行流控制。我相信对remove()的调用应该只改变标志状态。我认为循环所有对象并检查每个对象的已删除标志并没有真正的问题。
I agree that the exception approach is the best way to implement the remove method according to your specification.
However, maybe you should reconsider the specification. I would leave the decision of when updateEvent terminates to the implementor. Termination with the remove() call is confusing, and requires usage of exceptions for flow control. I believe that the call to remove() should only change the flag state. And I see no real problem with looping over all objects, checking the removed flag for each of them.
为什么不简单地返回,即
Why not simply return, i.e.,
为什么不直接:
Why don't you just:
@jball 的回答很棒——+1。
我使用过的另一种效果很好并且可能更简洁的方法是让 updateEvent() 方法返回一个布尔值。每当 updateEvent 返回 True 时,您就可以移除()该对象。
这允许您的事件循环更好地控制循环本身的执行方式,并删除类之间的一些不必要的绑定。
@jball's answer is great-- +1.
Another method I've used that works well and might be slightly cleaner is to have your updateEvent() method return a boolean. Whenever a True is returned from updateEvent, you remove() the object.
This allows your event loop to have more control over how the loop itself is executed and removes a little bit of unnecessary binding between your classes.