Ian_ Posted November 26, 2017 Share Posted November 26, 2017 Hi there, I am looking into how projectiles can be fired, my intention is to try and fire in the direction that the cursor is at ( me.input.pointer.pos ). My first idea was to try and work out if the cursor needs to move in a positive or negative direction, I added `mainPlayer` to the pool, so somehow if I can get the position of them then I can work out which way to shoot in regards to right or left, but I'm not sure how to access the `mainPlayer`. How would you go about solving this problem? My Entities are below so you can see how they currently react /** * Player Entity */ game.PlayerEntity = me.Entity.extend({ /** * constructor */ init: function (x, y, settings) { settings = settings || { image: 'character_default_run', height: 32, width: 32 }; // call the constructor this._super(me.Entity, 'init', [x, y, settings]); // set the default horizontal & vertical speed (accel vector) this.body.setVelocity(1, 1); // set the display to follow our position on both axis me.game.viewport.follow(this.pos, me.game.viewport.AXIS.BOTH); // ensure the player is updated even when outside of the viewport this.alwaysUpdate = true; // define a basic walking animation (using all frames) this.renderable.addAnimation("walk", [0, 1, 2, 3, 4, 5, 6, 7]); // define a standing animation (using the first frame) this.renderable.addAnimation("stand", [0]); // set the standing animation as default this.renderable.setCurrentAnimation("stand"); this.body.collisionType = me.collision.types.PLAYER_OBJECT; }, /** * update the entity */ update: function (dt) { if (me.input.isKeyPressed("action1")) { var action = me.pool.pull("iceBeam", this.pos.x, this.pos.y); me.game.world.addChild(action); } if (me.input.isKeyPressed("run")) { this.body.setVelocity(2, 2); } else this.body.setVelocity(1, 1); if (me.input.isKeyPressed("left")) { // update the entity velocity this.renderable.flipX(true); this.body.vel.x -= this.body.accel.x * me.timer.tick; if (!this.renderable.isCurrentAnimation("walk")) { this.renderable.setCurrentAnimation("walk"); } } else if (me.input.isKeyPressed("right")) { // unflip the sprite this.renderable.flipX(false); // update the entity velocity this.body.vel.x += this.body.accel.x * me.timer.tick; // change to the walking animation if (!this.renderable.isCurrentAnimation("walk")) { this.renderable.setCurrentAnimation("walk"); } } else { this.body.vel.x = 0; } if (me.input.isKeyPressed("up")) { // update the entity velocity this.body.vel.y -= this.body.accel.y * me.timer.tick; if (!this.renderable.isCurrentAnimation("walk")) { this.renderable.setCurrentAnimation("walk"); } } else if (me.input.isKeyPressed("down")) { // update the entity velocity this.body.vel.y += this.body.accel.y * me.timer.tick; if (!this.renderable.isCurrentAnimation("walk")) { this.renderable.setCurrentAnimation("walk"); } } else { this.body.vel.y = 0; } if (this.body.vel.y === 0 && this.body.vel.x === 0) this.renderable.setCurrentAnimation("stand"); this.body.update(dt); // handle collisions against other shapes me.collision.check(this); // return true if we moved or if the renderable was updated return (this._super(me.Entity, 'update', [dt]) || this.body.vel.x !== 0 || this.body.vel.y !== 0); }, /** * colision handler * (called when colliding with other objects) */ onCollision: function (response, other) { if (other.body.collisionType === me.collision.types.PROJECTILE_OBJECT) { return false; } // Make all other objects solid return true; } }); game.Spell = me.Entity.extend({}); game.Spell.Icebeam = game.Spell.extend({ /** * constructor */ init: function (x, y, settings) { settings = settings || { image: 'short-ray', height: 86, width: 16 }; // call the constructor this._super(me.Entity, 'init', [x, y, settings]); this.alwaysUpdate = false; this.body.collisionType = me.collision.types.PROJECTILE_OBJECT; var pos = me.input.pointer.pos; this.endX = pos.x; this.endY = pos.y; console.log('Aiming at', pos); }, update: function (dt) { this.body.setVelocity(3,3); // If the current position isnt at the endpoint then move it there console.log(me.game.world.getChildByName("mainPlayer")); // if(this.pos.x <= this.endX && this) // { // // Set x velocity // this.body.vel.x += this.body.accel.x * me.timer.tick; // // } // else // me.game.world.destroy(this); // handle collisions against other shapes me.collision.check(this); this.body.update(dt); // return true if we moved or if the renderable was updated return (this._super(me.Entity, 'update', [dt]) || this.body.vel.x !== 0 || this.body.vel.y !== 0); }, onCollision: function (response, other) { if (other.body.collisionType === me.collision.types.PROJECTILE_OBJECT || other.body.collisionType === me.collision.types.PLAYER_OBJECT) { return false; } me.game.world.removeChild(this); return true; } }); Appreciate any pointers, thanks Quote Link to comment Share on other sites More sharing options...
agmcleod Posted November 29, 2017 Share Posted November 29, 2017 Hey there. In order to have something translate from one point to another, you need to do some calculation to determine the angle. First thing is to grab the angle in radians between both points. const angle = Math.atan2(targetPos.y - pos.y, targetPos.x - pos.x) // The ice beam that you're firing, use that angle to set its rotation: // For some reason we need to offset by 90degrees. I think it's due to the natural orientation of things in the canvas this.renderable.currentTransform.rotate(angle - 90 * Math.PI / 180) // then calculate the velocity this.body.setVelocity(Math.cos(angle) * 3, Math.sin(angle) * 3) Note I haven't tested this with MelonJS. This some older code i pulled out from a game in 2013 i did with melon, and quickly tested the math in a code pen: You may not need to subtract the 90 degrees from the angle, depending on how the matrix applies the rotation. Quote Link to comment Share on other sites More sharing options...
Ian_ Posted December 2, 2017 Author Share Posted December 2, 2017 On 11/29/2017 at 3:18 AM, agmcleod said: Hey there. In order to have something translate from one point to another, you need to do some calculation to determine the angle. First thing is to grab the angle in radians between both points. const angle = Math.atan2(targetPos.y - pos.y, targetPos.x - pos.x) // The ice beam that you're firing, use that angle to set its rotation: // For some reason we need to offset by 90degrees. I think it's due to the natural orientation of things in the canvas this.renderable.currentTransform.rotate(angle - 90 * Math.PI / 180) // then calculate the velocity this.body.setVelocity(Math.cos(angle) * 3, Math.sin(angle) * 3) Note I haven't tested this with MelonJS. This some older code i pulled out from a game in 2013 i did with melon, and quickly tested the math in a code pen: You may not need to subtract the 90 degrees from the angle, depending on how the matrix applies the rotation. Sort of works, the angle is indeed now correct, however it doesn't move to it's destination, I think I messed something up, I have updated the code below. game.Spell = me.Entity.extend({}); game.Spell.Icebeam = game.Spell.extend({ /** * constructor */ init: function (x, y, settings) { settings = settings || { image: 'short-ray', height: 86, width: 16 }; // call the constructor this._super(me.Entity, 'init', [x, y, settings]); this.alwaysUpdate = true; this.body.collisionType = me.collision.types.PROJECTILE_OBJECT; var pos = me.input.pointer.pos; this.endX = pos.x; this.endY = pos.y; // then calculate the velocity console.log('Aiming at', pos); }, update: function (dt) { // If the current position isnt at the endpoint then move it there const angle = Math.atan2(this.endY - this.body.pos.y, this.endX - this.body.pos.x); // The ice beam that you're firing, use that angle to set its rotation: // For some reason we need to offset by 90degrees. I think it's due to the natural orientation of things in the canvas this.renderable.currentTransform.rotate(angle - 90 * Math.PI / 180); // then calculate the velocity this.body.setVelocity(Math.cos(angle) * 3, Math.sin(angle) * 3); // If current path of protectile is not at the endpoint move forward // The ice beam that you're firing, use that angle to set its rotation: // For some reason we need to offset by 90degrees. I think it's due to the natural orientation of things in the canvas // handle collisions against other shapes me.collision.check(this); this.body.update(dt); // return true if we moved or if the renderable was updated return (this._super(me.Entity, 'update', [dt]) || this.body.vel.x !== 0 || this.body.vel.y !== 0); }, onCollision: function (response, other) { if (other.body.collisionType === me.collision.types.PROJECTILE_OBJECT || other.body.collisionType === me.collision.types.PLAYER_OBJECT) { return false; } console.log('Collision on ice beam other', other.body.collisionType); console.log('Collision on ice beam response', response.body.collisionType); me.game.world.removeChild(this); return true; } }); I would also like to note that the IceBeam entitity spins round and round on the spot ONLY when the player moves. Quote Link to comment Share on other sites More sharing options...
agmcleod Posted December 8, 2017 Share Posted December 8, 2017 Hey sorry for not getting back sooner. You just need to increase the velocity by the accel value: this.body.vel.x -= this.body.accel.x * me.timer.tick; this.body.vel.y -= this.body.accel.y * me.timer.tick; Do that after calling setVelocity, and before the body.update(). If you have a look a the source of setVelocity, you'll see it's setting the acceleration rate: https://github.com/melonjs/melonJS/blob/master/src/physics/body.js#L412 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.