html2d
Version:
A Typescript game engine to build HTML5 games for the web using webcomponents.
379 lines (282 loc) • 10.3 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2D Game test</title>
<script type="module" src=""></script>
</head>
<body>
<style>
body, html {
background: #96ffc1;
margin: 0;
padding: 0;
width: 100%;
height: 100%;
image-rendering: pixelated;
image-rendering: crisp-edges;
display: flex;
justify-content: center;
align-items: center;
user-select: none;
}
.game-wrapper {
width: 640px;
height: 320px;
background-color:burlywood;
transform: scale(2);
will-change: transform;
}
</style>
<div class="game-wrapper" >
<km-hero></km-hero>
</div>
<template id="hero-element-template">
<style>
/* :host() {
will-change: transform;
}
.sprite {
position: absolute;
pointer-events: none;
}
.pixel-sprite {
image-rendering: pixelated;
image-rendering: crisp-edges;
}
.idle-animation {
animation: framesAnimation 1.1s steps(11) infinite;
animation-play-state: paused;
visibility: hidden;
}
:host([idle]) .idle-animation {
visibility: visible;
animation-play-state: running;
}
.attack-animation {
animation: framesAnimation 0.3s steps(3) infinite;
animation-play-state: paused;
visibility: hidden;
}
:host([attacking]) .attack-animation {
animation-play-state: running;
visibility: visible;
}
@keyframes framesAnimation {
from {
transform: translate(0px, 0)
}
to {
transform: translate(-100%, 0);
}
} */
</style>
<img class="sprite pixel-sprite idle-animation" draggable="false" src="sprites/01-King Human/Idle (78x58).png">
<img class="sprite pixel-sprite attack-animation" draggable="false" src="sprites/01-King Human/Attack (78x58).png">
</template>
<script>
// class Vector2D {
// /**
// * Representation of 2D vectors and points.
// * @param {number} x - X component of the vector.
// * @param {number} y - Y component of the vector.
// */
// constructor(x, y) {
// this.x = x ?? 0
// this.y = y ?? 0
// }
// }
// class Input2D {
// /**
// * @param {( "Horizontal" | "Vertical" )} direction - a virtual axis name.
// * */
// static getAxis(direction) {
// if (direction === "Horizontal") {
// return 1
// }
// if (direction === "Vertical") {
// return -1
// }
// console.error(`${direction} is not a valid axis name.`)
// }
// }
// Input2D.getAxis("Horizontal")
// class HeroElement extends HTMLElement {
// speed = 1
// movement = new Vector2D
// held_directions = []
// directions = {
// up: "up",
// down: "down",
// left: "left",
// right: "right"
// }
// keys = {
// 38: this.directions.up,
// 87: this.directions.up,
// 37: this.directions.left,
// 65: this.directions.left,
// 39: this.directions.right,
// 68: this.directions.right,
// 40: this.directions.down,
// 83: this.directions.down
// }
// get idle() {
// return this.hasAttribute("idle")
// }
// set idle(isIdle) {
// (isIdle) ? this.setAttribute("idle", "") : this.removeAttribute("idle")
// }
// get attacking() {
// return this.hasAttribute("attacking")
// }
// set attacking(isAttacking) {
// (isAttacking) ? this.setAttribute("attacking", "") : this.removeAttribute("attacking")
// }
// static get observedAttributes() {
// return ["idle", "attacking"]
// }
// constructor() {
// super()
// // const test = Input2D.getAxis("Horizontal")
// const template = document.getElementById("hero-element-template")
// this.attachShadow({mode: "open"}).appendChild(template.content.cloneNode(true))
// this.idle = true
// // key up, key down and click etc. should be in a Input handler
// document.addEventListener("keydown", (e) => {
// let dir = this.keys[e.which]
// console.log(dir)
// if(dir && this.held_directions.indexOf(dir) === -1) {
// this.held_directions.unshift(dir)
// }
// })
// document.addEventListener("keyup", (e) => {
// let dir = this.keys[e.which]
// let index = this.held_directions.indexOf(dir)
// if(index > -1) {
// this.held_directions.splice(index, 1)
// }
// })
// document.addEventListener("click", () => {
// this.idle = false
// this.attacking = true
// })
// this.shadowRoot.querySelector(".attack-animation").addEventListener('animationiteration', () => {
// this.attacking = false
// this.idle = true
// })
// // should be a game-element?
// this.style.display = "block"
// this.style.height = "58px"
// this.style.width = "78px"
// this.style.position = "relative"
// // should be in the image wrapper??
// this.style.overflow = "hidden"
// // temp to get starting x, refresh if the game size changes? and should be handled by a transform or something this is fugly
// this.x = this.getBoundingClientRect().x - document.querySelector(".game-wrapper").getBoundingClientRect().x
// this.y = this.getBoundingClientRect().y - document.querySelector(".game-wrapper").getBoundingClientRect().y
// }
// update() {
// let held_direction = this.held_directions[0]
// let currentSpeed = this.speed
// if (this.attacking) {
// currentSpeed = this.speed / 2
// }
// if (held_direction) {
// if (held_direction === this.directions.right) this.movement.x += currentSpeed
// if (held_direction === this.directions.left) this.movement.x -= currentSpeed
// if (held_direction === this.directions.down) this.movement.y += currentSpeed
// if (held_direction === this.directions.up) this.movement.y -= currentSpeed
// }
// this.style.transform = `translate(${this.movement.x}px, ${this.movement.y}px)`
// }
// }
// Registers custom element
window.customElements.define("km-hero", HeroElement)
const hero = document.querySelector("km-hero")
const update = () => {
hero.update()
}
const render = () => {
}
// Game logic
const gameLoop = () => {
update()
render()
requestAnimationFrame(() => {
gameLoop()
})
}
gameLoop()
// const character = document.querySelector(".player")
// let x = 0
// let y = 0
// let held_directions = []
// let speed = 1.5
// const directions = {
// up: "up",
// down: "down",
// left: "left",
// right: "right"
// }
// const placeCharacter = () => {
// let held_direction = held_directions[0]
// if (held_direction) {
// if (held_direction === directions.right) x += speed
// if (held_direction === directions.left) x -= speed
// if (held_direction === directions.down) y += speed
// if (held_direction === directions.up) y -= speed
// character.setAttribute("data-facing", held_direction)
// if (held_direction === directions.left) {
// character.style.transform += "scaleX(-1)"
// }
// }
// character.setAttribute("data-walking", held_direction ? String(true) : String(false))
// character.style.transform = `translate3d(${x}px, ${y}px, 0)`
// if (character.getAttribute("data-facing") === directions.left) {
// character.style.transform += "scaleX(-1)"
// }
// }
// const step = () => {
// placeCharacter()
// requestAnimationFrame(() => {
// step()
// })
// }
// step()
// const keys = {
// 38: directions.up,
// 87: directions.up,
// 37: directions.left,
// 65: directions.left,
// 39: directions.right,
// 68: directions.right,
// 40: directions.down,
// 83: directions.down
// }
// document.addEventListener("keydown", (e) => {
// let dir = keys[e.which]
// let index = held_directions.indexOf(dir)
// if(dir && held_directions.indexOf(dir) === -1) {
// held_directions.unshift(dir)
// }
// })
// document.addEventListener("keyup", (e) => {
// let dir = keys[e.which]
// let index = held_directions.indexOf(dir)
// if(index > -1) {
// held_directions.splice(index, 1)
// }
// })
// document.addEventListener("click", () => {
// // character.style = "width: 78px; background: green"
// character.setAttribute("data-attacking", true);
// })
// document.querySelector('.sprite-animation-attack').addEventListener('animationiteration', () => {
// character.setAttribute("data-attacking", String(false));
// });
</script>
</body>
</html>