Code Block References
Eng & Kor
DataLoader
void CDataLoader::LoadAllMobData()
{
std::string filePath = CPathManager::GetInst()->FindPath(DATA_PATH);
filePath += "GameData\\Mob_Data.csv";
std::ifstream file(filePath);
if (!file.is_open())
{
std::cerr << "Cannot open file at: " << filePath << "\n";
return;
}
std::string line;
while (std::getline(file, line))
{
if (line[0] == '#')
continue;
std::vector<std::string> row = Split(line, ',');
FRegularMobData data;
data.type = static_cast<ERegularMobType>(std::stoi(row[0]));
data.baseHP = std::stof(row[1]);
data.baseAttack = std::stof(row[2]);
data.baseSpeed = std::stof(row[3]);
data.baseExp = std::stof(row[4]);
CGameDataManager::GetInst()->GetMobDataManager()->AddMobData(data);
row.clear();
}
file.close();
}
Kor
void CScrollMapComponent::Render(SDL_Renderer* renderer)
{
SDL_Rect viewRect = mCamera->GetViewRect();
viewRect.x = (int)roundf(viewRect.x);
viewRect.y = (int)roundf(viewRect.y);
const SDL_Rect& texRect = mTexture->GetTextureFrame();
const FVector2D& mapScale = mTransform->GetWorldScale();
// 텍스처 내에서 카메라 오프셋 계산
int offsetX = viewRect.x % (int)mapScale.x;
int offsetY = viewRect.y % (int)mapScale.y;
if (offsetX < 0) offsetX += (int)mapScale.x;
if (offsetY < 0) offsetY += (int)mapScale.y;
// 텍스처 크기를 월드 스케일에 맞춰 비율로 계산
float texW = texRect.w / mapScale.x;
float texH = texRect.h / mapScale.y;
// 카메라 뷰가 텍스처 경계를 넘어가는지 확인
bool overX = offsetX + viewRect.w > (int)mapScale.x;
bool overY = offsetY + viewRect.h > (int)mapScale.y;
// 내부 영역과 넘침 영역 계산
int innerW = overX ? (int)mapScale.x - offsetX : viewRect.w;
int innerH = overY ? (int)mapScale.y - offsetY : viewRect.h;
int outerW = viewRect.w - innerW;
int outerH = viewRect.h - innerH;
SDL_Rect src, dst;
// 좌상단
src.x = (int)roundf(offsetX * texW);
src.y = (int)roundf(offsetY * texH);
src.w = (int)roundf(innerW * texW);
src.h = (int)roundf(innerH * texH);
dst = { 0, 0, innerW, innerH };
SDL_RenderCopy(renderer, mTexture->GetTexture(), &src, &dst);
// 우상단
if (outerW > 0)
{
src.x = 0;
src.y = (int)roundf(offsetY * texH);
src.w = (int)roundf(outerW * texW);
src.h = (int)roundf(innerH * texH);
dst = { innerW, 0, outerW, innerH };
SDL_RenderCopy(renderer, mTexture->GetTexture(), &src, &dst);
}
// 좌하단
if (outerH > 0)
{
src.x = (int)roundf(offsetX * texW);
src.y = 0;
src.w = (int)roundf(innerW * texW);
src.h = (int)roundf(outerH * texH);
dst = { 0, innerH, innerW, outerH };
SDL_RenderCopy(renderer, mTexture->GetTexture(), &src, &dst);
}
// 우하단
if (outerW > 0 && outerH > 0)
{
src.x = 0;
src.y = 0;
src.w = (int)roundf(outerW * texW);
src.h = (int)roundf(outerH * texH);
dst = { innerW, innerH, outerW, outerH };
SDL_RenderCopy(renderer, mTexture->GetTexture(), &src, &dst);
}
CComponent::Render(renderer);
}
Eng
void CScrollMapComponent::Render(SDL_Renderer* renderer)
{
SDL_Rect viewRect = mCamera->GetViewRect();
viewRect.x = (int)roundf(viewRect.x);
viewRect.y = (int)roundf(viewRect.y);
const SDL_Rect& texRect = mTexture->GetTextureFrame();
const FVector2D& mapScale = mTransform->GetWorldScale();
// Camera offset within the texture
int offsetX = viewRect.x % (int)mapScale.x;
int offsetY = viewRect.y % (int)mapScale.y;
if (offsetX < 0) offsetX += (int)mapScale.x;
if (offsetY < 0) offsetY += (int)mapScale.y;
// Texture coordinate ratio relative to world scale
float texW = texRect.w / mapScale.x;
float texH = texRect.h / mapScale.y;
// Check if the camera view exceeds the texture boundary
bool overX = offsetX + viewRect.w > (int)mapScale.x;
bool overY = offsetY + viewRect.h > (int)mapScale.y;
// Calculate inner and overflow regions
int innerW = overX ? (int)mapScale.x - offsetX : viewRect.w;
int innerH = overY ? (int)mapScale.y - offsetY : viewRect.h;
int outerW = viewRect.w - innerW;
int outerH = viewRect.h - innerH;
SDL_Rect src, dst;
// Top-left
src.x = (int)roundf(offsetX * texW);
src.y = (int)roundf(offsetY * texH);
src.w = (int)roundf(innerW * texW);
src.h = (int)roundf(innerH * texH);
dst = { 0, 0, innerW, innerH };
SDL_RenderCopy(renderer, mTexture->GetTexture(), &src, &dst);
// Top-right
if (outerW > 0)
{
src.x = 0;
src.y = (int)roundf(offsetY * texH);
src.w = (int)roundf(outerW * texW);
src.h = (int)roundf(innerH * texH);
dst = { innerW, 0, outerW, innerH };
SDL_RenderCopy(renderer, mTexture->GetTexture(), &src, &dst);
}
// Bottom-left
if (outerH > 0)
{
src.x = (int)roundf(offsetX * texW);
src.y = 0;
src.w = (int)roundf(innerW * texW);
src.h = (int)roundf(outerH * texH);
dst = { 0, innerH, innerW, outerH };
SDL_RenderCopy(renderer, mTexture->GetTexture(), &src, &dst);
}
// Bottom-right
if (outerW > 0 && outerH > 0)
{
src.x = 0;
src.y = 0;
src.w = (int)roundf(outerW * texW);
src.h = (int)roundf(outerH * texH);
dst = { innerW, innerH, outerW, outerH };
SDL_RenderCopy(renderer, mTexture->GetTexture(), &src, &dst);
}
CComponent::Render(renderer);
}
void CScrollEnvObj::Update(float deltaTime)
{
CObject::Update(deltaTime);
const FVector2D& cameraPos = mCamera->GetLookAt();
const FVector2D& objPos = GetTransform()->GetWorldPos();
FVector2D delta = cameraPos - objPos;
float snapDistance = delta.Length();
if (snapDistance >= mSnapThreshold)
{
int directionX = (int)roundf(delta.x / mMapScale.x);
int directionY = (int)roundf(delta.y / mMapScale.y);
float offsetX = mMapScale.x * directionX;
float offsetY = mMapScale.y * directionY;
GetTransform()->SetWorldPos(objPos + FVector2D(offsetX, offsetY));
}
}
MobSpawner
void CMobSpawner::Update(float deltaTime)
{
if (!mScene->GetPlayer())
return;
mRegularSpawnTime -= deltaTime;
mSubBossSpawnTime -= deltaTime;
SpawnMob();
RespawnMob();
}
void CMobSpawner::SpawnMob()
{
// SPAWN REGULAR MOB
if (mRegularSpawnTime <= 0.0f)
{
mRegularSpawnTime = CONST_REGULAR_MOB_SPAWN_INTERVAL;
CEnemy* mob = SpawnRegularMob(mUnlockedRegIdx);
mob->GetTransform()->SetWorldPos(GetRandomSpawnPos(1.1f));
// INDEX CONTROL
mRegSpawnAmount--;
if (mRegSpawnAmount <= 0)
{
mRegSpawnAmount = CONST_REGULAR_MOB_SPAWN_AMOUNT;
mUnlockedRegIdx = std::min(mUnlockedRegIdx + 1, (int)ERegularMobType::MAX - 1);
}
}
// SPAWN SUB BOSS
if (mSubBossSpawnTime <= 0.0f)
{
mSubBossSpawnTime = CONST_SUBBOSS_MOB_SPAWN_INTERVAL;
CEnemy* mob = SpawnSubBossMob(mUnlockedBosIdx);
mob->GetTransform()->SetWorldPos(GetRandomSpawnPos(1.1f));
// INDEX CONTROL
mUnlockedBosIdx = std::min(mUnlockedBosIdx + 1, (int)ESubBossMobType::MAX - 1);
}
}
void CMobSpawner::RespawnMob()
{
for (size_t i = mSpawnedMobs.size(); i > 0; i--)
{
CEnemy* mob = mSpawnedMobs[i - 1];
if (!mob->GetActive())
{
std::swap(mSpawnedMobs[i - 1], mSpawnedMobs.back());
mSpawnedMobs.pop_back();
continue;
}
FVector2D delta = mob->GetTransform()->GetWorldPos() - mScene->GetPlayer()->GetTransform()->GetWorldPos();
if (delta.Length() >= mDespawnThreshold)
{
mob->GetTransform()->SetWorldPos(GetRandomSpawnPos(1.1f));
}
}
}
FVector2D CMobSpawner::GetRandomSpawnPos(float scale) const
{
const FVector2D& playerPos = mScene->GetPlayer()->GetTransform()->GetWorldPos();
float halfW = mScene->GetCamera()->GetResolution().x * 0.5f;
float halfH = mScene->GetCamera()->GetResolution().y * 0.5f;
float scaledHalfW = halfW * scale;
float scaledHalfH = halfH * scale;
FVector2D pos = FVector2D::ZERO;
switch (std::rand() % 4)
{
case 0: // Left
pos.x = GetRandomRange(playerPos.x - scaledHalfW, playerPos.x - halfW);
pos.y = GetRandomRange(playerPos.y + scaledHalfH, playerPos.y - halfH);
break;
case 1: // Right
pos.x = GetRandomRange(playerPos.x + halfW, playerPos.x + scaledHalfW);
pos.y = GetRandomRange(playerPos.y + halfH, playerPos.y - scaledHalfH);
break;
case 2: // Up
pos.x = GetRandomRange(playerPos.x - scaledHalfW, playerPos.x + halfW);
pos.y = GetRandomRange(playerPos.y - halfH, playerPos.y - scaledHalfH);
break;
case 3: // Down
pos.x = GetRandomRange(playerPos.x - halfW, playerPos.x + scaledHalfW);
pos.y = GetRandomRange(playerPos.y + scaledHalfH, playerPos.y + halfH);
break;
}
return pos;
}
WeaponComponent
void CPistolComponent::Shoot()
{
CSoundManager::GetInst()->GetSound<CSFX>("SFX_Bullet")->Play();
CBullet* bullet = InstantiateObject<CBullet>("Bullet");
bullet->SetDamage(mOwner->GetAttack() + mPistolAttack);
}
Player
float CPlayer::GetAttack() const
{
int mightLevel = mStatus->GetMenuPowerUpLvl(EPowerUpType::MIGHT)
+ mInventory->GetPowerUpLevel(EPowerUpType::MIGHT);
float mightBonus = mStatus->GetStatModifier(EPowerUpType::MIGHT);
float mightAttack = mStatus->GetBaseAttack() * mightLevel * mightBonus;
return mStatus->GetBaseAttack() + mightAttack;
}