05-22-2012, 04:31 AM
Многие наверное знают игру Жизнь, так называемый клеточный автомат.
И многие кто увлекался/увлекается программированием наверняка реализовывали эту игру тем или иным способом. Я к примеру давным давно ее реализовывал на паскале, еще на 286 компе.
Ну и вот на днях мне от нечего делать пришло в голову - а почему бы не попробовать реализовать ее в линейке используя в качестве клеток поля неписей и меняя их вид при помощи выставления им разных значений NPC State.
Не ищите в реализации этого всего никакого практического смысла - мне просто стало интересно это все реализовать таким вот своеобразным способом, что я по быстрому и сделал.
Исходники реализации "жизни" под феникс:
Управлять игрой можно так же как эвентами к примеру - вызывая из хтмл нужные методы:
initWorld() - инициализирует игру (спавнит нпс при необходимости, задает начальное состояние клеток поля).
startGame() - запускает игру.
pauseGame() - останавливает игру.
Видео того как это выглядит в линейке:
И многие кто увлекался/увлекается программированием наверняка реализовывали эту игру тем или иным способом. Я к примеру давным давно ее реализовывал на паскале, еще на 286 компе.
Ну и вот на днях мне от нечего делать пришло в голову - а почему бы не попробовать реализовать ее в линейке используя в качестве клеток поля неписей и меняя их вид при помощи выставления им разных значений NPC State.
Не ищите в реализации этого всего никакого практического смысла - мне просто стало интересно это все реализовать таким вот своеобразным способом, что я по быстрому и сделал.
Исходники реализации "жизни" под феникс:
Код:
package events.GameOfLife;
import java.util.concurrent.ScheduledFuture;
import l2p.common.ThreadPoolManager;
import l2p.extensions.scripts.Functions;
import l2p.gameserver.model.L2Spawn;
import l2p.gameserver.model.instances.L2NpcInstance;
import l2p.gameserver.tables.NpcTable;
import l2p.util.Rnd;
/**
* Реализация игры Conway's Game of Life :)
*
* @author Gaikotsu
*/
public class GameOfLife extends Functions
{
private static final int worldWidth = 20;
private static final int worldHeight = 20;
private static final int cellNpcId = 18927;
private static final int liveCell = 1;
private static final int deadCell = 2;
private static final int initialLifeCells = 200;
private static final int autoStopSteps = 0;
private static final int posX = 149500;
private static final int posY = 46200;
private static final int posZ = -3430;
private static final int posStep = 50;
private static final int updateWorldPeriod = 2000;
private static ScheduledFuture<?> updateWorldTask = null;
private static int currentStep;
private static boolean gamePaused;
private static L2NpcInstance world[][] = new L2NpcInstance[worldWidth][worldHeight];
private static int worldState[][] = new int[worldWidth][worldHeight];
public void initWorld()
{
currentStep = 0;
gamePaused = true;
if (updateWorldTask != null)
{
updateWorldTask.cancel(false);
updateWorldTask = null;
}
try
{
for (int x = 0; x < worldWidth; x++)
for (int y = 0; y < worldHeight; y++)
{
if (world[x][y] == null)
{
L2Spawn spawn = new L2Spawn(NpcTable.getTemplate(cellNpcId));
spawn.setLocx(posX + x * posStep);
spawn.setLocy(posY + y * posStep);
spawn.setLocz(posZ);
spawn.setAmount(1);
L2NpcInstance npc = spawn.doSpawn(true);
npc.setImobilised(true);
npc.setNpcState(deadCell);
world[x][y] = npc;
worldState[x][y] = deadCell;
}
else
{
if (world[x][y].getNpcState() != deadCell)
world[x][y].setNpcState(deadCell);
worldState[x][y] = deadCell;
}
}
int currentIteration = 0;
int maxIteration = initialLifeCells * 10;
for (int i = 0; i < initialLifeCells; i++)
{
int x = Rnd.get(worldWidth);
int y = Rnd.get(worldHeight);
if (worldState[x][y] == deadCell)
worldState[x][y] = liveCell;
else
i--;
currentIteration++;
if (currentIteration > maxIteration)
break;
}
updateNpcState();
}
catch (Exception e)
{
e.printStackTrace();
}
}
public void startGame()
{
if (updateWorldTask != null)
return;
if (autoStopSteps > 0 && currentStep >= autoStopSteps)
return;
gamePaused = false;
updateWorldTask = ThreadPoolManager.getInstance().scheduleGeneral(new UpdateWorld(), 0);
}
public void pauseGame()
{
gamePaused = true;
if (updateWorldTask != null)
{
updateWorldTask.cancel(false);
updateWorldTask = null;
}
}
private static void updateNpcState()
{
for (int x = 0; x < worldWidth; x++)
for (int y = 0; y < worldHeight; y++)
if (world[x][y].getNpcState() != worldState[x][y])
world[x][y].setNpcState(worldState[x][y]);
}
private static class UpdateWorld implements Runnable
{
public void run()
{
int neighbors = 0;
int neighborX = 0;
int neighborY = 0;
for (int x = 0; x < worldWidth; x++)
for (int y = 0; y < worldHeight; y++)
{
neighbors = 0;
for (int i = -1; i <= 1; i++)
for (int j = -1; j <= 1; j++)
{
if (i == 0 && j == 0)
continue;
neighborX = x + i;
neighborY = y + j;
if (neighborX < 0)
neighborX = worldWidth - 1;
if (neighborY < 0)
neighborY = worldHeight - 1;
if (neighborX >= worldWidth)
neighborX = 0;
if (neighborY >= worldHeight)
neighborY = 0;
if (world[neighborX][neighborY].getNpcState() == liveCell)
neighbors++;
}
if (world[x][y].getNpcState() == deadCell && neighbors == 3)
worldState[x][y] = liveCell;
else
{
if (world[x][y].getNpcState() == liveCell && (neighbors < 2 || neighbors > 3))
worldState[x][y] = deadCell;
else
worldState[x][y] = world[x][y].getNpcState();
}
}
updateNpcState();
currentStep++;
if (autoStopSteps > 0 && currentStep >= autoStopSteps)
gamePaused = true;
updateWorldTask = !gamePaused ? ThreadPoolManager.getInstance().scheduleGeneral(new UpdateWorld(), updateWorldPeriod) : null;
}
}
}
initWorld() - инициализирует игру (спавнит нпс при необходимости, задает начальное состояние клеток поля).
startGame() - запускает игру.
pauseGame() - останавливает игру.
Видео того как это выглядит в линейке: