棘手动作的抽象实现,例如,呃,行走
哦,嗨。我是一名初级 Java 开发人员,在空闲时间从事一些基于 2D 图块的游戏。现在我正在尝试实现游戏模型中非常基本的东西 - 各种类型的对象如何彼此交互。 我希望有一天添加网络支持,所以现在动作对象同步更改它们的状态 - 当单例 Ticker(在自己的线程中运行)使用 .tick() 通知订阅对象时,使它们执行先前分配给它们的命令对象。 实现简单的一次性活动(例如拾取某个对象)非常简单,例如:
abstract class Character extends AbstractActing {
void tick() {
action.execute();
}
private void pickUp(Item item) {
inventory.add(item);
}
private IAction action;
//...
class PickUp implements IAction {
void execute() {
//check if allowed to do
pickUp(item)
}
PickUp(Item item) {
this.item = item;
}
private Item item;
}
}
现在我想编写一个骨架实现来执行更复杂的操作,例如引导某些咒语、踢某人的屁股或跑到地图上的点。我认为代表这些复杂操作的对象将在内部将自己解释为简单的原子指令队列。例如,“Walk(Location x)”命令将在内部使用寻路算法来构建“DoOneStep(Direction d)”队列,并且如果途中发生某些情况,将能够重建它。 问题是单个原子步骤将需要更多信息来执行,例如角色的速度或地面类型。顺便说一句,根据角色的速度,我可能想改变角色的真实位置,而不是每一个刻度。我想我必须在 Action 中添加一些步骤执行器对象,该对象观察与计算相关的对象并更新其状态。
我的问题(最后!)是 - 是否有一些众所周知的设计模式可供我思考?每次编辑我的代码都会变得更加难以理解和不可继承,也许我应该重写整个代理系统?
Oh, hi. I'm a junior java developer working in my free time on some 2D tile-based game. Now I am trying to implement the very basic things in game Model - how objects of various types interact with each other.
I hope to add network support someday, so now acting objects change their state synchronously - when singleton Ticker (running in its own thread) notifies subscribed objects with .tick(), making them execute command objects previously assigned to them.
Implementing simple one-tick activities like picking up some object was quite simple, like:
abstract class Character extends AbstractActing {
void tick() {
action.execute();
}
private void pickUp(Item item) {
inventory.add(item);
}
private IAction action;
//...
class PickUp implements IAction {
void execute() {
//check if allowed to do
pickUp(item)
}
PickUp(Item item) {
this.item = item;
}
private Item item;
}
}
Now I want to write a skeletal implementation for more complicated actions like channeling some spell, kicking one's ass or running to point on map. I suppose that objects representing these complex actions will inside interprete themselves into queue of simple, atomic instructions. For example, "Walk(Location x)" command will internally use pathfinding algorithms to build queue of "DoOneStep(Direction d)" and will be able to rebuild it if something will happen in the way.
The problem is that single atomic step will need more information to be executed like Character's speed or ground type. BTW, depending on character's speed I might wanna change Character's real location not every single tick. I think I have to add some step-executor object inside Action that observes objects related to calculations and updates its state.
My queston (finally!) is - is there some well-known design patterns fore me to meditate on? My code grows more unintelligible and un-inheritable with every edit, maybe I shall rewrite entire acting system?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可能需要考虑使用状态模式(也称为状态机模式,因为它基于有限状态机的数学理论)。这个想法是,角色(或任何其他类型的游戏对象)始终处于一种状态(从预定的可能状态集合中选取),并且某些事件可以触发转换到其他州。然后,
tick()
方法可以根据当前状态执行不同的操作。此模式的更高级版本是为不同的状态提供类,并使用状态类的实例来收集有关您处于该状态的时间等信息。因此,在您的情况下,可能的状态是Walking
、PickingUp
、Idle
等。实际上,您几乎自己发明了这种模式,因为您的
IAction
概念本质上与状态相同。所以我认为你正朝着正确的方向前进。编辑:为了更具体地针对您的情况,我建议您简单地放弃
IAction
是原子的要求;相反,它可能会持续几个周期。IAction.execute()
应该简单地执行在一次刻度期间可以执行的尽可能多的操作,例如沿着所需的路径走一小段距离。动作本身可以跟踪目标位置在哪里、已经走了多远等。(历史注释:最初的虚幻引擎是基于状态的(我猜新版本也是如此)-在编码时例如,一种自定义武器,您可以将代码拆分为每种可能状态的一个部分,例如
Firing
、Reloading
、Idle
等。 )You might want to consider using the State pattern (also known as the State Machine pattern, since it is based on the mathematical theory of finite state machines). The idea is that a character (or any other kind of game object, for that matter) is always in exactly one state (picked from a predetermined collection of possible states), and that certain events can trigger transitions to other states. Then, the
tick()
method can perform different actions depending on the current state. A more advanced version of this pattern is to have classes for the different states, and use instances of the state classes to collect information about e.g. how long you have been in that state. So in your case, possible states areWalking
,PickingUp
,Idle
, etc.Actually, you've almost invented this pattern yourself, as your
IAction
concept is essentialy the same thing as a state. So I think you're headed in the right direction.Edit: To be more specific to your situation, I'd suggest that you simply drop the requirement that an
IAction
is atomic; instead, it may last for several ticks.IAction.execute()
should simply perform as much of the action as can be performed in the course of one tick, such as walking a small distance along the desired path. The action itself can e.g. keep track of where the target position is, how far one has come, etc.(Historical note: The original Unreal Engine was based on states (and I'd guess that the newer versions are too) - when coding e.g. a custom weapon, you'd split the code into one section for each possible state, such as
Firing
,Reloading
,Idle
, etc.)