앞선 스프라이트 시트 재생에 이어서 방향키로 원하는 프레임을 표시하는 방법을 알아보겠습니다.
<template>
<p>현재 입력 : {{ currentInput }}</p>
<div :style="spriteStyle"></div>
</template>
<script>
export default {
props: {
frameWidth: {
type: Number,
required: true
},
frameHeight: {
type: Number,
required: true
},
// 그냥 재생이 아닌 키 입력에 의한 동작으로 totalFrames 삭제
animationSpeed: {
type: Number,
default: 100
},
spriteSheet: {
type: String,
required: true
},
scale: {
type: Number,
default: 1
}
},
data() {
return {
currentFrame: 0,
currentInput: '', // 현재 입력된 키를 나타내는 문자열
direction: 2, // 캐릭터의 현재 방향 (0: 위, 1: 오른쪽, 2: 아래, 3: 왼쪽)
isMoving: false, // 캐릭터가 움직이고 있는지 여부 (키 입력이 지속되고 있는지)
frames: {
// 캐릭터의 애니메이션 프레임을 정의한 객체
idle: [
[12, 13, 14, 15], // 위쪽 idle 애니메이션 프레임 번호들
[8, 9, 10, 11], // 오른쪽 idle 애니메이션 프레임 번호들
[0, 1, 2, 3], // 아래쪽 idle 애니메이션 프레임 번호들
[4, 5, 6, 7] // 왼쪽 idle 애니메이션 프레임 번호들
],
move: [
[34, 35, 36, 37, 38, 39], // 위쪽 이동 애니메이션 프레임 번호들
[28, 29, 30, 31, 32, 33], // 오른쪽 이동 애니메이션 프레임 번호들
[16, 17, 18, 19, 20, 21], // 아래쪽 이동 애니메이션 프레임 번호들
[22, 23, 24, 25, 26, 27] // 왼쪽 이동 애니메이션 프레임 번호들
],
die: [40, 41, 42, 43] // 캐릭터가 사망할 때의 애니메이션 프레임 번호들 (사용 x)
}
}
},
computed: {
spriteStyle() {
return {
width: `${this.frameWidth}px`,
height: `${this.frameHeight}px`,
backgroundImage: `url(${this.spriteSheet})`,
backgroundPosition: `-${this.getCurrentAnimationFrame() * this.frameWidth}px 0px`, // 현재 프레임에 맞게 배경 위치 조정
backgroundRepeat: 'no-repeat',
transform: `scale(${this.scale})`,
transformOrigin: 'top left'
}
}
},
mounted() {
this.startAnimation()
window.addEventListener('keydown', this.handleKeydown) // 키가 눌릴 때 이벤트 처리기 추가
window.addEventListener('keyup', this.handleKeyup) // 키에서 손을 뗄 때 이벤트 처리기 추가
},
beforeUnmount() {
this.stopAnimation()
window.removeEventListener('keydown', this.handleKeydown) // 키다운 이벤트 리스너 제거
window.removeEventListener('keyup', this.handleKeyup) // 키업 이벤트 리스너 제거
},
methods: {
startAnimation() {
this.animationInterval = setInterval(() => {
if (this.isMoving) {
// 캐릭터가 움직이고 있을 경우
this.currentFrame = (this.currentFrame + 1) % this.frames.move[this.direction].length
} else {
// 캐릭터가 움직이지 않고 있을 경우
this.currentFrame = (this.currentFrame + 1) % this.frames.idle[this.direction].length
}
}, this.animationSpeed)
},
stopAnimation() {
clearInterval(this.animationInterval)
},
getCurrentAnimationFrame() {
// 현재 방향과 상태(움직임 여부)에 따라 적절한 애니메이션 프레임을 반환
if (this.isMoving) {
return this.frames.move[this.direction][this.currentFrame]
} else {
return this.frames.idle[this.direction][this.currentFrame]
}
},
handleKeydown(event) {
// 사용자가 특정 방향키를 눌렀을 때 처리
switch (event.key) {
case 'ArrowUp':
this.direction = 0 // 위쪽 방향으로 설정
this.currentInput = '↑' // 현재 입력 표시를 위쪽 화살표로 설정
break
case 'ArrowRight':
this.direction = 1 // 오른쪽 방향으로 설정
this.currentInput = '→' // 현재 입력 표시를 오른쪽 화살표로 설정
break
case 'ArrowDown':
this.direction = 2 // 아래쪽 방향으로 설정
this.currentInput = '↓' // 현재 입력 표시를 아래쪽 화살표로 설정
break
case 'ArrowLeft':
this.direction = 3 // 왼쪽 방향으로 설정
this.currentInput = '←' // 현재 입력 표시를 왼쪽 화살표로 설정
break
default:
return // 지정된 키가 아니면 아무런 동작도 하지 않음
}
this.isMoving = true // 방향키가 눌리면 움직임 상태로 설정
},
handleKeyup() {
// 사용자가 방향키에서 손을 뗐을 때 처리
this.isMoving = false // 움직임 상태 해제
this.currentInput = '' // 현재 입력 표시 초기화
}
}
}
</script>
<style scoped>
div {
overflow: hidden;
}
</style>
true
이면 캐릭터가 움직이고 있는 상태를 나타내며, false
이면 움직임이 없는 상태를 나타냅니다.<template>
<div id="app">
<SpriteAnimator
:frameWidth="24"
:frameHeight="24"
:animationSpeed="100"
:spriteSheet="spriteSheetPath"
:scale="2"
/>
</div>
</template>
<script>
import SpriteAnimator from './components/SpriteAnimator.vue'
import spriteSheetPath from '@/assets/Girl-Sheet.png'
export default {
name: 'App',
components: {
SpriteAnimator
},
data() {
return {
spriteSheetPath
}
}
}
</script>
<style>
#app {
/* text-align: center; */
}
</style>