commit 9bf0b55f3351c18901b5e30b544f8cea67283cc1 Author: Brian Fertig Date: Sat Aug 30 20:38:17 2025 -0600 feat: Implement basic level 1 with tilemap, enemies, pathfinding and wave system - Added level 1 assets (tilemap, terrain, enemy sprites) - Implemented Level1 scene with tilemap loading and collision detection - Integrated EasyStar.js for enemy pathfinding between spawn and end points - Created wave manager system to handle enemy spawning schedules - Added basic enemy configuration and animation support - Set up game structure with Phaser 3 framework - Added web server startup script for local development This commit establishes the foundational level 1 gameplay including map rendering, collision detection, enemy spawning mechanics, and pathfinding behavior using EasyStar.js for AI movement. diff --git a/assets/basic-enemies.png b/assets/basic-enemies.png new file mode 100644 index 0000000..5c18d34 Binary files /dev/null and b/assets/basic-enemies.png differ diff --git a/assets/basic-enemies.psd b/assets/basic-enemies.psd new file mode 100644 index 0000000..b8c199a Binary files /dev/null and b/assets/basic-enemies.psd differ diff --git a/assets/josh-life.png b/assets/josh-life.png new file mode 100644 index 0000000..a42a474 Binary files /dev/null and b/assets/josh-life.png differ diff --git a/assets/level1.json b/assets/level1.json new file mode 100644 index 0000000..64092fb --- /dev/null +++ b/assets/level1.json @@ -0,0 +1,111 @@ +{ "compressionlevel":-1, + "height":9, + "infinite":true, + "layers":[ + { + "chunks":[ + { + "data":[2, 1, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 1, 2, 1, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 1, 1, 1, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":16, + "width":16, + "x":0, + "y":0 + }], + "height":16, + "id":1, + "name":"main", + "opacity":1, + "startx":0, + "starty":0, + "type":"tilelayer", + "visible":true, + "width":16, + "x":0, + "y":0 + }, + { + "chunks":[ + { + "data":[0, 0, 16, 0, 16, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 16, 0, 0, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 16, 16, 0, 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + "height":16, + "width":16, + "x":0, + "y":0 + }], + "height":16, + "id":2, + "name":"platforms", + "opacity":1, + "startx":0, + "starty":0, + "type":"tilelayer", + "visible":true, + "width":16, + "x":0, + "y":0 + }], + "nextlayerid":3, + "nextobjectid":1, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.11.2", + "tileheight":200, + "tilesets":[ + { + "columns":5, + "firstgid":1, + "image":"terrain.png", + "imageheight":1000, + "imagewidth":1000, + "margin":0, + "name":"terrain", + "spacing":0, + "tilecount":25, + "tileheight":200, + "tiles":[ + { + "id":1, + "properties":[ + { + "name":"collides", + "type":"bool", + "value":true + }] + }], + "tilewidth":200 + }], + "tilewidth":200, + "type":"map", + "version":"1.10", + "width":16 +} \ No newline at end of file diff --git a/assets/terrain.png b/assets/terrain.png new file mode 100644 index 0000000..2cb5785 Binary files /dev/null and b/assets/terrain.png differ diff --git a/assets/terrain.psd b/assets/terrain.psd new file mode 100644 index 0000000..ab62e81 Binary files /dev/null and b/assets/terrain.psd differ diff --git a/assets/tilesets/level1.tmx b/assets/tilesets/level1.tmx new file mode 100644 index 0000000..8d2b4ea --- /dev/null +++ b/assets/tilesets/level1.tmx @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + +2,1,2,2,2,2,2,2,0,0,0,0,0,0,0,0, +2,1,2,1,1,1,2,2,0,0,0,0,0,0,0,0, +2,1,1,1,2,1,1,2,0,0,0,0,0,0,0,0, +2,2,2,2,2,2,1,2,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + + + + + +0,0,16,0,16,0,16,0,0,0,0,0,0,0,0,0, +0,0,16,0,0,0,16,0,0,0,0,0,0,0,0,0, +16,0,0,0,16,0,0,0,0,0,0,0,0,0,0,0, +0,16,16,0,16,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + + + diff --git a/index.html b/index.html new file mode 100644 index 0000000..dbd1be8 --- /dev/null +++ b/index.html @@ -0,0 +1,17 @@ + + + + + Alien Rush + + + +
+ + + + + \ No newline at end of file diff --git a/src/EasyStar.js b/src/EasyStar.js new file mode 100644 index 0000000..281537c --- /dev/null +++ b/src/EasyStar.js @@ -0,0 +1,25 @@ +/*! + * @license + * The MIT License (MIT) + * + * Copyright (c) 2012-2020 Bryce Neal + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +var EasyStar=function(e){var o={};function r(t){if(o[t])return o[t].exports;var n=o[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,r),n.l=!0,n.exports}return r.m=e,r.c=o,r.d=function(t,n,e){r.o(t,n)||Object.defineProperty(t,n,{enumerable:!0,get:e})},r.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},r.t=function(n,t){if(1&t&&(n=r(n)),8&t)return n;if(4&t&&"object"==typeof n&&n&&n.__esModule)return n;var e=Object.create(null);if(r.r(e),Object.defineProperty(e,"default",{enumerable:!0,value:n}),2&t&&"string"!=typeof n)for(var o in n)r.d(e,o,function(t){return n[t]}.bind(null,o));return e},r.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return r.d(n,"a",n),n},r.o=function(t,n){return Object.prototype.hasOwnProperty.call(t,n)},r.p="/bin/",r(r.s=0)}([function(t,n,e){var P={},M=e(1),_=e(2),A=e(3);t.exports=P;var E=1;P.js=function(){var c,i,f,s=1.4,p=!1,u={},o={},r={},l={},a=!0,h={},d=[],y=Number.MAX_VALUE,v=!1;this.setAcceptableTiles=function(t){t instanceof Array?f=t:!isNaN(parseFloat(t))&&isFinite(t)&&(f=[t])},this.enableSync=function(){p=!0},this.disableSync=function(){p=!1},this.enableDiagonals=function(){v=!0},this.disableDiagonals=function(){v=!1},this.setGrid=function(t){c=t;for(var n=0;nc[0].length-1||n>c.length-1||e>c[0].length-1||o>c.length-1)throw new Error("Your start or end point is outside the scope of your grid.");if(t!==e||n!==o){for(var s=c[o][e],u=!1,l=0;l>1])<0;)t[e]=i,e=s;return t[e]=r},f=function(t,n,e){var o,r,i,s,u;for(null==e&&(e=p),r=t.length,i=t[u=n],o=2*n+1;o { + if (currentIndex >= path.length - 1) return; // Reached target + + const nextPoint = path[++currentIndex]; + + // Move josh to the next point + this.tweens.add({ + targets: this.josh, + x: nextPoint.x * 200 + 100, + y: nextPoint.y * 200 + 100, + duration: 2000, + onComplete: moveNextStep + }); + }; + + moveNextStep(); + } + + update(time, delta) { + this.waveManager.update(time, delta); + } +} \ No newline at end of file diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..22db7a2 --- /dev/null +++ b/src/main.js @@ -0,0 +1,29 @@ +import { Level1 } from './levels/level1.js'; + +const GAME_CONFIG = { + type: Phaser.AUTO, + scale: { + mode: Phaser.Scale.FIT, + autoCenter: Phaser.Scale.CENTER_BOTH, + width: 1600, + height: 900, + parent: 'game-container' + }, + parent: 'game-container', + backgroundColor: '#bb7432ff', + scene: [ + Level1 + ], + physics: { + default: 'arcade', + arcade: { + gravity: { y: 0 }, + debug: false + } + } +}; + +// Create the game instance +const game = new Phaser.Game(GAME_CONFIG); + +console.log('Alien Rush game initialized successfully!'); diff --git a/src/support/enemies.js b/src/support/enemies.js new file mode 100644 index 0000000..7675757 --- /dev/null +++ b/src/support/enemies.js @@ -0,0 +1,63 @@ +import { ENEMIES_CONFIG } from "./enemiesConfig.js"; + +export class Enemies { + + constructor(scene, type, x, y, path) { + this.scene = scene; + this.type = type; + this.x = x; + this.y = y; + this.path = path; + this.spread = ENEMIES_CONFIG[type].spread; + this.speedLow = ENEMIES_CONFIG[type].speedLow; + this.speedHigh = ENEMIES_CONFIG[type].speedHigh; + this.baseSprite = ENEMIES_CONFIG[type].spriteStart; + + this.spawnEnemy(); + } + + spawnEnemy() { + const randX = Phaser.Math.Between(-this.spread, this.spread); + const randY = Phaser.Math.Between(-this.spread, this.spread); + const randSpeed = Phaser.Math.Between(this.speedLow, this.speedHigh); + const spawnX = (this.x * 200) + 100 + randX; + const spawnY = (this.y * 200) + 100 + randY; + + // Create enemy and store reference + const enemy = this.scene.add.sprite(spawnX, spawnY, ENEMIES_CONFIG[this.type].spriteSheet, ENEMIES_CONFIG[this.type].spriteStart); + + // Create Animations + this.createAnim('side', ENEMIES_CONFIG[this.type].spriteStart, ENEMIES_CONFIG[this.type].spriteStart+2); + this.createAnim('up', ENEMIES_CONFIG[this.type].spriteStart+6, ENEMIES_CONFIG[this.type].spriteStart+7); + this.createAnim('down', ENEMIES_CONFIG[this.type].spriteStart+3, ENEMIES_CONFIG[this.type].spriteStart+5); + this.createAnim('die', ENEMIES_CONFIG[this.type].spriteStart+8, ENEMIES_CONFIG[this.type].spriteStart+9, 0); + + enemy.props = { + 'offsetX': randX, + 'offsetY': randY, + 'path': this.path, + 'pathPhase': 0, + 'speed': randSpeed, + 'health': ENEMIES_CONFIG[this.type].health, + 'type': this.type + }; + + this.scene.enemies.add(enemy); + + enemy.play(`${this.type}-side`); + } + + createAnim(type, start, end, repeat = -1) { + if (!this.scene.anims.get(`${this.type}-${type}`)) { + this.scene.anims.create({ + key: `${this.type}-${type}`, + frames: this.scene.anims.generateFrameNumbers(ENEMIES_CONFIG[this.type].spriteSheet, { + start: start, + end: end, + }), + frameRate: 5, + repeat: repeat + }); + } + } +} \ No newline at end of file diff --git a/src/support/enemiesConfig.js b/src/support/enemiesConfig.js new file mode 100644 index 0000000..e431984 --- /dev/null +++ b/src/support/enemiesConfig.js @@ -0,0 +1,18 @@ +export const ENEMIES_CONFIG = { + 'basic1': { + 'spread': 25, + 'health': 100, + 'speedLow': 25, + 'speedHigh': 35, + 'spriteStart': 0, + 'spriteSheet': 'basic-enemies' + }, + 'basic2': { + 'spread': 0, + 'health': 300, + 'speedLow': 45, + 'speedHigh': 55, + 'spriteStart': 0, + 'spriteSheet': 'basic-enemies' + } +} \ No newline at end of file diff --git a/src/support/waveConfig.js b/src/support/waveConfig.js new file mode 100644 index 0000000..3c6a72d --- /dev/null +++ b/src/support/waveConfig.js @@ -0,0 +1,42 @@ +export const WAVE_CONFIG = { + // Level + 1: { + //Spawn Point + spawnX: 1, + spawnY: 0, + endX: 6, + endY: 3, + // Wave + 1: { + // Schedule + 1: { + begin: 0, + basic1: 5 + }, + 2: { + begin: 15, + basic1: 1 + }, + 3: { + begin: 30, + basic1: 5 + } + }, + // Wave + 2: { + // Schedule + 1: { + begin: 0, + basic1: 5 + }, + 2: { + begin: 15, + basic1: 5 + }, + 3: { + begin: 30, + basic1: 5 + } + } + } +} \ No newline at end of file diff --git a/src/support/waveManager.js b/src/support/waveManager.js new file mode 100644 index 0000000..5fccff8 --- /dev/null +++ b/src/support/waveManager.js @@ -0,0 +1,194 @@ +import { WAVE_CONFIG } from './waveConfig.js' +import { Enemies } from './enemies.js' + +export class WaveManager { + + constructor(scene, level, wave) { + this.scene = scene; + this.level = level; + this.wave = wave; + this.schedule = 0; + this.scheduleInfo = null; + this.spawnX = WAVE_CONFIG[this.level].spawnX; + this.spawnY = WAVE_CONFIG[this.level].spawnY; + this.endX = WAVE_CONFIG[this.level].endX; + this.endY = WAVE_CONFIG[this.level].endY; + this.path = null; + + this.waveTimer = 0; + this.waveScheduleStartTime(); + } + + waveScheduleStartTime() { + this.schedule++; + this.scheduleInfo = WAVE_CONFIG[this.level][this.wave][this.schedule] + this.waveStart = this.scheduleInfo.begin * 1000; + } + + nextWave() { + this.wave++; + this.waveTimer = 0; + this.schedule = 0; + this.waveScheduleStartTime(); + } + + gridToLocation(num, offset = 0) { + return num * 200 + 100 + offset; + } + + update(time, delta) { + this.waveTimer += delta; + + // Handle Enemy Pathing + this.scene.enemies.children.iterate((enemy) => { + const path = enemy.props.path; + const pathPhase = enemy.props.pathPhase; + const speed = enemy.props.speed; + const offsetX = enemy.props.offsetX; + const offsetY = enemy.props.offsetY; + + // Only move if we have a valid path and pathPhase + if (path && pathPhase !== undefined) { + // Calculate movement for this frame + const segmentSpeed = speed; // Normalize by delta time + + // Get current and next points in the path + const currentPoint = path[pathPhase]; + const nextPoint = path[pathPhase + 1]; + + if (currentPoint && nextPoint) { + // Calculate direction vector from current to next point + const dx = this.gridToLocation(nextPoint.x, offsetX) - this.gridToLocation(currentPoint.x, offsetX); + const dy = this.gridToLocation(nextPoint.y, offsetY) - this.gridToLocation(currentPoint.y, offsetY); + const distance = Math.sqrt(dx * dx + dy * dy); + + // Normalize the direction + if (distance > 0) { + const normalizedDx = dx / distance; + const normalizedDy = dy / distance; + + const velocX = normalizedDx * segmentSpeed; + const velocY = normalizedDy * segmentSpeed; + // Move towards next point + enemy.body.setVelocity(velocX, velocY); + + if (Math.abs(velocY) > Math.abs(velocX)) { + if (velocY > 0) { + enemy.play(`${enemy.props.type}-down`, true); + } else { + enemy.play(`${enemy.props.type}-up`, true); + } + } else { + if (velocX > 0) { + enemy.play(`${enemy.props.type}-side`, true); + enemy.setFlipX(true); + } else { + enemy.play(`${enemy.props.type}-side`, true); + enemy.setFlipX(false); + } + } + + // Check if we've reached the next point + const distToNextPoint = Math.sqrt( + Math.pow(enemy.x - this.gridToLocation(nextPoint.x, offsetX), 2) + + Math.pow(enemy.y - this.gridToLocation(nextPoint.y, offsetY), 2) + ); + + if (distToNextPoint < segmentSpeed * 0.5) { // Threshold for reaching point + enemy.props.pathPhase++; // Move to next path segment + + // If we've reached the end of the path, remove the enemy or handle accordingly + if (enemy.props.pathPhase >= path.length - 1) { + // Enemy reached destination - you might want to handle this differently + enemy.body.setVelocity(0, 0); + // Remove enemy from scene or mark for removal + } + } + } else { + // We're at the last point in the path + enemy.body.setVelocity(0, 0); + } + } else if (currentPoint && !nextPoint) { + // Last point in path - stop moving + enemy.body.setVelocity(0, 0); + } + } + }); + + // Handle Waves and Schedules + if (this.waveTimer >= this.waveStart) { + console.log('Wave',this.wave,'Schedule',this.schedule); + // Make path synchronous + this.makePath().then(() => { + // Spawn enemies after path is ready + this.spawnSchedule(); + + if (WAVE_CONFIG[this.level][this.wave].hasOwnProperty(this.schedule + 1)) { + this.waveScheduleStartTime(); + } else if (WAVE_CONFIG[this.level].hasOwnProperty(this.wave+1)) { + this.nextWave(); + } else { + console.log('LEVEL COMPLETE'); + } + }); + } + + + } + + spawnSchedule() { + if (this.scheduleInfo.hasOwnProperty('basic1')) { + console.log('Spawn',this.scheduleInfo.basic1,'Basic1 enemies'); + for (let e = 0; e < this.scheduleInfo.basic1; e++) { + const enemy = new Enemies(this.scene, 'basic1', this.spawnX, this.spawnY, this.path); + } + } + } + + makePath() { + return new Promise((resolve) => { + this.easyStar = new EasyStar.js(); + + // Set up the grid for pathfinding + const width = this.scene.levelMap.width; + const height = this.scene.levelMap.height; + const grid = []; + + // Create a grid based on collision data + for (let y = 0; y < height; y++) { + grid[y] = []; + for (let x = 0; x < width; x++) { + // Check if the tile at this position is colliding + const tile = this.scene.mainLayer.getTileAt(x, y); + if (tile && tile.properties.collides) { + grid[y][x] = 1; // Blocked + } else { + grid[y][x] = 0; // Free space + } + } + } + this.easyStar.setGrid(grid); + + this.easyStar.setAcceptableTiles([0]); // Only allow movement on tiles with value 0 + + this.easyStar.findPath( + this.spawnX, + this.spawnY, + this.endX, + this.endY, + (path) => { + if (path === null) { + console.log("No path found"); + this.path = null; + } else { + this.path = path; + } + resolve(); + } + ); + + this.easyStar.calculate(); + }); + } + +} \ No newline at end of file diff --git a/start_web.bat b/start_web.bat new file mode 100644 index 0000000..f266b01 --- /dev/null +++ b/start_web.bat @@ -0,0 +1 @@ +python -m http.server 8000 \ No newline at end of file