Game not iterating, not sure why - javascript

I'm trying to make a browser game with pure javascript. I was using codesandbox.io for writing it at first, but the I decided I was done for the day and needed to check if it works in a browser. Lo and behold, it does not. I genuinely have no idea why it's not working.
All the code is supposed to do, is make a square jump. which it does do, however right when you let go of the up key, the page hangs, it won't even refresh. Doesn't crash the browser though. Anyways, here's my code.
class player {
constructor(gameW, gameH) {
this.gameH = gameH;
this.width = 50;
this.heigth = 50;
this.maxUpV = 5;
this.currV = 0;
this.gravConst = 50;
this.position = {
x: 50,
y: 150
};
}
jumpUp() {
this.currV = -this.maxUpV;
}
fall(falling) {
while (this.position.y < 150) {
this.currV = this.maxUpV;
}
return (falling = false);
}
draw(ctx) {
ctx.fillStyle = "#F00";
ctx.fillRect(this.position.x, this.position.y, this.width, this.heigth);
}
update(deltaTime) {
if (!deltaTime) {
return;
}
this.position.y += this.currV;
if (this.position.y + this.heigth > 200) {
this.position.y = 150;
}
}
}
class input {
constructor(Player) {
this.falling = false;
document.addEventListener("keydown", event => {
if (event.keyCode === 38) {
if (!Player.fall(this.falling)) {
Player.jumpUp();
}
}
});
document.addEventListener("keyup", event => {
if (event.keyCode === 38) {
this.falling = true;
Player.fall(this.falling);
}
});
}
}
const GAME_WIDTH = 800;
const GAME_HEIGHT = 300;
var canvas = document.getElementById("gameScreen");
var ctx = canvas.getContext("2d");
var Player = new player(GAME_WIDTH, GAME_HEIGHT);
ctx.clearRect(0, 0, 800, 300);
ctx.fillRect(0, 200, 800, 200);
ctx.fillRect(400, 100, 50, 1);
Player.draw(ctx);
new input(Player);
var lastTime = 0;
function gameLoop(timeStamp) {
var deltaTime = timeStamp - lastTime;
lastTime = timeStamp;
ctx.clearRect(0, 0, 800, 200);
Player.update(deltaTime);
Player.draw(ctx);
requestAnimationFrame(gameLoop);
}
gameLoop();
Oh and also, when I was writing it in codesandbox.io, the classes were separate files that I imported into the main .js file. That gave me an error in the browser, so I just put everything in one file. I tried both Vivaldi and Firefox, to no avail.

I originally misread the question. Your code is locking up in your fall function. Once you hit the max height you were getting stuck in a loop waiting for the fall but never returning control to anywhere that could generate a fall. I'm having some difficulty understanding your max height validation.
The fall function will always return false.
fall(falling) {
while (this.position.y < 150) {
this.currV = this.maxUpV;
}
return (falling = false);
}
The return value of an assignment is the value assigned, so in this case your return value will always be false
I also had to modify the logic for the end button press
if (!Player.fall(this.falling)) {
Player.jumpUp();
}
The conditional was basically always returning true and could be simplified.
I hope this helps!
class player {
constructor(gameW, gameH) {
this.gameH = gameH;
this.width = 50;
this.height = 50;
this.maxUpV = 5;
this.currV = 0;
this.gravConst = 50;
this.position = {
x: 50,
y: 150
};
}
jumpUp() {
this.currV = -this.maxUpV;
}
fall(falling) {
if (this.position.y <150) {
this.currV = this.maxUpV;
return true
}
return false;
}
draw(ctx) {
ctx.fillStyle = "#F00";
ctx.fillRect(this.position.x, this.position.y, this.width, this.height);
}
update(deltaTime) {
if (!deltaTime) {
return;
}
this.position.y += this.currV;
if (this.position.y + this.height > 200) {
this.position.y = 150;
}
}
}
class input {
constructor(Player) {
this.falling = false;
document.addEventListener("keydown", event => {
if (event.keyCode === 38) {
if (!this.falling) {
Player.jumpUp();
}
}
});
document.addEventListener("keyup", event => {
if (event.keyCode === 38) {
this.falling = true;
this.falling = Player.fall();
}
});
}
}
const GAME_WIDTH = 800;
const GAME_HEIGHT = 300;
var canvas = document.getElementById("gameScreen");
var ctx = canvas.getContext("2d");
var Player = new player(GAME_WIDTH, GAME_HEIGHT);
ctx.clearRect(0, 0, 800, 300);
ctx.fillRect(0, 200, 800, 200);
ctx.fillRect(400, 100, 50, 1);
Player.draw(ctx);
new input(Player);
var lastTime = 0;
function gameLoop(timeStamp) {
var deltaTime = timeStamp - lastTime;
lastTime = timeStamp;
ctx.clearRect(0, 0, 800, 200);
Player.update(deltaTime);
Player.draw(ctx);
requestAnimationFrame(gameLoop);
}
gameLoop();
<canvas id="gameScreen" width=400 height=400></canvas>

Related

Adding cursor movement function to the object creating function in javascript doesn't work

I am creating this game where you move a block with your mouse and avoid obstacles that are being created from right side of the screen to the left, my cursor used to work fine, so did the obstacle creation, but when i combined them it doesn't seem to work anymore and i can't figure out why, here is the game code,
var myGamePiece;
var myObstacles = [];
function startGame() {
myGamePiece = new component(30, 30, "red", 10, 120);
myGameArea.start();
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 600;
this.canvas.height = 600;
this.canvas.style.cursor = "none";
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('mousemove', function(e) {
myGameArea.x = e.pageX;
myGameArea.y = e.pageY;
})
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop: function() {
clearInterval(this.interval);
}
}
function everyinterval(n) {
if ((myGameArea.frameNo / n) % 1 == 0) {
return true;
}
return false;
}
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) ||
(mytop > otherbottom) ||
(myright < otherleft) ||
(myleft > otherright)) {
crash = false;
}
return crash;
}
}
function updateGameArea() {
var x, y;
for (i = 0; i < myObstacles.length; i += 1) {
if (myGamePiece.crashWith(myObstacles[i])) {
myGameArea.stop();
return;
myGameArea.clear();
myObstacle.x += -1;
myObstacle.update();
if (myGameArea.x && myGameArea.y) {
myGamePiece.x = myGameArea.x;
myGamePiece.y = myGameArea.y;
}
myGamePiece.update();
}
}
}
myGameArea.clear();
myGameArea.frameNo += 1;
if (myGameArea.frameNo == 1 || everyinterval(150)) {
x = myGameArea.canvas.width;
y = myGameArea.canvas.height - 200;
myObstacles.push(new component(10, 20, "green", x, y));
}
for (i = 0; i < myObstacles.length; i += 1) {
myObstacles[i].x += -1;
myObstacles[i].update();
}
startGame();
canvas {
border: 1px solid #d3d3d3;
background-color: #f1f1f1;
}
<body>
<p>move the cursor to move the blocky boii!</p>
</body>
if you guys figure out what's wrong with it and possibly add why and what am i doing wrong in the code in general (structure, position etc) i would be very grateful, feel free to hate and criticize the code, I am self learner and don't wont to get the wrong habits that will be difficult to get rid of in the future.
thank you for reply
I respect anyone who is open to improving, so please let me know if this helps. For further code improvements, tips, etc, I'd like to point you towards Code Review Stack Exchange. I'll put my notes and working code here, but it's bound to get rather long. First, though, your immediate errors are fixed and commented in the snippet below. (Mostly comes down to "fix your curly braces")
Errors Fixed
var myGamePiece;
var myObstacles = [];
function startGame() {
myGamePiece = new component(30, 30, "red", 10, 120);
myGameArea.start();
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 600;
this.canvas.height = 600;
this.canvas.style.cursor = "none";
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
window.addEventListener('mousemove', function(e) {
myGameArea.x = e.pageX;
myGameArea.y = e.pageY;
})
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop: function() {
clearInterval(this.interval);
}
}
function everyinterval(n) {
if ((myGameArea.frameNo / n) % 1 == 0) {
return true;
}
return false;
}
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) ||
(mytop > otherbottom) ||
(myright < otherleft) ||
(myleft > otherright)) {
crash = false;
}
return crash;
}
}
function updateGameArea() {
var x, y;
for (i = 0; i < myObstacles.length; i += 1) {
var myObstacle = myObstacles[i] // problem 3: this was missing
if (myGamePiece.crashWith(myObstacle)) {
myGameArea.stop();
return;
} // problem 4: needed to be closed
myGameArea.clear();
myObstacle.x += -1;
myObstacle.update();
if (myGameArea.x && myGameArea.y) {
myGamePiece.x = myGameArea.x;
myGamePiece.y = myGameArea.y;
}
myGamePiece.update();
}
// problem 1, from here down needed moved into the updateGameArea() function
// problem 2: myGameArea.clear(); needed removed from here
myGameArea.frameNo += 1;
if (myGameArea.frameNo == 1 || everyinterval(150)) {
x = myGameArea.canvas.width;
y = myGameArea.canvas.height - 200;
myObstacles.push(new component(10, 20, "green", x, y));
}
for (i = 0; i < myObstacles.length; i += 1) {
myObstacles[i].x += -1;
myObstacles[i].update();
}
}
startGame();
canvas {
border: 1px solid #d3d3d3;
background-color: #f1f1f1;
}
<p>move the cursor to move the blocky boii!</p>
Further Notes/Tips
General Development
Using some type of tool (like Atom, VSCode, etc) may help you identify where blocks start and end. You can often hover over an opening { and the matching } will get highlighted
You should delete obstacles so you don't infinitely spawn new ones
Try to keep "circular dependencies" out of your code
Time-based, rather than frame-based logic helps keep things moving smoothly. For the most basic approach, you can animate/move entities using the time since the last frame.
JavaScript
Knowing how prototypes work in JS can help keep your memory usage down and your game running faster. Your code currently adds new functions to every "component" instance when they get created
In the JS community, we have a couple standard style guides and conventions. For example, we usually capitalize constructor functions (and classes from ES2015). Check out some of the more complete guides like Standard and/or AirBnB to know what is considered common. (helps us speak the same language)
If you don't already know it, ES2015+ provides a number of improvements (often maintenance related) over older code. For example using const and let is now often more "normal" than using var, as is using arrow functions instead of regular functions. (these decisions are mostly highlighted in the style guides I provided above)
Try to avoid polluting the global namespace by creating variables like myGamePiece and myObstacles. Contain them using scoping somehow. In the code below, I used an IIFE to keep variables local to that code. The fewer implicit interactions we have between scripts, the better.
Also, avoid global functions, when you can. For example, most events you might need are best handled via .addEventListener(). Your pre-edit question included <body onload="startGame()">, which requires a global function. This can be replaced with a simple startGame() call within a script tag right above </body> OR you can use something like document.addEventListener('DOMContentLoaded', startGame)
You can create a better game loop using window.requestAnimationFrame() (see this documentation for more info)
Ideally, each of these classes and functions could be split into separate modules/files as they grow, too. It can be incredibly helpful to see the structure/architecture of an application without needing to read through the full code to understand...which leads me to the next section:
Architecture
Game developers often split up the parts of their games according to an architecture called ECS. I'd recommend learning how this works before going too deep. It's not considered a perfect architecture at its most basic form, but the goals behind it hold merit.
Also check out Functional Programming (FP) and what it considers to be "state". ECS is basically just FP within the context of a game loop.
Aligning yourself with the common terminology of each part will help you search for the details you don't yet know. I changed a few names around in my additional snippet below like "component" -> "Entity" and "crash" to "collision/collide" in an effort to align with what these parts are commonly called.
Putting the notes together...
The snippet below still isn't perfect, but I hope it demonstrates most of the points I provided above. I started with your code and slowly went through refactoring steps until it became what you see below:
;(() => {
class CanvasCamera2D {
constructor(canvas) {
this.canvas = canvas
this.context = canvas.getContext('2d')
}
get width() { return this.canvas.width }
get height() { return this.canvas.height }
clear() {
this.context.clearRect(0, 0, this.width, this.height)
}
render(fn) {
fn(this.context, this.canvas)
}
}
class Entity {
constructor(type, width, height, x = 0, y = 0) {
this.type = type
this.width = width
this.height = height
this.x = x
this.y = y
}
get left() { return this.x }
get right() { return this.x + this.width }
get top() { return this.y }
get bottom() { return this.y + this.height }
collidedWith(otherobj) {
return !(
(this.bottom < otherobj.top) ||
(this.top > otherobj.bottom) ||
(this.right < otherobj.left) ||
(this.left > otherobj.right)
)
}
}
const update = (
{ // state
gamePiece,
obstacles,
mouse,
deltaTime,
timestamp,
lastSpawnTime
},
{ // actions
stopGame,
setLastSpawnTime,
filterObstacles,
setGamePiecePosition,
},
camera
) => {
// Add an obstacle every so many milliseconds
if ((timestamp - lastSpawnTime) >= 800) {
obstacles.push(
new Entity('obstacle', 10, 20, camera.width, camera.height - 200)
)
setLastSpawnTime(timestamp)
}
// Go through each obstacle and check for collisions
filterObstacles(obstacle => {
if (obstacle.collidedWith(gamePiece)) {
stopGame()
}
// Move obstacles until they hit 0 (then remove from the list)
obstacle.x -= deltaTime / 4
return !(obstacle.x < 0)
})
// Move gamePiece with mouse
setGamePiecePosition(mouse.x, mouse.y)
}
const render = ({ gamePiece, obstacles }, camera) => {
camera.clear()
const entities = [gamePiece].concat(obstacles)
entities.forEach(entity => camera.render(ctx => {
ctx.fillStyle = entity.type === 'gamePiece' ? 'green' : 'red'
ctx.fillRect(entity.x, entity.y, entity.width, entity.height)
}))
}
const startGame = (update, render, inState, maxFrameRate) => {
const state = Object.assign({
deltaTime: 0,
timestamp: 0,
lastSpawnTime: 0,
gameRunning: true,
}, inState)
// Created in an effort to avoid direct modification of state
const actions = {
stopGame() { state.gameRunning = false },
setLastSpawnTime(time) { state.lastSpawnTime = time },
filterObstacles(fn) { state.obstacles = state.obstacles.filter(fn) },
setGamePiecePosition(x, y) { Object.assign(state.gamePiece, { x, y }) },
setMousePosition(x, y) { Object.assign(state.mouse, { x, y }) },
}
// Set up camera
const canvas = Object.assign(document.createElement('canvas'), {
width: 300,
height: 300,
})
document.body.insertBefore(canvas, document.body.childNodes[0])
const camera = new CanvasCamera2D(canvas)
// Update state when mouse moves (scaled in case canvas changes in size)
window.addEventListener('mousemove', e => {
actions.setMousePosition(
e.pageX * (canvas.width / canvas.clientWidth),
e.pageY * (canvas.height / canvas.clientHeight),
)
})
// Start game loop
let lastTimestamp = performance.now()
const loop = (timestamp) => {
const delta = timestamp - lastTimestamp
if (delta > MAX_FRAME_RATE) {
state.timestamp = timestamp
state.deltaTime = delta
update(state, actions, camera)
render(state, camera)
lastTimestamp = timestamp
if (!state.gameRunning) return
}
requestAnimationFrame(loop)
}
loop(performance.now())
}
const MAX_FRAME_RATE = 60 / 1000
startGame(update, render, {
mouse: { x: 0, y: 0 },
gamePiece: new Entity('gamePiece', 30, 30, 10, 120),
obstacles: [],
}, MAX_FRAME_RATE)
})()
canvas {
border: 1px solid #d3d3d3;
background-color: #f1f1f1;
max-width: 100%;
cursor: none;
}
<p>move the cursor to move the blocky boii!</p>

There is a problem with my previous character positions in canvas

I'm working to a JS game where I have a player named Ronin and the game is something like a 2d platformer. I worked on canvas to make him and I made him move x pixels to left/ right at keys A/D onkeydown. The problem is that I can't erase his 'copies' (previous positions of the character that now should dissapear). I would not want to use ctx.clearRect(), so please give me another solution.
Thanks in advance!
WalkLeft1------WalkLeft2------WalkRight1------WalkRight2
/* Walk Left/Right 1/2 in the description no matter with the'broken' state file, it's because it can't draw a file that he does not know :) */
/* ------------------------------------------ */
/* files in my directory:
index.html
style.css
script.js
Costumes >
WalkLeft >
WalkLeft1.jpg
WalkLeft2.jpg
WalkRight >
WalkRight1.jpg
WalkRight2.jpg
*/
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
Scene = function () {
this.x = 0;
this.y = 0;
this.w = canvas.width;
this.h = canvas.height;
this.style = {
fillStyle: "white",
strokeStyle: "red",
lineWidth: 5,
}
this.draw = function () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = this.style.fillStyle;
ctx.strokeStyle = this.style.strokeStyle;
ctx.lineWidth = this.style.lineWidth;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
Character = function () {
this.width = 77;
this.height = 92;
this.x = 10;
this.vx = 20;
this.padding = 10;
this.y = canvas.height - this.height - 10;
this.img0 = document.getElementById("img0");
this.img1 = document.getElementById("img1");
this.img2 = document.getElementById("img2");
this.img3 = document.getElementById("img3");
this.counter = {
walkLeft: 0,
walkRight: 0,
};
this.draw = {
walkLeft: () => {
if (this.counter.walkLeft == 0) {
ctx.drawImage(this.img0, this.x, this.y, this.width, this.height);
this.counter.walkLeft = 1;
} else if (this.counter.walkLeft == 1) {
ctx.drawImage(this.img1, this.x, this.y, this.width, this.height);
this.counter.walkLeft = 0;
}
},
walkRight: () => {
if (this.counter.walkRight == 0) {
ctx.drawImage(this.img2, this.x, this.y, this.width, this.height);
this.counter.walkRight = 1;
} else if (this.counter.walkRight == 1) {
ctx.drawImage(this.img3, this.x, this.y, this.width, this.height);
this.counter.walkRight = 0;
}
}
};
}
const scene = new Scene();
scene.draw();
var player = new Character();
var initInterval = setInterval(
function () {
player.draw.walkRight();
}, 400
);
var currentInterval = undefined;
document.addEventListener("keydown", function (e) {
if (e.key == "a" || e.key == "ArrowLeft") {
if (initInterval) {
clearInterval(initInterval);
initInterval = undefined;
}
if (currentInterval) {
clearInterval(currentInterval);
currentInterval = undefined;
}
setTimeout( // for first 300ms delay onchange
function () {
player.draw.walkLeft();
}, 1);
if(player.x - player.vx > player.padding) {
player.x -= player.vx;
} else {
player.x = player.padding;
}
currentInterval = setInterval(
function () {
player.draw.walkLeft();
}, 300);
}
if (e.key == "d" || e.key == "ArrowRight") {
if (initInterval) {
clearInterval(initInterval);
initInterval = undefined;
}
if (currentInterval) {
clearInterval(currentInterval);
currentInterval = undefined;
}
setTimeout( // for first 300ms delay onchange
function () {
player.draw.walkRight();
}, 1);
if(player.x + player.vx < canvas.width - player.padding) {
player.x += player.vx;
} else {
player.x = canvas.width - player.padding;
}
currentInterval = setInterval(
function () {
player.draw.walkRight();
}, 300);
}
});
body {
overflow: hidden;
margin: 0;
padding: 0;
}
<html>
<head>
<title></title>
</head>
<link rel="stylesheet" href="style.css">
<body>
<canvas id="canvas"></canvas>
<div id="images">
<img id="img0" width="77px" height="92px" src="Costumes\WalkLeft\WalkLeft1.jpg" />
<img id="img1" width="77px" height="92px" src="Costumes\WalkLeft\WalkLeft2.jpg" />
<img id="img2" width="77px" height="92px" src="Costumes\WalkRight\WalkRight1.jpg" />
<img id="img3" width="77px" height="92px" src="Costumes\WalkRight\WalkRight2.jpg" />
</div>
<script src="script.js"></script>
</body>
</html>
Work in layers. You put your background layer images in one canvas, your character and enemies in another, then copy the contents of each layer starting from the back, in order, onto a 'buffer' canvas. once that's done, you copy the result onto the visible on-screen canvas. Throw away the buffer (or clear it) at the end of each loop.
If a layer doesn't change, just keep it; if it does, create a new canvas for each frame (or clear the canvas you used). You can create as many layers as you like this way (or as many as you've got memory).

Matter.js for collision detection

I'm relatively new to asking questions here, so please bear with me. I am trying to create a top down driving game with Matter.js as the primary physics engine. I would like the red car to collide with the green square. However, I am still stuck on knowing how to implement Matter.js onto my game. Any form of response will be greatly appreciated!
<html>
<canvas width=1000 height=500 style='border:1px solid black'>
</canvas>
<body onload='start()'>
<script src='matter.js'>
</script>
<script>
function start() {
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
var x = 100;
var y = 100;
var s = 0;
var rot = 0;
var rightPressed = false;
var leftPressed = false;
var upPressed = false;
var downPressed = false;
document.addEventListener("keydown", keyDownHandler, false);
document.addEventListener("keyup", keyUpHandler, false);
function keyDownHandler(e) {
if (e.keyCode == 39) {
rightPressed = true;
} else if (e.keyCode == 37) {
leftPressed = true;
} else if (e.keyCode == 38) {
upPressed = true;
} else if (e.keyCode == 40) {
downPressed = true;
}
}
function keyUpHandler(e) {
if (e.keyCode == 39) {
rightPressed = false;
} else if (e.keyCode == 37) {
leftPressed = false;
} else if (e.keyCode == 38) {
upPressed = false;
} else if (e.keyCode == 40) {
downPressed = false;
}
}
function car() {
ctx.fillStyle = 'red';
ctx.fillRect(-20, -20, 40, 40);
ctx.beginPath();
ctx.moveTo(-20, -19);
ctx.lineTo(-20, -20);
ctx.lineTo(0, -30);
ctx.lineTo(20, -20);
ctx.lineTo(20, -19);
ctx.fill();
ctx.closePath();
ctx.fillStyle = 'black';
ctx.fillRect(-25, -20, 5, 10);
ctx.fillRect(-25, 10, 5, 10);
ctx.fillRect(20, -20, 5, 10);
ctx.fillRect(20, 10, 5, 10);
ctx.fillRect(-15, -5, 30, 20);
}
function block() {
ctx.fillStyle = 'green';
ctx.fillRect(200, 100, 50, 50);
}
function draw() {
requestAnimationFrame(draw);
ctx.clearRect(0, 0, 1000, 500);
if (s > 15) {
s = 15;
}
if (s < -15) {
s = -15;
}
if (upPressed) {
s++;
}
if (downPressed) {
s *= .9;
}
if (!upPressed) {
s *= .99;
}
if (leftPressed) {
rot -= s / 3;
}
if (rightPressed) {
rot += s / 3;
}
ctx.fillText(upPressed, 10, 10);
x += s * Math.cos(rot * Math.PI / 180);
y += s * Math.sin(rot * Math.PI / 180);
ctx.save();
ctx.translate(x, y);
ctx.rotate((rot + 90) * Math.PI / 180);
car();
ctx.restore();
block();
}
draw();
}
</script>
</body>
</html>
You would have to redo most of your code, but the movement code CAN be moved over fairly easily.
First you need to make a new engine and run it:
//Create engine - All the game stuff
var Engine = Matter.Engine,
Render = Matter.Render,
Runner = Matter.Runner,
Composites = Matter.Composites,
Common = Matter.Common,
World = Matter.World,
Bodies = Matter.Bodies,
Body = Matter.Body;
// create an engine
var engine = Engine.create(),
world = engine.world;
// create a renderer
var render = Render.create({
canvas: document.getElementById("canv"),
engine: engine,
options: {
width: 500,
height: 500,
wireframes: false,
background: '#6DDA4A'
}
});
engine.world.gravity.y = 0;
Render.run(render);
// create runner
var runner = Runner.create();
Runner.run(runner, engine);
Next, you should make and add a new car object and the block into the world. You can edit these values to whatever you need them to be.
Note: rot is not an actual parameter you need, I'm just using it to set the rotation of the car later.
var car = Bodies.rectangle(100, 100, 50, 80, {
friction: 1,
frictionAir: 0.1,
rot: 0,
restitution: 0,//Makes it so the car won't bounce off of objects
render: {
fillStyle: "#FF0000",
/*sprite: {
//You can use this to apply a background image to the car
texture: "Path/To/Image.png",
xScale: number,
yScale: number
}/**/
}
});
var block = Bodies.rectangle(350, 100, 100, 400, {
isStatic: true,//Makes block unmovable
friction: 1,
frictionAir: 0.1,
rot: 0,
restitution: 0,
render: {
fillStyle: "#0000FF",
/*sprite: {
texture: "Path/To/Image.png",
xScale: number,
yScale: number
}/**/
}
});
World.add(world, [car, block]);
For updating the car, you can either use body.setPosition or body.applyForce. Since it's a car, I would use body.applyForce so that the car keeps rolling after you've stopped pressing a button. Rotation can also be done with body.setAngle or body.rotate. This time, I'm going to use body.setAngle so the turning feels better.
function updateCar() {
//Declare variables for velocity
var speed = 5;
var carRot = car.rot*180/Math.PI;
var velY = speed * Math.cos(carRot * Math.PI / 180);
var velX = speed * Math.sin(carRot * Math.PI / 180)*-1;
var pushRot = 0;
//Update variables
if (upPressed==false&&downPressed==false) {
velY = 0;
velX = 0;
}
else {
//alert(carX+", "+carY);
}
if (downPressed == true) {
velY *= -1;
velX *= -1;
}
if (leftPressed) {
pushRot = -0.1;
}
if (rightPressed) {
pushRot = 0.1;
}
car.rot += pushRot;
//Set position of car
carX += velX;
carY += velY;
Body.applyForce(car, {x:carX,y:carY}, {x:velX/200,y:velY/200});
Body.setAngle(car, car.rot);
requestAnimationFrame(updateCar);
}
window.requestAnimationFrame(updateCar);
Check out a demo here

JavaScript Pong game. I can't move 2 players at once

I stuck in one place for few hours, so I decided to go for help here. I'm beginner and i wish to try write a simple pong game.
At this link in Khan Academy you'll see result.
KHAN ACADEMY my pong game
My issue is:
I can't move two players at once. Only player can move - who hit last the keyboard. Last hit key win.
I know there are few ready pong games, but a lot of it is in Java, or all different logic. Can you help me good people? :)
//THIS IS GAME FOR 2 PEOPLE
//PLAYER 1 CONTROLS: UP ARROW (MOVE UP), DOWN ARROW (MOVE DOWN)
//PLAYER 2 CONTROLS: W KEY (MOVE UP), S KEY (MOVE DOWN)
var player1Y = height/2;
var player2Y = height/2;
var player1Score = 0;
var player2Score = 0;
var ball;
var gameStarted = false;
var t = 0;
//Constants
var PAUSE_TIME = 60;
var PLAYER_MOVE_SPEED = 2;
var BALL_SPEED = 3;
var PADDLE_HEIGHT = 80;
var PADDLE_WIDTH = 8;
angleMode = "degrees";
var Ball = function(position, speed) {
this.position = position;
this.speed = speed || BALL_SPEED;
this.radius = 6;
this.resetVelocity = function() {
this.theta = random(0, 75);
this.velocity = new PVector(
this.speed*cos(this.theta), -this.speed*sin(this.theta));
};
this.resetVelocity();
this.draw = function() {
fill(0, 0, 0);
noStroke();
ellipse(this.position.x, this.position.y,
this.radius*2, this.radius*2);
};
this.collideWithPaddle = function(x, y) {
if (this.position.x - this.radius < x + PADDLE_WIDTH/2 &&
this.position.x + this.radius > x - PADDLE_WIDTH/2) {
if (dist(0, this.position.y, 0, y) <
PADDLE_HEIGHT/2 + this.radius) {
if (this.position.x > x) {
this.position.x = x +
this.radius + PADDLE_WIDTH/2;
}
else if (this.position.x < x) {
this.position.x = x -
this.radius - PADDLE_WIDTH/2;
}
this.velocity.mult(new PVector(-1, 1));
}
}
};
this.update = function() {
//Handle wall collisions
if (this.position.x < 0) {
player2Score++;
this.position = new PVector(width/2, height/2);
gameStarted = false;
this.resetVelocity();
}
else if (this.position.x > width) {
player1Score++;
this.position = new PVector(width/2, height/2);
gameStarted = false;
this.resetVelocity();
}
if (this.position.y < 0) {
this.position.y = 0;
this.velocity.mult(new PVector(1, -1));
}
else if (this.position.y > height) {
this.position.y = height;
this.velocity.mult(new PVector(1, -1));
}
//Handle paddle collisions
this.collideWithPaddle(20, player1Y);
this.collideWithPaddle(width-20, player2Y);
this.position.add(this.velocity);
};
};
ball = new Ball(new PVector(width/2, height/2));
var drawScores = function() {
var s;
fill(0, 0, 0);
textSize(16);
s = "Player 1: " + player1Score;
text(s, width*0.25-textWidth(s)/2, 25);
s = "Player 2: " + player2Score;
text(s, width*0.75-textWidth(s)/2, 25);
};
//Move the player1 up
var movePlayer1Up = function() {
player1Y -= PLAYER_MOVE_SPEED;
};
//Move the player1 down
var movePlayer1Down = function() {
player1Y += PLAYER_MOVE_SPEED;
};
//Move the player2 up
var movePlayer2Up = function() {
player2Y -= PLAYER_MOVE_SPEED;
};
//Move the player2 down
var movePlayer2Down = function() {
player2Y += PLAYER_MOVE_SPEED;
};
var drawPlayers = function() {
//Constrain the player movement
player1Y = constrain(player1Y, 0, 400);
player2Y = constrain(player2Y, 0, 400);
rectMode(CENTER);
fill(0, 0, 0);
rect(20, player1Y, PADDLE_WIDTH, PADDLE_HEIGHT);
rect(width-20, player2Y, PADDLE_WIDTH, PADDLE_HEIGHT);
};
draw = function() {
//Control Player 1
if (keyIsPressed) {
if (keyCode===38){
movePlayer1Up();
}
else if(keyCode===40) {
movePlayer1Down();
}
}
//Control Player 2
if (keyIsPressed) {
if (key.toString()==="w"){
movePlayer2Up();
}
else if(key.toString()==="s"){
movePlayer2Down();
}
}
//Draw the environment
background(255, 255, 255);
drawPlayers();
drawScores();
stroke(100, 100, 100);
line(width/2, 0, width/2, height);
//Draw the ball
ball.draw();
if (!gameStarted) {
t++;
if (t >= PAUSE_TIME) {
t = 0;
gameStarted = true;
}
return;
}
ball.update();
};
You should be watching the onkeyup, onkeydown events for moving players, see this related question here. JavaScript multiple keys pressed at once
Now I understand concept, and I just did something like that:
Scope for multiple keys:
var keys = [];
var keyPressed = function(){
keys[keyCode] = true;
};
var keyReleased = function(){
keys[keyCode] = false;
};
and drawing function:
//Controls
if (keys[87]) {
movePlayer2Up();
}
if (keys[83]) {
movePlayer2Down();
}
if (keys[38]) {
movePlayer1Up();
}
if (keys[40]) {
movePlayer1Down();
}
And now it's working! The same link to the Khan Academy - there's the effect. Thank you one more time.

JavaScript canvas element doesn't display after canvas clear

I have start develop small JavaScript game with canvas.
So i need to display multiple cards in the canvas.
But i seems, after i use gameArea.clear(); method within updateGameArea() function one card isn't display. But without using that gameArea.clear(); method those cards are displaying well. But i need multiple cards.
Here my JavaScript code
var cards = [];
var selectedCards = [];
var select = true;
window.addEventListener('DOMContentLoaded', function () {
startGame();
});
function startGame() {
cards.push(new PlayingCard("blue", 5, 150, 10));
cards.push(new PlayingCard("red", 1, 10, 10));
gameArea.click();
gameArea.start();
}
var gameArea = {
canvas: document.createElement("canvas"),
start: function () {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 100);
},
click: function () {
this.canvas.addEventListener('click', getPosition);
},
clear: function () {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
};
function getPosition(e) {
var top = this.offsetTop;
var left = this.offsetLeft;
var x = e.pageX - left;
var y = e.pageY - top;
cards.forEach(function (card) {
if (y > card.y && y < card.y + card.height && x > card.x && x < card.x + card.width) {
card.selected = select;
if (selectedCards.length < 2) {
selectedCards.push(card);
} else {
selectedCards = [];
selectedCards.push(card);
}
if (selectedCards.length === 2) {
selectedCards.forEach(function (selected_card) {
selected_card.x = 400;
if (selected_card.selected === select) {
console.log(selected_card);
}
});
}
}
});
}
function PlayingCard(color, value, x, y) {
this.color = function () {
if (color === 'red') {
return "#E53935";
} else if (color === 'blue') {
return "#0D47A1";
} else {
throw new Error("No Color Code Found!");
}
};
this.value = value;
this.width = 120;
this.height = 160;
this.x = x;
this.y = y;
this.selected = false;
this.update = function () {
var ctx = gameArea.context;
ctx.fillStyle = this.color();
ctx.shadowBlur = 8;
ctx.shadowColor = 'rgba(0, 0, 0, 0.5)';
ctx.fillRect(this.x, this.y, this.width, this.height);
};
}
function updateGameArea() {
cards.forEach(function (card) {
gameArea.clear();
card.update();
});
}
You are calling gameAera.clear() each time you draw a card. So this is why only the last card is displayed.
function updateGameArea() {
gameArea.clear(); // Move the gameArea.clear(); here
cards.forEach(function (card) {
card.update();
});
}

Categories