I am making a game engine called Forge.js. I have a Polygon method in a Entity class and it is not drawing the shapes. It loops through points and draws a line to each of the points. The lines however aren't being drawn. help plz
polygon method:
_polygon(points){
const local_ctx = new Path2D()
this.ctx.beginPath()
var j = 3
local_ctx.moveTo(points[0], points[1])
for (var i=0; i<=points.length; i++){
local_ctx.lineTo(points[i+2], points[i+j])
j += 2
}
this.ctx.fillStyle = constants.COLORS.black
this.ctx.fill()
}
As has been said in the comments, you need to pass the Path2D object to fill() in order for the context to draw it.
But this isn't the only issue with your code.
Your for loop probably doesn't do what you expected:
// Rewrote in order to log the indexes that are beign used in the loop
var j = 3
console.log(0, 1)
for (var i=0; i<=10; i++){
console.log(i+2, i+j)
j += 2
}
You can actually simplify this loop a lot by taking advantage of the fact that an empty subpath doesn't require an initial moveTo call. lineTo(x, y) gets automatically converted to moveTo(x, y) if your path is empty.
So we can treat all our points the same, all in a single for loop that only increments our index by 2.
const constants = { COLORS: { BLACK: "#000" } };
const obj = {
ctx: document.createElement("canvas").getContext("2d"),
_polygon(points){
const local_ctx = new Path2D()
// Since we're using a Path2D object we don't need to do anything
// on the context's subpath
// this.ctx.beginPath()
for (var i=0; i<=points.length; i+=2){
local_ctx.lineTo(points[i], points[i+1])
}
this.ctx.fillStyle = constants.COLORS.black
this.ctx.fill(local_ctx) // fill the context using the Path2D object
}
};
document.body.append(obj.ctx.canvas);
obj._polygon([13, 13, 13, 50, 50, 50]);
I recently got into p5 from watching The Coding Train, and I wish to generate two-dimensional surfaces in 3D (like using WEBGL) given by a function of two variables.
If there is a function in Processing that does the job and I’m not just seeing it, then this is a Processing question. Otherwise, this could be a general question on graphing algorithms. I have no background in CS or algorithms.
My first goal is to render a surface z = x^2 + y^2 only for z <= 50.
Here is my initial attempt:
var angleSliderX;
var contour = [];
var cols = 10;
var rows = 10
var d = 10;
function f(x, y) {
return x**2 + y**2;
}
for (i=0; i<cols; i++) {
contour.push([]);
for (j=0; j<rows; j++) {
contour[i].push(f(i, j));
}
}
function setup() {
createCanvas(400, 400, WEBGL);
angleSliderX = createSlider(-PI/2, PI/2, PI/4, 0.01);
}
function draw() {
background(220);
rotateX(angleSliderX.value());
noFill();
for (j=0; j<rows-1; j++) {
for (i=0; i<cols-1; i++) {
if (contour[i][j] < 50) {
beginShape()
vertex(i*d, j*d, contour[i][j]);
vertex((i+1)*d, j*d, contour[i+1][j]);
vertex((i+1)*d, (j+1)*d, contour[i+1][j+1]);
vertex(i*d, (j+1)*d, contour[i][j+1]);
endShape(CLOSE);
}
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
I’m concerned that this creates jagged boundaries which I’m not so happy with. Are there known best practices to deal with such concerns without consuming too much computing power? Ideally, I wish to have a flat cut-out at z = 50 of the surface.
Thank you for your time!
So I'm currently working on a project that requires a grid/checkerboard. I've already made my grid in Javascript and I've also managed to center my grid.
The problem I'm having is that when I change my resolution with the device toolbar, the grid gets out of view. My goal is to make the whole grid visible no matter what phone or computer I use.
I would appreciate the help from you guys!
This is how I'm making my grid.
for (i = 0; i < row; i++) {
grid[i] = new Array(col);
}
//making a spot for every grid.
for (i = 0; i < row; i++) {
for (j = 0; j < col; j++) {
grid[i][j] = new Spot(i, j);
}
}
This is how I'm drawing the grid.
function Spot(i, j) {
this.x = i;
this.y = j;
this.show = function (color) {
fill(color);
rect(this.x * w, this.y * h, w - 1, h - 1);
}
}
w is the width of ONE single grid and h is the height of ONE single grid. col and row are the amount of rows and columns I want the grid to have.
I also call the function "this.show" every frame. The result looks like this:
The grid that is out of view
you need to check against the media type:
var l_strMobileMedia = '(max-width:320px)'
var mqList = window.matchMedia(l_strMobileMedia);
if(!mqList.matches){
l_strMobileMedia = '(max-width:481px)'
mqList = window.matchMedia(l_strMobileMedia);
}
if(!mqList.matches){
l_strMobileMedia = '(max-width:768px)'
mqList = window.matchMedia(l_strMobileMedia);
}
if(s_bIsMobile == null || s_bIsMobile != mqList.matches){
Session.set_mobile_layout(mqList.matches);
}
s_bIsMobile = mqList.matches;
return mqList.matches;
I hope this gets you started. If you want to do it in realtime, you need to hook to window resize event or set a timer that does the queries for you.
Question: How can I make putImageData() update the canvas in real time, as various parts of the image have been computed?
I am working on a JavaScript/TypeScript application to draw the Mandelbrot set on an HTML5 <canvas> element. Math and details aside, my application draws the set just fine. However, if you are familiar with visualizing the set, you know that it can take a long time to draw.
It will draw in a few seconds, but until then, the canvas is completely blank, then the image appears. I'm looking for a way to draw each row as it is computed using putImageData(). Here is what I am trying:
// part of the class definition
private Context: CanvasRenderingContext2D;
private ImageData: ImageData;
private Pixels: number[];
constructor() {
var c: HTMLCanvasElement = <HTMLCanvasElement>document.getElementById("can");
this.Context = c.getContext("2d");
this.ImageData = this.Context.createImageData(this.Size.Width, 1);
this.Pixels = this.ImageData.data;
}
public draw() {
// tried this... does not help
// var handler = function(m: Mandelbrot) {
// m.Context.putImageData(m.ImageData, 0, i)
// };
for(var i: number = 0; i < this.Size.Height; ++i) { // Loop over each row
for(var j: number = 0; j < this.Size.Width; ++j) { // Calc px. for one row
// all the math to compute the set... (works)
this.setPixelColor(j, color); // sets a color in this.Pixels (works)
}
// setTimeout(handler(this), 0); // does not help
this.Context.putImageData(this.ImageData, 0, i); // Draw the row on the canvas?
}
}
Somehow, the putImageData() function, which is called after a row in the image has been computed, only shows the image after the entire image has been generated.
How can I make putImageData() update the canvas in real time, as each row has been computed?
Latest update of non-working code:
var handler = function(m: Mandelbrot, i: number) {
for (var j: number = 0; j < m.Size.Width; ++j) {
// math
m.setPixelColor(j, color);
}
m.Context.putImageData(m.ImageData, 0, i);
};
var that: Mandelbrot = this;
for(var i: number = 0; i < this.Size.Height; ++i) {
setTimeout(function() {
handler(that, i)
}, 0);
}
Working code, thanks to ekuusela:
var handler = function(m: Mandelbrot, i: number) {
return function() {
for (var j: number = 0; j < m.Size.Width; ++j) {
// math
m.setPixelColor(j, color);
}
m.Context.putImageData(m.ImageData, 0, i);
}
};
for(var i: number = 0; i < this.Size.Height; ++i) {
setTimeout(handler(this, i), 0);
}
Try wrapping putImageData and the calculation for a single row to a setTimeout call to execute it asynchronously (post accept edit: see the final code in the question, this won't work since i will be undefined in the putImageData row)
public draw() {
var that = this;
var drawRow = function() {
for(var j: number = 0; j < that.Size.Width; ++j) { // Calc px. for one row
that.setPixelColor(j, color); // sets a color in this.Pixels (works)
}
// TODO specify the dirty region in this call
that.Context.putImageData(that.ImageData, 0, i); // Draw the row on the canvas?
};
for(var i: number = 0; i < this.Size.Height; ++i) { // Loop over each row
setTimeout(drawRow, 0);
}
}
I'm in the process of building an entity system for a canvas game. This started from a simple particle emitter/updater which I am altering to accommodate a multi-particle/entity generator. Whilst I am usually ok with JavaScript/jQuery I am running into the limits of my experience as it concerns arrays and would gratefully accept any help on the following:
When I need a new particle/entity my current system calls a function to push an object into an array which contains variables for the entity updates.
Then the update function runs a for loop over the array, checking on the type variable to update the particle (position/colour/etc...). Previously I would then [array.splice] the particle, based on some condition. When I needed further particles/entities I would then push new particles.
What I would like to achieve here is:
In the makeParticle function, check over the particle array for any "dead" particles and if any are available reuse them, or push a new particle if not I have created a particleAlive var as a flag for this purpose.
var particles = [];
var playing = false;
function mousePressed(event) {
playing = !playing;
}
if(playing) {
makeParticle(1, 200, 200, 10, "blueFlame");
makeParticle(1, 300, 200, 10, "redFlame");
}
function makeParticle(numParticles, xPos, yPos, pRadius, pType) {
var i;
for (i = 0; i < numParticles; i++) {
var p = {
type : pType,
x : xPos,
y : yPos,
xVel : random(-0.5, 0.5),
yVel : random(-1, -3),
particleAlive : true,
particleRender : true,
size : pRadius
}; // close var P
particles.push(p);
// instead of pushing fresh particles all the time I would like the function, here, to check for free objects in the array
} // close for loop
} // close function makeParticle
function runtime() {
for(var i=0; i<particles.length; i++) {
var p = particles[i];
var thisType = p.type;
switch (thisType) {
case "blueFlame":
c.fillStyle = rgb(100,100,255);
c.fillCircle(p.x,p.y,p.size);
p.x += p.xVel;
p.y += p.yVel;
p.size*=0.9;
if (particles.size < 0.5) {
particleAlive = false;
particleRender = false;
} // close if
break;
case "redFlame":
c.fillStyle = rgb(255,100,100);
c.fillCircle(p.x,p.y,p.size);
p.x -= p.xVel;
p.y -= p.yVel;
p.size*=0.95;
if (particles.size < 0.5) {
particleAlive = false;
particleRender = false;
} // close if
break;
} // close switch
} // close function runtime
I've found previous answers to relate questions, but I've been unable to get it working within the makeParticle function, like how to assign the attributes of p to particle[j]:
var particleUseOldOrNew = function() {
for (var j = 0, len = particles.length; j < len; j++) {
if (particles[j].particleAlive === false)
// particles[j] = p;
return particle[j];
}
return null; // No dead particles found, create new "particles.push(p);" perhaps?
}
My personal opinion on the matter is that if you are making a new particle, it should be a new object, not a "re-using" of an old one with properties changed. Each new object should have a unique identifier, so if you need to track them (for development purposes, debugging, or later re-use), it is easy to do. Or at least keep a counter of the number of times you've re-used a particle object to represent a "new" particle! Though I guess if you've found that "re-using" improves performance (have you?), that's the way to go.
Anyway, enough pontificating, here is how I would do what you're asking (I assume speed is your main concern, so I did this with only native JS):
var particles = [];
//Function to create brand spanking new particle
function makeNewParticle(xPos, yPos, pRadius, pType){
return {
type : pType,
x : xPos,
y : yPos,
xVel : random(-0.5, 0.5),
yVel : random(-1, -3),
particleAlive : true,
particleRender : true,
size : pRadius
};
};
//Function to change the properties of an old particle to make a psuedo-new particle (seriously, why do you want to do this?)
function changeExistingParticle(existing, xPos, yPos, pRadius, pType){
existing.x = xPos;
existing.y = yPos;
existing.size = pRadius;
existing.type = pType;
return existing;
};
//Figure out the keys of dead particles in the particles[] array
function getDeadParticleKeys() {
var keys = [];
for(var p = 0; P < particles.length; p++) {
if (!particles[p].particleAlive) {
keys.push(p);
}
}
};
function makeParticle(numParticles, xPos, yPos, pRadius, pType) {
var d, i, deadParticles;
//Grab the "dead" particle keys
deadParticleKeys = getDeadParticleKeys();
numParticles -= deadParticleKeys.length;
//Replace each dead particle with a "live" one at a specified key
for (d = 0; d < deadParticleKeys.length; d++) {
particles[ deadParticleKeys[d] ] = changeExistingParticle(particles[ deadParticleKeys[d] ], xPos, yPos, pRadius, pType)
}
//If we had more particles than there were dead spaces available, add to the array
for (i = 0; i < numParticles; i++) {
particles.push( makeNewParticle(xPos, yPos, pRadius, pType) );
}
};
Now, here's how I recommend doing it: abandon the idea or "re-using" particles, make a separate constructor for each particle (will help immensely if you add methods to your particles in the future), and just scrap dead particles every time one is added:
//Make a constructor for a particle
var Particle = function(props){
if (typeof props === 'function') {
props = props();
}
this.type = props.type;
this.x = props.x;
this.y = props.y;
this.size = props.size;
};
Paticle.prototype.particleAlive = true;
Paticle.prototype.particleRender = true;
//Global particles list
var particles = [];
//Remove all dead element from a ParticleList
particles.clean = function(){
var p, keys;
for (p = this.length; p >= 0; p--) {
if (!p.particleAlive) {
this.splice(p, 1);
}
}
};
//Method for adding x amount of new particles - if num parameter isn't provided, just assume it to be 1
particles.add = function(props, num){
//First, clean out all the garbage!
this.clean();
//Now, append new particles to the end
var n, limit = (num && typeof num === 'number') ? num : 1;
for (n = 0; n < limit; n++){
particles.push( new Particle(props) );
}
};
//A couple examples
particles.add({ //Add a single blueFlame
type: "blueFlame",
size: 10,
x: 200,
y: 200
});
particles.add({ //Add 4 redFlames
type: "redFlame",
size: 10,
x: 300,
y: 200
}, 4);
particles.add(function(){//Add 4 greenFlames, with randomized XY cooridinates
this.x = Math.round(Math.random() * 1000);
this.y = Math.round(Math.random() * 1000);
this.size = 20;
this.type = "greenFlame";
}, 4);
Way less code to manage. I'm not sure which way is faster, but I'd bet the speed difference is negligible. Of course, you could check for yourself by making a quick jsPerf.