← 返回项目列表

Libra

AI的Heat Map

C++2D PhysicsGame Engine

Heat Map

AI的Heat Map

void Map::SolidMapBFS( TileHeatMap& out_distanceField, IntVec2 startTileCoords )
{
	for (int i = 0; i < out_distanceField.m_dimensions.x * out_distanceField.m_dimensions.y; i++)
	{
		out_distanceField.m_values[i] = HEAT_MAP_SPECIAL_VALUE;
		m_isTileSearchedSolidMap[i] = false;
	}
	std::vector tileCoordinates;

	int currentIndex = 0;
	tileCoordinates.reserve(  m_mapDef.m_dimensions.x *  m_mapDef.m_dimensions.y );
	tileCoordinates.push_back( startTileCoords );
	out_distanceField.SetValue( GetTileIndexForTileCoords( startTileCoords ), 0.f );

	while (currentIndex < tileCoordinates.size())
	{
		startTileCoords = tileCoordinates[currentIndex];
		m_isTileSearchedSolidMap[GetTileIndexForTileCoords( startTileCoords )] = true;
		int tempIndex = 0;
		IntVec2 nextCoord;

		nextCoord = startTileCoords + IntVec2( 1, 0 );
		tempIndex = GetTileIndexForTileCoords( nextCoord );

		if (!isTileOutOfBound( nextCoord ) && !m_isTileSearchedSolidMap[tempIndex] && !m_tiles[tempIndex].m_tileDefinition->m_isSolid)
		{
			m_isTileSearchedSolidMap[tempIndex] = true;
			tileCoordinates.push_back( nextCoord );
			float currentTileValue = out_distanceField.GetValue( startTileCoords );
			out_distanceField.SetValue( tempIndex, currentTileValue + 1 );
		}

		nextCoord = startTileCoords + IntVec2( -1, 0 );
		tempIndex = GetTileIndexForTileCoords( nextCoord );
		if (!isTileOutOfBound( nextCoord ) && !m_isTileSearchedSolidMap[tempIndex] && !m_tiles[tempIndex].m_tileDefinition->m_isSolid)
		{
			m_isTileSearchedSolidMap[tempIndex] = true;
			tileCoordinates.push_back( nextCoord );
			float currentTileValue = out_distanceField.GetValue( startTileCoords );
			out_distanceField.SetValue( tempIndex, currentTileValue + 1 );
		}

		nextCoord = startTileCoords + IntVec2( 0, 1 );
		tempIndex = GetTileIndexForTileCoords( nextCoord );
		if (!isTileOutOfBound( nextCoord ) && !m_isTileSearchedSolidMap[tempIndex] && !m_tiles[tempIndex].m_tileDefinition->m_isSolid)
		{
			m_isTileSearchedSolidMap[tempIndex] = true;
			tileCoordinates.push_back( nextCoord );
			float currentTileValue = out_distanceField.GetValue( startTileCoords );
			out_distanceField.SetValue( tempIndex, currentTileValue + 1 );
		}

		nextCoord = startTileCoords + IntVec2( 0, -1 );
		tempIndex = GetTileIndexForTileCoords( nextCoord );
		if (!isTileOutOfBound( nextCoord ) && !m_isTileSearchedSolidMap[tempIndex] && !m_tiles[tempIndex].m_tileDefinition->m_isSolid)
		{
			m_isTileSearchedSolidMap[tempIndex] = true;
			tileCoordinates.push_back( nextCoord );
			float currentTileValue = out_distanceField.GetValue( startTileCoords );
			out_distanceField.SetValue( tempIndex, currentTileValue + 1 );
		}
		currentIndex++;
	}

	EntityList &scorpios = m_entityListsByType[_EVIL_SCORPIO];
	for (int i = 0; i < scorpios.size(); i++)
	{
		if (scorpios[i] != nullptr)
		{
			IntVec2 scorpioCoords = GetTileCoordsForWorldPos( scorpios[i]->m_position );
			int scorpioTileIndex = GetTileIndexForTileCoords( scorpioCoords );
			out_distanceField.SetValue( scorpioTileIndex, HEAT_MAP_SPECIAL_VALUE );
		}		
	}
}

生成HeatMap的代码

碰撞

子弹碰撞是预防性碰撞,坦克碰撞是矫正性碰撞

​Libra中的碰撞

void Map::EntityCollision( EntityType entityType1, EntityType entityType2 )
{
	EntityList& typeEntity1 = m_entityListsByType[entityType1];
	EntityList& typeEntity2 = m_entityListsByType[entityType2];
	if (typeEntity1 == typeEntity2)
	{
		for (int i = 0; i < typeEntity1.size(); i++)
		{
			for (int j = i + 1 ; j < typeEntity2.size(); j++)
			{
				if (typeEntity1[i] != nullptr && typeEntity2[j] != nullptr)
				{
					if (typeEntity1[i]->m_isPushByOthers && typeEntity1[i]->m_isPushOthers && typeEntity2[j]->m_isPushByOthers && typeEntity2[j]->m_isPushOthers)
					{
						PushDiscsOutOfEachOther2D( typeEntity1[i]->m_position, typeEntity1[i]->m_physicsRadius, typeEntity2[j]->m_position, typeEntity2[j]->m_physicsRadius );
					}
					else if (typeEntity1[i]->m_isPushByOthers && typeEntity1[i]->m_isPushOthers && !typeEntity2[j]->m_isPushByOthers && typeEntity2[j]->m_isPushOthers)
					{
						PushDiscOutOfFixedDisc2D( typeEntity1[i]->m_position, typeEntity1[i]->m_physicsRadius, typeEntity2[j]->m_position, typeEntity2[j]->m_physicsRadius );
					}
					else if (!typeEntity1[i]->m_isPushByOthers && typeEntity1[i]->m_isPushOthers && typeEntity2[j]->m_isPushByOthers && typeEntity2[j]->m_isPushOthers)
					{
						PushDiscOutOfFixedDisc2D( typeEntity2[j]->m_position, typeEntity2[j]->m_physicsRadius, typeEntity1[i]->m_position, typeEntity1[i]->m_physicsRadius );
					}
				}

			}
		}
	}
	else
	{
		for (int i = 0; i < typeEntity1.size(); i++)
		{
			for (int j = 0; j < typeEntity2.size(); j++)
			{
				if (typeEntity1[i] != nullptr && typeEntity2[j] != nullptr)
				{
					if (typeEntity1[i]->m_isPushByOthers && typeEntity1[i]->m_isPushOthers && typeEntity2[j]->m_isPushByOthers && typeEntity2[j]->m_isPushOthers)
					{
						PushDiscsOutOfEachOther2D( typeEntity1[i]->m_position, typeEntity1[i]->m_physicsRadius, typeEntity2[j]->m_position, typeEntity2[j]->m_physicsRadius );
					}
					else if (typeEntity1[i]->m_isPushByOthers && typeEntity1[i]->m_isPushOthers && !typeEntity2[j]->m_isPushByOthers && typeEntity2[j]->m_isPushOthers)
					{
						PushDiscOutOfFixedDisc2D( typeEntity1[i]->m_position, typeEntity1[i]->m_physicsRadius, typeEntity2[j]->m_position, typeEntity2[j]->m_physicsRadius );
					}
					else if (!typeEntity1[i]->m_isPushByOthers && typeEntity1[i]->m_isPushOthers && typeEntity2[j]->m_isPushByOthers && typeEntity2[j]->m_isPushOthers)
					{
						PushDiscOutOfFixedDisc2D( typeEntity2[j]->m_position, typeEntity2[j]->m_physicsRadius, typeEntity1[i]->m_position, typeEntity1[i]->m_physicsRadius );
					}
				}

			}
		}
	}
}

纠正性碰撞代码

void Bullet::BulletReflecStone( float deltaSeconds )
{
	Vec2 currentPos = m_position;
	m_position += m_velocity * deltaSeconds;
	if (g_theGame->m_currentMap->IsPositionInSolidTile( m_position ))
	{
		if (m_entityType == _GOOD_BULLET)
		{
			if (m_bulletType == GOOD_BOLT || m_bulletType == GOOD_BULLET)
			{
				g_audio->StartSound( g_soundArray[bulletReflectionSound] );
				IntVec2 currentTileCoords = g_theGame->m_currentMap->GetTileCoordsForWorldPos( currentPos );
				IntVec2 nextFrameTileCoords = g_theGame->m_currentMap->GetTileCoordsForWorldPos( m_position );
				Vec2 tanVec = Vec2( 0.f, 0.f );
				tanVec.x = (float)(nextFrameTileCoords.x - currentTileCoords.x);
				tanVec.y = (float)(nextFrameTileCoords.y - currentTileCoords.y);
				Vec2 normal = (tanVec).GetRotated90Degrees();
				m_velocity = -m_velocity.GetReflected( normal );
				m_orientationDegrees = m_velocity.GetOrientationDegrees();
				float offSetDegrees = rng->RollRandomFloatInRange( -5.f, 5.f );
				m_orientationDegrees += offSetDegrees;
				m_velocity = Vec2::MakeFromPolarDegrees( m_orientationDegrees, m_speed );
				m_position = currentPos;
				m_hitStoneTime++;

				IntVec2 tileCoords = g_theGame->m_currentMap->GetTileCoordsForWorldPos( m_position );
				int currentTileIndex = g_theGame->m_currentMap->GetTileIndexForTileCoords( currentTileCoords.x, currentTileCoords.y );
				if (g_theGame->m_currentMap->m_tiles[currentTileIndex].m_tileDefinition->m_isDestructible)
				{
					g_theGame->m_currentMap->m_tiles[currentTileIndex].m_tileDefinition->m_health--;
					if (g_theGame->m_currentMap->m_tiles[currentTileIndex].m_tileDefinition->m_health <= 0)
					{
						g_theGame->m_currentMap->m_tiles[currentTileIndex].m_tileDefinition = TileDefinition::GetDefByName( g_theGame->m_currentMap->m_tiles[currentTileIndex].m_tileDefinition->m_destroyedTileType );
					}
				}
			}
		}
}

预防性碰撞代码

截图