var car;
var front;
var back;
var carpoint1;
var carpoint2;
var carpoint3;
var carpoint4;
var img = new Image();
img.src = 'https://cdn4.iconfinder.com/data/icons/transportation-2-4/60/transportation-2-flat-036-racing-car-top-512.png';
function startGame() {
car = new move(12, 20, "red", 600, 300);
pg.start();
}
var pg = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 1200;
this.canvas.height = 600;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateframe, 20);
window.addEventListener('keydown', function (e) {
e.preventDefault();
pg.keys = (pg.keys || []);
pg.keys[e.keyCode] = (e.type == "keydown");
})
window.addEventListener('keyup', function (e) {
pg.keys[e.keyCode] = (e.type == "keydown");
})
},
stop : function() {
clearInterval(this.interval);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function move(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speed = 0;
this.angle = 0;
this.moveAngle = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = pg.context;
ctx.save();
getcarpoints(this.x, this.y, this.angle);
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.drawImage(img, this.width / -2, this.height / -2,20,40);
ctx.restore();
ctx.beginPath();
ctx.moveTo(300, 150);
ctx.lineTo(600, 800);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(300, 150);
ctx.lineTo(carpoint1[0], carpoint1[1]);
ctx.stroke();
}
this.newPos = function() {
this.angle += this.moveAngle * Math.PI / 180;
this.x += this.speed * Math.sin(this.angle);
this.y -= this.speed * Math.cos(this.angle);
}
}
function getcarpoints(prex,prey,rotation)
{
carpoint1=[getrotatedx(prex,prey,rotation), getrotatedy(prex,prey,rotation)];
carpoint2=[carpoint1[0], carpoint1[1]+40];
carpoint3=[carpoint2[0]+20, carpoint2[1]+40];
carpoint4=[carpoint3[0]+20, carpoint3[1]];
// console.log(carpoint1[0]);
}
function getrotatedx(prex,prey,rotation)
{
piangle=Math.abs((rotation/ Math.PI * 180)%360);
newx=Math.cos(piangle)*prex+(-(Math.sin(piangle)*prey));
return newx;
}
function getrotatedy(prex,prey,rotation)
{
piangle=Math.abs((rotation/ Math.PI * 180)%360);
newy=Math.sin(piangle)*prex+(Math.cos(piangle)*prey);
return newy;
}
function updateframe() {
pg.clear();
car.moveAngle = 0;
car.speed = 0;
if (pg.keys && pg.keys[37]) { if (pg.keys && pg.keys[40]) {car.moveAngle= 5; } if (pg.keys && pg.keys[38]){car.moveAngle = -5; } }
if (pg.keys && pg.keys[39]) { if (pg.keys && pg.keys[40]) {car.moveAngle= -5; } if (pg.keys && pg.keys[38]){car.moveAngle = 5; } }
if (pg.keys && pg.keys[38]) {car.speed= 5; }
if (pg.keys && pg.keys[40]) {car.speed= -5; }
car.newPos();
car.update();
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
canvas {
border:1px solid #d3d3d3;
background-color: #f1f1f1;
}
</style>
</head>
<body onload="startGame()">
<script src="control.js"></script>
</body>
</html>
Here is my full code in snippet. I am trying to make a line from one fix point to the car... and this is the problem.
Now when is horizontal at any x point it works perfectly but the moment car turn the angle changes and it all messes up! you can see that when you turn the car (use arrow and left or right arrow at the same time) the line jumps.
Note: it is my project requirement to do it with 2d rotation matrix which means I can't make the line before i restore the canvas.
carpoint1,2,3,4 are the corners of car but right now I am just working with the carpoint1.
Do something so getrotatedx and getrotatedy always gives correct value that are car coordinates after matrix rotation.
Use ctx.lineTo(this.x, this.y); instead of ctx.lineTo(carpoint1[0], carpoint1[1]);
var car;
var front;
var back;
var carpoint1;
var carpoint2;
var carpoint3;
var carpoint4;
var img = new Image();
img.src = 'https://cdn4.iconfinder.com/data/icons/transportation-2-4/60/transportation-2-flat-036-racing-car-top-512.png';
function startGame() {
car = new move(12, 20, "red", 600, 300);
pg.start();
}
var pg = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 1200;
this.canvas.height = 600;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateframe, 20);
window.addEventListener('keydown', function (e) {
e.preventDefault();
pg.keys = (pg.keys || []);
pg.keys[e.keyCode] = (e.type == "keydown");
})
window.addEventListener('keyup', function (e) {
pg.keys[e.keyCode] = (e.type == "keydown");
})
},
stop : function() {
clearInterval(this.interval);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function move(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speed = 0;
this.angle = 0;
this.moveAngle = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = pg.context;
ctx.save();
getcarpoints(this.x, this.y, this.angle);
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.drawImage(img, this.width / -2, this.height / -2,20,40);
ctx.restore();
ctx.beginPath();
ctx.moveTo(300, 150);//fixed point
ctx.lineTo(600, 800);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(300, 150);
ctx.lineTo(this.x, this.y);
ctx.stroke();
}
this.newPos = function() {
this.angle += this.moveAngle * Math.PI / 180;
this.x += this.speed * Math.sin(this.angle);
this.y -= this.speed * Math.cos(this.angle);
}
}
function getcarpoints(prex,prey,rotation)
{
carpoint1=[getrotatedx(prex,prey,rotation), getrotatedy(prex,prey,rotation)];
carpoint2=[carpoint1[0], carpoint1[1]+40];
carpoint3=[carpoint2[0]+20, carpoint2[1]+40];
carpoint4=[carpoint3[0]+20, carpoint3[1]];
// console.log(carpoint1[0]);
}
function getrotatedx(prex,prey,rotation)
{
piangle=Math.abs((rotation/ Math.PI * 180)%360);
newx=Math.cos(piangle)*prex+(-(Math.sin(piangle)*prey));
return newx;
}
function getrotatedy(prex,prey,rotation)
{
piangle=Math.abs((rotation/ Math.PI * 180)%360);
newy=Math.sin(piangle)*prex+(Math.cos(piangle)*prey);
return newy;
}
function updateframe() {
pg.clear();
car.moveAngle = 0;
car.speed = 0;
if (pg.keys && pg.keys[37]) { if (pg.keys && pg.keys[40]) {car.moveAngle= 5; } if (pg.keys && pg.keys[38]){car.moveAngle = -5; } }
if (pg.keys && pg.keys[39]) { if (pg.keys && pg.keys[40]) {car.moveAngle= -5; } if (pg.keys && pg.keys[38]){car.moveAngle = 5; } }
if (pg.keys && pg.keys[38]) {car.speed= 5; }
if (pg.keys && pg.keys[40]) {car.speed= -5; }
car.newPos();
car.update();
}
startGame()
canvas {
border:1px solid #d3d3d3;
background-color: #f1f1f1;
}
Related
I have created a simple game using Canvas in Javascript where the player has to avoid obstacles by jumping over or shrinking. The obstacle images, which are animated moving towards the left, flickers at some sort of interval. The interval increases in parallel with the gameSpeed variable, making me wonder if this might have something to do with either the spawnObstacle() or the update() functions. Another reason why I believe so is because neither the drawn playerImg.png nor the drawn Score/Highscore ever flickers. I have tried several different solutions found online, but none seem to solve my problem.
Here is my index.js and index.html below:
import {registerNewHighscore, makeList} from "./globalHs.js";
const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');
const newGameBtn = document.getElementById("newGame");
const seeInstrBtn = document.getElementById("instrBtn");
const seeHsBtn = document.getElementById("hsBtn");
const goBackBtn = document.getElementById("backBtn");
let score;
let highscore;
let scoreText;
let highscoreText;
let player;
let gravity;
let obstacles = [];
let gameSpeed;
let keyPressed;
let isKeyPressed = false
let active = true;
let rotation = 0;
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
function createImage(path){
let image = new Image();
image.src = path;
return image;
}
const obsImg = createImage("img/chatbubble.png");
const rockImg = createImage("img/rock.png");
const roadblockImg = createImage("img/roadblock.png");
const playerImg = createImage("img/logoPlayer.png");
newGameBtn.addEventListener('click', function() {
document.getElementById("newGame").style.display = "none";
document.getElementById("header").style.display = "none";
document.getElementById("instr").style.display = "none";
document.getElementById("main").style.display = "block";
document.getElementById("instrBtn").style.display = "none";
document.getElementById("hsBtn").style.display = "none";
document.getElementById("hsBoard").style.display = "none";
start();
});
seeInstrBtn.addEventListener('click', function(){
document.getElementById("header").style.display = "none";
document.getElementById("instrBtn").style.display = "none";
document.getElementById("newGame").style.display = "none";
document.getElementById("instr").style.display = "block";
document.getElementById("instr").style.visibility = "visible";
document.getElementById("backBtn").style.display = "block";
document.getElementById("hsBtn").style.display = "none";
document.getElementById("hsBoard").style.display = "none";
document.getElementById("backBtn").style.top = "50%";
});
seeHsBtn.addEventListener('click', function(){
document.getElementById("header").style.display = "none";
document.getElementById("hsBtn").style.display = "none";
document.getElementById("newGame").style.display = "none";
document.getElementById("instrBtn").style.display = "none";
document.getElementById("instr").style.display = "none";
document.getElementById("hsBoard").style.display = "block";
document.getElementById("backBtn").style.display = "block";
document.getElementById("backBtn").style.top = "70%";
makeList();
});
goBackBtn.addEventListener('click', function() {
goBack();
});
function goBack() {
document.getElementById("backBtn").style.display = "none";
document.getElementById("instr").style.display = "none";
document.getElementById("header").style.display = "block";
document.getElementById("newGame").style.display = "block";
document.getElementById("instrBtn").style.display = "block";
document.getElementById("hsBtn").style.display = "block";
document.getElementById("hsBoard").style.display = "none";
};
document.addEventListener('keydown', function(evt) {
if (isKeyPressed) return;
isKeyPressed = true;
keyPressed = evt.code;
});
document.addEventListener('keyup', function(evt) {
if (evt.code !== keyPressed) return; // only respond to the key already pressed
isKeyPressed = false;
keyPressed = null;
});
function randomIntInRange (min, max){
return Math.round(Math.random() * (max - min) + min);
}
class Player{
constructor (x, y, r, w, h, playerImg){
this.playerImg = playerImg;
this.x = x;
this.y = y;
this.r = r;
this.w = r*2;
this.h = r*2;
this.dy = 0;
this.jumpForce = 18;
this.originalRad = r;
this.grounded = false;
this.jumpTimer = 0;
/* this.newRotation = 0; */
}
animate () {
if (['Space', 'KeyW'].includes(keyPressed)) {
this.jump();
} else{
this.jumpTimer = 0;
}
if (['ShiftLeft', 'KeyS'].includes(keyPressed)){
/* this.newRotation = rotation * 2; */
this.r = this.originalRad / 2;
this.w = this.originalRad;
this.h = this.originalRad;
} else {
/* this.newRotation = rotation; */
this.r = this.originalRad;
this.w = this.r * 2;
this.h = this.r * 2;
}
this.y += this.dy;
if (this.y + this.r < canvas.height){
this.dy += gravity;
this.grounded = false;
} else{
this.dy = 0;
this.grounded = true;
this.y = canvas.height - this.r;
}
this.draw();
}
jump () {
if (this.r != this.originalRad) return;
if (this.grounded && this.jumpTimer == 0){
this.jumpTimer = 1.5;
this.dy = -this.jumpForce;
} else if (this.jumpTimer > 0 && this.jumpTimer < 15){
this.jumpTimer++;
this.dy = -this.jumpForce - (this.jumpTimer / 50);
}
}
draw () {
ctx.translate(this.x, this.y);
ctx.rotate(rotation);
ctx.translate(-(this.x), -(this.y));
ctx.drawImage(this.playerImg, (this.x-this.r), (this.y-this.r), this.w, this.h);
ctx.setTransform(1, 0, 0, 1, 0, 0);
}
}
class Obstacle {
constructor (x, y, w, h, obsImg){
this.obsImg = obsImg;
this.x = x,
this.y = y,
this.w = w;
this.h = h;
this.dx = -gameSpeed;
obsImg.width = this.w;
obsImg.height = this.h;
}
update (){
this.x += this.dx;
this.dx = -gameSpeed;
}
draw () {
ctx.beginPath();
ctx.fillStyle = "rgba(0, 0, 0, 0)";
ctx.fillRect(this.x, this.y, this.w, this.h,);
ctx.drawImage(this.obsImg, this.x, this.y, this.w*1.1, this.h);
ctx.closePath();
}
/////// CIRCLE
/*draw () {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, (2 * Math.PI), false)
ctx.fillStyle = this.c;
ctx.fill();
ctx.closePath();
}*/
/////// ELLIPSE
/*draw () {
ctx.beginPath();
ctx.ellipse(this.x, this.y, this.radX, this.radY, 0, 0, 2 * Math.PI);
ctx.fillStyle = this.c;
ctx.fill();
ctx.stroke();
}*/
}
class Rock {
constructor (x, y, w, h, rockImg){
this.rockImg = rockImg;
this.x = x,
this.y = y,
this.w = w;
this.h = h;
this.dx = -gameSpeed;
rockImg.width = this.w;
rockImg.height = this.h;
}
update (){
this.x += this.dx;
this.dx = -gameSpeed;
}
draw () {
ctx.beginPath();
ctx.fillStyle = "rgba(0, 0, 0, 0)";
ctx.fillRect(this.x+20, this.y+40, this.w-20, this.h-40);
ctx.drawImage(this.rockImg, this.x-20, this.y, this.w*1.5, this.h*1.5);
ctx.closePath();
}
}
class Roadblock {
constructor (x, y, w, h, roadblockImg){
this.roadblockImg = roadblockImg;
this.x = x,
this.y = y,
this.w = w;
this.h = h;
this.dx = -gameSpeed;
roadblockImg.width = this.w;
roadblockImg.height = this.h;
}
update (){
this.x += this.dx;
this.dx = -gameSpeed;
}
draw () {
ctx.beginPath();
ctx.fillStyle = "rgba(0, 0, 0, 0)";
ctx.fillRect(this.x, this.y+15, this.w, this.h,);
ctx.drawImage(this.roadblockImg, this.x, this.y, this.w, this.h*1.15);
ctx.closePath();
}
}
class Text{
constructor(t, x, y, a, c, s){
this.t = t;
this.x = x;
this.y = y;
this.a = a;
this.c = c;
this.s = s;
}
draw () {
ctx.beginPath();
ctx.fillStyle = this.c;
ctx.font = this.s + "px";
ctx.textAlign = this.a;
ctx.fillText(this.t, this.x, this.y);
ctx.closePath();
}
}
function getDistance(player, obstacle) {
var distX = Math.abs(player.x - (obstacle.x + obstacle.w / 2));
var distY = Math.abs(player.y - (obstacle.y + obstacle.h / 2));
if (distX > (obstacle.w / 2 + player.r)) { return false; }
if (distY > (obstacle.h / 2 + player.r)) { return false; }
if (distX <= (obstacle.w)) { return true; }
if (distY <= (obstacle.h)) { return true; }
var dx = distX - obstacle.w / 2;
var dy = distY - obstacle.h / 2;
return (dx * dx + dy * dy <= (player.r*player.r));
}
let initialSpawnTimer = 200;
let spawnTimer = initialSpawnTimer;
function spawnObstacle (){
let sizeX;
let sizeY;
let type = randomIntInRange(0, 2);
let obstacle = new Obstacle(
canvas.width + sizeX,
canvas.height - sizeX,
sizeX,
sizeY,
obsImg
);
if (type == 0){
sizeX = randomIntInRange(100, 160);
sizeY = sizeX / 2;
obstacle = new Rock(
canvas.width + sizeX,
canvas.height - sizeY,
sizeX,
sizeY,
rockImg
);
} else if (type == 1){
sizeX = randomIntInRange(80, 160);
sizeY = sizeX / 2;
obstacle = new Obstacle(
canvas.width + sizeX,
canvas.height - sizeX,
sizeX,
sizeY,
obsImg
);
obstacle.y -= player.originalRad + randomIntInRange(-50, 150);
} else if (type == 2){
sizeX = 150;
sizeY = sizeX / 2;
obstacle = new Roadblock(
canvas.width + sizeX,
canvas.height - sizeY,
sizeX,
sizeY,
roadblockImg
);
}
obstacles.push(obstacle);
}
function start () {
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
ctx.font = "40px Courier New";
active = true;
gameSpeed = 6;
gravity = 1;
score = 0;
highscore = 0;
if (localStorage.getItem('highscore')){
highscore = localStorage.getItem('highscore');
}
player = new Player(100, 0, 50, 100, 100, playerImg);
scoreText = new Text("Score: " + score, 45, 45, "left", "#212121", "40");
highscoreText = new Text("Highscore: " + highscore, 45,
90, "left", "gold", "40");
window.requestAnimationFrame(update);
}
let lastTime;
function update (time) {
if (lastTime != null) {
const delta = time - lastTime;
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
spawnTimer--;
if (spawnTimer <= 0){
spawnObstacle();
spawnTimer = initialSpawnTimer - gameSpeed * 8;
if (spawnTimer < 60){
spawnTimer = randomIntInRange(40, 80);
}
}
for (let i = 0; i < obstacles.length; i++){
let o = obstacles[i];
o.draw();
o.update();
if (o.x + o.y < 0){
obstacles.splice(i, 1);
}
if (getDistance(player, o)) {
active = false;
obstacles = [];
spawnTimer = initialSpawnTimer;
gameSpeed = 6;
window.localStorage.setItem('highscore', highscore);
score -= 1;
highscore -= 1;
if (score >= highscore){
registerNewHighscore(highscore+1);
}
goBack();
}
}
lastTime = time;
if (active){
window.requestAnimationFrame(update);
}
player.animate();
score++;
scoreText.t = "Score: " + score;
scoreText.draw();
if (score > highscore){
highscore = score;
highscoreText.t = "Highscore: " + highscore;
}
highscoreText.draw();
rotation+=Math.PI/180 * 2 + gameSpeed * 0.01;
gameSpeed += 0.002;
}
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Kindly Waiting Game V2</title>
<link rel="stylesheet" href="styles.css" />
</head>
<body>
<div class="world">
<div id="header">The Kindly Game</div>
<div id="newGame" onmouseover="this.style.backgroundColor = 'goldenrod'"
onmouseout="this.style.backgroundColor= 'gold'">New Game</div>
<div id="instrBtn" onmouseover="this.style.backgroundColor = 'goldenrod'" onmouseout="this.style.backgroundColor
= 'gold'">Instructions</div>
<div id="hsBtn" onmouseover="this.style.backgroundColor = 'goldenrod'" onmouseout="this.style.backgroundColor
= 'gold'">Highscores</div>
<div id="instr" style="display: none">Avoid the <br>chatbubbles, <br>roadblocks, <br>and rocks!<br><br>
Instructions: <br>Space/W: Jump <br>ShiftLeft/S: Shrink</div>
<div id="hsBoard" style="display: none">Highscores:</div>
<div id="backBtn" onmouseover="this.style.backgroundColor = 'goldenrod'" onmouseout="this.style.backgroundColor
= 'gold'">Back</div>
<div id="main"></div>
<div id="score"></div>
<div id="cloudLarge"></div>
<div id="cloudMedium"></div>
<div id="cloudSmall"></div>
<div id="cloudSmall2"></div>
<div id="ufo"></div>
<div id="airplane"></div>
<div id="ye"></div>
</div>
<canvas id="game" width="640" height="400"></canvas>
<script src="globalHs.js" type="module"></script>
<script src="index.js" type="module"></script>
</body>
</html>
Your issue is caused by this block of code inside your update() function:
if (o.x + o.y < 0){
obstacles.splice(i, 1);
}
Now while I don't know the exact logic why you're checking the sum of the obstacles' horizontal and vertical position, you're actually removing something from an array with the .splice() method. As this is happening inside a for-loop you're actually modifying the length of the array while it might still loop over it.
You can fix this by looping over the array from the last to the first element:
for (let i = obstacles.length-1; i>=0; i--) {
let o = obstacles[i];
o.draw();
o.update();
if (o.x + o.y < 0) {
obstacles.splice(i, 1);
}
if (getDistance(player, o)) {
active = false;
obstacles = [];
spawnTimer = initialSpawnTimer;
gameSpeed = 6;
window.localStorage.setItem('highscore', highscore);
score -= 1;
highscore -= 1;
if (score >= highscore) {
registerNewHighscore(highscore + 1);
}
goBack();
}
}
When the component or square touches the bottom of the canvas and I press the up arrow afterwards it collides with the bottom, every jump the component jumps when I press the up arrow it jumps upwards less and less until the component eventually does not jump at all. But the component at the same time moves left and right perfectly still when this problem occurs.
I am controlling the square with the arrow keys and it is the player for this platform game that i am creating and i have no clue how i can change it.
var myGamePiece;
var platformWidth = 500;
var platformX = 0;
var platformY = 250;
function startGame() {
myGameArea.start();
myGamePiece = new component(30, 30, "red", 10, 120);
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
window.addEventListener("keydown", function(e) {
myGameArea.key = e.keyCode;
});
window.addEventListener("keyup", function(e) {
myGameArea.key = false;
});
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
};
function component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.speedX = 0;
this.speedY = 0;
this.gravity = 0.05;
this.gravitySpeed = 0;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
};
this.newPos = function() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
this.y += this.speedY + this.gravitySpeed;
this.hitBottom();
};
this.hitBottom = function() {
var rockbottom = myGameArea.canvas.height - this.height;
if (this.y > rockbottom) {
this.y = rockbottom;
if (myGameArea.canvas.height - this.height && myGamePiece.key == 38) {
this.y = this.speedY;
}
}
};
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
if (myGameArea.key && myGameArea.key == 37) {
myGamePiece.speedX = -5;
}
if (myGameArea.key && myGameArea.key == 39) {
myGamePiece.speedX = 5;
}
if (myGameArea.key && myGameArea.key == 38) {
myGamePiece.speedY = -5;
} else {
myGamePiece.speedY = 5;
}
if (myGameArea.key && myGameArea.key == 40) {
myGamePiece.speedY = 5;
}
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
Did you forget to reset the gravity speed?
this.hitBottom = function() {
// ...
if (this.y > rockbottom) {
// ...
this.gravitySpeed = 0; // reset?
}
};
var myGamePiece;
var platformWidth = 360;
var platformX = 0;
var platformY = 120;
function startGame() {
myGameArea.start();
myGamePiece = new Component(12, 12, "red", 10, 10);
}
var myGameArea = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = platformWidth;
this.canvas.height = platformY;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 20);
window.addEventListener("keydown", function(e) {
myGameArea.key = e.keyCode;
});
window.addEventListener("keyup", function(e) {
myGameArea.key = false;
});
},
fill: function(color) {
this.context.save();
this.context.fillStyle = color;
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.context.restore();
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
};
function Component(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.speedX = 0;
this.speedY = 0;
this.gravity = 0.05;
this.gravitySpeed = 0;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
};
this.newPos = function() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
this.y += this.speedY + this.gravitySpeed;
this.hitBottom();
};
this.hitBottom = function() {
var rockbottom = myGameArea.canvas.height - this.height;
if (this.y > rockbottom) {
this.y = rockbottom;
if (myGameArea.canvas.height - this.height && myGamePiece.key == 38) {
this.y = this.speedY;
}
this.gravitySpeed = 0; // reset?
}
};
}
function updateGameArea() {
myGameArea.fill('#DE7');
myGamePiece.speedX = 0;
myGamePiece.speedY = 0;
if (myGameArea.key) {
switch (myGameArea.key) {
case 37: // left arrow
myGamePiece.speedX = -5;
break;
case 38: // up arrow
myGamePiece.speedY = -5;
break;
case 39: // right arrow
myGamePiece.speedX = +5;
break;
case 40: // down arrow
default:
myGamePiece.speedY = +5;
}
}
myGamePiece.newPos();
myGamePiece.update();
}
startGame();
body {
background: #000;
}
Here is another approach using classes, you can clean up the vector math, by using actual vector classes e.g. Victor.js.
const main = () => {
new GravityGame({
width : 360,
height : 180,
refreshRate : 20
}).start();
}
class AbstractGameClient {
constructor(options) {
this.refreshRate = options.refreshRate
this.view = new GameArea({
width : options.width,
height : options.height
})
}
update() {
this.view.update()
}
start() {
let self = this
self.intervalId = setInterval(function() { self.update() }, self.refreshRate)
return self
}
stop() {
if (self.intervalId) {
clearInterval(self.intervalId)
}
}
}
class GravityGame extends AbstractGameClient {
constructor(options) {
super(options)
let myGamePiece = new Component({
width : 12,
height : 12,
color : 'red'
})
this.view.addComponent(myGamePiece)
}
}
class GameArea {
constructor(options) {
let self = this
self.canvas = document.createElement('canvas')
self.width = options.width
self.height = options.height
self.key = null
self.components = []
self.addListeners()
self.render()
}
render() {
let self = this
self.canvas.width = self.width
self.canvas.height = self.height
self.context = self.canvas.getContext('2d')
document.body.insertBefore(self.canvas, document.body.childNodes[0])
}
addComponent(component) {
this.centerComponent(component)
this.components.push(component)
}
addListeners() {
let self = this;
window.addEventListener('keydown', function(e) {
self.key = e.keyCode;
});
window.addEventListener('keyup', function(e) {
self.key = false;
});
}
fill(color) {
this.context.save();
this.context.fillStyle = color;
this.context.fillRect(0, 0, this.canvas.width, this.canvas.height);
this.context.restore();
}
clear() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
update() {
let self = this
let speed = { x : 0, y : 0 }
if (self.key) {
switch (self.key) {
case 37: // left arrow
speed.x = -5;
break;
case 38: // up arrow
speed.y = -5;
break;
case 39: // right arrow
speed.x = +5;
break;
case 40: // down arrow
default:
speed.y = +5;
}
}
self.fill('#DE7')
self.components.forEach(component => {
component.speed.x = speed.x
component.speed.y = speed.y
component.reposition(self.context)
component.redraw(self.context)
})
}
centerComponent(component) {
let xOffset = Math.floor((this.canvas.width / 2) - component.width / 2)
let yOffset = Math.floor((this.canvas.height / 2) - component.height / 2)
component.position = { x : xOffset, y : yOffset }
}
};
class Component {
constructor(options) {
let self = this
self.width = options.width
self.height = options.height
self.position = options.position
self.color = options.color
self.type = options.type
self.speed = { x : 0, y : 0 }
self.gravity = { x : 0, y : 0.05 };
self.acceleration = { x : 0, y : 0 };
}
redraw(context) {
context.fillStyle = this.color;
context.fillRect(this.position.x, this.position.y, this.width, this.height);
}
reposition(context) {
let self = this
// Increase acceleration
self.acceleration.x += self.gravity.x;
self.acceleration.y += self.gravity.y;
// pos + speed + acceleration
self.position.x += self.speed.x + self.acceleration.x;
self.position.y += self.speed.y + self.acceleration.y;
self.checkBounds(context);
}
checkBounds(context) {
let self = this
let rockbottom = context.canvas.height - this.height
if (self.position.y > rockbottom) {
self.position.y = rockbottom
if (context.canvas.height - self.height && self.key == 38) {
self.position.y = self.speed.y
}
self.acceleration = { x : 0, y : 0 } // reset
}
}
}
main();
body {
background: #000;
}
var car;
var front;
var back;
var img = new Image();
img.src = 'https://cdn4.iconfinder.com/data/icons/transportation-2-4/60/transportation-2-flat-036-racing-car-top-512.png';
function startGame() {
car = new move(12, 20, "red", 600, 300);
pg.start();
}
var pg = {
canvas: document.createElement("canvas"),
start: function() {
this.canvas.width = 1200;
this.canvas.height = 600;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateframe, 20);
window.addEventListener('keydown', function(e) {
e.preventDefault();
pg.keys = (pg.keys || []);
pg.keys[e.keyCode] = (e.type == "keydown");
})
window.addEventListener('keyup', function(e) {
pg.keys[e.keyCode] = (e.type == "keydown");
})
},
stop: function() {
clearInterval(this.interval);
},
clear: function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function move(width, height, color, x, y, type) {
this.type = type;
this.width = width;
this.height = height;
this.speed = 0;
this.angle = 0;
this.moveAngle = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = pg.context;
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.drawImage(img, this.width / -2, this.height / -2,20,40);
ctx.beginPath();
ctx.moveTo(this.width / -2, this.height / -2);
ctx.lineTo(this.width / -2, 30);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(this.width / -2, 30);
ctx.lineTo(13, (this.height / -2)+40);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(14, (this.height / -2)+40);
ctx.lineTo(14, this.height / -2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(14, this.height / -2);
ctx.lineTo(this.width / -2, this.height / -2);
ctx.stroke();
ctx.restore();
ctx.beginPath();
ctx.moveTo(300, 150);
ctx.lineTo(600, 800);
ctx.stroke();
}
this.newPos = function() {
this.angle += this.moveAngle * Math.PI / 180;
this.x += this.speed * Math.sin(this.angle);
this.y -= this.speed * Math.cos(this.angle);
}
}
function updateframe() {
pg.clear();
car.moveAngle = 0;
car.speed = 0;
if (pg.keys && pg.keys[37]) {
if (pg.keys && pg.keys[40]) {
car.moveAngle = 5;
}
if (pg.keys && pg.keys[38]) {
car.moveAngle = -5;
}
}
if (pg.keys && pg.keys[39]) {
if (pg.keys && pg.keys[40]) {
car.moveAngle = -5;
}
if (pg.keys && pg.keys[38]) {
car.moveAngle = 5;
}
}
if (pg.keys && pg.keys[38]) {
car.speed = 5;
}
if (pg.keys && pg.keys[40]) {
car.speed = -5;
}
car.newPos();
car.update();
}
startGame();
canvas {
border: 1px solid #d3d3d3;
background-color: #f1f1f1;
}
There is a car and a line, now i want to make an alert whenever the car get touched by the the line.
I know how to do this logically. like if i convert the car image in four lines (border) then use line intersection formula to get if there is a intersection but i am new to this canvas drawing and i cant figure how to get the border line equation of car.
update: i have made lines of border around the car, now i just need help with getting if these lines intersects with each other...
code is updated plz check it now...
one more thing, at this point there is only one line and i am going to add more lines in it... so i need a function to call it more often and get if the lines are intersecting with car border...
Note : use arrow keys to move car in snippet
I am trying to create a basic HTML game using the Canvas element, but I am having trouble with it. Unfortunately, I don't know where the error is in my code, so I have posted the entirety of the document I'm working on below.
My problem: The canvas is not displaying when I run the HTML document.
This code's based off of (as in it pretty much is) the Movement tutorial from w3schools for using the Canvas, available at https://www.w3schools.com/graphics/tryit.asp?filename=trygame_movement_keyboard, but when chaing variable names I must've broken something, because after looking at this for hours I can't figure out what I'm missing.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
canvas {
border:1px solid #d3d3d3;
background-color: #f1f1f1;
}
</style>
</head>
<body onload = "initial()">
<script>
var playerOne;
function initial() {
playerOne = new canvasObject(30, 30, "red", 225, 225);
gameArea.start();
}
var gameArea = {
canvas : document.createElement("canvas");
start : function() {
this.canvas.width = 480;
this.canvas.height = 270;
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('keydown', function (e) {
e.preventDefault();
gameArea.keys = (gameArea.keys || []);
gameArea.keys[e.keyCode] = (e.type == "keydown");
})
window.addEventListener('keyup', function (e) {
gameArea.keys[e.keyCode] = (e.type == "keydown");
})
},
stop : function() {
clearInterval(this.interval);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function canvasObject(width, height, color, x, y, type)
{
this.type = type;
this.width = width;
this.height = height;
this.speed = 0;
this.angle = 0;
this.moveAngle = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = gameArea.context;
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.fillStyle = color;
ctx.fillRect(this.width / -2, this.height / -2, this.width, this.height);
ctx.restore();
}
this.newPos = function() {
this.angle += this.moveAngle * Math.PI / 180;
this.x += this.speed * Math.sin(this.angle);
this.y -= this.speed * Math.cos(this.angle);
}
}
function updateGameArea() {
gameArea.clear();
playerOne.moveAngle = 0;
playerOne.speed = 0;
if (gameArea.keys && gameArea.keys[37]) {
playerOne.moveAngle = -1;
}
if (gameArea.keys && gameArea.keys[39]) {
playerOne.moveAngle = 1;
}
if (gameArea.keys && gameArea.keys[38]) {
playerOne.speed= 1;
}
if (gameArea.keys && gameArea.keys[40]) {
playerOne.speed= -1;
}
playerOne.newPos();
playerOne.update();
}
</script>
</body>
</html>
gameArea is an object. Object properties are separated with ,, not ;. Hence, there is a syntax error after the definition of canvas.
var playerOne;
function initial() {
playerOne = new canvasObject(30, 30, "red", 225, 225);
gameArea.start();
}
var gameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 480;
this.canvas.height = 270;
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('keydown', function (e) {
e.preventDefault();
gameArea.keys = (gameArea.keys || []);
gameArea.keys[e.keyCode] = (e.type == "keydown");
})
window.addEventListener('keyup', function (e) {
gameArea.keys[e.keyCode] = (e.type == "keydown");
})
},
stop : function() {
clearInterval(this.interval);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function canvasObject(width, height, color, x, y, type)
{
this.type = type;
this.width = width;
this.height = height;
this.speed = 0;
this.angle = 0;
this.moveAngle = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = gameArea.context;
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.fillStyle = color;
ctx.fillRect(this.width / -2, this.height / -2, this.width, this.height);
ctx.restore();
}
this.newPos = function() {
this.angle += this.moveAngle * Math.PI / 180;
this.x += this.speed * Math.sin(this.angle);
this.y -= this.speed * Math.cos(this.angle);
}
}
function updateGameArea() {
gameArea.clear();
playerOne.moveAngle = 0;
playerOne.speed = 0;
if (gameArea.keys && gameArea.keys[37]) {
playerOne.moveAngle = -1;
}
if (gameArea.keys && gameArea.keys[39]) {
playerOne.moveAngle = 1;
}
if (gameArea.keys && gameArea.keys[38]) {
playerOne.speed= 1;
}
if (gameArea.keys && gameArea.keys[40]) {
playerOne.speed= -1;
}
playerOne.newPos();
playerOne.update();
}
canvas {
border:1px solid #d3d3d3;
background-color: #f1f1f1;
}
<body onload = "initial()">
You have a syntax error:
var gameArea = {
canvas : document.createElement("canvas");
...
}
You've used ; instead of ,
I have taken an image and made it into my gamepiece put on a canvas, but I cannot get it to rotate properly. I apologize if my code is not very organized just got a little bit hurried. The problem will lie in the component function. Thank you for your help!
var myGamePiece;
function startGame() {
myGamePiece = new component(40, 40, "character.png", 300, 300, "image");
myGameArea.start();
}
var myGameArea = {
canvas: document.createElement("canvas")
, start: function () {
this.canvas.width = 640;
this.canvas.height = 480;
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('keydown', function (e) {
e.preventDefault();
myGameArea.keys = (myGameArea.keys || []);
myGameArea.keys[e.keyCode] = (e.type == "keydown");
})
window.addEventListener('keyup', function (e) {
myGameArea.keys[e.keyCode] = (e.type == "keydown");
})
}
, stop: function () {
clearInterval(this.interval);
}
, clear: function () {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
if (type == "image") {
this.image = new Image();
this.image.src = color;
}
this.width = width;
this.height = height;
this.speed = 0;
this.angle = 0;
this.moveAngle = 0;
this.x = x;
this.y = y;
this.update = function () {
ctx = myGameArea.context;
if (type == "image") {
ctx.save();
ctx.rotate(this.angle);
ctx.drawImage(this.image, this.x, this.y, this.width, this.height);
ctx.restore();
} else {
ctx.save();
ctx.translate(this.x, this.y);
ctx.fillStyle = color;
ctx.fillRect(this.width / -2, this.height / -2, this.width, this.height);
}
}
this.newPos = function () {
this.angle += this.moveAngle * Math.PI / 180;
this.x += this.speed * Math.sin(this.angle);
this.y -= this.speed * Math.cos(this.angle);
}
this.hitBottom = function () {
var bottom = myGameArea.canvas.height - 20;
if (this.y > bottom) {
this.y = this.y - 2.5;
}
}
this.hitTop = function () {
if (this.y < 20) {
this.y = this.y + 2.5;
}
}
this.hitLeft = function () {
if (this.x < 20) {
this.x = this.x + 2.5;
}
}
this.hitRight = function () {
var side = myGameArea.canvas.width - 20;
if (this.x > side) {
this.x = this.x - 2.5;
}
}
}
function updateGameArea() {
myGameArea.clear();
myGamePiece.moveAngle = 0;
myGamePiece.speed = 0;
if (myGameArea.keys && myGameArea.keys[37]) {
myGamePiece.moveAngle = -2.5;
}
if (myGameArea.keys && myGameArea.keys[39]) {
myGamePiece.moveAngle = 2.5;
}
if (myGameArea.keys && myGameArea.keys[38]) {
myGamePiece.speed = 2.5;
}
if (myGameArea.keys && myGameArea.keys[40]) {
myGamePiece.speed = -1;
}
myGamePiece.newPos();
myGamePiece.update();
myGamePiece.hitBottom();
myGamePiece.hitTop();
myGamePiece.hitLeft();
myGamePiece.hitRight();
}