animation(temp)
code:cpp
# include <Siv3D.hpp> // OpenSiv3D v0.2.8
enum class Direction
{
Up,
Right,
Down,
Left
};
constexpr Point ToPoint(Direction direction)
{
switch (direction)
{
case Direction::Up:
return Point::Up();
case Direction::Right:
return Point::Right();
case Direction::Down:
return Point::Down();
default:
return Point::Left();
}
}
enum class MoveType
{
Move,
Merge,
None
};
constexpr MoveType GetMoveType(int32 my, int32 target)
{
if (target == 0 && my != 0)
{
return MoveType::Move;
}
else if ((my != 0) && (my == target))
{
return MoveType::Merge;
}
else
{
return MoveType::None;
}
}
struct AnimationData
{
AnimationData()
{
indices = Grid<Array<int32>>(4, 4);
for (auto i : step(16))
{
}
}
Grid<Array<int32>> indices;
Array<Point> mergePositions;
Stopwatch moveTimer;
Stopwatch mergeTimer;
};
std::pair<Grid<int32>, AnimationData> AllUp(Grid<int32> grid)
{
AnimationData animation;
//move
for (auto x : step(4))
{
for (auto y : Range(1, 3))
{
for (auto i : step(y))
{
const Point targetPos = Point(x, (y - i) - 1);
const Point myPos = Point(x, (y - i));
int32& myValue = gridmyPos; const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
animation.indicesmyPos.clear(); }
}
}
}
//merge
for (auto x : step(4))
{
for (auto y : Range(1, 3))
{
const Point targetPos = Point(x, y - 1);
const Point myPos = Point(x, y);
int32& myValue = gridmyPos; const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Merge)
{
++valueAtTarget;
myValue = 0;
animation.indicesmyPos.clear(); }
}
}
//move
for (auto x : step(4))
{
for (auto y : Range(1, 3))
{
for (auto i : step(y))
{
const Point targetPos = Point(x, (y - i) - 1);
const Point myPos = Point(x, (y - i));
int32& myValue = gridmyPos; const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
animation.indicesmyPos.clear(); }
}
}
}
return { grid, animation };
}
Grid<int32> AllRight(Grid<int32> grid)
{
//move
for (auto y : step(4))
{
for (auto x : { 2, 1, 0 })
{
for (auto i : step(3 - x))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
//merge
for (auto y : step(4))
{
for (auto x : { 2, 1, 0 })
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Merge)
{
++valueAtTarget;
myValue = 0;
}
}
}
//move
for (auto y : step(4))
{
for (auto x : { 2, 1, 0 })
{
for (auto i : step(3 - x))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
return grid;
}
Grid<int32> AllDown(Grid<int32> grid)
{
//move
for (auto x : step(4))
{
for (auto y : { 2, 1, 0 })
{
for (auto i : step(3 - y))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
//merge
for (auto x : step(4))
{
for (auto y : { 2, 1, 0 })
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Merge)
{
++valueAtTarget;
myValue = 0;
}
}
}
//move
for (auto x : step(4))
{
for (auto y : { 2, 1, 0 })
{
for (auto i : step(3 - y))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
return grid;
}
Grid<int32> AllLeft(Grid<int32> grid)
{
//move
for (auto y : step(4))
{
for (auto x : Range(1, 3))
{
for (auto i : step(x))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
//merge
for (auto y : step(4))
{
for (auto x : Range(1, 3))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Merge)
{
++valueAtTarget;
myValue = 0;
}
}
}
//move
for (auto y : step(4))
{
for (auto x : Range(1, 3))
{
for (auto i : step(x))
{
const MoveType moveType = GetMoveType(myValue, valueAtTarget);
if (moveType == MoveType::Move)
{
valueAtTarget = myValue;
myValue = 0;
}
}
}
}
return grid;
}
Array<Point> GetEmptyPoints(const Grid<int32>& grid)
{
Array<Point> emptyPoints;
for (auto p : step(grid.size()))
{
{
emptyPoints << p;
}
}
return emptyPoints;
}
void Main()
{
Graphics::SetBackground(ColorF(0.8, 0.9, 1.0));
constexpr double CellSize = 100.0;
const Font font(30, Typeface::Bold);
Grid<int32> grid = {
{ 1, 1, 1, 0 },
{ 1, 0, 1, 1 },
{ 1, 1, 1, 0 },
{ 1, 1, 0, 1 } };
//{
// Array<Point> initialSpawnPoints = Range(0, 15).asArray().choice(2).map([](int32 n) { return Point(n%4, n/4); });
// for (auto& spawnPoint : initialSpawnPoints)
// {
// }
//}
bool isGameOver = false;
AnimationData animation;
Grid<int32> oldGrid = grid;
while (System::Update())
{
Optional<Direction> direction;
if (KeyUp.down())
{
direction = Direction::Up;
}
else if (KeyRight.down())
{
direction = Direction::Right;
}
else if (KeyDown.down())
{
direction = Direction::Down;
}
else if (KeyLeft.down())
{
direction = Direction::Left;
}
if (animation.moveTimer.isRunning() || animation.mergeTimer.isRunning())
{
direction = none;
}
if (direction)
{
animation = AnimationData();
oldGrid = grid;
//Print << animation.indices;
if (direction == Direction::Up)
{
std::tie(grid, animation) = AllUp(grid);
}
else if (direction == Direction::Right)
{
//grid = AllRight(grid);
}
else if (direction == Direction::Down)
{
//grid = AllDown(grid);
}
else if (direction == Direction::Left)
{
//grid = AllLeft(grid);
}
//Print << animation.indices;
if (grid != oldGrid)
{
const Array<Point> emptyPoints = GetEmptyPoints(grid);
if (!emptyPoints)
{
isGameOver = true;
}
else
{
const Point spawnPoint = emptyPoints.choice();
}
animation.moveTimer.start();
}
}
const auto getRect = &(const Point& p) {
return RectF(p * CellSize, CellSize);
};
const int cycleT1 = 100;
const int cycleT2 = 100;
if (cycleT1 <= animation.moveTimer.ms())
{
animation.moveTimer.reset();
animation.mergeTimer.start();
}
else if (cycleT2 <= animation.mergeTimer.ms())
{
animation.mergeTimer.reset();
}
if (animation.moveTimer.isRunning())
{
Transformer2D t(Mat3x2::Translate(120, 40));
RectF(400).stretched(5).rounded(3).draw(ColorF(0.5));
std::unordered_map<Point, Point> animationPoints;
for (auto p : step(animation.indices.size()))
{
const auto currentIndices = animation.indicesp; for (auto index : currentIndices)
{
{
}
}
}
const double progress = 1.0 * animation.moveTimer.ms() / cycleT1;
for (auto p : step(Size(4, 4)))
{
const int32 value = oldGridp; RectF rect(p * CellSize, CellSize);
if (value)
{
Vec2 positionVec = rect.center();
if (animationPoints.find(p) != animationPoints.end())
{
positionVec = Math::Lerp(getRect(p).center(), getRect(animationPointsp).center(), progress); }
rect.setCenter(positionVec);
rect.stretched(-5).rounded(3).draw(HSV(0, value * 0.1, 0.9));
font(Exp2(value)).drawAt(rect.center(), ColorF(0.3));
}
else
{
rect.stretched(-5).rounded(3).draw(ColorF(0.6));
}
}
}
else
{
double deltaSize = 0.0;
std::set<int> mergedIndices;
if (animation.mergeTimer.isRunning())
{
const double progress = 1.0 * animation.mergeTimer.ms() / cycleT2;
deltaSize = -10.0*Abs((progress * 2) - 1.0);
for (auto p : step(animation.indices.size()))
{
const auto currentIndices = animation.indicesp; int count = 0;
for (auto index : currentIndices)
{
{
++count;
}
}
if (2 <= count)
{
mergedIndices.emplace(p.y * 4 + p.x);
}
}
}
Transformer2D t(Mat3x2::Translate(120, 40));
RectF(400).stretched(5).rounded(3).draw(ColorF(0.5));
for (auto p : step(Size(4, 4)))
{
const int32 value = gridp; const RectF rect(p * CellSize, CellSize);
double currentDeltaSize = 0.0;
if (mergedIndices.find(p.y * 4 + p.x) != mergedIndices.end())
{
currentDeltaSize = deltaSize;
}
if (value)
{
rect.stretched(currentDeltaSize -5).rounded(3).draw(HSV(0, value * 0.1, 0.9));
font(Exp2(value)).drawAt(rect.center(), ColorF(0.3));
}
else
{
rect.stretched(currentDeltaSize -5).rounded(3).draw(ColorF(0.6));
}
}
}
if (isGameOver)
{
Window::ClientRect().draw(ColorF(1.0, 0.5));
}
}
}