Game Development Using IIFEs - Code Seperation - javascript

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.

Related

Why does my triangle on canvas have artifacts? [duplicate]

I'm doing a Pong game in javascript in order to learn making games, and I want to make it object oriented.
I can't get clearRect to work. All it does is draw a line that grows longer.
Here is the relevant code:
function Ball(){
this.radius = 5;
this.Y = 20;
this.X = 25;
this.draw = function() {
ctx.arc(this.X, this.Y, this.radius, 0, Math.PI*2, true);
ctx.fillStyle = '#00ff00';
ctx.fill();
};
}
var ball = new Ball();
function draw(){
player.draw();
ball.draw();
}
function update(){
ctx.clearRect(0, 0, 800, 400);
draw();
ball.X++;
}
I've tried to put the ctx.clearRect part in the draw() and ball.draw() functions and it doesn't work.
I also tried fillRect with white but it gives the same results.
How can I fix this?
Your real problem is you are not closing your circle's path.
Add ctx.beginPath() before you draw the circle.
jsFiddle.
Also, some tips...
Your assets should not be responsible for drawing themselves (their draw() method). Instead, perhaps define their visual properties (is it a circle? radius?) and let your main render function handle canvas specific drawing (this also has the advantage that you can switch your renderer to regular DOM elements or WebGL further down the track easily).
Instead of setInterval(), use requestAnimationFrame(). Support is not that great at the moment so you may want to shim its functionality with setInterval() or the recursive setTimeout() pattern.
Your clearRect() should be passed the dimensions from the canvas element (or have them defined somewhere). Including them in your rendering functions is akin to magic numbers and could lead to a maintenance issue further down the track.
window.onload = function() {
var cvs = document.getElementById('canvas');
var ctx = cvs.getContext('2d');
var cvsW = cvs.Width;
var cvsH = cvs.Height;
var snakeW = 10;
var snakeH = 10;
function drawSnake(x, y) {
ctx.fillStyle = '#FFF';
ctx.fillRect(x*snakeW, y * snakeH, snakeW, snakeH);
ctx.fillStyle = '#000';
ctx.strokeRect(x*snakeW, y * snakeH, snakeW, snakeH);
}
// drawSnake(4, 5)
//create our snake object, it will contain 4 cells in default
var len = 4;
var snake = [];
for(var i = len -1; i >=0; i--) {
snake.push(
{
x: i,
y: 0
}
)
};
function draw() {
ctx.clearRect(0, 0, cvsW, cvsH)
for(var i = 0; i < snake.length; i++) {
var x = snake[i].x;
var y = snake[i].y;
drawSnake(x, y)
}
//snake head
var snakeX = snake[0].x;
var snakeY = snake[0].y;
//remove to last entry (the snake Tail);
snake.pop();
// //create a new head, based on the previous head and the direction;
snakeX++;
let newHead = {
x: snakeX,
y: snakeY
}
snake.unshift(newHead)
}
setInterval(draw, 60);
}
my clearRect is not working, what's the problem and solution?

HTML5 Canvas: Not drawing

I'm currently creating a simple program using HTML Canvas and Javascript. All that I need to happen is for a ball to be drawn at coordinates on the canvas and then move around using some velocity variables etc.
The issue is, I've created a Ball object as I intend to have multiple balls on screen at a time, however nothing is showing on my canvas.
I've read over this a few times, I'm receiving no errors so I'm struggling to figure out what's happening with this.
EDIT:
I've added a console log to check the drawSelf() is running, which it is but still no error/result
CODE
<!DOCTYPE html>
<html>
<head>
<title>Bouncing Ball</title>
</head>
<script>
var Date
var canvas;
var ctx;
var dx=5;
var dy=5;
function init(){
canvas = document.getElementById('game');
ctx = canvas.getContext('2d');
setInterval(draw,10);
console.log("Initialised: " + new Date());
}
function Ball(x, y, dx, dy){
this.x = x;
this.y = y;
this.dx = dx;
this.dy = dy;
this.drawSelf = function () {
ctx.beginPath();
ctx.fillStyle = "#4286f4";
ctx.arc(this.x,this.y,20,0,Math.PI*2,true);
ctx.closePath();
console.log("Ball is drawing self!");
if(this.x<0 || this.x>800){
dx=-dx;
}
if(this.y<0 || this.y>800){
dy=-dy;
}
this.x+=this.dx;
this.y+=this.dy;
}
this.getX = function () {
console.log("X:" + this.x);
console.log("Y:" + this.y);
}
}
//Creating Ball object.
let ball1 = new Ball(400, 400, 5, 5);
function draw(){
ball1.drawSelf();
}
</script>
<body onLoad="init()">
<div id="canvas-area">
<canvas id="game" width="800" height="800"></canvas>
</div>
</body>
<html>
You forgot to add ctx.stroke() or ctx.fill(), taken from the Mozilla docs
this.drawSelf = function () {
ctx.beginPath();
ctx.fillStyle = "#4286f4";
ctx.arc(this.x,this.y,20,0,Math.PI*2,true);
ctx.stroke();
ctx.closePath();
console.log("Ball is drawing self!");
if(this.x<0 || this.x>800){
dx=-dx;
}
if(this.y<0 || this.y>800){
dy=-dy;
}
this.x+=this.dx;
this.y+=this.dy;
}
Also sidenote, since you don't set the background every draw, your canvas will just add the ball to it's current state, resulting in a cool pattern, but something you probably don't want. To fix this, make this your draw method.
function draw(){
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ball1.drawSelf();
}
EDIT: Instead of using setInterval I recommend using requestAnimationFrame. You can read more about it here

html canvas javascript fill and stroke methods

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();}
}

Canvas Javascript Looping

I'm trying to loop my animation, but no matter what I do, it won't loop. I'm pretty new to canvas, javascript and code in general.
var canvas = document.getElementById("fabrication");
var ctx = canvas.getContext("2d");
var background = new Image();
background.src =
"C:/Users/dylan/Desktop/ProjectTwo/Images/fabricationbackground.jpg";
background.onload = function(){
}
//Loading all of my canvas
var posi =[];
posi[1] = 20;
posi[2] = 20;
var dx=10;
var dy=10;
var ballRadius = 4;
//Variables for drawing a ball and it's movement
function drawballleft(){
posi =xy(posi[1],posi[2])
}
function xy(x,y){
ctx.drawImage(background,0,0);
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#FFFFFFF";
ctx.fill();
ctx.closePath();
var newpos=[];
newpos[1]= x +dx;
newpos[2]= y +dy;
return newpos;
//Drawing the ball, making it move off canvas.
if (newpos[1] > canvas.width) {
newpos[1] = 20;
}
if (newpos[2] > canvas.height) {
newpos[2] = 20;
}
//If statement to detect if the ball moves off the canvas, to make it return to original spot
}
setInterval(drawballleft, 20);
//Looping the function
Please let me know if I've done something wrong, I really want to learn what I'm doing here. The ball is supposed to go off the canvas, and loop back onto itself, but it goes off the canvas and ends.
Thanks in advance!
I have made a few changes to your code.
First I am using requestAnimationFrame instead of setInterval. http://www.javascriptkit.com/javatutors/requestanimationframe.shtml
Second I am not using an image because I didn't want to run into a CORS issue. But you can put your background image back.
I simplified your posi array to use indexes 0 and 1 instead of 1 and 2 to clean up how you create your array.
I moved your return from before the two ifs to after so the ball will move back to the left or top when it goes off the side. I think that was the real problem you were seeing
var canvas = document.getElementById("fabrication");
var ctx = canvas.getContext("2d");
//Loading all of my canvas
var posi =[20,20];
var dx=10;
var dy=10;
var ballRadius = 4;
//Variables for drawing a ball and it's movement
function drawballleft(){
posi = xy(posi[0],posi[1])
requestAnimationFrame(drawballleft);
}
function xy(x,y){
ctx.fillStyle = '#FFF';
ctx.fillRect(0,0,400,300);
ctx.beginPath();
ctx.arc(x, y, ballRadius, 0, Math.PI*2);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
var newpos=[x+dx,y+dy];
//Drawing the ball, making it move off canvas.
if (newpos[0] > canvas.width) {
newpos[0] = 20;
}
if (newpos[1] > canvas.height) {
newpos[1] = 20;
}
//If statement to detect if the ball moves off the canvas, to make it return to original spot
return newpos;
}
requestAnimationFrame(drawballleft);
canvas {
outline: 1px solid red;
}
<canvas width="400" height="300" id="fabrication"></canvas>
To make it all even simpler...
Use an external script for handling the canvas.
A really good one ;) :
https://github.com/GustavGenberg/handy-front-end#canvasjs
Include it with
<script type="text/javascript" src="https://gustavgenberg.github.io/handy-front-end/Canvas.js"></script>
Then it's this simple:
// Setup canvas
const canvas = new Canvas('my-canvas', 400, 300).start(function (ctx, handyObject, now) {
// init
handyObject.Ball = {};
handyObject.Ball.position = { x: 20, y: 20 };
handyObject.Ball.dx = 10;
handyObject.Ball.dy = 10;
handyObject.Ball.ballRadius = 4;
});
// Update loop, runs before draw loop
canvas.on('update', function (handyObject, delta, now) {
handyObject.Ball.position.x += handyObject.Ball.dx;
handyObject.Ball.position.y += handyObject.Ball.dy;
if(handyObject.Ball.position.x > canvas.width)
handyObject.Ball.position.x = 20;
if(handyObject.Ball.position.y > canvas.height)
handyObject.Ball.position.y = 20;
});
// Draw loop
canvas.on('draw', function (ctx, handyObject, delta, now) {
ctx.clear();
ctx.beginPath();
ctx.arc(handyObject.Ball.position.x, handyObject.Ball.position.y, handyObject.Ball.ballRadius, 0, Math.PI * 2);
ctx.fillStyle = '#000';
ctx.fill();
ctx.closePath();
});
I restructured your code and used the external script, and now it looks much cleaner and easier to read and toubleshoot!
JSFiddle: https://jsfiddle.net/n7osvt7y/

How to use Prototypal Pattern to make an html5 rectangle for reuse

I'm trying to understand Prototypal Inheritance using the Prototypal pattern by making a rectangle object and an instance of the rectangle. Seems easy, but I'm not getting it. The RectanglePrototype's method is not drawing the rectangle onto the canvas. If I use the same function as the method it works. Where am I going wrong? Also, I understand that I will need to make an initialization function, but I'm thinking I can do that later after I get the first basic steps down.
javascript:
window.onload = function () {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var RectanglePrototype = {
// Properties
x: 0,
y: 0,
width: 100,
height: 100,
color: "white",
// Method
get:function (x, y, width, height, color) {
context.translate(0 , 0);
context.beginPath();
context.rect(x, y, width, height);
context.fillStyle = color;
context.fill();
return this.x, this.y, this.width, this.height, this.color;
}
};
console.log(RectanglePrototype.get);
// Instance of RectanglePrototype
var rectangle1 = Object.create(RectanglePrototype);
rectangle1.x = 200;
rectangle1.y = 100;
rectangle1.width = 300;
rectangle1.height = 150;
rectangle1.color = '#DBE89B';
// Draw Rectangle Function
function rect(x, y, width, height, color) {
context.translate(0 , 0);
context.beginPath();
context.rect(x, y, width, height); // yLoc-canvas.height = -300
context.fillStyle = color;
context.fill();
};
rect(0, 450, 50, 50, '#F7F694');
}
</script>
Prototypes are extensions of objects that result from a constructor. Method lookups go through the object properties before looking into prototype.
I proper JS design, you would only add the non-function properties in your constructor.
//Your constructor
function Rectangle(){
// Properties
this.x = 0;
this.y = 0;
this.width = 100;
this.height = 100;
this.color = 'red';
}
And then put the methods in your prototype:
//I prefer the term 'draw'
Rectangle.prototype.draw = function(ctx){
ctx.save();
ctx.beginPath();
ctx.rect(this.x, this.y, this.width, this.height);
ctx.fillStyle = this.color;
ctx.fill();
ctx.restore();
};
Then, to use in your project:
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
//List of your shapes to draw on the canvas
var shapes = [];
//Instance of Rectangle
var rectangle1 = new Rectangle();
rectangle1.x = 200;
rectangle1.y = 100;
rectangle1.width = 300;
rectangle1.height = 150;
rectangle1.color = '#DBE89B';
shapes.push(rectangle1);
//Draw your shapes
function draw(){
window.requestAnimationFrame(draw); //See MDN for proper usage, but always request next fram at the start of your draw loop!
for(var i = 0; i<shapes.length; i++){
shapes[i].draw(context);
}
}
This is the 'proper' way of drawing to the canvas. For anything larger scale, please look into existing engines that do a looooot of hard work for you and have thought of everything so you don't have to. I have worked on such engines.

Categories

Resources