void Run(EntityManager& em, CSnakeGame& gsnake) { CGrid& grid = gsnake.GetGrid(); for (auto a = em.begin(); a != em.end(); a++) { if (!(*a)->HasComponent<CMotion>() || !(*a)->HasComponent<CHead>()) { continue; } if (!IsInsideGrid(*(*a)->GetComponent<CMotion>(), gsnake.GetGrid().GetGridSize())) { gsnake.GameOver(); } } for (auto a = em.begin(); a != em.end(); a++) { if ((*a).get() == 0 || !(*a)->HasComponent<CPlayerControlled>()) { continue; } CHead* head_a = (*a)->GetComponent<CHead>(); CMotion* motion_a = (*a)->GetComponent<CMotion>(); for (auto b = em.begin(); b != em.end(); b++) { if ((*b).get() == 0 || a == b || !(*b)->HasComponent<CMotion>()) { continue; } CMotion* motion_b = (*b)->GetComponent<CMotion>(); if (motion_a->GetCoords() == motion_b->GetCoords()) { std::pair<int, int> xy = motion_b->GetCoords(); if (grid.Get(xy.first, xy.second) < 0) { head_a->SetLength(head_a->GetLength() + 1); xy = grid.EatFood(xy.first, xy.second); em.MarkAdded(std::unique_ptr<CEntity>(new CFood(xy.first, xy.second))); em.MarkRemoved(*b); } else if (grid.Get(xy.first, xy.second) > 0 || (*b)->HasComponent<CHead>()) { gsnake.GameOver(); } } } } em.Update(); }
bool VoxelGrid::Trace(const SceneObject* parentObject, Ray* inputRay, IntersectionState* outputIntersection) { glm::mat4 spaceTransform(1.f); if (parentObject) { spaceTransform = parentObject->GetWorldToObjectMatrix(); } glm::vec3 rayPos = glm::vec3(spaceTransform * inputRay->GetPosition()); const glm::vec3 rayDir = glm::vec3(spaceTransform * inputRay->GetForwardDirection()); glm::ivec3 step; for (int i = 0; i < 3; ++i) { if (std::abs(rayDir[i]) < SMALL_EPSILON) { step[i] = 0; } else { step[i] = (rayDir[i] > SMALL_EPSILON) ? 1 : -1; } } // Implementation of "A Fast Voxel Traversal Algorithm for Ray Tracing" by John Amanatides and Andrew Woo // Link: http://www.cse.chalmers.se/edu/year/2010/course/TDA361/grid.pdf glm::ivec3 currentVoxelIndex = GetVoxelForPosition(rayPos, false); #if DEBUG_VOXEL_GRID std::cout << "Initial Voxel Position: " << glm::to_string(currentVoxelIndex) << " for " << glm::to_string(rayPos) << " going " << glm::to_string(rayDir) << std::endl; #endif // If we aren't currently within the grid, move the ray position such that we are. if (!IsInsideGrid(currentVoxelIndex)) { IntersectionState tempState; if (!boundingBox.Trace(parentObject, inputRay, &tempState)) { return false; } const float dt = tempState.intersectionT + SMALL_EPSILON; currentVoxelIndex = GetVoxelForPosition(rayPos + rayDir * dt); } #if DEBUG_VOXEL_GRID std::cout << "Final Voxel Position: " << glm::to_string(currentVoxelIndex) << " for " << glm::to_string(rayPos) << " going " << glm::to_string(rayDir) << std::endl; std::cout << "Scene Bounding: " << glm::to_string(boundingBox.minVertex) << " " << glm::to_string(boundingBox.maxVertex) << std::endl; std::cout << "Voxel Size: " << glm::to_string(voxelSize) << std::endl; #endif while (IsInsideGrid(currentVoxelIndex)) { #if DEBUG_VOXEL_GRID std::cout << "Trace Voxel: " << glm::to_string(currentVoxelIndex) << std::endl; #endif IntersectionState tempIntersection; tempIntersection.TestAndCopyLimits(outputIntersection); bool hitVoxel = grid[currentVoxelIndex[0]][currentVoxelIndex[1]][currentVoxelIndex[2]].Trace(parentObject, inputRay, &tempIntersection); // Need to verify that the hit position is within the voxel -- otherwise we're looking too far ahead. const glm::vec3 hitPosition = rayPos + rayDir * tempIntersection.intersectionT; #if DEBUG_VOXEL_GRID std::cout << " -- hit position " << glm::to_string(hitPosition) << " " << glm::to_string(GetVoxelForPosition(hitPosition)) << std::endl; #endif if (hitVoxel && GetVoxelForPosition(hitPosition) == currentVoxelIndex) { if (outputIntersection) { *outputIntersection = tempIntersection; } #if DEBUG_VOXEL_GRID std::cout << " did done hit" << std::endl; #endif return true; } int minIndex = 0; float minTMax = 0.f; FindClosestVoxelSide(minIndex, minTMax, currentVoxelIndex, step, rayPos, rayDir); assert(minIndex >= 0); currentVoxelIndex[minIndex] += step[minIndex]; #if DEBUG_VOXEL_GRID std::cout << " -- next voxel: " << glm::to_string(currentVoxelIndex) << " " << minIndex << " " << minTMax << std::endl; #endif } return false; }