UNPKG

type3games-engine

Version:

Modulární herní engine pro 2D hry v JavaScriptu

197 lines (175 loc) 8.87 kB
import {Sprite} from "../engine.js"; // Ensure this matches the export in sprite.js import {Hitbox} from "../coretools.js"; import {Vector} from "../coretools.js"; class Entity extends Sprite { /** * Creates an instance of the Entity class. * @param {Object} config - Configuration object containing necessary properties. * @param {number} config.x - The x-coordinate of the entity. * @param {number} config.y - The y-coordinate of the entity. * @param {string} config.imageSrc - The URL of the image for the entity. * @param {number} config.width - The width of the entity. * @param {number} config.height - The height of the entity. * @param {Render} config.render - An instance of the Render class to which this entity will be added. * @param {Physic} config.physic - An instance of the Physic class to which this entity will be added. * @param {Vector} [config.gravity=new Vector(0, 500)] - The gravity affecting the entity (default is (0,5)). * @param {Function} config.onLoadCallback - A callback function that is called when the */ constructor(config) { const options = { x: config.x, y: config.y, imageSrc: config.imageSrc, width: config.width, height: config.height, render: config.render, onLoadCallback: config.onLoadCallback }; super(options); this.collisionOffset = config.collisionOffset || 1 this.hitbox = new Hitbox(new Vector(0, 0), new Vector(this.width, this.height), this.position); this.groundSensor = new Hitbox(new Vector(0, this.height ), new Vector(this.width, this.height+this.collisionOffset+0.01), this.position); // Array to hold ground sensors this.onGround = false; // Flag to indicate if the entity is on the ground this.velocity = new Vector(0, 0); // Velocity vector for the entity this.acceleration = new Vector(0, 0); // Acceleration vector for the entity this.gravity = config.gravity || new Vector(0, 500); // Default gravity if not provided this.inAirDrag = config.inAirDrag this.touching = []; this.passableOnGround = []; // Flag to indicate if the entity is passable on ground config.physic.addEntity(this); // Assuming physic is an instance of a class that manages entities this.resolveXlist = [] this.resolveYlist = [] this.collisionHapened = false } update(deltaTime) { // Apply gravity to the entity's velocity this.touching = []; // Reset touching array if on ground if (this.onGround) { //console.log("Entity is on the ground"); // Update ground sensors positions this.onGround = this.passableOnGround.some((a) => a); }else{ this.velocity.add(Vector.mult(this.gravity, deltaTime)); this.velocity.x *= this.inAirDrag } // Update the entity's position based on its velocity this.velocity.add(Vector.mult(this.acceleration, deltaTime)); // if (Math.abs(this.velocity.x) < this.collisionOffset){ // this.velocity.x = 0; // Prevents the entity from moving too slowly // } // if (Math.abs(this.velocity.y) < this.collisionOffset){ // this.velocity.y = 0; // Prevents the entity from moving too slowly vertically // } this.position.add(Vector.mult(this.velocity, deltaTime)); // Update the hitbox position this.hitbox.updatePosition(this.position); this.groundSensor.updatePosition(this.position); // Update the ground sensor position // Reset latest axis of collision this.passableOnGround = []; // Reset onGround flag at the start of each update this.acceleration = new Vector(0, 0); // Reset acceleration after applying it this.resolveXlist = [] this.resolveYlist = [] this.collisionHapened = false } afterUpdate(deltaTime) { if (this.collisionHapened){ let max = 0 let maId = 0 let type = "" this.resolveXlist.forEach((block,i) => { if (block[1].mag > max){ max = Math.abs(Math.abs(block[1].x)-Math.abs(block[1].y)) maId = i type = "x" } }) this.resolveYlist.forEach((block,i) => { if (block[1].mag > max){ max = Math.abs(Math.abs(block[1].x)-Math.abs(block[1].y)) maId = i type = "y" } }) if (type == "x"){ this.resolveX(this.resolveXlist[maId]) }else if(type == "y"){ this.resolveY(this.resolveYlist[maId]) } } } addVelocity(velocity) { this.velocity.add(velocity); // Add the given velocity to the entity's velocity } addAcceleration(acceleration) { this.acceleration.add(acceleration); // Add the given acceleration to the entity's acceleration } checkCollision(block) { // Check if the entity's hitbox collides with the block's hitbox if (this.hitbox.isColliding(block.hitbox)) { this.onCollision(block); return true; // Collision detected } if(this.onGround){ // Check if the entity is touching the ground sensors this.passableOnGround.push(this.checkSensor(block)); } return false; // No collision } onCollision(block) { this.collisionHapened = true // console.log("Collision with block detected",this.latesAxes); let positionDifference = Vector.sub(Vector.add(block.position,Vector.div(block.hitbox.offset2,2)), Vector.add(this.position,Vector.div(this.hitbox.offset2,2))); //console.log("v"+positionDifference.x+" "+positionDifference.y); if (Math.floor(Math.abs(positionDifference.x)) > Math.floor(Math.abs(positionDifference.y))){ this.resolveXlist.push([block,positionDifference]) }else{ this.resolveYlist.push([block,positionDifference]) } } resolveX([block,positionDifference]){ //console.log("Latest axis set to x"); if (positionDifference.x > 0) { // Collision from the left //console.log("Collision from the left"); this.position.x = block.hitbox.position.x - this.width-this.collisionOffset; block.onCollision(this, new Vector(1,0)); // Notify the block of the collision } else if (positionDifference.x < 0) { //console.log("Collision from the right"); // Collision from the right this.position.x = block.hitbox.position.x + block.hitbox.offset2.x+this.collisionOffset; block.onCollision(this, new Vector(-1,0)); // Notify the block of the collision } } resolveY([block,positionDifference]){ //console.log("Latest axis set to y"); if (positionDifference.y > 0) { // Collision from above //console.log("Collision from above"); this.position.y = block.hitbox.position.y - this.height-this.collisionOffset; block.onCollision(this, new Vector(0,1)); // Notify the block of the collision this.onGround = true; // Set onGround to true this.passableOnGround.push(true); // Add to passableOnGround array }else if (positionDifference.mag < Math.sqrt(block.height*block.height + block.width*block.width) && positionDifference.y < 0) { // Collision from below //console.log("Collision from below"); this.position.y = block.hitbox.position.y + block.hitbox.offset2.y+this.collisionOffset; let velocityY = this.velocity.y block.onCollision(this,new Vector(0,-1)); // Notify the block of the collision // Prevents the entity from sticking to the bottom of blocks when gravity is negative if (velocityY < 0) { velocityY = this.gravity.y * 0.1; // Small positive value to push the entity downwards } this.velocity.y = velocityY; } } checkSensor(block){ if (this.groundSensor.isColliding(block.hitbox)){ this.touching.push(block); block.touching(this); return true; // At least one sensor is colliding } else { return false; // No collision with this sensor } } } export default Entity; // Ensure Entity is exported as default