I am having problem with my code,
// JavaScript Document
var canvas = document.getElementById("PlayingArea");
var ctx = canvas.getContext("2d");
var canvasWidth = canvas.width;
var canvasHeight = canvas.height;
var foodArray = [];
var size = 10;
var food;
var player1 = {x:150, y:150};
//create Player1
ctx.beginPath();
ctx.arc(150, 150, size, 0, Math.PI * 2);
ctx.fillStyle = "black";
ctx.fill();
function update() {
"use strict";
//BG Refresh
ctx.fillStyle = "white";
ctx.fillRect(0,0,canvasWidth,canvasHeight);
ctx.strokeStyle = "black";
ctx.strokeRect(0,0,canvasWidth,canvasHeight);
document.addEventListener("keydown", Player1Control);
function Player1Control(){
if(event.keyCode === 38) {
player1.y--;
}
if(event.keyCode === 40) {
player1.y++;
}
if(event.keyCode === 39) {
player1.x++;
}
if(event.keyCode === 37) {
player1.x--;
}
}
if (player1.x >= canvasWidth) {
player1.x = canvasWidth;
} else if (player1.x <= 5) {
player1.x = 5;
}
if (player1.y > canvasHeight) {
player1.y = canvasHeight;
} else if (player1.y <= 5) {
player1.y = 5;
}
//Player Show
ctx.beginPath();
ctx.arc(player1.x, player1.y, size, 0, Math.PI * 2);
ctx.fillStyle = "black";
ctx.fill();
//Food Show
for(var i=foodArray.length; i>0; i--){
ctx.beginPath();
ctx.arc({x:foodArray[i].x},{y:foodArray[i].y} , size, 0, Math.PI * 2);
ctx.fill();
}
setTimeout(update, 10);
}
function foodGen(){
"use strict";
food = {x:Math.round(Math.random()*(canvasWidth)),
y:Math.round(Math.random()*(canvasHeight))};
ctx.beginPath();
ctx.arc(food.x, food.y, 5, 0, Math.PI * 2);
ctx.fillStyle = "black";
ctx.fill();
foodArray.push({x:1,y:1});
setTimeout(foodGen, 1000);
}
update();
foodGen(0,750);
The player is not show in my code and I do not know why my player isn't Moving.
I am pretty new at JavaScript and HTML/CSS. This is my first time Stack overflow so I am sorry for any derps.
-lt1489
edit: My player now appears on the screen, can't be moved.
Link: https://jsfiddle.net/5os0qrhp/2/
The original question was answered with the following comment:
Since you don't change fillStyle between clearing the canvas and drawing the player, you are drawing the player white. Since it is white on white, you cannot see the player.
Regarding the second issue, move document.addEventListener and Player1Control to outside update. Additionally, Player1Control needs event as an argument, resulting in:
document.addEventListener("keydown", Player1Control);
function Player1Control(event) { ... }
function update() { ... }
A few syntax changes fixes the code. See jsfiddle to see those changes outlined.
Related
I try to create a class with a function which might be use to change the angle of a line already drawn.
With what I write, the line doesn't move. When I press the right or left key, I have this error :
TypeError: this.changeAngle is not a function
Indeed, I don't have "function" keyword in my code ... I don't know what to use instead.
Could you help me ?
Thank you very much.
window.onload = init;
let canvas, ctx;
let mousePos;
let angle = 0;
class Lanceur {
constructor() {
this.changeAngle(this.angle);
}
update(ctx) {
this.drawAiguille(ctx);
}
drawSocleLanceur(ctx) {
ctx.save();
ctx.beginPath();
ctx.lineWidth = 2;
ctx.arc(w/2, h, 20, 0, 2 * Math.PI);
ctx.stroke();
ctx.restore();
}
drawAiguille(ctx) {
ctx.save();
ctx.rotate(this.angle);
ctx.strokeStyle = "rgb(255, 0, 0)";
ctx.lineWidth=3;
ctx.beginPath();
ctx.moveTo(w/2, h-h*0.12);
ctx.lineTo(w/2, h-h*0.035);
ctx.stroke();
ctx.restore();
}
changeAngle(a) {
this.angle = a;
}
getAngle() {
return this.angle;
}
}
function init() {
canvas = document.querySelector("#jeu");
ctx = canvas.getContext("2d");
w = canvas.width;
h = canvas.height;
a = new Lanceur();
requestAnimationFrame(mainloop);
}
function mainloop() {
ctx.clearRect(0, 0, w, h);
a.update(ctx);
requestAnimationFrame(mainloop);
}
document.addEventListener('keypress', function(event){
gereTouches(event);
});
function gereTouches(event) {
if(event.key == "ArrowRight") {
this.changeAngle(this.getAngle - 1);
console.log("ça bouge : " + this.angle);
}else if(event.key == "ArrowLeft") {
this.changeAngle(this.getAngle + 1);
}
}
Main changes:
added this.angle to thr constructor()
using keydown event
the function gereTouches(event) uses a instead of this and a.getAngle() instead of a.getAngle
also 1 for the the angle is way too big (those are radians). I'm using .01 instead.
I hope it helps.
window.onload = init;
let canvas, ctx;
let mousePos;
let angle = 0;
class Lanceur {
constructor() {
this.angle = 0;
this.changeAngle(this.angle);
}
update(ctx) {
this.drawAiguille(ctx);
}
drawSocleLanceur(ctx) {
ctx.save();
ctx.beginPath();
ctx.lineWidth = 2;
ctx.arc(w/2, h, 20, 0, 2 * Math.PI);
ctx.stroke();
ctx.restore();
}
drawAiguille(ctx) {
ctx.save();
ctx.rotate(this.angle);
ctx.strokeStyle = "rgb(255, 0, 0)";
ctx.lineWidth=3;
ctx.beginPath();
ctx.moveTo(w/2, h-h*0.12);
ctx.lineTo(w/2, h-h*0.035);
ctx.stroke();
ctx.restore();
}
changeAngle(a) {
this.angle = a;
}
getAngle() {
return this.angle;
}
}
function init() {
canvas = document.querySelector("#jeu");
ctx = canvas.getContext("2d");
w = canvas.width = 500;
h = canvas.height = 500;
a = new Lanceur();
requestAnimationFrame(mainloop);
}
function mainloop() {
ctx.clearRect(0, 0, w, h);
a.update(ctx);
requestAnimationFrame(mainloop);
}
document.addEventListener('keydown', function(event){
gereTouches(event);
});
function gereTouches(event) {
if(event.key == "ArrowRight") {
a.changeAngle(a.getAngle() - .01);
console.log("ça bouge : " + a.angle);
}else if(event.key == "ArrowLeft") {
a.changeAngle(a.getAngle() + .01);
}
}
canvas{border:1px solid}
<canvas id="jeu"></canvas>
So I'm trying to implement platforms for the game I'm making for a project (similar to falldown) and have created multiple arrays that have contain all the possible platforms (canvas is 360 so there is if platform[i] == 1 it draws a rect)
var canvas;
var ctx;
var isPlaying = false;
window.onload = function(){
canvas= document.getElementById("gamesCanvas");
ctx = canvas.getContext("2d");
var fps = 60;
setInterval(function(){
}, 1000/fps);
createMenu();
canvas.addEventListener('click', getClicks.bind(this), false)
//canvas.addEventListener("mousemove", getPos)
}
function initialise(){
isPlaying = true;
ctx.clearRect(0, 0, canvas.width, canvas.height);
createRect(0,0, canvas.width, canvas.height, 'black');
createPlatforms();
}
function createPlatforms(){
x = randint(1,2);
console.log(x)
var i;
var pos = -60;
var platform1 = [0,1,1,1,1,1];
var platform2 = [1,0,1,1,1,1];
var platform3 = [1,1,0,1,1,1];
var platform4 = [1,1,1,0,1,1];
var platform5 = [1,1,1,1,0,1];
var platform6 = [1,1,1,1,1,0];
if(x==1){
for (i=0; i<platform1.length; ++i) {
var pos = (pos+60);
if(platform1[i] == 1){
createRect(pos, 60, 60,5, 'white');
}
}
}
else if(x==2){
for (i=0; i<platform2.length; ++i){
var pos = (pos+60);
if (platform2[i] ==2){
createRect(pos,60,75,5,'white');
}
}
}
}
function randint(min, max) {
return ~~(Math.random() * (max - min + 1) + min);
}
function background(color) {
ctx.fillStyle = color;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function createMenu(){
background("black");
if (!isPlaying) {
ctx.font = "60px monospace";
ctx.fillStyle = "white";
ctx.fillText("FallDown", 40, 130);
ctx.font = "34px Arial";
ctx.fillStyle = "white";
ctx.fillText("PLAY", 130, 260);
ctx.font = "34px Arial";
ctx.fillStyle = "white";
ctx.fillText("LEADERBOARD", 50, 340);
ctx.font = "34px Arial";
ctx.fillStyle = "white";
ctx.fillText("SETTINGS", 90, 420);
}
}
function createRect(leftX, topY, width, height, color){
ctx.fillStyle = color;
ctx.fillRect(leftX, topY, width, height);
}
function getClicks(evt) {
var x = evt.offsetX;
var y = evt.offsetY;
if ((x > 110 && x < 240) && (y > 220 && y < 275) && !isPlaying) {
initialise()
}
}
<html>
<head>
<title>Falldown</title>
</head>
<body>
<canvas id="gamesCanvas" width="360" height="640"></canvas>
<!--script src="test.js"></script-->
</body>
</html>
However, if x>1 (so basically an else if statement is required to run) it doesn't draw anything.
I was testing to see whether it is something that I could fix, however, all I managed to realise that if the if statement has got the contents of the else if statement than it will draw the rects in the right position so in this case (platform2) would be drawn.
I've managed to narrow down the problem but I'm not sure how to fix it. I have experience with python but have never experienced anything like this
Just letting you know that I can't just use the else statement as I have to implement 6 platforms and if I were to use just if and else than that would mean I could only draw 2 of the 6 platforms
Your initial problem wasn't with the if / else.. but the if inside..
But with -> if (platform2[i] ==2){ this wanted to be if (platform2[i] == 1){
But saying all this, your createPlatforms was only creating a single platform. It didn't really need any If/else or arrays.
Below I've modified createPlatforms, using just two for loops.
var canvas;
var ctx;
var isPlaying = false;
window.onload = function(){
canvas= document.getElementById("gamesCanvas");
ctx = canvas.getContext("2d");
var fps = 60;
setInterval(function(){
}, 1000/fps);
createMenu();
canvas.addEventListener('click', getClicks.bind(this), false)
//canvas.addEventListener("mousemove", getPos)
}
function initialise(){
isPlaying = true;
ctx.clearRect(0, 0, canvas.width, canvas.height);
createRect(0,0, canvas.width, canvas.height, 'black');
createPlatforms();
}
function createPlatforms(){
for (var y = 0; y < 8; y ++) {
var x = randint(0, 5), pos = 0;
for (var i = 0; i < 6; i ++) {
if (i !== x) {
createRect(pos, 60 + y*60 ,75,5,'white');
}
pos += 60;
}
}
}
function randint(min, max) {
return ~~(Math.random() * (max - min + 1) + min);
}
function background(color) {
ctx.fillStyle = color;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
function createMenu(){
background("black");
if (!isPlaying) {
ctx.font = "60px monospace";
ctx.fillStyle = "white";
ctx.fillText("FallDown", 40, 130);
ctx.font = "34px Arial";
ctx.fillStyle = "white";
ctx.fillText("PLAY", 130, 260);
ctx.font = "34px Arial";
ctx.fillStyle = "white";
ctx.fillText("LEADERBOARD", 50, 340);
ctx.font = "34px Arial";
ctx.fillStyle = "white";
ctx.fillText("SETTINGS", 90, 420);
}
}
function createRect(leftX, topY, width, height, color){
ctx.fillStyle = color;
ctx.fillRect(leftX, topY, width, height);
}
function getClicks(evt) {
var x = evt.offsetX;
var y = evt.offsetY;
if ((x > 110 && x < 240) && (y > 220 && y < 275) && !isPlaying) {
initialise()
}
}
<html>
<head>
<title>Falldown</title>
</head>
<body>
<canvas id="gamesCanvas" width="360" height="640"></canvas>
<!--script src="test.js"></script-->
</body>
</html>
You can use a switch statement in javascript to handle lots of cases.
Example:
switch(x){
case 1:
//logic here
break;
case 2:
// and so on
break:
default:
break;
}
You can add as many cases as you would like. This will eliminate the need to use if else.
Hope this helps!
This is my JavaScript. I have an animate function, I think this is where the redrawing background code goes. I have tried to use document.getElementById to get the id of the canvas, and give the style rule of background: white. But it didn't work. All help is appreciated!:
function initCanvas(){
var ctx = document.getElementById('my_canvas').getContext('2d');
var cW = ctx.canvas.width, cH = ctx.canvas.height;
var dist = 10;
function Player(){
this.x = 0, this.y = 0, this.w = 50, this.h = 50;
ctx.fillStyle = "orange";
this.render = function(){
ctx.fillRect(this.x, this.y, this.w, this.h);
}
}
var player = new Player();
player.x = 100;
player.y = 225;
function animate(){
//This is where I think the background redrawing should go
player.render();
}
var animateInterval = setInterval(animate, 30);
document.addEventListener('keydown', function(event) {
var key_press = String.fromCharCode(event.keyCode);
if(key_press == "W"){
player.y-=dist;
} else if(key_press == "S"){
player.y+=dist;
} else if(key_press == "A"){
player.x-=dist;
} else if(key_press == "D"){
player.x+=dist;
}
});
}
window.addEventListener('load', function(event) {
initCanvas();
});
Here are a couple things I've noticed:
You didn't declare var canvas = document.getElementById('my_canvas');
Your initCanvas() wasn't firing(It wasn't for me)
Your render() function should reset the fillStyle before it draws your character. Having the fillStyle set when initializing the Player constructor is useless(It can be overridden).
Here is what your animate() function should look like:
function animate(){
ctx.fillStyle = '#000';
ctx.fillRect(0,0,canvas.width, canvas.height);
player.render();
}
Notice how fillRect() clears the canvas before drawing the player.
I have created a working JSFiddle with the fixes here.
I have some code below for the start of a snake game that I'm making using HTML5 canvas. For some reason, the red circle that I'm temporarily using to represent my snake is drawing constantly following the path the mouse moves in. and it uses the food as a starting point. Check it out in your browser, because it's really hard to describe. All I want is for the circle to follow the mouse and leave a small trail that ends and doesn't stay on the canvas. How would I go about doing this. Thanks in advance!
<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Snake 2.0</title>
</head>
<style>
</style>
<body>
<div>
<canvas id="canvas" width=500 height=500></canvas>
</div>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
makeFood();
function makeFood() {
foods = [];
for (var i = 0; i < 1; i++){
foods.push(new Food());
}
}
function Food() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = 10;
}
function drawFood() {
for (var i = 0; i < 1; i++){
foods.push(new Food());
}
for (var i = 0; i < foods.length; i++){
var f = foods[i];
context.beginPath();
var grd = context.createRadialGradient(f.x, f.y, (f.radius - (f.radius - 1)), f.x + 1, f.y + 1, (f.radius));
grd.addColorStop(0, 'red');
grd.addColorStop(1, 'blue');
context.arc(f.x, f.y, f.radius, 0, 2 * Math.PI, true);
context.fillStyle = grd;
context.fill();
}
}
function makePower() {
powers = [];
for (var i = 0; i < 1; i++){
powers.push(new Power());
}
}
function Power() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = 8;
}
function drawPower() {
for (var i = 0; i < powers.length; i++){
var p = powers[i];
context.beginPath();
var grd = context.createRadialGradient(p.x, p.y, (p.radius - (p.radius - 1)), p.x + 1, p.y + 1, (p.radius));
grd.addColorStop(0, 'green');
grd.addColorStop(1, 'yellow');
context.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true);
context.fillStyle = grd;
context.fill();
}
}
canvas.addEventListener("mousemove", function(event) {
move(event);
});
function move(e) {
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
var a = e.clientX;
var b = e.clientY;
context.arc(a, b, 20, 0, 2 * Math.PI, true);
context.fillStyle = "red";
context.fill();
}
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
var functions = [drawFood];
var timer = setInterval(function(){
drawFood();
}, 5000);
function stop() {
clearInterval(timer);
}
canvas.addEventListener("click", stop);
//timer = setInterval(start, 1000);
//timer = setInterval(start, 5000);
</script>
</body>
</html>
You could start by adding "context.beginPath();" in your "move" function, before "context.arc(a, b, 20, 0, 2 * Math.PI, true);", line 102-103 in my editor.
function move(e) {
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
var a = e.clientX;
var b = e.clientY;
context.beginPath();
context.arc(a, b, 20, 0, 2 * Math.PI, true);
context.fillStyle = "red";
context.fill();
}
Here is the fiddle : http://jsfiddle.net/sd5hh57b/1/
You should store the positions you move along in an array. Then a new timer should revisit those discs and redraw them in a more faded color each time it ticks, until a disc becomes black. Then it should be removed from that array.
Here is fiddle that does that.
The change in the code starts at canvas.addEventListener("mousemove",... and goes like this:
canvas.addEventListener("mousemove", function(event) {
// Replaced move function by drawDisc function,
// which needs coordinates and color intensity
drawDisc(event.clientX, event.clientY, 0xF);
});
// Array to keep track of previous positions, i.e. the trail
var trail = [];
function drawDisc(x, y, red) {
context.beginPath();
context.arc(x, y, 20, 0, 2 * Math.PI, true);
context.fillStyle = '#' + red.toString(16) + '00000';
context.fill();
// If disc is not completely faded out, push it in the trail list
if (red) {
trail.push({x: x, y: y, red: red});
}
}
// New function to regularly redraw the trail
function fadeTrail() {
var discs = trail.length;
// If there is only one disc in the trail, leave it as-is,
// it represents the current position.
if (discs > 1) {
for (var i = discs; i; i--) {
// take "oldest" disc out of the array:
disc = trail.shift();
// and draw it with a more faded color, unless it is
// the current disc, which keeps its color
drawDisc(disc.x, disc.y, disc.red - (i === 1 ? 0 : 1));
}
}
}
// New timer to fade the trail
var timerFade = setInterval(function(){
fadeTrail();
}, 10);
I think the comments will make clear what this does. Note that the colors of the discs go from 0xF00000 to 0xE00000, 0xD00000, ... , 0x000000. Except the current disc, that one keeps its 0xF00000 color all the time.
The other answers are right :
Use beginPath() at each new arc() to create a new Path and avoid context.fill() considers the whole as a single Path.
Use a trail Array to store your last positions to draw the trail.
But, the use of setTimeout and setInterval should be avoided (and even further the use of multiple ones).
Modern browsers do support requestAnimationFrame timing method, and for olders (basically IE9), you can find polyfills quite easily. It has a lot of advantages that I won't enumerate here, read the docs.
Here is a modified version of your code, which uses a requestAnimationFrame loop.
I also created two offscreen canvases to update your foods and powers, this way they won't disappear at each draw. Both will be painted in the draw function.
I changed the mousemove handler so it only updates the trail array, leaving the drawing part in the draw loop. At each call, it will set a moving flag that will let our draw function know that we are moving the mouse. Otherwise, it will start to remove old trail arcs from the Array.
var canvas = document.getElementById("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var context = canvas.getContext("2d");
// create other contexts (layer like) for your food and powers
var foodContext = canvas.cloneNode(true).getContext('2d');
var pwrContext = canvas.cloneNode(true).getContext('2d');
// a global to tell weither we are moving or not
var moving;
// a global to store our animation requests and to allow us to pause it
var raf;
// an array to store our trail position
var trail = [];
// here we can determine how much of the last position we'll keep at max (can then be updated if we ate some food)
var trailLength = 10;
// your array for the foods
var foods = [];
// a global to store the last time we drawn the food, no more setInterval
var lastDrawnFood = 0;
// start the game
draw();
function makeFood() {
foods.push(new Food());
}
function Food() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = 10;
}
function drawFood() {
// clear the food Canvas (this could be done only if we ate some, avoiding the loop through all our foods at each call of this method)
foodContext.clearRect(0, 0, canvas.width, canvas.height);
foods.push(new Food());
for (var i = 0; i < foods.length; i++) {
var f = foods[i];
// draw on the food context
foodContext.beginPath();
foodContext.arc(f.x, f.y, f.radius, 0, 2 * Math.PI, true);
var foodGrd = foodContext.createRadialGradient(f.x, f.y, (f.radius - (f.radius - 1)), f.x + 1, f.y + 1, (f.radius));
foodGrd.addColorStop(0, 'red');
foodGrd.addColorStop(1, 'blue');
foodContext.fillStyle = foodGrd;
foodContext.fill();
}
}
// I'll let you update this one
function makePower() {
powers = [];
for (var i = 0; i < 1; i++) {
powers.push(new Power());
}
}
function Power() {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = 8;
}
function drawPower() {
pwrContext.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < powers.length; i++) {
var p = powers[i];
var pwrGrd = pwrContext.createRadialGradient(p.x, p.y, (p.radius - (p.radius - 1)), p.x + 1, p.y + 1, (p.radius));
pwrGrd.addColorStop(0, 'green');
pwrGrd.addColorStop(1, 'yellow');
pwrContext.beginPath();
pwrContext.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true);
pwrContext.fillStyle = pwrGrd;
pwrContext.fill();
}
}
// the event object is already passed, no need for an anonymous function here
canvas.addEventListener("mousemove", move);
function move(e) {
// we paused the game, don't update our position
if (!raf) return;
// update the snake
var a = e.clientX - canvas.offsetLeft;
var b = e.clientY - canvas.offsetTop;
trail.splice(0, 0, {
x: a,
y: b
});
// tell our draw function that we moved
moving = true;
}
function draw(time) {
// our food timer
if (time - lastDrawnFood > 5000) {
lastDrawnFood = time;
drawFood();
}
// clear the canvas
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
// draw the food
context.drawImage(foodContext.canvas, 0, 0);
// draw the power
context.drawImage(pwrContext.canvas, 0, 0);
//draw the snake
for (var i = 0; i < trail.length; i++) {
// decrease the opacity
opacity = 1 - (i / trail.length);
context.fillStyle = "rgba(255, 0,0," + opacity + ")";
// don't forget to create a new Path for each circle
context.beginPath();
context.arc(trail[i].x, trail[i].y, 20, 0, 2 * Math.PI, true);
context.fill();
}
// if we're not moving or if our trail is too long
if ((!moving || trail.length > trailLength) && trail.length > 1)
// remove the oldest trail circle
trail.pop();
// we're not moving anymore
moving = false;
// update the animation request
raf = requestAnimationFrame(draw);
}
context.fillStyle = "black";
context.fillRect(0, 0, canvas.width, canvas.height);
function toggleStop() {
if (!raf) {
// restart the animation
raf = window.requestAnimationFrame(draw);
} else {
// cancel the next call
cancelAnimationFrame(raf);
raf = 0;
}
}
canvas.addEventListener("click", toggleStop);
html, body{margin:0;}
<canvas id="canvas" width=500 height=500></canvas>
Well I've got a few question to ask! Firstly What this code is doing is creating and drawing snowflakes with unique density which will all fall at a different rate. My first question is how do i make this loop continuous?
Secondly, I've translated my origin point(0,0) to the middle of the canvas (it was part of the criteria). I've now got this issue in which that when the snowfall is called it will either be drawn on the left side of the screen or the right, not both. How do i solve this?
Finally i know when doing animations that you have to clear the canvas after each re-drawing, however i haven't added this in and yet it still works fine?
//Check to see if the browser supports
//the addEventListener function
if(window.addEventListener)
{
window.addEventListener
(
'load', //this is the load event
onLoad, //this is the evemnt handler we going to write
false //useCapture boolen value
);
}
//the window load event handler
function onLoad(Xi, Yy) {
var canvas, context,treeObj, H, W, mp;
Xi = 0;
Yy = 0;
mp = 100;
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
W = window.innerWidth;
H = window.innerHeight;
canvas.width = W;
canvas.height = H;
context.translate(W/2, H/2);
var particles = [];
for(var i = 0; i < mp; i++) {
particles.push({
x: Math.random()*-W, //x
y: Math.random()*-H, //y
r: Math.random()*6+2, //radius
d: Math.random()* mp // density
})
}
treeObj = new Array();
var tree = new TTree(Xi, Yy);
treeObj.push(tree);
function drawCenterPot(){
context.beginPath();
context.lineWidth = "1";
context.strokeStyle = "Red";
context.moveTo(0,0);
context.lineTo(0,-H);
context.lineTo(0, H);
context.lineTo(-W, 0);
context.lineTo(W,0);
context.stroke();
context.closePath();
}
function drawMountain() {
context.beginPath();
context.fillStyle = "#FFFAF0";
context.lineWidth = "10";
context.strokeStyle = "Black";
context.moveTo(H,W);
context.bezierCurveTo(-H*10,W,H,W,H,W);
context.stroke();
context.fill();
}
function drawSky() {
var linearGrad = context.createLinearGradient(-100,-300, W/2,H);
linearGrad.addColorStop(0, "#000000");
linearGrad.addColorStop(1, "#004CB3");
context.beginPath();
context.fillStyle = linearGrad;
context.fillRect(-W/2, -H/2, W, H);
context.stroke();
context.fill();
drawMountain();
drawCenterPot();
}
function drawSnow(){
context.fillStyle = "White";
context.beginPath();
for(i = 0; i<mp; i++)
{
var p = particles[i];
context.moveTo(p.x,p.y);
context.arc(p.x, p.y, p.r, Math.PI*2, false);
}
context.fill();
}
function update() {
var angle = 0;
angle+=0.1;
for(var i=0; i<mp; i++) {
var p = particles[i];
p.x += Math.sin(angle) * 2;
p.y += Math.cos(angle+p.d) + 1 * p.r;
}
drawSky();
drawSnow();
draw();
}
function draw() {
for(var i =0; i < treeObj.length; i++)
{
context.save();
context.translate(Xi-H,Yy-W);
context.scale(1, 1);
treeObj[0].draw(context);
context.restore();
}
}
setInterval(update, 33);
}
About your animation:
What's happening is your flakes are falling out of view below the bottom of the canvas.
So when any flake's p.y+p.r > canvas.height you could:
destroy that flake and (optionally) add another falling from above the canvas
or
"recycle" that flake by changing its p.y to above the canvas.
About your design working without context.clearRect:
In your design, when you fill the whole canvas with "sky", you are effectively clearing the canvas.
About your flakes only falling on half the screen:
Instead of translating to mid-screen:
Don't translate at all and let p.x be any Math.random()*canvas.width