HTML5 Canvas drawImage only draws after second refresh - javascript

OK, I have a HTML5 canvas... and it draws images from .png tiles (32x32). It works. Sort of. It only draws on the canvas after the second refresh. For example, if you were to load it up... al you would see is a red canvas (the background for #canvas is red) then if you were to refresh it... it would be successfully draw the images... why is that?
Here is the code. (All you need is two images. t0.png and t1.png in line_tiles folder) But I am sure you can spot the error right away that I can't :P
game.js
// HTML5 JS Tile Example
var canvas, context, board, imageObj, tiles;
var currentMap = 1;
var upMap = 0;
var rightMap = 0;
var leftMap = 0;
var downMap = 3;
var NUM_OF_TILES = 1; // starting from ZERO
// Set return 2D array of map
function loadMap(map) {
if (map == 1) {
return [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]];
}
}
// On load...
window.onload = function () {
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
imageObj = new Image();
tiles = [];
board = loadMap(1);
canvas.width = 512;
canvas.height = 352;
// 2. SET UP THE MAP TILES
for (x = 0; x <= NUM_OF_TILES; x++) {
imageObj = new Image(); // new instance for each image
imageObj.src = "line_tile/t" + x + ".png";
tiles.push(imageObj);
}
var theX;
var theY;
// 3. DRAW MAP BY ROWS AND COLS
for (x = 0; x <= 10; x++) {
for (y = 0; y <= 15; y++) {
theX = x * 32;
theY = y * 32;
context.drawImage(tiles[board[x][y]], theY, theX, 32, 32);
}
}
};
index.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<title>HTML5</title>
<script type="text/javascript" src="game.js"></script>
<style type="text/css">
<!--
#canvas {
background:red;
z-index:0;
position:relative;
}
.container {
width: 512px;
position: relative;
}
-->
</style>
</head>
<body>
<div class="container">
<canvas id="canvas"></canvas>
</div>
</body>
</html>

You need to add onload hooks on your images (the tiles) and draw only when all images are loaded.
Here's a suggestion :
// HTML5 JS Tile Example
var canvas, context, board, imageObj, tiles;
var currentMap = 1;
var upMap = 0;
var rightMap = 0;
var leftMap = 0;
var downMap = 3;
var NUM_OF_TILES = 1; // starting from ZERO
// Set return 2D array of map
function loadMap(map) {
if (map == 1) {
return [
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]];
}
}
// On load...
window.onload = function () {
canvas = document.getElementById("canvas");
context = canvas.getContext("2d");
imageObj = new Image();
tiles = [];
board = loadMap(1);
canvas.width = 512;
canvas.height = 352;
var draw = function() {
var theX;
var theY;
// 3. DRAW MAP BY ROWS AND COLS
for (x = 0; x <= 10; x++) {
for (y = 0; y <= 15; y++) {
theX = x * 32;
theY = y * 32;
context.drawImage(tiles[board[x][y]], theY, theX, 32, 32);
}
}
}
var loadedImagesCount = 0;
// 2. SET UP THE MAP TILES
for (x = 0; x <= NUM_OF_TILES; x++) {
var imageObj = new Image(); // new instance for each image
imageObj.src = "line_tile/t" + x + ".png";
imageObj.onload = function() {
loadedImagesCount++;
if (loadedImagesCount==NUM_OF_TILES) draw();
};
tiles.push(imageObj);
}
};
And be careful not to forget the var keyword (look at the loop).

Related

Javascript 2d tilemap without drawing all tiles

I am creating a 2D platformer in JavaScript. I am trying to create a tilemap that does not spawn in blocks where there is supposed to be air (labeled 0 in tilemap). I do not get any errors. However, no blocks are spawned in the canvas. The game also crashes unless i remove the collision detection.
Main js
//drawing variables
var canvas;
var context;
//game variables
var gameLoop;
var player;
var borders = [];
var mapHeight = 12;
var mapWidth = 22;
var tilesize = 50;
//input variables
var upKey;
var rightKey;
var downKey;
var leftKey;
//runs once pace has been loaded
window.onload = function(){
//canvas and context variable setup
canvas = document.getElementById("gameCanvas")
context = canvas.getContext("2d")
//key listeners
setupInputs();
//create player
player = new Player(400, 400);
//create border
let tilemap = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
]
//create a box (border) based on tilemap position. Let 0's be air
for (let row = 0; row < mapHeight; row++){
for(let col = 0; col < mapWidth; col++){
if(tilemap[row][col] !== 0){
borders.push(new Border(tilemap[row]*tilesize, tilemap[col]*tilesize, tilesize, tilesize, tilemap[row][col]));
}
}
}
//initialize main game loop. Framerate = 30/sec
gameLoop = setInterval(step, 1000/30);
//draw canvas
context.fillStyle = "#f4f4f4f4"
context.fillRect(0, 0, mapWidth*tilesize, mapHeight*tilesize);
}
function step(){
player.step();
//draw after updates
draw();
}
function draw(){
//Clear previous canvas
context.fillStyle = "#f4f4f4f4"
context.fillRect(0, 0, mapWidth*tilesize, mapHeight*tilesize);
//draw the player
player.draw();
//draw borders
for(let i = 0; i < borders.length; i++){
borders[i].draw();
}
}
//keyboard inputs
function setupInputs(){
document.addEventListener("keydown", function(event){
if(event.key === "w"){
upKey = true;
} else if(event.key === "a"){
leftKey = true;
} else if(event.key === "s"){
downKey = true;
} else if(event.key === "d"){
rightKey = true;
}
});
document.addEventListener("keyup", function(event){
if(event.key === "w"){
upKey = false;
} else if(event.key === "a"){
leftKey = false;
} else if(event.key === "s"){
downKey = false;
} else if(event.key === "d"){
rightKey = false;
}
});
}
//Checking to see if player and border intersect
function checkIntersection(r1, r2){
if (r1.x >= r2.x + r2.width){
return false;
} else if (r1.x + r1.width <= r2.x){
return false;
} else if (r1.y >= r2.y + r2.height){
return false;
} else if (r1.y + r1.height <= r2.y){
return false;
} else {
return true;
}
}
Player js
function Player(x, y){
//Player variables
this.x = x;
this.y = y;
this.xvel = 0;
this.yvel = 0;
this.friction = 0.6;
this.maxVel = 12;
this.width = tilesize;
this.height = tilesize;
this.active = true;
this.falling = false;
this.step = function(){
if(this.active){
if(!leftKey && !rightKey || leftKey && rightKey){
this.xvel *= this.friction;
} else if (rightKey){
this.xvel++;
} else if (leftKey){
this.xvel--;
}
if(upKey){
//check if standing on ground
if (this.yvel === 0 && this.falling === false){
this.yvel -= 70;
this.falling = true;
} else{
this.yvel += 0;
}
}
this.yvel += 1;
//not allowing velocity to surpass maximum velocity
if (this.xvel > this.maxVel){
this.xvel = this.maxVel;
} else if(this.xvel < -this.maxVel){
this.xvel = -this.maxVel;
}
if (this.yvel > this.maxVel){
this.yvel = this.maxVel;
} else if(this.yvel < -this.maxVel){
this.yvel = -this.maxVel;
}
if (this.xvel > 0){
this.xvel = Math.floor(this.xvel);
} else {
this.xvel = Math.ceil(this.xvel);
}
if (this.yvel > 0){
this.yvel = Math.floor(this.yvel);
} else {
this.yvel = Math.ceil(this.yvel);
}
//collision rectangles
let horizontalRect = {
x: this.x + this.xvel,
y: this.y,
width: this.width,
height: this.height
}
let verticalRect = {
x: this.x,
y: this.y + this.yvel,
width: this.width,
height: this.height
}
//Collision deteQction
for(let i = 0; i<borders.length; i++){
let borderRect = {
x: borders[i].x,
y: borders[i].y,
width: borders[i].width,
height: borders[i].height
}
if (checkIntersection(horizontalRect, borderRect)){
while (checkIntersection(horizontalRect, borderRect)){
horizontalRect.x -= Math.sign(this.xvel);
}
this.x = horizontalRect.x;
this.xvel = 0;
}
if (checkIntersection(verticalRect, borderRect)){
while(checkIntersection(verticalRect, borderRect)){
verticalRect.y -= Math.sign(this.yvel);
}
this.y = verticalRect.y;
this.yvel = 0;
this.falling = false;
}
}
if (this.x + this.xvel > mapWidth*tilesize - tileisze){
this.xvel = 0;
}
if (this.x + this.xvel < 0){
this.xvel = 0;
}
this.x += this.xvel;
this.y += this.yvel;
}
}
this.draw = function(){
context.fillStyle = "orange";
context.fillRect(this.x, this.y, this.width, this.height);
}
}
Border js
function Border(x, y, width, height, type){
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.type = type;
this.draw = function(){
if (this.type === 1){
context.fillStyle = "#2C2C34";
} else if (this.type === 2){
context.fillStyle = "#39393A";
}
context.fillRect(this.x, this.y, this.width, this.height);
}
}
There seems to be several errors in your code and it may take a while to find them all. You hex colors have 8 characters "#f4f4f4f4". You have a map width of 22 but only have 21 columns in the 2D array. It also seems off that when you are creating your borders array you have rows in the x spot and col in the y spot. I seems like it should be reversed. Anyway if you're not opposed to using a 1D array here is a simplified version of you code without the player stuff.
Border
function Border(type, x, y){
this.x = x;
this.y = y;
this.width = TILE_SIZE;
this.height = TILE_SIZE;
this.type = type;
this.draw = function(){
if (this.type === 1){
context.fillStyle = "purple";
context.fillRect(this.x, this.y, this.width, this.height);
} else if (this.type === 2){
context.fillStyle = "orange";
context.fillRect(this.x, this.y, this.width, this.height);
}
}
}
and the main file
const canvas = document.getElementById("canvas")
const context = canvas.getContext("2d")
const TILE_SIZE = 25; //50 was too big for my screen based on how many rows/columns you wanted
canvas.width = 525; //TILE_SIZE * columns
canvas.height = 300; //TILE_SIZE * rows
var borders = [];
let tileMap = {
mapHeight: 12,
mapWidth: 21,
size: TILE_SIZE,
grid: [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 2, 0, 2, 2, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0,
0, 0, 2, 2, 2, 2, 0, 0, 2, 0, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 2, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 2, 0, 0, 2, 0, 2, 2, 2, 0, 2, 0, 2, 0, 2, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
]
}
//Uses 1 loop to create the grid
function createGrid() {
for (let i = 0; i < tileMap.grid.length; i++) {
let x = (i % tileMap.mapWidth) * tileMap.size;
let y = Math.floor((i / tileMap.mapWidth)) * tileMap.size;
let type = tileMap.grid[i];
borders.push(new Border(type, x, y));
}
};
createGrid(); //creates the grid when file is loaded
function animate() {
context.clearRect(0, 0, canvas.width, canvas.height);
for(let i = 0; i < borders.length; i++){
borders[i].draw();
}
requestAnimationFrame(animate);
}
animate()
I stuck the for loop in the animate function only for this example. Normally it would be its own function and that is where you can handle collision detection or drawing tiles or anything else you want to do with them.
If you must use a 2d array here is a function that will create it
function createGrid() {
for (let row = 0; row < tileMap.mapHeight; row++) {
for (let col = 0; col < tileMap.mapWidth; col++) {
let type = tileMap.grid[row][col];
let x = col * TILE_SIZE;
let y = row * TILE_SIZE;
borders.push(new Border(type, x, y))
}
}
}
createGrid()
Be sure to change the map back to 2d if you use the one I posted above. I also noticed in your player file you have tileisze at one point instead of tilesize. I would take some time to carefully scrub your files for errors as these may be the cause of some of your problems.

Fps for a tile map does not show up

I'm trying to make the fps on my simple tile map show up (top right) but for some reason it does not appear on the browser when I load it. I have been following the tutorial of Technologies4 me on youtube and have just a few different adjustments to the code. I am a beginner so it might be a typo, but I would really appreciate some help.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<canvas id="game" width="600" height="300"></canvas>
<script>
var ctx=null;
var tileW=30, TileH=30;
var mapW=20, mapH=10;
var currentSecond= 0, frameCount=0, framesLastSecond=0;
var gameMap=[
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,3,3,0,0,3,3,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,3,3,0,0,0,0,0,
0,0,0,0,2,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,2,2,2,2,2,2,2,0,0,0,0,0,0,2,0,0,2,
1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,
];
window.onload=function(){
ctx=document.getElementById("game").getContext("2d");
requestAnimationFrame(drawGame);
ctx.font="bold 10px sans-serif";
};
function drawGame(){
if(ctx==null){return;}
var sec=Math.floor(Date.now()/1000);
if(sec!=currentSecond){
currentSecond=sec;
framesLastSecond=frameCount;
frameCount=1;
}
else{frameCount++;}
for(var y=0; y<mapH; y++){
for(var x=0; x<mapW; x++){
switch(gameMap[((y*mapW)+x)]){
case 0:
ctx.fillStyle="White";
break;
default:
ctx.fillStyle="Green";
}
ctx.fillRect(x*tileW,y*TileH,tileW,TileH);
}
}
ctx.fillStyle="Red";
ctx.fillText=("FPS: "+framesLastSecond, 10, 20);
requestAnimationFrame(drawGame);
}
</script>
</body>
</html>
It's just a typo. ctx.fillText is a function, but you are assigning to it instead of calling it.
Remove the = in ctx.fillText=("FPS: "+framesLastSecond, 10, 20);:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<canvas id="game" width="600" height="300"></canvas>
<script>
var ctx = null;
var tileW = 30,
TileH = 30;
var mapW = 20,
mapH = 10;
var currentSecond = 0,
frameCount = 0,
framesLastSecond = 0;
var gameMap = [
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0,
0, 0, 0, 0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 2,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1,
];
window.onload = function() {
ctx = document.getElementById("game").getContext("2d");
ctx.font = "bold 10px sans-serif";
requestAnimationFrame(drawGame);
};
function drawGame() {
if (ctx == null) {
return;
}
var sec = Math.floor(Date.now() / 1000);
if (sec != currentSecond) {
currentSecond = sec;
framesLastSecond = frameCount;
frameCount = 1;
} else {
frameCount++;
}
for (var y = 0; y < mapH; y++) {
for (var x = 0; x < mapW; x++) {
switch (gameMap[((y * mapW) + x)]) {
case 0:
ctx.fillStyle = "White";
break;
default:
ctx.fillStyle = "Green";
}
ctx.fillRect(x * tileW, y * TileH, tileW, TileH);
}
}
ctx.fillStyle = "Red";
ctx.fillText("FPS: " + framesLastSecond, 10, 20);
requestAnimationFrame(drawGame);
}
</script>
</body>
</html>
Change this:
ctx.fillText=("FPS: "+framesLastSecond, 10, 20);
to this:
ctx.fillText("FPS: "+framesLastSecond, 10, 20);

Why fillText doesn't show up in canvas?

Tried changing the fillStyle color to many different ones, also different positions but nothing. No errors in console either. I already have tileset and sprites drawn on the canvas, does that has anything to do with it? I just need to print out a simple text on every character move on key press.
Here is the code:
function move(e) {
if (e.keyCode == 39) {
boatPosX += 5;
view.x -= 5
moveCount++;
context.fillStyle = "red";
context.fillText(theArray[0].question, 0, 0);
console.log(theArray[0].question);
}
The rest of the code:
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
var view = {x: 0, y: 0};
var questionsArray = [];
var moveCount = 0;
var mapArray = [
[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 1, 1, 1, 0, 0, 2, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 2, 2, 0],
[0, 0, 1, 1, 1, 0, 0, 2, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
];
function isPositionWall(ptX, ptY) {
var gridX = Math.floor(ptX / 36)
var gridY = Math.floor(ptY / 36)
if(gridX < 0 || gridX >= mapArray[0].length)
return true;
if(gridY < 0 || gridY >= mapArray.length)
return true;
return mapArray[gridX][gridY];
}
var theArray = [];
var Question = function(question, answer1, answer2, correctAnswer) {
this.question = question;
this.answer1 = answer1;
this.answer2 = answer2;
this.correctAnswer = correctAnswer;
this.addToArray = function(){
theArray.push(this);
};
this.addToArray();
}
Question.prototype.checkAnswer = function() {
return answer1 || answer2 == correctAnswer;
}
var question1 = new Question("Taip ar ne?", "Taip", "Ne", "Taip");
var question2 = new Question("Jo ar ne?", "Ne", "Jo", "Jo");
var question3 = new Question("Aha ar ne?", "Aha", "Ne", "Ne");
var question4 = new Question("Ja ar ne?", "Taip", "Ne", "Taip");
var question5 = new Question("Jojo ar ne?", "Taip", "Ne", "Taip");
var question6 = new Question("Taip ar ne?", "Taip", "Ne", "Taip");
var question7 = new Question("Taip ar ne?", "Taip", "Ne", "Taip");
var StyleSheet = function(image, width, height, x, y) {
this.image = image;
this.width = width;
this.height = height;
this.x = x;
this.y = y
this.draw = function(image, sx, sy, swidth, sheight, x, y, width, height) {
context.drawImage(image, sx, sy, swidth, sheight, x, y, width, height);
};
this.drawimage = function(image, x, y, width, height) {
context.drawImage(image, x, y, width, height);
};
};
/* Initial Sprite Position */
var boatPosX = canvas.height/2 - 50;
var boatPosY = canvas.height/2 - 50;
function render(viewport) {
context.save();
context.translate(view.x, view.y);
requestAnimationFrame(render);
var oldPosX = boatPosX;
var oldPosY = boatPosY;
for (let i = 0; i < mapArray.length; i++) {
for (let j = 0; j < mapArray[i].length; j++) {
if (mapArray[i][j] == 0) {
this.sprite.draw(
background,
190,
230,
26,
26,
i * this.sprite.width,
j * this.sprite.height,
this.sprite.width,
this.sprite.height
);
}
if (mapArray[i][j] == 1) {
this.sprite.draw(
background,
30,
30,
26,
26,
i * this.sprite.width,
j * this.sprite.height,
this.sprite.width,
this.sprite.height
);
}
if (mapArray[i][j] == 2) {
this.sprite.draw(
background,
200,
20,
26,
26,
i * this.sprite.width,
j * this.sprite.height,
this.sprite.width,
this.sprite.height
);
}
}
}
this.ship.drawimage(boat, boatPosX, boatPosY, 50, 50);
//console.log(boatPosX + ship.width)
if(isPositionWall(boatPosX, boatPosY)) {
boatPosX = oldPosY;
console.log("collision");
}
context.restore();
};
function move(e) {
if (e.keyCode == 39) {
boatPosX += 5;
//canvas.width += 2;
view.x -= 5
moveCount++;
console.log(moveCount);
console.log("right");
context.fillStyle = "red";
context.fillText(theArray[0].question, 0, 0);
console.log(theArray[0].question);
}
if (e.keyCode == 37) {
boatPosX -= 5;
view.x += 5
moveCount++;
console.log(moveCount);
console.log("left");
}
if (e.keyCode == 38) {
boatPosY -= 5;
view.Y += 5
moveCount++;
console.log(moveCount);
console.log("up");
}
if (e.keyCode == 40) {
boatPosY += 5;
view.Y += 5
moveCount++;
console.log(moveCount);
console.log("down");
}
}
document.onkeydown = move;
var background = new Image();
background.src = "ground.png";
var sprite = new StyleSheet(background, 36, 36, 16, 16);
var boat = new Image();
boat.src = "ship.png";
var ship = new StyleSheet(boat, 90, 100, 16, 16);
console.log(Math.floor(boatPosX / 36));
console.log(mapArray[Math.floor(boatPosX / 36)]);
render();
Seems to be because you are trying to put the text at 0,0. By default the text will be drawn above the Y position of 0 (so off the top of the canvas which is why you don't see anything). If you made it 0,10 or 0,20 then you will probably see some text.
It is possible to change the text base line like this, so at 0,0 you will see something..
context.textBaseline = "top";

How to check canvas element (pixel matrix) contains another canvas element inside

I have 2 matrix, which are the result of several arrays of pixels from 2 images.
I need to detect when the canvas element of matrix 2 is inside or steps on the edge of element 1 (rectangle of matrix 1), at this moment it must notify the user "match detected!"
My code to create matrix 1 and 2:
var matrix = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];
var matrix2 = [
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 1, 1, 1, 0, 0, 0],
[1, 1, 0, 1, 0, 0, 0, 1, 0, 0],
[1, 0, 0, 1, 0, 0, 0, 1, 0, 0],
[0, 0, 1, 1, 1, 0, 0, 1, 0, 0],
[0, 0, 0, 1, 0, 0, 1, 1, 1, 0],
[0, 0, 0, 1, 0, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 0, 0, 1, 1, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
];
var contFilas = matrix.length;
var contColumnas = matrix[0].length;
var canvas = document.querySelector("canvas");
var ctx = canvas.getContext("2d");
var sz = 20;
var regions = [];
var regionCollection = [];
canvas.width = sz * contColumnas;
canvas.height = sz * contColumnas;
ctx.fillStyle = "silver";
ctx.fillRect(0, 0, canvas.width, canvas.height);
for (var y = 0; y < contFilas; y++) {
var regionline = [];
regions.push(regionline);
for (var x = 0; x < contColumnas; x++) {
var pixelRegion = 0;
regionline[x] = 0;
if (matrix[y][x] === 1) {
// check previous row
if (y) {
if (matrix[y - 1][x]) {
pixelRegion = regions[y - 1][x];
} else if (x && matrix[y - 1][x - 1]) {
pixelRegion = regions[y - 1][x - 1];
} else if (x + 1 < contColumnas && matrix[y - 1][x + 1]) {
pixelRegion = regions[y - 1][x + 1];
}
}
// check current row
if (x && matrix[y][x - 1]) {
pixelRegion = regions[y][x - 1];
}
// if not connected, start a new region
if (!pixelRegion) {
regionCollection.push([]);
pixelRegion = regionCollection.length;
}
// remember region
regionline[x] = pixelRegion;
regionCollection[pixelRegion - 1].push([x, y]);
// paint it
ctx.fillStyle = "black";
ctx.fillRect(x * sz + 1, y * sz + 1, sz - 2, sz - 2);
}
ctx.fillStyle = "white";
ctx.fillText(pixelRegion, x * sz + 8, y * sz + 13);
}
}
document.querySelector("#result").innerHTML = JSON.stringify(regionCollection);
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>getUserMedia</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
</head>
<body>
<canvas></canvas>
<div id="result"></div>
<div id="result2"></div>
</body>
</html>
How can I do this? detect when there is an element inside or touching rectangle 1 (matrix)?

Practicing 2D Arrays

I'm writing a script that will generate a square room within a larger map. The code looks like this:
var mapSize = 10;
var map = [];
for (var x = 0; x < mapSize; x++) {
map[x] = [];
for (var y = 0; y < mapSize; y++) {
map[x][y] = 0
};
};
//Make square room within map
var roomSize = 3;
var roomType = "Kitchen"
var paintRoom = function(mapX, mapY) {
for (var j = 0; j < roomSize; j++) {
map[mapX + j][mapY] = roomType;
map[mapX][mapY + j] = roomType;
};
};
paintRoom(3, 4);
console.log(map);
The result that I want is this:
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, "Kitchen", "Kitchen", "Kitchen", 0, 0, 0],
[0, 0, 0, 0, "Kitchen", "Kitchen", "Kitchen", 0, 0, 0],
[0, 0, 0, 0, "Kitchen", "Kitchen", "Kitchen", 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
But instead I end up with this:
[
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, "Kitchen", "Kitchen", "Kitchen", 0, 0, 0],
[0, 0, 0, 0, "Kitchen", 0, 0, 0, 0, 0],
[0, 0, 0, 0, "Kitchen", 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
]
What am I missing here? I'm just starting out, and would like to figure out as much as possible on my own, so if anyone could give me a hint instead of answering outright, I would really appreciate it.
It is doing what you've asked, if you follow the code carefully. It just needs an extra loop. Since what you're doing is 2 dimensional then you'll need 2 loops as well...
var paintRoom = function(mapX, mapY) {
for (var x = 0; x < roomSize; x++) {
for (var y = 0; y < roomSize; y++) {
map[mapX + x][mapY + y] = roomType;
}
};
};
you a missing 1 loop:
var mapSize = 10;
var map = [];
for (var x = 0; x < mapSize; x++) {
map[x] = [];
for (var y = 0; y < mapSize; y++) {
map[x][y] = 0
};
};
//Make square room within map
var roomSize = 3;
var roomType = "Kitchen"
var paintRoom = function(mapX, mapY) {
for (var j = 0; j < roomSize; j++) {
for (var k = 0; k < roomSize; k++) {
map[mapX + j][mapY + k] = roomType;
}
};
};
paintRoom(3, 4);
console.log(map);
https://jsfiddle.net/nfnpesmd/

Categories

Resources