I’ve been coding a sonic game here on PlayCanvas, and I got mostly everything done for my basic first step. Sonic can run through loops. His speed changes based on the angle he’s currently at (an angle variable is used). The method I’ve been using for rotation is simple. I check what tag the collision has, and the player adjusts it’s angle to the ground. (Ex. if player collides with collision with ‘turn45’, it turns 45 angles). Now with a slope, this isn’t as intuitive, as you can’t have separate blocks checking what angle the player should be at. I want to make it so that the player rotates accordingly to the slope angle. Basically, the angle variables changes depending on the angle of the slope. My problem is that I can’t figure out a good way to do this. Does anyone know how I can get my player to rotate on a slope accordingly, without using tags?
Code:
var PlayerScript = pc.createScript('playerScript');
//Variables
var xsp = 0;
var ysp = 0;
var gsp = 0;
var acc = 0.126875;
var dec = 0.5;
var frc = acc;
var limit = 14;
var goingRight;
var angle = 0;
var grv = 0.81875;
var grounded = false;
var pcos = true;
var air = 0.19375;
var jmp = 16.5;
var checkAir = true;
var isJumping = false;
//Animations
PlayerScript.attributes.add("main", { type: 'entity', title: 'Main' });
PlayerScript.attributes.add("idle", { type: 'entity', title: 'Idle' });
PlayerScript.attributes.add("walk", { type: 'entity', title: 'Walk' });
PlayerScript.attributes.add("run", { type: 'entity', title: 'Run' });
PlayerScript.attributes.add("jump", { type: 'entity', title: 'Jump' });
//Layers
PlayerScript.attributes.add("frontLayer", { type: 'entity', title: 'Front Layer' });
PlayerScript.attributes.add("backlayer", { type: 'entity', title: 'Back Layer' });
var frontLayer;
var backLayer;
// initialize code called once per entity
PlayerScript.prototype.initialize = function() {
this.app.keyboard.on(pc.EVENT_KEYDOWN, this.onKeyDown, this);
this.app.keyboard.on(pc.EVENT_KEYUP, this.onKeyUp, this);
this.entity.collision.on('collisionstart', this.onCollisionStart, this);
this.entity.collision.on('contact', this.onContact, this);
this.idle.enabled = true;
this.walk.enabled = false;
this.run.enabled = false;
this.jump.enabled = false;
frontLayer = this.app.root.findByName('Front Layer');
backLayer = this.app.root.findByName('Back Layer');
};
// update code called every frame
PlayerScript.prototype.update = function(dt) {
//Main
this.entity.rigidbody.linearVelocity = new pc.Vec3(xsp, ysp, 0);
if (pcos === true) {
xsp = gsp * this.cosine(angle);
if (grounded === true) {
ysp = gsp * this.sine(angle);
}
}
//Functions
this.movement();
this.friction();
this.gravity();
this.animation();
this.flip();
};
PlayerScript.prototype.movement = function() {
//Main Movement Check
if (checkAir === false) {
if (this.app.keyboard.isPressed(pc.KEY_RIGHT)) {
gsp += acc;
goingRight = true;
}
if (this.app.keyboard.isPressed(pc.KEY_LEFT)) {
gsp -= acc;
goingRight = false;
}
if ((!this.app.keyboard.isPressed(pc.KEY_RIGHT) && !this.app.keyboard.isPressed(pc.KEY_LEFT)) || (this.app.keyboard.isPressed(pc.KEY_RIGHT) && this.app.keyboard.isPressed(pc.KEY_LEFT))) {
goingRight = null;
}
}
if (checkAir === true) {
if (this.app.keyboard.isPressed(pc.KEY_RIGHT)) {
gsp += air;
goingRight = true;
}
if (this.app.keyboard.isPressed(pc.KEY_LEFT)) {
gsp -= air;
goingRight = false;
}
//Air Drag
if (ysp > 0 && ysp < 14) {
if (Math.abs(xsp) >= 0.125) {
xsp = xsp * 0.96875;
}
}
}
//Jump
if (this.app.keyboard.wasPressed(pc.KEY_A) && grounded === true) {
ysp += jmp;
grounded = false;
isJumping = true;
}
//Limits
if (gsp > limit || gsp < -limit) {
if (gsp > limit) {
gsp = limit;
}
if (gsp < -limit) {
gsp = -limit;
}
}
};
PlayerScript.prototype.friction = function() {
//Main
if (gsp > 0 && goingRight === false) {
gsp = gsp - dec;
}
if (gsp < 0 && goingRight === true) {
gsp = gsp + dec;
}
if ((gsp > 0 || gsp < 0) && goingRight === null) {
if (gsp > 0) {
gsp -= frc;
}
if (gsp < 0) {
gsp += frc;
}
if (gsp < frc && gsp > -frc && gsp !== 0) {
gsp = 0;
if (gsp === 0) {
gsp = gsp;
}
}
}
};
PlayerScript.prototype.gravity = function() {
//Main
if (grounded === false) {
ysp -= grv;
if (ysp < -26) {
ysp = -16;
}
checkAir = true;
}
if (grounded === true && ysp !== 0) {
ysp = ysp;
if (ysp === 0) {
ysp = ysp;
}
checkAir = false;
}
};
PlayerScript.prototype.animation = function() {
if ((gsp < 0.01 && gsp > -0.01) && isJumping === false) {
this.idle.enabled = true;
this.walk.enabled = false;
this.run.enabled = false;
this.jump.enabled = false;
}
if (((gsp > 0.01 && gsp < limit) || (gsp < -0.01 && gsp > -limit)) && isJumping === false) {
this.idle.enabled = false;
this.walk.enabled = true;
this.run.enabled = false;
this.jump.enabled = false;
}
if ((gsp >= limit || gsp <= -limit) && isJumping === false) {
this.idle.enabled = false;
this.walk.enabled = false;
this.run.enabled = true;
this.jump.enabled = false;
}
if (isJumping === true) {
this.idle.enabled = false;
this.walk.enabled = false;
this.run.enabled = false;
this.jump.enabled = true;
}
};
PlayerScript.prototype.flip = function() {
if (goingRight === true && gsp > 0) {
this.main.setLocalScale(1, 1, 1);
}
if (goingRight === false && gsp < 0) {
this.main.setLocalScale(-1, 1, 1);
}
};
PlayerScript.prototype.onCollisionStart = function(result) {
//Check Ground
if (result.other.tags.has('ground')) {
grounded = true;
checkAir = false;
isJumping = false;
}
//Rotations
if (result.other.tags.has('turn0')) {
this.entity.rigidbody.teleport(this.entity.getPosition().x, this.entity.getPosition().y, this.entity.getPosition().z, 0, 0, 0);
}
if (result.other.tags.has('turn45')) {
this.entity.rigidbody.teleport(this.entity.getPosition().x, this.entity.getPosition().y, this.entity.getPosition().z, 0, 0, 45);
}
if (result.other.tags.has('turn90')) {
this.entity.rigidbody.teleport(this.entity.getPosition().x, this.entity.getPosition().y, this.entity.getPosition().z, 0, 0, 90);
}
if (result.other.tags.has('turn135')) {
this.entity.rigidbody.teleport(this.entity.getPosition().x, this.entity.getPosition().y, this.entity.getPosition().z, 0, 0, 135);
}
if (result.other.tags.has('turn180')) {
this.entity.rigidbody.teleport(this.entity.getPosition().x, this.entity.getPosition().y, this.entity.getPosition().z, 0, 0, 180);
}
if (result.other.tags.has('turn225')) {
this.entity.rigidbody.teleport(this.entity.getPosition().x, this.entity.getPosition().y, this.entity.getPosition().z, 0, 0, 225);
}
if (result.other.tags.has('turn270')) {
this.entity.rigidbody.teleport(this.entity.getPosition().x, this.entity.getPosition().y, this.entity.getPosition().z, 0, 0, 270);
}
if (result.other.tags.has('turn315')) {
this.entity.rigidbody.teleport(this.entity.getPosition().x, this.entity.getPosition().y, this.entity.getPosition().z, 0, 0, 315);
}
//Switch Layers
if (result.other.tags.has('switchLayer')) {
frontLayer.enabled = !frontLayer.enabled;
backLayer.enabled = !backLayer.enabled;
}
};
PlayerScript.prototype.onContact = function(result) {
//Rotations
if (result.other.tags.has('turn0')) {
angle = 0;
pcos = true;
}
if (result.other.tags.has('turn45')) {
angle = 45;
pcos = true;
}
if (result.other.tags.has('turn90')) {
angle = 90;
pcos = true;
}
if (result.other.tags.has('turn135')) {
angle = 144;
pcos = true;
}
if (result.other.tags.has('turn180')) {
angle = 0;
pcos = false;
xsp = gsp * -this.cosine(angle);
ysp = gsp * -this.sine(angle);
}
if (result.other.tags.has('turn225')) {
angle = -126;
pcos = true;
}
if (result.other.tags.has('turn270')) {
angle = -90;
pcos = true;
}
if (result.other.tags.has('turn315')) {
angle = -45;
pcos = true;
}
};
PlayerScript.prototype.sine = function(value) {
var accuracy = 0.0001, denominator, sinx, sinval;
//Convert Degrees to Radians
value = value * (3.142 / 180.0);
var x1 = value;
//Maps the Sum along the Series
sinx = value;
//Holds the actual value of sin(value)
sinval = Math.sin(value);
var i = 1;
do {
denominator = 2 * i * (2 * i + 1);
x1 = -x1 * value * value / denominator;
sinx = sinx + x1;
i = i + 1;
} while (accuracy <= sinval - sinx);
return sinx;
};
PlayerScript.prototype.cosine = function(value) {
var accuracy = 0.0001, x1, denominator, cosx, cosval;
//Converting Degrees to Radians
value = value * (3.142 / 180.0);
x1 = 1;
//Maps the Sum along the Series
cosx = x1;
//Holds the actual value of cosine(value)
cosval = Math.cos(value);
var i = 1;
do {
denominator = 2 * i * (2 * i - 1);
x1 = -x1 * value * value / denominator;
cosx = cosx + x1;
i = i + 1;
} while (accuracy <= cosval - cosx);
return cosx;
};
// swap method called for script hot-reloading
// inherit your script state here
// PlayerScript.prototype.swap = function(old) { };
// to learn more about script anatomy, please read:
// http://developer.playcanvas.com/en/user-manual/scripting/
Link To Editor: https://playcanvas.com/editor/scene/926034