jeudi 9 avril 2015

Best pattern to reduce excessive conditionals

I have the following code for a game that manages display patterns for items by randomly deciding on one, creating the items based on the pattern chosen and then animating them.


The problem is that cleaning code and managing changes can be cumbersome due to the sheer size, I have been studying design patterns lately and I was wondering which would be the best one to apply here, so far I have considered strategy and command as possible options


"The strategy pattern is used to create an interchangeable family of algorithms from which the required process is chosen at run-time." Seems like something I could use to apply the positioning of the items depending on the pattern selected.


And by looking at previous questions here when asked about reducing the amount of if/elses the command pattern came up quite a bit.


" The command pattern is used to express a request, including the call to be made and all of its required parameters, in a command object. The command may then be executed immediately or held for later use."


Still, I don't know if I may be finding relevance where there is not, so I thought I'd ask if such patterns can be applied to the following scenarios.


Below is the relevant code, I'm specially interested in learning about this because almost the same code is repeated for enemies.



/**
* Set items pattern.
*
*/

private function setItemsPattern():void
{
// Chamge until enough flight distance has been accumulated.
if (patternChange > 0)
{
patternChange -= playerSpeed * elapsed;
}
else
{
// As the player moves, change item patterns.

if ( Math.random() < 0.7 )
{
// If < normal item chance (0.7), get a random pattern.
pattern = Math.ceil(Math.random() * 4);
}
else
{
// If random number is > normal item chance (0.3), create special item.

pattern = Math.ceil(Math.random() * 2) + 9;
}

if (pattern == 1)
{
// Vertical
patternStep = 15;
patternChange = Math.random() * 500 + 500;
}
else if (pattern == 2)
{
// Horizontal
patternOnce = true;
patternStep = 40;
patternChange = patternGap * Math.random() * 3 + 5;
}
else if (pattern == 3)
{
// ZigZag
patternStep = Math.round(Math.random() * 2 + 2) * 10;
if ( Math.random() > 0.5 )
{
patternDirection *= -1;
}
patternChange = Math.random() * 800 + 800;
}
else if (pattern == 4)
{
// Random
patternStep = Math.round(Math.random() * 3 + 2) * 50;
patternChange = Math.random() * 400 + 400;
}
else
{
patternChange = 0;
}
}
}

/**
* Creates items - called by createPattern()
*
*/

private function createItems():void
{

var itemToTrack:Item;

switch (pattern)
{
case 1:
// Horizontal.
if (Math.random() > 0.9)
{
// Asignes items not too close to border.
patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;
}


itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_1);
this.addChild(itemToTrack);


// Sets pos
itemToTrack.x = stage.stageWidth + itemToTrack.width ;
itemToTrack.y = patternPosY;

// Marks item for animation
itemsToAnimate.push(itemToTrack);


break;

case 2:
// Vertical
if (patternOnce == true)
{
patternOnce = false;


patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;


patternLength = (Math.random() * 0.4 + 0.4) * stage.stageHeight;
}


patternPosYstart = patternPosY;


while (patternPosYstart + patternStep < patternPosY + patternLength && patternPosYstart + patternStep < stage.stageHeight * 0.8)
{


itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_1);
this.addChild(itemToTrack);



itemToTrack.x = stage.stageWidth + itemToTrack.width;
itemToTrack.y = patternPosYstart;


itemsToAnimate.push(itemToTrack)


patternPosYstart += patternStep;
}
break;

case 3:
// ZigZag

if (patternDirection == 1 && patternPosY > gameArea.bottom - 50)
{
patternDirection = -1;
}
else if ( patternDirection == -1 && patternPosY < gameArea.top )
{
patternDirection = 1;
}

if (patternPosY >= gameArea.top && patternPosY <= gameArea.bottom)
{


itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_1);
this.addChild(itemToTrack);


itemToTrack.x = stage.stageWidth + itemToTrack.width;
itemToTrack.y = patternPosY;


itemsToAnimate.push(itemToTrack)


patternPosY += patternStep * patternDirection;
}
else
{
patternPosY = gameArea.top;
}

break;

case 4:
// Random, creates N amount of items on screen.
if (Math.random() > 0.3)
{

patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;


while (patternPosY + patternStep < gameArea.bottom)
{


itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_1);
this.addChild(itemToTrack);


itemToTrack.x = stage.stageWidth + itemToTrack.width;
itemToTrack.y = patternPosY;


itemsToAnimate.push(itemToTrack)


patternPosY += Math.round(Math.random() * 100 + 100);
}
}

break;

case 10:

// special item

patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;


itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_MANA);
this.addChild(itemToTrack);


itemToTrack.x = stage.stageWidth + itemToTrack.width;
itemToTrack.y = patternPosY;


itemsToAnimate.push(itemToTrack);

break;

case 11:

// special item

patternPosY = Math.floor(Math.random() * (gameArea.bottom - gameArea.top + 1)) + gameArea.top;



itemToTrack = itemFactory.getItem(GameConstants.ITEM_TYPE_REFERENCIA);
this.addChild(itemToTrack);

itemToTrack.x = stage.stageWidth + itemToTrack.width;
itemToTrack.y = patternPosY;


itemsToAnimate.push(itemToTrack);

break;


}
}


/**
* Animates the vector itemsToAnimate.
*
*/


private function animateItems():void
{

var itemToTrack:Item;

for(var i:uint = 0;i<itemsToAnimate.length;i++)
{
itemToTrack = itemsToAnimate[i];

if (itemToTrack != null)
{

if (referencia > 0 && itemToTrack.itemType <= GameConstants.ITEM_TYPE_REFERENCIA)
{

itemToTrack.x -= (itemToTrack.x - brujaX) * 0.2;
itemToTrack.y -= (itemToTrack.y - brujaY) * 0.2;


}
else
{

itemToTrack.x -= playerSpeed * elapsed;
}


if (itemToTrack.x < -80 || gameState == GameConstants.GAME_STATE_OVER)
{
disposeItemTemporarily(i, itemToTrack);
}
else
{

brujaItem_xDist = itemToTrack.x - brujaX;
brujaItem_yDist = itemToTrack.y - brujaY;
brujaItem_sqDist = brujaItem_xDist * brujaItem_xDist + brujaItem_yDist * brujaItem_yDist;

if (brujaItem_sqDist < 5000)
{

if (itemToTrack.itemType == GameConstants.ITEM_TYPE_1)
{
scoreItems += itemToTrack.itemType;
hud.itemScore = scoreItems;
if (!Sounds.muted) Sounds.sndPag.play();
}

else if (itemToTrack.itemType == GameConstants.ITEM_TYPE_MANA)
{

scoreItems += 1;


mana = 5;
if (isHardwareRendering) particleMana.start(mana);

if (!Sounds.muted) Sounds.sndMana.play();
if (!Sounds.muted) Sounds.sndRisa.play();
}

else if (itemToTrack.itemType == GameConstants.ITEM_TYPE_REFERENCIA)
{

scoreItems += 1;

referencia = 20;
partRef = 0.5;
if (isHardwareRendering) particleRef.start(partRef);

playRandomRef();

}

if(referencia > 0){referencia--;}


disposeItemTemporarily(i, itemToTrack);
}
}
}
}
}

Aucun commentaire:

Enregistrer un commentaire