summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--index.html60
-rw-r--r--script.js221
-rw-r--r--style.css84
3 files changed, 280 insertions, 85 deletions
diff --git a/index.html b/index.html
index fa5498b..94f298c 100644
--- a/index.html
+++ b/index.html
@@ -1,12 +1,12 @@
<html>
<head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width,initial-scale=1">
+
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="wrap">
- <div>Money: <div id="money"></div></div>
- <div id="party"></div>
-
<div id="battle">
<div id="battle__enemy">
<img class="battle__monster-sprite__animation" src="" draggable="false" />
@@ -15,18 +15,38 @@
<div id="battle__player"></div>
</div>
- <div id="catch">CATCH</div>
+ <div id="status">
+ <div>Money: <span id="money"></span></div>
+ </div>
+
+ <div id="menu">
+ <div id="menu__party">
+ <img src="/modules/tuxemon/mods/tuxemon/gfx/ui/menu/tuxemon.png" title="Tuxemon" width="64" height="64" />
+ </div>
+
+ <div id="menu__inventory">
+ <img src="/modules/tuxemon/mods/tuxemon/gfx/ui/item/backpack.png" title="Inventory" width="64" height="64" />
+ </div>
+
+ <div id="menu__catch">
+ <img src="/modules/tuxemon/mods/tuxemon/gfx/items/tuxeball.png" title="Catch" width="64" height="64" />
+ </div>
+ </div>
</div>
<template id="tpl___party__monster">
<div class="party__monster">
<div><div class="monster__level"></div></div>
- <img src="" />
+ <img class="monster__img" src="" />
<div class="monster__exp">
<div class="monster__exp-bar"></div>
</div>
<div class="monster__exp-text"></div>
- <div class="monster__active-technique"></div>
+ <div class="monster__active-technique">
+ <div class="monster__active-technique__name"></div>
+ <div class="monster__active-technique__types"></div>
+ <div class="monster__active-technique__power"></div>
+ </div>
</div>
</template>
@@ -35,14 +55,19 @@
<div class="battle__monster-info">
<div class="battle__monster-info-box">
<div>
- <span class="battle__monster-info__name">{NAME}</span> <span class="battle__monster-info__gender">{GENDER}</span> Lv. <span class="battle__monster-info__level">{LEVEL}</span>
+ <span class="battle__monster-info__name">{NAME}</span>
+ <span class="battle__monster-info__gender">{GENDER}</span>
+ Lv. <span class="battle__monster-info__level">{LEVEL}</span>
</div>
- <div class="hp">
- <div class="hp-bar-wrap">
- <div class="hp-bar"></div>
+ <div class="battle__monster-info-box__status">
+ <div class="battle__monster-info__status"></div>
+ <div class="hp">
+ <div class="hp-bar-wrap">
+ <div class="hp-bar"></div>
+ </div>
+ <div class="hp-text"></div>
+ </div>
</div>
- <div class="hp-text"></div>
- </div>
</div>
<div class="battle__monster-info-exp">
<div class="exp-label">XP</div>
@@ -58,7 +83,11 @@
<div class="battle__monster-sprite">
<img class="battle__monster-img" src="" draggable="false" />
</div>
- <div class="battle__monster-technique"></div>
+ <div class="battle__monster-technique">
+ <div class="battle__monster-technique__name"></div>
+ <div class="battle__monster-technique__types"></div>
+ <div class="battle__monster-technique__power"></div>
+ </div>
</div>
</div>
</template>
@@ -74,7 +103,10 @@
</template>
<template id="tpl___moveset__item">
<div class="moveset__item">
- name, lvlrequired, types, power
+ <span class="moveset__item__name"></span>
+ <span class="moveset__item__type"></span>
+ <span class="moveset__item__power"></span>
+ <span class="moveset__item__level"></span>
</div>
</template>
diff --git a/script.js b/script.js
index 575db99..9eecc44 100644
--- a/script.js
+++ b/script.js
@@ -14,6 +14,34 @@ const ElementType = {
earth: 'earth',
metal: 'metal',
water: 'water',
+
+ /* lightning: 'lightning',
+ frost: 'frost',
+ venom: 'venom',
+ //vermin: 'vermin',
+ cosmic: 'cosmic',
+ battle: 'battle',
+ psionic: 'psionic',
+ darkness: 'darkness',
+ heaven: 'heaven',
+
+ combineTypes(typeA, typeB) {
+ if (typeA === ElementType.earth & typeB === ElementType.fire) {
+ return ElementType.lightning;
+ }
+ if (typeA === ElementType.earth & typeB === ElementType.water) {
+ return ElementType.frost;
+ }
+ if (typeA === ElementType.earth & typeB === ElementType.wood) {
+ return ElementType.venom;
+ }
+ // if (typeA === ElementType.earth & typeB === ElementType.metal) {
+ // return ElementType.vermin;
+ // }
+ if (typeA === ElementType.fire && typeB === ElementType.water) {
+ return ElementType.cosmic;
+ }
+ } */
};
const ElementTypeColor = {
[ElementType.aether]: 'rgba(255, 255, 255, 1)',
@@ -58,7 +86,10 @@ class State {
money = 0;
monsters = [];
+ inventory = [];
+
partyMonsters = [];
+
activeMonster = null;
activeTechnique = null;
@@ -77,6 +108,9 @@ class Monster {
gender = '';
+ heldItem = null;
+ statusEffect = '';
+
statusModifiers = {
hp: 0,
melee: 0,
@@ -164,7 +198,8 @@ class Monster {
}
getPossibleEvolutions () {
- return this.evolutions.filter((evolution) => this.level >= evolution.at_level && (!evolution.item || this.heldItem === evolution.item));
+ // return this.evolutions.filter((evolution) => this.level >= evolution.at_level && (!evolution.item || this.heldItem === evolution.item));
+ return this.evolutions.filter((evolution) => evolution.path === 'standard' && this.level >= evolution.at_level);
}
canEvolve () {
@@ -268,8 +303,14 @@ class Technique {
get animation () {
return DB.techniques[this.slug].animation;
}
+
+ get sfx () {
+ return DB.techniques[this.slug].sfx;
+ }
}
+class Item {}
+
function simpleDamageMultiplier (techniqueTypes, targetTypes) {
let multiplier = 1;
@@ -412,7 +453,7 @@ function slugToName (slug) {
const UI = {
activeMonster: null,
- damageAnimationInterval: null,
+ damageAnimationIsRunning: false,
damageAnimationNumber: 0,
getTemplate (template) {
@@ -449,13 +490,13 @@ function slugToName (slug) {
hpText.textContent = monster.hp + ' / ' + monster.status.hp;
},
- createDamage (event, damage) {
+ async createDamage (event, damage) {
const damageNode = document.createElement('div');
damageNode.classList.add('damage');
damageNode.textContent = damage;
const damageMultiplier = simpleDamageMultiplier(state.activeTechnique.types, state.enemy.monster.types);
- damageNode.style.fontSize = damageMultiplier + 'rem';
+ damageNode.style.fontSize = damageMultiplier*2 + 'rem';
damageNode.style.top = event.pageY - battleEnemy.offsetTop + (Math.random() * 40 - 20);
damageNode.style.left = event.pageX - battleEnemy.offsetLeft + (Math.random() * 40 - 20);
@@ -476,57 +517,34 @@ function slugToName (slug) {
clickTimeout = setTimeout(() => enemyImg.classList.remove('damaged'), imgClickDuration * 1000);
var enemyAnimation = battleEnemy.querySelector('.battle__monster-sprite__animation');
- // enemyAnimation.style.top = enemyImg.getBoundingClientRect().top;
- // enemyAnimation.style.left = enemyImg.getBoundingClientRect().left;
- if (!this.damageAnimationInterval && state.activeTechnique.animation) {
- this.damageAnimationInterval = setInterval(() => {
+ if (!this.damageAnimationIsRunning && state.activeTechnique.animation) {
+ this.damageAnimationIsRunning = true;
+
+ const damageAnimationLoop = () => {
enemyAnimation.src = `/modules/tuxemon/mods/tuxemon/animations/technique/${state.activeTechnique.animation}_${("00" + this.damageAnimationNumber).slice(-2)}.png`;
enemyAnimation.style.top = event.clientY - (enemyAnimation.clientHeight / 2);
enemyAnimation.style.left = event.clientX - (enemyAnimation.clientWidth / 2);
- console.log(enemyAnimation.src);
+ // console.log(enemyAnimation.src);
this.damageAnimationNumber++;
if (this.damageAnimationNumber === DB.allAnimations[state.activeTechnique.animation].length) {
- clearInterval(this.damageAnimationInterval);
- this.damageAnimationInterval = null;
+ this.damageAnimationIsRunning = false;
this.damageAnimationNumber = 0;
enemyAnimation.src = '';
+ return;
}
- }, 50);
- }
- },
-
- addPartyMonster (slug) {
- let partyMonster = document.createElement('div');
- partyMonster.innerHTML = templatePartyMonster.trim();
- partyMonster = partyMonster.firstChild;
-
- partyMonster.dataset.slug = slug;
- partyMonster.querySelector('img').src = `/modules/tuxemon/mods/tuxemon/gfx/sprites/battle/${slug}-front.png`;
- partyMonster.addEventListener('click', (event) => {
- let target = event.target;
- while (target.parentNode.id !== 'party') {
- target = target.parentNode;
- }
+ setTimeout(() => requestAnimationFrame(damageAnimationLoop), 50);
+ };
- state.activeMonster = state.partyMonsters[Array.prototype.indexOf.call(document.querySelector('#party').children, target)];
- UI.setActiveMonster();
- });
- partyMonster.style.cursor = 'pointer';
+ requestAnimationFrame(damageAnimationLoop);
- party.appendChild(partyMonster);
- },
-
- async setActiveMonster () {
- let activeMoveIndex = 0;
- while ((await fetchTechnique(state.activeMonster.moveset[activeMoveIndex].technique)).power === 0) {
- activeMoveIndex++;
+ // sfx
+ /* let sfx = state.activeTechnique.sfx.substr(4);
+ const audio = new Audio(`/modules/tuxemon/mods/tuxemon/sounds/technique/${sfx}.ogg`);
+ audio.play(); */
}
- state.activeTechnique = await fetchTechnique(state.activeMonster.moveset[activeMoveIndex].technique);
-
- UI.setBattleMonster(state.activeMonster, 'player');
},
setBattleMonster (monster, where) {
@@ -537,28 +555,44 @@ function slugToName (slug) {
battleMonster.querySelector('.battle__monster-info__name').textContent = monster.name;
battleMonster.querySelector('.battle__monster-info__gender').textContent = monster.gender === 'male' ? '♂' : monster.gender === 'female' ? '♀' : '⚲';
battleMonster.querySelector('.battle__monster-info__level').textContent = monster.level;
+ battleMonster.querySelector('.battle__monster-info__status').innerHTML = UI.createStatusIcon(monster.statusEffect);
+ battleMonster.querySelector('.battle__monster-img').src = `/modules/tuxemon/mods/tuxemon/gfx/sprites/battle/${monster.slug}-front.png`;
+
UI.setHp(monster, battleMonster.querySelector('.hp'));
- battleMonster.querySelector('img').src = `/modules/tuxemon/mods/tuxemon/gfx/sprites/battle/${monster.slug}-front.png`;
if (where === 'player') {
UI.setExp(monster, battleMonster.querySelector('.exp'));
- battleMonster.querySelector('.battle__monster-technique').textContent =
- state.activeTechnique.slug + ' - ' + state.activeTechnique.types + ' - ' + state.activeTechnique.power;
+ battleMonster.querySelector('.battle__monster-technique').innerHTML =
+ slugToName(state.activeTechnique.slug) + ' &nbsp; '
+ + state.activeTechnique.types.map((type) => UI.createElementTypeIcon(type)).join('');
battleMonster.querySelector('.battle__monster-technique').addEventListener('click', UI.openMovesetSelection);
battleMonster.classList.add('battle__monster--player');
- battlePlayer.replaceChildren(battleMonster);
+ battlePlayer.querySelector('.battle__monster') && battlePlayer.removeChild(battlePlayer.querySelector('.battle__monster'));
+ battlePlayer.appendChild(battleMonster);
} else {
battleMonster.classList.add('battle__monster--enemy');
- // battleEnemy.replaceChildren(battleMonster);
battleEnemy.querySelector('.battle__monster') && battleEnemy.removeChild(battleEnemy.querySelector('.battle__monster'));
battleEnemy.appendChild(battleMonster);
}
},
+ setEnemyMonster () {
+ UI.setBattleMonster(state.enemy.monster, 'enemy');
+ },
+
+ async setActiveMonster () {
+ let activeMoveIndex = 0;
+ while ((await fetchTechnique(state.activeMonster.moveset[activeMoveIndex].technique)).power === 0) {
+ activeMoveIndex++;
+ }
+ state.activeTechnique = await fetchTechnique(state.activeMonster.moveset[activeMoveIndex].technique);
+
+ UI.setBattleMonster(state.activeMonster, 'player');
+ },
+
async openMovesetSelection () {
- const popup = UI.getTemplate(templatePopup);
- popup.addEventListener('click', ({ target }) => target === popup && popup.remove());
+ const popup = UI.createPopup();
const movesetList = UI.getTemplate(templateMovesetList);
for (const move of state.activeMonster.moveset) {
@@ -570,7 +604,11 @@ function slugToName (slug) {
const movesetItem = UI.getTemplate(templateMovesetItem);
- movesetItem.textContent = slugToName(technique.slug) + ' - ' + technique.types + ' - ' + technique.power + ' - ' + move.level_learned;
+ movesetItem.querySelector('.moveset__item__name').textContent = slugToName(technique.slug);
+ movesetItem.querySelector('.moveset__item__type').innerHTML = technique.types.map((type) => UI.createElementTypeIcon(type)).join('');
+ movesetItem.querySelector('.moveset__item__power').innerHTML = technique.power;
+ movesetItem.querySelector('.moveset__item__level').innerHTML = move.level_learned;
+
movesetItem.addEventListener('click', () => {
if (movesetItem.getAttribute('disabled')) {
return false;
@@ -598,17 +636,79 @@ function slugToName (slug) {
state.enemy.monster.level = Math.ceil(Math.random() * state.activeMonster.level);
// state.enemy.monster.experienceModifier = state.enemy.monster.level;
state.enemy.monster.moneyModifier = state.enemy.monster.level;
- UI.setBattleMonster(state.enemy.monster, 'enemy');
+ UI.setEnemyMonster();
},
- };
- for (const monster of state.partyMonsters) {
- UI.addPartyMonster(monster.slug);
- }
+ createElementTypeIcon (type) {
+ var img = document.createElement('img');
+ img.src = `/modules/tuxemon/mods/tuxemon/gfx/ui/icons/element/${type}_type.png`;
+ img.title = slugToName(type);
+
+ return img.outerHTML;
+ },
+
+ createStatusIcon (status) {
+ if (!status) return '';
+
+ var img = document.createElement('img');
+ img.src = `/modules/tuxemon/mods/tuxemon/gfx/ui/icons/status/icon_${status}.png`;
+ img.title = slugToName(status);
+
+ return img.outerHTML;
+ },
+
+ createPopup () {
+ const popup = UI.getTemplate(templatePopup);
+ popup.addEventListener('click', ({ target }) => target === popup && popup.remove());
+
+ return popup;
+ },
+
+ openPartyMenu () {
+ const popup = UI.createPopup();
+
+ const party = document.createElement('div');
+ party.id = 'party';
+ for (const monster of state.partyMonsters) {
+ const partyMonster = UI.getTemplate(templatePartyMonster);
+
+ partyMonster.dataset.slug = monster.slug;
+ partyMonster.querySelector('img').src = `/modules/tuxemon/mods/tuxemon/gfx/sprites/battle/${monster.slug}-front.png`;
+
+ partyMonster.addEventListener('click', (event) => {
+ let target = event.target;
+ while (target.parentNode.id !== 'party') {
+ target = target.parentNode;
+ }
+
+ state.activeMonster = state.partyMonsters[Array.prototype.indexOf.call(document.querySelector('#party').children, target)];
+ UI.setActiveMonster();
+
+ popup.remove();
+ });
+
+ party.appendChild(partyMonster);
+ }
+
+ popup.querySelector('.popup').appendChild(party);
+ document.body.appendChild(popup);
+ },
+
+ openInventoryMenu () {
+ const popup = UI.createPopup();
+
+ const inventory = document.createElement('div');
+ inventory.id = 'inventory';
+ for (const item of state.inventory) {
+ }
+
+ popup.querySelector('.popup').appendChild(inventory);
+ document.body.appendChild(popup);
+ },
+ };
- UI.setBattleMonster(state.activeMonster, 'player');
- UI.setBattleMonster(state.enemy.monster, 'enemy');
UI.setActiveMonster();
+ UI.setEnemyMonster();
var clickTimeout;
document.querySelector('#battle__enemy').addEventListener('click', async (event) => {
@@ -630,20 +730,21 @@ function slugToName (slug) {
state.activeMonster.evolve();
UI.setActiveMonster();
}
-
- UI.setBattleMonster(state.activeMonster, 'player');
}
UI.setHp(state.enemy.monster, battleEnemy);
money.textContent = state.money;
});
- document.querySelector('#catch').addEventListener('click', async (event) => {
+ document.querySelector('#menu__party').addEventListener('click', UI.openPartyMenu);
+
+ document.querySelector('#menu__catch').addEventListener('click', async () => {
const caughtMonster = new Monster(state.enemy.monster.slug);
caughtMonster.level = state.enemy.monster.level;
state.partyMonsters.push(caughtMonster);
UI.createNewEnemyMonster();
- UI.addPartyMonster(caughtMonster.slug);
});
+
+ document.querySelector('#menu__inventory').addEventListener('click', UI.openInventoryMenu);
})();
diff --git a/style.css b/style.css
index 3a97ff1..c0bf5f4 100644
--- a/style.css
+++ b/style.css
@@ -2,6 +2,10 @@
box-sizing: border-box;
}
+html {
+ font-size: 14px;
+}
+
body {
margin: 0;
}
@@ -13,11 +17,10 @@ img {
.wrap {
margin: 0 auto;
- width: 1200px;
+ min-width: 360px;
+ max-width: 750px;
+ width: 100vw;
height: 100vh;
- display: flex;
- justify-content: center;
- align-items: center;
}
.popup__overlay {
@@ -33,21 +36,19 @@ img {
}
.popup {
background-color: #fff;
- padding: 1rem;
+ padding: 0.25rem 0.5rem;
}
#battle {
user-select: none;
- min-width: 750px;
min-height: 300px;
- padding: 1rem;
+ padding: 0.5rem;
display: flex;
flex-direction: column;
justify-content: space-between;
- background-image: url('/modules/tuxemon/mods/tuxemon/gfx/backgrounds/test/back02.png');
- background-image: url('https://wiki.tuxemon.org/images/9/9f/Sea_background.png');
+ background-image: url('/modules/tuxemon/mods/tuxemon/gfx/ui/combat/sea_background.png');
background-size: cover;
}
@@ -78,6 +79,17 @@ img {
.battle__monster-info__gender {
line-height: 1em;
}
+
+.battle__monster-info-box__status {
+ display: flex;
+ justify-content: space-between;
+ /* align-items: center; */
+}
+.battle__monster-info__status {
+ flex-basis: 5%;
+ text-align: center;
+}
+
.battle__monster-info-exp {
display: flex;
align-items: center;
@@ -113,9 +125,14 @@ img {
.battle__monster-technique {
background-color: beige;
border: 2px solid #000;
- display: inline;
padding: 0.25rem;
+
+ display: inline-flex;
+ align-items: center;
}
+.battle__monster-technique__name {}
+.battle__monster-technique__types {}
+.battle__monster-technique__power {}
.battle__monster--player {
flex-direction: row-reverse;
@@ -139,6 +156,9 @@ img {
transition: background-color;
width: 0%;
}
+.hp {
+ flex-grow: 1;
+}
.hp-bar-wrap {
width: 100%;
border: 1px solid rgba(0, 0, 0, 0.5);
@@ -149,8 +169,50 @@ img {
transition: background-color;
}
+.moveset__item {
+ font-size: 1.5rem;
+ border: 1px solid #000;
+ padding: 0.5em 0.75em;
+ margin: 0.5em 0;
+ line-height: 1em;
+ cursor: pointer;
+}
+.moveset__item:hover {
+ background-color: rgba(0, 0, 0, 0.1);
+}
.moveset__item[disabled] {
- color: #ebebeb;
+ filter: grayscale(100%);
+ opacity: 0.5;
+}
+.moveset__item img {
+ height: 1em;
+ width: 1em;
+}
+
+
+#menu {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr;
+ text-align: center;
+}
+#menu > div {
+ cursor: pointer;
+}
+#menu > div:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+
+
+#party {
+ display: grid;
+ grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
+}
+
+.party__monster {
+ cursor: pointer;
+}
+.party__monster:hover {
+ background-color: rgba(0, 0, 0, 0.1);
}