feat: agent
This commit is contained in:
parent
3388743f4a
commit
fe69b98a71
@ -13,6 +13,8 @@
|
|||||||
<!-- Modules -->
|
<!-- Modules -->
|
||||||
<script src="modules/floor.js"></script>
|
<script src="modules/floor.js"></script>
|
||||||
<script src="modules/grid.js"></script>
|
<script src="modules/grid.js"></script>
|
||||||
|
<script src="modules/agentController.js"></script>
|
||||||
|
<script src="modules/agent.js"></script>
|
||||||
|
|
||||||
<!-- Main script file -->
|
<!-- Main script file -->
|
||||||
<script src="main.js"></script>
|
<script src="main.js"></script>
|
||||||
|
@ -6,4 +6,5 @@ window.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
const floor = new Floor(floorCanvas);
|
const floor = new Floor(floorCanvas);
|
||||||
const grid = new Grid(gridCanvas);
|
const grid = new Grid(gridCanvas);
|
||||||
|
const agent = new Agent(agentCanvas);
|
||||||
});
|
});
|
13
src/modules/agent.js
Normal file
13
src/modules/agent.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
class Agent extends AgentController {
|
||||||
|
constructor(canvas) {
|
||||||
|
super(canvas);
|
||||||
|
|
||||||
|
let { x, y } = Grid.instance.randomPlace();
|
||||||
|
this.moveTo(x, y);
|
||||||
|
|
||||||
|
this.onDestinationReached(() => {
|
||||||
|
let { x, y } = Grid.instance.randomPlace();
|
||||||
|
this.moveTo(x, y);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
146
src/modules/agentController.js
Normal file
146
src/modules/agentController.js
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
class AgentController {
|
||||||
|
constructor(canvas) {
|
||||||
|
this.ctx = canvas.getContext('2d');
|
||||||
|
this.events = {
|
||||||
|
'ON_DESTINATION_REACHED': [],
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setCanvasSize(canvas);
|
||||||
|
|
||||||
|
this.position = { x: 6, y: 0 };
|
||||||
|
|
||||||
|
this.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
setCanvasSize (canvas) {
|
||||||
|
canvas.width = 2000;
|
||||||
|
canvas.height = 900;
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
this.clearCanvas();
|
||||||
|
if (this.currentPath) {
|
||||||
|
this.drawPath(this.currentPath);
|
||||||
|
this.updateAgentPosition();
|
||||||
|
}
|
||||||
|
this.drawAgent();
|
||||||
|
|
||||||
|
requestAnimationFrame(this.update.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
updateAgentPosition() {
|
||||||
|
const speed = 30;
|
||||||
|
if (!this.currentPathIndex) {
|
||||||
|
this.currentPathIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let nearestPoint = this.currentPath[this.currentPathIndex];
|
||||||
|
|
||||||
|
if (nearestPoint) {
|
||||||
|
this.position = {
|
||||||
|
x: this.position.x + (Math.sign(nearestPoint.x - this.position.x)/speed),
|
||||||
|
y: this.position.y + (Math.sign(nearestPoint.y - this.position.y)/speed)
|
||||||
|
}
|
||||||
|
if (Math.abs(nearestPoint.x - this.position.x) < 0.001 && Math.abs(nearestPoint.y - this.position.y) < 0.001) {
|
||||||
|
nearestPoint = this.currentPath[++this.currentPathIndex];
|
||||||
|
if (!nearestPoint) {
|
||||||
|
this.position = {
|
||||||
|
x: Math.round(this.position.x),
|
||||||
|
y: Math.round(this.position.y)
|
||||||
|
}
|
||||||
|
this.currentPath = [];
|
||||||
|
this.currentPathIndex = 0;
|
||||||
|
this.events.ON_DESTINATION_REACHED.forEach(func => func());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
moveTo(x, y) {
|
||||||
|
this.currentPath = this.findPathTo(x, y, this.position.x, this.position.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
drawPath(path) {
|
||||||
|
for(let i = 0; i < path.length - 1; i++) {
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.strokeWidth = 5;
|
||||||
|
this.ctx.strokeStyle = 'red';
|
||||||
|
this.ctx.moveTo(path[i].x * 100 + 50, path[i].y * 100 + 50);
|
||||||
|
this.ctx.lineTo(path[i + 1].x * 100 + 50, path[i + 1].y * 100 + 50);
|
||||||
|
this.ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawAgent() {
|
||||||
|
const {x, y} = this.position;
|
||||||
|
const offset = 5;
|
||||||
|
this.ctx.clearRect((x * 100) + (offset), (y * 100) + (offset), 100 - (offset * 2), 100 - (offset * 2));
|
||||||
|
this.roundRect((x * 100) + (offset), (y * 100) + (offset), 100 - (offset * 2), 100 - (offset * 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
findPathTo(dx, dy, sx, sy) {
|
||||||
|
const grid = JSON.parse(JSON.stringify(Grid.instance.grid));
|
||||||
|
const queue = [];
|
||||||
|
const lastPoint = [];
|
||||||
|
|
||||||
|
if (grid[dx][dy] === GRID_FIELD_TYPE.SHELF) {
|
||||||
|
if(grid[dx][dy + 1] === GRID_FIELD_TYPE.PATH) {
|
||||||
|
lastPoint.push({ x: dx, y: dy, options: { isShelf: true } });
|
||||||
|
dy++;
|
||||||
|
} else if(grid[dx][dy - 1] === GRID_FIELD_TYPE.PATH) {
|
||||||
|
lastPoint.push({ x: dx, y: dy, options: { isShelf: true } });
|
||||||
|
dy--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
queue.push({ x: sx, y: sy, path: [] });
|
||||||
|
|
||||||
|
while(queue.length) {
|
||||||
|
const { x, y, path } = queue.shift();
|
||||||
|
path.push({ x, y });
|
||||||
|
|
||||||
|
if (x === dx && y === dy) {
|
||||||
|
return [...path, ...lastPoint];
|
||||||
|
}
|
||||||
|
if (grid[x][y - 1] === GRID_FIELD_TYPE.PATH) {
|
||||||
|
queue.push({ x, y: y - 1, path: [...path] });
|
||||||
|
}
|
||||||
|
if (grid[x][y + 1] === GRID_FIELD_TYPE.PATH) {
|
||||||
|
queue.push({ x, y: y + 1, path: [...path] });
|
||||||
|
}
|
||||||
|
if (grid[x - 1] && grid[x - 1][y] === GRID_FIELD_TYPE.PATH) {
|
||||||
|
queue.push({ x: x - 1, y, path: [...path] });
|
||||||
|
}
|
||||||
|
if (grid[x + 1] && grid[x + 1][y] === GRID_FIELD_TYPE.PATH) {
|
||||||
|
queue.push({ x: x + 1, y, path: [...path] });
|
||||||
|
}
|
||||||
|
|
||||||
|
grid[x][y] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDestinationReached(func) {
|
||||||
|
this.events.ON_DESTINATION_REACHED.push(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearCanvas() {
|
||||||
|
this.ctx.clearRect(0, 0, 2000, 900);
|
||||||
|
}
|
||||||
|
|
||||||
|
roundRect(x, y, w, h, r = 20) {
|
||||||
|
this.ctx.lineWidth = 5;
|
||||||
|
this.ctx.strokeStyle = 'red';
|
||||||
|
this.ctx.beginPath();
|
||||||
|
this.ctx.moveTo(x + r, y);
|
||||||
|
this.ctx.lineTo(x + w - r, y);
|
||||||
|
this.ctx.quadraticCurveTo(x + w, y, x + w, y + r);
|
||||||
|
this.ctx.lineTo(x + w, y + h - r);
|
||||||
|
this.ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
|
||||||
|
this.ctx.lineTo(x + r, y + h);
|
||||||
|
this.ctx.quadraticCurveTo(x, y + h, x, y + h - r);
|
||||||
|
this.ctx.lineTo(x, y + r);
|
||||||
|
this.ctx.quadraticCurveTo(x, y, x + r, y);
|
||||||
|
this.ctx.closePath();
|
||||||
|
this.ctx.stroke();
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,8 @@ const GRID_FIELD_TYPE = Object.freeze({
|
|||||||
});
|
});
|
||||||
|
|
||||||
class Grid {
|
class Grid {
|
||||||
|
static instance;
|
||||||
|
|
||||||
constructor(canvas) {
|
constructor(canvas) {
|
||||||
this.grid = [[]];
|
this.grid = [[]];
|
||||||
this.ctx;
|
this.ctx;
|
||||||
@ -15,6 +17,8 @@ class Grid {
|
|||||||
this.processGrid();
|
this.processGrid();
|
||||||
this.drawShelfs();
|
this.drawShelfs();
|
||||||
this.drawStorages();
|
this.drawStorages();
|
||||||
|
|
||||||
|
Grid.instance = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
getGrid () {
|
getGrid () {
|
||||||
@ -39,7 +43,6 @@ class Grid {
|
|||||||
for (let i = 0; i < 20; i++) {
|
for (let i = 0; i < 20; i++) {
|
||||||
this.grid[i] = [...this.grid[i], lastLine[i]];
|
this.grid[i] = [...this.grid[i], lastLine[i]];
|
||||||
}
|
}
|
||||||
console.log(this.grid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drawShelfs () {
|
drawShelfs () {
|
||||||
@ -52,6 +55,16 @@ class Grid {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
randomPlace() {
|
||||||
|
const x = Math.floor(Math.random() * this.grid.length);
|
||||||
|
const y = Math.floor(Math.random() * this.grid[0].length);
|
||||||
|
const rand = this.grid[x][y];
|
||||||
|
if (rand === GRID_FIELD_TYPE.SHELF || rand === GRID_FIELD_TYPE.PATH) {
|
||||||
|
return { x, y };
|
||||||
|
}
|
||||||
|
return this.randomPlace();
|
||||||
|
}
|
||||||
|
|
||||||
drawStorages () {
|
drawStorages () {
|
||||||
let isFirstOfType = true;
|
let isFirstOfType = true;
|
||||||
let isLastOfType = false;
|
let isLastOfType = false;
|
||||||
|
Loading…
Reference in New Issue
Block a user