Buttons Graphical Element - SSBDoppler/slippi-hud GitHub Wiki
Lets take my Slippi-HUD implementation for the Left Player.
<div id="p1stick" class="astick" style="position: absolute; top: ${Math.round(40-(this.playerData[0].slippi.controller.mainStickY*17))}px; left: ${Math.round(56+(this.playerData[0].slippi.controller.mainStickX*17))}px"></div>
<div id="p1cstick" class="cstick" style="position: absolute; top: ${49-(this.playerData[0].slippi.controller.cStickY*18)}px; left: ${147+(this.playerData[0].slippi.controller.cStickX*18)}px"></div>
<div id="Abutton" class="${this.playerData[0].slippi.controller.pressedButtons.A}"></div>
<div id="Bbutton" class="${this.playerData[0].slippi.controller.pressedButtons.B}"></div>
<div id="Xbutton" class="${this.playerData[0].slippi.controller.pressedButtons.X}"></div>
<div id="Ybutton" class="${this.playerData[0].slippi.controller.pressedButtons.Y}"></div>
<div id="Zbutton" class="${this.playerData[0].slippi.controller.pressedButtons.Z}"></div>
<div id="Rbutton" class="${this.playerData[0].slippi.controller.pressedButtons.R}"></div>
<div id="Lbutton" class="${this.playerData[0].slippi.controller.pressedButtons.L}"></div>
<div id="Startbutton" class="${this.playerData[0].slippi.controller.pressedButtons.START}"></div>
<div id="DUbutton" class="${this.playerData[0].slippi.controller.pressedButtons.D_UP}"></div>
<div id="DDbutton" class="${this.playerData[0].slippi.controller.pressedButtons.D_DOWN}"></div>
<div id="DRbutton" class="${this.playerData[0].slippi.controller.pressedButtons.D_RIGHT}"></div>
<div id="DLbutton" class="${this.playerData[0].slippi.controller.pressedButtons.D_LEFT}"></div>
<div id="LTrigger" style="height: ${this.playerData[0].slippi.controller.leftTrigger*103}px;"></div>
<div id="RTrigger" style="height: ${this.playerData[0].slippi.controller.rightTrigger*103}px;"></div>
<div id="outline" class="button"><img src="./img/slippi-hud/buttons/buttons.png" width="300" height="124"></img></div>
</div>
For the Analog Stick I'll break this down and you should be able to recreate my thought process for the cStick
<div id="p1stick" class="astick" style="position: absolute; top: ${Math.round(40-(this.playerData[0].slippi.controller.mainStickY*17))}px; left: ${Math.round(56+(this.playerData[0].slippi.controller.mainStickX*17))}px"></div>
Math round is used to get whole numbers for pixels, it doesn't really do anything except calm my OCD.
${Math.round(40-(this.playerData[0].slippi.controller.mainStickY*17))}px
40 Represents the distance from the top of the div box to the center of the control stick area subtracting half the analog stick image height in pixels.
this.playerData[0].slippi.controller.mainStickY
represents the y axis. 1 is UP and -1 is down and 0 is the neutral. This is multiplied by 17 because 17 is half the height of the entire control stick area.
(this.playerData[0].slippi.controller.mainStickY*17)
in effect is the pixel position from center the analog stick should be displayed. This however does not place it properly inside our controller box.
Since we're measuring pixels from the top and mainStickY == 1 is up we subtract (this.playerData[0].slippi.controller.mainStickY*17)
from the 40.
${Math.round(56+(this.playerData[0].slippi.controller.mainStickX*17))}
56 represents the distance from the left of the div box to the center of the control stick area subtracting half the analog stick image width in pixels.
this.playerData[0].slippi.controller.mainStickX
represents the x axis. 1 is right and -1 is left and 0 is the neutral. This is multiplied by 17 because 17 is half the width of the entire control stick area.
(this.playerData[0].slippi.controller.mainStickX*17)
in effect is the pixel position from center the analog stick should be displayed. This however does not place it properly inside our controller box.
Since we're measuring pixels from the left and mainStickX == 1 is right we add (this.playerData[0].slippi.controller.mainStickX*17)
to the 56.
<div id="Bbutton" class="${this.playerData[0].slippi.controller.pressedButtons.B}"></div>
<div id="Xbutton" class="${this.playerData[0].slippi.controller.pressedButtons.X}"></div>
<div id="Ybutton" class="${this.playerData[0].slippi.controller.pressedButtons.Y}"></div>
<div id="Zbutton" class="${this.playerData[0].slippi.controller.pressedButtons.Z}"></div>
<div id="Rbutton" class="${this.playerData[0].slippi.controller.pressedButtons.R}"></div>
<div id="Lbutton" class="${this.playerData[0].slippi.controller.pressedButtons.L}"></div>
<div id="Startbutton" class="${this.playerData[0].slippi.controller.pressedButtons.START}"></div>
<div id="DUbutton" class="${this.playerData[0].slippi.controller.pressedButtons.D_UP}"></div>
<div id="DDbutton" class="${this.playerData[0].slippi.controller.pressedButtons.D_DOWN}"></div>
<div id="DRbutton" class="${this.playerData[0].slippi.controller.pressedButtons.D_RIGHT}"></div>
<div id="DLbutton" class="${this.playerData[0].slippi.controller.pressedButtons.D_LEFT}"></div>
Buttons are actually really easy, to make displaying button presses really easy we might have to look at the style section of the template.
#Abutton {
position: absolute;
background: url('./img/slippi-hud/buttons/a.png') 0px 0px no-repeat;
width: 44px;
height: 44px;
top: 47px;
left: 195px;
}
#Bbutton {
position: absolute;
background: url('./img/slippi-hud/buttons/b.png') 0px 0px no-repeat;
width: 19px;
height: 19px;
top: 93px;
left: 180px;
}
#Xbutton {
position: absolute;
background: url('./img/slippi-hud/buttons/x.png') 0px 0px no-repeat;
width: 20px;
height: 32px;
top: 46px;
left: 246px;
}
#Ybutton {
position: absolute;
background: url('./img/slippi-hud/buttons/y.png') 0px 0px no-repeat;
width: 32px;
height: 20px;
top: 19px;
left: 194px;
}
#Zbutton {
position: absolute;
background: url('./img/slippi-hud/buttons/z.png') 0px 0px no-repeat;
width: 36px;
height: 25px;
top: 7px;
left: 233px;
}
#Lbutton {
background: url('./img/slippi-hud/buttons/digital.png') 0px 0px no-repeat;
width: 15px;
position: absolute;
height: 18px;
top: 3px;
left: 4px;
}
#Rbutton {
background: url('./img/slippi-hud/buttons/digital.png') 0px 0px no-repeat;
width: 15px;
height: 18px;
top: 3px;
position: absolute;
left: 282px;
}
#DLbutton {
background: url('./img/slippi-hud/buttons/d.png') 0px 0px no-repeat;
position: absolute;
width: 8px;
height: 8px;
top: 100px;
left: 106px;
}
#DRbutton {
background: url('./img/slippi-hud/buttons/d.png') 0px 0px no-repeat;
width: 8px;
height: 8px;
top: 100px;
position: absolute;
left: 124px;
}
#DUbutton {
background: url('./img/slippi-hud/buttons/d.png') 0px 0px no-repeat;
width: 8px;
height: 8px;
top: 91px;
position: absolute;
left: 115px;
}
#DDbutton {
background: url('./img/slippi-hud/buttons/d.png') 0px 0px no-repeat;
width: 8px;
height: 8px;
top: 109px;
position: absolute;
left: 115px;
}
#RTrigger {
background: url('./img/slippi-hud/buttons/analog.png') 0px 0px no-repeat;
width: 15px;
top: 21px;
left: 282px;
position: absolute;
}
#LTrigger {
background: url('./img/slippi-hud/buttons/analog.png') 0px 0px no-repeat;
width: 15px;
top: 21px;
left: 4px;
position: absolute;
}
.sticks {
background: url('./img/slippi-hud/buttons/sticks.png') 0px 0px no-repeat;
}
.astick {
background: url('./img/slippi-hud/buttons/AStick.png') 0px 0px no-repeat;
height: 31px;
width: 31px;
}
.cstick {
background: url('./img/slippi-hud/buttons/CStick.png') 0px 0px no-repeat;
height: 17px;
width: 17px;
}
.button {
height: 124px;
width: 300px;
}
.true {
opacity: 1;
}
.false {
opacity: 0;
}
As you can see, I have the buttons always loaded and in the correct position, and just use the true and false values of this.playerData[0].slippi.controller.pressedButtons.value
to turn the opacity to 1 and 0 respectively, this is considerably less laggy than loading and unloading the images each time the button is pressed.
<div id="LTrigger" style="height: ${this.playerData[0].slippi.controller.leftTrigger*103}px;"></div>
<div id="RTrigger" style="height: ${this.playerData[0].slippi.controller.rightTrigger*103}px;"></div>
the trigger values are between 0 and 1, so you just multiply that by the analog area's height. A full analog press will be the full height and no press is a 0 and so it'll remove the image from view. It can be useful when seeing if/which trigger is sticking as well.