Loop will not increment or array is broken - javascript

var starNum = 20;
var starry = new Array(starNum);
for(var s = 0 ; s < 20 ; s++){
starry[i] = new stars()
}
var starDraw = function() {
var starCanvas = document.getElementById("stars");
var starCtx = starCanvas.getContext("2d");
starCtx.clearRect(0, 0, 1000, 900);
for(i = 0; i < 20 ; i++){
var star = starry[i];
starCtx.fillStyle= "gold";
starCtx.beginPath();
// draw it
starCtx.arc(star.x, star.y, star.radius, Math.PI * 2, false);
starCtx.stroke();
starCtx.fill();
}
}
function starFinish(){
setInterval(starDraw, 10);
}
starFinish()
Now the main problem here is that the program only draws on star when it should be drawing many stars. Here is my html code. When i tried finding the x of star[i] , it tells me that it is undefined. I used the idea for this code somewhere else and it worked , not sure what went wrong here. I need this to be solved very quickly please.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>xdd</title>
</head>
<body>
<canvas id="mycanvas" width="900" height="1000"
style="position: absolute; left: 0; top: 0; z-index: 1"></canvas>
<canvas id="stars" width="900" height="1000"
style="position: absolute; left: 0; top: 0; z-index: 0; ; background-color:#000066"></canvas>
<script src="Project.js"></script>
</body>
</html>

Pacifier21 spotted the error in your code, but as you have some other code thats not all that CPU friendly I have done a quick rewrite
// > Use const for variables that do not change
// var starNum = 20;
const starNum = 20;
// > Try to avoid using new Array and unless you wish to assign the array
// declare it as a const
// var starry = new Array(starNum);
const starry = [];
// > Simple mistakes due to inconsistent code style. I use i in 99% of for loops
// then j,k not because they have any special meaning, but because it stops from
// doing this type of thing, which is often very hard to spot
//for(var s = 0 ; s < 20 ; s++){
for(var i = 0; i < starNum; i ++) { // You have the const starNum you should use it
starry[i] = new stars()
}
// > The following two lines were in the function starDraw and are relatively slow
// in the great scheme of things. As neither canvas or context will change it
// is best to get them once.
const starCanvas = document.getElementById("stars");
const starCtx = starCanvas.getContext("2d");
// > Use function statements rather than function expressions. function statements
// are hoisted to the top of the current scope and are safer to use than
// function expressions
// var starDraw = function() {
function starDraw () {
// > Removed following two lines
// var starCanvas = document.getElementById("stars");
// var starCtx = starCanvas.getContext("2d");
// > Could also use canvas size saves you hunting down this line if the
// canvas size is changed
// starCtx.clearRect(0, 0, 1000, 900);
starCtx.clearRect(0, 0, starCanvas.width, starCanvas.height);
// > Using an undeclared variable, i is thus put in the global name space
// and can be a source of very hard to track bugs.
// for(i = 0; i < 20 ; i++){
for(var i = 0; i < starNum; i++){
var star = starry[i];
starCtx.fillStyle= "gold";
starCtx.beginPath();
starCtx.arc(star.x, star.y, star.radius, Math.PI * 2, false);
// > You use stroke but don't set the stroke style ?
starCtx.stroke();
starCtx.fill();
}
}
// > Never use setInterval for high frame rate animations
//function starFinish(){
// setInterval(starDraw, 10);
//}
// > Use requestAnimation frame and an animation loop function
function mainLoop(){ // > This function will be called 60 times a second
// if the browser can maintain that rendering speed.
starDraw(); // > draw the frame
requestAnimationFrame(mainLoop); // > request next frame
}
// > This will start the animation
requestAnimationFrame(mainLoop);
// starFinish() // > Not needed

Related

How do you blur a single object in Matter.js?

I'm trying to create a fire effect for a game in Matter.js, and I need to blur a circle to make it look more realistic. However, I need to make it so it only blurs the fire, not the whole canvas. How can I do this?
This is the code I have so far:
function setOnFire(object) {
var fireX = object.position.x;
var fireY = object.position.y;
var fire = Bodies.circle(fireX, fireY, vw*1, {
isStatic: true,
render: {
fillStyle: "rgba(255,130,0,1)"
}
});
World.add(world, fire);
}
This is not exactly what I had in mind, but it is as close as you can get.
Start by going to matter.js and go to this section:
for (k = body.parts.length > 1 ? 1 : 0; k < body.parts.length; k++) {
part = body.parts[k];
if (!part.render.visible)
continue;
Add this code after the continue;:
if (body.bloom) {
c.shadowColor = body.render.fillStyle;
c.shadowOffsetX = 0;
c.shadowOffsetY = 0;
c.shadowBlur = body.bloom;
}
Then, go to the very end of the loop and add this:
if (body.bloom) {
c.shadowColor = "transparent";
c.shadowOffsetX = 0;
c.shadowOffsetY = 0;
c.shadowBlur = 0;
}
Then, just add the bloom while making your body. For instance:
let fireParticle = Bodies.circle(0, 0, {
bloom: 25
});

how to detect an element inside a canvas?

I am trying to detect the drawn elements inside the canvas (for example: every slice in the pie) to put a click event on them later, but it seems not to be an easy task, I think the math would be the best way to carry it out, but where should I start.
Please Help me to find a solution for this.
here is the demo:
outer link
code is:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#myCanvas{
width: 50%;
height: 50%;
}
</style>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
class Piechart{
constructor(){
this.options = arguments[0];
this.canvas = arguments[0].canvas;
this.ctx = this.canvas.getContext('2d');
if(this.options.colors){
this.colors = arguments[0].colors;
}
else if (!this.options.colors){
this.colors = [
"#fde23e",
"#f16e23",
"#57d9ff",
"#937e88",
'#2fe678',
'#228888',
'#b111c1'
];
}
this.donut_hole = 0.5;
}
drawPie(){
var total_value = 0;
var color_index = 0;
for(var categ in this.options.data){
var val = this.options.data[categ];
total_value += val;
}
var start_angle = 0;
for(var categ in this.options.data){
var val = this.options.data[categ];
var slice_angle = 2*Math.PI*val/total_value;
this.drawPieSlice(
this.ctx,
this.canvas.width/2,
this.canvas.height/2,
Math.min(this.canvas.width/2,this.canvas.height/2),
start_angle,
start_angle+slice_angle,
this.colors[color_index%this.colors.length]
);
start_angle += slice_angle;
color_index++;
}
}
drawPieSlice(){
arguments[0].fillStyle = arguments[6];
arguments[0].beginPath();
arguments[0].moveTo(arguments[1],arguments[2]);
arguments[0].arc(
arguments[1],
arguments[2],
arguments[3],
arguments[4],
arguments[5]
);
arguments[0].closePath();
arguments[0].fill();
}
}
var myCanvas = document.getElementById("myCanvas");
var myCanvas_width = myCanvas.scrollWidth;
var myCanvas_height = myCanvas.scrollHeight;
myCanvas.width = myCanvas_width;
myCanvas.height = myCanvas_height;
var myVinyls = {
'Classical music':10,
'Rock':14,
'Pop':15,
'Jazz':4,
'test':6,
'test_1':7,
'test_2':8
};
var myPiechart = new Piechart(
{
canvas:myCanvas,
data:myVinyls,
colors:[
"#fde23e",
"#f16e23",
"#57d9ff",
"#937e88",
'#2fe678',
'#228888',
'#b111c1'
]
}
);
myPiechart.drawPie();
How to be able to detect each slice? Thank you.
EDIT
I have found an amazing solution for the purpose of adding hit region in the canvas and here is the link: Anton Lavrenov
First of all there are no elements on canvas you should understand this. It is a 2d plane where things are just drawn and if you want to move things around you need to redraw them entirely.
This said lets go back to the original problem.
Since you create the "object" in the canvas you know the size and distances of the object which you should keep in some js object for later use.
what i would do in this case to have an object that will hold the data of all other objects so when you click on the canvas you can get the click x and y and determine whether they are greater or equal to any of your objects' xs and ys
an example algorithm would be
if click.X>elem.X && click.X<elem.X+elem.Width
{
x is in check the same for y
}
if x__in&&y__in
{
you clicked the element
}

Replace and loop images after X milliseconds

I am having trouble getting this to work, I just want the images to loop endlessly. What isn't right here?
var croppingImages = new Array()
croppingImages[0] = "https://img.f1today.eu/x/topstory/58c7e187745517a1c90fc5ebe21c55da49223c999500b.jpg";
croppingImages[1] = "https://pbs.twimg.com/media/C69Y8aWW0AEkCIW.jpg:small";
setTimeout("animateImages()", 100);
var cropImg = 0;
function animateImages() {
document.getElementById("cropping__animation").src = croppingImages[cropImg]
x++;
}
<img src="https://img.f1today.eu/x/topstory/58c7e187745517a1c90fc5ebe21c55da49223c999500b.jpg" id="cropping__animation">
There are a couple of things here.
1) cropImg is never incremented, so animateImages will always show the same image
2) animateImages will only ever be called once by setTimeout
This code works better:
var cropImg = 0;
var croppingImages = new Array()
croppingImages[0] = "https://img.f1today.eu/x/topstory/58c7e187745517a1c90fc5ebe21c55da49223c999500b.jpg";
croppingImages[1] = "https://pbs.twimg.com/media/C69Y8aWW0AEkCIW.jpg:small";
animateImages();
function animateImages() {
document.getElementById("cropping__animation").src = croppingImages[cropImg];
if (++cropImg > croppingImages.length - 1)
{
cropImg = 0;
}
setTimeout(function() {
animateImages();
}, 3000);
}
https://jsfiddle.net/y6bhgm53/5/
if you want to loop them endless you maybe should use setInterval() and not setTimeout(). Also you should make it that your cropImg variable loops by checking if the value is greater than the array length.
https://jsfiddle.net/nyxeen/y6bhgm53/6/
I hope it helps
var croppingImages = new Array()
croppingImages[0] = "https://img.f1today.eu/x/topstory/58c7e187745517a1c90fc5ebe21c55da49223c999500b.jpg";
croppingImages[1] = "https://pbs.twimg.com/media/C69Y8aWW0AEkCIW.jpg:small";
setInterval(animateImages, 100);
var cropImg = 0;
function animateImages() {
document.getElementById("cropping__animation").src = croppingImages[cropImg]
cropImg++;
if(cropImg>=croppingImages.length)cropImg=0
}
<img src="https://img.f1today.eu/x/topstory/58c7e187745517a1c90fc5ebe21c55da49223c999500b.jpg" id="cropping__animation">

How to create objects on runtime and move them?

I'm trying to create objects on my game update and move them. This is my banana object:
function Banana() {
this.height = 1.96;
this.width = 3.955;
this.pos_x = CENTER - this.width/2;
this.pos_y = -475;
this.banana_image = banana_image;
};
And this is the Move method:
Banana.prototype.move = function(){
if (this.pos_y > 500) {
//this.banana_image.parentElement.removeChild(this.banana_image);
}
this.height += ZOOM_RATE;
this.width += ZOOM_RATE;
this.pos_y += 3;
this.pos_x -= SIDES_RATE;
};
This is the Game Update part:
Game.update = function() {
this.player.move();
//creating bananas
if (objs.lenght <= 0) {
this.banana = new Banana();
} else {
for (i = 0; i < 10; i++) {
objs.push(new Banana());
}
}
//moving bananas
for (i = 0; i < objs.lenght; i++) {
this.objs[0].move();
}
};
Game Draw:
function Game.draw = function() {
this.context.drawImage(road, 0,0, rw, rh);
this.context.drawImage(
this.player.player_image,
this.player.pos_x, this.player.pos_y,
this.player.width, this.player.height);
this.context.drawImage(
this.banana.banana_image,
this.banana.pos_x, this.banana.pos_y,
this.banana.width, this.banana.height);
};
I tried to ask this to multiple people, but I can't find an answer for it.
Let's say you want to move the objects 10 times and then stop.
First you need to add a line to the start of Game.draw, so that it clears the canvas making you always start drawing from scratch:
this.context.clearRect(0,0,500,500); // clear canvas, adjust box size if needed
Then make a function to call both update and draw, and queue that function to be called again:
var count = 10;
function updateAndDraw() {
Game.update();
Game.draw();
count--;
if (count) requestAnimationFrame(updateAndDraw);
}
// start moving:
requestAnimationFrame(updateAndDraw);
The movement may go too fast to your liking, so then adjust the move method to make smaller changes, or use setTimeout instead of requestAnimationFrame (but that will make the animation less fluent).
Note that you have a few errors in your code, which you will need to fix first:
lenght should be length
function Game.draw = function() {: remove function before Game.draw.
... check the error messages you get in console.

Console error when drawing to canvas

I have a main javascript file which is trying to draw a tilemap to a canvas for a game, and i have an included file which actually draws the maps etc, but im getting this error in firebug:
TypeError: Value could not be converted to any of: HTMLImageElement, HTMLCanvasElement, HTMLVideoElement.
[Break On This Error]
ctx.drawImage(mapTiles[map[x][y]],x*tilesize, y*tilesize);
the main js which calls my level.js file looks like this:
$(document).ready(function(){
var canvas = document.getElementById("TBG");
var context = canvas.getContext("2d");
var ui = new Gui();
var level = new Level();
//----------Login/Register Gui --------------
$('#TBG').hide();
$('#load-new').hide();
$('#reg').hide();
$('#login').hide();
//if login_but is clicked do ui.login function
$('#login_but').click(ui.login);
//if reg_but is clicked do ui.register function
$('#reg_but').click(ui.register);
$('#new_but').click(function(){
game_settings("new");
});
$('#load_but').click(function(){
game_settings("load");
});
//if login_sumbit button is clicked do ui.login_ajax function
$("#login_submit").click(ui.login_ajax);
$("#reg_submit").click(ui.register_ajax);
$("#welcome").on("click", "#logout_but", ui.logout);
//____________________________________________
//Initialisation of game
function game_settings(state){
if(state == "load"){
ui.load_game();
//do ajax call to load user last save
//level.level_init(0,1);
draw();
}
else{
//set beginning params
//Change screens
ui.new_game();
alert("new game");
}
}
function draw () {
context.clearRect(0,0,canvas.width,canvas.height);
level.draw(context);
setTimeout(draw, 30);
}
// End Loop
});
and the file where this line of code (level.js) looks like this:
function Level(){
var tilesize = 32;
var map = 0;
var mapTiles = [];
// var saved_level = level;
//var saved_location = location;
map = [
[1,1,1,1,1,1,1,1,1,1],
[2,2,2,2,2,2,2,2,2,2]
];
for (x = 1; x <= 256; x++) {
var imageObj = new Image(); // new instance for each image
imageObj.src = "images/prototype/"+x+".jpg";
mapTiles.push(imageObj);
}
this.draw = function(ctx) {
for (var x = 0; x <= 31; x++){
for ( var y = 0; y <= 31; y++){
ctx.drawImage(mapTiles[map[x][y]],x*tilesize, y*tilesize);
}
}
};
}
Have any of you ever encountered this error?
and how would i correct the issue, thanks tom
Forget about canvas and everything else and look at the map array and the code that uses it. Let's rip out the canvas code and examine the array accesses with some console.log() calls:
map = [
[1,1,1,1,1,1,1,1,1,1],
[2,2,2,2,2,2,2,2,2,2]
];
console.log( map.length );
console.log( map[0].length );
for (var x = 0; x <= 31; x++){
for ( var y = 0; y <= 31; y++){
console.log( x, y, map[x], map[x] && map[x][y] );
}
}
Do you see the problem? You may be able to spot it by thinking about what those console.log() calls will print. If not, paste that code into the Chrome developer console and see what it does. (BTW, where the last argument has map[x] && map[x][y], that's essentially the same as map[x][y] but it protects the code from crashing when map[x] is undefined as you will see happen in the log.)
Now that we now that map[x][y] is undefined some of the time, go back to the drawImage() call, which uses this as the image argument:
mapTiles[ map[x][y] ]
When map[x][y] is undefined, what will that expression evaluate to?

Categories

Resources