Ваш гравець і ваш троль - це не що інше, як набір даних, що ми називаємо Модель даних, яка описує ваш світ. Життя, інвентар, можливості нападу, навіть їхнє знання про світ - все полягає у моделі даних.
Зберігайте єдиний головний об'єкт 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.
}
Остаточне зауваження полягає в тому, що також корисно зберігати логіку відображення окремо від логіки гри. Логіка відображення буде: "Де я малюю це на екрані і в якому кольорі?" проти логіки гри - це те, що я окреслив у псевдокоді вище.
(Примітка Dev: Під час використання класів це слабко дотримується функціонального підходу програмування, який розглядає всі методи як ідеально бездержавні, дозволяючи створити чисту модель даних та підхід до обробки, який мінімізує помилки, викликані збереженим станом. мета чіткого розмежування проблем. Дивіться це питання .)