Skip to content

Instantly share code, notes, and snippets.

@cometkim
Last active November 7, 2020 12:16
Show Gist options
  • Save cometkim/f33cf8cdb61bada27cb2df72bfa295ba to your computer and use it in GitHub Desktop.
Save cometkim/f33cf8cdb61bada27cb2df72bfa295ba 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,
sliding: false,
health: 100,
flipCount: 0,
life: 'alive',
},
states: {
jumpButton: {
id: 'jumpButton',
initial: 'idle',
states: {
idle: {
entry: assign({ jumpEnabled: true }),
on: {
JUMP_BUTTON_DOWN: 'pressed',
},
},
pressed: {
entry: assign({ jumpEnabled: false }),
on: {
JUMP_BUTTON_UP: 'idle',
},
},
},
},
slideButton: {
id: 'slideButton',
initial: 'idle',
states: {
idle: {
entry: assign({ sliding: false }),
on: {
SLIDE_BUTTON_DOWN: 'pressed',
},
},
pressed: {
entry: assign({ sliding: true }),
on: {
SLIDE_BUTTON_UP: 'idle',
},
},
},
},
life: {
id: 'life',
initial: 'alive',
states: {
alive: {
entry: assign({ life: 'alive' }),
on: {
HIT: [
{
target: 'invincible',
cond: 'enoughHealthForHit',
actions: 'getHitDamage',
},
{
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: {
entry: assign({ life: 'invincible' }),
after: {
[INVINCIBLE_TIME]: 'alive',
},
},
retired: {
type: 'final',
entry: [
assign({ life: 'retired' }),
send('RETIRED'),
'drainHealth',
],
},
dead: {
type: 'final',
entry: [
assign({ life: 'dead' }),
send('DEAD'),
'drainHealth',
],
},
},
},
motion: {
id: 'motion',
initial: 'running',
on: {
DEAD: {
target: '.dead',
cond: 'dead',
},
RETIRED: {
target: '.retired',
cond: 'retired',
},
HIT: {
target: '.hitted',
cond: 'alive',
},
},
states: {
running: {
on: {
JUMP_BUTTON_DOWN: {
target: 'jumping',
cond: 'jumpEnabled',
},
SLIDE_BUTTON_DOWN: 'sliding',
},
},
jumping: {
initial: 'first',
states: {
first: {
on: {
JUMP_BUTTON_DOWN: {
target: 'second',
cond: 'jumpEnabled',
},
},
},
second: {
initial: 'up',
entry: 'resetFlipCount',
exit: 'resetFlipCount',
on: {
FLIP: [
{
target: '.flipping',
cond: 'canFlip',
actions: 'flip',
},
{
target: '.down',
},
],
},
states: {
up: {
},
flipping: {
},
down: {
type: 'final',
},
},
},
},
on: {
// 착지 시 아주 잠깐 쭈그리는 모션이 존재함
LAND: 'landed',
},
},
hitted: {
after: {
100: [
{
target: 'sliding',
cond: 'sliding',
},
{
target: 'running',
},
],
},
},
landed: {
after: {
100: [
{
target: 'sliding',
cond: 'sliding',
},
{
target: 'running',
},
],
},
},
sliding: {
on: {
SLIDE_BUTTON_UP: 'running',
JUMP_BUTTON_DOWN: {
target: 'jumping',
cond: 'jumpEnabled',
},
},
},
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,
}),
flip: assign({
flipCount: ctx => ctx.flipCount + 1,
}),
resetFlipCount: assign({
flipCount: 0,
}),
},
guards: {
jumpEnabled: (ctx) => ctx.jumpEnabled,
sliding: (ctx) => ctx.sliding,
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 !== 'dead',
canFlip: (ctx) => ctx.flipCount < 2,
},
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment