mirror of
https://github.com/danbulant/heaventaker
synced 2026-06-22 00:02:00 +00:00
phaser rewrite
This commit is contained in:
parent
7f452963d9
commit
5d7db80f3d
7 changed files with 366 additions and 344 deletions
88
package-lock.json
generated
88
package-lock.json
generated
|
|
@ -11,6 +11,7 @@
|
|||
"dependencies": {
|
||||
"fabric": "^4.3.1",
|
||||
"howler": "^2.2.1",
|
||||
"phaser": "^3.54.0",
|
||||
"sirv-cli": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
@ -1999,6 +2000,11 @@
|
|||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
|
||||
},
|
||||
"node_modules/extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
|
|
@ -3122,6 +3128,15 @@
|
|||
"integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/path": {
|
||||
"version": "0.12.7",
|
||||
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
|
||||
"integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=",
|
||||
"dependencies": {
|
||||
"process": "^0.11.1",
|
||||
"util": "^0.10.3"
|
||||
}
|
||||
},
|
||||
"node_modules/path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
|
|
@ -3143,6 +3158,15 @@
|
|||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/phaser": {
|
||||
"version": "3.54.0",
|
||||
"resolved": "https://registry.npmjs.org/phaser/-/phaser-3.54.0.tgz",
|
||||
"integrity": "sha512-/1XVI6J2siS0OGwJez7vLbRjars1zb//EvJdYMVyd3wNTUf5DHrvYUj1f6TsEISr4vjnbrNtS66QIuPbGU8x6A==",
|
||||
"dependencies": {
|
||||
"eventemitter3": "^4.0.7",
|
||||
"path": "^0.12.7"
|
||||
}
|
||||
},
|
||||
"node_modules/picomatch": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
|
||||
|
|
@ -3176,6 +3200,14 @@
|
|||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
"integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=",
|
||||
"engines": {
|
||||
"node": ">= 0.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
|
|
@ -4115,12 +4147,25 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util": {
|
||||
"version": "0.10.4",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
|
||||
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
|
||||
"dependencies": {
|
||||
"inherits": "2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/util/node_modules/inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"node_modules/uuid": {
|
||||
"version": "3.4.0",
|
||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
|
||||
|
|
@ -6275,6 +6320,11 @@
|
|||
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
|
||||
"devOptional": true
|
||||
},
|
||||
"eventemitter3": {
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
|
||||
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||
|
|
@ -7183,6 +7233,15 @@
|
|||
"integrity": "sha512-fxNG2sQjHvlVAYmzBZS9YlDp6PTSSDwa98vkD4QgVDDCAo84z5X1t5XyJQ62ImdLXx5NdIIfihey6xpum9/gRQ==",
|
||||
"optional": true
|
||||
},
|
||||
"path": {
|
||||
"version": "0.12.7",
|
||||
"resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz",
|
||||
"integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=",
|
||||
"requires": {
|
||||
"process": "^0.11.1",
|
||||
"util": "^0.10.3"
|
||||
}
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
|
|
@ -7201,6 +7260,15 @@
|
|||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||
"optional": true
|
||||
},
|
||||
"phaser": {
|
||||
"version": "3.54.0",
|
||||
"resolved": "https://registry.npmjs.org/phaser/-/phaser-3.54.0.tgz",
|
||||
"integrity": "sha512-/1XVI6J2siS0OGwJez7vLbRjars1zb//EvJdYMVyd3wNTUf5DHrvYUj1f6TsEISr4vjnbrNtS66QIuPbGU8x6A==",
|
||||
"requires": {
|
||||
"eventemitter3": "^4.0.7",
|
||||
"path": "^0.12.7"
|
||||
}
|
||||
},
|
||||
"picomatch": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz",
|
||||
|
|
@ -7225,6 +7293,11 @@
|
|||
"integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==",
|
||||
"dev": true
|
||||
},
|
||||
"process": {
|
||||
"version": "0.11.10",
|
||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||
"integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
|
||||
},
|
||||
"process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
|
|
@ -7983,6 +8056,21 @@
|
|||
"punycode": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"util": {
|
||||
"version": "0.10.4",
|
||||
"resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz",
|
||||
"integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==",
|
||||
"requires": {
|
||||
"inherits": "2.0.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
}
|
||||
}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
"dependencies": {
|
||||
"fabric": "^4.3.1",
|
||||
"howler": "^2.2.1",
|
||||
"phaser": "^3.54.0",
|
||||
"sirv-cli": "^1.0.0"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
211
src/game/gameScene.js
Normal file
211
src/game/gameScene.js
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
import Phaser, { Animations } from "phaser";
|
||||
import { keys } from "./input";
|
||||
|
||||
const textureWidth = 100;
|
||||
|
||||
export class GameScene extends Phaser.Scene {
|
||||
constructor(map) {
|
||||
super({
|
||||
key: "GameScene",
|
||||
active: true,
|
||||
physics: {
|
||||
default: "arcade"
|
||||
}
|
||||
});
|
||||
/** @type {{
|
||||
background: string,
|
||||
sprite: string,
|
||||
offset: { x: number, y: nunber },
|
||||
size: { x: number, y: number },
|
||||
px: number,
|
||||
map: (string | null | {
|
||||
type: string,
|
||||
direction?: number
|
||||
})[][]
|
||||
}} */
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
preload() {
|
||||
this.load.setBaseURL();
|
||||
this.load.image("level1", "/sprite/level1.webp");
|
||||
this.load.image("lyre", "/sprite/lyre.webp");
|
||||
this.load.image("cloud", "/sprite/clouds.webp");
|
||||
this.load.spritesheet("wind", "/sprite/wind.png", { frameWidth: textureWidth });
|
||||
this.load.spritesheet("uriel", "/sprite/uriel.png", { frameWidth: textureWidth });
|
||||
this.load.spritesheet("michael", "/sprite/michael.png", { frameWidth: textureWidth });
|
||||
this.load.spritesheet("spawn", "/sprite/michael.png", { frameWidth: textureWidth });
|
||||
}
|
||||
|
||||
create() {
|
||||
this.input.on("keydown", function() {
|
||||
if (this.game.sound.context.state === 'suspended') {
|
||||
this.game.sound.context.resume();
|
||||
}
|
||||
});
|
||||
console.log(this.map);
|
||||
|
||||
this.container = this.add.container();
|
||||
this.container.width = this.map.size.x * this.map.px + this.map.offset.x * 2;
|
||||
this.container.height = this.map.size.y * this.map.px + this.map.offset.y * 2;
|
||||
this.grid = this.add.container(this.map.offset.x, this.map.offset.y);
|
||||
this.container.width = this.map.size.x * this.map.px;
|
||||
this.container.height = this.map.size.y * this.map.px;
|
||||
|
||||
this.background = this.add.image(this.container.width / 2, this.container.height / 2, this.map.background);
|
||||
this.container.add(this.background);
|
||||
this.container.add(this.grid);
|
||||
|
||||
/**
|
||||
* @type {{ type: string, direction?: number, sprite: Phaser.GameObjects.Sprite, animated: boolean }[][]}
|
||||
*/
|
||||
this.items = new Array(this.map.map.length);
|
||||
for(var y in this.map.map) {
|
||||
var row = this.map.map[y];
|
||||
|
||||
for(var x in row) {
|
||||
if(!this.items[x]) {
|
||||
this.items[x] = new Array(row.length);
|
||||
}
|
||||
var item = row[x];
|
||||
if(!item) {
|
||||
this.items[x][y] = null;
|
||||
continue;
|
||||
}
|
||||
if(typeof item === "string") {
|
||||
item = {
|
||||
type: item
|
||||
}
|
||||
}
|
||||
item.direction = item.direction ?? 0;
|
||||
y = parseInt(y);
|
||||
x = parseInt(x);
|
||||
if(item.type !== "barrier") {
|
||||
var type = item.type;
|
||||
if(type === "angel") type = this.map.sprite;
|
||||
if(this.textures.get(type).frameTotal > 1) {
|
||||
console.log("Generating animation for", item);
|
||||
var sprite = this.add.sprite(x * this.map.px, y * this.map.px);
|
||||
item.animated = true;
|
||||
if(!this.anims.exists(type)) {
|
||||
this.anims.create({
|
||||
key: type,
|
||||
frames: this.anims.generateFrameNumbers(type, {
|
||||
start: 0
|
||||
}),
|
||||
frameRate: 10,
|
||||
repeat: -1
|
||||
});
|
||||
}
|
||||
sprite.play(type);
|
||||
} else {
|
||||
var sprite = this.add.sprite(x * this.map.px, y * this.map.px, type);
|
||||
item.animated = false;
|
||||
}
|
||||
sprite.setRotation(item.direction * Math.PI / 2);
|
||||
this.grid.add(sprite);
|
||||
item.sprite = sprite;
|
||||
if(type !== item.type) {
|
||||
item.texture = type;
|
||||
}
|
||||
|
||||
if(item.type === "spawn") {
|
||||
this.player = item;
|
||||
this.player.x = x;
|
||||
this.player.y = y;
|
||||
}
|
||||
} else {
|
||||
item.sprite = null;
|
||||
}
|
||||
this.items[x][y] = item;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
move(fromX, fromY, toX, toY, onComplete = () => {}) {
|
||||
var item = this.items[fromX][fromY];
|
||||
this.tweens.add({
|
||||
targets: item.sprite,
|
||||
onComplete,
|
||||
x: toX * this.map.px,
|
||||
y: toY * this.map.px,
|
||||
duration: 400
|
||||
});
|
||||
this.items[fromX][fromY] = null;
|
||||
this.items[toX][toY] = item;
|
||||
}
|
||||
|
||||
underPlace = null;
|
||||
|
||||
getMovementFromDirection(direction) {
|
||||
switch(direction) {
|
||||
case 1:
|
||||
return { x: 0, y: -1 };
|
||||
case 2:
|
||||
return { x: 1, y: 0 };
|
||||
case 3:
|
||||
return { x: 0, y: 1 };
|
||||
case 4:
|
||||
return { x: -1, y: 0 };
|
||||
default:
|
||||
return { x: 0, y: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
movePlayer(moveX, moveY) {
|
||||
if(!this.canMove) return;
|
||||
var toX = this.player.x + moveX;
|
||||
var toY = this.player.y + moveY;
|
||||
console.log("Moving", this.player.x, this.player.y, toX, toY);
|
||||
if(toX > this.map.size.x - 1 || toX < 0 || toY > this.map.size.y - 1 || toY < 0) return;
|
||||
var underPlace = this.underPlace;
|
||||
this.underPlace = null;
|
||||
if(this.items[toX][toY]) {
|
||||
if(this.items[toX][toY].type === "wind") {
|
||||
this.underPlace = this.items[toX][toY];
|
||||
} else {
|
||||
if(this.items[toX][toY].type !== "lyre") return;
|
||||
if(toX + moveX > this.map.size.x - 1|| toX + moveX < 0 || toY + moveY > this.map.size.y - 1 || toY + moveY < 0) return;
|
||||
if(this.items[toX + moveX][toY + moveY] && this.items[toX + moveX][toY + moveY].type !== "wind") return;
|
||||
this.move(toX, toY, toX + moveX, toY + moveY);
|
||||
}
|
||||
}
|
||||
this.canMove = false;
|
||||
this.move(this.player.x, this.player.y, toX, toY, () => {
|
||||
this.canMove = true;
|
||||
this.items[this.player.x][this.player.y] = underPlace;
|
||||
this.player.x = toX;
|
||||
this.player.y = toY;
|
||||
if(this.underPlace) {
|
||||
var movement = this.getMovementFromDirection(this.underPlace.direction);
|
||||
this.movePlayer(movement.x, movement.y);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
canMove = true;
|
||||
|
||||
update() {
|
||||
// debug mode
|
||||
if(keys.wasKeyPressed("debug")) {
|
||||
console.log("Toggled debug mode");
|
||||
this.physics.config.debug = !this.physics.config.debug;
|
||||
if(this.physics.config.debug) this.physics.world.createDebugGraphic();
|
||||
this.physics.world.drawDebug = this.physics.config.debug;
|
||||
if(!this.physics.config.debug) this.physics.world.debugGraphic.destroy();
|
||||
}
|
||||
|
||||
this.container.x = this.cameras.main.width / 2 - this.container.width / 2;
|
||||
this.container.y = this.cameras.main.height / 2 - this.container.height / 2;
|
||||
|
||||
var movement = { x: 0, y: 0};
|
||||
if(keys.isKeyPressed("down")) movement.y++;
|
||||
if(keys.isKeyPressed("up")) movement.y--;
|
||||
if(keys.isKeyPressed("left")) movement.x--;
|
||||
if(keys.isKeyPressed("right")) movement.x++;
|
||||
|
||||
if((movement.x !== 0 && movement.y === 0) || (movement.x === 0 && movement.y !== 0)) {
|
||||
this.movePlayer(movement.x, movement.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,339 +1,48 @@
|
|||
import { fabric } from "fabric";
|
||||
import images from "./images";
|
||||
import { keys } from "./input";
|
||||
import { CANVAS, Game, Scale, WEBGL } from "phaser";
|
||||
import { GameScene } from "./gameScene";
|
||||
import { maps } from "./maps";
|
||||
import { Sprite } from "./sprite";
|
||||
|
||||
export function resize() {
|
||||
|
||||
/**
|
||||
* @typedef Sprite
|
||||
* @property {"sprite"} type
|
||||
* @property {number} spriteWidth
|
||||
* @property {number} spriteHeight
|
||||
* @property {number} spriteIndex
|
||||
* @property {number} frameTime
|
||||
*
|
||||
* @property {(element: HTMLImageElement, options: any) => Sprite} constructor
|
||||
*/
|
||||
|
||||
/** @type {HTMLCanvasElement} */
|
||||
var htmlcanvas;
|
||||
/** @type {fabric.StaticCanvas} */
|
||||
var canvas;
|
||||
export function setCanvas(htmlCanvas) {
|
||||
htmlcanvas = htmlCanvas;
|
||||
canvas = new fabric.StaticCanvas(htmlcanvas);
|
||||
canvas.backgroundColor = "#01021B";
|
||||
load();
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {Map<string, fabric.Object>}
|
||||
*/
|
||||
const objects = new Map;
|
||||
/**
|
||||
* @type {Map<string, { object: fabric.Object, piece: any }>}
|
||||
*/
|
||||
const points = new Map;
|
||||
var htmlcanvas;
|
||||
/** @type {Game} */
|
||||
var game;
|
||||
export function setCanvas(canvas) {
|
||||
htmlcanvas = canvas;
|
||||
var ctx = canvas.getContext("webgl2") || canvas.getContext("webgl");
|
||||
game = new Game({
|
||||
canvas: canvas,
|
||||
url: window.location.host,
|
||||
hideBanner: true,
|
||||
type: ctx ? WEBGL : CANVAS,
|
||||
context: ctx || canvas.getContext("2d"),
|
||||
customEnvironment: false,
|
||||
width: canvas.parentElement.clientWidth,
|
||||
height: canvas.parentElement.clientHeight,
|
||||
scale: {
|
||||
mode: Scale.RESIZE
|
||||
},
|
||||
physics: {
|
||||
default: "arcade",
|
||||
},
|
||||
title: "Heaventaker",
|
||||
version: "beta",
|
||||
scene: [new GameScene(map)],
|
||||
backgroundColor: "#01021B"
|
||||
});
|
||||
game.hideBanner = true;
|
||||
}
|
||||
|
||||
function load() {
|
||||
objects.set("loadingText", new fabric.Text("Loading", {
|
||||
left: canvas.getWidth() / 2,
|
||||
top: 0,
|
||||
fill: "white",
|
||||
textAlign: "center",
|
||||
originX: "center",
|
||||
fontFamily: "monospace"
|
||||
}))
|
||||
canvas.add(objects.get("loadingText"));
|
||||
images.load("level1", "/sprite/level1.webp");
|
||||
images.load("lyre", "/sprite/lyre.webp");
|
||||
images.load("wind", "/sprite/wind.png");
|
||||
images.load("cloud", "/sprite/clouds.webp");
|
||||
images.load("uriel", "/sprite/uriel.png");
|
||||
images.load("michael", "/sprite/michael.png");
|
||||
images.load("spawn", "/sprite/michael.png");
|
||||
images.startLoad();
|
||||
loading = true;
|
||||
export function stop() {
|
||||
game.destroy(false);
|
||||
}
|
||||
|
||||
var map;
|
||||
/** @type {{
|
||||
background: string,
|
||||
sprite: string,
|
||||
offset: { x: number, y: nunber },
|
||||
size: { x: number, y: number },
|
||||
px: number,
|
||||
map: string[][]
|
||||
}}
|
||||
*/
|
||||
var mapdata;
|
||||
var mapName;
|
||||
export function setMap(name) {
|
||||
if(mapName === name) return;
|
||||
mapdata = maps[name];
|
||||
mapName = name;
|
||||
|
||||
map = mapdata.map.map(m => m.map(piece => typeof piece === "string" && { type: piece } || piece));
|
||||
|
||||
console.table(map);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {{
|
||||
* object: fabric.Object,
|
||||
* property: string,
|
||||
* value: number,
|
||||
* onComplete: Function,
|
||||
* start: Date,
|
||||
* update: Function
|
||||
* }[]}
|
||||
*/
|
||||
var animations = [];
|
||||
|
||||
/**
|
||||
* Animates given property
|
||||
* @param {fabric.Object} object
|
||||
* @param {string} property
|
||||
* @param {number} value
|
||||
* @param {Function} onComplete
|
||||
*/
|
||||
function animate(object, property, value, onComplete) {
|
||||
const length = 400;
|
||||
animations.push({
|
||||
object,
|
||||
property,
|
||||
value,
|
||||
onComplete,
|
||||
start: new Date,
|
||||
initial: object[property],
|
||||
update() {
|
||||
var diff = (new Date - this.start) / length;
|
||||
var toUpdate = {
|
||||
originX: "center",
|
||||
originY: "center"
|
||||
};
|
||||
if(diff > 1) {
|
||||
onComplete();
|
||||
animations.splice(animations.indexOf(this), 1);
|
||||
toUpdate[this.property] = this.value
|
||||
this.object.set(toUpdate);
|
||||
return;
|
||||
}
|
||||
toUpdate[this.property] = (this.value - this.initial) * diff + this.initial;
|
||||
this.object.set(toUpdate);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves given object with animation
|
||||
* @param {fabric.Object} source
|
||||
* @param {number} fromX
|
||||
* @param {number} fromY
|
||||
* @param {number} toX
|
||||
* @param {number} toY
|
||||
* @param {Function} done
|
||||
*/
|
||||
function move(source, fromX, fromY, toX, toY, done = () => {}) {
|
||||
if(fromX !== toX) animate(source, "left", toX * mapdata.px + (mapdata.px / 2) + canvas.getWidth() / 2 - mapdata.size.x * mapdata.px / 2, done);
|
||||
if(fromY !== toY) animate(source, "top", (toY + 1) * mapdata.px + canvas.getHeight() / 2 - mapdata.size.y * mapdata.px / 2, done);
|
||||
// map[toY][toX] = map[fromY][fromX];
|
||||
// map[fromY][fromX] = undefined;
|
||||
}
|
||||
|
||||
export function resize() {
|
||||
canvas.setWidth(htmlcanvas.parentElement.clientWidth);
|
||||
canvas.setHeight(htmlcanvas.parentElement.clientHeight - 7);
|
||||
}
|
||||
|
||||
function getPieceAt(x, y) {
|
||||
return points.get(x + "-" + y)?.piece;
|
||||
}
|
||||
|
||||
var canMove = true;
|
||||
function tryMove(toX, toY, wind = false) {
|
||||
const player = objects.get("player");
|
||||
if(toX > mapdata.size.x - 1 || toY > mapdata.size.y - 1 || toX < 0 || toY < 0) return;
|
||||
var point = points.get(toX + "-" + toY);
|
||||
if(point) {
|
||||
if(point.piece.type !== "wind") {
|
||||
if(!wind && point.piece.type === "lyre") {
|
||||
points.delete(toX + "-" + toY);
|
||||
var diff = { x: toX - position.x, y: toY - position.y };
|
||||
points.set((toX + diff.x) + "-" + (toY + diff.y), point);
|
||||
move(point.object, toX, toY, toX + diff.x, toY + diff.y);
|
||||
} else return;
|
||||
}
|
||||
}
|
||||
if(!canMove) return;
|
||||
|
||||
canMove = false;
|
||||
move(player, position.x, position.y, toX, toY, () => {
|
||||
canMove = true;
|
||||
if(point && point.piece.type === "wind") {
|
||||
var res = moveInDirection(point.piece.direction);
|
||||
tryMove(toX + res.x, toY + res.y, true);
|
||||
} else {
|
||||
if(getPieceAt(toX + 1, toY)?.type === "angel" ||
|
||||
getPieceAt(toX, toY + 1)?.type === "angel" ||
|
||||
getPieceAt(toX - 1, toY)?.type === "angel" ||
|
||||
getPieceAt(toX, toY - 1)?.type === "angel") {
|
||||
console.log("found angel");
|
||||
}
|
||||
}
|
||||
});
|
||||
position.x = toX;
|
||||
position.y = toY;
|
||||
console.log(position, player.left / mapdata.px, player.top / mapdata.px);
|
||||
}
|
||||
|
||||
keys.addEventListener("keyDown", key => {
|
||||
console.log(key);
|
||||
const { x, y } = position;
|
||||
switch(key) {
|
||||
case "right":
|
||||
tryMove(x + 1, y);
|
||||
break;
|
||||
case "left":
|
||||
tryMove(x - 1, y);
|
||||
break;
|
||||
case "up":
|
||||
tryMove(x, y - 1);
|
||||
break;
|
||||
case "down":
|
||||
tryMove(x, y + 1);
|
||||
break;
|
||||
default:
|
||||
console.error("Unrecognized key", key);
|
||||
}
|
||||
});
|
||||
|
||||
function offsetDirection(direction) {
|
||||
switch(direction) {
|
||||
case 1:
|
||||
return { x: 1, y: 0 };
|
||||
case 2:
|
||||
return { x: 1, y: 1 };
|
||||
case 3:
|
||||
return { x: 0, y: 1 };
|
||||
case 4:
|
||||
default:
|
||||
return { x: 0, y: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
function moveInDirection(direction) {
|
||||
switch(direction) {
|
||||
case 1:
|
||||
return { x: 0, y: -1 };
|
||||
case 2:
|
||||
return { x: 1, y: 0 };
|
||||
case 3:
|
||||
return { x: 0, y: 1 };
|
||||
case 4:
|
||||
return { x: -1, y: 0 };
|
||||
default:
|
||||
return { x: 0, y: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
var position = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
|
||||
var resizeDirty = true;
|
||||
window.onresize = () => {
|
||||
resizeDirty = true;
|
||||
}
|
||||
|
||||
var loading = true;
|
||||
export function render(delta) {
|
||||
if(images.areAllLoaded() && loading) {
|
||||
loading = false;
|
||||
|
||||
objects.set("background", new fabric.Image(images.get(mapdata.background), {
|
||||
left: canvas.getWidth() / 2,
|
||||
top: canvas.getHeight() / 2,
|
||||
originX: "center",
|
||||
originY: "center",
|
||||
}));
|
||||
|
||||
canvas.add(objects.get("background"));
|
||||
|
||||
for(const y in map) {
|
||||
const pieces = map[y];
|
||||
for(const x in pieces) {
|
||||
const piece = pieces[x];
|
||||
if(!piece || piece.type === "barrier") {
|
||||
objects.set("object-" + x + "-" + y, null);
|
||||
continue;
|
||||
}
|
||||
let type = piece.type;
|
||||
if(type === "angel") type = mapName;
|
||||
/** @type {fabric.Image || Sprite} */
|
||||
let object;
|
||||
if(piece.type === "angel" || piece.type === "spawn" || piece.type === "wind") {
|
||||
object = new Sprite(images.get(type), {
|
||||
spriteWidth: 100,
|
||||
spriteHeight: 100
|
||||
});
|
||||
object.play();
|
||||
if(piece.type === "spawn") {
|
||||
objects.set("player", object);
|
||||
position = { x: parseInt(x), y: parseInt(y) };
|
||||
console.log(position);
|
||||
}
|
||||
} else {
|
||||
object = new fabric.Image(images.get(type));
|
||||
}
|
||||
object.set({
|
||||
originX: "left",
|
||||
originY: "top",
|
||||
left: parseInt(x) * mapdata.px + (mapdata.px / 2) + canvas.getWidth() / 2 - (mapdata.offset.x / 2),
|
||||
top: parseInt(y) * mapdata.px + canvas.getHeight() / 2 - (mapdata.offset.y / 2) - 200,
|
||||
angle: 90 * (piece.direction || 0)
|
||||
});
|
||||
if(piece.type !== "spawn") {
|
||||
points.set(x + "-" + y, { object, piece });
|
||||
}
|
||||
canvas.add(object);
|
||||
}
|
||||
}
|
||||
|
||||
canvas.remove(objects.get("loadingText"));
|
||||
} else if(loading) return canvas.renderAll();
|
||||
|
||||
var background = objects.get("background");
|
||||
background.set({
|
||||
left: canvas.getWidth() / 2,
|
||||
top: canvas.getHeight() / 2
|
||||
});
|
||||
if(resizeDirty) {
|
||||
for(var [name, point] of points) {
|
||||
if(!point) {
|
||||
console.log(name, points);
|
||||
continue;
|
||||
}
|
||||
var [x, y] = name.split("-");
|
||||
var offset = offsetDirection(point.piece.direction);
|
||||
x = parseInt(x) + offset.x;
|
||||
y = parseInt(y) + offset.y;
|
||||
point.object.set({
|
||||
left: parseInt(x) * mapdata.px + canvas.getWidth() / 2 - mapdata.size.x * mapdata.px / 2,
|
||||
top: parseInt(y) * mapdata.px + (mapdata.px / 2) + canvas.getHeight() / 2 - mapdata.size.y * mapdata.px / 2,
|
||||
});
|
||||
}
|
||||
resizeDirty = false;
|
||||
}
|
||||
var player = objects.get("player");
|
||||
player.set({
|
||||
left: position.x * mapdata.px + (mapdata.px / 2) + canvas.getWidth() / 2 - mapdata.size.x * mapdata.px / 2,
|
||||
top: (position.y + 1) * mapdata.px + canvas.getHeight() / 2 - mapdata.size.y * mapdata.px / 2
|
||||
});
|
||||
for(var animation of animations) {
|
||||
animation.update();
|
||||
}
|
||||
canvas.renderAll();
|
||||
/** @type {string} */
|
||||
var mapname;
|
||||
export function setMap(newmap) {
|
||||
mapname = newmap;
|
||||
map = maps[mapname];
|
||||
}
|
||||
|
|
@ -2,7 +2,8 @@ const keybinds = {
|
|||
"right": "ArrowRight",
|
||||
"left": "ArrowLeft",
|
||||
"up": "ArrowUp",
|
||||
"down": "ArrowDown"
|
||||
"down": "ArrowDown",
|
||||
"debug": "f3"
|
||||
};
|
||||
|
||||
class KeyHandler {
|
||||
|
|
@ -21,6 +22,7 @@ class KeyHandler {
|
|||
this.addHandlers();
|
||||
this.mounted = false;
|
||||
this.mountHandlers();
|
||||
this.keysWasPressed = new Map();
|
||||
/** @type {Map<string, Function[]>} */
|
||||
this.listeners = new Map();
|
||||
}
|
||||
|
|
@ -73,10 +75,16 @@ class KeyHandler {
|
|||
}
|
||||
addHandlers() {
|
||||
this.addDocumentEventListener("keydown", (ev) => {
|
||||
this.pressKeyBind(ev.key);
|
||||
if(this.pressKeyBind(ev.key)) {
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
};
|
||||
});
|
||||
this.addDocumentEventListener("keyup", (ev) => {
|
||||
this.unpressKeyBind(ev.key);
|
||||
if(this.unpressKeyBind(ev.key)) {
|
||||
ev.preventDefault();
|
||||
return false;
|
||||
};
|
||||
});
|
||||
// this.addDocumentEventListener("mousemove", (ev) => {
|
||||
// var rotation = Math.atan2(ev.pageY - window.innerHeight / 2, ev.pageX - window.innerWidth / 2) * 180 / Math.PI;
|
||||
|
|
@ -137,12 +145,14 @@ class KeyHandler {
|
|||
pressKeyBind(key) {
|
||||
var kb = this.getKeyBind(key);
|
||||
if(!kb) return null;
|
||||
this.keysWasPressed.set(kb, true);
|
||||
this.emit("keyDown", kb);
|
||||
return this.pressKey(kb);
|
||||
}
|
||||
unpressKeyBind(key) {
|
||||
var kb = this.getKeyBind(key);
|
||||
if(!kb) return null;
|
||||
this.keysWasPressed.delete(kb);
|
||||
this.emit("keyUp", kb);
|
||||
return this.unpressKey(kb);
|
||||
}
|
||||
|
|
@ -152,7 +162,7 @@ class KeyHandler {
|
|||
return this.setAxis(kb, value);
|
||||
}
|
||||
getKeyBind(key) {
|
||||
var index = Object.values(keybinds).indexOf(key);
|
||||
var index = Object.values(keybinds).map(t => t.toLowerCase()).indexOf(key.toLowerCase());
|
||||
if(index === -1) return null;
|
||||
return Object.keys(keybinds)[index];
|
||||
}
|
||||
|
|
@ -160,7 +170,13 @@ class KeyHandler {
|
|||
isKeyPressed(key) {
|
||||
return this.keys.has(key) && this.keys.get(key) > this.treshold;
|
||||
}
|
||||
|
||||
|
||||
wasKeyPressed(key) {
|
||||
var was = this.keysWasPressed.has(key);
|
||||
this.keysWasPressed.delete(key);
|
||||
return was;
|
||||
}
|
||||
|
||||
getAxis(key) {
|
||||
if(!this.axis.has(key)) return;
|
||||
var val = this.axis.get(key);
|
||||
|
|
|
|||
|
|
@ -24,10 +24,10 @@ function wind(direction) {
|
|||
export const maps = {
|
||||
uriel: {
|
||||
background: "level1",
|
||||
sprite: "/sprite/uriel.gif",
|
||||
sprite: "uriel",
|
||||
offset: { // map offset for alignment
|
||||
x: 90,
|
||||
y: 0
|
||||
x: 60,
|
||||
y: 100
|
||||
},
|
||||
size: { // map size (per block)
|
||||
x: 5,
|
||||
|
|
@ -36,7 +36,7 @@ export const maps = {
|
|||
px: 100, // block size
|
||||
map: [
|
||||
["barrier", "barrier", "angel" , "barrier", "barrier"],
|
||||
["barrier", "barrier", null , null , "barrier"],
|
||||
["barrier", "barrier", null , "barrier", "barrier"],
|
||||
[null , null , wind(1) , null , null ],
|
||||
[null , "lyre" , wind(1) , null , null ],
|
||||
["lyre" , null , "cloud" , null , null ],
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
import { dialog } from "../stores/dialog.js";
|
||||
import { characters } from "../stores/characters.js";
|
||||
import { onMount } from "svelte";
|
||||
import { setCanvas, render, setMap, resize } from "../game";
|
||||
import { setCanvas, setMap, resize, stop } from "../game";
|
||||
|
||||
export var current;
|
||||
|
||||
|
|
@ -36,12 +36,9 @@
|
|||
setMap(dialog[current].map);
|
||||
setCanvas(canvas);
|
||||
resize();
|
||||
function update(delta) {
|
||||
render(delta);
|
||||
frame = requestAnimationFrame(update);
|
||||
return () => {
|
||||
stop();
|
||||
}
|
||||
var frame = requestAnimationFrame(update);
|
||||
return () => cancelAnimationFrame(frame);
|
||||
});
|
||||
|
||||
$: setMap(dialog[current].map);
|
||||
|
|
|
|||
Loading…
Reference in a new issue