I am making a 2d game in JavaScript but my character can only move around the length of the screen so I was wondering if there was a way to make the canvas move but my character stay on the middle of the screen could Simone please help me
here is my code for the test game
<html>
<body>
<canvas id="canvas">
</canvas>
</body>
</html>
<script>
var audio = new Audio('sounds/theServerRoom.mp3');
audio.play();
// Create the canvas
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function() {
bgReady = true;
};
bgImage.src = "images/gamemap.png";
//computer
var computerReady = false;
var computerImage = new Image();
computerImage.onload = function() {
computerReady = true;
};
computerImage.src = "images/computer1.png";
//hp box
var hpBoxReady = false;
var hpBoxImage = new Image();
hpBoxImage.onload = function() {
hpBoxReady = true;
};
hpBoxImage.src = "images/hpbox.png";
// player image
var playerReady = false;
var playerImage = new Image();
playerImage.onload = function() {
playerReady = true;
};
playerImage.src = "images/char.png";
// enemy image
var enemyReady = false;
var enemyImage = new Image();
enemyImage.onload = function() {
enemyReady = true;
};
enemyImage.src = "images/enemy_idle01.png";
var computer = {
wifi: true,
x: 399,
y: 200
}
// Game objects
var hpBox = {
restoreHealth: 34,
x: 300,
y: 300
}
var player = {
hackingSkill : 10,
stamina: 7,
health: 100,
sprintSpeed: 400,
weakSpeed: 150,
speed: 300 // movement in pixels per second
};
var enemy = {
speed: 250,
viewDistance: 40
};
var enemysCaught = 0;
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function(e) {
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function(e) {
delete keysDown[e.keyCode];
}, false);
// Reset the game when the player catches a enemy
var reset = function() {
player.x = canvas.width / 2;
player.y = canvas.height / 2;
// Throw the enemy somewhere on the screen randomly
enemy.x = 32 + (Math.random() * (canvas.width - 64));
enemy.y = 32 + (Math.random() * (canvas.height - 64));
};
//w is 87
//a is 65
//s is 83
//d is 68
// Update game objects
var update = function(modifier) {
if (87 in keysDown) { // Player holding up
player.y -= player.speed * modifier;
}
if (83 in keysDown) { // Player holding down
player.y += player.speed * modifier;
}
if (65 in keysDown) { // Player holding left
player.x -= player.speed * modifier;
}
if (68 in keysDown) { // Player holding right
player.x += player.speed * modifier;
}
if (
player.x <= (0)) {
player.health -= 1;
console.log('health decreasing');
}
}
if (
player.y <= (0)) {
player.health -= 1;
console.log('health decreasing');
};
// Are they touching?
if (
player.x <= (enemy.x + 32) &&
enemy.x <= (player.x + 32) &&
player.y <= (enemy.y + 32) &&
enemy.y <= (player.y + 32)
) {
++enemysCaught;
reset();
}
// Draw everything
var render = function() {
if (bgReady) {
context.drawImage(bgImage, 0, 0);
}
if (computerReady) {
context.drawImage(computerImage, computer.x, computer.y);
}
if (hpBoxReady) {
context.drawImage(hpBoxImage, hpBox.x, hpBox.y);
}
if (playerReady) {
context.drawImage(playerImage, player.x, player.y);
}
if (enemyReady) {
context.drawImage(enemyImage, enemy.x, enemy.y);
}
// Score
};
function dieEvent() {
player.health = 100;
}
function updateHealth() {
context.fillStyle = "white";
context.textAlign = "left";
context.fillText("Health: " + player.health, 30, 32);
context.fillStyle="#FF0000";
context.fillRect(10,10,(player.health/100)*140,25);
context.stroke();
}
function updateHackerSkill(){
context.fillStyle = "green";
context.textAlign = "left";
context.fillText("Health: " + player.hackerSkill, 30, 32);
context.fillStyle="#FF0000";
context.fillRect(10,10,(player.hackerSkill/100)*1,45);
context.stroke();
}
function isNearComputer() {
if (player.y <= (computer.y + enemy.viewDistance + 23) &&
player.y >= (computer.y - enemy.viewDistance) &&
player.x <= (computer.x + enemy.viewDistance + 32) &&
player.x >= (computer.x - enemy.viewDistance)) {
console.log("near computer");
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
context.stroke();
context.fillStyle = "green";
context.font = "24px Helvetica";
context.textAlign = "left";
context.textBaseline = "top";
context.fillText("Welcome to uOS v1.0 " , 20 ,10);
window.setTimeout(500);
context.fillText("user$> " , 20 ,35);
}
}
function isNearHPBox() {
if (
player.y <= (hpBox.y + enemy.viewDistance + 64) &&
player.y >= (hpBox.y - enemy.viewDistance - 64) &&
player.x <= (hpBox.x + enemy.viewDistance + 64) &&
player.x >= (hpBox.x - enemy.viewDistance - 64)) {
console.log("healing!");
if (player.health <= 100) {
hpBox.restoreHealth = player.health - 100;
player.health += hpBox.restoreHealth;
}
}
}
function moveEnemy() {
if (
player.y <= (enemy.y + enemy.viewDistance + 64) &&
player.y >= (enemy.y - enemy.viewDistance - 64) &&
player.x <= (enemy.x + enemy.viewDistance + 64) &&
player.x >= (enemy.x - enemy.viewDistance - 64)) {
console.log("seen on enemys Y");
var audio = new Audio('sounds/theWanderer_Scream.m4a');
audio.play();
if (player.x >= (enemy.x)) {
enemy.x -= enemy.speed;
}
if (player.x >= (enemy.x)) {
enemy.x -= enemy.speed;
}
}
}
function checkWallCollision() {
if (player.y <= 0) {
console.log("y")
player.y += 64;
}
if (player.x <= 0) {
console.log("x")
player.x += 64;
}
if (enemy.y <= 0) {
console.log("y")
enemy.y += 64;
}
if (enemy.x <= 0) {
console.log("x")
enemy.x += 64;
}
}
// function updateMouseCoords(){
// document.onmousemove = function(e){
// cursorX = e.pageX;
// cursorY = e.pageY;
// context.fillStyle = "green";
// context.font = "24px Helvetica";
// context.textAlign = "left";
// context.textBaseline = "top";
// context.fillText("x" + cursorX + "y" + cursorY , 20 ,10);
//
// }
// }
// function drawViewLine(){
// var cursorX;
// var cursorY;
// context.beginPath();
// context.moveTo(player.x,player.y);
// context.lineTo(cursorX,cursorY);
// context.stroke();
// console.log("drawing line")
// }
function reducedSpeed() {
player.speed = player.weakSpeed;
}
// The main game loop
var main = function() {
var now = Date.now();
var delta = now - then;
update(delta / 1000);
context.clearRect(0, 0, canvas.width, canvas.height);
render();
updateHealth();
moveEnemy();
if (player.health <= 20) {
reducedSpeed();
} else {
player.speed = 300;
}
if (player.health <= 0) {
dieEvent();
}
checkWallCollision();
isNearHPBox();
isNearComputer();
//updateMouseCoords();
//drawViewLine();
then = now;
// Request to do this again ASAP
requestAnimationFrame(main);
};
// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
// Let's play this game!
var then = Date.now();
reset();
main();
</script>
<style>
body {
margin: 0;
padding: 0;
}
</style>
there are multiple ways to deal with this issue, here are the main 2 i can think of right now:
1.- Move the world instead of your character: what you do is that your character actually stays in place, and you move the rest of the world instead, this is mainly useful for runner games, where movement is constant or one-dimensional (only left-right or up-down but never both in the same level)
2.- I haven't tested this, but what if your canvas is actually the size of the level, but it is partially hidden by a parent DIV with a specific width and height? this way you can move your character around the canvas, and move the canvas around the div to keep the character centered.
These solutions may or may not translate properly to your specific game though, since you gave literally no details about how movement is being dealt with at the moment.
Related
There are two squares, they are moved with the arrows and asdw, and I have been trying to get this collision detection down for ages, it's killing me. Anyways, I have tried so many methods, I got really really close with one method, and everything was fine with it, until I found out that when you jumped next to it, it didn't complete the full jump because one of the sides was able to go through the other square. After a long time, I found out that method wouldn't work because with GetContext.2d, you cannot reference the bottom left of a square. There also was the issue that one corner could touch two different sides, which would set off conflicting messages. My solution for that was to make a third condition to specify which side the corner was touching, weather the top/bottom or left/right. I made a model of how the code would be structured:
The code I have currently looks like this:
const context = document.getElementById("canvasmulti").getContext("2d");
canvasmulti.width = window.innerWidth;
canvasmulti.height = window.innerHeight;
//CHARACTER:
const square = {
height: 75,
jumping: true,
width: 75,
x: canvasmulti.width - 75,
xVelocity: 0,
y: canvasmulti.height / 2,
yVelocity: 0,
jumpHeight: 30
};
const square2 = {
height: 75,
jumping: true,
width: 75,
x: 0,
xVelocity: 0,
y: canvasmulti.height / 2,
yVelocity: 0,
jumpHeight: 30
};
//MOVEMENT:
const controller = {
left: false,
right: false,
up: false,
keyListener: function (event) {
let key_state = (event.type == "keydown") ? true : false;
switch (event.keyCode) {
case 37: // left arrow
controller.left = key_state;
break;
case 38: // up arrow
controller.up = key_state;
break;
case 39: // right arrow
controller.right = key_state;
break;
}
}
};
const controller2 = {
left: false,
right: false,
up: false,
keyListener: function (event) {
let key_state = (event.type == "keydown") ? true : false;
switch (event.keyCode) {
case 65: // left arrow
controller2.left = key_state;
break;
case 87: // up arrow
controller2.up = key_state;
break;
case 68: // right arrow
controller2.right = key_state;
break;
}
}
};
const loop = function () {
//controller one
if (controller.up && square.jumping == false) {
square.yVelocity -=square.jumpHeight;
square.jumping = true;}
if (controller.left) {
square.xVelocity -= 0.5;}
if (controller.right) {
square.xVelocity += 0.5;}
//controller two
if (controller2.up && square2.jumping == false) {
square2.yVelocity -= square2.jumpHeight;
square2.jumping = true;}
if (controller2.left) {
square2.xVelocity -= 0.5;}
if (controller2.right) {
square2.xVelocity += 0.5;}
//controller one
square.yVelocity += 1.5;// gravity
square.x += square.xVelocity;
square.y += square.yVelocity;
square.xVelocity *= 0.9;// friction
square.yVelocity *= 0.9;// friction
//controller two
square2.yVelocity += 1.5;// gravity
square2.x += square2.xVelocity;
square2.y += square2.yVelocity;
square2.xVelocity *= 0.9;// friction
square2.yVelocity *= 0.9;// friction
// if square1 is falling below floor line
if (square.y > canvasmulti.height - 75) {
square.jumping = false;
square.y = canvasmulti.height - 75;
square.yVelocity = 0;
}
// if square2 is falling below floor line
if (square2.y > canvasmulti.height - 75) {
square2.jumping = false;
square2.y = canvasmulti.height - 75;
square2.yVelocity = 0;
}
// if square1 is going off the left of the screen
if (square.x < 0) {
square.x = 0;
} else if (square.x > canvasmulti.width - 75) {// if square goes past right boundary
square.x = canvasmulti.width - 75;
}
// if square2 is going off the left of the screen
if (square2.x < 0) {square2.x = 0;}
else if (square2.x > canvasmulti.width - 75) {// if square goes past right boundary
square2.x = canvasmulti.width - 75;
}
// Creates the backdrop for each frame
context.fillStyle = "#394129";
context.fillRect(0, 0, canvasmulti.width, canvasmulti.height); // x, y, width, height
// Creates and fills square1 for each frame
context.fillStyle = "#8DAA9D"; // hex for cube color
context.beginPath();
context.rect(square.x, square.y, square.width, square.height);
context.fill();
// Creates and fills square2 for each frame
context.fillStyle = "#781818"; // hex for cube color
context.beginPath();
context.rect(square2.x, square2.y, square2.width, square2.height);
context.fill();
// Collision detection of squares
if (square.x <= square2.x + square2.width && square.x >= square2.x &&
square.y >= square2.y && square.y <= square2.y + square2.height &&
square2.y + square2.height >= square.y && square2.y + square2.height <= square.y + square.height)
{square.y = square2.y - square.height; //set it to a position where they don't overlap
square.yVelocity = 0;}; //One move down
if (square.x <= square2.x + square2.width && square.x >= square2.x &&
square.y >= square2.y && square.y <= square2.y + square2.height &&
square2.x + square2.width >= square.x && square2.x + square2.width <= square.x + square.width);
{square.x = square2.x + square2.width; // set it to a position where they don't overlap
square.xVelocity = 0;}; //One move right
if (square2.x >= square.x && square2.x <= square.x + square.width &&
square2.y >= square.y && square2.y <= square.y + square.heights &&
square.y + square.height >= square2.y && square.y + square.height <= square2.y + square2.height)
{square.y = square2.y - square.height; // set it to a position where they don't overlap
square.yVelocity = 0;}; //One move up
if (square2.x >= square.x && square2.x <= square.x + square.width &&
square2.y >= square.y && square2.y <= square.y + square.heights &&
square.x + square.width >= square2.y && square.x + square.width <= square2.y + square2.height)
{square.x = square2.x - square.width; // set it to a position where they don't overlap
square.xVelocity = 0;}; //One move left
// call update when the browser is ready to draw again
window.requestAnimationFrame(loop);
};
//square1
window.addEventListener("keydown", controller.keyListener)
window.addEventListener("keyup", controller.keyListener);
//square2
window.addEventListener("keydown", controller2.keyListener)
window.addEventListener("keyup", controller2.keyListener);
window.requestAnimationFrame(loop);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height">
<title>ToneMain</title>
<style>
body {
height:100vh;
width:100vh;
margin: 0;
}
</style>
</head>
<body>
<canvas id="canvasmulti"></canvas>
<script src="ToneMainMulti.js"></script>
</body>
</html>
For the love of my sanity this was the last time in a month I tried to fix this. This was my last blow. I would really apprestiate any effort or advice to solve my problem, this is tough to wrap your head around and may take a long time, thxxx <3
I feel your pain. CD is not as easy as one would hope. I was unable to get your code working so I rewrote it using ES6 classes because I like them. I also don't put everything into a loop function but rather place controlling parameters into separate functions and call those functions in the animate loop. Hopefully it isn't confusing from how you write.
The CD portion calculates the distance between the different sides of the blocks and determines which sides from each block are the closest and will collide. By doing this only one function will get called at a time. This prevents any of the unwanted behavior you get because of the blocks having a slight overlap and causing other functions to trigger also. i.e. colliding on the X but having the Y trigger too. I've also set it to where if the blocks are stacked only the top one can jump.
You can tailor this to whatever suits your needs.
const canvas = document.getElementById('canvasmulti');
const context = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 500;
let gravity = 1.5;
let friction = 0.9;
//CHARACTER:
class Player {
constructor(x, y, vx, vy, c, j) {
//each player must have separate values for control purposes i.e. velocity/jump/attack etc.
this.x = x;
this.y = y;
this.w = 50;
this.h = 50;
this.vx = vx;
this.vy = vy;
this.color = c;
this.jumping = j;
}
draw() {
context.fillStyle = this.color;
context.fillRect(this.x, this.y, this.w, this.h);
}
canvasCollision() {
if (this.x <= 0) this.x = 0;
if (this.y <= 0) this.y = 0;
if (this.x + this.w >= canvas.width) this.x = canvas.width - this.w;
if (this.y + this.h >= canvas.height) {this.y = canvas.height - this.h; this.vy = 0; this.jumping = false};
}
update() {
this.draw();
this.vy += gravity;
this.x += this.vx;
this.y += this.vy;
this.vx *= friction;
this.vy *= friction;
this.canvasCollision() //must be after other updates
}
}
let player1 = new Player(0, 0, 0, 0, 'red', false); //must have separate variables like jump/attack etc
let player2 = new Player(canvasmulti.width - 50, 0, 0, 0, 'blue', false);
function controlPlayer1(obj) {
//this order matters. If update is before jump then obj won't jump when on top of other block.
if (controller1.up1 && !obj.jumping) { obj.vy -= 25; obj.jumping = true };
if (controller1.left1) { obj.vx -= 0.5 };
if (controller1.right1) { obj.vx += 0.5 };
obj.update();
}
function controlPlayer2(obj) {
if (controller2.up2 && !obj.jumping) { obj.vy -= 25; obj.jumping = true };
if (controller2.right2) { obj.vx += 0.5 };
if (controller2.left2) { obj.vx -= 0.5 };
obj.update();
}
//MOVEMENT:
class Controller {
constructor() {
this.left1 = false;
this.up1 = false;
this.right1 = false;
this.left2 = false;
this.up2 = false;
this.right2 = false;
let controller1 = (e) => {
if (e.code === 'ArrowRight') { this.right1 = e.type === 'keydown' }
if (e.code === 'ArrowLeft') { this.left1 = e.type === 'keydown' }
if (e.code === 'ArrowUp') { this.up1 = e.type === 'keydown' }
}
let controller2 = (e) => {
if (e.code === 'KeyD') { this.right2 = e.type === 'keydown' }
if (e.code === 'KeyA') { this.left2 = e.type === 'keydown' }
if (e.code === 'KeyW') { this.up2 = e.type === 'keydown' }
}
window.addEventListener('keydown', controller1);
window.addEventListener('keyup', controller1);
window.addEventListener('keydown', controller2);
window.addEventListener('keyup', controller2);
}
}
let controller1 = new Controller();
let controller2 = new Controller();
function collisionDetection(obj, obj2) {
//center point of each side of obj1
let objLeft = {x: obj.x, y: obj.y + obj.h/2};
let objTop = {x: obj.x + obj.w/2, y: obj.y};
let objRight = {x: obj.x + obj.w, y: obj.y + obj.h/2};
let objBottom = {x: obj.x + obj.w/2, y: obj.y + obj.h};
//center point of each side a obj2
let obj2Left = {x: obj2.x, y: obj2.y + obj2.h/2};
let obj2Top = {x: obj2.x + obj2.w/2, y: obj2.y};
let obj2Right = {x: obj2.x + obj2.w, y: obj2.y + obj2.h/2};
let obj2Bottom = {x: obj2.x + obj2.w/2, y: obj2.y + obj2.h};
//distance between obj1 and obj2 opposing sides
let rightDistX = objRight.x - obj2Left.x;
let rightDistY = objRight.y - obj2Left.y;
let leftDistX = objLeft.x - obj2Right.x;
let leftDistY = objLeft.y - obj2Right.y;
let topDistX = objTop.x - obj2Bottom.x;
let topDistY = objTop.y - obj2Bottom.y;
let bottomDistX = objBottom.x - obj2Top.x;
let bottomDistY = objBottom.y - obj2Top.y;
//pythagorean theorem for distance. dRight is from the right side of obj1 to the left of obj2. the rest follow suit.
let dRight = Math.sqrt(rightDistX*rightDistX + rightDistY*rightDistY);
let dLeft = Math.sqrt(leftDistX*leftDistX + leftDistY*leftDistY);
let dTop = Math.sqrt(topDistX*topDistX + topDistY*topDistY);
let dBottom = Math.sqrt(bottomDistX*bottomDistX + bottomDistY*bottomDistY);
//Math.min return the smallest value thus variable minimum will be which ever sides are closest together
let minimum = Math.min(dRight, dLeft, dBottom, dTop);
let val = 0;
//compare minimum to d*** and set val based on which ever side is closest
if (dTop == minimum) {
val = 1;
//the context stuff can be deleted. It's just here for visual. The if statements can be one line each.
context.lineWidth = 2;
context.strokeStyle = 'blue';
context.beginPath();
context.moveTo(objTop.x, objTop.y);
context.lineTo(obj2Bottom.x, obj2Bottom.y);
context.stroke();
}
else if (dRight == minimum) {
val = 2;
context.strokeStyle = 'orange';
context.beginPath();
context.moveTo(objRight.x, objRight.y);
context.lineTo(obj2Left.x, obj2Left.y);
context.stroke();
}
else if (dBottom == minimum) {
val = 3;
context.strokeStyle = 'green';
context.beginPath();
context.moveTo(objBottom.x, objBottom.y);
context.lineTo(obj2Top.x, obj2Top.y);
context.stroke();
}
else if (dLeft == minimum) {
val = 4;
context.strokeStyle = 'pink';
context.beginPath();
context.moveTo(objLeft.x, objLeft.y);
context.lineTo(obj2Right.x, obj2Right.y);
context.stroke();
}
//pass the objects and val to collisionActions
collisionActions(obj, obj2, val)
}
function collisionActions(obj, obj2, val) {
//player1 top to player2 bottom
if (obj.y <= obj2.y + obj2.h && obj2.y + obj2.h >= obj.y && val == 1) {
obj2.y = obj.y - obj2.h;
obj.y = obj2.y + obj2.h;
obj.vy = 0;
obj2.vy = 0;
obj2.jumping = false;
obj.jumping = true;
}
//player1 right to player2 left
if (obj.x + obj.w >= obj2.x && obj2.x <= obj.x + obj.w && val == 2) {
obj2.x = obj.x + obj.w;
obj.x = obj2.x - obj.w - 1;
obj.vx = 0;
obj2.vx = 0;
}
//player1 bottom to player2 top
if (obj.y + obj.h >= obj2.y && obj2.y <= obj.y + obj.h && val == 3) {
obj.y = obj2.y - obj.h;
obj2.y = obj.y + obj.h;
obj.vy = 0;
obj2.vy = 0;
obj.jumping = false;
obj2.jumping = true;
}
//player1 left to player2 right
if (obj.x <= obj2.x + obj2.w && obj2.x + obj2.w >= obj.x && val == 4) {
obj2.x = obj.x - obj2.w;
obj.x = obj2.x + obj2.w + 1;
obj.vx = 0;
obj2.vx = 0;
}
}
function loop() {
context.clearRect(0, 0, canvas.width, canvas.height);
context.fillStyle = 'grey';
context.fillRect(0, 0, canvas.width, canvas.height);
controlPlayer1(player1);
controlPlayer2(player2);
collisionDetection(player1, player2)
requestAnimationFrame(loop)
}
loop();
It may seem like a lot but it's really not and it works very well. I was having the same issues a while back and came up with this to use on a collision map because my character would randomly shoot of in the wrong direction or jumping next to a block wouldn't work. I have modified that code to be used here with just 2 moving blocks. Let me know if this works for you.
I have a canvas game in my webpage and it operates with arrow key controls, but whenever somebody tries to play it the page scrolls. Is there any way I can prevent it? The code for my game is here. All I need is for the page to not be bouncing up and down whenever somebody is trying to play. I know it would be easier to just use the wasd keys but to me that feels like putting duct tape on a leak on the hull of a boat instead of actually fixing it. Any suggestions? I'm using google apps script HTML service so I'm not sure if using jquery is possible or if it is whether its going going to be hours and hours of work that are eventually ditched in favor of a quicker solution. Anyways, hope somebody can help.
<h1> example html</h1>
<p>exampleHTMLexampleHTMLexampleHTMLexampleHTMLexampleHTMLexampleHTMLexampleHTMLexampleHTMLexampleHTMLexampleHTMLexampleHTMLexampleHTML</p>
<h2>example html </h2>
<canvas id='my' width = '640' height = '480' style = 'display: none;'></canvas>
<script>
var paused = false
function PausePlay(){
if (paused === false)
{paused = true;}
else{paused = false;}
}
var canvas = document.getElementById("my");
var ctx = canvas.getContext("2d");
function paddle(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.speedModifier = 0;
this.hasCollidedWith = function(ball) {
var paddleLeftWall = this.x;
var paddleRightWall = this.x + this.width;
var paddleTopWall = this.y;
var paddleBottomWall = this.y + this.height;
if (ball.x > paddleLeftWall &&
ball.x < paddleRightWall &&
ball.y > paddleTopWall &&
ball.y < paddleBottomWall) {
return true;
}
return false;
};
this.move = function(keyCode) {
var nextY = this.y;
if (keyCode == 40) {
nextY += 5;
this.speedModifer = 1.5;
} else if (keyCode == 38) {
nextY += -5;
this.speedModifier = 1.5;
} else {
this.speedModifier = 0;
}
nextY = nextY < 0 ? 0 : nextY;
nextY = nextY + this.height > 480 ? 480 - this.height : nextY;
this.y = nextY;
};
}
var player = new paddle(5, 200, 25, 100);
var ai = new paddle(610, 200, 25, 100);
var ball = {
x: 320,
y: 240,
radius: 7,
xSpeed: 2,
ySpeed: 0,
playerscore: 0,
aiscore: 0,
reverseX: function() {
this.xSpeed *= -1;
},
reverseY: function() {
this.ySpeed *= -1;
},
reset: function() {
alert('The score is now ' + this.playerscore + ' to ' + this.aiscore);
this.x = 20;
this.y = 24;
this.xSpeed = 2;
this.ySpeed = 0;
},
isBouncing: function() {
return ball.ySpeed != 0;
},
modifyXSpeedBy: function(modification) {
modification = this.xSpeed < 0 ? modification * -1 : modification;
var nextValue = this.xSpeed + modification;
nextValue = Math.abs(nextValue) > 9 ? 9 : nextValue;
this.xSpeed = nextValue;
},
modifyYSpeedBy: function(modification) {
modification = this.ySpeed < 0 ? modification * -1 : modification;
this.ySpeed += modification;
}
};
function tick() {
updateGame();
draw()
window.setTimeout("tick()", 1000 / 60);
}
function updateGame() {
if (paused === false){
ball.x += ball.xSpeed;
ball.y += ball.ySpeed;
if (ball.x < 0) {
ball.reset();
ball.aiscore = ball.aiscore + 1;
}
if (ball.x > 640) {
ball.reset();
ball.playerscore = ball.playerscore + 1
}
if (ball.y <= 0 || ball.y >= 480) {
ball.reverseY();
}
var collidedWithPlayer = player.hasCollidedWith(ball);
var collidedWithAi = ai.hasCollidedWith(ball);
if (collidedWithPlayer || collidedWithAi) {
ball.reverseX();
ball.modifyXSpeedBy(0.25);
var speedUpValue = collidedWithPlayer ? player.speedModifier : ai.speedModifier;
ball.modifyYSpeedBy(speedUpValue);
}
for (var keyCode in heldDown) {
player.move(keyCode);
}
var aiMiddle = ai.y + (ai.height / 2);
if (aiMiddle < ball.y) {
ai.move(40);
}
if (aiMiddle > ball.y) {
ai.move(38);
}
}
}
function draw() {
if(paused === false){
ctx.fillStyle = "black";
ctx.fillRect(0, 0, 640, 480);
renderPaddle(player);
renderPaddle(ai);
renderBall(ball);
}
}
function renderPaddle(paddle) {
ctx.fillStyle = "blue";
ctx.fillRect(paddle.x, paddle.y, paddle.width, paddle.height);
}
function renderBall(ball) {
ctx.beginPath();
ctx.arc(ball.x, ball.y, ball.radius, 0, 2 * Math.PI, false);
ctx.fillStyle = "pink";
ctx.fill();
}
var heldDown = {};
window.addEventListener("keydown", function(keyInfo) {
heldDown[event.keyCode] = true;
}, false);
window.addEventListener("keyup", function(keyInfo) {
delete heldDown[event.keyCode];
}, false);
function playPong(){
canvas.style.display = 'block';
tick()
}
function show(){
var canvas = document.getElementById('my')
canvas.style.display = 'block';
}
</script>
<div>
<button onclick = 'hide()'> Hide or show the games</button>
<br>
<button onclick = 'PausePlay()'> Pause/play games</button>
<br>
</div>
<br><br><br><br>
<button onclick = 'playPong()'> Play pong </button>
You may use overflow: hidden; CSS property in order to control the ability of scrolling. If you need to prevent vertical/horizontal scrolling only, so you may use overflow-x and overflow-y More about overflow property here.
Im making a simple pong game and when you move the red box up with 'w' the ball still bounces on nothing back to the left. I feel like maybe the bounding box is set up incorrectly to the left side. I cant figure out what I did wrong?
var canvas;
var context;
var timer;
var interval = 1000 / 60;
var player1;
var player2;
var ball;
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
//player = new Player();
player1 = new GameObject();
player2 = new GameObject();
ball = new GameObject();
timer = setInterval(animate, interval);
function animate() {
context.clearRect(0, 0, canvas.width, canvas.height);
ball.move();
//Move the Player to the right
if (w) {
console.log("");
player1.y += -8;
}
if (s) {
console.log("");
player1.y += 8;
}
if (d) {
console.log("");
player2.y += -8;
}
if (u) {
console.log("");
player2.y += 8;
}
if (player1.y > canvas.height - player1.height / 2) {
player1.y = canvas.height - player1.height / 2;
}
if (player1.y < player1.height / 2) {
player1.y = player1.height / 2;
}
if (player2.y > canvas.height - player2.height / 2) {
player2.y = canvas.height - player2.height / 2;
}
if (player2.y < player2.height / 2) {
player2.y = player2.height / 2;
}
//bounce
if (ball.x > canvas.width - ball.width / 2) {
ball.vx = -ball.vx;
//ball.x = 300;
color = "#ff0000";
}
if (ball.x < 0 + ball.width / 2) {
//this flips it if its a negative sign.
ball.vx = -ball.vx;
//ball.x = 300;
color = "#FF4500";
}
//-------------------------------------------------------
//Define Booleans for each key
var w = false;
var s = false;
var u = false;
var d = false;
//Add Event Listeners
document.addEventListener("keydown", press);
document.addEventListener("keyup", release);
document.addEventListener("keydown", presss);
document.addEventListener("keyup", releases);
//Event Functions
function press(e) {
//---This logs key codes into the browser's console.
console.log("Pressed" + e.keyCode);
if (e.keyCode == 87) {
w = true;
}
if (e.keyCode == 83) {
s = true;
}
}
function release(e) {
//---This logs key codes into the browser's console.
//console.log("Released" + e.keyCode);
if (e.keyCode == 87) {
w = false;
}
if (e.keyCode == 83) {
s = false;
}
}
function presss(e) {
//---This logs key codes into the browser's console.
//console.log("Pressed" + e.keyCode);
if (e.keyCode == 40) {
u = true;
}
if (e.keyCode == 38) {
d = true;
}
}
function releases(e) {
//---This logs key codes into the browser's console.
//console.log("Released" + e.keyCode);
if (e.keyCode == 40) {
u = false;
}
if (e.keyCode == 38) {
d = false;
}
}
// JavaScript Document
function GameObject() {
//player's location
this.x = canvas.width / 4;
this.y = canvas.height / 2;
//player's dimensions
this.width = 50;
this.height = 250;
//barriers
//ballss velocity or speed on each axis
this.vx = 8;
this.vy = 0;
//player's color
var red = "#ff0000";
this.blue = "#0000FF";
this.color = "#ff0000";
this.other = "#0000FF";
//This draws the player to the screen
this.drawRect = function() {
context.save();
context.fillStyle = this.color;
context.translate(this.x, this.y);
context.fillRect((-this.width / 2), (-this.height / 2), this.width, this.height);
context.restore();
}
this.second_drawRect = function() {
context.save();
context.fillStyle = this.blue;
context.translate(canvas.width / 1.5, this.y);
context.fillRect((-this.width / 2), (-this.height / 2), this.width, this.height);
context.restore();
}
this.drawCircle = function() {
context.save();
context.fillStyle = this.color;
context.translate(this.x, this.y);
context.beginPath();
context.arc(0, 0, 50, 0, 360 * Math.PI / 180, true)
context.fill();
context.stroke();
//context.fillRect((-this.width/2), (-this.height/2), this.width, this.height);
context.restore();
}
//This changes the player's position
this.move = function() {
this.x += this.vx;
this.y += this.vy;
}
this.left = function() {
return this.x - this.width / 1;
}
this.right = function() {
return this.x + this.width / 2;
}
this.top = function() {
return this.y - this.height / 4;
}
this.bottom = function() {
return this.y + this.height / 4;
}
//////////////////////////////////////////////////////////////
this.leftt = function() {
return this.x - this.width / 2;
}
this.rightt = function() {
return this.x + this.width / 2;
}
this.topp = function() {
return this.y - this.height / 2;
}
this.bottomm = function() {
return this.y + this.height / 2;
}
this.hitTestObject = function(obj) {
if (this.left() < obj.right() &&
this.right() > obj.left() &&
this.top() < obj.bottom() &&
this.bottom() > obj.top()) {
return true
}
return false;
}
}
<canvas id="canvas" width = "1024" height ="800" >
Your browser is outdated and does not support HTML5. Please update to the latest version.
</canvas>
I'm developing a game and I was wondering why isn't the "crab" (an entity) killable like the "monster" (also an entity). What I mean is that if I touch the goblin monster, I get a point, but I just walk across the crab.
I attempted to add an if..else, but then the player got thousands of points per second.
What have I done wrong?
// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function() {
bgReady = true;
};
bgImage.src = "images/background.png";
// Hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function() {
heroReady = true;
};
heroImage.src = "images/hero.png";
// Monster image
var monsterReady = false;
var monsterImage = new Image();
monsterImage.onload = function() {
monsterReady = true;
};
monsterImage.src = "images/monster.png";
// Crab image
var crabReady = false;
var crabImage = new Image();
crabImage.onload = function() {
crabReady = true;
};
crabImage.src = "images/old/hero.png";
// Game objects
var hero = {
speed: 300 // movement in pixels per second
};
var monster = {};
var crab = {};
var monstersCaught = 0;
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function(e) {
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function(e) {
delete keysDown[e.keyCode];
}, false);
// Reset the game when the player catches a monster
var reset = function() {
hero.x = canvas.width / 2;
hero.y = canvas.height / 2;
// Throw the monster somewhere on the screen randomly
monster.x = 32 + (Math.random() * (canvas.width - 64));
monster.y = 32 + (Math.random() * (canvas.height - 64));
// Throw the crab somewhere on the screen randomly
crab.x = 32 + (Math.random() * (canvas.width - 64));
crab.y = 32 + (Math.random() * (canvas.height - 64));
};
// Update game objects
var update = function(modifier) {
if (38 in keysDown) { // Player holding up
hero.y -= hero.speed * modifier;
}
if (40 in keysDown) { // Player holding down
hero.y += hero.speed * modifier;
}
if (37 in keysDown) { // Player holding left
hero.x -= hero.speed * modifier;
}
if (39 in keysDown) { // Player holding right
hero.x += hero.speed * modifier;
}
// Are they touching?
if (
hero.x <= (monster.x + 32) && monster.x <= (hero.x + 32) && hero.y <= (monster.y + 32) && monster.y <= (hero.y + 32)
) {
++monstersCaught;
reset();
}
};
// Draw everything
var render = function() {
if (bgReady) {
ctx.drawImage(bgImage, 0, 0);
}
if (heroReady) {
ctx.drawImage(heroImage, hero.x, hero.y);
}
if (monsterReady) {
ctx.drawImage(monsterImage, monster.x, monster.y);
}
if (crabReady) {
ctx.drawImage(crabImage, crab.x, crab.y);
}
// Score
ctx.fillStyle = "rgb(250, 250, 250)";
ctx.font = "24px Helvetica";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText("Mobs killed: " + monstersCaught, 32, 32);
};
// The main game loop
var main = function() {
var now = Date.now();
var delta = now - then;
update(delta / 1000);
render();
then = now;
// Request to do this again ASAP
requestAnimationFrame(main);
};
// Cross-browser support for requestAnimationFrame
var w = window;
requestAnimationFrame = w.requestAnimationFrame || w.webkitRequestAnimationFrame || w.msRequestAnimationFrame || w.mozRequestAnimationFrame;
// Let's play this game!
var then = Date.now();
reset();
main();
<!DOCTYPE html>
<html>
<head>
<title>Underbound</title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="game">
<script src="js/game.js"></script>
</div>
</body>
</html>
Because you're only checking if the hero collides with monster.
hero.x <= (monster.x + 32) && monster.x <= (hero.x + 32) && hero.y <= (monster.y + 32) && monster.y <= (hero.y + 32)
Instead, you should probably create a function for checking if they collide:
function isColliding(a, b) {
return a.x <= (b.x + 32) && b.x <= (a.x + 32) &&
a.y <= (b.y + 32) && b.y <= (a.y + 32);
}
if (isColliding(hero, monster)) { ...
Then use also check if they collide with crab.
if (isColliding(hero, crab)) { ...
It'd be more sustainable (until you have a whole lot of monsters) if you put all of your "monsters" into an array then check against each monster in the array.
As for the issue with gaining lots of points quickly: you have to remove the monster (or crab) from the play area and stop checking for collisions during the update phase or the player will continue to collide with the crab and gain points.
One solution for this would be to give your monsters an active (or similar property). By default, this will be true but when the player collides with them, this will be false. Then you will only draw them and check for collisions if active is true.
My HTML5 Canvas element doesn't seem to hide.
I created a timer that should hide the element when the timer reaches 0, I tested this with an alert flag and that worked fine.
Issue:
if (TotalSeconds <= 0)
{
ctx.clearRect(0, 0, canvas.width, canvas.height)
}
Entire code:
// Create the canvas
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 512;
canvas.height = 480;
document.body.appendChild(canvas);
// Background image
var bgReady = false;
var bgImage = new Image();
bgImage.onload = function () {
bgReady = true;
};
bgImage.src = "images/background.png";
// Hero image
var heroReady = false;
var heroImage = new Image();
heroImage.onload = function () {
heroReady = true;
};
heroImage.src = "images/hero.png";
// Monster image
var monsterReady = false;
var monsterImage = new Image();
monsterImage.onload = function () {
monsterReady = true;
};
monsterImage.src = "images/flamingo.png";
// Game objects
var hero = {
speed: 256 // movement in pixels per second
};
var monster = {};
var monstersCaught = 0;
// Handle keyboard controls
var keysDown = {};
addEventListener("keydown", function (e) {
keysDown[e.keyCode] = true;
}, false);
addEventListener("keyup", function (e) {
delete keysDown[e.keyCode];
}, false);
// Reset the game when the player catches a monster
var reset = function () {
hero.x = canvas.width / 2;
hero.y = canvas.height / 2;
// Throw the monster somewhere on the screen randomly
monster.x = 32 + (Math.random() * (canvas.width - 64));
monster.y = 32 + (Math.random() * (canvas.height - 64));
};
// Update game objects
var update = function (modifier) {
if (38 in keysDown) { // Player holding up
hero.y -= hero.speed * modifier;
}
if (40 in keysDown) { // Player holding down
hero.y += hero.speed * modifier;
}
if (37 in keysDown) { // Player holding left
hero.x -= hero.speed * modifier;
}
if (39 in keysDown) { // Player holding right
hero.x += hero.speed * modifier;
}
// Are they touching?
if (
hero.x <= (monster.x + 32)
&& monster.x <= (hero.x + 32)
&& hero.y <= (monster.y + 32)
&& monster.y <= (hero.y + 32)
)
{
++monstersCaught;
reset();
}
if (hero.x <= 0)
{
hero.x = 510
}
if (hero.y <= 0)
{
hero.y = 478
}
};
CreateTimer(5);
var Timer;
var TotalSeconds;
function CreateTimer(Time) {
Timer = $("#timer").text();
TotalSeconds = Time;
UpdateTimer()
window.setTimeout("Tick()", 1000);
}
function Tick() {
TotalSeconds -= 1;
UpdateTimer()
window.setTimeout("Tick()", 1000);
}
function UpdateTimer() {
$("#timer").text(TotalSeconds);
if (TotalSeconds <= 0)
{
ctx.clearRect(0, 0, canvas.width, canvas.height)
}
}
// Draw everything
var render = function () {
if (bgReady) {
ctx.drawImage(bgImage, 0, 0);
}
if (heroReady) {
ctx.drawImage(heroImage, hero.x, hero.y);
}
if (monsterReady) {
ctx.drawImage(monsterImage, monster.x, monster.y);
}
// Score
ctx.fillStyle = "rgb(250, 250, 250)";
ctx.font = "24px Helvetica";
ctx.textAlign = "left";
ctx.textBaseline = "top";
ctx.fillText("Flamingos slaughtered: " + monstersCaught, 32, 32);
ctx.textAlign = "right";
ctx.textBaseline = "bottom";
ctx.fillText("Time left: " + TotalSeconds, 150,32);
};
// The main game loop
var main = function () {
var now = Date.now();
var delta = now - then;
update(delta / 1000);
render();
then = now;
};
// Let's play this game!
reset();
var then = Date.now();
setInterval(main, 1); // Execute as fast as possible
The html is just <canvas></canvas>
Pretty new to this so any help would be appreciated.
Thanks!
This does not hide the canvas but clear the context, which means it's clear the drawn shape on canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
You can hide it by appying a CSS style for it:
if (TotalSeconds <= 0) {
ctx.canvas.style.display = 'none';
}
and to reveal it again simple use block or inline-block instead of none.
If you want to hide it but keep its space you can use:
ctx.canvas.style.visibility = 'hidden';
You can also remove it completely from the DOM tree by using:
parent.removeChild(canvasElement);
where parent is the container element (for example document.body as you are using now) and canvasElement is a reference is your canvas.
All that being said - if you want to just clear the canvas then you need to stop the loop you have running. You can use for example a flag to do this:
function Tick() {
TotalSeconds--;
UpdateTimer();
if (TotalSeconds > 0) setTimeout(Tick, 1000); // only loop if sec > 0
}
and then clear it as you already do.
Hope this helps!