I want to be able to draw an array of balls, I can push the balls into the array (when clicking the canvas).
I can draw 1 of the balls on the canvas if I create it with ball = new Ball, but as soon as I try to draw from inside the array it breaks.
I draw inside a for loop with balls[i].draw
Here's a jsFiddle.
And here's the relevant code:
function init(){
defaultBall();
for(i=0;i<balls.length;i++){
balls[i].draw;
}
ball.draw();
}
function Ball(X, Y, Radius, Color){
this.X = X || 0;
this.Y = Y || 0;
this.radius = 5;
this.color = Color;
}
Ball.prototype.draw = function(){
ctx.fillStyle = this.color;
ctx.beginPath();
ctx.arc(this.X, this.Y, this.radius, 10, 0, Math.PI*2, true);
ctx.closePath();
ctx.fill();
}
var balls = [];
function defaultBall(){
addBall(new Ball(50, 50, 5, '#6B7E00'));
addBall(new Ball(150, 50, 5, '#6B7E00'));
}
function addBall(ball){
balls.push(ball);
}
var ball = new Ball(50, 50, 5, '#6B7E00');
How should I formulate the loop to be able to draw the balls?
Help appriciated.
Maybe
balls[i].draw;
should be
balls[i].draw();
on line 4
Your init method isn't getting called again. If you change
function addBall(ball){
balls.push(ball);
ball.draw();
}
to
function addBall(ball){
balls.push(ball);
}
you'll see the new balls. You need to have some sort of mechanism that calls init (aka draw) again.
And as Frits pointed out you will need to use draw() instead of draw.
Your code runs just fine, it is just that there is a small error with your balls loop.
defaultBall();
for(i=0;i<balls.length;i++){
balls[i].draw;
}
ball.draw();
You forgot to use the parenthesis to call the draw method when looping through your balls. The fix is simple:
defaultBall();
for(i=0;i<balls.length;i++){
balls[i].draw();
}
ball.draw();
Note that now your balls will show up as intended. When the fiddle is edited with this new fix for looping through the balls you can see two green balls show up.
Related
so I am trying to make thisgame called GO and I need to place circles in the edges like this. I've made the grid and now need to place the circles in there. I 'v tried different things like using the arc in canvas with mouse position and placing it but it isn't working something else I tried is to make an array that checks where the lines cross but it still didn't do anything. but i may have done it wrong. I'm not sure what's wrong so hope you guys could help me find a way to place the circles on the board every time I click the mouse. I've deleted the things that didn't work and this is my code now:
const canvas = document.getElementById("myCanvas")
const ctx = canvas.getContext("2d")
//canvas.style.border = "1px solid black"
let w = ctx.canvas.width
let h = ctx.canvas.height
goBoard = []
goCheckBoard = []
function drawGrid(w, h) {
for (x = 0; x <= w; x += 40) {
for (y = 0; y <= h; y += 40) {
ctx.moveTo(x, 0);
ctx.lineTo(x, h);
ctx.stroke();
ctx.moveTo(0, y);
ctx.lineTo(w, y);
ctx.stroke();
}
}
}
drawGrid(400, 400)
this just makes the grid
one example i've tried is this:
mouseClicked = function () {
ctx.beginPath()
ctx.strokeStyle = "black"
ctx.ellipse(mouseX, mouseY, 20, 20);
ctx.stroke()
};
another:
function rtn(n, r){
return Math.round(n/r)*r;
}
canvas.onclick = function(event){
ellipse(rtn(event.clientX, 40), rtn(event.clientY, 40), 180, 180);
};
im not sure if that is the correct way to do it
maybe make an array of all the possible places to place the circle but im not sure how
here is a fiddle if you want to test it out https://jsfiddle.net/pwe0vx7o/
you first need to change the ellipse(...) to ctx.ellipse(...), because ellipse isn't a global function, but a metod of the CanvasRenderingContext2D.
Through the docs I also found that this function takes 7 arguments so added ones for radiusX, radiusY, rotation, startAngle, endAngle.
Here is also a fiddle for the finished result: https://jsfiddle.net/c6udn9gf/8/
This will get you close, but you need to figure out something with your rounding function.
canvas.onclick = function (event) {
ctx.beginPath();
const x = rtn(event.clientX, 40);
const y = rtn(event.clientY, 40);
ctx.ellipse(x - 20, y - 20, 10, 10, 0, 0, 360);
ctx.fill();
};
I have been given the following task, but I am getting errors that can be seen when the code snippet is run. I would like some help figuring out what exactly I am doing wrong.
Basically, I need to draw a circle, make it so that it moves and changes the direction/color when touching the walls of the screen.
Task: create a Circle class with the following properties:
x - the initial value of the coordinate x
y is the initial value of the y coordinate
radius - values โโof width and height
color - fill color Describe the methods:
draw () - marks off on the screen an element that is described by the given properties
setColor (newColor) - Changes the fill color to newColor
move ({x = 0, y = 0}) - moves the captured object by the vector (x, y) - each time period (for example, 100 ms) changes (adds \ subtracts)
to the values โโx and y, respectively. When a circle collides with any
edge of the screen it is necessary to realize its mirror reflection
(change the value of the corresponding coordinate of the vector on the
opposite of the value of the sign, and call this method with the new
vector) and generate the collision event, collision, which is captured
at the document level.Hang on this event a handler that will change
the color of the pouring of the circle into another (random) value.
Movement occurs until the stop method is called.
stop () - stops the circle movement
If the Escape button on the keyboard was pressed, the movement should stop.
I created a canvas and set the frame to move. I drew a circle and tried to move it using setInterval(), but it seems like I'm losing the context.
let c = document.getElementById("mycanvas");
let ctx = c.getContext("2d");
let xinc = 1;
let yinc = 1;
class Circle {
constructor(xpos, ypos, radius, color) {
this.xpos = xpos;
this.ypos = ypos;
this.radius = radius;
this.color = color;
}
draw() {
ctx.beginPath();
ctx.arc(this.xpos, this.ypos, this.radius, 0, Math.PI * 2);
ctx.fillStyle = "red";
ctx.fill();
}
move(xpos, ypos) {
ctx.clearRect(0, 0, c.width, c.height);
ctx.beginPath();
this.draw();
xpos += xinc;
ypos += yinc;
console.log(xpos, ypos);
if ((this.xpos > c.width - this.radius) || (this.xpos < 0 + this.radius)) {
xinc = -xinc;
}
if ((this.ypos > c.height - this.radius) || (this.ypos < 0 + this.radius)) {
yinc = -yinc;
}
setInterval(this.move, 10);
//this.draw();
}
}
let circle = new Circle(200, 300, 50, "red");
circle.draw();
circle.move(200, 300);
<canvas id="mycanvas" width="1335" height="650" style="border: 1px solid"> </canvas>
I am just starting to learn events and DOMs, please help me correctly implement this task
You are passing this.move to setInterval with no context - just a function, with no this to call it in. You can pass in this.move.bind(this) to create a bound function. You can also do it once in the constructor: this.move = this.move.bind(this).
Also, the call to beginPath in move seems unnecessary.
I have this jsfiddle which creates a pattern of 4 points.
What I want is for it to continuously draw the projected line until the user click for point B, then point C and D.
function draw(){
//
ctx.clearRect(0,0,cw,ch);
// draw connecting lines
for(var i=0;i<connectors.length;i++){
var c=connectors[i];
var s=anchors[c.start];
var e=anchors[c.end];
ctx.beginPath();
ctx.moveTo(s.x,s.y);
ctx.lineTo(e.x,e.y);
ctx.stroke();
}
// draw circles
for(var i=0;i<anchors.length;i++){
ctx.beginPath();
ctx.arc(anchors[i].x,anchors[i].y,radius,0,Math.PI*2);
ctx.fill();
ctx.fillText(anchors[i].label,anchors[i].x-5,anchors[i].y-15);
}
}
Ok so, basically you need your connector adding function to be slightly smarter, so we can make this work like in this fiddle
(You were adding way to many connectors, and it stopped at length over 7, this fixes both those)
if(draggingIndex==-1 && fullDrag == null){
addAnchor(startX,startY);
var al = anchors.length-1;
var almod4 = al%4;
if(almod4==1){
connectors.push({start:al-1,end:al});
}
if(almod4==2){
connectors.push({start:al-2,end:al});
connectors.push({start:al-1,end:al});
}
if(almod4==3){
connectors.push({start:al-2,end:al});
connectors.push({start:al-1,end:al});
}
draw();
}
As you can see, based on the value of anchors.length-1 modular 4, we know if we need to draw 1 or 2 lines. In our draw function we can then add:
if (anchors.length>0 && anchors.length%4>0){
ctx.strokeStyle='gray';
var al = anchors.length-1;
var almod4 = al%4;
if (almod4==1 || almod4==2){
//draw extra line
ctx.beginPath();
ctx.moveTo(anchors[al-1].x,anchors[al-1].y);
ctx.lineTo(mouseX,mouseY);
ctx.stroke();
}
ctx.beginPath();
ctx.moveTo(anchors[al].x,anchors[al].y);
ctx.lineTo(mouseX,mouseY);
ctx.stroke();
}
Note that instead of checking for almod4 being 2 or 3, we check for 1 and 2, because that means we're in the process of adding 2 or 3.
Now all you need to do is tell it to draw at every mouseover, and voila, preview lines.
I'm currently working on a little experimental project with HTML5 Canvas.
Basically, at the moment i'm just trying to make the canvas clear as expected. The only thing that my code does as the moment is generate a lines that are broken in the middle. However, at the moment i'm trying to make one line, and then remove that line and add another line at another different position without showing the first line.
I would of thought that this code would work:
poles(20); // this number is the x position at which the line (pole) will be generated
ctx.clearRect(0, 0, WIDTH, HEIGHT);
poles(140)
In all technically, this should show only the second pole because the canvas should have been cleared after the first pole was generated. But hit still shows both.
When I tried only:
poles(20);
ctx.clearRect(0, 0, WIDTH, HEIGHT);
The canvas was blank which told me that the clearing worked correctly.
I tried one more thing:
poles(20);
ctx.clearRect(0, 0, WIDTH, HEIGHT);
setTimeout(function () {
poles(140)
}, 1000);
In this case, both poles did show up but not until after 1 second which told me that the poles function is causing both to be generated again even though the function doesn't loop:
function poles(x) {
var bottomH = getRandomInt(20, 180)
// using seperate rectangles will make a break
rect(40, 220 - bottomH, x, 0); // first section of line
rect(40, bottomH, x, HEIGHT - bottomH); // second section of line
}
I hope someone can explain to me how come my poles function is cause both of the poles to reappear.
You can view the example here.
For Reference, the main code is:
var canvas = document.getElementById("canvas"),
WIDTH = canvas.width,
HEIGHT = canvas.height;
var ctx = canvas.getContext("2d");
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function rect(w, h, x, y) {
ctx.rect(x, y, w, h);
ctx.fill();
}
function poles(x) {
var bottomH = getRandomInt(20, 180); // determine where the line break will be
rect(40, 220 - bottomH, x, 0);
rect(40, bottomH, x, HEIGHT - bottomH);
}
poles(20);
ctx.clearRect(0, 0, WIDTH, HEIGHT);
setTimeout(function () {
poles(140)
}, 1000);
The problem lies with your rect function. Specifically, with the usage of the .rect() member of the ctx. The rect member creates a path, which you then fill with ctx.fill() - only problem is, it doesn't close the path, so it remains open and is added to when the second call to poles comes along.
You can either close the path before exiting the rect function, or even more simply, avoid paths altogether by defining and filling the rectangle in a single call, by using ctx.fillRect.
The following change makes the code function as expected:
function rect(w, h, x, y)
{
// ctx.rect(x, y, w, h);
// ctx.fill();
ctx.fillRect(x,y,w,h);
}
Hey guys In another question about function pushing-Here
I was then given this code -
var postDrawHooks = [];
var draw = function(){
// do stuff
postDrawHooks.forEach(function(hook){hook()});
}
var playerUpdate = function(){...};
postDrawHooks.push(playerUpdate);
Which works very nicely, and allows you to push an outide function into another one like your game loop without having to edit your engine.js file for every game if you want to add an update to an object just push the hook. Anyways I need a way to push drawing like Context2D.drawImage(blah blah blah); now when I try to push this like above below I get the error trying to draw from null.
post_draw_render.push(context2D.drawImage(player.tilesheet, player.frameX,player.frameY, 46, 45, player.PosX, player.PosY+1, 46, 45));
I can't even use Context2D.drawImage anywhere oustide of my draw function and I don't know why any Ideas?
engine -
//engine vars//
function init() {
canvas = document.getElementById('canvas');
context2D = canvas.getContext('2d');
setInterval(draw, 1000/FPS);
}
function draw() {
post_draw_function.forEach(function(hook){hook()});
gameloop();
context2D.clearRect(0, 0, canvas.width, canvas.height);
post_draw_render.forEach(function(hook){hook});
//Basic Draw - context2D.drawImage(playerImg, player.PosX, player.PosY);
//Tilesheet draw - context2D.drawImage(tilesheet, sx, sy, sw, sh, dx, dy, dw, dh);
context2D.fillStyle = "white";
context2D.font = 'bold 25px Times New Roman';
}
The object you are pushing into the array is not a function, it's the return value of a call to the drawImage function.
I think you want
post_draw_render.push(function () {
context2D.drawImage(player.tilesheet, player.frameX,player.frameY, 46, 45, player.PosX, player.PosY+1, 46, 45);
});