2016년 9월 25일 일요일

4)ActionFighter's state design_2

4) ActionFighter


previously, I introduce how Image drawing and state working in AF(ActionFighter). and this time I'll explain how AF use state and receive input and process this.

AF need to have various state. in BitmapWorld,using skill by mouse click and drag and each skill constituted by more than one of state. AF use AFskillMap,object, to save these skills.



-      AFskillMap




there are function and variable of SkillMap.
in one SkillMap, it contain owner AF and 6 of initial state of skill.
(continuous next state is created and called by this state's inputSlot function)

addSkill function overlay initiated skill on wanted slot and by getSkill, you can get that slot's reference.






now Let's see ActionFighter's variable.


state  Changed by input is saved in skillMap's slot. but AF need more state change except on input and that kind of state saved in AF directly.

these states initiate when AF created.

CurState: AF's current activating state.
CurSkillMap: AF's current activating skillMap.
AtkSkillMap: skillMap saving attacking skills, activating by leftClick.
DefSkillMap: skillMap saving defencing skills, activating by rightClick.
IdleState: defult State. idleState will be explain lately.
DamagedState: when AF take damage, change to this state.
DeadState: when you die.
PushedState: AF pushed by special situation.
Downstate: down.
EventState: state for eventScene






AF change it's state on various situation.

AFstate's all state changing using changeState(). and changeState usually using in inner AFstate.

it Mean AF change it's state by calling curState's function.



-      damaged
when AF take damage by target, curState's damaged function called and it process it's action in curState.



-      update
when tick event call, curState's Update called.






-      inputSlot
this is BitmapWorld's special inputStyle. by drag mouse to each 6 direction, you can get slot data.
according to slot input, curState's inputSlot data changed. but before that, it need to convert mouse input to slot input.

first, by click mouse, mouse position is initiated and skillMap activated.






















row inputProcess in playerController. It will explain later.



this graph attached to tick event' sequence 2.


AF check curSkillMap is activated every time. and when curSkillMap is activated and mouse position' length overrun some distance, it calculate it's degree and sand slot data to curState's inputSlot.

simply ActionFighter perform it's action by curState's function called by damaged,update,inputSlot Event.

by this, ActionFighter's major performance is explained.
next I'll introduce PlayerConteroller that work for player input.



4)ActionFighter의 상태 구현_2


4) ActionFighter

지금까지 AF(ActionFighter) 안에서 어떻게 이미지가 그려지는지, 그리고 어떻게 상태가 작동되는지를 설명했습니다. 이번엔 AF가 어떻게 상태를 사용하는지 그리고 어떻게 입력을 받아들여서 처리하는지를 설명하겠습니다.



AF는 다양한 상태를 지닐 수 있어야 합니다. 비트맵월드는 마우스 클릭과 드래그로 스킬을 사용합니다. 그리고 각각의 스킬은 한 개 이상의 상태로 구현되어 있습니다. 이 스킬을 저장하기 위해 AFskillMap이라는 클래스를 사용합니다.



-      AFskillMap




SkillMap의 함수와 변수들입니다.
하나의 skillMap 안에는 해당 객체의 소유AF와 스킬의 초기 상태를 저장하는 slot6개 있습니다. (연속된 다음 상태는 해당 상태의 inputSlot 함수를 통해 생성, 호출합니다)

AddSkill 함수는 원하는 슬롯에 스킬을 초기화 하여 덮어씌우고 getSkill을 통해 해당 슬롯의 레퍼런스를 받아옵니다.






이제 ActionFighter의 변수를 살펴보겠습니다.

입력을 통한 상태 변화는 skillMap의 해당 슬롯값에 저장됩니다. 하지만 입력 이외에도 다양한 상태변화가 필요하고 그러한 상태들은 AF에 직접 저장되어 있습니다.
해당 상태들은 AF가 생성될 때 초기화됩니다.

CurState: 현재 AF의 상태입니다.
CurSkillMap: 현재 활성화 되어있는 skillMap 값입니다.
AtkSkillMap: 마우스 왼쪽 클릭으로 활성화되는 공격형 스킬을 저장하는 스킬맵의 값입니다.
DefSkillMap: 마우스 오른쪽 클릭으로 활성화되는 수비형 스킬을 저장하는 스킬맵의 값입니다.
IdleState: 아무런 행동도 취하지 않을 시 진입되는 상태. idle상태에 대해선 나중에 더 설명하겠습니다.
DamagedState: 공격을 당할 시 진입하게 되는 상태입니다.
DeadState: 차가운 시체가 되는 상태입니다.
PushedState: 특정 조건에 의해 밀려나게 되는 상태입니다.
Downstate: 쓰러진 상태입니다.
EventState: 이벤트씬에서 사용되는 상태입니다.






AF는 상황에 따라 저장된 상태들로 상태 변화를 합니다.

저번 AFstate 설명에서 말했듯 모든 상태 변화는 AFstatechangeState()에 의해 변화됩니다. 그리고 changeState는 보통 AFstate의 내부에서 구현됩니다.
AFcurState의 함수를 호출함으로써 상태를 변화시킵니다.



-      damaged
상대의 공격에 의해 대미지를 받게 되면 curStatedamaged함수를 호출하여 현재 상태에서 취해야 할 행동을 처리합니다.



-      update
매 틱마다 curStateUpdate 함수를 호출합니다.






-      inputSlot

비트맵월드의 특수한 입력 형식입니다. 6방향으로 마우스를 드레그 함으로써 각각의 slot값에 접근할 수 있게 됩니다.
슬롯 입력에 따라 curState가 입력받은 slot값에 따라 처리하게 됩니다. 하지만 일단 그 전에 마우스 입력을 슬롯입력으로 바꾸는 작업이 필요합니다.
 우선 마우스 클릭을 통해 마우스 좌표를 초기화하고 skillMap을 활성화 합니다.



















1차적인 입력 처리는 playerController에서 이루어집니다. 이는 나중에 설명하겠습니다.



해당 그래프는 틱 이벤트의 시퀸스2에서 이어져있습니다.

AF는 매순간 curSkillMap이 활성화되어 있는지 확인합니다. 마우스 입력에 의해 curSkillMap이 활성화 되고 마우스 포인터의 드래그 길이가 일정 거리를 초과하게 되면 각도를 계산하여 curStateinputSlot에 계산된 slot값을 전달해 호출한 후 다시 포인터의 위치를 초기화 시킵니다.



정리하자면 ActionFighterdamaged, update, inputSlot 이벤트를 통해 curState에 접근하여 필요한 기능을 구현하게 됩니다.

이로써 ActionFighter의 대부분의 기능에 대한 설명이 끝났습니다.
다음엔 사용자의 입력을 담당하는 playerController에 대하여 설명하겠습니다.



2016년 9월 5일 월요일

3)ActionFighter's State design





When I first making this, the hardest thing was how Making various character’s action. And the hardest thing in making action is keeping independency on each action.

I’ve searched, and I found state pattern and I use it.

Simply state pattern mean making each character’s state (move, attack, damaged etc.) to object.

I’ll explain state pattern more with BitmapWorld.



- AFstate


In BitmapWorld, all state inheritance AFstate. AFstate do not use itself but it has some functions that all state share.




Let’s see variable.
 


ownerRef: reference of AF having this. When state initiate, it connected.

state: structure having essential variables for expressing AF’s state.





 

And having information about other variable used in functions and reference of nextState.


AFstate has some functions to realize state.



Initiate: called when object created. by this function, state initiate.

Update: called on every tick. by this function, state realize continual action.
  • update charge time and atk, next slot image needed to change by charge rate.
  • change Stamina according as staminaUse.
  • check curSkillMap with Essential SkillMap and if wrong, change state to IdelState.
*SkillMap: Object saving state can called by AF's input. by mouse left or right click, you can call each different skillMap.
Enter: called one time when enter this state.
  • if this state cause damage to target, calculate finalDamage by preChargeRate of pre state. target take final damage.
  • change AF's sprite to state's motion.
  • create slotComponents and draw def, pre slot image.

Leave: like enter, it called one time when leave state.
  • reset chargeTime to 0.
  • clean slot data.
  • return chargeRate to nextState.

InputSlot: called when receive AF's input.
  • if state's nextSlot data and input Slot data is same and state have nextState, change state to next state. in this action, when real object of nextState is not exist, create one and if exist object of nextState, use this.

Damaged: called when AF take damage.
  • receive causer's finalDamage and check it succeed blocking by damage's atkDirection match with state's defSlot.
  • if it fail to block, change Hp and Stamina by damage formula.

*damage formula
BitmapWorld have damage formula related with Hp and Stamina both.
this is Damage structure.



if attackDirection avoid defSlot and succeed attack, damage caused by 3 type of damage.

damage = pureDamage+(normalDamage - stamina / 2) and deal to stamina after deal Hp.
after taking damage, if stamina is 0, AF changeState to down and if Hp is 0, AF dead.



ChangeState: it used for change state. in this function, enter and leave realizate.

All state changing work by this function.

most of state add it's own logic to AFstate's function. some special state change all function but purpose of function call never change.


nextTime, I'll introduce how ActionFighter work including this State.

3)ActionFighter의 상태 구현





게임을 만들려고 했을 때 가장 고민이었던 부분은 다양한 캐릭터의 행동을 어떻게 구현하는가 였습니다. 행동을 구현하는데 가장 힘들었던 점은 각각의 행동이 서로 간섭하지 않는 거였죠.

여러가지 알아보던 중 상태 패턴이란 것을 알게 되었고 이를 이용하기로 했습니다.

상태 패턴은 간단히 말해서 캐릭터의 상태(이동, 공격 준비, 타격 당함 등등)를 하나의 객체로 만들어서 구현하는 것입니다.

비트맵월드에 적용시킨 상태 패턴을 보며 좀 더 자세히 설명하겠습니다.


- AFstate


비트맵월드에서의 상태는 모두 AFstate라는 클래스를 상속받습니다. AFstate는 그 자체만으로 쓰이진 않지만 모든 상태들이 공유하는 공통된 기능을 구현하고 있습니다.

AFstate의 변수들부터 살펴보겠습니다.

 
ownerRef: 현재 상태를 소유하고 있는 AF의 레퍼런스. 초기화 할 때 레퍼런스를 연결시켜줍니다.
state: AF의 상태를 표현하는데 필수적인 요소들을 가지고 있는 구조체입니다.



 
그 외 내부적으로 사용되는 변수들과 해당 상태가 가지고 있는 다음 상태에 대한 레퍼런스등에 대한 정보가 있습니다.


AFstate는 상태를 구현하기 위한 몇가지 함수들을 가지고 있습니다.
Initiate: 객체가 처음 생성 될 때 호출하는 함수입니다. 상태별로 필요한 초기화를 합니다.

Update: 매 틱마다 발동되는 함수입니다. 해당 상태에서 지속적으로 이루어져야 할 일을 구현합니다.
  • 충전시간의 최신화와 충전시간에 따라 이미지가 바뀔 수 있는 atkSlotnextSlot을 매번 최신화 합니다.
  • 스태미나 사용량에 따라 시간에 따라 스태미나를 일정량 변화시킵니다.
  • 현재 AF의 스킬맵을 확인해서 필수 스킬맵이 있을 경우 그것과 맞지 않다면 idel상태로 상태를 변화시킵니다.
*스킬맵: AF가 입력을 통해 불러올 수 있는 상태를 저장 해놓는 객체입니다. 마우스 우클릭, 좌클릭으로 각기 다른 스킬맵을 불러올 수 있습니다.
Enter: 해당 상태에 들어올 때 한번 발동되는 함수입니다.
  • 상대에게 대미지를 주는 상태일 경우 이전 상태에서 받은 충전시간을 이용해 최종 대미지를 계산합니다. 상대에겐 이 최종 대미지가 들어가게 됩니다.
  • 상태가 가진 모션에 따라 AF의 스프라이트를 변경시깁니다.
  • 슬롯을 그리기 위해 슬롯 컴포넌트를 만들고 실시간으로 그려질 필요 없는 defSlotpreSlot을 그립니다.

Leave: enter와 마찬가지로 해당 상태에서 나갈 때 발동되는 함수입니다.
  • 해당 상태의 충전시간을 다시 0으로 초기화합니다.
  • 만들었던 슬롯들을 제거하고 초기화합니다.
  • 현재 상태의 충전률을 반환합니다.

InputSlot: AF의 입력을 받을 시 실행되는 함수입니다.
  • 상태의 nextSlot 정보와 입력 받은 Slot 정보가 같고, 다음 상태에 대한 정보가 있다면 다음 상태로 변경합니다. 이 과정에서 만약 다음 상태에 대한 실질적인 객체가 아직 생성되지 않았다면 객체를 만들고 이미 객체가 있다면 해당 객체를 사용합니다.

Damaged: 피격 당했을 때 발동되는 함수입니다.
  • 공격을 당할 시 공격자측의 최종대미지구조체를 받아서 상태의 defSlot정보를 읽어 방어가 성공했는지 아닌지 판별하여 반환합니다.
  • 방어가 실패했을 경우 공식에 따라 hpstamina를 변화시킨 후 상태를 변화시킵니다.

*대미지 계산 공식
비트맵월드는 staminahp가 연관되는 대미지 계산방식을 가지고 있습니다.

그리고 그를 위한 대미지 구조체가 필요합니다.




공격방향이 방어방향을 피해 공격에 성공했을 경우 총 3가지 형식의 대미지에 의해 피해가 결정됩니다.

피해량 = 순수 대미지 + (일반 대미지 스태미나/2) 해당 피해를 받은 후 스태미나대미지에 의해 스태미나가 감소하게 됩니다.

피해를 받은 후 stamina0일 경우 넉백 상태로 변하게 되고 hp0일 경우 죽게 됩니다.



ChangeState: 상태를 변경시킬 때 쓰이는 함수입니다. 이 함수 내에서 상태의 enterleave 함수가 구현되어 사용됩니다.

모든 상태의 변경은 이 함수를 통해서만 이루어집니다.


거의 대부분의 상태는 AFstate의 함수에 자신만의 기능을 추가시켜 사용합니다. 몇몇 특정 상태는 함수를 완전히 바꿀 수도 있지만 함수의 호출 목적은 변하지 않습니다.

다음엔 ActionFighterAFstate를 포함해서 어떻게 동작하는지 설명하겠습니다.

2016년 9월 1일 목요일

2)ActionFighter and imageDrawing


first of all, Let's see ActionFighter(AF), the most Important thing in BitmapWorld.

AFis blueprintClass heritaged by PaperCharacter.

AF do many thing, but first let's see How it draw Character.


-      CharacterFlipbook


first, let's see How it change characterFlipbook.

2Dcharacter can't move one model by anim, not like 3Dcharacter. in fact It can use like that, I don't like it. so BitmapWorld's AF have each Flipbook on each motion.




It's okay that drawing Image and making Flipbook. but how we can connect this with AF?

simply, we can set Flipbook of AF's Sprite.

Like This.

but we need to think about it deeply. currently we only have BIT, one character. but we can't make Game with only one Character. there are various characters that have each individual Image. and it will change in various situation.

Rather than making each flipbookSetter one by one, Making new component that work only for changing AF's Flipbook. and by this component's function, AF change it's flipbook by it's own flipbook variable.

we need something to that.


FlipbookMotionGuide








FlipbookMotionGuide is enum about all Motion that AF can have.
each AF have Flipbook matching on this motionEnum.

 















AFflipbookComponent



component to change AF's Flipbook.


it look like messy but by this AF can call it's own var and change flipbook. at least we don't need to make this messy thing over and over again.
eventually AF can make different character by changing it's motionFlipbook var.
surely we still need to draw each resource. :(

-      ActionMap

in this Screen, there are almost Images AF need to draw.

as you see, AF have round interface, ActionMap, surrounding it's character.

actionMap have 6 direction's slot and each slot have to show 4type of image.
and each slot image can overlap and show multiply.








now let's make AF draw slot.

slot drawing's programming is focused in AF. In fact CharacterFlipbookChange also in AF and I find about conponent and divide this on component. I think slot drawing also need to divide... but only think.



anyway, slot's drawing work very dynamically.
slot create new PaperSpriteComponent when it need, and draw slot and destroy again. by this, we can draw various slot limitlessly.



CreateSlot

AF's CreateSlot Function craete and save slot on each type's individual slotArray.

it read slotInfo as parameter and calculate how many PaperSpriteComponent need and create(ex. slotinfo = 123 then it make 3 slot) and attach new component to actionMap. by this, slot can draw on actionMap.


DrawSlot
DrawSlot use same slotInfo that used on creating and by this, match resource on right position.
nextSlot type need to draw chargeRate so it also read chargeRate and match resource.

ClearSlotSet
when slot need to be changed or disappear, each SlotsetData all deleted and clear. it clear all slot type togater.




with this, AF draw Character and actionMap.

next, let's see how AF's gameAction work.