Open ICEGAMER opened 7 years ago
Do the bricks have to work like the ones in Mario? Like as in you can push them upwards when you jump? Example: https://github.com/Camto/Brix
yes pls, and how did you make him jump only once when pressed on W ?
You have to make sure the player only jumps when it's touching the floor.
If you look in the code, you might notice that the you
object (representing the player) never actually touches anything at the end of it's update cycle.
It's always at least one pixel away from everything, if not, it'd be able to jump off anything.
In my code, first, the player changes it's y (you.y
) position by it's y velocity (you.yv
) with this.y += this.yv;
and then, I check if it's colliding width any object (touching_world
is set to true
if it is and false
if it isn't). If it's touching a brick with it's top though, push the brick upward (check in Brick.js
) and push the player out of the brick, but if the brick can't go any higher, set touching_world = true;
and push the player out of the brick.
If it ISN'T colliding with the world, I increase it's y velocity this.yv += 0.25;
(since positive y is lower on the canvas, gravity makes your y position increase) and if his y is over 6, I set it back to 6 with if(this.yv > 6) { this.yv = 6; }
If it IS colliding with the world, it means it's either touching the floor or the roof (because it can't be touching the side, if in the x moving part it gets kicked out of the side). Then I push it out of wherever it is (roof/floor) with this.y -= this.yv;
. Next, I set it's y velocity to 0 this.yv = 0;
because if it's touching the roof, it has to fall back down and if it's touching the floor, I don't want the player to fall under it. Afterwards, I lower it's y position by one this.y++;
(downwards) so if it used to be in the roof, it would be way under it, but if it was in the floor, he's pushed back in (so it can jump, btw it's y position gets increased back up later). Then, if it's touching the floor (remember: can't be in ceiling and can't be in side, so it's got to be on the floor) and the player is pressing up, let it jump this.yv = -5;
! After all that I finally increase the player's position back up one pixel this.y--;
Sorry the script is so complex, that's just how it is.
(btw, the brick pushing mechanism has room for improvement, but I had to figure out by myself)
Just fyi, there are some things in your code that you should modify:
Don't call GotoMidGuys()
every frame, once the canvas goes to the center, it'll stay there. (no, it won't try to escape)
DO NOT use functions that return objects as constructors, instead use special constructor function or event better, classes:
constructor function:
function Brick(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
Use: `brickList.push( new Brick(100, 500, 400, 20) );`
* class:
```javascript
class Brick {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
Use: brickList.push( new Brick(100, 500, 400, 20) );
I suggest classes because once you master them, everything gets so much simpler and you can add methods (functions for all instances of an object) with ease. In case you'd like to learn more about classes: Classes - JavaScript | MDN
Collision detection between two objects should be a function of it's own:
function collide(obj1, obj2) {
return ((obj1.x < (obj2.x + obj2.width)) && ((obj1.x + obj1.width) > obj2.x) && (obj1.y < (obj2.y + obj2.height)) && ((obj1.y + obj1.height) > obj2.y)); // Classic AABB (A.xis A.ligned B.ounding B.ox).
}
Example:
object_1 = {x: 1, y: 1, width: 5, height: 5};
object_2 = {x: 3, y: 2, width: 3, height: 4};
collide(object_1, object_2); // returns "true" because both objects are touching.
Use ONE event to check for key presses:
In this case, keys
is an object which is also a list of all the keys that are currently being pressed:
keys = {}; // Make a global variable called keys, it will hold ALL keys pressed.
document.addEventListener("keydown", function(key) { // When the user presses any key, it will be registered as "true" in the object "keys".
keys[key.keyCode] = true; // Even if "keys" is an object you can acces it's properties with square brackets [].
});
document.addEventListener("keydown", function(key) { // When the user STOPS pressing any key, it will be registered as "false" in the object "keys".
delete keys[key.keyCode]; // We will delete from the list the key which is NOT pressed.
}); // If you think an error would pop up for keys that don't exist, fear not, undefined counts as false for if statements.
key_codes = { // We will keep a register of all keys we care about. for more key codes, I found "keycode.info" (it works fine).
up: 38, // These keys are the basic platformer keys: up / w for jump, left / a for left movement, and right / d for right movement.
left: 37,
right: 39,
w: 87,
a: 65,
d: 68
}
To know if a key is being pressed, just use: keys[key_codes.up]
, it'll return true
if the user is pressing the up arrow key.
To check if the user is pressing at least one out of two keys, use the ||
operator like so: (keys[key_codes.up] || keys[key_codes.w])
, it'll return true
if the user is pressing the up arrow key or the w key.
I know this is a lot at once, but after a while of copy, pasting, and modifying variable names, you'll get the hang of it.
thank you ill try to understand all the code
Your welcome. Glad I could help!
hey Camto maybe you can help me ? with collision i have a problem heres my project
Hey ICEGAMER, I can see that you use p5.js
as another canvas API, but what's Matter.js
doing in your libraries?
I think your main problem is in how you make the 'jumper' move in moveJumper()
.
By the way, in jumperCollisions()
(line 230) you have to replace if (jumper.y > canvas.width)
by if (jumper.x > canvas.width)
because the jumper can wrap around the screen to the left, but not to the right. Seriously, try it.
thank you it way a typo with a jumper and th libraries is was thinking that matter.js will make my jumps better but p5.js and matter.js make another canvas so to use then i needed to rec0de my game
The way I understand your code is:
Move cactus's x by his x velocity.
Move cactus's y by his y velocity.
If he's touching a brick:
Stop his up or down velocity.
I can see that you put the controls in another function, but you shouldn't do that. If the controls are separate from the physics, they can de-synchronize, and that can lead to glitches. Instead, you can do that when a key event is triggered, a variable is switched on or off, but that the physics still controls the player's speed. The correct version is:
// The cactus's x movement. If the player is pressing left: Change the cactus's x velocity by -1. // Go left! If the player is pressing right: Change the cactus's x velocity by 1. // Go right! Change the cactus's x velocity to itself times friction. // Slow down over time. Move his x by his x velocity. // Actually do the moving. If he's touching a brick: Move him back. // Move the cactus's x position by the negative x velocity. Set his x velocity to 0. // Stop his movement. // End of the cactus's x movement. // The cactus's y movement. Move the cactus's y by his y velocity. // Move up or down. If he's touching a brick: Move him back. // Move the cactus's y position by the negative y velocity. Set his y velocity to 0. // Stop his movement. Move the cactus down one pixel. // If he got forced out of the floor, force him back in, but if he got forced out of the ceiling, going down won't get him back into the ceiling. If he's touching a brick AND pressing up: // If he got forced back into the floor. Set his y velocity up to his maximum jump speed. // JUMP! Move the cactus back up one pixel. else: // If he was never touching a brick in the FIRST place. Change the cactus's y velocity by the fall speed. // Make him fall. If he's going faster than the maximum fall speed: Make him go at the maximum fall speed instead. // End of the cactus's y movement.
I use that pseudocode (words that can easily be translated to code: WikiPedia's article on pseudocode) in EVERY platformer I make that uses normal physics.
In your game, it would be:
function moveJumper() {
// The cactus's x movement.
if(keys[key_codes.a]) {
jumper.speedX -= 1; // Go left!
}
if(keys[key_codes.d]) {
jumper.speedX +=1; // Go right!
}
jumper.speedX *= 0.95; // Slow down over time.
jumper.x += jumper.speedX; // Actually do the moving.
var touching_brick = false;
for(var i = 0; i < brickList.length; i++) {
let brick = brickList[i];
if(jumper.x < brick.x + brick.width && jumper.x + jumper.width > brick.x && jumper.y < brick.y + brick.height && jumper.y + jumper.height > brick.y) {
touching_brick = true;
}
}
if(touching_brick) {
jumper.x -= jumper.speedX; // Move the cactus's x position by the negative x velocity.
jumper.speedX = 0; // Stop his movement.
}
// End of the cactus's x movement.
// The cactus's y movement.
jumper.y += jumper.speedY; // Move up or down.
var touching_brick = false;
for(var i = 0; i < brickList.length; i++) {
let brick = brickList[i];
if(jumper.x < brick.x + brick.width && jumper.x + jumper.width > brick.x && jumper.y < brick.y + brick.height && jumper.y + jumper.height > brick.y) {
touching_brick = true;
}
}
if(touching_brick) {
jumper.y -= jumper.speedY; // Move the cactus's y position by the negative y velocity.
Set his y velocity to 0. // Stop his movement.
jumper.y++; // If he got forced out of the floor, force him back in, but if he got forced out of the ceiling, going down won't get him back into the ceiling.
var touching_brick = false;
for(var i = 0; i < brickList.length; i++) {
let brick = brickList[i];
if(jumper.x < brick.x + brick.width && jumper.x + jumper.width > brick.x && jumper.y < brick.y + brick.height && jumper.y + jumper.height > brick.y) {
touching_brick = true;
}
}
if(touching_brick && keys[key_codes.w]) { // If he got forced back into the floor.
jumper.speedY = 10; // JUMP!
}
jumper.y--;
} else { // If he was never touching a brick in the FIRST place.
jumper.speedY += 0.2; // Make him fall.
if(jumper.speedY > 10) {
jumper.speedY = 10;
}
}
// End of the cactus's y movement.
}
I used the same commets in the pseudocode as in the JavaScript alternative.
By the way, this script assumes you've defined keys
. So you still have to do that. (Check previous answers)
can you guys help me to make the collision(its in function checkBrickCollisions) with the brick so the player jumps jn them and helpe me make so the jumper jumps only once heres the code (JS)
var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d');
var jumperColor = '#660033';; var jumperXSpeed = 10; var gravity = 9.8;
var brickList = [];
var jumper = { width: 30, height: 30, x: 450, y: 50, mass: 100,
}
var brick = createBrick(100, 500, 400, 20); brickList.push(brick); brick = createBrick(400, 300, 200, 20); brickList.push(brick);
registerKeyboard(); setInterval(gameController, 10);
function gameController() { draw(); move(); }
function move () { moveJumper() }
function draw () { clearCanvas(); drawJumper(); drawBricks(); GotoMidGuys(); }
function drawBricks() { for (var i = 0; i < brickList.length; i++) { var brick = brickList[i]; context.fillStyle = "#3E263A"; context.fillRect(brick.x, brick.y, brick.width, brick.height); } }
function moveJumper()
{ jumper.x += jumper.speedX; jumper.y += jumper.speedY;
}
function getRandomCoordinate() { return Math.floor(Math.random() * squareCount + 1); }
function clearCanvas() { context.clearRect(0, 0, 600, 600); }
function drawJumper () { context.fillStyle = jumperColor; context.fillRect(jumper.x, jumper.y, jumper.width, jumper.height);
}
function GotoMidGuys() { document.getElementById("canvas").style.marginLeft = "auto"; document.getElementById("canvas").style.marginRight = "auto"; canvas.style.display = 'block'; }
function registerKeyboard() { document.addEventListener('keydown', function (event) { / key codes W = 119 S = 115 A = 65 D = 68 /
}
function createBrick(x, y, width, height) { return { width: width, height: height, x: x, y: y } }
function checkCollisions () { checkBrickcollisions(); }
function checkBrickCollisions () { for (var i = 0; i < brickList.length; i++) { var brick = brickList[i]; if (jumper.x + jumper.width >= brick.x && jumper.x <= brick.x + brick.width && jumper.y > brick.y && jumper.y <= brick.y + brick.height) { jumper.speedY -= jumper.speedY ; jumper.speedx -= jumper.speedx ; gravity -= gravity; } } }