> 기능 및 특징
1. 싱글톤 ManagerData.cs
2. Chatacter.cs 상속
- Hero.cs
- Monster.cs
3. HeroInfo.cs 저장될 데이터 클래스, 선택적 매개변수 생성자 활용
4. Data파일들
- HeroData
- ClassData
- ExpData
- GoldData
- ItemData
- MonsterData
> 추후 개선시 참고사항
- UI / 기능,데이터의 명확한 역할 구분
- 매니저클래스에 제너릭 활용
- enum 및 데이터 파일 저장 등
> JSON Data
1. class_data.json
[{
"id": 100,
"class_type": 0,
"class_name": "초보자",
"require_level": 0
},
{
"id": 101,
"class_type": 1,
"class_name": "검사",
"require_level": 10
},
{
"id": 102,
"class_type": 1,
"class_name": "파이터",
"require_level": 30
},
{
"id": 103,
"class_type": 1,
"class_name": "크루세이더",
"require_level": 50
},
{
"id": 104,
"class_type": 1,
"class_name": "히어로",
"require_level": 90
},
{
"id": 105,
"class_type": 1,
"class_name": "하이퍼 히어로",
"require_level": 120
},
{
"id": 106,
"class_type": 2,
"class_name": "아처",
"require_level": 10
},
{
"id": 107,
"class_type": 2,
"class_name": "헌터",
"require_level": 40
},
{
"id": 108,
"class_type": 2,
"class_name": "레인저 ",
"require_level": 80
},
{
"id": 109,
"class_type": 2,
"class_name": "보우마스터",
"require_level": 120
},
{
"id": 110,
"class_type": 2,
"class_name": "하이퍼 보우마스터",
"require_level": 160
}
]
2. exp_data.json
[
{
"exp_id": 100000,
"level": 1,
"require_exp": 50
},
{
"exp_id": 100001,
"level": 2,
"require_exp": 100
},
{
"exp_id": 100002,
"level": 3,
"require_exp": 150
},
{
"exp_id": 100003,
"level": 4,
"require_exp": 225
},
{
"exp_id": 100004,
"level": 5,
"require_exp": 337
},
{
"exp_id": 100005,
"level": 6,
"require_exp": 506
},
{
"exp_id": 100006,
"level": 7,
"require_exp": 759
},
{
"exp_id": 100007,
"level": 8,
"require_exp": 1139
},
{
"exp_id": 100008,
"level": 9,
"require_exp": 1708
},
{
"exp_id": 100009,
"level": 10,
"require_exp": 2562
},
{
"exp_id": 100010,
"level": 11,
"require_exp": 3844
}
]
3. gold_data.json
[{
"id": 100,
"name": "골드"
}]
4. hero_data.json
[{
"id": 1000,
"class_id": 100,
"hp": 50,
"mp": 30,
"damage": 1.5
}]
5. item_data.json
[
{
"id": 100,
"name": "초록 달팽이 껍질",
"resource_name": "green_snail_shell",
"icon_name": "ico_green_snail_shell",
"sell_price": 1,
"item_type": 0
},
{
"id": 101,
"name": "파란 달팽이 껍질",
"resource_name": "bule_snail_shell",
"icon_name": "ico_bule_snail_shell",
"sell_price": 1,
"item_type": 0
},
{
"id": 102,
"name": "빨간 달팽이 껍질",
"resource_name": "red_snail_shell",
"icon_name": "ico_red_snail_shell",
"sell_price": 1,
"item_type": 0
},
{
"id": 103,
"name": "매소 (소 )",
"resource_name": "meso_small",
"icon_name": "ico_meso_small",
"sell_price": 0,
"item_type": 4
},
{
"id": 104,
"name": "매소 (중)",
"resource_name": "meso_midium",
"icon_name": "ico_meso_midium",
"sell_price": 0,
"item_type": 4
},
{
"id": 105,
"name": "매소 (대)",
"resource_name": "meso_large",
"icon_name": "ico_meso_large",
"sell_price": 0,
"item_type": 4
}
]
6. monster_data.json
[
{
"id": 1000,
"name": "초록 달팽이",
"hp": 25,
"damage": 2.5,
"exp": 1,
"drop_item_id": 100
},
{
"id": 1001,
"name": "파란 달팽이",
"hp": 25,
"damage": 2.8,
"exp": 2,
"drop_item_id": 101
},
{
"id": 1002,
"name": "빨간 달팽이",
"hp": 25,
"damage": 3,
"exp": 3,
"drop_item_id": 102
},
{
"id": 2000,
"name": "머쉬맘",
"hp": 1000,
"damage": 8,
"exp": 10,
"drop_item_id": 103
}
]
> Code
1. Data 클래스
class MonsterData
{
public int id;
public string name;
public int hp;
public float dmage;
public int exp;
public int drop_item_id;
}
class ItemData
{
public int id;
public string name;
public string resource_name;
public string icon_name;
public int sell_price;
public int item_type;
}
class HeroData
{
public int id;
public int class_id;
public int hp;
public int mp;
public float damage;
public HeroData(int id, int class_id, int hp, int mp, float damage)
{
this.id = id;
this.class_id = class_id;
this.hp = hp;
this.mp = mp;
this.damage = damage;
}
}
class GoldData
{
public int id;
public string name;
}
class ExpData
{
public int exp_id;
public int level;
public int require_exp;
}
class ClassData
{
public int id;
public int class_type;
public string class_name;
public int require_level;
}
class Character
{
public Character()
{
}
public virtual void Attack(Character target) { }
public virtual void Hit(float damamge) { }
public virtual void Die() { }
}
2. Info 클래스
class HeroInfo
{
public string name;
public int level;
public int classType; // 직업타입
public int classGrade; // 등급 id 검사or 파이터등 등급을 말하는 것?
public float damage;
public int hp;
public int mp;
public int exp;
public int gold;
// 선택적 매개변수 뒤쪽에 배치 필요
public HeroInfo(string name, int hp, int mp, float damage,
int level = 1, int classType = 0, int classGrade = -1, int exp = 0, int gold=0)
{
this.name = name;
this.level = level;
this.classType = classType;
this.classGrade = classGrade;
this.hp = hp;
this.mp = mp;
this.damage = damage;
this.exp = exp;
this.gold = gold;
}
}
3. 싱글톤 매니저 클래스
class DataManager
{
private static DataManager singleTone;
private Dictionary<int, HeroData> dicHeroData;
private Dictionary<int, ClassData> dicClassData;
private Dictionary<int, ExpData> dicExpData;
private Dictionary<int, GoldData> dicGoldData;
public Dictionary<int, ItemData> dicItemData;
private Dictionary<int, MonsterData> dicMonsterData;
public static DataManager GetInstance()
{
if (DataManager.singleTone == null)
{
DataManager.singleTone = new DataManager();
return DataManager.singleTone;
}
else
{
return DataManager.singleTone;
}
}// GetInstance end;
public void LoadDatas()
{
string json = "";
string path = "";
try
{
// 영웅 생성
path = "./data/hero_data.json";
if (File.Exists(path))
{
json = File.ReadAllText(path);
this.dicHeroData = JsonConvert.DeserializeObject<HeroData[]>(json).ToDictionary(x => x.id, x => x);
}
// 몬스터 생성
path = "./data/monster_data.json";
if (File.Exists(path))
{
json = File.ReadAllText(path);
this.dicMonsterData = JsonConvert.DeserializeObject<MonsterData[]>(json).ToDictionary(x => x.id, x => x);
}
// 아이템 생성
path = "./data/item_data.json";
if (File.Exists(path))
{
json = File.ReadAllText(path);
this.dicItemData = JsonConvert.DeserializeObject<ItemData[]>(json).ToDictionary(x => x.id, x => x);
}
// 전직 데이터
path = "./data/class_data.json";
if (File.Exists(path))
{
json = File.ReadAllText(path);
this.dicClassData = JsonConvert.DeserializeObject<ClassData[]>(json).ToDictionary(x => x.id, x => x);
}
// 경험치 데이터
path = "./data/exp_data.json";
if (File.Exists(path))
{
json = File.ReadAllText(path);
this.dicExpData = JsonConvert.DeserializeObject<ExpData[]>(json).ToDictionary(x => x.exp_id, x => x);
}
// 골드 데이터
path = "./data/gold_data.json";
if (File.Exists(path))
{
json = File.ReadAllText(path);
this.dicGoldData = JsonConvert.DeserializeObject<GoldData[]>(json).ToDictionary(x => x.id, x => x);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
throw;
}
}
public HeroData GetCharacterDataById(int id)
{
return this.dicHeroData[id];
}
public MonsterData GetMonsterDataById(int id)
{
return this.dicMonsterData[id];
}
public ExpData GetExpDataByLevel(int level){
var result = this.dicExpData.FirstOrDefault(v => v.Value.level == level).Value;
return result;
}
public ClassData GetClassDataByClassType(int classType){
var result = this.dicClassData.FirstOrDefault(v => v.Value.class_type == classType).Value;
return result;
}
public GoldData GetGoldDataById(int id){
return this.dicGoldData[id];
}
public ItemData GetItemDataById(int dropItemId){
return this.dicItemData[dropItemId];
}
}
4. Monster / Hero 클래스
class Monster : Character
{
public int id;
public string name;
public float hp;
public float damage;
public int exp;
public int drop_item_id;
public float maxHp;
public Monster(MonsterData data)
{
this.id = data.id;
this.name = data.name;
this.hp = data.hp;
this.damage = data.dmage;
this.exp = data.exp;
this.drop_item_id = data.drop_item_id;
this.maxHp = data.hp;
Console.WriteLine(this.name + " 이 생성되었습니다.");
}
public override void Attack(Character target)
{
Console.WriteLine(target);
target.Hit(this.damage);
}
public override void Hit(float damage)
{
Console.WriteLine("몬스터 hit");
this.hp -= damage;
if (this.hp <= 0)
{
this.Die();
}
}
public override void Die()
{
Console.WriteLine("몬스터가 죽었습니다.");
}
public bool IsDie() {
this.hp = 0; //강제 죽임 test
if (this.hp <= 0) {
return true;
}
return false;
}
}
class Hero : Character
{
// 데이터 변경과 에니메이션 담당 -> 외부에 결과 전달(App())
public HeroInfo info;
public Hero()
{
Console.WriteLine("영웅이 생성되었습니다.");
}
public void Init(HeroInfo info)
{
this.info = info;
}
public override void Attack(Character target)
{
target.Hit(this.info.damage);
}
public override void Hit(float damage)
{
Console.WriteLine($"{this.info.name}이 {damage} 피해를 입어습니다.");
}
public override void Die()
{
this.info.hp = 0;
Console.WriteLine("- game over 주인공이 죽었습니다.");
}
// 경험치 획득
public void GetExp(int getExp) {
this.info.exp += getExp;
Console.WriteLine($"{this.info.exp} 경험치 획득");
Console.WriteLine();
}
// 경험치 확인
public void CheckExp(Hero hero) {
var dataManager = DataManager.GetInstance();
var exp = hero.info.exp; // 현재 경험치
//현재 레벨로 가져온 exp데이터
var expData = dataManager.GetExpDataByLevel(hero.info.level);
//다음레벨 exp데이터
var nextData = dataManager.GetExpDataByLevel(hero.info.level+1);
// 레벨업 체크
if(exp >= expData.require_exp){
this.LevelUp(hero);
}else{
Console.WriteLine($"-Lev{hero.info.level} / {hero.info.exp} -> -Lev{nextData.level} / {expData.require_exp} 필요");
}
Console.WriteLine();
}
// 레벨 업
public void LevelUp(Hero hero)
{
// 전직 여부 체크
var dataManager = DataManager.GetInstance();
if(hero.info.classType == 0 ){ // 초보자 일경우
Console.WriteLine("- 축하합니다. 전직이 가능합니다.");
this.ClassChange();
this.HeroPrint();
}else{
// 레벨업
Console.WriteLine("- 레벨이 올랐습니다.");
this.UpGrage();
this.HeroPrint();
}
}
// 스텟 상향
public void UpGrage(){
var dataManager = DataManager.GetInstance();
var classData = dataManager.GetClassDataByClassType(this.info.classGrade+1);
this.info.classGrade = classData.id;
this.info.name = classData.class_name;
this.info.level +=1;
}
public void HeroPrint(){
var hero = this.info;
Console.WriteLine($"name:{hero.name}/ Lev:{hero.level} / (hp:{hero.hp}/hp:{hero.mp})");
}
// 전직
public void ClassChange()
{
var dataManager = DataManager.GetInstance();
var choiceClass1 = dataManager.GetClassDataByClassType(1);
var choiceClass2 = dataManager.GetClassDataByClassType(2);
Console.WriteLine($"1.{choiceClass1.class_name} / 2.{choiceClass2.class_name} 선택");
Console.WriteLine("1번 선택");
var userInput=1;
switch (userInput)
{
case 1:
Console.WriteLine("검사를 선택하셨습니다.");
this.info.name = choiceClass1.class_name;
this.info.classType = choiceClass1.class_type;
this.info.classGrade = choiceClass1.id; // 검사 101
this.info.level +=1;
break;
case 2:
Console.WriteLine("아처를 선택하셨습니다.");
this.info.name = choiceClass2.class_name;
this.info.classType = choiceClass2.class_type;
this.info.classGrade = choiceClass2.id; // 아처 10
this.info.level +=1;
break;
default:
break;
}
Console.WriteLine();
}
//아이템 획득
public void PickItem(Monster target){
var dataManager = DataManager.GetInstance();
var getItem = dataManager.GetItemDataById(target.drop_item_id);
Console.WriteLine($"- 아이템획득: {getItem.name} / 판매가격:{getItem.sell_price} / {getItem.resource_name}");
Console.WriteLine();
}
//골드 획득
public void PickGold(int id){
var dataManagere = DataManager.GetInstance();
GoldData goldData = dataManagere.GetGoldDataById(id);
this.info.gold += goldData.id;
Console.WriteLine($"- {goldData.name}({goldData.id}) 획득!");
Console.WriteLine();
}
}
5. App 클래스
class App
{
public App()
{
// 데이터 로드
// 영웅 생성
// 몬스터 생성
// 몬스터 공격
// 몬스터 처치
// 아이템 드랍
// 경험치, 아이템 획득
// 레벨업
// 전직
var dataManager = DataManager.GetInstance();
dataManager.LoadDatas();
Hero hero = this.CreateDefaultHero();
Monster monster = this.CreateMonster(1000);
//몬스터 공격
hero.Attack(monster);
Console.WriteLine($"({monster.hp}/{monster.maxHp})" );
// 죽임
monster.Die();
monster.IsDie();
// 경험치 획득
if (monster.IsDie())
{
hero.GetExp(monster.exp);
hero.CheckExp(hero);
// 강제 레벨업 - 전직
hero.LevelUp(hero);
// 아이템 획득
hero.PickItem(monster);
// 골드획득 - 몬스터 고유 id 전달하여 해당 수치만큼 골드 수급
hero.PickGold(100);
}
}
public Monster CreateMonster(int id)
{
var monsterData = DataManager.GetInstance().GetMonsterDataById(id);
return new Monster(monsterData);
}
public Hero CreateDefaultHero()
{
var characterData = DataManager.GetInstance().GetCharacterDataById(1000);
var heroInfo = new HeroInfo("홍길동", characterData.hp, characterData.mp, characterData.damage);
Hero hero = new Hero();
hero.Init(heroInfo);
Console.WriteLine(hero.info.name + " 님이 입장하셨습니다.");
return hero;
}
}
'c# 강의 > 과제' 카테고리의 다른 글
20200429 - 일일보상 + 연속보상 + Date연산 (0) | 2020.05.01 |
---|---|
20200428 - 상점(판매종료일/레벨제한/구매수량제한 등) (0) | 2020.04.29 |
20200421 - File 읽기 (JSON) (0) | 2020.04.22 |
20200420 - List 과제 (0) | 2020.04.20 |
20200417 - 주말과제(요리,레시피) (0) | 2020.04.19 |