Skip to content

Instantly share code, notes, and snippets.

@danielsdesk
Created October 31, 2020 20:45
Show Gist options
  • Save danielsdesk/0173b16c69bf63adc1e073e6faa7373f to your computer and use it in GitHub Desktop.
Save danielsdesk/0173b16c69bf63adc1e073e6faa7373f to your computer and use it in GitHub Desktop.
Generated by XState Viz: https://xstate.js.org/viz
// 충돌시 데미지
const HIT_DAMAGE = 30;
// 충돌 후 무적 시간
const INVINCIBLE_TIME = 2000;
// 시간당 데미지
const TICK_DAMAGE = 5;
const gameMachine = Machine({
id: 'game',
type: 'parallel',
context: {
jumpEnabled: true,
health: 100,
life: 'alive',
},
states: {
jumpButton: {
id: 'jumpButton',
initial: 'idle',
states: {
idle: {
on: {
JUMP_BUTTON_DOWN: {
target: 'pressed',
actions:'disableJump',
},
},
},
pressed: {
on: {
JUMP_BUTTON_UP: {
target: 'idle',
actions: 'enableJump',
},
},
},
},
},
slideButton: {
id: 'slideButton',
initial: 'idle',
states: {
idle: {
on: {
SLIDE_BUTTON_DOWN: 'pressed',
},
},
pressed: {
on: {
SLIDE_BUTTON_UP: 'idle',
},
},
},
},
life: {
id: 'life',
initial: 'alive',
states: {
alive: {
entry: assign({
life: 'alive',
}),
on: {
HIT: [
{
target: 'invincible',
cond: 'enoughHealthForHit',
},
{
target: 'dead',
},
],
TICK: [
{
target: 'alive',
cond: 'enoughHealthForTick',
actions: 'getTickDamage',
},
{
target: 'retired',
},
],
},
invoke: {
src: _ctx => cb => {
const interval = setInterval(() => {
cb('TICK');
}, 1000);
return () => {
clearInterval(interval);
};
},
},
},
invincible: {
onEntry: [
assign({
life: 'invincible',
}),
'getHitDamage',
],
after: {
[INVINCIBLE_TIME]: 'alive',
},
},
retired: {
type: 'final',
entry: [
assign({
life: 'retired',
}),
send('RETIRE'),
'drainHealth',
],
},
dead: {
type: 'final',
entry: [
assign({
life: 'dead',
}),
send('DEAD'),
'drainHealth',
],
},
},
on: {
// 즉사 지원 ^^7
DIE: {
target: '.dead',
cond: 'notRetired',
},
},
},
cookie: {
id: 'cookie',
initial: 'running',
on: {
DIE: {
target: '.dead',
cond: 'notRetired',
},
// 쿠키런에선 점프 중에 부딪혀 죽긴 해도 점프 중에 지쳐 죽진 않기 때문에 더 세부적인 컨트롤을 위해 하위 노드들에 직접 연결
// RETIRE: '.retired',
},
states: {
running: {
on: {
JUMP_BUTTON_DOWN: {
target: 'jumping',
cond: 'jumpEnabled',
},
SLIDE_BUTTON_DOWN: 'sliding',
HIT: {
target: 'hitted',
cond: 'notInvincible',
},
RETIRE: 'retired',
},
},
jumping: {
initial: 'first',
states: {
first: {
on: {
JUMP_BUTTON_DOWN: {
target: 'second',
cond: 'jumpEnabled',
},
}
},
second: {
type: 'final',
},
},
on: {
HIT: {
target: 'hitted',
cond: 'notInvincible',
},
// 착지 시 아주 잠깐 쭈그리는 모션이 존재함
LAND: 'landed',
},
},
hitted: {
after: {
100: [
{
target: 'dead',
cond: 'dead',
},
{
target: 'running',
},
],
},
},
landed: {
after: {
100: [
{
target: 'running',
cond: 'enoughHealthForTick',
},
{
target: 'retired',
},
],
},
},
sliding: {
on: {
SLIDE_BUTTON_UP: 'running',
JUMP_BUTTON_DOWN: {
target: 'jumping',
cond: 'jumpEnabled',
},
RETIRE: 'retired',
},
},
retired: {
type: 'final',
},
dead: {
type: 'final',
},
},
},
},
}, {
actions: {
getHitDamage: assign({
health: ctx => ctx.health - HIT_DAMAGE,
}),
getTickDamage: assign({
health: ctx => ctx.health - TICK_DAMAGE,
}),
getInvincibility: assign({
invincible: true,
}),
lostInvincibility: assign({
invincible: false,
}),
drainHealth: assign({
health: 0,
}),
enableJump: assign({
jumpEnabled: true,
}),
disableJump: assign({
jumpEnabled: false,
}),
},
guards: {
jumpEnabled: (ctx) => ctx.jumpEnabled,
enoughHealthForHit: (ctx) => ctx.health - HIT_DAMAGE > 0,
enoughHealthForTick: (ctx) => ctx.health - TICK_DAMAGE > 0,
alive: (ctx) => ctx.life === 'alive',
notAlive: (ctx) => ctx.life !== 'alive',
retired: (ctx) => ctx.life === 'retired',
notRetired: (ctx) => ctx.life !== 'retired',
invincible: (ctx) => ctx.life === 'invincible',
notInvincible: (ctx) => ctx.life !== 'invincible',
dead: (ctx) => ctx.life === 'dead',
notDead: (ctx) => ctx.life === 'notDead',
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment