A method of binding data from an array of objects in Vue using v-bind

I am tasked with rendering a board that is 20x15 and placing creatures on it. The information on where to place the creatures is stored in this.creaturesOnBoard within the gameEngine. My plan is to take X and y coordinates, then check if a creature exists on that tile. However, I am unsure how to implement the logic for checking each tile and assigning values from another object.

gameBoard.vue

<template>
  <div class="container">
    <div class="wrapper">
      <h1>Player 1 vs Player 2</h1>
    </div>
    <div class="wrapper">
      <div class="board">
        <div v-for="x in gameEngine.board.boardX" :key="x">
          <div v-for="y in gameEngine.board.boardY" :key="y">
//Something like this 
            <div 
             v-if='creatureExistsAtPointFromCreatureOnBoardObject'
             :name='creature.name'
             :x='creature.x'
             :y='creature.y'
            ></div>
            <div
              v-else //<=if creature is not on this point them render empty field
              class="board-creature field"
              :x="`${x}`"
              :y="`${y}`"
              @click="creatureAction(x, y, $event)"
            >
              {{ x }},{{ y }}
            </div>
          </div>
        </div>
      </div>
    </div>

    <div class="wrapper">
      <div>
        <button>Spell Book</button>
        <button @click="passCreature()">Pass</button>
        <button>Defend</button>
        <button>Run</button>
      </div>
    </div>
  </div>
</template>
<script>
import Creature from "../js/creature.js";
import GameEngine from "../js/gameEngine.js";
import Point from "../js/point.js";
import Range from "../js/range.js";
export default {
  data() {
    return {
      gameEngine: "",
      myCreature: [],
      ennemyCreature: [],
    };
  },
  created() {
    this.createGameEngineObjectAndBoard();
  },
  methods: {
    // prettier-ignore
    createGameEngineObjectAndBoard() {

        let newCreature1 = new Creature("Skeleton", 5, 4, 6, 4, new Range(1, 3));
        let newCreature2 = new Creature("WalkingDead", 5, 5, 15, 3, new Range(2, 3));
        let newCreature3 = new Creature("Wight", 7, 7, 18, 5, new Range(3, 5));
        let newCreature4 = new Creature("Vampire", 10, 9, 30, 6, new Range(5, 8));
        let newCreature5 = new Creature("Lich", 13, 10, 30, 6, new Range(11, 13));
        let newCreature6 = new Creature("BlackKnight", 16, 16, 120, 7, new Range(15, 30));
        let newCreature7 = new Creature("BoneDragon", 17, 15, 150, 9, new Range(25, 30));

        let newCreature8 = new Creature("SkeletonWarrior", 6, 6, 6, 5, new Range(1, 3));
        let newCreature9 = new Creature("Zombie", 5, 5, 20, 4, new Range(2, 3));
        let newCreature10 = new Creature("Wraith", 7, 7, 18, 7, new Range(3, 5));
        let newCreature11 = new Creature("VampireLord", 10, 10, 40, 9, new Range(5, 8));
        let newCreature12 = new Creature("PowerLich", 13, 10, 40, 7, new Range(11, 15));
        let newCreature13 = new Creature("DreadKnight", 18, 18, 120, 9, new Range(15, 30));
        let newCreature14 = new Creature("GhostDragon", 19, 17, 200, 14, new Range(25, 50));

      this.myCreature.push(newCreature1, newCreature2, newCreature3,newCreature4,newCreature5,newCreature6,newCreature7);

      this.ennemyCreature.push(newCreature8,newCreature9,newCreature10,newCreature11,newCreature12,newCreature13,newCreature14);

      this.gameEngine = new GameEngine(this.myCreature, this.ennemyCreature);
    },

gameEngine.js

import Board from './board.js';
import CreatureTurnQueue from './creatureTurnQueue.js';
import Point from './point';

export default class GameEngine {
    constructor(_myCreatures, _EnnemyCreatures) {
        this.board = new Board();
        this.queue = new CreatureTurnQueue()
        this.creaturesOnBoard = [];
        this.i = 0;
        this.putCreatureToBoard(_myCreatures, _EnnemyCreatures)
    }
    putCreatureToBoard(_myCreatures, _EnnemyCreatures) {
        this.putCreaturesFromeOneSideToBoard(_myCreatures, false)
        this.putCreaturesFromeOneSideToBoard(_EnnemyCreatures, true)

        this.queue.initQueue(this.board.map)
    }
    putCreaturesFromeOneSideToBoard(_creatures, _site) {
        _creatures.forEach(((item, index) => {
            let newPoint = new Point(_site ? 20 : 1, index + 1)
            this.board.add(newPoint, item)
            this.creaturesOnBoard.push({
                id: this.i,
                creature: item,
                player: _site ? 'ennemy' : 'player',
                x: _site ? 20 : 1,
                y: index + 1,
            });
            this.i++;
        }))
    }
    canMove(_x, _y) {
        return this.board.canMove(this.queue.getActiveCreature(), _x, _y);
    }
    canAttack(_attacker, _defender) {
        return this.board.canAttack(_attacker, _defender)
    }
    move(_targetPoint) {
        this.board.moveByCreature(this.queue.getActiveCreature(), _targetPoint)
        this.creaturesOnBoard.forEach(item => {
            if (item.creature === this.queue.getActiveCreature()) {
                item.x = _targetPoint.x
                item.y = _targetPoint.y
            }
        })
    }
    pass() {
        this.queue.next(this.board.map);
        this.board.pass(this.queue.getActiveCreature());
    }
    attack(_point) {
        this.queue.getActiveCreature().attack(this.board.getVal(_point))
    }
}

board.js

import Point from './point.js';
export default class Board {
    constructor() {
        this.map = new Map();
        this.keyArray = [];
        this.boardX = 20;
        this.boardY = 15;
    }
    add(_point, _creature) {
        this.isThatPointOnMap(_point.x, _point.y)
        this.isThisTileTaken(_point)

        this.map.set(_point, _creature);
        this.keyArray.push([_point.getX(), _point.getY()]);
        if (this.equals(this.map.get(_point), _creature.stats)) {
            throw "Exception: => Klucz nie jest równy tej wartosci która powinna byc wpisana";
        }
    }
    getVal(_point) {
        return this.map.get(_point);
    }
    getPoint(_creature) {
        for (const [key, val] of this.map.entries()) {
            if (this.equals(val, _creature)) {
                return key;
            }
        }
    }
    moveByCreature(_creature, _newPoint) {
        this.move(this.getPoint(_creature), _newPoint);
    }
    move(_point, _newPoint) {
        this.isThatPointOnMap(_newPoint.x, _newPoint.y)
        this.isThisTileTaken(_newPoint)

        let creature = this.map.get(_point);
        this.map.delete(_point);
        this.map.set(_newPoint, creature);
    }
    pass(_creature) {
        for (const [key, val] of this.map.entries()) {
            if (val === _creature) {
                this.map.delete(key);
                this.map.set(key, _creature);
                break;
            }
        }
    }
    canMove(_creature, _x, _y) {
        this.isThatPointOnMap(_x, _y)

        let pointToMoveCreature = new Point(_x, _y);
        let currentCreaturePoint = this.getPoint(_creature)

        let distanse = currentCreaturePoint.distanse(pointToMoveCreature)

        return distanse <= _creature.getMoveRange() && !this.isThisTileTaken(pointToMoveCreature);
    }
    canAttack(_attacker, _defender) {
        this.isThatPointOnMap(this.getPoint(_defender))

        let attackerPoint = this.getPoint(_attacker)
        let defenderPoint = this.getPoint(_defender)

        let distanse = attackerPoint.distanse(defenderPoint)

        return parseInt(distanse) <= 1;
    }
    reduseMovment(_creature, _x, _y) {
        this.isThatPointOnMap(_x, _y)
        let pointToMoveCreature = new Point(_x, _y);
        let currentCreaturePoint = this.getPoint(_creature)

        let distanse = currentCreaturePoint.distanse(pointToMoveCreature)

        _creature.stats.moveRange -= distanse;

    }
    isThatPointOnMap(_x, _y) {
        if (_x > this.boardX || _y > this.boardY) {
            throw "Exception: => Creature nie zostala ruszona, wskazaany pkt jest poza mapa";
        }
    }
    isThisTileTaken(_point) {
        for (const [key] of this.map.entries()) {
            if (this.equals(key, _point)) {
                // throw "Exception: => To pole jest zajete, nie mozesz tam ruszyc jednostki";
                return true;
            }
        }
        return false
    }
    equals(val, toAssert) {
        if (JSON.stringify(val) === JSON.stringify(toAssert)) {
            return true;
        } else {
            return false;
        }
    }
}

creature.js

import CreatureStatistics from "./creatureStatistics.js";
import DamageCalculator from './damageCalculator.js';
import Range from './range.js';
export default class Creature {
    constructor(_name, _attack, _armor, _maxHp, _moveRange, _damage) {
        this.stats = this.createCreature(_name, _attack, _armor, _maxHp, _moveRange, _damage);
        this.stats.currentHp = this.stats.maxHp;
        this.stats.wasCounterAttack = false;
        this.damageCalculator = new DamageCalculator();
    }
    createCreature(_name, _attack, _armor, _maxHp, _moveRange, _damage) {
        return new CreatureStatistics(
            _name || "Smok",
            _attack || 1,
            _armor || 1,
            _maxHp || 100,
            _moveRange || 5,
            _damage || new Range(1, 5)
        );
    }
    setDefaultStats() {
        this.stats.currentHp = this.getCurrentHp() != undefined ? this.getCurrentHp() : this.getMaxHp();
    }
    attack(_defender) {
        _defender.setDefaultStats();
        this.setDefaultStats();

        if (_defender.isAlive()) {
            _defender.stats.currentHp = _defender.getCurrentHp() - this.damageCalculator.calculate(this, _defender)
            if (_defender.isAlive() && !_defender.stats.wasCounterAttack) {
                _defender.stats.wasCounterAttack = true;
                this.stats.currentHp = _defender.getCurrentHp() - this.damageCalculator.calculate(_defender, this)
            }
        }
    }
    isAlive() {
        if (this.stats.currentHp > 0) {
            return true;
        }
    }
    resetCounterAttack() {
        this.stats.wasCounterAttack = false;
    }
    canCounterAttack() {
        return !this.stats.wasCounterAttack
    }
    getName() {
        return this.stats.name;
    }
    getAttack() {
        return this.stats.attack;
    }
    getArmor() {
        return this.stats.armor;
    }
    getMaxHp() {
        return this.stats.maxHp;
    }
    getCurrentHp() {
        return this.stats.currentHp;
    }
    getMoveRange() {
        return this.stats.moveRange;
    }
    getMaxRange() {
        return this.stats.maxRange;
    }
    getDamage() {
        return this.stats.damage;
    }
}


point.js

export default class Point {
    constructor(_x, _y) {
        this.x = _x;
        this.y = _y;
    }
    getX() {
        return this.x;
    }
    getY() {
        return this.y;
    }
    distanse(_point) {
        let x = Math.abs(this.x - _point.x)
        let y = Math.abs(this.y - _point.y)

        return Math.sqrt(x * x + y * y);
    }
}

Answer №1

Assuming that this.creaturesOnBoardObject is an array consisting of objects with all creatures, you may want to consider updating the following line:

v-if='creature with this points is in creatureOnBoardObject'

To:

v-if="hasCreature(x, y)"

The method hasCreature will be utilized, utilizing a method like some:

hasCreature(x, y) {
  return this.creaturesOnBoardObject.some(creature => creature.x === x && creature.y === y);
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How to handle multiple radio inputs and determine the checked value in Vue?

Currently, I am in the process of learning Vue.js and developing a basic poll generator. However, I have encountered an issue with radio inputs. In this application, each question can be of two types - 'select' or 'range.' 'Select ...

Utilizing Node.js with Express and Swig to seamlessly pass a local JSON file to a template

I am new to working with nodes, and I have successfully managed to integrate Express/swig and display them on the screen. However, when I include my d3 code (which functions independently), I encounter an error in the console: Uncaught TypeError: Cannot re ...

Discover the key to optimizing your JavaScript development workflow by automating project structures and eliminating the need to start from scratch

I was looking for a way to streamline the process of setting up project structures for my projects so that I could utilize ALE linting and fixing without any hassle. After trying out one method, I'm confident that there must be a more efficient soluti ...

Creating a dependent picklist feature using node.js and express

I am currently delving into the world of node.js and express. In my node.js application, I am utilizing express along with express-handlebars as the templating framework. My goal is to incorporate a dependent picklist that dynamically renders based on the ...

Exploring the concept of jQuery handler functions

Within my code, I have the following: <script type="text/javascript"> $(document).ready(function (e) { $('#EventCreate').click(function (e) { location.href = '@Url.Action("Create", "AEvents")'; }); ...

The middleware code remains dormant and is left untouched

I am encountering an issue with this code that is supposed to create a folder if it doesn't already exist. When I debug and set a breakpoint on fs.mkdir, the code does not enter into it. Do you have any idea what could be causing this problem? ... ap ...

Applying CSS rules from an array to elements by looping through

I'm looking for a way to allow users to input CSS styles and have those styles applied to the last selected element, which is determined by the "rangeselector" variable. Currently, the code selects the correct element, but only the first CSS rule is b ...

Developing a TypeScript library through modular class implementation

I have developed a Web API and now I want to streamline my code by creating a library that can be reused in any new project I create that interacts with this API. My goal is to organize my code efficiently, so I plan to have separate classes for each endp ...

Exploring the use of Angular with tables: applying classes dynamically using ngClass and repeating items using

My table is generated from a Web Service JSON, each row has a button to mark it for deletion. When you click the button, a JS alert displays the ID of the row element, and I also need to add the 'danger' bootstrap class to the row. Now, I can cap ...

Steps to activate the image viewer for each individual looping image:

I'm struggling with my JavaScript code that fetches images and displays them in a modal view when clicked. The issue I'm facing is that the image view only works for the second and other images, but not for the first one. I know there are issues ...

JavaScript validation failing to validate number ranges for 4-digit numbers

Currently, I am facing an issue with validating numbers entered between two text boxes to ensure that the first number is not greater than the second number. The validation process seems to work fine for three-digit numbers (e.g., 800 - 900), but it fails ...

Learn how to properly register the order of checkboxes in AngularJS

I have a unique requirement for my webapp where I need to display the order in which checkboxes are checked. I came up with the following code to achieve this functionality: $scope.updateNumbers = function(id, checked, inputs) { if (checked === true) ...

Guide to making a slider menu using html, css, and javascript

Just dipping my toes into the world of web development. I'm intrigued by the idea of creating a "slider menu" where users can view and select options by clicking on next or previous buttons (see example image below). While I've got some basic HTM ...

What could be causing the vue-property-decorator @Emit to malfunction in my Vue TypeScript file?

I am currently working with Typescript and Vuejs, where I have a child component called child.component.tsx import Vue from 'vue'; import Component from 'vue-class-component'; import { Emit } from 'vue-property-decorator'; ...

What is the best way to retrieve child elements from JSON within an Angular JS controller?

I'm having trouble understanding how to ensure the resource call completes before assigning the data.properties to $scope in my controller. My confusion lies here: The resource call returns the following response: [ { "PreAlertInventory": "5.00 ...

Why isn't my lightbox able to read this specific property?

A gallery was created using both lightgallery and cycle2. Cycle is a carousel plugin while lightgallery is a lightbox gallery. Clicking on an image in the carousel opens it in the lightbox. Everything worked perfectly until a category in the carousel was ...

What causes the values to constantly change whenever I insert an element into the array?

When I add an element, it automatically replaces all the others. This issue only occurs when I insert the entire object; if I insert a typical element such as an integer or a string, it works without any problems. <body> <div id="app&quo ...

Using socket.io-client in Angular 4: A Step-by-Step Guide

I am attempting to establish a connection between my server side, which is PHP Laravel with Echo WebSocket, and Angular 4. I have attempted to use both ng2-socket-io via npm and laravel-echo via npm, but unfortunately neither were successful. If anyone h ...

Is it possible for a Vuex module to observe or monitor another Vuex module?

Is it possible for Vuex modules to monitor the state of other modules and accordingly trigger actions? Consider this scenario: store.js import time from './store/time' ; import position from './store/position' ; const store = new Vu ...

To iterate through a multi-dimensional array

I am facing an issue with fetching data within an array in the code below var str = "Service1|USER_ID, Service1|PASSWORD" var str_array = str.split(','); console.log(str_array) for(var i = 0; i < str_array.length; i++) { str_array[i] = st ...