Creating/Drawing multiple images on canvas html5 - javascript

I was wondering what I was doing wrong because I'm making a memory game but the images wouldn't draw on my canvas.
var ctx;
var cardBacks = "Resources/monster.png"; //shows back of card when turned over
var faces = [];
var tiles = [];
var Tile;
var columns = 5;
var rows = 4;
function createTile(x,y){
this.x = x;
this.y = y;
this.width = 70;
ctx.drawImage(cardBacks, this.x, this.y, this.width, this.width);
}
function initialize(){
ctx = document.getElementById("myCanvas").getContext("2d");
for (var i = 0; i < columns; i++) {
for (var j = 0; j < rows; j++) {
tiles.push(createTile(i * 78 + 10, j * 78 + 40));
}
}
}

Try this code with onload callback function.
var ctx;
var cardBacks = new Image();
cardBacks.src = "Resources/monster.png"; //shows back of card when turned over
cardBacks.onload = function() {
ctx.drawImage(cardBacks, this.x, this.y, this.width, this.width);
}
var faces = [];
var tiles = [];
var Tile;
var columns = 5;
var rows = 4;
function createTile(x, y) {
this.x = x;
this.y = y;
this.width = 70;
}
function initialize() {
ctx = document.getElementById("myCanvas").getContext("2d");
for (var i = 0; i < columns; i++) {
for (var j = 0; j < rows; j++) {
tiles.push(createTile(i * 78 + 10, j * 78 + 40));
}
}
}

You need to draw an HTML image element onto the canvas, not a url. I think you could do
var cardBacks = new Image();
cardBacks.src = "Resources/monster.png";
Here's an example: https://jsfiddle.net/yarhqskx/
Here's with multiple (added onload): https://jsfiddle.net/yarhqskx/7/

Related

Algorithm for adding black bars to an image

I am trying to write a function that adds black bars to an image such as in the example below:
before and after
I have the following code. I believe the algorithm is correct, however, it only works for certain images and certain values. For example, it does work when the "cuts" variable is equal to 7 and the resolution of the uploaded image is 1920x1080, however it doesn't for any other values other than 7, 1 or 2. Why?
Also, if you think of a better algorithm please share it with me.
rectangleButton.addEventListener("click", () => {
if(loadCounter === 4) {
var cuts = parseInt(text.value);
text.value = null;
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var divisions = (2*cuts)+1;
var lines = canvas.height;
var columns = canvas.width;
console.log(canvas.height);
console.log(canvas.width);
console.log(divisions);
var k = 1;
var scannedRectangleImage = ctx.getImageData(0, 0, canvas.width, canvas.height);
var scannedRectangleImageData = scannedRectangleImage.data;
for(k = 1; k < 2*cuts; k = k+2) {
for(var i = k*lines/divisions; i < (k+1)*lines/divisions; i++)
{
for(var j = 0; j < columns; j++)
{
scannedRectangleImageData[i*4*columns+4*j] = 0;
scannedRectangleImageData[i*4*columns+4*j+1] = 0;
scannedRectangleImageData[i*4*columns+4*j+2] = 0;
}
}
console.log(k + " < " + 2*cuts);
}
scannedRectangleImage.data = scannedRectangleImageData;
ctx.putImageData(scannedRectangleImage, 0, 0); }
else
{
alert("Image upload is not ready");
}
})
This is how I would do it
function drawImage(image) {
const canvas = document.getElementById('canvas');
canvas.setAttribute('width', image.width);
canvas.setAttribute('height', image.height);
const ctx = canvas.getContext('2d');
ctx.drawImage(image, 0, 0);
const stripeCount = document.getElementById('stripeCount').value;
const sectionCount = 2 * stripeCount + 1;
const stripeHeight = Math.ceil(image.height / sectionCount);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
for (let i = 0; i < stripeCount; i++) {
drawStripe(2 * i + 1, stripeHeight, imageData.data, canvas.width);
}
ctx.putImageData(imageData, 0, 0);
}
function drawStripe(stripeIdx, stripeHeight, imageData, imageWidth) {
const lineStart = stripeIdx * stripeHeight;
const dataStart = lineStart * imageWidth * 4;
const dataLength = stripeHeight * imageWidth * 4;
for (let idx = dataStart, l = dataStart + dataLength; idx < l; idx += 4) {
imageData[idx] = 0;
imageData[idx + 1] = 0;
imageData[idx + 2] = 0;
}
}

How to generate continues Colorful Artistic Perlin Flow Field

I am trying to achieve effect as shown in the picture below:
Im using p5.js library but im not a graphics programmer and thats why its very difficult to achieve this particular graphical effect. I am sharing my code with you and also I followed this tutorial.
Index.html
<html>
<head>
<script language="javascript" type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.min.js"></script>
<script language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.dom.min.js"></script>
<script language="javascript" src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/addons/p5.sound.min.js"></script>
<script language="javascript" type="text/javascript" src="sketch.js"></script>
<script language="javascript" type="text/javascript" src="particle.js"></script>
</head>
<body>
</body>
</html>
particle.js
function Particle() {
this.pos = createVector(random(width), random(height));
this.vel = createVector(0, 0);
this.acc = createVector(0, 0);
this.maxspeed = 4;
this.h = 0;
this.alphaPower = 20;
this.prevPos = this.pos.copy();
this.update = function() {
this.vel.add(this.acc);
this.vel.limit(this.maxspeed);
this.pos.add(this.vel);
this.acc.mult(0);
}
this.follow = function(vectors) {
var x = floor(this.pos.x / scl);
var y = floor(this.pos.y / scl);
var index = x + y * cols;
var force = vectors[index];
this.applyForce(force);
}
this.applyForce = function(force) {
this.acc.add(force);
}
this.showBlue = function() {
stroke(0, 76, 153, this.alphaPower);
strokeWeight(1);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.showMaroon = function() {
stroke(165, 0, 68, this.alphaPower); // maroon
strokeWeight(1);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.showYellow = function() {
stroke(237, 188, 0, this.alphaPower);
//stroke(1,2);
strokeWeight(1);
line(this.pos.x, this.pos.y, this.prevPos.x, this.prevPos.y);
this.updatePrev();
}
this.updatePrev = function() {
this.prevPos.x = this.pos.x;
this.prevPos.y = this.pos.y;
}
this.edges = function() {
if (this.pos.x > width) {
this.pos.x = 0;
this.updatePrev();
}
if (this.pos.x < 0) {
this.pos.x = width;
this.updatePrev();
}
if (this.pos.y > height) {
this.pos.y = 0;
this.updatePrev();
}
if (this.pos.y < 0) {
this.pos.y = height;
this.updatePrev();
}
}
}
sketch.js
var inc = 0.01;
var scl = 10;
var cols, rows;
var zoff = 0;
var fr;
var particles = [];
var particlesMaroon = [];
var particlesBlue = [];
var particlesYellow = [];
var flowfield;
var flowfieldMaroon;
var flowfieldBlue;
var flowfieldYellow;
var gamma_is_high = false;
var beta_is_high = false;
var alpha_is_high = false;
var maroon_data=1000;
var blue_data = 1000;
var yellow_data = 1000;
setInterval(function() {
ChangeLines();
}, 5000);
function dataRequest(){
socket.emit('datarequest', {data: "request"});
}
function ChangeLines(){
maroon_data = random(500, 2000);
blue_data = random(500, 2000);
yellow_data = random(500, 2000);
gamma_is_high = true;
alpha_is_high = true;
beta_is_high = true;
}
function setup() {
slider = createSlider(0.01, 0.1, 0.02,0);
slider.position(10, 10);
slider.style('width', '80px');
ChangeLines();
createCanvas(windowWidth-15, windowHeight-20);
cols = floor(width / scl);
rows = floor(height / scl);
fr = createP('');
flowfield = new Array(cols * rows);
flowfieldMaroon = new Array(cols * rows);
flowfieldBlue = new Array(cols * rows);
flowfieldYellow = new Array(cols * rows);
for (var i = 0; i < 1000; i++) {
particles[i] = new Particle();
particlesMaroon[i] = new Particle();
particlesBlue[i] = new Particle();
particlesYellow[i] = new Particle();
}
background(255);
}
function draw() {
let val = slider.value();
inc = val;
var yoff = 0;
for (var y = 0; y < rows; y++) {
var xoff = 0;
for (var x = 0; x < cols; x++) {
var index = x + y * cols;
var angle = noise(xoff, yoff, zoff) * TWO_PI;
var angleMaroon = noise(xoff, yoff, zoff) * TWO_PI;
var angleBlue = noise(xoff, yoff, zoff) * TWO_PI;
var angleYellow = noise(xoff, yoff, zoff) * TWO_PI;
var v = p5.Vector.fromAngle(angle);
var vm = p5.Vector.fromAngle(angleMaroon);
var vb = p5.Vector.fromAngle(angleBlue);
var vy = p5.Vector.fromAngle(angleYellow);
v.setMag(5);
vm.setMag(5);
vb.setMag(5);
vy.setMag(5);
flowfield[index] = v;
flowfieldMaroon[index] = vm;
flowfieldBlue[index] = vb;
flowfieldYellow[index] = vy;
xoff += inc;
}
yoff += inc;
}
zoff += 0.0003;
for (var i = 0; i < particles.length; i++) {
if(gamma_is_high==true){
particlesMaroon[i].follow(flowfieldMaroon);
particlesMaroon[i].update();
particlesMaroon[i].edges();
particlesMaroon[i].showMaroon();
}
if(beta_is_high){
particlesBlue[i].follow(flowfieldBlue);
particlesBlue[i].update();
particlesBlue[i].edges();
particlesBlue[i].showBlue();
}
if(alpha_is_high){
particlesYellow[i].follow(flowfieldYellow);
particlesYellow[i].update();
particlesYellow[i].edges();
particlesYellow[i].showYellow();
}
}
fr.html(floor(frameRate()));
}
The variables maroon_data, blue_dataand yellow_data are data coming from EEG device which will be calculated later but for now its hard coded values for prototype only. Also booleans gamma_is_high, beta_is_high and alpha_is_high are set to true for now. But with this much effort I only manage to achieve this as shown below:
And the actual output is like this:
Kindly help me get this actual output. Any help would be appreciated. Thanks.
Ive sorta done this before. I only had one array of particles and just changed their rgb values by a small random amount. I used an object to store the colour values.
function setup() {
//Do all the normal stuff
var c = {r: 100, g:100, b:100)
}
function draw() {
//All the other stuff
c.r += random(-3,3);
c.g += random(-3,3);
c.b += random(-3,3);
}
And then in the particle:
show() {
fill(c.r,c.g,c.b, whateverAlphaYouWant);
//Do all the rest
}
You can always tweak the values to get whatever colour you want.

How to draw multiple array entities on canvas

I want to draw out all of the objects that I have in my zombielist. but I can't get it to work.
var FatZombieWikki = new Image();
FatZombieWikki.src = "FatZombieWikki.png";
var Zombie = function(x, y) {
this.x = x;
this.y = y;
this.Draw = function(ctx) {
ctx.drawImage(FatZombieWikki,200,ZombieY,50,50);
}
this.Update = function(){
if(ZombieY < 900) {
ZombieY += 0.5;
}
}
}
var z = new Zombie(100, 200,);
var zombieList = [];
for (var i = 0; i < 10; i++) {
zombieList.push(new Zombie(40 * i, 100));
}
call your draw function inside loop, after creating object.
DEMO
var ctx = document.getElementById('c').getContext('2d');
var FatZombieWikki = new Image();
FatZombieWikki.src = "//i.stack.imgur.com/ubK40.jpg";
FatZombieWikki.onload = function(){
var zombieList = [];
for (var i = 0; i < 10; i++) {
zombieList.push(new Zombie(40 * i, 30*i));
zombieList[i].draw(ctx);
}
}
var Zombie = function(x, y) {
this.x = x;
this.y = y;
this.draw = function(ctx) {
ctx.drawImage(FatZombieWikki,this.x,this.y,50,50);
}
}
canvas{
border:2px solid #000
}
<canvas id='c' width=500 height=400></canvas>
zombieList.forEach(zombie => zombie.Draw(ctx))

Canvas rotation - fixed background, moving foreground

Goal
The stripes in the background remain fixed while the cones rotate about the center.
Current State
live demo:
https://codepen.io/WallyNally/pen/yamGYB
/*
The loop function is around line 79.
Uncomment it to start the animation.
*/
var c = document.getElementById('canv');
var ctx = c.getContext('2d');
var W = c.width = window.innerWidth;
var H = c.height = window.innerHeight;
var Line = function() {
this.ctx = ctx;
this.startX = 0;
this.startY = 0;
this.endX = 0;
this.endY = 0;
this.direction = 0;
this.color = 'blue';
this.draw = function() {
this.ctx.beginPath();
this.ctx.lineWidth = .1;
this.ctx.strokeStlye = this.color;
this.ctx.moveTo(this.startX, this.startY);
this.ctx.lineTo(this.endX, this.endY);
this.ctx.closePath();
this.ctx.stroke();
}
this.update = function() {
//for fun
if (this.direction == 1) {
this.ctx.translate(W/2, H/2);
this.ctx.rotate(-Math.PI/(180));
}
}//this.update()
}//Line();
objects=[];
function initLines() {
for (var i =0; i < 200; i++) {
var line = new Line();
line.direction = (i % 2);
if (line.direction == 0) {
line.startX = 0;
line.startY = -H + i * H/100;
line.endX = W + line.startX;
line.endY = H + line.startY;
}
if (line.direction == 1) {
line.startX = 0;
line.startY = H - i * H/100;
line.endX = W - line.startX;
line.endY = H - line.startY;
}
objects.push(line);
line.draw();
}
}
initLines();
function render(c) {
c.clearRect(0, 0, W, H);
for (var i = 0; i < objects.length; i++)
{
objects[i].update();
objects[i].draw();
}
}
function loop() {
render(ctx);
window.requestAnimationFrame(loop);
}
//loop();
What I have tried
The translate(W/2, H/2) should place the context at the center of the page, then this.ctx.rotate(-Math.PI/(180)) should rotate it one degree at a time. This is the part that is not working.
Using save()and restore() is the proper way to keep some parts of an animation static while others move. I placed the save and restore in different parts of the code to no avail. There are one of two types of result : Either a new entirely static image is produced, or some erratic animation happens (in the same vein of where it is now).
Here is the changed pen: http://codepen.io/samcarlinone/pen/LRwqNg
You needed a couple of changes:
var c = document.getElementById('canv');
var ctx = c.getContext('2d');
var W = c.width = window.innerWidth;
var H = c.height = window.innerHeight;
var angle = 0;
var Line = function() {
this.ctx = ctx;
this.startX = 0;
this.startY = 0;
this.endX = 0;
this.endY = 0;
this.direction = 0;
this.color = 'blue';
this.draw = function() {
this.ctx.beginPath();
this.ctx.lineWidth = .1;
this.ctx.strokeStlye = this.color;
this.ctx.moveTo(this.startX, this.startY);
this.ctx.lineTo(this.endX, this.endY);
this.ctx.closePath();
this.ctx.stroke();
}
this.update = function() {
//for fun
if (this.direction == 1) {
this.ctx.translate(W/2, H/2);
this.ctx.rotate(angle);
this.ctx.translate(-W/2, -H/2);
}
}//this.update()
}//Line();
objects=[];
function initLines() {
for (var i =0; i < 200; i++) {
var line = new Line();
line.direction = (i % 2);
if (line.direction == 0) {
line.startX = 0;
line.startY = -H + i * H/100;
line.endX = W + line.startX;
line.endY = H + line.startY;
}
if (line.direction == 1) {
line.startX = 0;
line.startY = H - i * H/100;
line.endX = W - line.startX;
line.endY = H - line.startY;
}
objects.push(line);
line.draw();
}
}
initLines();
function render(c) {
c.clearRect(0, 0, W, H);
for (var i = 0; i < objects.length; i++)
{
ctx.save();
objects[i].update();
objects[i].draw();
ctx.restore();
}
}
function loop() {
render(ctx);
window.requestAnimationFrame(loop);
angle += Math.PI/360;
}
loop();
First I added a variable to keep track of rotation and increment it in the loop
Second I save and restore for each individual line, alternatively if all lines were going to perform the same transformation you could move that code before and after the drawing loop
Third to get the desired affect I translate so the center point is in the middle of the screen, then I rotate so that the lines are rotated, then I translate back because all the lines have coordinates on the interval [0, H]. Instead of translating back before drawing another option would be to use coordinates on the interval [-(H/2), (H/2)] etc.

Javascript canvas draw rect not working, trying to make a game board

So I made a program that is supposed to make an empty 2d game board using stroke rect or draw img. Here it is (using stroke rect):
window.onload = function() {
//set up the canvas items
var canvas = document.getElementById("paper");
var emptySquare = canvas.getContext("2d");
var player = canvas.getContext("2d");
var background = canvas.getContext("2d");
//An empty game board, with basic stats
var boardArray = [];
var rowNum = 7;
var colNum = 7;
//Makes the board with the empty squares
for (i = 0; i < colNum; i++) {
for (x = 0; x < rowNum; x++) {
boardArray.push([colNum*10, rowNum*10]);
}
}
//This is the png of an empty board part of an array
var emptySquareImg = new Image();
emptySquareImg.src = "border.png";
function displayBoard() {
background.fillStyle = "rgb(0, 0, 0)";
background.fillRect(0, 0, canvas.width, canvas.height);
for (x = 0; x < boardArray.length; x++) {
for (y = 0; y < x.length; y++) {
emptySquare.beginPath();
emptySquare.lineWidth = "4";
emptySquare.strokeStyle = "rgb(200, 34, 22)";
emptySquare.rect(boardArray[x], boardArray[y], 10, 10)
emptySquare.stroke();
}
}
}
displayBoard();
}
It does not display anything except the black background. It also throws no errors, which is sort of weird. Thank you for any help, and I can soon make my little board game!
There are a few issues with your loops and generation of the array of squares. Remember to use the var keyword when setting up for-loops in javascript. Otherwise the variable will not be in the local scope and you probably won't get what you expect. Especially with x in your case since it's used in two loops.
http://jsfiddle.net/mfohao5x/
window.onload = function() {
var canvas = document.getElementById("paper");
var emptySquare = canvas.getContext("2d");
var player = canvas.getContext("2d");
var background = canvas.getContext("2d");
var boardArray = [];
var rowNum = 7;
var colNum = 7;
// probably worth defining the width and height of cells here
var width = 10;
var height = 10;
// remember to include the keyword "var"
for (var i = 0; i < rowNum; i++) {
// add a new row to boardArray
boardArray.push([]);
for (var x = 0; x < colNum; x++) {
// add your values for this square within this row
boardArray[i].push([i*width, x*height]);
}
}
//console.log(boardArray);
var emptySquareImg = new Image();
emptySquareImg.src = "border.png";
function displayBoard() {
background.fillStyle = "rgb(0, 0, 0)";
background.fillRect(0, 0, canvas.width, canvas.height);
for (var x = 0; x < boardArray.length; x++) {
// get the row here and then iterate through it
var row = boardArray[x];
for (var y = 0; y < row.length; y++) {
// now row[y] will give you your square
emptySquare.beginPath();
emptySquare.lineWidth = "4";
emptySquare.strokeStyle = "rgb(200, 34, 22)";
// use row[y][0] and row[y][1] to position the rect
emptySquare.rect(row[y][0], row[y][1], width, height);
emptySquare.stroke();
}
}
}
displayBoard();
}
Here's your code with adjusted loops. boardArray.push([colNum*10, rowNum*10]); is changed to boardArray.push([i*10, x*10]);. boardArray[x], boardArray[y] is changed to arr[0], arr[1].
window.onload = function() {
//set up the canvas items
var canvas = document.getElementById("paper");
var emptySquare = canvas.getContext("2d");
var player = canvas.getContext("2d");
var background = canvas.getContext("2d");
//An empty game board, with basic stats
var boardArray = [];
var rowNum = 7;
var colNum = 7;
//Makes the board with the empty squares
for (i = 0; i < colNum; i++) {
for (x = 0; x < rowNum; x++) {
boardArray.push([i*10, x*10]);
}
}
//This is the png of an empty board part of an array
var emptySquareImg = new Image();
emptySquareImg.src = "border.png";
function displayBoard() {
background.fillStyle = "rgb(0, 0, 0)";
background.fillRect(0, 0, canvas.width, canvas.height);
for (x = 0; x < colNum; x++) {
for (y = 0; y < rowNum; y++) {
emptySquare.beginPath();
emptySquare.lineWidth = "4";
emptySquare.strokeStyle = "rgb(200, 34, 22)";
var arr = boardArray[y+x*colNum];
emptySquare.rect(arr[0], arr[1], 10, 10)
emptySquare.stroke();
}
}
}
displayBoard();
}
<canvas id='paper'></canvas>

Categories

Resources