UNPKG

html2d

Version:

A Typescript game engine to build HTML5 games for the web using webcomponents.

379 lines (282 loc) 10.3 kB
<!DOCTYPE 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>