#pragma once
#include "Math.h"
// 자식들이 공통적으로 가져야 할 기능을 만들어야 한다.
class ConsoleObject
{
public:
ConsoleObject();
ConsoleObject(const int2& _StartPos, char _RenderChar);
int2 GetPos();
void SetPos(const int2& _Pos);
char GetRenderChar();
protected:
int2 Pos = { 0, 0 };
char RenderChar = '@';
};
#include "ConsoleObject.h"
ConsoleObject::ConsoleObject() {
}
ConsoleObject::ConsoleObject(const int2& _StartPos, char _RenderChar)
: Pos(_StartPos), RenderChar(_RenderChar)
{
}
int2 ConsoleObject::GetPos()
{
return Pos;
}
char ConsoleObject::GetRenderChar()
{
return RenderChar;
}
void ConsoleObject::SetPos(const int2& _Pos) {
Pos = _Pos;
}
#include "Player.h"
#include "ConsoleScreen.h"
#include <conio.h>
Player::Player()
{
}
Player::Player(const int2& _StartPos, char _RenderChar)
: ConsoleObject(_StartPos, _RenderChar)
{
//Pos = _StartPos;
//RenderChar = _RenderChar;
}
...
Is A : ~이다. 상속.
Has A : 가졌다.
Player 클래스가 FightUnit 클래스를 상속 받았으므로 Player
Is A FightUnit
,
멤버변수로 다른 클래스를 가지면 Player
Has A Sword
라고 표현한다.
class Item {
public:
int cost;
};
class Sword : public Item {
};
class FightUnit {
};
class Player : public FightUnit {
private:
Sword Weapon;
};
자식 클래스의 객체는 언제든 부모 클래스의 참조형으로 형변환이 될 수 있다.
참조형으로 주고받는 것이 굉장히 건강하고 권장되는 암시적 형변환이다.
class FightUnit {
public:
};
class Player : public FightUnit {
private:
Sword Weapon;
};
int main() {
{
// 업캐스팅
// 굉장히 건강하고 권장되는 암시적 형변환
Player NewPlayer;
FightUnit* Unit = &NewPlayer;
}
{
// 이렇게도 되긴 함
Player NewPlayer;
FightUnit Unit = NewPlayer;
}
return 0;
}
부모클래스의 참조형에서 자식클래스의 참조형으로 변환하는 것이다.
class FightUnit {
};
class Player : public FightUnit {
};
class Monster : public FightUnit {
};
int main() {
Player NewPlayer;
Monster NewMonster;
FightUnit* NewUnit = &NewMonster;
// 다운캐스팅
Player* CurPlayer = reinterpret_cast<Player*>(NewUnit);
return 0;
}
여러 클래스를 상속받을 수 있다.
#include <iostream>
class TalkUnit {
public:
void Talk(const TalkUnit& _Unit) {
}
};
class MoveUnit {
public:
void Move() {
}
};
class FightUnit {
public:
void Fight(const FightUnit& _Unit) {
if (this == &_Unit) {
return;
}
}
};
class Player : public TalkUnit, public MoveUnit, public FightUnit { // 다중상속
};
class Monster : public MoveUnit, public FightUnit {
};
int main() {
Player NewPlayer;
Monster NewMonster;
return 0;
}
ex) FightUnit를 상속받는 Player가 있다. " FightUnit에서 Player를 알아야 하는 코딩을 해야겠다. " 라는 생각이 들었다면 잘못된 생각이다.
문법적으로는 가능하다.
class FightUnit {
public:
Player* Test; // 구조를 망치는 행위
};
class Player : public FightUnit {
};
함수 뒤에 const를 붙이는 것은 this를 const Player* const this
로 변환하겠다는 의미이다. this의 멤버변수값을 바꾸지 않도록 한다.
Tip) 클래스는 밑단 개념이 아닌 근본적인 개념을 제공하기 위한 클래스를 만드는 경우가 많다.
부모의 함수를 사용하고 싶다면 FullName을 사용하는 것이 정석이지만 보통 그렇게 사용하지 않는다. 클래스 멤버변수, 멤버함수 모두 FullName이 있다.
F8
: 에러난 곳으로 바로 이동.
// in 'StatusUnit.cpp'
void StatusUnit::SetName(const char* _Name)
{
int Count = 0;
while (*(_Name + Count)) {
Count++;
}
for (int i = 0; i < Count; i++) {
Name[i] = _Name[i];
}
}
Hp -= _Unit.Att
라고 사용하던 것을 랜덤 데미지rDamage
를 바로 계산해서 때리도록 변경하였다. // in 'FightUnit.cpp'
void FightUnit::DamageLogic(FightUnit& _Unit) // _Unit이 때리는 것
{
// Min ~ Max 사이의 랜덤한 공격력으로 공격.
rDamage = rand() % (_Unit.MaxAtt - _Unit.MinAtt + 1) + _Unit.MinAtt;
Hp -= rDamage;
_Unit.PrevAtt = rDamage;
}
int main()
{
// 실핼할 때마다 달라지는 변수의 메모리 주소를 이용해서 srand()
int Value = 0;
__int64 Seed = reinterpret_cast<__int64>(&Value);
srand(static_cast<unsigned int>(Seed));
Player NewPlayer = Player();
NewPlayer.SetName("Player");
FightZone NewZone;
NewZone.Fight(NewPlayer);
}
속도 - 체력
이 큰 곳이 선공을 할 수 있도록 한다. (속도가 빠르고 체력이 적을수록 선공 확률이 높도록 만들고 싶었다.)// in 'FightZone.cpp'
void FightZone::Fight(FightUnit& _Player)
{
NewMonster.SetName("Monster");
//NewMonster.AddSpeed(5); // 테스트용
while (true)
{
_Player.StatusRender();
NewMonster.StatusRender();
bool IsEnd = false;
// 속도가 빠르고 체력이 적으면 선공
int PlayerStat = _Player.GetSpeed() - _Player.GetHp();
int MonsterStat = NewMonster.GetSpeed() - NewMonster.GetHp();
if (PlayerStat > MonsterStat) {
// Player 선공
IsEnd = FightLogic(_Player, NewMonster, _Player, NewMonster);
}
else {
IsEnd = FightLogic(NewMonster, _Player, _Player, NewMonster);
}
if (true == IsEnd) { // 죽었으면 끝
return;
}
else { // 안 끝났으면 한 쪽에 속도 지급
// Player의 이전 공격력이 더 쎘으면 Player 속도 [1]만큼 추가
int gap = _Player.GetPrevAtt() - NewMonster.GetPrevAtt();
if (gap > 0) {
_Player.AddSpeed(1);
}
else if (gap < 0) {
NewMonster.AddSpeed(1);
}
}
}
}
(키를 누를 때마다 공격이 이어지는 모습)
공격력이 랜덤이고 선공, 후공도 계산에따라 달라진다.