Evénements et méthodes
Exercice 1, 2 & 3 -
4°/ shop.html
4°/ Archive globale
Exercice 1, 2 & 3 -
1°/ model.js
- Il suffit de suivre les indications du TP, en remplaçant la méthode buy().
- contenu de model.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
function getRandomInt(max) { return Math.floor(Math.random() * Math.floor(max)); } var itemCats = [ 'helmet', 'crown', 'armor', 'clothes', 'weapon', 'lighter', 'purse', 'potion', 'spell', 'food']; var itemLimits = [ {slot:'head', limit:1, types: [ 'helmet' , 'crown' ]}, {slot:'body', limit:1, types: [ 'armor', 'clothes' ]}, {slot:'hands', limit:2, types: [ 'weapon', 'lighter']}, {slot:'belt', limit:3, types: [ 'weapon', 'purse']}, {slot:'bag', limit:10, types: [ 'helmet', 'crown', 'clothes', 'lighter', 'potion', 'spell', 'food', 'purse' ]} ]; class Item { constructor(id, name, type, price, effect) { this.id = id; this.name = name; //let idx = itemCats.findIndex(e => e == type); //var testType = function(el) {return el == type}; function testType(el) { return el == type;} let idx = itemCats.findIndex(testType); if (idx != -1) { this.type = type; } else { this.type = ''; } if (price>=0) { this.price = price; } else { this.price = 0; } this.effect = effect; } } var items = [ new Item(0, 'conic helmet', 'helmet', 200, 'A+10'), new Item(1, 'great crown of apologia', 'crown', 200, 'A+20'), new Item(2, 'band of joy', 'crown', 100, 'L+10'), new Item(3, 'leather armor', 'armor', 100, 'A+10'), new Item(4, 'broigne', 'armor', 200, 'A+20'), new Item(5, 'hauberk', 'armor', 500, 'A+40'), new Item(6, 'plate armor', 'armor', 1000, 'A+60'), new Item(7, 'tuxedo', 'clothes', 600, 'L+1'), new Item(8, 'cursed swimsuit', 'clothes', 10, 'A-10'), new Item(9, 'unicorn cosplay', 'clothes', 200, 'L+10'), new Item(10, 'dagger', 'weapon', 100, 'S+5'), new Item(11, 'cursed dagger', 'weapon', 100, 'S-5'), new Item(12, 'short sword', 'weapon', 200, 'S+10'), new Item(13, 'cursed short sword', 'weapon', 200, 'S-10'), new Item(14, 'long sword', 'weapon', 300, 'S+20'), new Item(15, 'cursed long sword', 'weapon', 300, 'S-20'), new Item(16, 'axe', 'weapon', 100, 'S+10'), new Item(17, 'cursed axe', 'weapon', 100, 'S-10'), new Item(18, 'great axe', 'weapon', 200, 'S+20'), new Item(19, 'cursed great axe', 'weapon', 200, 'S-20'), new Item(20, 'torch', 'lighter', 2, ''), new Item(21, 'oil lamp', 'lighter', 10, ''), new Item(22, 'leather purse', 'purse', 10, ''), new Item(23, 'protection potion', 'potion', 100, 'a+10'), new Item(24, 'health potion', 'potion', 100, 'l+10'), new Item(25, 'strength potion', 'potion', 100, 's+10'), new Item(26, 'fireball', 'spell', 1000, ''), new Item(27, 'ice cone', 'spell', 1000, ''), new Item(28, 'total healing', 'spell', 1000, ''), new Item(29, 'invisibility', 'spell', 1000, ''), new Item(30, 'levitation', 'spell', 1000, ''), new Item(31, 'apple', 'food', 1, 'l+1'), new Item(32, 'chicken', 'food', 10, 'l+5'), new Item(33, 'beef', 'food', 15, 'l+10'), new Item(34, 'wine', 'food', 2, 'l+2') ]; class Perso { constructor(name, level) { this.name = name; this.level = level; this.slots = [ {name:'head', id:1, items:[]}, {name:'body', id:2, items:[]}, {name:'hands', id:3, items:[]}, {name:'belt', id:4, items:[]}, {name:'bag', id:5, items:[]} ]; this.boughtItems = []; // list of item bought but not yet assigned this.life = 50*this.level; // the actual level of life this.gold=500; this.updateCaracs(); } updateCaracs() { this.vitaliy = this.level*50; this.armor = 0; this.strength = this.level*20; for(let i=0;i<this.slots.length;i++) { let slot = this.slots[i]; for(let j=0;j<slot.items.length;j++) { let item = slot.items[j]; // search for armor effects if (item.effect[0] == 'A') { let val = item.effect.substring(2,item.effect.length); if (item.effect[1] == '+') this.armor += eval(val); else if (item.effect[1] == '-') this.armor -= eval(val); } // search for vitality effects if (item.effect[0] == 'L') { let val = item.effect.substring(2,item.effect.length); if (item.effect[1] == '+') this.vitality += eval(val); else if (item.effect[1] == '-') this.vitality -= eval(val); } // search for strength effects if (item.effect[0] == 'S') { let val = item.effect.substring(2,item.effect.length); if (item.effect[1] == '+') this.strength += eval(val); else if (item.effect[1] == '-') this.strength -= eval(val); } } } if (this.life > this.vitality) this.life = this.vitality; } /* modified version for TP 4: - called from buy() in vue instance, where checks/confirmation are done. - item parameter is an item object */ buy(item) { this.boughtItems.push(item); this.gold -= item.price; } /* assign(): try to assign an item to a slot - itemId is the index of item in boughtItem - slot is the name of the slot (see attribute name in slots) return true if it's possible (i.e. limits and type of item respected) else return false. */ assign(itemId, to) { let item = this.boughtItems[itemId]; if (item == undefined) return false; let slot = this.slots.find(e => e.name == to); let slotLim = itemLimits.find(e => e.slot == to); // if to exists in player's slots and itemLimits if ((slot != undefined) && (slotLim != undefined)) { // check if limits/type is ok or not if (slot.items.length == slotLim.limit) { alert('limit for '+to+' alreay reached'); return false; } let t = slotLim.types.find(e => e == item.type); if (t == undefined) { alert(to+' cannot be assigned with '+item.type); return false; } console.log("assign "+item.name+" to "+slot.name); slot.items.push(item); this.boughtItems.splice(itemId,1); this.updateCaracs(); return true; } return false; } } var players = [ new Perso("toto",1), new Perso("tutu",2) ]; // create the shop, filling with items taken at random var shop = []; for(let i=0;i<10;i++) { let idx = getRandomInt(items.length); shop.push(items[idx]); } |
2°/ index.js
- Tout ce qui concerne l'affichage dynamique ET les événements est maintenant géré grâce à vuejs.
- La propriété calculée player consiste juste à faire un return d'un élément de players. NB : si on sort de ce tableau, la porirété calculée prend comme valeur undefined, ce qui peut être testé.
- La méthode buy() contient en gros les mêmes choses que celle de model.js du TP 3.
- contenu de index.js :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
var app = new Vue({ el: '#mydiv', data: { idPlayer:'', players, // to observe and have an access to players array shop, // to observe the shop idToBuy:'', idDrag : -1 // the id in boughtItems of the item currently dragged }, computed : { player : function() { return players[this.idPlayer]; } }, methods: { /* NB : since shop defined in data observes shop defined in model.js any modification of the latter will be observed. Thus, we can use directly shop instead of this.shop in the following code. */ buy : function() { if (shop[this.idToBuy].price > this.player.gold) { alert("Not enough gold"); } else { let r = confirm("want to buy " + shop[this.idToBuy].name+" for "+shop[this.idToBuy].price+"gp ?"); if (r == true) { this.player.buy(shop[this.idToBuy]); shop.splice(this.idToBuy,1); this.idToBuy=''; } } }, dragStart(index) { console.log("start dragging "+this.player.boughtItems[this.idDrag].name); this.idDrag = index; }, dragEnd() { console.log("stop dragging"); this.idDrag = -1; }, drop(slot) { console.log("item dropped on "+slot); this.player.assign(this.idDrag,slot); } } }) |
4°/ shop.html
- Grâce à l'ajout de la propriété claculée player, toutes les occurences de players[idPlayer] ont été remplacées par player.
- Pour que l'événement dragstart appelle dragStart(index), il suffit d'assigner la valeur index grâce à v-for. En effet, v-for permet de récupérer l'indice des éléments parcourus, par ex v-for="(el,index) in ...".
- Par rapport au TP 3, la gestion de la boutique a un peu changé : on n'ajoute/retranche plus 1 à index. En fait, ce n'était utile que pour le TP 3 où 2 versions de la boutique cohabitent et doivent appeler la même fonction buy().
- contenu de shop.html :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<html> <head> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script src="model.js"></script> </head> <body> <div id="mydiv"> <label for="idperso">#player:</label><input id="idperso" v-model="idPlayer"><br> <div v-if="player != undefined"> <h1>{{player.name}}, level {{player.level}}, life = {{player.life}}, strength = {{player.strength}}</h1> <table border="1"> <tr v-for="sl in player.slots"> <td @dragover.prevent @drop="drop(sl.name)">{{sl.name}}</td> <td v-for="it in sl.items">{{it.name}}</td> </tr> </table> <p>Bought items :<button draggable="true" v-for="(it,index) in player.boughtItems" @dragstart="dragStart(index)" @dragend="dragEnd()">{{it.name}}</button></p> <label for="gold">Gold:</label> <input type="text" readonly id="gold" :value="player.gold"><br> <p v-for="(it,index) in shop"> <input type="radio" name="itemsToBuy" :id="'ittobuy'+index" :value="index" v-model="idToBuy"> <label :for="'ittobuy'+index">{{it.name}} : {{it.price}} gp</label> </p> <button @click="buy()" v-if="shop[idToBuy]!=undefined">Buy {{shop[idToBuy].name}}</button> </div> </div> <script src="index.js"></script> </body> </html> |
4°/ Archive globale
- Vous pouvez télécharger une archive avec tous les fichiers [ ici ]