html canvas javascript fill and stroke methods - javascript

I am working on creating squares with HTML canvas and javascript. However, it is glitchy. I don't understand why. I have created two javascript objects, one for hollow blocks, one for filled blocks. I am iterating through both arrays to create the blocks at animate. However, I can only get one filled block at a time. I have not been able to have more than one at a time. However, I am successful creating hollow blocks. The code is the same, but it does not work the same. Why is that?
function hBlock(h,w,x,y){
this.h = h;
this.w = w;
this.x = x;
this.y = y;
this.create = function(){
ctx.rect(x,y,w,h);
ctx.stroke();
}
}
function fBlock(h,w,x,y){
this.h = h;
this.w = w;
this.x = x;
this.y = y;
this.create = function(){
ctx.fillRect(x,y,w,h);
}
}
function newblock(){
if(f==1){fBlocks.push(new fBlock(h,w,x,y));}
else{hBlocks.push(new hBlock(h,w,x,y));}
console.log(hBlocks);
console.log(fBlocks);
animate();
}
function animate(){
requestAnimationFrame(animate);
ctx.clearRect(0, 0, cw, ch);
if(hBlocks.length>1){hBlocks[hBlocks.length-1].create();}
if(fBlocks.length>1){fBlocks[fBlocks.length-1].create();}
}

Related

What is the best way to remove/delete a function object once instantiated/drawn to canvas?

The snippet code below shows a single function object called "Circle" being drawn to a canvas element. I know how to remove the visual aspect of the circle from the screen. I can simply change its opacity over time with c.globalAlpha=0.0; based on event.listener 's or 'object collision', However if I visually undraw said circle; it still is there and being computed on, its still taking up browser resources as it invisibly bounces to and fro on my canvas element.
So my question is: What is the best way to remove/delete a function object once instantiated/drawn to canvas? =>(so that it is truly removed and not invisibly bouncing in the browser)
let canvas = document.getElementById('myCanvas');
let c = canvas.getContext('2d');
function Circle(x, y, arc, dx, dy, radius){
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.arc = arc;
this.cCnt = 0;
this.radius = radius;
this.draw = function() {
c.beginPath();
//context.arc(x,y,r,sAngle,eAngle,counterclockwise);
c.arc(this.x, this.y, this.radius, this.arc, Math.PI * 2, false); //
c.globalAlpha=1;
c.strokeStyle = 'pink';
c.stroke();
}
this.update = function() {
if (this.x + this.radius > canvas.width || this.x - this.radius < 0){
this.dx = -this.dx;
}
if (this.y + this.radius > canvas.height || this.y - this.radius < 0){
this.dy = -this.dy;
}
this.x += this.dx;
this.y += this.dy;
this.draw();
}
}
var circle = new Circle(2, 2, 0, 1, 1, 2); // x, y, arc, xVel, yVel, radius
function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, canvas.width, canvas.height)
circle.update();
}
animate();
body {
background-color: black;
margin: 0;
}
<canvas id="myCanvas" width="200" height="60" style="background-color: white">
A lot of canvas libraries solve this problem by keeping an array of objects that are in the canvas scene. Every time the animate() function is called, it loops through the list of objects and calls update() for each one (I'm using the names you're using for simplicity).
This allows you to control what is in the scene by adding or removing objects from the array. Once objects are removed from the array, they will no longer be updated (and will get trash collected if there are no other references hanging around).
Here's an example:
const sceneObjects = [];
function animate() {
requestAnimationFrame(animate);
c.clearRect(0, 0, canvas.width, canvas.height);
// Update every object in the scene
sceneObjects.forEach(obj => obj.update());
}
// Elsewhere...
function foo() {
// Remove an object
sceneObjects.pop();
// Add a different object
sceneObjects.push(new Circle(2, 2, 0, 1, 1, 2));
}
It's not uncommon to take this a step further by creating a Scene or Canvas class/object that keeps the list of scene objects and gives an interface for other parts of the program to use (for example, Scene.add(myNewCircle) or Scene.remove(myOldCircle)).

ES6 class methods not a function

I'm messing around with Javascript "classes" and I have a paddle that has a proper method to draw, but for some reason my moveBall function is messed up. Could anyone point out why? I get an error saying that moveBall() is not a function.
Edit: I included some more code, I call init() to start it all.
class Ball {
constructor(x, y, r, sAngle, rAngle) {
this.x = x;
this.y = y;
this.r = r;
this.sAngle = sAngle;
this.rAngle = rAngle;
this.speed = null;
}
drawBall() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, this.sAngle, this.rAngle);
ctx.fillStyle = "#FF0000";
ctx.fill();
}
moveBall() {
this.x += this.speed;
}
}
function init() {
var ball = new Ball(c.height / 2, c.width / 2, 10, 0, 2 * Math.PI);
var paddleLeft = new Paddle(0, 0, 20, 100);
ball.ballPhysics = 1.0;
draw(ball, paddleLeft);
main(ball);
}
window.main = function (ball) {
window.requestAnimationFrame(main);
ball.moveBall();
window.onload = function () {
document.addEventListener('keydown', function (event) {
if (event.keyCode === 65) {
}
}, false);
}
};
If you are using it like Ball.moveBall() than it's incorrect, you must instantiate Ball class first or use static methods like
class A {
static f() {
}
}
and call like
A.f();
otherwise check the snippet below
class Ball {
constructor(x, y, r, sAngle, rAngle) {
this.x = x;
this.y = y;
this.r = r;
this.sAngle = sAngle;
this.rAngle = rAngle;
this.speed = null;
}
drawBall() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, this.sAngle, this.rAngle);
ctx.fillStyle = "#FF0000";
ctx.fill();
}
moveBall() {
this.x += this.speed;
}
}
var greenBall = new Ball(0, 0 , 10, 0, 0);
greenBall.speed = 5;
greenBall.moveBall();
document.write(greenBall.x);
make sure you have an instance of ball in the scope of the code you are trying to run, and try var moveball = function(){this.x += this.speed; }; to see if it's a compile issue, and make sure you are accessing it like ball.moveball()
You define main to accept an argument ball. But you are never calling main, so you cannot pass an argument to it.
While window.requestAnimationFrame(main); will call the function, it won't pass anything to it.
It seems you want to refer to the ball variable that is defined inside init. In that case, remove the parameter ball from the function definition so that it doesn't shadow that variable:
window.main = function() { ... };
You also don't want to assign to window.onload inside main, because that wouldn't happen over and over again.

Game Development Using IIFEs - Code Seperation

So, I'm currently learning how to use Javascript for Canvas game development. After seeing the method used in several examples, and having read the benefits, I started shifting my code over into IIFEs.
However, at the moment, all of my code is in a single IIFE. What I want to do is begin separating my code in to individual files.
The part I'm stuck on, however, is how to allow each IIFE function see data that's in another. I don't really understand how this works.
My full code is in this fiddle, https://jsfiddle.net/473z1g2t/1/, whilst a sample of my code is below;
(function(){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
function Ball(x, y, radius, color){
/* .. */
}
function Paddle(x, y){
/* .. */
}
var ball = new Ball((canvas.width / 2), canvas.height - 60, 10, 'black');
var paddle = new Paddle((canvas.width / 2) - 20, 550);
function initCanvas(){
canvas.addEventListener('click', function(){
if(!ball.active)
ball.active = true;
else
ball.active = false;
});
canvas.addEventListener('mousemove', function(e){
});
}
initCanvas();
function Update(){
Draw();
requestAnimationFrame(Update);
if(ball.active){
/* .. */
}
}
function Draw(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ball.draw();
paddle.draw();
}
requestAnimationFrame(Update);
})();
TLDR
I want to separate my Paddle and Ball logic from the rest of the application (and possibly the canvasInit function too). What is the preferred method of going about this? I know I can pass parameters to these functions, but what do I pass between them?
Thanks in Advance.
As far as I understand from your code, you don't actually have communication between the pad and the ball.
So you can just move the classes into another file and have a master file (the canvas one) which orchestrate the elements on the screen.
```
(function(canvas, ctx) {
function Ball(x, y, radius, color){
this.x = x;
this.y = y;
this.r = radius;
this.c = color;
this.vx = -3;
this.vy = -3;
this.active = false;
this.draw = function(){
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, Math.PI*2);
ctx.fill();
ctx.closePath();
}
}
})(canvas, ctx);
```
You can either do that and share the globals canvas and ctx or you can send canvas and ctx as parameters in Ball/Paddle constructors
Bu if you do want to share data between them, you can do it during the orchestration calling method with specific parameters.

Which was is it to best declare a property in JavaScript?

If you are building a function type class in JavaScript when you declare a variable is it better to do it with
var this.variableName = variableName
var this.x = x
or is it better to just do it like this.
this.x
I tried using the var and it gave an error in Google debuger. Why would this be the case or are properties different than a variable that is set in a function "object".
Code:
function Circle(x,y,r) {
this.x = x;
this.y = y;
this.r = r;
// I've added the drawing code to the actual circle
// they can draw themselves.
this.draw = function(context){
context.beginPath();
context.arc(this.x, this.y, this.r, 0, Math.PI*2, true);
context.closePath();
context.fill();
}
}
When an object is declared, it is already declared, so doing something like this is, not only illegal, but also redundant.
// DON'T DO THIS!!!
var this.a = 'a'; // NO!!!!!!!!!
Instead, just declare your object and then just append things to that object, since it's already initialized
var obj = {};
obj.a = 'a';
obj.b = 'b';
The problem you'll probably face when declaring a function in your object is a matter of scope and how this works in Javascript.
For this, you have a couple of alternatives:
Declare a that variable that you can then use in your function:
function Circle(x,y,r) {
this.x = x;
this.y = y;
this.r = r;
// I've added the drawing code to the actual circle
// they can draw themselves.
var that = this;
this.draw = function(context){
// this refers to the global object (window)
// that refers to your Circle Object
context.beginPath();
context.arc(that.x, that.y, that.r, 0, Math.PI*2, true);
context.closePath();
context.fill();
}
}
If you're using an ECMAScript 5 supported browser (not IE8), you can bind the function to your Circle object.
function Circle(x,y,r) {
this.x = x;
this.y = y;
this.r = r;
// I've added the drawing code to the actual circle
// they can draw themselves.
this.draw = function(context){
context.beginPath();
context.arc(this.x, this.y, this.r, 0, Math.PI*2, true);
context.closePath();
context.fill();
}.bind(this);
}
If you want to support IE8 and use .bind, you can just use underscore.js and use the _.bind function.
function Circle(x,y,r) {
this.x = x;
this.y = y;
this.r = r;
// I've added the drawing code to the actual circle
// they can draw themselves.
this.draw = _.bind(function(context){
context.beginPath();
context.arc(this.x, this.y, this.r, 0, Math.PI*2, true);
context.closePath();
context.fill();
}, this);
}

how to make modular, oo "animations" with canvas / JavaScript?

I come from a flash animation background, and am learning to create animations with HTML5 <canvas> and plain JavaScript.
In flash, you can draw a movieclip and link it to an actionScript class file. This makes each movieclip somewhat OO / modular and allows you to more easily call and reference them in your app.
As JS has no native class support, and drawing with Canvas seems more rudimentary than in Flash, what is an example of a way to structure your javascript for a large/complex canvas animation?
You can use a pseudo-class approach by using objects.
For example, if you want to lets say move a box across the canvas you define the box as an object and update it for each frame:
Live demo
function ooRect(x, y, w, h, color, dx, dy) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.dx = dx;
this.dy = dy;
}
Now ooRect is an object which you can update to move around and change color etc.
You can extend it with methods which makes it self-contained update-wise so it updates itself per frame:
function ooRect(x, y, w, h, color, dx, dy) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.dx = dx;
this.dy = dy;
this.update = function(ctx) {
this.x += this.dx;
this.y += this.dy;
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
You can now have a "host" routine (or another special object) to update all your objects stored in the array:
var objects = [
new ooRect(10, 20, 50, 70, 'blue', 2, 3),
new ooRect(200, 300, 50, 70, 'red', -3, 2) /// etc.
];
(function loop() {
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); /// clear canvas
for(var i = 0, o; o = objects[i++];) /// update all objects
o.update(ctx);
requestAnimationFrame(loop); /// next frame
})();
Now it is a matter of implementing different types of shape objects with its properties and methods.
If you plan to use a lot of objects you can prototype them as that allow the browser to share code-base memory:
function ooRect(x, y, w, h, color, dx, dy) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.dx = dx;
this.dy = dy;
}
ooRect.prototype.update = function(ctx) {
this.x += this.dx;
this.y += this.dy;
ctx.fillStyle = this.color;
ctx.fillRect(this.x, this.y, this.w, this.h);
}
Go with requirejs which is JavaScript file and module loader.
http://requirejs.org/

Categories

Resources