added extra demo classes and implemented pathfinding groundwork
This commit is contained in:
parent
19028a9a58
commit
1047e31c70
|
@ -5,6 +5,7 @@ import Color from "./Utils/Color";
|
||||||
import Boid from "./_DemoClasses/Boids/Boid";
|
import Boid from "./_DemoClasses/Boids/Boid";
|
||||||
import FlockBehavior from "./_DemoClasses/Boids/FlockBehavior";
|
import FlockBehavior from "./_DemoClasses/Boids/FlockBehavior";
|
||||||
import Player from "./_DemoClasses/Player/Player";
|
import Player from "./_DemoClasses/Player/Player";
|
||||||
|
import PlayerController from "./_DemoClasses/Player/PlayerController";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This demo emphasizes an ai system for the game engine with component architecture
|
* This demo emphasizes an ai system for the game engine with component architecture
|
||||||
|
@ -27,7 +28,9 @@ export default class BoidDemo extends Scene {
|
||||||
|
|
||||||
// Add the player
|
// Add the player
|
||||||
let player = this.add.graphic(Player, layer, new Vec2(0, 0));
|
let player = this.add.graphic(Player, layer, new Vec2(0, 0));
|
||||||
|
player.addPhysics();
|
||||||
|
let ai = new PlayerController(player, "topdown");
|
||||||
|
player.update = (deltaT: number) => {ai.update(deltaT)}
|
||||||
this.viewport.follow(player);
|
this.viewport.follow(player);
|
||||||
this.viewport.enableZoom();
|
this.viewport.enableZoom();
|
||||||
|
|
||||||
|
|
55
src/DataTypes/Graphs/Graph.ts
Normal file
55
src/DataTypes/Graphs/Graph.ts
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
export const MAX_V = 100;
|
||||||
|
|
||||||
|
export default class Graph {
|
||||||
|
edges: Array<EdgeNode>;
|
||||||
|
degree: Array<number>;
|
||||||
|
numVertices: number;
|
||||||
|
numEdges: number;
|
||||||
|
directed: boolean;
|
||||||
|
weighted: boolean;
|
||||||
|
|
||||||
|
constructor(directed: boolean = false){
|
||||||
|
this.directed = directed;
|
||||||
|
this.weighted = false;
|
||||||
|
|
||||||
|
this.numVertices = 0;
|
||||||
|
this.numEdges = 0;
|
||||||
|
|
||||||
|
this.edges = new Array(MAX_V);
|
||||||
|
this.degree = new Array(MAX_V);
|
||||||
|
}
|
||||||
|
|
||||||
|
addNode(): number {
|
||||||
|
this.numVertices++;
|
||||||
|
return this.numVertices;
|
||||||
|
}
|
||||||
|
|
||||||
|
addEdge(x: number, y: number, weight?: number){
|
||||||
|
let edge = new EdgeNode(y, weight);
|
||||||
|
|
||||||
|
edge.next = this.edges[x];
|
||||||
|
|
||||||
|
this.edges[x] = edge;
|
||||||
|
this.numEdges += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
getEdges(x: number): EdgeNode {
|
||||||
|
return this.edges[x];
|
||||||
|
}
|
||||||
|
|
||||||
|
getDegree(x: number): number {
|
||||||
|
return this.degree[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class EdgeNode {
|
||||||
|
y: number;
|
||||||
|
next: EdgeNode;
|
||||||
|
weight: number;
|
||||||
|
|
||||||
|
constructor(index: number, weight?: number){
|
||||||
|
this.y = index;
|
||||||
|
this.next = null;
|
||||||
|
this.weight = weight ? weight : 1;
|
||||||
|
}
|
||||||
|
}
|
33
src/DataTypes/Graphs/PositionGraph.ts
Normal file
33
src/DataTypes/Graphs/PositionGraph.ts
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import Graph, { MAX_V } from "./Graph";
|
||||||
|
import Vec2 from "../Vec2";
|
||||||
|
import { Debug_Renderable } from "../Interfaces/Descriptors";
|
||||||
|
|
||||||
|
export default class PositionGraph extends Graph implements Debug_Renderable{
|
||||||
|
positions: Array<Vec2>;
|
||||||
|
|
||||||
|
constructor(directed: boolean = false){
|
||||||
|
super(directed);
|
||||||
|
this.positions = new Array(MAX_V);
|
||||||
|
}
|
||||||
|
|
||||||
|
setNodePosition(index: number, position: Vec2): void {
|
||||||
|
this.positions[index] = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
addEdge(x: number, y: number): void {
|
||||||
|
if(!this.positions[x] || !this.positions[y]){
|
||||||
|
throw "Can't add edge to un-positioned node!";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Weight is the distance between the nodes
|
||||||
|
let weight = this.positions[x].distanceSqTo(this.positions[y]);
|
||||||
|
|
||||||
|
super.addEdge(x, y, weight);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_render(ctx: CanvasRenderingContext2D, origin: Vec2, zoom: number): void {
|
||||||
|
for(let point of this.positions){
|
||||||
|
ctx.fillRect((point.x - origin.x - 4)*zoom, (point.y - origin.y - 4)*zoom, 8, 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -75,6 +75,8 @@ export interface Physical {
|
||||||
/** The rectangle swept by the movement of this object, if dynamic */
|
/** The rectangle swept by the movement of this object, if dynamic */
|
||||||
sweptRect: AABB;
|
sweptRect: AABB;
|
||||||
|
|
||||||
|
isPlayer: boolean;
|
||||||
|
|
||||||
/*---------- FUNCTIONS ----------*/
|
/*---------- FUNCTIONS ----------*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -117,5 +119,5 @@ export interface Renderable {
|
||||||
|
|
||||||
export interface Debug_Renderable {
|
export interface Debug_Renderable {
|
||||||
/** Renders the debugging infor for this object. */
|
/** Renders the debugging infor for this object. */
|
||||||
debug_render: (ctx: CanvasRenderingContext2D) => void;
|
debug_render: (ctx: CanvasRenderingContext2D, origin: Vec2, zoom: number) => void;
|
||||||
}
|
}
|
||||||
|
|
27
src/DataTypes/Navmesh.ts
Normal file
27
src/DataTypes/Navmesh.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import PositionGraph from "./Graphs/PositionGraph"
|
||||||
|
import Vec2 from "./Vec2";
|
||||||
|
|
||||||
|
export default class Navmesh {
|
||||||
|
protected graph: PositionGraph;
|
||||||
|
|
||||||
|
getNavigationPath(fromPosition: Vec2, toPosition: Vec2): Array<number> {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
getClosestNode(position: Vec2): number {
|
||||||
|
let n = this.graph.numVertices;
|
||||||
|
let i = 1;
|
||||||
|
let index = 0;
|
||||||
|
let dist = position.distanceSqTo(this.graph.positions[0]);
|
||||||
|
while(i < n){
|
||||||
|
let d = position.distanceSqTo(this.graph.positions[i]);
|
||||||
|
if(d < dist){
|
||||||
|
dist = d;
|
||||||
|
index = i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,7 @@ export default abstract class Shape {
|
||||||
private static getTimeOfCollision_AABB_AABB(A: AABB, velA: Vec2, B: Shape, velB: Vec2): [Vec2, Vec2, boolean, boolean] {
|
private static getTimeOfCollision_AABB_AABB(A: AABB, velA: Vec2, B: Shape, velB: Vec2): [Vec2, Vec2, boolean, boolean] {
|
||||||
let posSmaller = A.center;
|
let posSmaller = A.center;
|
||||||
let posLarger = B.center;
|
let posLarger = B.center;
|
||||||
|
|
||||||
let sizeSmaller = A.halfSize;
|
let sizeSmaller = A.halfSize;
|
||||||
let sizeLarger = B.halfSize;
|
let sizeLarger = B.halfSize;
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,7 @@ export default class Tileset {
|
||||||
* @param origin The viewport origin in the current layer
|
* @param origin The viewport origin in the current layer
|
||||||
* @param scale The scale of the tilemap
|
* @param scale The scale of the tilemap
|
||||||
*/
|
*/
|
||||||
renderTile(ctx: CanvasRenderingContext2D, tileIndex: number, dataIndex: number, worldSize: Vec2, origin: Vec2, scale: Vec2): void {
|
renderTile(ctx: CanvasRenderingContext2D, tileIndex: number, dataIndex: number, worldSize: Vec2, origin: Vec2, scale: Vec2, zoom: number): void {
|
||||||
let image = ResourceManager.getInstance().getImage(this.imageKey);
|
let image = ResourceManager.getInstance().getImage(this.imageKey);
|
||||||
|
|
||||||
// Get the true index
|
// Get the true index
|
||||||
|
@ -104,6 +104,6 @@ export default class Tileset {
|
||||||
// Calculate the position in the world to render the tile
|
// Calculate the position in the world to render the tile
|
||||||
let x = Math.floor((dataIndex % worldSize.x) * width * scale.x);
|
let x = Math.floor((dataIndex % worldSize.x) * width * scale.x);
|
||||||
let y = Math.floor(Math.floor(dataIndex / worldSize.x) * height * scale.y);
|
let y = Math.floor(Math.floor(dataIndex / worldSize.x) * height * scale.y);
|
||||||
ctx.drawImage(image, left, top, width, height, x - origin.x, y - origin.y, width * scale.x, height * scale.y);
|
ctx.drawImage(image, left, top, width, height, Math.floor((x - origin.x)*zoom), Math.floor((y - origin.y)*zoom), Math.ceil(width * scale.x * zoom), Math.ceil(height * scale.y * zoom));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ import Shape from "../DataTypes/Shapes/Shape";
|
||||||
import GameEvent from "../Events/GameEvent";
|
import GameEvent from "../Events/GameEvent";
|
||||||
import Map from "../DataTypes/Map";
|
import Map from "../DataTypes/Map";
|
||||||
import AABB from "../DataTypes/Shapes/AABB";
|
import AABB from "../DataTypes/Shapes/AABB";
|
||||||
|
import Debug from "../Debug/Debug";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The representation of an object in the game world
|
* The representation of an object in the game world
|
||||||
|
@ -35,6 +36,7 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
|
||||||
triggers: Map<string>;
|
triggers: Map<string>;
|
||||||
_velocity: Vec2;
|
_velocity: Vec2;
|
||||||
sweptRect: AABB;
|
sweptRect: AABB;
|
||||||
|
isPlayer: boolean;
|
||||||
|
|
||||||
protected input: InputReceiver;
|
protected input: InputReceiver;
|
||||||
protected receiver: Receiver;
|
protected receiver: Receiver;
|
||||||
|
|
|
@ -86,6 +86,7 @@ export default class OrthogonalTilemap extends Tilemap {
|
||||||
ctx.globalAlpha = this.getLayer().getAlpha();
|
ctx.globalAlpha = this.getLayer().getAlpha();
|
||||||
|
|
||||||
let origin = this.getViewportOriginWithParallax();
|
let origin = this.getViewportOriginWithParallax();
|
||||||
|
let zoom = this.getViewportScale();
|
||||||
|
|
||||||
if(this.visible){
|
if(this.visible){
|
||||||
for(let i = 0; i < this.data.length; i++){
|
for(let i = 0; i < this.data.length; i++){
|
||||||
|
@ -93,7 +94,7 @@ export default class OrthogonalTilemap extends Tilemap {
|
||||||
|
|
||||||
for(let tileset of this.tilesets){
|
for(let tileset of this.tilesets){
|
||||||
if(tileset.hasTile(tileIndex)){
|
if(tileset.hasTile(tileIndex)){
|
||||||
tileset.renderTile(ctx, tileIndex, i, this.size, origin, this.scale);
|
tileset.renderTile(ctx, tileIndex, i, this.size, origin, this.scale, zoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,14 +75,16 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
||||||
// TODO - This is problematic if a collision happens, but it is later learned that another collision happens before it
|
// TODO - This is problematic if a collision happens, but it is later learned that another collision happens before it
|
||||||
if(node1.triggers.has(group2)){
|
if(node1.triggers.has(group2)){
|
||||||
// Node1 should send an event
|
// Node1 should send an event
|
||||||
|
console.log("Trigger")
|
||||||
let eventType = node1.triggers.get(group2);
|
let eventType = node1.triggers.get(group2);
|
||||||
this.emitter.fireEvent(eventType, {node: node1, other: node2});
|
this.emitter.fireEvent(eventType, {node: node1, other: node2, collision: {firstContact: firstContact}});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(node2.triggers.has(group1)){
|
if(node2.triggers.has(group1)){
|
||||||
// Node2 should send an event
|
// Node2 should send an event
|
||||||
|
console.log("Trigger")
|
||||||
let eventType = node2.triggers.get(group1);
|
let eventType = node2.triggers.get(group1);
|
||||||
this.emitter.fireEvent(eventType, {node: node2, other: node1});
|
this.emitter.fireEvent(eventType, {node: node2, other: node1, collision: {firstContact: firstContact}});
|
||||||
}
|
}
|
||||||
|
|
||||||
if(collidingX && collidingY){
|
if(collidingX && collidingY){
|
||||||
|
@ -94,6 +96,9 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
||||||
let xScale = MathUtils.clamp(firstContact.x, 0, 1);
|
let xScale = MathUtils.clamp(firstContact.x, 0, 1);
|
||||||
let yScale = MathUtils.clamp(firstContact.y, 0, 1);
|
let yScale = MathUtils.clamp(firstContact.y, 0, 1);
|
||||||
|
|
||||||
|
MathUtils.floorToPlace(xScale, 4);
|
||||||
|
MathUtils.floorToPlace(yScale, 4);
|
||||||
|
|
||||||
// Handle special case of stickiness on perfect corner to corner collisions
|
// Handle special case of stickiness on perfect corner to corner collisions
|
||||||
if(xScale === yScale){
|
if(xScale === yScale){
|
||||||
xScale = 1;
|
xScale = 1;
|
||||||
|
@ -111,8 +116,8 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!node2.isStatic && node2.moving){
|
if(!node2.isStatic && node2.moving){
|
||||||
node1.onGround = !node1onTop;
|
node2.onGround = !node1onTop;
|
||||||
node1.onCeiling = node1onTop;
|
node2.onCeiling = node1onTop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -129,16 +134,12 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scale velocity for either node if it is moving
|
// Scale velocity for either node if it is moving
|
||||||
if(!node1.isStatic && node1.moving){
|
|
||||||
node1._velocity.scale(xScale, yScale);
|
node1._velocity.scale(xScale, yScale);
|
||||||
}
|
|
||||||
|
|
||||||
if(!node2.isStatic && node2.moving){
|
|
||||||
node2._velocity.scale(xScale, yScale);
|
node2._velocity.scale(xScale, yScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
collideWithTilemap(node: Physical, tilemap: Tilemap, velocity: Vec2): void {
|
collideWithTilemap(node: Physical, tilemap: Tilemap, velocity: Vec2): void {
|
||||||
if(tilemap instanceof OrthogonalTilemap){
|
if(tilemap instanceof OrthogonalTilemap){
|
||||||
|
@ -274,6 +275,18 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
||||||
// Get Collision (which may or may not happen)
|
// Get Collision (which may or may not happen)
|
||||||
let [firstContact, lastContact, collidingX, collidingY] = Shape.getTimeOfCollision(node1.collisionShape, node1._velocity, node2.collisionShape, node2._velocity);
|
let [firstContact, lastContact, collidingX, collidingY] = Shape.getTimeOfCollision(node1.collisionShape, node1._velocity, node2.collisionShape, node2._velocity);
|
||||||
|
|
||||||
|
if(collidingX && collidingY){
|
||||||
|
console.log("overlapping")
|
||||||
|
}
|
||||||
|
|
||||||
|
if(node1.isPlayer){
|
||||||
|
if(firstContact.x !== Infinity || firstContact.y !== Infinity)
|
||||||
|
Debug.log("playercol", "First Contact: " + firstContact.toFixed(4))
|
||||||
|
} else if(node2.isPlayer) {
|
||||||
|
if(firstContact.x !== Infinity || firstContact.y !== Infinity)
|
||||||
|
Debug.log("playercol", "First Contact: " + firstContact.toFixed(4))
|
||||||
|
}
|
||||||
|
|
||||||
this.resolveCollision(node1, node2, firstContact, lastContact, collidingX, collidingY);
|
this.resolveCollision(node1, node2, firstContact, lastContact, collidingX, collidingY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ export default class SweepAndPrune extends BroadPhase {
|
||||||
let node = this.xList[i];
|
let node = this.xList[i];
|
||||||
|
|
||||||
let index = 1;
|
let index = 1;
|
||||||
while(i + index < this.xList.length && node.sweptRect.right > this.xList[i + index].sweptRect.left){
|
while(i + index < this.xList.length && node.sweptRect.right >= this.xList[i + index].sweptRect.left){
|
||||||
// Colliding pair in x-axis
|
// Colliding pair in x-axis
|
||||||
xCollisions.push([node, this.xList[i + index]]);
|
xCollisions.push([node, this.xList[i + index]]);
|
||||||
index++;
|
index++;
|
||||||
|
@ -44,7 +44,7 @@ export default class SweepAndPrune extends BroadPhase {
|
||||||
let node = this.yList[i];
|
let node = this.yList[i];
|
||||||
|
|
||||||
let index = 1;
|
let index = 1;
|
||||||
while(i + index < this.yList.length && node.sweptRect.bottom > this.yList[i + index].sweptRect.top){
|
while(i + index < this.yList.length && node.sweptRect.bottom >= this.yList[i + index].sweptRect.top){
|
||||||
// Colliding pair in y-axis
|
// Colliding pair in y-axis
|
||||||
yCollisions.push([node, this.yList[i + index]]);
|
yCollisions.push([node, this.yList[i + index]]);
|
||||||
index++;
|
index++;
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import Scene from "../Scene";
|
import Scene from "../Scene";
|
||||||
import CanvasNodeFactory from "./CanvasNodeFactory";
|
import CanvasNodeFactory from "./CanvasNodeFactory";
|
||||||
import TilemapFactory from "./TilemapFactory";
|
import TilemapFactory from "./TilemapFactory";
|
||||||
import PhysicsManager from "../../Physics/PhysicsManager";
|
|
||||||
import Tilemap from "../../Nodes/Tilemap";
|
import Tilemap from "../../Nodes/Tilemap";
|
||||||
|
|
||||||
export default class FactoryManager {
|
export default class FactoryManager {
|
||||||
|
@ -10,9 +9,9 @@ export default class FactoryManager {
|
||||||
private canvasNodeFactory: CanvasNodeFactory = new CanvasNodeFactory();
|
private canvasNodeFactory: CanvasNodeFactory = new CanvasNodeFactory();
|
||||||
private tilemapFactory: TilemapFactory = new TilemapFactory();
|
private tilemapFactory: TilemapFactory = new TilemapFactory();
|
||||||
|
|
||||||
constructor(scene: Scene, physicsManager: PhysicsManager, tilemaps: Array<Tilemap>){
|
constructor(scene: Scene, tilemaps: Array<Tilemap>){
|
||||||
this.canvasNodeFactory.init(scene);
|
this.canvasNodeFactory.init(scene);
|
||||||
this.tilemapFactory.init(scene, tilemaps, physicsManager);
|
this.tilemapFactory.init(scene, tilemaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expose all of the factories through the factory manager
|
// Expose all of the factories through the factory manager
|
||||||
|
|
|
@ -12,13 +12,11 @@ import Sprite from "../../Nodes/Sprites/Sprite";
|
||||||
export default class TilemapFactory {
|
export default class TilemapFactory {
|
||||||
private scene: Scene;
|
private scene: Scene;
|
||||||
private tilemaps: Array<Tilemap>;
|
private tilemaps: Array<Tilemap>;
|
||||||
private physicsManager: PhysicsManager;
|
|
||||||
private resourceManager: ResourceManager;
|
private resourceManager: ResourceManager;
|
||||||
|
|
||||||
init(scene: Scene, tilemaps: Array<Tilemap>, physicsManager: PhysicsManager): void {
|
init(scene: Scene, tilemaps: Array<Tilemap>): void {
|
||||||
this.scene = scene;
|
this.scene = scene;
|
||||||
this.tilemaps = tilemaps;
|
this.tilemaps = tilemaps;
|
||||||
this.physicsManager = physicsManager;
|
|
||||||
this.resourceManager = ResourceManager.getInstance();
|
this.resourceManager = ResourceManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,15 +81,39 @@ export default class TilemapFactory {
|
||||||
tilemap.addPhysics();
|
tilemap.addPhysics();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
let isNavmeshPoints = false
|
||||||
|
if(layer.properties){
|
||||||
|
for(let prop of layer.properties){
|
||||||
|
if(prop.name === "NavmeshPoints"){
|
||||||
|
isNavmeshPoints = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isNavmeshPoints){
|
||||||
|
console.log("Parsing NavmeshPoints")
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Layer is an object layer, so add each object as a sprite to a new layer
|
// Layer is an object layer, so add each object as a sprite to a new layer
|
||||||
for(let obj of layer.objects){
|
for(let obj of layer.objects){
|
||||||
// Check if obj is collidable
|
// Check if obj is collidable
|
||||||
let collidable = false;
|
let isCollidable = false;
|
||||||
|
let hasPhysics = false;
|
||||||
|
let isStatic = true;
|
||||||
|
let group = "";
|
||||||
|
|
||||||
if(obj.properties){
|
if(obj.properties){
|
||||||
for(let prop of obj.properties){
|
for(let prop of obj.properties){
|
||||||
if(prop.name === "Collidable"){
|
if(prop.name === "Collidable"){
|
||||||
collidable = prop.value;
|
isCollidable = prop.value;
|
||||||
|
} else if(prop.name === "Static"){
|
||||||
|
isStatic = prop.value;
|
||||||
|
} else if(prop.name === "hasPhysics"){
|
||||||
|
hasPhysics = prop.value;
|
||||||
|
} else if(prop.name === "Group"){
|
||||||
|
group = prop.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,8 +148,9 @@ export default class TilemapFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we have sprite. Associate it with our physics object if there is one
|
// Now we have sprite. Associate it with our physics object if there is one
|
||||||
if(collidable){
|
if(hasPhysics){
|
||||||
sprite.addPhysics();
|
sprite.addPhysics(sprite.boundary.clone(), isCollidable, isStatic);
|
||||||
|
sprite.group = group;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ import SceneManager from "./SceneManager";
|
||||||
import Receiver from "../Events/Receiver";
|
import Receiver from "../Events/Receiver";
|
||||||
import Emitter from "../Events/Emitter";
|
import Emitter from "../Events/Emitter";
|
||||||
import { Renderable, Updateable } from "../DataTypes/Interfaces/Descriptors";
|
import { Renderable, Updateable } from "../DataTypes/Interfaces/Descriptors";
|
||||||
|
import Navmesh from "../DataTypes/Navmesh";
|
||||||
|
|
||||||
export default class Scene implements Updateable, Renderable {
|
export default class Scene implements Updateable, Renderable {
|
||||||
/** The size of the game world. */
|
/** The size of the game world. */
|
||||||
|
@ -49,6 +50,8 @@ export default class Scene implements Updateable, Renderable {
|
||||||
/** An interface that allows the loading of different files for use in the scene */
|
/** An interface that allows the loading of different files for use in the scene */
|
||||||
public load: ResourceManager;
|
public load: ResourceManager;
|
||||||
|
|
||||||
|
protected navmeshes: Array<Navmesh>;
|
||||||
|
|
||||||
constructor(viewport: Viewport, sceneManager: SceneManager, game: GameLoop){
|
constructor(viewport: Viewport, sceneManager: SceneManager, game: GameLoop){
|
||||||
this.worldSize = new Vec2(500, 500);
|
this.worldSize = new Vec2(500, 500);
|
||||||
this.viewport = viewport;
|
this.viewport = viewport;
|
||||||
|
@ -63,7 +66,7 @@ export default class Scene implements Updateable, Renderable {
|
||||||
this.sceneGraph = new SceneGraphArray(this.viewport, this);
|
this.sceneGraph = new SceneGraphArray(this.viewport, this);
|
||||||
this.physicsManager = new BasicPhysicsManager();
|
this.physicsManager = new BasicPhysicsManager();
|
||||||
|
|
||||||
this.add = new FactoryManager(this, this.physicsManager, this.tilemaps);
|
this.add = new FactoryManager(this, this.tilemaps);
|
||||||
|
|
||||||
this.load = ResourceManager.getInstance();
|
this.load = ResourceManager.getInstance();
|
||||||
}
|
}
|
||||||
|
|
21
src/Utils/GraphUtils.ts
Normal file
21
src/Utils/GraphUtils.ts
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import Graph, { EdgeNode } from "../DataTypes/Graphs/Graph";
|
||||||
|
|
||||||
|
export default class GraphUtils {
|
||||||
|
|
||||||
|
static djikstra(g: Graph, start: number): void {
|
||||||
|
let i: number; // Counter
|
||||||
|
let p: EdgeNode; // Pointer to edgenode
|
||||||
|
let inTree: Array<boolean>
|
||||||
|
let distance: number;
|
||||||
|
let v: number; // Current vertex to process
|
||||||
|
let w: number; // Candidate for next vertex
|
||||||
|
let weight: number; // Edge weight
|
||||||
|
let dist; // Best current distance from start
|
||||||
|
|
||||||
|
for(i = 0; i < g.numVertices; i++){
|
||||||
|
inTree[i] = false;
|
||||||
|
distance[i] = Infinity;
|
||||||
|
// parent[i] = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -47,6 +47,26 @@ export default class MathUtils {
|
||||||
return a + x * (b - a);
|
return a + x * (b - a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cuts off decimal points of a number after a specified place
|
||||||
|
* @param num The number to floor
|
||||||
|
* @param place The last decimal place of the new number
|
||||||
|
*/
|
||||||
|
static floorToPlace(num: number, place: number): number {
|
||||||
|
if(place === 0){
|
||||||
|
return Math.floor(num);
|
||||||
|
}
|
||||||
|
|
||||||
|
let factor = 10;
|
||||||
|
while(place > 1){
|
||||||
|
factor != 10;
|
||||||
|
place--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math.floor(num*factor)/factor;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number as a hexadecimal
|
* Returns the number as a hexadecimal
|
||||||
* @param num The number to convert to hex
|
* @param num The number to convert to hex
|
||||||
|
|
31
src/_DemoClasses/Enemies/Afraid.ts
Normal file
31
src/_DemoClasses/Enemies/Afraid.ts
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
import GameEvent from "../../Events/GameEvent";
|
||||||
|
import MathUtils from "../../Utils/MathUtils";
|
||||||
|
import { CustomGameEventType } from "../CustomGameEventType";
|
||||||
|
import { GoombaStates } from "./GoombaController";
|
||||||
|
import OnGround from "./OnGround";
|
||||||
|
|
||||||
|
export default class Afraid extends OnGround {
|
||||||
|
|
||||||
|
onEnter(): void {}
|
||||||
|
|
||||||
|
handleInput(event: GameEvent): void {
|
||||||
|
if(event.type === CustomGameEventType.PLAYER_MOVE){
|
||||||
|
let pos = event.data.get("position");
|
||||||
|
this.parent.direction.x = MathUtils.sign(this.owner.position.x - pos.x);
|
||||||
|
} else if(event.type === "playerHitCoinBlock") {
|
||||||
|
if(event.data.get("collision").firstContact.y < 1 && event.data.get("node").collisionShape.center.y > event.data.get("other").collisionShape.center.y){
|
||||||
|
this.finished("previous");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
update(deltaT: number): void {
|
||||||
|
super.update(deltaT);
|
||||||
|
|
||||||
|
this.parent.velocity.x = this.parent.direction.x * this.parent.speed * 1.2;
|
||||||
|
|
||||||
|
this.owner.move(this.parent.velocity.scaled(deltaT));
|
||||||
|
}
|
||||||
|
|
||||||
|
onExit(): void {}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ import { CustomGameEventType } from "../CustomGameEventType";
|
||||||
import Idle from "../Enemies/Idle";
|
import Idle from "../Enemies/Idle";
|
||||||
import Jump from "../Enemies/Jump";
|
import Jump from "../Enemies/Jump";
|
||||||
import Walk from "../Enemies/Walk";
|
import Walk from "../Enemies/Walk";
|
||||||
|
import Afraid from "../Enemies/Afraid";
|
||||||
import Debug from "../../Debug/Debug";
|
import Debug from "../../Debug/Debug";
|
||||||
import GameNode from "../../Nodes/GameNode";
|
import GameNode from "../../Nodes/GameNode";
|
||||||
import Vec2 from "../../DataTypes/Vec2";
|
import Vec2 from "../../DataTypes/Vec2";
|
||||||
|
@ -11,7 +12,8 @@ export enum GoombaStates {
|
||||||
IDLE = "idle",
|
IDLE = "idle",
|
||||||
WALK = "walk",
|
WALK = "walk",
|
||||||
JUMP = "jump",
|
JUMP = "jump",
|
||||||
PREVIOUS = "previous"
|
PREVIOUS = "previous",
|
||||||
|
AFRAID = "afraid"
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class GoombaController extends StateMachine {
|
export default class GoombaController extends StateMachine {
|
||||||
|
@ -28,6 +30,7 @@ export default class GoombaController extends StateMachine {
|
||||||
this.jumpy = jumpy;
|
this.jumpy = jumpy;
|
||||||
|
|
||||||
this.receiver.subscribe(CustomGameEventType.PLAYER_MOVE);
|
this.receiver.subscribe(CustomGameEventType.PLAYER_MOVE);
|
||||||
|
this.receiver.subscribe("playerHitCoinBlock");
|
||||||
if(this.jumpy){
|
if(this.jumpy){
|
||||||
this.receiver.subscribe(CustomGameEventType.PLAYER_JUMP);
|
this.receiver.subscribe(CustomGameEventType.PLAYER_JUMP);
|
||||||
}
|
}
|
||||||
|
@ -38,11 +41,13 @@ export default class GoombaController extends StateMachine {
|
||||||
this.addState(GoombaStates.WALK, walk);
|
this.addState(GoombaStates.WALK, walk);
|
||||||
let jump = new Jump(this, owner);
|
let jump = new Jump(this, owner);
|
||||||
this.addState(GoombaStates.JUMP, jump);
|
this.addState(GoombaStates.JUMP, jump);
|
||||||
|
let afraid = new Afraid(this, owner);
|
||||||
|
this.addState(GoombaStates.AFRAID, afraid);
|
||||||
}
|
}
|
||||||
|
|
||||||
changeState(stateName: string): void {
|
changeState(stateName: string): void {
|
||||||
|
|
||||||
if(stateName === GoombaStates.JUMP){
|
if(stateName === GoombaStates.JUMP || stateName === GoombaStates.AFRAID){
|
||||||
this.stack.push(this.stateMap.get(stateName));
|
this.stack.push(this.stateMap.get(stateName));
|
||||||
}
|
}
|
||||||
super.changeState(stateName);
|
super.changeState(stateName);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import State from "../../DataTypes/State/State";
|
import State from "../../DataTypes/State/State";
|
||||||
import StateMachine from "../../DataTypes/State/StateMachine";
|
import StateMachine from "../../DataTypes/State/StateMachine";
|
||||||
|
import GameEvent from "../../Events/GameEvent";
|
||||||
import GameNode from "../../Nodes/GameNode";
|
import GameNode from "../../Nodes/GameNode";
|
||||||
import GoombaController from "./GoombaController";
|
import GoombaController, { GoombaStates } from "./GoombaController";
|
||||||
|
|
||||||
export default abstract class GoombaState extends State {
|
export default abstract class GoombaState extends State {
|
||||||
owner: GameNode;
|
owner: GameNode;
|
||||||
|
@ -14,6 +15,14 @@ export default abstract class GoombaState extends State {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleInput(event: GameEvent): void {
|
||||||
|
if(event.type === "playerHitCoinBlock") {
|
||||||
|
if(event.data.get("collision").firstContact.y < 1 && event.data.get("node").collisionShape.center.y > event.data.get("other").collisionShape.center.y){
|
||||||
|
this.finished(GoombaStates.AFRAID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
update(deltaT: number): void {
|
update(deltaT: number): void {
|
||||||
// Do gravity
|
// Do gravity
|
||||||
this.parent.velocity.y += this.gravity*deltaT;
|
this.parent.velocity.y += this.gravity*deltaT;
|
||||||
|
|
|
@ -16,7 +16,6 @@ export default class Idle extends OnGround {
|
||||||
this.finished(GoombaStates.WALK);
|
this.finished(GoombaStates.WALK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.handleInput(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update(deltaT: number): void {
|
update(deltaT: number): void {
|
||||||
|
|
|
@ -6,8 +6,6 @@ export default class Jump extends GoombaState {
|
||||||
|
|
||||||
onEnter(): void {}
|
onEnter(): void {}
|
||||||
|
|
||||||
handleInput(event: GameEvent): void {}
|
|
||||||
|
|
||||||
update(deltaT: number): void {
|
update(deltaT: number): void {
|
||||||
super.update(deltaT);
|
super.update(deltaT);
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@ export default class OnGround extends GoombaState {
|
||||||
this.finished(GoombaStates.JUMP);
|
this.finished(GoombaStates.JUMP);
|
||||||
this.parent.velocity.y = -2000;
|
this.parent.velocity.y = -2000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
super.handleInput(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
update(deltaT: number): void {
|
update(deltaT: number): void {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import Color from "../../Utils/Color";
|
||||||
import PlayerController from "../Player/PlayerStates/Platformer/PlayerController";
|
import PlayerController from "../Player/PlayerStates/Platformer/PlayerController";
|
||||||
import { PlayerStates } from "../Player/PlayerStates/Platformer/PlayerController";
|
import { PlayerStates } from "../Player/PlayerStates/Platformer/PlayerController";
|
||||||
import GoombaController from "../Enemies/GoombaController";
|
import GoombaController from "../Enemies/GoombaController";
|
||||||
|
import InputReceiver from "../../Input/InputReceiver";
|
||||||
|
|
||||||
export default class MarioClone extends Scene {
|
export default class MarioClone extends Scene {
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ export default class MarioClone extends Scene {
|
||||||
let player = this.add.graphic(Rect, layer, new Vec2(0, 0), new Vec2(64, 64));
|
let player = this.add.graphic(Rect, layer, new Vec2(0, 0), new Vec2(64, 64));
|
||||||
player.setColor(Color.BLUE);
|
player.setColor(Color.BLUE);
|
||||||
player.addPhysics();
|
player.addPhysics();
|
||||||
|
player.isPlayer = true;
|
||||||
this.viewport.follow(player);
|
this.viewport.follow(player);
|
||||||
this.viewport.setBounds(0, 0, 5120, 1280);
|
this.viewport.setBounds(0, 0, 5120, 1280);
|
||||||
|
|
||||||
|
@ -28,6 +29,8 @@ export default class MarioClone extends Scene {
|
||||||
ai.initialize(PlayerStates.IDLE);
|
ai.initialize(PlayerStates.IDLE);
|
||||||
player.update = (deltaT: number) => {ai.update(deltaT)};
|
player.update = (deltaT: number) => {ai.update(deltaT)};
|
||||||
|
|
||||||
|
player.addTrigger("CoinBlock", "playerHitCoinBlock");
|
||||||
|
|
||||||
for(let xPos of [14, 20, 25, 30, 33, 37, 49, 55, 58, 70, 74]){
|
for(let xPos of [14, 20, 25, 30, 33, 37, 49, 55, 58, 70, 74]){
|
||||||
let goomba = this.add.sprite("goomba", layer);
|
let goomba = this.add.sprite("goomba", layer);
|
||||||
let ai = new GoombaController(goomba, false);
|
let ai = new GoombaController(goomba, false);
|
||||||
|
|
26
src/_DemoClasses/Pathfinding/PathfindingScene.ts
Normal file
26
src/_DemoClasses/Pathfinding/PathfindingScene.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import Scene from "../../Scene/Scene";
|
||||||
|
import Rect from "../../Nodes/Graphics/Rect";
|
||||||
|
import Vec2 from "../../DataTypes/Vec2";
|
||||||
|
import PlayerController from "../Player/PlayerController";
|
||||||
|
|
||||||
|
export default class PathfindingScene extends Scene {
|
||||||
|
|
||||||
|
loadScene(){
|
||||||
|
this.load.tilemap("interior", "/assets/tilemaps/Interior.json");
|
||||||
|
}
|
||||||
|
|
||||||
|
startScene(){
|
||||||
|
this.add.tilemap("interior");
|
||||||
|
|
||||||
|
let layer = this.addLayer();
|
||||||
|
|
||||||
|
let player = this.add.graphic(Rect, layer, new Vec2(500, 500), new Vec2(64, 64));
|
||||||
|
player.addPhysics();
|
||||||
|
let ai = new PlayerController(player, "topdown");
|
||||||
|
ai.speed = 400;
|
||||||
|
player.update = (deltaT: number) => {ai.update(deltaT)}
|
||||||
|
this.viewport.setBounds(0, 0, 40*64, 40*64);
|
||||||
|
this.viewport.follow(player);
|
||||||
|
this.viewport.enableZoom();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,13 @@
|
||||||
import StateMachine from "../../DataTypes/State/StateMachine";
|
import StateMachine from "../../DataTypes/State/StateMachine";
|
||||||
import CanvasNode from "../../Nodes/CanvasNode";
|
import Vec2 from "../../DataTypes/Vec2";
|
||||||
|
import Debug from "../../Debug/Debug";
|
||||||
|
import GameNode from "../../Nodes/GameNode";
|
||||||
import IdleTopDown from "./PlayerStates/IdleTopDown";
|
import IdleTopDown from "./PlayerStates/IdleTopDown";
|
||||||
import MoveTopDown from "./PlayerStates/MoveTopDown";
|
import MoveTopDown from "./PlayerStates/MoveTopDown";
|
||||||
|
import Idle from "./PlayerStates/Platformer/Idle";
|
||||||
|
import Jump from "./PlayerStates/Platformer/Jump";
|
||||||
|
import Run from "./PlayerStates/Platformer/Run";
|
||||||
|
import Walk from "./PlayerStates/Platformer/Walk";
|
||||||
|
|
||||||
export enum PlayerType {
|
export enum PlayerType {
|
||||||
PLATFORMER = "platformer",
|
PLATFORMER = "platformer",
|
||||||
|
@ -9,20 +15,31 @@ export enum PlayerType {
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PlayerStates {
|
export enum PlayerStates {
|
||||||
|
IDLE = "idle",
|
||||||
MOVE = "move",
|
MOVE = "move",
|
||||||
IDLE = "idle"
|
WALK = "walk",
|
||||||
|
RUN = "run",
|
||||||
|
JUMP = "jump",
|
||||||
|
PREVIOUS = "previous"
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class PlayerController extends StateMachine {
|
export default class PlayerController extends StateMachine {
|
||||||
protected owner: CanvasNode;
|
protected owner: GameNode;
|
||||||
|
velocity: Vec2 = Vec2.ZERO;
|
||||||
|
speed: number;
|
||||||
|
MIN_SPEED: number = 400;
|
||||||
|
MAX_SPEED: number = 1000;
|
||||||
|
|
||||||
constructor(owner: CanvasNode, playerType: string){
|
|
||||||
|
constructor(owner: GameNode, playerType: string){
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
|
|
||||||
if(playerType === PlayerType.TOPDOWN){
|
if(playerType === PlayerType.TOPDOWN){
|
||||||
this.initializeTopDown();
|
this.initializeTopDown();
|
||||||
|
} else {
|
||||||
|
this.initializePlatformer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,13 +50,32 @@ export default class PlayerController extends StateMachine {
|
||||||
let idle = new IdleTopDown(this);
|
let idle = new IdleTopDown(this);
|
||||||
let move = new MoveTopDown(this, this.owner);
|
let move = new MoveTopDown(this, this.owner);
|
||||||
|
|
||||||
|
this.speed = 150;
|
||||||
|
|
||||||
this.addState(PlayerStates.IDLE, idle);
|
this.addState(PlayerStates.IDLE, idle);
|
||||||
this.addState(PlayerStates.MOVE, move);
|
this.addState(PlayerStates.MOVE, move);
|
||||||
|
|
||||||
this.initialize(PlayerStates.IDLE);
|
this.initialize(PlayerStates.IDLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initializePlatformer(): void {
|
||||||
|
this.speed = 400;
|
||||||
|
|
||||||
|
let idle = new Idle(this, this.owner);
|
||||||
|
this.addState(PlayerStates.IDLE, idle);
|
||||||
|
let walk = new Walk(this, this.owner);
|
||||||
|
this.addState(PlayerStates.WALK, walk);
|
||||||
|
let run = new Run(this, this.owner);
|
||||||
|
this.addState(PlayerStates.RUN, run);
|
||||||
|
let jump = new Jump(this, this.owner);
|
||||||
|
this.addState(PlayerStates.JUMP, jump);
|
||||||
|
}
|
||||||
|
|
||||||
changeState(stateName: string): void {
|
changeState(stateName: string): void {
|
||||||
|
if(stateName === PlayerStates.JUMP){
|
||||||
|
this.stack.push(this.stateMap.get(stateName));
|
||||||
|
}
|
||||||
|
|
||||||
if(stateName === PlayerStates.MOVE){
|
if(stateName === PlayerStates.MOVE){
|
||||||
// If move, push to the stack
|
// If move, push to the stack
|
||||||
this.stack.push(this.stateMap.get(stateName));
|
this.stack.push(this.stateMap.get(stateName));
|
||||||
|
@ -47,4 +83,22 @@ export default class PlayerController extends StateMachine {
|
||||||
|
|
||||||
super.changeState(stateName);
|
super.changeState(stateName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update(deltaT: number): void {
|
||||||
|
super.update(deltaT);
|
||||||
|
|
||||||
|
if(this.currentState instanceof Jump){
|
||||||
|
Debug.log("playerstate", "Player State: Jump");
|
||||||
|
} else if (this.currentState instanceof Walk){
|
||||||
|
Debug.log("playerstate", "Player State: Walk");
|
||||||
|
} else if (this.currentState instanceof Run){
|
||||||
|
Debug.log("playerstate", "Player State: Run");
|
||||||
|
} else if (this.currentState instanceof Idle){
|
||||||
|
Debug.log("playerstate", "Player State: Idle");
|
||||||
|
} else if (this.currentState instanceof IdleTopDown){
|
||||||
|
Debug.log("playerstate", "Player State: Idle");
|
||||||
|
} else if (this.currentState instanceof MoveTopDown){
|
||||||
|
Debug.log("playerstate", "Player State: Move");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -3,16 +3,17 @@ import StateMachine from "../../../DataTypes/State/StateMachine";
|
||||||
import Vec2 from "../../../DataTypes/Vec2";
|
import Vec2 from "../../../DataTypes/Vec2";
|
||||||
import GameEvent from "../../../Events/GameEvent";
|
import GameEvent from "../../../Events/GameEvent";
|
||||||
import InputReceiver from "../../../Input/InputReceiver";
|
import InputReceiver from "../../../Input/InputReceiver";
|
||||||
import CanvasNode from "../../../Nodes/CanvasNode";
|
import GameNode from "../../../Nodes/GameNode";
|
||||||
import { CustomGameEventType } from "../../CustomGameEventType";
|
import { CustomGameEventType } from "../../CustomGameEventType";
|
||||||
|
import PlayerController from "../PlayerController";
|
||||||
|
|
||||||
export default class MoveTopDown extends State {
|
export default class MoveTopDown extends State {
|
||||||
direction: Vec2 = Vec2.ZERO;
|
direction: Vec2 = Vec2.ZERO;
|
||||||
speed: number = 0;
|
|
||||||
input: InputReceiver = InputReceiver.getInstance();
|
input: InputReceiver = InputReceiver.getInstance();
|
||||||
owner: CanvasNode;
|
owner: GameNode;
|
||||||
|
parent: PlayerController
|
||||||
|
|
||||||
constructor(parent: StateMachine, owner: CanvasNode) {
|
constructor(parent: StateMachine, owner: GameNode) {
|
||||||
super(parent);
|
super(parent);
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +21,6 @@ export default class MoveTopDown extends State {
|
||||||
onEnter(): void {
|
onEnter(): void {
|
||||||
// Initialize or reset the direction and speed
|
// Initialize or reset the direction and speed
|
||||||
this.direction.zero();
|
this.direction.zero();
|
||||||
this.speed = 100;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleInput(event: GameEvent): void {
|
handleInput(event: GameEvent): void {
|
||||||
|
@ -38,7 +38,7 @@ export default class MoveTopDown extends State {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we are still moving, so update position
|
// Otherwise, we are still moving, so update position
|
||||||
let velocity = this.direction.normalize().scale(this.speed);
|
let velocity = this.direction.normalize().scale(this.parent.speed);
|
||||||
this.owner.move(velocity.scale(deltaT));
|
this.owner.move(velocity.scale(deltaT));
|
||||||
|
|
||||||
// Emit an event to tell the world we are moving
|
// Emit an event to tell the world we are moving
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
import GameLoop from "./Loop/GameLoop";
|
import GameLoop from "./Loop/GameLoop";
|
||||||
import {} from "./index";
|
import {} from "./index";
|
||||||
import MainScene from "./MainScene"
|
|
||||||
import QuadTreeScene from "./QuadTreeScene";
|
|
||||||
import BoidDemo from "./BoidDemo";
|
import BoidDemo from "./BoidDemo";
|
||||||
import MarioClone from "./_DemoClasses/MarioClone/MarioClone";
|
import MarioClone from "./_DemoClasses/MarioClone/MarioClone";
|
||||||
|
import PathfindingScene from "./_DemoClasses/Pathfinding/PathfindingScene";
|
||||||
|
|
||||||
function main(){
|
function main(){
|
||||||
// Create the game object
|
// Create the game object
|
||||||
let game = new GameLoop({canvasSize: {x: 800, y: 600}});
|
let game = new GameLoop({canvasSize: {x: 800, y: 600}});
|
||||||
game.start();
|
game.start();
|
||||||
let sm = game.getSceneManager();
|
let sm = game.getSceneManager();
|
||||||
sm.addScene(MarioClone);
|
sm.addScene(PathfindingScene);
|
||||||
}
|
}
|
||||||
|
|
||||||
CanvasRenderingContext2D.prototype.roundedRect = function(x: number, y: number, w: number, h: number, r: number): void {
|
CanvasRenderingContext2D.prototype.roundedRect = function(x: number, y: number, w: number, h: number, r: number): void {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user