2048 in javascript: updating the canvas - javascript

I am in a computer science class at my high school, and for my final project, my partner and I have decided to make 2048. We are not going to have the tiles "move", but instead, the 4x4 board will have "tiles" that are have properties of the number and color of the "tile" as it appears on the board. We are able to get the x and y coordinates of a tile to change, but the canvas will not update. We have had this problem for two weeks now, and have tried everything, but nothing has worked. Our code is posted below.
Please keep in mind that as we have only used javascript for a couple months, and only to do very simple things, our understanding is limited. Thank you for your help.
<!DOCTYPE html>
<html lang = "en">
<body style="background-color:lightgrey;">
<title>2048</title>
<canvas id="myCanvas" width="410" height="410" style="border:1px solid #d3d3d3;">
</canvas>
<script>
var x = 10;
var y = 10;
document.addEventListener('keydown', function(event)
{
if(event.keyCode == 37)//left
{
x -= 100;
console.log("x:"+ x);
}
else if(event.keyCode == 38)//up
{
y -= 100;
console.log("y:"+ y);
}
else if(event.keyCode == 39)//right
{
x += 100;
console.log("x:"+ x);
}
else if(event.keyCode == 40)//down
{
y += 100;
console.log("y:"+ y);
}
});
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// grey rectangle
ctx.beginPath();
ctx.lineWidth = "2";
ctx.strokeStyle = "grey";
ctx.rect(5, 5, 400, 400);
ctx.stroke();
// blue rectangle
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "blue";
ctx.rect(x, y, 100, 100);
ctx.stroke();
ctx.fillStyle = "blue";
ctx.fill();
</script>
</body>
</html>

What your game needs is a game loop. So the drawing needs to happen continously, at the moment you draw only one time at the beginning.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function draw() {
// clear the canvas so the old rectangles are gone
ctx.clearRect(0, 0, c.width, c.height);
// grey rectangle
ctx.beginPath();
ctx.lineWidth = "2";
ctx.strokeStyle = "grey";
ctx.rect(5, 5, 400, 400);
ctx.stroke();
// blue rectangle
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "blue";
ctx.rect(x, y, 100, 100);
ctx.stroke();
ctx.fillStyle = "blue";
ctx.fill();
}
// repeat game loop function forever, 30 times per second
window.setInterval(draw, 1000.0 / 30.0)
Notice the use of window.setInterval and ctx.clearRect.

Every time you want to update what is shown on the canvas, you have to 'Draw' again. Your code will run once when the page loads but never draws again so your changes to x and y are never seen.
I added a draw function here that is called on startup and after each keydown.
<!DOCTYPE html>
<html lang = "en">
<body style="background-color:lightgrey;">
<title>2048</title>
<canvas id="myCanvas" width="410" height="410" style="border:1px solid #d3d3d3;">
</canvas>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var x = 10;
var y = 10;
document.addEventListener('keydown', function(event)
{
if(event.keyCode == 37)//left
{
x -= 100;
console.log("x:"+ x);
}
else if(event.keyCode == 38)//up
{
y -= 100;
console.log("y:"+ y);
}
else if(event.keyCode == 39)//right
{
x += 100;
console.log("x:"+ x);
}
else if(event.keyCode == 40)//down
{
y += 100;
console.log("y:"+ y);
}
draw();
});
function draw(){
ctx.clearRect(0, 0, c.width, c.height);
// grey rectangle
ctx.beginPath();
ctx.lineWidth = "2";
ctx.strokeStyle = "grey";
ctx.rect(5, 5, 400, 400);
ctx.stroke();
// blue rectangle
ctx.beginPath();
ctx.lineWidth = "5";
ctx.strokeStyle = "blue";
ctx.rect(x, y, 100, 100);
ctx.stroke();
ctx.fillStyle = "blue";
ctx.fill();
}
draw();
</script>
</body>
</html>

Related

set grid made by js on the background of canvas

I try to make paint app in javascript. I need to make square grid and by pushing button. I made such grid but it is not on the background. How should I pass grid made by js on the background?
function print_grid()
{
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillRect(0, 0, 5100, 5100);
ctx.clearRect(0, 0, 5100, 5100);
ctx.beginPath();
for (let i = 0; i < 39; i++)
{
ctx.lineWidth = 1;
ctx.moveTo(50*i, 0);
ctx.lineTo(50*i, 5100);
ctx.moveTo(0, 50*i);
ctx.lineTo(5100, 50*i);
}
ctx.stroke();
}
<!DOCTYPE html>
<html>
<body>
<h1>Board</h1>
<button onclick="print_grid()">square</button>
<p >draw!!!</p>
<canvas id="myCanvas" width="1000" height="1000" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
</body>
</html>
One easy solution is using two canvases layered on top of each other. This way you can draw the grid onto the background layer independent from the canvas in the foreground.
Here's an example:
const canvas = document.getElementById('canvas2');
const ctx = canvas.getContext('2d');
let coordinates = {
x: 0,
y: 0
};
let painting = false;
function getPosition(event) {
coordinates.x = event.clientX - canvas.offsetLeft;
coordinates.y = event.clientY - canvas.offsetTop;
}
function startPainting(event) {
painting = true;
getPosition(event);
}
function stopPainting() {
painting = false;
}
function draw(event) {
if (!painting) return;
ctx.beginPath();
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.strokeStyle = 'red';
ctx.moveTo(coordinates.x, coordinates.y);
getPosition(event);
ctx.lineTo(coordinates.x, coordinates.y);
ctx.stroke();
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
function printGrid() {
let backgroundCanvas = document.getElementById('canvas');
let context = backgroundCanvas.getContext("2d");
context.beginPath();
for (let a = 0; a < 10; a++) {
context.moveTo(0, parseInt(a * (backgroundCanvas.height / 9)));
context.lineTo(backgroundCanvas.width, parseInt(a * (backgroundCanvas.height / 9)));
context.moveTo(parseInt(a * (backgroundCanvas.width / 9)), 0);
context.lineTo(parseInt(a * (backgroundCanvas.width / 9)), backgroundCanvas.height);
}
context.stroke();
context.closePath();
}
printGrid();
document.addEventListener('mousedown', startPainting);
document.addEventListener('mouseup', stopPainting);
document.addEventListener('mousemove', draw);
<button onclick='clearCanvas();'>Clear</button>
<div>
<canvas id='canvas' style='position: absolute'></canvas>
<canvas id='canvas2' style='position: absolute'></canvas>
</div>

Cube gets a little bigger when i draw it again. (Canvas, Javascript)

//Selectors
canvas = document.querySelector('.canvas');
canvas.setAttribute("tabindex", 0);
canvas.focus();
pointerImg = document.querySelector('.pointer');
//Variables
const pi = Math.PI;
const c = canvas.getContext('2d');
var grid = {
'x':60,
'y':20,
'size':20,
}
var pointerValues = {
37: {'x':-1, 'y':0},
38: {'x':0, 'y':-1},
39: {'x':1, 'y':0},
40: {'x':0, 'y':1},
}
//Event Listeners
window.addEventListener('resize', function() {
//init();
})
var cells = [];
for(let i=0;i<grid.x;i++) {
cells[i] = new Array(grid.y);
}
//Functions
function init() {
resizeGrid();
initCells();
}
init();
function update(){
requestAnimationFrame(update)
}
update();
function Cell(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.color = 'white';
this.update = function() {
this.draw();
}
this.draw = function() {
c.beginPath();
c.rect(this.x*this.size, this.y*this.size, this.size, this.size);
c.strokeStyle = 'black';
c.stroke();
c.fillStyle=this.color; c.fill();
c.closePath();
}
this.resetCell = function() {
c.clearRect(this.x, this.y, this.size, this.size);
this.update();
}
}
function resizeGrid() {
let windowX = window.innerWidth;
windowX -= windowX*0.1;
grid.size = windowX/grid.x;
let canvasX = windowX, canvasY = grid.y * grid.size;
canvas.width = canvasX;
canvas.height = canvasY;
}
function initCells() {
cells = [];
for(let i=0;i<grid.x;i++) {
cells[i] = new Array(grid.y);
}
for(let i=0;i<grid.x;i++) {
for(let j=0;j<grid.y;j++) {
cells[i][j] = new Cell(i, j, grid.size);
cells[i][j].update();
}
}
}
<html>
<head>
<link rel="stylesheet" href="assets/css/main.css">
<div style="display:none;">
<img class='pointer' src="assets/img/pointer.svg">
</div>
<div class='nav'>
</div>
</head>
<body>
<div class="content">
<canvas class='canvas'></canvas>
</div>
<script src='assets/js/canvas.js'></script>
</body>
</html>
function Cell(x, y, size) {
this.x = x;
this.y = y;
this.size = size;
this.color = 'white';
this.update = function () {
this.draw();
}
this.draw = function () {
c.beginPath();
c.rect(this.x * this.size, this.y * this.size, this.size, this.size);
c.strokeStyle = 'black';
c.stroke();
c.fillStyle = this.color;
c.fill();
c.closePath();
}
this.resetCell = function () {
c.clearRect(this.x, this.y, this.size, this.size);
this.update();
}
This is my code for a single cell in a grid. After I draw it a single time, when I call resetCell(), it draws the cell just a little bit bigger.
In this picture, I call Update for the very first cell and it becomes a tiny bit bigger than the rest.
I've tried pretty much everything but nothing seems to work.
Also can someone recommend better way to draw and control grid.
I need it to demonstrate BFS algorithm.
You were tricked by the thickness of the border
The border has a thickness, which is easy to forget. If you draw a box which is X wide, its left and right border are in addition to the width of X.
So if you do NOT fill the interior, you get this nice appearance (left), but if you FILL, you get this ugly appearance (right).
When you draw a grid of these squares, each one covers over the right-hand and bottom sides of previous squares, so that it is not obvious what is happening.
Unless you redraw one that is not the last of the list, as I have done here (bottom-middle). Then it becomes obvious that something is wrong.
Here is the code to reproduce the above figures, and below I recommend a solution.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
// With NO fill, it looks fine
ctx.beginPath();
ctx.rect(40, 40, 40, 40);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.rect(80, 80, 40, 40);
ctx.stroke();
ctx.closePath();
// With white fill, the inner half of each box gets covered up by the white fill.
ctx.beginPath();
ctx.rect(140, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(180, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
// Make Grid. This part looks OK initially.
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.rect(240, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(240, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(280, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(280, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(320, 40, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
ctx.beginPath();
ctx.rect(320, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
// Redraw one: this will look messed up.
ctx.beginPath();
ctx.rect(280, 80, 40, 40);
ctx.stroke();
ctx.fillStyle="white";
ctx.fill();
ctx.closePath();
<!DOCTYPE html>
<html>
<body>
<canvas id="myCanvas" width="400" height="150" ></canvas>
</body>
</html>
Solution 1. Don't fill the interiors
This is the neatest solution, if you can get away with it, and it works regardless of any (non-zero) border thickness.
Solution 2. Shrink the width to allow for border thickness
This is complicated because you need to manually set the border thickness, and realise that it is in addition to the numerical values you specify for the rectangle's size.
Look at this messy business at CSS-tricks, even when they are trying to make borders interesting! https://css-tricks.com/almanac/properties/b/border/

javascript my arc is not showing up or moving across the screen

hello i am trying to make a white circle move across a black box in javascript my circle is not showing up the big black box does but the circle does not show up i dont know why i am loading the page in google chrome here is the code
<html>
<head>
<title>paddle</title>
</head>
<body>
<canvas id="myCanvas" width="800" height="600"></canvas>
<script>
var canvas
var canvasContext
var ballX = 5
window.onload = function() {
var fps = 30;
setInterval(updateAll, 1000)
canvas = document.getElementById("myCanvas");
canvasContext = canvas.getContext("2d")
canvasContext.fillStyle = "black"
canvasContext.fillRect(0, 0, canvas.width, canvas.height)
}
function updateAll() {
ballX++
canvasContext.fillStyle = "white";
canvasContext.beginPath()
canvasContext.arc(ballX, 100, 10, 0, Math.PI*2, true);
canvasContext.stroke()
}
</script>
</body>
</html>
The problem is that you are using stroke to draw the circle but you have not set the stroke style which is by default black. So you are drawing a black circle on a black background. Hence no see circle.
Also it is best to use requestAnimationFrame to animate rather than set interval.
Example animating a circle
requestAnimationFrame(animationLoop);
const ctx = myCanvas.getContext("2d");
var ballX = 5;
var speed = 1
const radius = 10;
const fps = 30;
var frameCount = 0;
function animationLoop() {
if (frameCount % (60 / fps) === 0) {
ctx.fillStyle = "black"
ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
draw();
}
frameCount ++;
requestAnimationFrame(animationLoop);
}
function draw() {
ballX = (ballX + speed) % (ctx.canvas.width + radius * 2);
ctx.strokeStyle = "white";
ctx.lineWidth = 2;
ctx.beginPath()
ctx.arc(ballX - radius, 20, 10, 0, Math.PI * 2);
ctx.stroke()
}
<canvas id="myCanvas" width="600" height="40"></canvas>

Javascript - Why isn't my while loop executing? (Pong)

Amateur here :) Sorry if this seems like a dumb question, but why isn't my while loop executing? It should draw a pink rectangle with two black rectangle for paddles. P.S. Yes, I know that i<10 doesn't make sense, but it is a placeholder for later and shouldn't impact the running of the code. Anyways, here's my code-
//set up the javascript canvas
var c = document.getElementById("canvas");
var ctx = c.getContext("2d");
var i = 1;
//Game loop
while (i < 10) {
//register pressed keys
//var x = event.key;
if (window.event) {
var keynum = event.keyCode;
} else if (event.which) {
var keynum = event.which;
}
//draw the pink background
ctx.beginPath();
ctx.rect(0, 0, 315, 100);
ctx.fillStyle = "#FFC0CB";
ctx.fill();
ctx.closePath();
//Draw the player's paddle
ctx.beginPath();
var playerY = 35;
ctx.rect(15, playerY, 10, 25);
ctx.fillStyle = "#000000";
ctx.fill();
ctx.closePath();
//Draw the bot's paddle
ctx.beginPath();
var botY = 35;
ctx.rect(280, botY, 10, 25);
ctx.fill();
ctx.closePath();
i++;
}

How can I stop filling my circle at some point?

How can I stop filling my circle at some point?
Like only fill 50% of the circle or 25% of the circle and leave the left over. Just like progress bar.
below is the code Im using but it is filling entire circle.
Kindly please give me suggestions.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
ctx.lineCap = "round";
var y = ch - 10;
var drawingColor = "#0092f9";
animate();
function animate() {
if (y > 0) {
requestAnimationFrame(animate);
}
ctx.clearRect(0, 0, cw, ch);
ctx.save();
drawContainer(0, null, null);
drawContainer(15, drawingColor, null);
drawContainer(7, "white", "white");
ctx.save();
ctx.clip();
drawLiquid();
ctx.restore();
ctx.restore();
y--;
}
function drawLiquid() {
ctx.beginPath();
ctx.moveTo(0, y);
for (var x = 0; x < 300; x += 1) {
ctx.quadraticCurveTo(x + 5, y+5, x + 5, y);
}
ctx.lineTo(cw, ch);
ctx.lineTo(0, ch);
ctx.closePath();
ctx.fillStyle = drawingColor;
ctx.fill();
}
function drawContainer(linewidth, strokestyle, fillstyle) {
ctx.beginPath();
ctx.arc(cw/2, ch/2,cw/2-30,0,2*Math.PI);
ctx.lineWidth = linewidth;
ctx.strokeStyle = strokestyle;
ctx.stroke();
if (fillstyle) {
ctx.fillStyle = fillstyle;
ctx.fill();
}
}
<canvas id="canvas" width=200 height=200></canvas>
I know zit at javascript but: Just change the limit of y in animate. I put 100 instead of 0 and it fills half the circle.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
ctx.lineCap = "round";
var y = ch - 10;
var drawingColor = "#0092f9";
animate();
function animate() {
if (y > 100) {
requestAnimationFrame(animate);
}
ctx.clearRect(0, 0, cw, ch);
ctx.save();
drawContainer(0, null, null);
drawContainer(15, drawingColor, null);
drawContainer(7, "white", "white");
ctx.save();
ctx.clip();
drawLiquid();
ctx.restore();
ctx.restore();
y--;
}
function drawLiquid() {
ctx.beginPath();
ctx.moveTo(0, y);
for (var x = 0; x < 300; x += 1) {
ctx.quadraticCurveTo(x + 5, y+5, x + 5, y);
}
ctx.lineTo(cw, ch);
ctx.lineTo(0, ch);
ctx.closePath();
ctx.fillStyle = drawingColor;
ctx.fill();
}
function drawContainer(linewidth, strokestyle, fillstyle) {
ctx.beginPath();
ctx.arc(cw/2, ch/2,cw/2-30,0,2*Math.PI);
ctx.lineWidth = linewidth;
ctx.strokeStyle = strokestyle;
ctx.stroke();
if (fillstyle) {
ctx.fillStyle = fillstyle;
ctx.fill();
}
}
<canvas id="canvas" width=200 height=200></canvas>

Categories