Vue.js make script game (feat. this)

강정우·2023년 3월 29일
0

vue.js

목록 보기
7/72
post-thumbnail
post-custom-banner

Vue property에서의 this

...
    methods:{
        attackMonster(){
            const attackValue = getRandomValue(12, 5)
            this.monsterHealth -= attackValue
            this.attackPlayer()
        },
        attackPlayer(){
            const attackValue = getRandomValue(15, 8)
            this.playerHealth -= attackValue
        }
    }
...
  • 위 코드는 가장은 스크립트 게임을 만들어보는 과정이다. 코드를 보면 4번째 줄에 this.attckplayer를 확인할 수 있는데 이를 자세히 보면

  • this 키워드를 사용하면 data 프로퍼티도 액세스할 수 있고 Vue 인스턴스 구성 객체 내의 method도 액세스할 수 있다.

  • 작동 원리는 data 프로퍼티의 경우와 같다. method나 computed 프로퍼티의 경우도 마찬가지이다 모두 다 내부에서 관리되는 전역적 객체로 통합되기 때문이다.

  • 그렇기 때문에 methods 내에서 this 키워드를 사용해서 data 프로퍼티에 액세스하는 것과 같이 methods 내의 메서드도 액세스하고 호출할 수 있다.

Vue.createApp 내부와 외부의 차이

  • Vue.createApp({ 내부 }) 와 외부에 선언되는 차이점은 무엇일까?
  1. Vue 인스턴스 내부에서 액세스를 해야하는 경우

  2. Vue 인스턴스 값이 바뀌면 Vue가 인지해야하는 경우

예제 코드 (make script game)

index.html (template)

<div id="game">
    <section id="monster" class="container">
        <h2>Monster Health</h2>
        <div class="healthbar">
            <div class="healthbar__value" :style="monsterBarStyle"></div>
        </div>
    </section>
    <section id="player" class="container">
        <h2>Your Health</h2>
        <div class="healthbar">
            <div class="healthbar__value" :style="playerBarStyle"></div>
        </div>
    </section>

    <section class="container" v-if="winner">
        <h2>game over!</h2>
        <h3 v-if="winner === 'player'">you win!</h3>
        <h3 v-else-if="winner === 'monster'">you lost!</h3>
        <h3 v-else>draw!</h3>
        <button @click="startGame">start new game!</button>
    </section>

    <section id="controls" v-else>
        <button @click="attackMonster">ATTACK</button>
        <button :disabled="mayUseSpecialAttack" @click="specialAttackMonster">SPECIAL ATTACK</button>
        <button @click="healPlayer">HEAL</button>
        <button @click="surrender">SURRENDER</button>
    </section>
    <section id="log" class="container">
        <h2>Battle Log</h2>
        <ul>
            <li v-for="logMessage in logMessages">
                <span :class="{'log--player':logMessage.actionBy === 'player', 'log--monster': logMessage.actionBy === 'monster'}">
                  {{logMessage.actionBy === 'player' ? 'Player' : 'Monster'}}
                </span>
                <span v-if="logMessage.actionType === 'heal'">
                  heals <span class="log--heal">{{logMessage.actionValue}}</span>
                </span>
                <span v-else>
                  attacks <span class="log--damage">{{logMessage.actionValue}}</span>
                </span>
            </li>
        </ul>
    </section>
</div>

app.js

const getRandomValue = (max, min) => {
    return Math.floor(Math.random()*(max-min))+min
}

const app = Vue.createApp({
    data(){
        return{
            playerHealth : 100,
            monsterHealth : 100,
            currentRound:0,
            winner:null,
            logMessages : []
        }
    },
    computed:{
        monsterBarStyle(){
            if(this.monsterHealth <= 0) {
                return {width: 0}
            }
            return {width:this.monsterHealth+'%'}
        },
        playerBarStyle(){
            if(this.playerHealth <= 0){
                return {width: 0}
            }
            return {width: this.playerHealth+'%'}
        },
        mayUseSpecialAttack(){
            return this.currentRound % 3 !== 0
        }
    },
    watch:{
        playerHealth(value){
            if(value<=0 && this.monsterHealth<=0){
                this.winner = "draw"
            } else if (value <= 0){
                this.winner = "monster"
            }
        },
        monsterHealth(value){
            if(value<=0 && this.playerHealth<=0){
                this.winner = "draw"
            } else if (value <= 0){
                this.winner = "player"
            }
        }

    },
    methods:{
        attackMonster(){
            this.currentRound++
            const attackValue = getRandomValue(12, 5)
            this.monsterHealth -= attackValue
            this.addLogMessage("player","attack",attackValue)
            this.attackPlayer()
        },
        attackPlayer(){
            const attackValue = getRandomValue(15, 8)
            this.addLogMessage("monster","attack",attackValue)
            this.playerHealth -= attackValue
        },
        specialAttackMonster(){
            this.currentRound++
            const attackValue = getRandomValue(10, 25)
            this.monsterHealth -= attackValue
            this.addLogMessage("player","special-attack",attackValue)
            this.attackPlayer()
        },
        healPlayer(){
            this.currentRound++
            const healValue = getRandomValue(8,20)
            if(this.playerHealth+healValue>100){
                this.playerHealth = 100
            } else {
                this.playerHealth += healValue
            }
            this.addLogMessage("player","heal",healValue)
            this.attackPlayer()
        },
        startGame(){
            this.playerHealth = 100,
            this.monsterHealth = 100,
            this.currentRound = 0,
            this.winner = null,
            this.logMessages = []
        },
        surrender(){
            // this.addLogMessage("player","surrender")
            this.winner="monster"
        },
        addLogMessage(who, what, value){
            this.logMessages.unshift({
                actionBy : who,
                actionType : what,
                actionValue : value
            })
        }
    }
})
app.mount("#game")
  • data : state 느낌
  • computed : 주로 styling 할 때
  • watch : 동작의 결과로 state가 로직에 들어가야할 때
  • mothods : 동작들을 명시

unshift

  • array의 메서드중 하나로 push배열 맨 마지막 , unshift배열 맨 처음에 추가하는 것이다.

  • 참고로 shift() 메서드는 제일 앞에 요소를 "pop"해가는 것이다.

profile
智(지)! 德(덕)! 體(체)!
post-custom-banner

0개의 댓글