Here's the code, below is a link to the jsfiddle.
The first row of the block isn't drawn for some reason, all these 2 dimension for loops are hard for me to wrap my head around, and can't find the reason why the block is only being drawn from the second row and not complete.
The add_block function is supposed to read array data from any block and put it on the grid where my x and y coordinates are.
If there's anyone who knows how to rotate the block, that would be cool too, i know in order to turn something +90 degrees i need to transpose and then revese each row, but it hasn't really worked in earlier tries.
I know i'm not good at explaining but i'll be sure to answer any of your questions.
Thanks in advance! I really want to have a complete picture of how arrays and double for loops interact with eachother, in my head.
var canvas = document.getElementById('c');
var ctx = canvas.getContext('2d');
canvas.width = 300;
canvas.height = 500;
var grid_columns = 10;
var grid_rows = 15;
var grid_cell_size = 10;
var grid = [];
function create_empty_grid(){
for(var i=0;i<grid_columns;i++){
grid[i] = [];
for(var j=0;j<grid_rows;j++){
grid[i][j] = 0;
}
}
// END DOUBLE FOR LOOPS
}
function clear_grid(){
for(var i=0;i<grid_columns;i++){
for(var j=0;j<grid_rows;j++){
grid[i][j] = 0;
}
}
// END DOUBLE FOR LOOPS
}
var x = 0;
var y = 0;
var w = 2;
var h = 3;
var block = [];
block[0] = [
[1,0,0,0],
[1,1,0,0],
[0,1,0,0],
[0,0,0,0]
];
function add_block(num){
var b = block[num];
for(var i=0;i<w;i++){
for(var j=0;j<h;j++){
if(i >= x && j >= y && i <= w && j <= h){
grid[i][j] = b[i][j];
}
}
}
// END DOUBLE FOR LOOPS
}
function draw(){
for(var i=0;i<grid_columns;i++){
for(var j=0;j<grid_rows;j++){
ctx.fillStyle = "black";
if(grid[i][j] === 1){
ctx.fillStyle = "red";
}else if(grid[i][j] === 0){
ctx.fillStyle = "green";
}
ctx.fillRect(i*grid_cell_size,j*grid_cell_size,grid_cell_size-1,grid_cell_size-1);
}
}
// END DOUBLE FOR LOOP
}
function update(){
}
function tick(){
clearRect(0,0,canvas.width,canvas.height);
clear_grid();
draw();
update();
}
create_empty_grid();
add_block(0);
draw();
View in jsfiddle
It seems like you're using i and j to represent "block" coordinates, and
x and y to represent "grid" coordinates. So I think this condition is wrong:
if(i >= x && j >= y && i <= w && j <= h){
grid[i][j] = b[i][j];
}
I think all you really need here is to replace the if statement with something like:
grid[i+x][j+y] = b[i][j];
But as #Arnauld pointed out, there is also a bit of confusion about whether i,j denotes "row, column" or "column, row", and it looks like your usage is opposite from the way the arrays are initialized. In other words, you're using:
grid[row][column] and b[row][column]
but the way you laid out the arrays, it needs to be
grid[column][row] and b[column][row]
So you'll need to make a few adjustments here and there to make the code do what you want.
The "b" arrays were upside-down for some reason so i changed grid[j+x][i+y] = b[j][i] to grid[j+x][i+y] = b[i][j] this displays the full block, but i still can't visualise the arrays or be able to prevent these problems in the future.
Arrays are so confusing to me.
I'll figure it out eventually i guess, but a day has to go by.
I'm trying to load a map from a image, I get the hex codes for every pixel on my image, which is put into map[]. The world[] will store 1 or 0 or whatever number for number of sprite on the spritesheet. If the color is #8aff00 then it will store 0 for grass. The map is 16 by 16 pixels, which is my world size. When I try to make the world array, the for statement is working right, there is no errors. I know I have all the data, but this part of my function is not working, it just stops after these for statements:
function createWorld() {
for (var y=0; y < worldHeight; y++) {
for (var x=0; x < worldWidth; x++) {
if (map[pl] == '#8aff00') world[x][y] = 0;
if (map[pl] == '#000000') world[x][y] = 1;
pl+=4;
}
}
alert('about to draw');
draw();
}
The alert never gets called. When I displayed the x and y, it went '0,0' to '1,0' then back to '0,0' for the value x and y. The pl is for which number of the array I want. When I put another for statement to handle that it messed up more. Is there something wrong with the code, if you need more of the code just let me know.
I've managed to build code which is working.
Now it's Your turn to implement it as You need.
worldHeight = 16;
worldWidth = 16;
world = {};
map = ['#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000','#8aff00','#000000']
pl = 0
function draw(){
console.log(world);
}
function createWorld() {
for (var y=0; y < worldHeight; y++) {
for (var x=0; x < worldWidth; x++) {
if (map[pl] == '#8aff00')
world[x] = 0;
world[x][y] = 0;
if (map[pl] == '#000000')
world[x] = 0;
world[x][y] = 1;
pl+=4;
}
}
alert('about to draw');
draw();
}
createWorld();
Cheers.
How would one zoom in a Canvas to see the pixels? Currently when I try to use the scale() function the image is always antialiased.
The property mozImageSmoothingEnabled seems to work, but it's only for Firefox.
As far as I know any rescaling done by the browser will result in a smooth interpolation.
So as long as you want to do this with JS you will have to let JS do all the work. This means either finding a nice library or writing a function yourself. It could look like this. But I hope it's possible to make it faster. As it's one of the simplest scaling algorithms there are probably many people who thought up improvements to do it even faster.
function resize(ctx, sx, sy, sw, sh, tx, ty, tw, th) {
var source = ctx.getImageData(sx, sy, sw, sh);
var sdata = source.data;
var target = ctx.createImageData(tw, th);
var tdata = target.data;
var mapx = [];
var ratiox = sw / tw, px = 0;
for (var i = 0; i < tw; ++i) {
mapx[i] = 4 * Math.floor(px);
px += ratiox;
}
var mapy = [];
var ratioy = sh / th, py = 0;
for (var i = 0; i < th; ++i) {
mapy[i] = 4 * sw * Math.floor(py);
py += ratioy;
}
var tp = 0;
for (py = 0; py < th; ++py) {
for (px = 0; px < tw; ++px) {
var sp = mapx[px] + mapy[py];
tdata[tp++] = sdata[sp++];
tdata[tp++] = sdata[sp++];
tdata[tp++] = sdata[sp++];
tdata[tp++] = sdata[sp++];
}
}
ctx.putImageData(target, tx, ty);
}
This function would take the rectangle of size (sw,sh) at (sx,sy), resize it to (tw,th) and draw it at (tx,ty).
As far as I know the antialiasing behavior is not defined in the spec and will depend on the browser.
One thing you could try is if you set the canvas's width/height with CSS into for example 300x300 and then give the canvas width and height attributes of 150 and 150, it will appear "zoomed in" by 200%. I'm not sure whether this will trigger the antialiasing, but do give it a shot.