Skip to content

Instantly share code, notes, and snippets.

@brokenprogrammer
Created November 21, 2023 18:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brokenprogrammer/66f94a741422fdaa67ab7ff64ab7eba3 to your computer and use it in GitHub Desktop.
Save brokenprogrammer/66f94a741422fdaa67ab7ff64ab7eba3 to your computer and use it in GitHub Desktop.
STN_INTERNAL void
PerformMove(entity *Entity, event_queue *EventQueue, vector2i CurrentTile,
move_direction MoveDirection, world *World)
{
Assert(Entity->Type == ENTITY_TYPE_BRAINROLL);
u32 TemporaryArenaSize = Maraton->FrameArena.MemoryLeft / 2.0f;
memory_arena Arena = MemoryArenaInit(MemoryArenaAllocate(&Maraton->FrameArena, TemporaryArenaSize),
TemporaryArenaSize);
STNDefer { MemoryArenaFreeBytes(&Maraton->FrameArena, TemporaryArenaSize); };
if (Entity->Brainroll.HasBeenAmended)
{
return;
}
b32 NextTileIsOutOfBounds = false;
b32 DidAlterDestination = false;
vector2i MovementVector = MoveDirectionToVector(MoveDirection);
vector2i Destination = Vector2Add(CurrentTile, MovementVector);
rope_list_build_order RopeBuildOrder = ROPE_LIST_BUILD_ORDER_BACKWARDS;
if (MoveFromCurrentTileIsBlocked(World, CurrentTile))
{
EventQueuePushWallCollision(EventQueue, Entity, CurrentTile, MoveDirection);
return;
}
NextTileIsOutOfBounds = WorldTileIsOufOfBounds(World, Destination);
if (Entity->HasRopeConnection)
{
if (EntityIsFirstInRope(Entity, World))
{
RopeBuildOrder = ROPE_LIST_BUILD_ORDER_FORWARDS;
}
rope_list RopeList = RopeListCreate(Entity, World, &Arena, RopeBuildOrder);
if (!RopeInAdjacentTile(RopeList.Next, World, Destination))
{
rope_transaction_list *TransactionList = RopeCreateTransactionList(&Arena);
if (!RopeTryMove(RopeList.Next, World, &Arena, MoveDirection, EventQueue, Entity, TransactionList))
{
Destination = Vector2Minus(Destination, MovementVector);
EventQueuePushWallCollision(EventQueue, Entity, Destination, MoveDirection);
}
else
{
entity *NextTile = WorldGetStaticEntityAt(World, Destination);
entity *NextObject = WorldGetDynamicEntityAt(World, Destination);
if ((NextTile == NULL && NextObject == NULL) ||
(NextObject != NULL && NextObject->Type == ENTITY_TYPE_ROPE && RopeListContainsEntity(RopeList.Next, World, NextObject)) ||
(NextObject == NULL && NextTile != NULL && NextTile->Type == ENTITY_TYPE_PRESSURE_PLATE) ||
(NextObject == NULL && NextTile != NULL && NextTile->Type == ENTITY_TYPE_SLIME))
{
if (IsMovingTowardsRope(MoveDirection, CurrentTile, RopeList.Next->Tile))
{
RopeTransactionsCommit(TransactionList, World, EventQueue);
MoveManagePressurePlateOnMove(EventQueue, Entity, World, CurrentTile, Destination);
EventQueuePushMove(EventQueue, Entity, CurrentTile, Destination, MoveDirection);
WorldSwapTiles(World, CurrentTile, Destination);
if (NextTile != NULL && NextTile->Type == ENTITY_TYPE_PRESSURE_PLATE)
{
EventQueuePushEnterPressurePlate(EventQueue, Entity, NextTile);
}
CurrentTile = Destination;
Destination = Vector2Add(Destination, MovementVector);
DidAlterDestination = true;
}
else
{
MoveManagePressurePlateOnMove(EventQueue, Entity, World, CurrentTile, Destination);
EventQueuePushMove(EventQueue, Entity, CurrentTile, Destination, MoveDirection);
WorldSwapTiles(World, CurrentTile, Destination);
if (NextTile != NULL && NextTile->Type == ENTITY_TYPE_PRESSURE_PLATE)
{
EventQueuePushEnterPressurePlate(EventQueue, Entity, NextTile);
}
CurrentTile = Destination;
Destination = Vector2Add(Destination, MovementVector);
RopeTransactionsCommit(TransactionList, World, EventQueue);
DidAlterDestination = true;
}
}
}
}
}
entity *NextTile = WorldGetStaticEntityAt(World, Destination);
entity *NextObject = WorldGetDynamicEntityAt(World, Destination);
b32 RopeCollisionManaged = false;
while (NextTile == NULL &&
NextObject == NULL &&
NextTileIsOutOfBounds == false &&
RopeCollisionManaged == false)
{
if (!DidAlterDestination)
{
Destination = Vector2Add(Destination, MovementVector);
}
else
{
DidAlterDestination = false;
}
NextTileIsOutOfBounds = WorldTileIsOufOfBounds(World, Destination);
if (NextTileIsOutOfBounds)
{
break;
}
NextTile = WorldGetStaticEntityAt(World, Destination);
NextObject = WorldGetDynamicEntityAt(World, Destination);
if (Entity->HasRopeConnection)
{
rope_list RopeList = RopeListCreate(Entity, World, &Arena, RopeBuildOrder);
if (!RopeInAdjacentTile(RopeList.Next, World, Destination))
{
rope_transaction_list *TransactionList = RopeCreateTransactionList(&Arena);
if (!RopeTryMove(RopeList.Next, World, &Arena, MoveDirection, EventQueue, Entity, TransactionList))
{
RopeCollisionManaged = true;
Destination = Vector2Minus(Destination, MovementVector);
if (Destination.X != 0 || Destination.Y != 0)
{
MoveManagePressurePlateOnMove(EventQueue, Entity, World, CurrentTile, Destination);
EventQueuePushMove(EventQueue, Entity, CurrentTile, Destination, MoveDirection);
WorldSwapTiles(World, CurrentTile, Destination);
EventQueuePushWallCollision(EventQueue, Entity, Destination, MoveDirection);
}
}
else
{
entity *NextTile = WorldGetStaticEntityAt(World, Destination);
entity *NextObject = WorldGetDynamicEntityAt(World, Destination);
if ((NextTile == NULL && NextObject == NULL) ||
(NextObject != NULL && NextObject->Type == ENTITY_TYPE_ROPE && RopeListContainsEntity(RopeList.Next, World, NextObject)) ||
(NextObject == NULL && NextTile != NULL && NextTile->Type == ENTITY_TYPE_PRESSURE_PLATE) ||
(NextObject == NULL && NextTile != NULL && NextTile->Type == ENTITY_TYPE_SLIME))
{
if (IsMovingTowardsRope(MoveDirection, CurrentTile, RopeList.Next->Tile))
{
RopeTransactionsCommit(TransactionList, World, EventQueue);
MoveManagePressurePlateOnMove(EventQueue, Entity, World, CurrentTile, Destination);
EventQueuePushMove(EventQueue, Entity, CurrentTile, Destination, MoveDirection);
WorldSwapTiles(World, CurrentTile, Destination);
CurrentTile = Destination;
}
else
{
MoveManagePressurePlateOnMove(EventQueue, Entity, World, CurrentTile, Destination);
EventQueuePushMove(EventQueue, Entity, CurrentTile, Destination, MoveDirection);
WorldSwapTiles(World, CurrentTile, Destination);
CurrentTile = Destination;
RopeTransactionsCommit(TransactionList, World, EventQueue);
}
}
NextTile = WorldGetStaticEntityAt(World, Destination);
NextObject = WorldGetDynamicEntityAt(World, Destination);
}
}
else
{
NextTile = WorldGetStaticEntityAt(World, Destination);
NextObject = WorldGetDynamicEntityAt(World, Destination);
}
}
}
if (DidAlterDestination)
{
Destination = Vector2Minus(Destination, MovementVector);
NextTile = WorldGetStaticEntityAt(World, Destination);
NextObject = WorldGetDynamicEntityAt(World, Destination);
}
if (!RopeCollisionManaged)
{
if (NextTileIsOutOfBounds)
{
EventQueuePushMove(EventQueue, Entity, CurrentTile, Destination, MoveDirection);
EventQueuePushOutOfBounds(EventQueue, Entity);
}
else
{
if (NextObject)
{
if (NextObject == Entity)
{
return;
}
MoveCheckDynamicCollision(Entity, EventQueue, CurrentTile, Destination, MoveDirection, World, NextObject);
}
else if (NextTile)
{
MoveCheckStaticCollision(Entity, EventQueue, CurrentTile, Destination, MoveDirection, World, NextTile);
}
else
{
if (Destination.X != 0 || Destination.Y != 0)
{
EventQueuePushMove(EventQueue, Entity, CurrentTile, Destination, MoveDirection);
WorldSwapTiles(World, CurrentTile, Destination);
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment