Ваш игрок и ваш тролль - это не что иное, как наборы данных, которые мы называем Модель данных, которая описывает ваш мир. Жизнь, инвентарь, возможности атаки, их знание мира - все состоит в модели данных.
Держите один основной объект Model, который содержит все данные, описывающие ваш мир. Он будет содержать общую информацию о мире, такую как сложность, физические параметры и т. Д. Он также будет содержать список / массив данных конкретных объектов , как я описал выше. Эта основная модель может состоять из множества подобъектов для описания вашего мира. Нигде в вашей модели не должно быть никаких функций, управляющих игровой логикой или логикой отображения; геттеры - единственное исключение, и они будут использоваться только для того, чтобы вы могли с большей готовностью получать данные из модели (если публичные члены еще не добились цели).
Затем создайте функции в одном или нескольких классах «контроллера»; Вы можете написать их все как вспомогательные функции в своем основном классе, хотя это может стать немного большим через некоторое время. Они будут вызываться при каждом обновлении, чтобы воздействовать на данные сущностей для различных целей (перемещение, атака и т. Д.). Хранение этих функций вне класса сущности является более ресурсоэффективным, и как только вы узнаете, что описывает вашу сущность, вы автоматически узнаете, какие функции должны на нее воздействовать.
class Main
{
//...members variables...
var model:GameModel = new GameModel();
//...member functions...
function realTimeUpdate() //called x times per second, on a timer.
{
for each (var entity in model.entities)
{
//command processing
if (entity == player)
decideActionsFromPlayerInput(entity);
else //everyone else is your enemy!
decideActionsThroughDeviousAI(entity);
act(entity);
}
}
//OR
function turnBasedUpdate()
{
if (model.whoseTurn == "player")
{
decideActionsFromInput(model.player); //may be some movement or none at all
act(player);
}
else
{
var enemy;
for each (var entity in model.entities)
{
if (entity != model.player)
{
enemy = entity;
decideActions(enemy);
act(enemy);
}
}
}
}
//AND THEN... (common to both turn-based and real-time)
function decideActionsThroughDeviousAI(enemy)
{
if (distanceBetween(enemy, player) <= enemy.maximumAttackDistance)
storeAttackCommand(enemy, "kidney punch", model.player);
else
storeMoveCommand(player, getVectorFromTo(enemy, model.player));
}
function decideActionsFromPlayerInput(player)
{
//store commands to your player data based on keyboard input
if (KeyManager.isKeyDown("A"))
storeMoveCommand(player, getForwardVector(player));
if (KeyManager.isKeyDown("space"))
storeAttackCommand(player, "groin slam", currentlyHighlightedEnemy);
}
function storeAttackCommand(entity, attackType, target)
{
entity.target = target;
entity.currentAttack = attackType;
//OR
entity.attackQueue.add(attackType);
}
function storeMoveCommand(entity, motionVector)
{
entity.motionVector = motionVector;
}
function act(entity)
{
entity.position += entity.motionVector;
attack(entity.target, entity.currentAttack);
}
}
class GameModel
{
var entities:Array = []; //or List<Entity> or whatever!
var player:Entity; //will often also appear in the entity list, above
var difficultyLevel:int;
var globalMaxAttackDamage:int;
var whoseTurn:Boolean; //if turnbased
//etc.
}
И последнее замечание: полезно также отделить логику отображения от логики игры. Логика дисплея будет такой: «Где я могу нарисовать это на экране и каким цветом?» против игровой логики то, что я обрисовал в общих чертах в псевдокоде выше.
(Примечание разработчика: при использовании классов этот метод слабо следует подходу функционального программирования, который рассматривает все методы как идеально не сохраняющие состояния, позволяя использовать чистую модель данных и подход обработки, который сводит к минимуму ошибки, вызванные сохраненным состоянием. FP является окончательным MVC, поскольку он достигает MVC цель разделения проблем явно. См. этот вопрос .)