← Back to all tutorials

Simple Punchbag Game

Build a fun punchbag game to practice Vue fundamentals — combining data, methods, computed properties, events, and conditionals.

Simple Punchbag Game

Let us put everything we have learned so far into practice by building a Simple Punchbag Game. A punchbag has a health bar that decreases when you punch it, and the game ends when health reaches zero.

The Game Plan

  • A punchbag with a health bar (starts at 100)
  • A "Punch" button that reduces health by a random amount
  • The health bar shrinks and changes color as health decreases
  • A "Game Over" message and "Restart" button when health hits zero

The HTML Template

<div id="app">
    <h1>Punchbag Game</h1>

    <div id="bag" :class="{ burst: ended }"></div>

    <div id="health">
        <div :style="{ width: health + '%' }" :class="healthClass"></div>
    </div>

    <div id="controls">
        <button @click="punch" v-show="!ended">Punch</button>
        <button @click="restart" v-show="ended">Restart</button>
    </div>
</div>

The Vue Instance

new Vue({
    el: '#app',
    data: {
        health: 100,
        ended: false
    },
    computed: {
        healthClass() {
            if (this.health <= 20) return 'danger';
            if (this.health <= 50) return 'warning';
            return 'healthy';
        }
    },
    methods: {
        punch() {
            this.health -= Math.floor(Math.random() * 12) + 3;
            if (this.health <= 0) {
                this.health = 0;
                this.ended = true;
            }
        },
        restart() {
            this.health = 100;
            this.ended = false;
        }
    }
});

The CSS

#bag { width: 200px; height: 300px; margin: 20px auto; background: #888; border-radius: 100px; transition: 0.5s; }
#bag.burst { background: #c00; transform: scale(1.1); }
#health { width: 300px; height: 20px; margin: 10px auto; background: #ddd; border-radius: 10px; overflow: hidden; }
#health div { height: 100%; transition: width 0.3s; }
.healthy { background: #4caf50; }
.warning { background: #ff9800; }
.danger { background: #f44336; }

Concepts Used

ConceptWhere Used
Datahealth and ended properties
Methodspunch() and restart()
ComputedhealthClass for dynamic CSS
Events@click on buttons
Dynamic class:class on bag and health bar
Dynamic style:style for health bar width
Conditionalsv-show to toggle buttons

Key Takeaways

  • This game combines all Vue fundamentals: data, methods, computed, events, and conditionals
  • Dynamic :style and :class create visual feedback based on data
  • Computed properties keep template logic clean — healthClass calculates the CSS class