JavaScript running pretty slow in specific computer - javascript

I writing a code that take a Black & White image and check the pixels in an specific area (with an square shape) and finally retur the sum of how many of them are balck, each pixel of the area is read in a For loop like the next example:
function is_box_black_corner(x,y,width,heigth){
var counter=0;
for (var i=x; i<(x+width); i++){
for (var j=y; j<(y+heigth); j++){
if(my_isblack(i,j)==1){
counter++;
}
}
}
And as you can see inside the for loop a I call a function that verifies if the specific pixel is fairly black:
function my_isblack(x,y){
var p = ctx.getImageData(x, y, 1, 1).data;
if(p[0]<50 && p[1]<50 && p[2]<50){
return 1;
}
else{
return 0;
}
}
As you can imagine, this is a little bit computational expensive. but the problem is that with my computer, suddenly it got much slower than others (even with worst processors). I already check the RAM memory and the processor and none of them were used more than 30%, and the processor before running the code is close to 0%.
And don’t know where else to look. I appreciate some help, also if somebody knows how to do this much faster it will be highly apreciated

I will try wiht one call to getImageData as suggested by #ASDFGerte:
var x=10; var y=10; var width=50; var height=50;
var counter=0;
var image;
var p; //global data
function init(){
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.fillStyle = "black";
ctx.fillRect(10, 10, 50, 50); //this is just a black square
image = ctx.getImageData(x, y, width, height); //Load the image
p = image.data; //get the data of the image
is_box_black_corner();
};
function is_box_black_corner(){
for (var i=x; i<(x+width); i++){
for (var j=y; j<(y+height); j++){
if(my_isblack(i,j)==1){
counter++;
}
}
}
console.log(counter);
};
function my_isblack(x,y){
if(p[0]<50 && p[1]<50 && p[2]<50){ //check the global data
return 1;
}
else{
return 0;
}
};

Related

How to show image when all sprites are collected p5js (play)

I'm coding a simple game in p5js with the play library in which a person wins after collecting all the "sprinkles". But I can't figure out how to show an image when all the sprinkles are collected. Can someone please help me out? I put the code parts in which the "sprinkles" and collect things happen because the total code is quite long.
function setup(){
sprinkles = new Group();
for(var i = 0; i <25; i++) {
var ang = random(360);
var px = SCENE_W/2 + 1000*cos(radians(ang));
var py = SCENE_H/2 + 1000*sin(radians(ang));
createSprinkles(2, px, py);
}
}
function draw(){
for(var j=0; j<sprinkles.length; j++) {
var s = sprinkles[j];
if(s.position.x<-MARGIN) s.position.x = SCENE_W+MARGIN;
if(s.position.x>SCENE_W+MARGIN) s.position.x = -MARGIN;
if(s.position.y<-MARGIN) s.position.y = SCENE_H+MARGIN;
if(s.position.y>SCENE_H+MARGIN) s.position.y = -MARGIN;
}
mouse.overlap(sprinkles, collect);
}
function createSprinkles(type, x, y){
var a = createSprite(x, y);
var img = loadImage('assets/sprinkles/sprinkle'+floor(random(0,5))+'.png');
a.addImage(img);
a.setSpeed(2.5-(type/2), random(360));
a.rotationSpeed = 0.5;
sprinkles.add(a);
}
function collect(collector, collected) {
collector.changeAnimation('stretch');
collector.animation.rewind();
collected.remove();
}
I've found it! I made a really dumb mistake... the dumbest one ever because I'm too tired. yay.
So if anyone is wondering about the same thing:
if(sprinkles.length<1){
background(255,200,0);
}
Here I tried a simple thing with the background colour to see if it works. Just add this code in the function draw(){} part and you're done!

Phaser JS walk up tile based stairs

I'm creating a small 2d-minecraft clone, in Phaser js, on my own as a learning experience. So far I have gotten player movement and random level seeds to work ok.
I am using Phasers P2JS engine and have sprites that are box based. What I'm struggling with now Is I want the player to be able to walk unhindered up small elevations, (1-tile high) but I don't have any good idea of how I should Implement this.
I have tried changing the bounding box of the player so that it had a slope at the bottom but this gets me in to a bunch of trouble with wall climbing. I want a way to do this where it gets as seamless as possible. Preferably the player speed is not altered much by climbing the steps.
I am concidering writing some kind of collision detection function to handle this but I am uncertain if this is the best way to do it.
Thanks for your help.
Below is my code and an image that shows the kind of step I want to beable to walk up. Its the first elevation to the left in the image.
var pablo = require('../generators/pablo.js');
var destiny = {};
var socket;
var player;
var jumpButton;
var levelCollisionGroup;
var playerCollisionGroup;
destiny.create = function () {
console.info("game loaded");
// World
this.game.world.setBounds(0, 0, 4000, 1000);
this.game.physics.startSystem(Phaser.Physics.P2JS);
this.game.physics.p2.gravity.y = 600;
this.game.physics.p2.applySpringForces= false;
this.game.physics.p2.applyDamping= false;
this.game.physics.p2.restitution = 0;
this.game.physics.p2.friction = 0.01;
// Player
playerCollisionGroup = this.game.physics.p2.createCollisionGroup();
player = this.game.add.sprite(this.game.world.centerX, 800, 'player');
this.game.physics.p2.enable(player,true);
player.body.fixedRotation = true;
player.body.setCollisionGroup(playerCollisionGroup);
player.body.mass = 2;
// Camera
this.game.camera.follow(player);
this.game.camera.deadzone = new Phaser.Rectangle(200, 0, 400, 100);
// Controls
jumpButton = this.game.input.keyboard.addKey(Phaser.Keyboard.SPACEBAR);
leftButton = this.game.input.keyboard.addKey(Phaser.Keyboard.A);
rightButton = this.game.input.keyboard.addKey(Phaser.Keyboard.D);
// Level
levelCollisionGroup = this.game.physics.p2.createCollisionGroup();
this.game.physics.p2.updateBoundsCollisionGroup();
for (i = 0; i < 280; i = i + 1) {
var block;
var height = pablo.getHeight(i);
for(j = 0; j < height; j = j + 1){
if(j === height-1){
block = this.game.add.sprite(15*i, 993-15*j, 'grass');
} else {
block = this.game.add.sprite(15*i, 993-15*j, 'dirt');
}
block.width = 15;
block.height = 15;
this.game.physics.p2.enable(block);
block.body.static=true;
block.body.immovable = true;
block.body.collides([levelCollisionGroup, playerCollisionGroup]);
block.body.setCollisionGroup(levelCollisionGroup);
if(j == height){
}
}
}
player.body.collides(levelCollisionGroup);
this.game.stage.backgroundColor = "#5599CC";
};
destiny.update = function() {
player.body.velocity.x=0;
if (leftButton.isDown) {
player.body.velocity.x = -200;
} else if (rightButton.isDown) {
player.body.velocity.x = 200;
}
if (jumpButton.isDown && this.checkIfCanJump()) {
player.body.velocity.y = -400;
}
};
destiny.render = function() {
this.game.debug.cameraInfo(this.game.camera, 32, 32);
this.game.debug.spriteCoords(player, 32, 550);
};
destiny.checkIfCanJump = function() {
var result = false;
for (var i=0; i < this.game.physics.p2.world.narrowphase.contactEquations.length; i++) {
var c = this.game.physics.p2.world.narrowphase.contactEquations[i];
if (c.bodyA === player.body.data || c.bodyB === player.body.data) {
var d = p2.vec2.dot(c.normalA, p2.vec2.fromValues(0, 1));
if (c.bodyA === player.body.data) {
d *= -1;
}
if (d > 0.5) {
result = true;
}
}
}
return result;
};
module.exports = destiny;
===================== Edit =====================
I have now tried creating slopes of the edge pieces when generating the world. But I realized that this makes me have to regenerate the world when I later add the feature for hacking away blocks. Thus this is not the solution. I think I will need to do some collision detection and move the player up when I hit an edge. But I'm not quite sure how to do this in phaser. Any help is still appreciated.
!!! Here is an image of what not to do !!!
Emanuele Feronato has a post on replicating the game Magick in Phaser.
There he covers the case of a block colliding with a barrier/wall, with the ability of the block to climb one level up.
You can check the tutorial, but what he appears to be doing is checking to see if the diagonal tile is empty (in other words, is it just a 'step' up), and if it is, running a 'jump' function, which looks more like a climb.
Depending upon how you want your character to step, you could potentially look at both the next tile (on the x-axis) as well as the one after it to check for the height.
So for example, if moving right and the next tile is flat, but the second tile has a step, you might start moving your character up on the y-axis.

Pixel manipulation and canvas

Is there a way in javascript to change the alpha channels of each pixel into being fully transparent (a=0) while coding for pixel manipulation (meaning that you can still change the transparency in some of the alpha channels as desired)?
Basically, what I'm doing is: given some data for a specific image, I manipulate the pixel array using an algorithm so that some pixels become fully transparent unless they satisfy some certain condition. In the case of them satisfying the condition I want them to be fully opaque, aka alpha=1. However, because of a complication with the way the algorithm works, I need to have my data "reset"; meaning I want the pixel array to start off as having every alpha = 0. I can provide code if that helps in better understanding the scope of my question.
Thanks so much.
EDIT: I'm looking more for a method/one-line code. Would context.globalAlpha = 0 serve the purposes? Is there any pitfall I should be careful about?
EDIT2: This is my code. Does globalAlpha where I've put it do what I'm expecting it to do? I'm not sure how to use it...
function getBoundary(imagedata){
var imageData = new Array(imagedata.data.length);
imageData = imagedata.data;
var w = imagedata.width;
var h = imagedata.height;
var color1 = [];
var colorRight = [];
var colorDown = [];
context.globalAlpha = 0;
for (var i = 0; i < 4*w*h; i +=4) {
color1 = [imageData[i],imageData[i+1],imageData[i+2]];
colorRight = [imageData[i+4],imageData[i+5],imageData[i+6]];
colorDown = [imageData[4*w+i],imageData[4*w+i+1],imageData[4*w+i+2]];
if(colorRight = [255,255,255]){ //if right is white
if(color1 = [0,0,0]){
imageData[i+3] = 255;
}
else{
if(colorDown = [0,0,0]){
imageData[4*w+i+3] = 255;
}
}
}
else{ //colorRight = black
if(color1 = [0,0,0]){
if(colorDown = [255,255,255]){
imageData[i+3] = 255;
}
}
else if(color1 = [255,255,255]){
imageData[i+7] = 255;
if(colorDown = [0,0,0]){
imageData[4*w+i+3] = 255;
}
else{
}
}
}
}
console.log("done");
imagedata.data = imageData;
return imagedata;
}
You can use getImageData and flip all the alpha elements to zero:
You can create a function that zeros the alpha of all pixels on the canvas like this:
function zeroAllAlpha(){
var imageData=context.getImageData(0,0,canvas.width,canvas.height);
var data=imageData.data;
// set all alpha elements to zero (fully transparent);
for(var i=3;i<data.length;i+=4){
data[i]=0;
}
context.putImageData(imagedata,0,0);
}
And you can call the function with one line like this:
zeroAllAlpha();

HTML5 canvas break up image

My overall aim is to make a sliding puzzle piece game. Using the canvas, I have managed to split up the image into multiple pieces. In order to shuffle the pieces, I wrote the co-ordinates of the pieces into an array, shuffled the co-ordinates, and re-drew the image on the canvas. However, the puzzle ends up with some pieces being duplicated! I have no idea why?!
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById("map");
//img,sx,sy,swidth,sheight,x,y,width,height
function recreate_map(){
ctx.drawImage(img,0,0,133,100,0,0,133,100);
ctx.drawImage(img,133,0,133,100,133,0,133,100);
ctx.drawImage(img,266,0,133,100,266,0,133,100);
ctx.drawImage(img,0,100,133,100,0,100,133,100);
ctx.drawImage(img,133,100,133,100,133,100,133,100);
ctx.drawImage(img,266,100,133,100,266,100,133,100);
ctx.drawImage(img,0,200,133,100,0,200,133,100);
ctx.drawImage(img,133,200,133,100,133,200,133,100);
ctx.drawImage(img,266,200,133,100,266,200,133,100);
}
function shuffle_array(arr){
var i = arr.length;
while(--i>0){
var n = Math.floor(Math.random()*(i));
var temp = arr[n];
arr[n] = arr[i];
arr[i] = temp;
}
return arr;
}
function shuffle_tiles(){
var positions_x = [0,133,266,0,133,266,0,133,266];
var positions_y = [0,0,0,100,100,100,200,200,200];
shuffle_array(positions_x);
shuffle_array(positions_y);
ctx.drawImage(img,0,0,133,100,positions_x[0],positions_y[0],133,100);
ctx.drawImage(img,133,0,133,100,positions_x[1],positions_y[1],133,100);
ctx.drawImage(img,266,0,133,100,positions_x[2],positions_y[2],133,100);
ctx.drawImage(img,0,100,133,100,positions_x[3],positions_y[3],133,100);
ctx.drawImage(img,133,100,133,100,positions_x[4],positions_y[4],133,100);
ctx.drawImage(img,266,100,133,100,positions_x[5],positions_y[5],133,100);
ctx.drawImage(img,0,200,133,100,positions_x[6],positions_y[6],133,100);
ctx.drawImage(img,133,200,133,100,positions_x[7],positions_y[7],133,100);
ctx.drawImage(img,266,200,133,100,positions_x[8],positions_y[8],133,100);
}
If it helps, I'm using JS Bin, on Firefox. Thanks.
You need to clear the canvas for each redraw or else the previous content will remain.
Try this:
function recreate_map(){
/// call this first
ctx.clearRect(0, 0, c.width, c.height);
ctx.drawImage(img,0,0,133,100,0,0,133,100);
...

HTML 5 Canvas Image Rendering

First time poster here but definitely not a first time reader.
My question is aimed directly at this portion of code I have. I am currently learning how HTML 5 canvases work and am designing my own RPG style game for a University project. After looking around I found some good tutorials on this guys blog, I have followed his code and triple checked it but images are now showing up.
I tried putting an alert() before and after when the image is called to the canvas under drawMap(). It works before the image is drawn but not after, leading me to believe it is something to do with my image rendering. Can someone double check my code and see what is going on? It's driving me insane!
<canvas id="game-viewport" width="760" height="440"></canvas>
<script>
window.onload = init;
var map = Array([0,0],[0,0],[0,0],[0,0]);
var tileSize = 40;
tileTypes = Array("grass.png");
tileImage = new Array();
var loaded = 0;
var loadTimer;
function loadImage(){
for(i = 0; i < tileTypes.length; i++){
tileImage[i] = new Image();
tileImage[i].src = "./game/lib/icons/own_icons/" + tileTypes[i];
tileImage[i].onload = function(){
loaded++;
}
}
}
function loadAll(){
if(loaded == tileTypes.length){
clearInterval(loadTimer);
drawMap();
}
}
function drawMap(){
var mapX = 80;
var mapY = 10;
for(i = 0; i < map.length; i++){
for(j = 0; j < map[i].length; j++){
var drawTile = map[i][j];
var xPos = (i - j) * tileSize;
var yPos = (i + j) * tileSize;
ctx.drawImage(tileImage[drawTile], xPos, yPos);
}
}
}
function init(){
var canvas = document.getElementById('game-viewport')
var ctx = canvas.getContext('2d');
loadImage();
loadTimer = setInterval(loadAll, 100);
}
</script>
The only problem is that ctx is not defined in your drawMap function.
Either pass ctx in to the function as an argument or make it a global variable.
I was lazy and did the second, but you should really do the first. Working code:
http://jsfiddle.net/YUddC/
You really should have the Chrome debugger (or whatever browser you use) on 100% of the time you're developing.. If you did, you'd see an error saying that ctx is not defined in drawMap. If you're using Chrome and press F12 to open developer tools and go to the scripts tab, you'd see this:
Which makes the problem pretty clear!

Categories