I'm trying to edit a pacman implementation (source) using htlm5 and js. The problem is when I make the background transparent, the ghosts and pacman images holding the previews frames. This is an example about my problem.
My js code:
Pacman.FPS = 30;
Pacman.Ghost = function (game, map, colour) {
function getColour() {
if (eatable) {
if (secondsAgo(eatable) > 5) {
return game.getTick() % 20 > 10 ? "rgba(0, 0, 0, 0.1)" : "rgba(0, 0, 0, 0.1)";
} else {
return "rgba(0, 0, 0, 0.1)";
}
} else if(eaten) {
return "#222";
}
return colour;
};
function draw(ctx) {
var s = map.blockSize,
top = (position.y/10) * s,
left = (position.x/10) * s;
if (eatable && secondsAgo(eatable) > 8) {
eatable = null;
}
if (eaten && secondsAgo(eaten) > 3) {
eaten = null;
}
var tl = left + s;
var base = top + s - 3;
var inc = s / 10;
var high = game.getTick() % 10 > 5 ? 3 : -3;
var low = game.getTick() % 10 > 5 ? -3 : 3;
ctx.fillStyle = getColour();
ctx.beginPath();
ctx.moveTo(left, base);
ctx.quadraticCurveTo(left, top, left + (s/2), top);
ctx.quadraticCurveTo(left + s, top, left+s, base);
// Wavy things at the bottom
ctx.quadraticCurveTo(tl-(inc*1), base+high, tl - (inc * 2), base);
ctx.quadraticCurveTo(tl-(inc*3), base+low, tl - (inc * 4), base);
ctx.quadraticCurveTo(tl-(inc*5), base+high, tl - (inc * 6), base);
ctx.quadraticCurveTo(tl-(inc*7), base+low, tl - (inc * 8), base);
ctx.quadraticCurveTo(tl-(inc*9), base+high, tl - (inc * 10), base);
ctx.closePath();
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "#FFF";
ctx.arc(left + 6,top + 6, s / 6, 0, 300, false);
ctx.arc((left + s) - 6,top + 6, s / 6, 0, 300, false);
ctx.closePath();
ctx.fill();
var f = s / 12;
var off = {};
off[RIGHT] = [f, 0];
off[LEFT] = [-f, 0];
off[UP] = [0, -f];
off[DOWN] = [0, f];
ctx.beginPath();
ctx.fillStyle = "rgba(0, 0, 0, 0)";
//ctx.fillStyle = "#000";
ctx.arc(left+6+off[direction][0], top+6+off[direction][3],
s / 15, 0, 300, false);
ctx.arc((left+s)-6+off[direction][0], top+6+off[direction][4],
s / 15, 0, 300, false);
ctx.closePath();
ctx.fill();
};
function pane(pos) {
if (pos.y === 100 && pos.x >= 190 && direction === RIGHT) {
return {"y": 100, "x": -10};
}
if (pos.y === 100 && pos.x <= -10 && direction === LEFT) {
return position = {"y": 100, "x": 190};
}
return false;
};
function move(ctx) {
var oldPos = position,
onGrid = onGridSquare(position),
npos = null;
if (due !== direction) {
npos = getNewCoord(due, position);
if (onGrid &&
map.isFloorSpace({
"y":pointToCoord(nextSquare(npos.y, due)),
"x":pointToCoord(nextSquare(npos.x, due))})) {
direction = due;
} else {
npos = null;
}
}
if (npos === null) {
npos = getNewCoord(direction, position);
}
if (onGrid &&
map.isWallSpace({
"y" : pointToCoord(nextSquare(npos.y, direction)),
"x" : pointToCoord(nextSquare(npos.x, direction))
})) {
due = getRandomDirection();
return move(ctx);
}
position = npos;
var tmp = pane(position);
if (tmp) {
position = tmp;
}
due = getRandomDirection();
return {
"new" : position,
"old" : oldPos
};
};
return {
"eat" : eat,
"isVunerable" : isVunerable,
"isDangerous" : isDangerous,
"makeEatable" : makeEatable,
"reset" : reset,
"move" : move,
"draw" : draw
};
};
Pacman.User = function (game, map) {
var position = null,
direction = null,
eaten = null,
due = null,
lives = null,
score = 5,
keyMap = {};
keyMap[KEY.ARROW_LEFT] = LEFT;
keyMap[KEY.ARROW_UP] = UP;
keyMap[KEY.ARROW_RIGHT] = RIGHT;
keyMap[KEY.ARROW_DOWN] = DOWN;
function addScore(nScore) {
score += nScore;
if (score >= 10000 && score - nScore < 10000) {
lives += 1;
}
};
function theScore() {
return score;
};
function loseLife() {
lives -= 1;
};
function getLives() {
return lives;
};
function initUser() {
score = 0;
lives = 3;
newLevel();
}
function newLevel() {
resetPosition();
eaten = 0;
};
function resetPosition() {
position = {"x": 90, "y": 120};
direction = LEFT;
due = LEFT;
};
function reset() {
initUser();
resetPosition();
};
function keyDown(e) {
if (typeof keyMap[e.keyCode] !== "undefined") {
due = keyMap[e.keyCode];
e.preventDefault();
e.stopPropagation();
return false;
}
return true;
};
function getNewCoord(dir, current) {
return {
"x": current.x + (dir === LEFT && -2 || dir === RIGHT && 2 || 0),
"y": current.y + (dir === DOWN && 2 || dir === UP && -2 || 0)
};
};
function onWholeSquare(x) {
return x % 10 === 0;
};
function pointToCoord(x) {
return Math.round(x/10);
};
function nextSquare(x, dir) {
var rem = x % 10;
if (rem === 0) {
return x;
} else if (dir === RIGHT || dir === DOWN) {
return x + (10 - rem);
} else {
return x - rem;
}
};
function next(pos, dir) {
return {
"y" : pointToCoord(nextSquare(pos.y, dir)),
"x" : pointToCoord(nextSquare(pos.x, dir)),
};
};
function onGridSquare(pos) {
return onWholeSquare(pos.y) && onWholeSquare(pos.x);
};
function isOnSamePlane(due, dir) {
return ((due === LEFT || due === RIGHT) &&
(dir === LEFT || dir === RIGHT)) ||
((due === UP || due === DOWN) &&
(dir === UP || dir === DOWN));
};
function move(ctx) {
var npos = null,
nextWhole = null,
oldPosition = position,
block = null;
if (due !== direction) {
npos = getNewCoord(due, position);
if (isOnSamePlane(due, direction) ||
(onGridSquare(position) &&
map.isFloorSpace(next(npos, due)))) {
direction = due;
} else {
npos = null;
}
}
if (npos === null) {
npos = getNewCoord(direction, position);
}
if (onGridSquare(position) && map.isWallSpace(next(npos, direction))) {
direction = NONE;
}
if (direction === NONE) {
return {"new" : position, "old" : position};
}
if (npos.y === 100 && npos.x >= 190 && direction === RIGHT) {
npos = {"y": 100, "x": -10};
}
if (npos.y === 100 && npos.x <= -12 && direction === LEFT) {
npos = {"y": 100, "x": 190};
}
position = npos;
nextWhole = next(position, direction);
block = map.block(nextWhole);
if ((isMidSquare(position.y) || isMidSquare(position.x)) &&
block === Pacman.BISCUIT || block === Pacman.PILL) {
map.setBlock(nextWhole, Pacman.EMPTY);
addScore((block === Pacman.BISCUIT) ? 10 : 50);
eaten += 1;
if (eaten === 182) {
game.completedLevel();
}
if (block === Pacman.PILL) {
game.eatenPill();
}
}
return {
"new" : position,
"old" : oldPosition
};
};
function isMidSquare(x) {
var rem = x % 10;
return rem > 3 || rem < 7;
};
function calcAngle(dir, pos) {
if (dir == RIGHT && (pos.x % 10 < 5)) {
return {"start":0.25, "end":1.75, "direction": false};
} else if (dir === DOWN && (pos.y % 10 < 5)) {
return {"start":0.75, "end":2.25, "direction": false};
} else if (dir === UP && (pos.y % 10 < 5)) {
return {"start":1.25, "end":1.75, "direction": true};
} else if (dir === LEFT && (pos.x % 10 < 5)) {
return {"start":0.75, "end":1.25, "direction": true};
}
return {"start":0, "end":2, "direction": false};
};
function drawDead(ctx, amount) {
var size = map.blockSize,
half = size / 2;
if (amount >= 1) {
return;
}
ctx.fillStyle = "#FFFF00";
ctx.beginPath();
ctx.moveTo(((position.x/10) * size) + half,
((position.y/10) * size) + half);
ctx.arc(((position.x/10) * size) + half,
((position.y/10) * size) + half,
half, 0, Math.PI * 2 * amount, true);
ctx.fill();
};
function draw(ctx) {
var s = map.blockSize,
angle = calcAngle(direction, position);
ctx.fillStyle = "#FFFF00";
ctx.beginPath();
ctx.moveTo(((position.x/10) * s) + s / 2,
((position.y/10) * s) + s / 2);
ctx.arc(((position.x/10) * s) + s / 2,
((position.y/10) * s) + s / 2,
s / 2, Math.PI * angle.start,
Math.PI * angle.end, angle.direction);
ctx.fill();
};
initUser();
return {
"draw" : draw,
"drawDead" : drawDead,
"loseLife" : loseLife,
"getLives" : getLives,
"score" : score,
"addScore" : addScore,
"theScore" : theScore,
"keyDown" : keyDown,
"move" : move,
"newLevel" : newLevel,
"reset" : reset,
"resetPosition" : resetPosition
};
};
Pacman.Map = function (size) {
var height = null,
width = null,
blockSize = size,
pillSize = 0,
map = null;
function withinBounds(y, x) {
return y >= 0 && y < height && x >= 0 && x < width;
}
function isWall(pos) {
return withinBounds(pos.y, pos.x) && map[pos.y][pos.x] === Pacman.WALL;
}
function isFloorSpace(pos) {
if (!withinBounds(pos.y, pos.x)) {
return false;
}
var peice = map[pos.y][pos.x];
return peice === Pacman.EMPTY ||
peice === Pacman.BISCUIT ||
peice === Pacman.PILL;
}
function drawWall(ctx) {
var i, j, p, line;
ctx.strokeStyle = "#fFF";
ctx.lineWidth = 5;
ctx.lineCap = "round";
for (i = 0; i < Pacman.WALLS.length; i += 1) {
line = Pacman.WALLS[i];
ctx.beginPath();
for (j = 0; j < line.length; j += 1) {
p = line[j];
if (p.move) {
ctx.moveTo(p.move[0] * blockSize, p.move[1] * blockSize);
} else if (p.line) {
ctx.lineTo(p.line[0] * blockSize, p.line[1] * blockSize);
} else if (p.curve) {
ctx.quadraticCurveTo(p.curve[0] * blockSize,
p.curve[1] * blockSize,
p.curve[2] * blockSize,
p.curve[3] * blockSize);
}
}
ctx.stroke();
}
}
function reset() {
map = Pacman.MAP.clone();
height = map.length;
width = map[0].length;
};
function block(pos) {
return map[pos.y][pos.x];
};
function setBlock(pos, type) {
map[pos.y][pos.x] = type;
};
function drawPills(ctx) {
if (++pillSize > 30) {
pillSize = 0;
}
for (i = 0; i < height; i += 1) {
for (j = 0; j < width; j += 1) {
if (map[i][j] === Pacman.PILL) {
ctx.beginPath();
ctx.fillStyle = "rgba(0, 0, 0, 0)";
//ctx.fillStyle = "#000";
ctx.fillRect((j * blockSize), (i * blockSize),
blockSize, blockSize);
ctx.fillStyle = "#FFF";
ctx.arc((j * blockSize) + blockSize / 2,
(i * blockSize) + blockSize / 2,
Math.abs(5 - (pillSize/3)),
0,
Math.PI * 2, false);
ctx.fill();
ctx.closePath();
}
}
}
};
function draw(ctx) {
var i, j, size = blockSize;
ctx.fillStyle = "rgba(0, 0, 0, 0)";
//ctx.fillStyle = "#000";
ctx.fillRect(0, 0, width * size, height * size);
drawWall(ctx);
for (i = 0; i < height; i += 1) {
for (j = 0; j < width; j += 1) {
drawBlock(i, j, ctx);
}
}
};
function drawBlock(y, x, ctx) {
var layout = map[y][x];
if (layout === Pacman.PILL) {
return;
}
ctx.beginPath();
if (layout === Pacman.EMPTY || layout === Pacman.BLOCK ||
layout === Pacman.BISCUIT) {
ctx.fillStyle = "rgba(0, 0, 0, 0)";
//ctx.fillStyle = "#000";
ctx.fillRect((x * blockSize), (y * blockSize),
blockSize, blockSize);
if (layout === Pacman.BISCUIT) {
ctx.fillStyle = "#FFF";
ctx.fillRect((x * blockSize) + (blockSize / 2.5),
(y * blockSize) + (blockSize / 2.5),
blockSize / 6, blockSize / 6);
}
}
ctx.closePath();
};
reset();
return {
"draw" : draw,
"drawBlock" : drawBlock,
"drawPills" : drawPills,
"block" : block,
"setBlock" : setBlock,
"reset" : reset,
"isWallSpace" : isWall,
"isFloorSpace" : isFloorSpace,
"height" : height,
"width" : width,
"blockSize" : blockSize
};
};
Pacman.Audio = function(game) {
var files = [],
endEvents = [],
progressEvents = [],
playing = [];
function load(name, path, cb) {
var f = files[name] = document.createElement("audio");
progressEvents[name] = function(event) { progress(event, name, cb); };
f.addEventListener("canplaythrough", progressEvents[name], true);
f.setAttribute("preload", "true");
f.setAttribute("autobuffer", "true");
f.setAttribute("src", path);
f.pause();
};
function progress(event, name, callback) {
if (event.loaded === event.total && typeof callback === "function") {
callback();
files[name].removeEventListener("canplaythrough",
progressEvents[name], true);
}
};
function disableSound() {
for (var i = 0; i < playing.length; i++) {
files[playing[i]].pause();
files[playing[i]].currentTime = 0;
}
playing = [];
};
function ended(name) {
var i, tmp = [], found = false;
files[name].removeEventListener("ended", endEvents[name], true);
for (i = 0; i < playing.length; i++) {
if (!found && playing[i]) {
found = true;
} else {
tmp.push(playing[i]);
}
}
playing = tmp;
};
return {
"disableSound" : disableSound,
"load" : load,
"play" : play,
"pause" : pause,
"resume" : resume
};
};
var PACMAN = (function () {
var state = WAITING,
audio = null,
ghosts = [],
ghostSpecs = ["#00FFDE", "#FF0000", "#FFB8DE", "#FFB847"],
eatenCount = 0,
level = 0,
tick = 0,
ghostPos, userPos,
stateChanged = true,
timerStart = null,
lastTime = 0,
ctx = null,
timer = null,
map = null,
user = null,
stored = null;
function getTick() {
return tick;
};
function collided(user, ghost) {
return (Math.sqrt(Math.pow(ghost.x - user.x, 2) +
Math.pow(ghost.y - user.y, 2))) < 10;
};
function drawFooter() {
var topLeft = (map.height * map.blockSize),
textBase = topLeft + 17;
ctx.fillStyle = "rgba(0, 0, 0, 0)";
//ctx.fillStyle = "#000000";
ctx.fillRect(0, topLeft, (map.width * map.blockSize), 30);
ctx.fillStyle = "rgba(0, 0, 0, 0)";
//ctx.fillStyle = "#FFFF00";
for (var i = 0, len = user.getLives(); i < len; i++) {
ctx.fillStyle = "rgba(0, 0, 0, 0)";
//ctx.fillStyle = "#FFFF00";
ctx.beginPath();
ctx.moveTo(150 + (25 * i) + map.blockSize / 2,
(topLeft+1) + map.blockSize / 2);
ctx.arc(150 + (25 * i) + map.blockSize / 2,
(topLeft+1) + map.blockSize / 2,
map.blockSize / 2, Math.PI * 0.25, Math.PI * 1.75, false);
ctx.fill();
}
ctx.fillStyle = !soundDisabled() ? "#00FF00" : "#FF0000";
ctx.font = "bold 16px sans-serif";
//ctx.fillText("♪", 10, textBase);
ctx.fillText("s", 10, textBase);
ctx.fillStyle = "#FFF";
ctx.font = "14px BDCartoonShoutRegular";
ctx.fillText("Score: " + user.theScore(), 30, textBase);
ctx.fillText("Level: " + level, 260, textBase);
}
function redrawBlock(pos) {
map.drawBlock(Math.floor(pos.y/10), Math.floor(pos.x/10), ctx);
map.drawBlock(Math.ceil(pos.y/10), Math.ceil(pos.x/10), ctx);
}
function mainDraw() {
var diff, u, i, len, nScore;
ghostPos = [];
for (i = 0, len = ghosts.length; i < len; i += 1) {
ghostPos.push(ghosts[i].move(ctx));
}
u = user.move(ctx);
for (i = 0, len = ghosts.length; i < len; i += 1) {
redrawBlock(ghostPos[i].old);
}
redrawBlock(u.old);
for (i = 0, len = ghosts.length; i < len; i += 1) {
ghosts[i].draw(ctx);
}
user.draw(ctx);
userPos = u["new"];
for (i = 0, len = ghosts.length; i < len; i += 1) {
ctx.fillStyle = "rgba(0, 0, 0, 0)";
if (collided(userPos, ghostPos[i]["new"])) {
if (ghosts[i].isVunerable()) {
audio.play("eatghost");
ghosts[i].eat();
eatenCount += 1;
nScore = eatenCount * 50;
drawScore(nScore, ghostPos[i]);
user.addScore(nScore);
setState(EATEN_PAUSE);
timerStart = tick;
} else if (ghosts[i].isDangerous()) {
audio.play("die");
setState(DYING);
timerStart = tick;
}
}
}
};
function mainLoop() {
var diff;
if (state !== PAUSE) {
++tick;
}
map.drawPills(ctx);
if (state === PLAYING) {
mainDraw();
} else if (state === WAITING && stateChanged) {
stateChanged = false;
map.draw(ctx);
dialog("Press N to start a New game");
} else if (state === EATEN_PAUSE &&
(tick - timerStart) > (Pacman.FPS / 3)) {
map.draw(ctx);
setState(PLAYING);
} else if (state === DYING) {
if (tick - timerStart > (Pacman.FPS * 2)) {
loseLife();
} else {
redrawBlock(userPos);
for (i = 0, len = ghosts.length; i < len; i += 1) {
redrawBlock(ghostPos[i].old);
//ctx.fillStyle = "rgba(0, 0, 0, 0)";
ghostPos.push(ghosts[i].draw(ctx));
}
user.drawDead(ctx, (tick - timerStart) / (Pacman.FPS * 2));
}
} else if (state === COUNTDOWN) {
diff = 5 + Math.floor((timerStart - tick) / Pacman.FPS);
if (diff === 0) {
map.draw(ctx);
setState(PLAYING);
} else {
if (diff !== lastTime) {
lastTime = diff;
map.draw(ctx);
dialog("Starting in: " + diff);
}
}
}
drawFooter();
}
}());
For every game you want to make, your gameLoop should contain game logic like this (and in advance: GameAlchemist is right, everything should be redrawn every frame):
Clear the whole canvas
Draw background elements (don't use expensive calls, simply draw an image. If you have a lot of drawn elements, such as shapes, lines, etc., make sure to buffer this first on f.e. another, hidden canvas)
Draw more static (background) elements if you want to, that don't change position (f.e. walls)
Draw dynamic elements (your Hero, enemies, bullets, etc.)
Think of all these steps as layers (as in f.e. Photoshop) and make sure to do it in the right order.
This cheat sheet is very helpful.
Also, instead of setInterval, start using requestAnimationFrame. See f.e. this link.
PS Please don't beg for code, in the way you do. Experiment, try, fail, and try again. Then you will learn. Not by asking for gift wrapped pieces of code.
Related
I was trying to Build a spectrum and waterfall Plot HTML canvas. After a long research and googling i found this SOURCE CODE
Now i am trying to learn how this code works. i added 3 points on the spectrum using drawPoint2 function.
Can some one please Guild me. thank you.
"use strict";
var colors = [
"rgba(60, 229, 42, 0.31)",
"rgba(60, 229, 42, 0.31)",
"rgba(60, 229, 42, 0.31)",
"rgba(60, 229, 42, 0.31)",
"rgba(60, 229, 42, 0.31)",
"rgba(252, 182, 3, 0.31)",
"rgba(3, 103, 252, 0.31)",
"rgba(219, 3, 252, 0.31)",
"rgba(252, 3, 49, 0.31)",
"rgba(221, 48, 232, 0.31)",
];
var closeEnough = 5;
var crop = 150;
var data_sb = -10;
var canvas = document.getElementById("spectrumSM");
Spectrum.prototype.countDecimals = function (value) {
if (Math.floor(value) !== value)
return value.toString().split(".")[1].length || 0;
return 0;
};
Spectrum.prototype.map = function (x, in_min, in_max, out_min, out_max) {
return Math.round(
((x - in_min) * (out_max - out_min)) / (in_max - in_min) + out_min
);
};
Spectrum.prototype.updateSpectrumRatio = function () {
this.spectrumHeight = Math.round(
(this.canvas.height * this.spectrumPercent) / 100.0
);
// create a slop
this.gradient = this.ctx.createLinearGradient(0, 0, 0, this.spectrumHeight);
for (var i = 0; i < this.colormap.length; i++) {
var c = this.colormap[this.colormap.length - 1 - i];
this.gradient.addColorStop(
i / this.colormap.length,
"rgba(220,220,220,0.2)"
); //hardcode the patch above Xaxis
}
};
Spectrum.prototype.resize = function () {
var width = this.canvas.clientWidth;
var height = this.canvas.clientHeight;
if (this.canvas.width != width || this.canvas.height != height) {
this.canvas.width = width;
this.canvas.height = height;
this.updateSpectrumRatio();
for (var z = 0; z < this.tags.length; z++) {
this.tags[z].StayX = this.map(
this.tags[z].xval,
this.cutfromArray,
this.orignalArrayLength - this.cutfromArray,
0 + crop,
width
); ///////
}
}
if (this.axes.width != width || this.axes.height != this.spectrumHeight) {
this.axes.width = width;
this.axes.height = this.spectrumHeight;
this.updateAxes();
}
};
Spectrum.prototype.updateAxes = function () {
var width = this.ctx_axes.canvas.width + 100; //width of x axis izz
var height = this.ctx_axes.canvas.height;
this.maxScaleX = this.centerHz + this.spanHz / 2;
this.minScaleX = this.centerHz - this.spanHz / 2;
// Clear and fill with black
this.ctx_axes.fillStyle = "black";
this.ctx_axes.fillRect(0, 0, width, height);
// Draw axes
this.ctx_axes.font = "12px Arial";
this.ctx_axes.fillStyle = "white";
this.ctx_axes.textBaseline = "middle";
this.ctx_axes.textAlign = "center"; //change izz
var step = 10; //steps for y-axis
for (var i = this.max_db - 10; i >= this.min_db + 10; i -= step) {
var y = height - this.squeeze(i, 0, height);
this.ctx_axes.fillText(i, 20, y); // height - y
this.ctx_axes.beginPath();
this.ctx_axes.moveTo(22, y); //y axis stroked set izz
this.ctx_axes.lineTo(width, y);
this.ctx_axes.strokeStyle = "rgba(255, 255, 255, 0.15)"; //changed strokes izz
this.ctx_axes.stroke();
}
this.ctx_axes.textBaseline = "bottom";
// change X-axis
var x_axisSteps = 10;
for (var i = 0; i < x_axisSteps; i++) {
var x = Math.round((width - crop) / x_axisSteps - 1) * i + crop;
if (this.spanHz > 0) {
var adjust = 0;
if (i == 0) {
this.ctx_axes.textAlign = "left";
adjust = 3;
} else if (i == 10) {
this.ctx_axes.textAlign = "right";
adjust = -3;
} else {
this.ctx_axes.textAlign = "center";
}
//Graph points in whole points
var freq = this.centerHz + (this.spanHz / 10) * (i - 5);
if (freq > 1e9) {
freq = freq / 1e9;
if (this.countDecimals(freq) > 4) {
freq = freq.toFixed(0);
}
freq = freq + " GHz";
} else if (freq > 1e6) {
freq = freq / 1e6;
if (this.countDecimals(freq) > 4) {
freq = freq.toFixed(0);
}
freq = freq + " MHz"; //this function executed
} else {
if (this.countDecimals(freq) > 2) {
freq = freq.toFixed(0);
}
freq = freq + " MHz";
}
this.ctx_axes.fillText(freq, x - 130, height); // x axia height change izz plus values placment
}
//console.log("ctx_axes : ", this.ctx_axes);
this.ctx_axes.beginPath();
this.ctx_axes.moveTo(x, 0);
this.ctx_axes.lineTo(x, height);
this.ctx_axes.strokeStyle = "rgba(200, 200, 200, 0.2)"; //straight gridline on x axis izza
this.ctx_axes.stroke();
}
// const input = prompt("What's your name?");
};
Spectrum.prototype.toggleColor = function () {
this.colorindex++;
if (this.colorindex >= colormaps.length) this.colorindex = 0;
this.colormap = colormaps[this.colorindex];
this.updateSpectrumRatio();
};
Spectrum.prototype.setCenterHz = function (hz) {
this.centerHz = hz;
if (this.center != 0 && this.center != this.centerHz) {
this.centerHz = this.center;
}
this.updateAxes();
};
Spectrum.prototype.setSpanHz = function (hz) {
this.orignalSpanHz = hz;
this.spanHz = hz;
if (this.zoom != 0 && this.spanHz != this.zoom) {
this.spanHz = this.zoom;
}
this.updateAxes();
};
Spectrum.prototype.squeeze = function (value, out_min, out_max) {
if (value <= this.min_db) {
return out_min;
} else if (value >= this.max_db) {
return out_max;
} else {
return Math.round(
((value - this.min_db) / (this.max_db - this.min_db)) * out_max
);
}
};
Spectrum.prototype.squeeze2 = function (value, out_min, out_max) {
if (value <= 30000000) {
return out_min;
} else if (value >= 300000000) {
return out_max;
} else {
return Math.round(
((value - 30000000) / (300000000 - 30000000)) * out_max
);
}
};
Spectrum.prototype.drawRectSpectrogram = function (y, h) {
this.ctx.beginPath();
this.ctx.fillStyle = colors[this.rectColor]; //"rgba(60, 229, 42, 0.31)"; //rect color
this.ctx.strokeStyle = "green";
this.ctx.rect(this.clickRectX, y, this.clickRectWidth, h);
this.ctx.stroke();
this.ctx.fill();
this.ctx.closePath();
};
Spectrum.prototype.threshold = function (y, width, color) {
this.ctx.beginPath();
this.ctx.strokeStyle = color;
this.ctx.lineWidth = 2; //threshold line width
this.ctx.beginPath();
this.ctx.moveTo(0, y);
this.ctx.lineTo(width + crop, y);
this.ctx.stroke();
this.ctx.closePath();
this.ctx.lineWidth = 1;
};
function drawPoint2(can, x, y, label) {
can.beginPath();
can.arc(x, y, 5, 0, 2 * Math.PI);
can.fillStyle = "red";
can.fill();
can.fillText(label, x + 10, y);
can.stroke(); // it creates X axies and
}
Spectrum.prototype.drawSpectrum = function (bins) {
//get canvas height and width to draw spectrum ayaz
var width = this.ctx.canvas.width;
var height = this.ctx.canvas.height;
//console.log("spectrum width and height : "+width+" "+ height);
// width of Green Color ayaz
this.ctx.lineWidth = 1; //Amplitude green line width .
//All of the points are 119 nut few points are 118 and few 120 ayaz
if (!this.binsAverage || this.binsAverage.length != bins.length) {
//console.log('this.binsAverage ', this.binsAverage );
this.binsAverage = bins;
} else {
for (var i = 0; i < bins.length; i++) {
this.binsAverage[i] +=
(1 - this.averaging) * (bins[i] - this.binsAverage[i]);
}
}
bins = this.binsAverage;
//Do not draw anything if spectrum is not visible
if (this.ctx_axes.canvas.height < 1) return;
//////////////////////////////////////////////////////////////Creation of X and Y axis completed
// Copy axes from offscreen canvas
this.ctx.drawImage(this.ctx_axes.canvas, -1, -1); // create Spectrums X and Y axis
// // Scale for FFT
this.ctx.save(); // saves sppectrum previous stage
//////////////////////////////////////////////////////////////Creation of X and Y axis completed
this.ctx.scale(width / this.wf_size, 1); //green line visiblity izza
var peakY = this.spectrumHeight;
// Draw FFT bins
this.ctx.beginPath();
this.offset = Math.round(
this.map(crop, 0, this.ctx.canvas.width + 6000, 0, this.wf_size)
); // green line axis set izza
//console.log('this.offset : ', this.offset);
console.log(
"X and Y are : ",
-1 + this.offset + " " + this.spectrumHeight + 0
);
this.ctx.moveTo(-1 + this.offset, this.spectrumHeight + 0); //change for waterfall izza
// above line is the address of left bottom corner of spectrum
// console.log(
// "clkkkkkkkkkkkkkkk : ",
// this.clickRectX+
// crop+
// width+
// this.minScaleX+
// this.maxScaleX
// );
var rangeMin = this.map(
this.clickRectX,
crop,
width,
this.minScaleX,
this.maxScaleX
);
var rangeMax = this.map(
this.clickRectWidth + this.clickRectX,
crop,
width,
this.minScaleX,
this.maxScaleX
);
if (rangeMin > rangeMax) {
var temp;
temp = rangeMax;
rangeMax = rangeMin;
rangeMin = temp;
}
var max = 100000000;
this.scaleY = this.map(this.threshY, this.min_db, this.max_db, height / 2, 0); // 0, height/2 // height of threshold izza
this.detectedFrequency.length = 0;
// console.log('bins are ', bins);
//console.log('new array ');
for (var i = 0; i < bins.length; i++) {
// if ( parseFloat( bins[i]) > -100 ) {
// console.log("bins : ", bins[i]);
// const input = prompt("What's your name?");
// alert(`Your name is ${input}`);
// }
var y =
this.spectrumHeight - 1 - this.squeeze(bins[i], 0, this.spectrumHeight);
peakY = this.squeeze(bins[i], 0, this.spectrumHeight);
if (y > this.spectrumHeight - 1) {
y = this.spectrumHeight - 1;
console.log("Y has chnaged : ", y);
}
if (y < 0) {
y = 0;
console.log("y=0");
}
if (i == 0) {
this.ctx.lineTo(-1 + this.offset, y);//responsible for height of green line
}
// green lines are created here ayaz
// create green lines
// important
//drawPoint2(this.ctx ,i + this.offset, y);
this.ctx.lineTo(i + this.offset, y); // that what point we start drawing green horizental green line
// console.log(
// "Starting Line 1 i " +
// i +
// " X : " +
// parseInt(i + this.offset) +
// " y : " +
// y
// );
if (i == bins.length - 1) {
//drawPoint2(this.ctx ,i + this.offset, y);
this.ctx.lineTo(this.wf_size + 1 + this.offset, y);
// console.log(
// "Second 2 i == bins.length - 1 i " +
// i +
// " Drawingg -1 + this.offset : " +
// parseInt(i + this.offset) +
// " y : " +
// y
// );
}
for (var z = 0; z < this.tags.length; z++) {
if (
i + this.cutfromArray == this.tags[z].xval &&
this.check_click == true
) {
this.tags[z].tagY = y;
this.tags[z].yval = Math.round(bins[i]);
this.tags[z].displayX = Math.round(
this.map(i, 0, bins.length, this.minScaleX, this.maxScaleX)
);
}
}
if (y < max) {
max = y;
}
let newVal = Math.round(
this.map(i, 0, bins.length, this.minScaleX, this.maxScaleX)
);
if (this.check_bar) {
if (newVal < rangeMax && newVal > rangeMin) {
if (y < this.scaleY) {
var obj = new Object();
obj.x = newVal;
obj.y = Math.round(bins[i]);
obj.count = 1;
var check = true;
for (var j = 0; j < this.threshRange.length; j++) {
if (
this.threshRange[j].x == obj.x &&
this.threshRange[j].y == obj.y
) {
this.threshRange[j].count++;
check = false;
}
}
if (check) {
let tableRows = document
.getElementById("thresh-table-body")
.getElementsByTagName("tr").length;
if (tableRows < 100) {
this.threshRange.push(obj);
// filling table
let tbody = document.getElementById("thresh-table-body");
let tr = document.createElement("tr");
let td1 = document.createElement("td");
let td2 = document.createElement("td");
let td3 = document.createElement("td");
td1.innerHTML = obj.x; //+" Hz"
td2.innerHTML = obj.y;
td3.innerHTML = obj.count;
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3);
tbody.appendChild(tr);
}
} else {
// update table count
for (let c = 0; c < this.threshRange.length; c++) {
let tableRows =
document.getElementById("thresh-table-body").rows[c].cells;
if (
tableRows[0].innerHTML == obj.x &&
tableRows[1].innerHTML == obj.y
) {
let countValue = Number(tableRows[2].innerHTML);
countValue++;
tableRows[2].innerHTML = countValue;
}
}
}
}
}
} else {
if (y < this.scaleY) {
var obj = new Object();
obj.x = newVal;
obj.y = Math.round(bins[i]);
obj.count = 1;
var check = true;
for (var j = 0; j < this.threshRange.length; j++) {
if (
this.threshRange[j].x == obj.x &&
this.threshRange[j].y == obj.y
) {
this.threshRange[j].count++;
check = false;
}
}
}
}
}
// this.ctx.beginPath();
// this.ctx.arc(100, 75, 20, 0, 1 * Math.PI);
// this.ctx.stroke();
//this.ctx.strokeRect(1800,10, 40, 190);
function containsObject(obj, list) {
var i;
for (i = 0; i < list.length; i++) {
if (list[i] === obj) {
return true;
}
}
return false;
}
this.ctx.fillStyle = "rgba(0, 0, 0, 0.11)";
// drawPoint2(this.ctx ,
// this.wf_size + 1 + this.offset,
// this.spectrumHeight + 1
// );
this.ctx.lineTo(this.wf_size + 1 + this.offset, this.spectrumHeight + 1);
// console.log(
// "thired 3 this.wf_size + 1 + this.offset : " +
// parseInt(this.wf_size + 1 + this.offset) +
// " this.spectrumHeight + 1 : " +
// parseInt(this.spectrumHeight + 1)
// );
// drawPoint2(this.ctx ,
// this.wf_size + this.offset,
// this.spectrumHeight
// );
this.ctx.lineTo(this.wf_size + this.offset, this.spectrumHeight );
// console.log(
// "Forth this.wf_size + this.offset : " +
// parseInt(this.wf_size + this.offset) +
// " y : " +
// y
// );
if (y < 230 && y > 245) {
console.log("foundddddddddddddd");
}
this.ctx.closePath();
this.ctx.restore();
this.ctx.strokeStyle = "#259a00"; //color of spectrum green
this.ctx.stroke(); // it creates X axies and
/////////////////////////////////////////////////////////////////////////green ended
if (this.spectrumColorCheck) {
this.ctx.fillStyle = this.gradient; //chnage color of under line chart
} else {
this.ctx.fillStyle = "rgba(0, 0, 0, 0.0)";
}
this.ctx.fill();
if (this.check_bar) {
this.drawRectSpectrogram(0, height);
}
var colorTh = "#cc8315"; //By uncomment Change the threshold line color change
this.threshold(this.scaleY, width, colorTh); // yellow light
if (this.check_click == true) {
for (let c = 0; c < this.tags.length; c++) {
this.drawTag(
this.tags[c].StayX,
this.tags[c].tagY,
this.tags[c].displayX,
this.tags[c].yval
);
}
if (this.removeTagCheck == true) {
closeEnough = 30;
for (var z = 0; z < this.tags.length; z++) {
if (this.checkCloseEnough(this.StayX, this.tags[z].StayX + 15)) {
this.tags.splice(z, 1);
z--;
}
}
}
}
closeEnough = 5;
// span hz commented
if (this.updateValueCheck) {
if (this.countDecimals(this.threshY) > 2) {
this.threshY = this.threshY.toFixed(2);
}
this.updateValueCheck = false;
}
var arrt = [ -100000000 , 40000000,35000000];
this.spectrumWidth = Math.round(
(this.canvas.width * this.spectrumPercent) / 100.0
);
for (var k = 0; k < 4; k++) {
var alpha =
this.spectrumHeight - 620 - this.squeeze2(arrt[k], 0, this.spectrumWidth);
drawPoint2(this.ctx, alpha + 600, 150, "A");
}
// draw separate lines
// for (var k=0;k< 4; k++){
// drawPoint2(this.ctx, "200000000", "-80");
// drawPoint2(this.ctx,"100000000", "-80");
// drawPoint2(this.ctx,"35000000", "-80");
// }
//console.log('this.ctx : ',this.ctx);
};
Spectrum.prototype.addData = function (data, bmp) {
if (!this.paused) {
if (data.length > 32768) {
data = this.sequenceResize(data, 32767);
}
this.orignalArrayLength = data.length;
if (this.orignalSpanHz > this.spanHz) {
data = data.slice(
this.cutfromArray,
this.orignalArrayLength - this.cutfromArray
);
}
if (data.length != this.wf_size) {
this.wf_size = data.length;
if (data.length > 32767) {
this.ctx_wf.canvas.width = 32767;
} else {
this.ctx_wf.canvas.width = data.length;
}
this.ctx_wf.fillStyle = "black";
this.ctx_wf.fillRect(0, 0, this.wf.width, 0); //strokes of waterfall
for (var z = 0; z < this.tags.length; z++) {
this.tags[z].StayX = this.map(
this.tags[z].xval,
this.cutfromArray,
this.orignalArrayLength - this.cutfromArray,
crop,
this.ctx.canvas.width
);
}
}
this.drawSpectrum(data);
// this.addWaterfallRowBmp(bmp);
// this.addWaterfallRow(data);
this.resize();
}
};
function Spectrum(id, options) {
// Handle options
this.centerHz = options && options.centerHz ? options.centerHz : 0;
this.spanHz = options && options.spanHz ? options.spanHz : 0;
this.wf_size = options && options.wf_size ? options.wf_size : 0;
this.wf_rows = options && options.wf_rows ? options.wf_rows : 50;
this.spectrumPercent =
options && options.spectrumPercent ? options.spectrumPercent : 25;
this.spectrumPercentStep =
options && options.spectrumPercentStep ? options.spectrumPercentStep : 5;
this.averaging = options && options.averaging ? options.averaging : 0.5;
this.rectColor = options && options.rectColor ? options.rectColor : 0;
// Setup state
this.paused = false;
this.fullscreen = true;
this.min_db = -140;
this.max_db = -20;
this.spectrumHeight = 0;
// Colors
this.colorindex = 2;
this.colormap = colormaps[0];
// Create main canvas and adjust dimensions to match actual
this.canvas = document.getElementById("spectrumSM");
canvas.height = this.canvas.clientHeight;
this.canvas.width = this.canvas.clientWidth;
this.ctx = this.canvas.getContext("2d");
this.checkclick = false;
this.clickRectWidth = 1000;
this.dragL = true;
this.dragR = true;
// this.ctx.globalAlpha = 0.1;
this.drag = true;
this.click_x = 0;
this.click_y = 0;
this.check_click = true;
this.threshY = -70;
this.StayX = -10;
this.scaleY = 0;
//for change waterfall design
this.threshCheck = true;
this.removeTagCheck = true;
this.spectrumColorCheck = true;
this.check_bar = true;
this.updateValueCheck = true;
this.tags = [];
this.addTagsCheck = true;
this.maxScaleX = 0;
this.minScaleX = 0;
this.orignalArrayLength = 0;
this.zoom = this.spanHz;
this.center = this.centerHz;
this.threshRange = [];
this.detectedFrequency = [];
this.offset = 10;
this.arraySizeto = 0;
this.orignalSpanHz = 0;
this.cutfromArray = 0;
this.ctx.fillStyle = "black";
this.ctx.fillRect(10, 10, this.canvas.width, this.canvas.height);
// Create offscreen canvas for axes
this.axes = document.createElement("canvas");
this.axes.id = "myCheck";
this.axes.height = 1; // Updated later
this.axes.width = this.canvas.width;
this.ctx_axes = this.axes.getContext("2d");
function myFunction() {
this.style.fontSize = "40px";
}
// Create offscreen canvas for waterfall
this.wf = document.createElement("canvas");
this.wf.height = this.wf_rows;
this.wf.width = this.wf_size;
this.ctx_wf = this.wf.getContext("2d");
// Trigger first render
this.updateSpectrumRatio();
this.resize();
}
Here showing value of spectrum at specific point via click and zoom in/ zoom out functionality.
var closeEnough = 5;
var crop = 150;
var data_sb = -10;
var canvas = document.getElementById("spectrumSM");
Spectrum.prototype.mousedown = function (evt) {
this.checkclick = true;
if (this.checkCloseEnough(this.click_x-3, this.clickRectX)) {
this.dragR = false;
this.dragL = true;
} else if (
this.checkCloseEnough(this.click_x-3, this.clickRectX + this.clickRectWidth)
) {
this.dragR = true;
this.dragL = false;
} else if (this.checkCloseEnough(this.click_y-3, this.scaleY)) {
this.drag = true;
}
};
Spectrum.prototype.mouseup = function (evt) {
this.checkclick = false;
this.dragL = false;
this.dragR = false;
this.drag = false;
if (evt.button === "right") {
this.tags = [];
}
};
Spectrum.prototype.mousemove = function (evt) {
var rect = this.canvas.getBoundingClientRect();
this.click_x = evt.clientX - rect.left;
this.click_y = evt.clientY - rect.top;
closeEnough = Math.abs(this.clickRectWidth);
if (this.dragL == false && this.dragR == false && this.drag == false) {
if (
this.checkclick == true &&
this.checkCloseEnough(
this.click_x,
this.clickRectX + this.clickRectWidth / 2
)
) {
this.clickRectX = this.click_x - this.clickRectWidth / 2;
}
} else if (this.dragL) {
this.clickRectWidth += this.clickRectX - this.click_x;
this.clickRectX = this.click_x;
} else if (this.dragR) {
this.clickRectWidth = -(this.clickRectX - this.click_x);
} else if (this.drag && this.threshCheck) {
this.updateValueCheck = true;
this.threshY = this.map(
this.click_y,
this.canvas.height / 2,
0,
this.min_db,
this.max_db
); // this.max_db, this.min_db
}
closeEnough = 10;
};
Spectrum.prototype.click = function (evt) {
// change izza
this.check_click = true;
this.StayX = this.click_x;
console.log('tag list : ',this.addTagsCheck);
if (this.addTagsCheck == true && this.StayX > 3) {
var tag = {
StayX: this.click_x,
tagY: 0,
yval: 0,
xval: Math.round(
this.map(
this.click_x,
28,
this.ctx.canvas.width,
this.cutfromArray,
this.orignalArrayLength - this.cutfromArray
)
),
displayX: 0,
};
this.tags.push(tag);
}
};
Spectrum.prototype.wheel = function (evt) {
this.zoom = this.spanHz;
var inc;
if (this.arraySizeto == 0) {
inc = Math.round(this.orignalArrayLength * 0.05);
} else {
inc = Math.round(this.arraySizeto * 0.05);
}
let zoomInc = 0;
if (this.orignalSpanHz > this.orignalArrayLength) {
zoomInc = this.orignalSpanHz / this.orignalArrayLength;
} else {
zoomInc = this.orignalArrayLength / this.orignalSpanHz;
}
if (evt.deltaY > 0) {
if (
this.orignalSpanHz - (zoomInc * this.cutfromArray - inc * 2) <
this.orignalSpanHz &&
this.cutfromArray - inc >= 0
) {
this.cutfromArray = this.cutfromArray - inc;
this.zoom = this.orignalSpanHz - zoomInc * this.cutfromArray * 2;
} else if (
this.orignalSpanHz + zoomInc * this.cutfromArray * 2 >=
this.orignalSpanHz &&
this.cutfromArray - inc <= 0
) {
this.zoom = this.orignalSpanHz;
this.cutfromArray = 0;
}
} else if (evt.deltaY < 0) {
if (
this.orignalSpanHz - (zoomInc * this.cutfromArray + inc * 2) > inc &&
this.orignalArrayLength - this.cutfromArray * 2 - inc * 2 >
this.ctx.canvas.width
) {
this.cutfromArray = this.cutfromArray + inc;
this.zoom = this.orignalSpanHz - zoomInc * this.cutfromArray * 2;
}
}
this.arraySizeto = this.orignalArrayLength - this.cutfromArray * 2;
this.maxScaleX = this.centerHz + this.zoom / 20;
this.minScaleX = this.centerHz - this.zoom / 20;
};
Spectrum.prototype.undoTag = function () {
this.tags.pop();
};
Spectrum.prototype.checkCloseEnough = function (p1, p2) {
return Math.abs(p1 - p2) < closeEnough;
};
Spectrum.prototype.drawTag = function (locx, locy, xval, yval) {
this.ctx.beginPath();
this.ctx.strokeStyle = "#cc8315";
let freq = xval;
if (freq > 1e9) {
freq = freq / 1e9;
if (this.countDecimals(freq) > 2) {
freq = freq.toFixed(2);
}
freq = freq + " GHz";
} else if (freq > 1e6) {
freq = freq / 1e6;
if (this.countDecimals(freq) > 2) {
freq = freq.toFixed(2);
}
freq = freq + " MHz";
} else {
if (this.countDecimals(freq) > 2) {
freq = freq.toFixed(2);
}
}
var text = " ( " + freq + ", " + yval + ")";
var padding = 5;
var fontSize = 20;
var xPos = locx - padding;
var width = this.ctx.measureText(text).width + padding * 2;
var height = fontSize * 1.286;
var yPos = locy - height / 1.5;
this.ctx.lineWidth = 2;
this.ctx.fillStyle = "rgba(204, 131, 21, 0.8)";
// draw the rect
this.ctx.fillRect(xPos, yPos, width, height);
this.ctx.fillStyle = "white";
this.ctx.font = "bold 10pt droid_serif";
this.ctx.fillText(text, locx, locy);
this.ctx.fillStyle = "white";
this.ctx.beginPath();
this.ctx.arc(locx, locy, 2, 0, Math.PI * 2, true);
this.ctx.fill();
this.ctx.closePath();
};
The spectrum project you reference expects to receive regular updates of an array of data passed into drawSpectrum. Each time it renders that data as a new spectrum in drawFFT, with the data scaled by the numbers set in setRange. Each time it receives data, it also creates a new row of pixels for the waterfall in the rowToImageData function, again scaled by the numbers set in setRange. The previously created rows of pixels are shifted down by one row in addWaterfallRow.
I've made a fiddle that shows how data is handled by the Spectrum object: https://jsfiddle.net/40qun892/
If you run the fiddle it shows two examples, one with three points and another with 100 points of randomly generated data. This line shows how an x-axis is added to the graph:
const spectrumB = new Spectrum("spectrumCanvasB", {spanHz: 5000, centerHz: 2500});
The x-axis is only shown when spanHz is defined. It is generated by drawing 11 labels, equally distributed across the canvas. With the center label based on centerHz, and the remaining labels calculated based on spanHz.
As you can see from the spectrums generated by the fiddle, the x-axis labels are not connected to the data, they are just equally distributed across the canvas.
The graph behind the data is created by applying a scale to the graph so that using the array index will result in data stretched across the graph.
this.ctx.scale(width / <number of data points>, 1);
for (var i = 0; i < <number of data points>.length; i++) {
// lines removed
this.ctx.lineTo(i, y);
// lines removed
}
As you can see from the examples in the fiddle, this doesn't look very nice when there's only three datapoints, because the white lines are stretched in the x-direction but not the y-direction.
Spectrum doesn't care about x-coordinates. It just stretches whatever it is given to fit the canvas. If you give it a spanHz property, it will distribute some labels across the canvas too, but it does not associate them with the data.
The scaling seems to be slightly wrong in Spectrum (which is only noticeable if very few datapoints are used). If I make this change, the points are correctly stretched:
this.ctx.scale(width / (this.wf_size - 1), 1);
Then this change would set the x-axis labels to 100Mhz - 300Mhz:
const spectrumA = new Spectrum("spectrumCanvasA", {spanHz: 200000000, centerHz: 200000000});
Edit: (The relationship between frequency and data)
The only thing the code knows about the frequency is based on the spanHz anad centerHz.
The frequency at an array index is
(<array index> / <number of points on X axis> * <spanHz>) + (<centerHz> / 2)
The frequency at a pixel is
(<x coordinate> / <width of canvas> * <spanHz>) + (<centerHz> / 2)
If you want to convert a frequency to an array index (or a pixel) it would be slightly more complicated, because you would need to find the closest element to that frequency. For example, the pixel at a frequency is:
round((<frequency> - (<centerHz> / 2)) / <spanHz> * <width of canvas>)
I created a RaceTrack game, where you simply drive a car, collect yellow bonuses and avoid black obstacles.
The problem is that the animation of my car is not smooth ( When u try to go left or right etc. )
Can someone help me understand how can I do a smooth animation when steering a car ?
How could I add a spontanious curves instead of straight road?
Ps. I know my ColissionChecker() functions aren't perfect, but that is a problem for another day.
I don't know why in snippet's Full Page the canvas is very small and you can't see anything.
var canvas = document.querySelector('canvas');
var c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var LineWidth = 10;
var LineHeight = 80;
var boundaryTopOffset = 5;
var boundaryLeftOffset = 2;
var boundaryPadding = 50;
var boundaryMiddleOffset = 2;
var speed = 50;
let executedTimer = false;
let dateDiff;
let currentScore = 0;
var leftBoundary = [];
var rightBoundary = [];
var middleBoundary = [];
var bonuses = [];
var obstacles = [];
var car = {
x: 1200,
y: 800
}
document.addEventListener('keydown', function(event) {
let key = event.which
if(key === 37) {
car.x -= speed;
} else if(key === 39) {
car.x += speed;
} else if(key === 38) {
car.y -= speed;
} else if(key === 40) {
car.y += speed;
}
})
for (x = 0; x < 8; x++) {
leftBoundary[x] =
{
offset: boundaryLeftOffset + 400,
topOffset: 0,
width: LineWidth,
height: LineHeight,
color: "red"
};
}
for (x = 0; x < 8; x++) {
middleBoundary[x] =
{
offset: boundaryMiddleOffset + 890,
topOffset: 0,
width: LineWidth,
height: LineHeight,
color: "white"
};
}
for (x = 0; x < 8; x++) {
rightBoundary[x] =
{
offset: boundaryLeftOffset + 1400,
topOffset: 0,
width: LineWidth,
height: LineHeight,
color: "red"
};
}
var cycle = 0,
totalCycle = LineHeight + boundaryPadding;
window.requestAnimationFrame(draw);
function draw() {
if(executedTimer == false) {
obstacles.push({x: Math.floor((Math.random() * 1000) + 450), y: 10});
timerStart();
}
drawCanvas(boundaryLeftOffset-2, 0, canvas.width, canvas.height, 'grey');
cycle = (cycle + 4) % totalCycle;
for (boundary of [leftBoundary, rightBoundary, middleBoundary]) {
for (i = 0; i < boundary.length; i++) {
boundary[i].topOffset = cycle + (i-1) * totalCycle;
drawBoundary(boundary[i], boundary[i].color);
}
}
if(dateDiff >= 1000) {
obstacles.push({x: Math.floor((Math.random() * 900) + 490), y: 10});
bonuses.push({x: Math.floor((Math.random() * 900) + 490), y: 10})
}
drawScore();
drawObstacle();
drawBonus();
drawCar();
obstacleColissionChecker();
bonusColissionChecker();
timerCheck();
window.requestAnimationFrame(draw);
}
function drawBoundary(x, elementColor) {
c.fillStyle = elementColor;
c.fillRect(x.offset+100, x.topOffset, x.width, x.height);
}
function drawCanvas(posX, posY, width, height, elementColor) {
c.fillStyle = elementColor;
c.fillRect(posX, posY, width, height);
}
function drawCar() {
c.fillStyle = "blue";
c.fillRect(car.x, car.y, 100, 150);
c.fillStyle = "black";
for(var i = 0; i < 101; i+=100){
c.beginPath();
c.ellipse(car.x + i, car.y + 10, 10, 15, Math.PI, 0, 2 * Math.PI);
c.ellipse(car.x + i, car.y + 140, 10, 15, Math.PI, 0, 2 * Math.PI);
c.fill();
c.closePath();
}
}
function timerStart() {
date1 = new Date();
executedTimer = true;
}
function timerCheck() {
var date2 = new Date();
dateDiff = Math.abs(date1 - date2);
if(dateDiff >= 1000)date1 = date2;
}
function drawScore() {
c.font='25px Verdana';
c.fillStyle = 'hsl('+ 0 +', 100%, 50%)';
c.fillText('Score : ' + currentScore, 100, 80);
}
function drawObstacle() {
c.fillStyle = "#080D23";
for(obstacle of [obstacles]) {
for (i = 0; i < obstacles.length; i++) {
c.fillRect(obstacle[i].x, obstacle[i].y+= 5, 80, 50);
}
}
}
function drawBonus() {
c.fillStyle = "#F2C14A";
for(bonus of [bonuses]) {
for (i = 0; i < bonuses.length; i++) {
c.beginPath();
c.arc(bonuses[i].x, bonuses[i].y+= 5, 20, 0, Math.PI * 2, false);
c.fill();
c.closePath();
}
}
}
function obstacleColissionChecker() {
for (i = 0; i < obstacles.length; i++) {
if(car.y + 20 - obstacles[i]?.y + 20 > 0 && car.y - 20 - obstacles[i]?.y + 20 < 100
&& car.x + 100 - obstacles[i]?.x + 20 > 0 && car.x - 100 - obstacles[i]?.x - 20 < 200) {
currentScore--;
}
}
}
function bonusColissionChecker() {
for (i = 0; i < bonuses.length; i++) {
if(car.y + 20 - bonuses[i]?.y + 20 > 0 && car.y - 20 - bonuses[i]?.y + 20 < 100
&& car.x + 100 - bonuses[i]?.x + 20 > 0 && car.x - 100 - bonuses[i]?.x - 20 < 200) {
currentScore++;
}
}
}
canvas {
border: 1px solid black;
margin: 0 !important;
padding: 0 !important;
}
body {
margin: 0;
}
<canvas></canvas>
In your code the speed is constant.
The car is either moving at that speed or is not moving.
This is the problem : you need to introduce acceleration.
You should car.x += speed on every frame and alter the speed in the key press handler. It would be a good start for you.
I am getting errors when I used instance mode in my code. My mini game isn't showing up I am not sure where the error is coming from. It works fine without the instance mode but I need to use the instance mode so that I can reference this code in another file. I'm using this link as a reference. http://p5js.org/examples/instance-mode-instantiation.html
let sketch = function(p) {
let blob;
let blobs = [];
let zoom = 1;
let timer = 20;
let hits = false;
let score = 0;
p.setup = function() {
p.createCanvas(600, 600);
blob = new Blob(0, 0, 64);
for (let i = 0; i < 300; i++) {
let x = p.random(-p.width,p.width);
let y = p.random(-p.height,p.height);
blobs[i] = new Blob(x, y, 15);
}
};
p.draw = function() {
p.background(0);
p.translate(width/2, height/2);
let newzoom = 64 / blob.r;
p.zoom = p.lerp(zoom, newzoom, 0.1);
p.scale(zoom);
p.translate(-blob.pos.x, -blob.pos.y);
for (var i = blobs.length-1; i >=0; i--) {
blobs[i].show();
if (blob.eats(blobs[i])) {
blobs.splice(i, 1);
}
}
if (frameCount % 60 == 0 && timer > 0) { // if the frameCount is divisible by 60, then a second has passed. it will stop at 0
p.timer --;
}
if (timer == 0 && score >=250) {
p.text("You Win", 0, 0);
p.noLoop();
}
if (blob.eats){
p.console.log("hit");
}
if (timer == 0 && score <= 250){
p.text("You Lose", 0, 0);
p.textSize(200);
p.noLoop();
}
blob.show();
blob.update();
};
};
let myp5 = new p5(sketch);
class Blob {
constructor(x, y, r) {
this.pos = createVector(x, y);
this.r = r;
this.vel = createVector(0,0);
}
show(p) {
p.ellipse(this.pos.x, this.pos.y, this.r, this.r);
}
eats(other) {
let d = p5.Vector.dist(this.pos, other.pos);
if (d < this.r + other.r) {
let sum = PI * this.r * this.r + PI * other.r * other.r;
score ++;
this.r = sqrt(sum / PI);
//this.r += other.r;
return true;
} else {
return false;
}
}
While width, height and frameCount are properties of the canvas, console is it not.
p.translate(width/2, height/2);
p.translate(p.width/2, p.height/2);
if (frameCount % 60 == 0 && timer > 0) {
if (p.frameCount % 60 == 0 && timer > 0) {
console.log("hit");
console.log("hit");
I don't know the implementation of Blob. but you have to passe the canvas object (p) to the show method and the let constructor.
The variable score can't be accessed in the class Blob
See the example, where I applied the suggested changes to your original code:
class Blob {
constructor(p, x, y, r) {
this.pos = p.createVector(x, y);
this.r = r;
this.vel = p.createVector(0,0);
}
show(p) {
p.ellipse(this.pos.x, this.pos.y, this.r, this.r);
}
eats(other) {
let d = this.pos.dist(other.pos);
if (d < this.r + other.r) {
let sum = Math.pi * this.r * this.r + Math.pi * other.r * other.r;
this.r = Math.sqrt(sum / Math.pi);
//this.r += other.r;
return true;
} else {
return false;
}
}
update() {
// ...
}
}
let sketch = function(p) {
let blob;
let blobs = [];
let zoom = 1;
let timer = 20;
let hits = false;
let score = 0;
p.setup = function() {
p.createCanvas(600, 600);
blob = new Blob(p, 0, 0, 64);
for (let i = 0; i < 300; i++) {
let x = p.random(-p.width,p.width);
let y = p.random(-p.height,p.height);
blobs[i] = new Blob(p, x, y, 15);
}
};
p.draw = function() {
p.background(0);
p.translate(p.width/2, p.height/2);
let newzoom = 64 / blob.r;
p.zoom = p.lerp(zoom, newzoom, 0.1);
p.scale(zoom);
p.translate(-blob.pos.x, -blob.pos.y);
for (var i = blobs.length-1; i >=0; i--) {
blobs[i].show(p);
if (blob.eats(blobs[i])) {
score ++;
blobs.splice(i, 1);
}
}
if (p.frameCount % 60 == 0 && timer > 0) {
p.timer --;
}
if (timer == 0 && score >=250) {
p.text("You Win", 0, 0);
p.noLoop();
}
if (blob.eats){
console.log("hit");
}
if (timer == 0 && score <= 250){
p.text("You Lose", 0, 0);
p.textSize(200);
p.noLoop();
}
blob.show(p);
blob.update();
};
};
let myp5 = new p5(sketch)
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>
I am working on a project on Khan Academy in which I have to create a game with at least 3 levels. I have developed most of the game but when I tried to proceed from one level to next the game somehow stops.
Here is the full project:
Project Link
/**
* Contains 3 levels
*
*
* Changed Ground
* Brown rectangle is replaced with Dirt Block.
*
* Scoring system changed
* Collecting Good sticks gets 1 point.
* Collecting Bad sticks gets -1 point. (i.e. loses point).
* Hitting rocks will lose 1 point.
*
**/
var level = 0;
var nosOfSticks = 5;
var target = 0;
var speed = 1;
var endLevel = false;
var buttonClicked = false;
var levelButtonEnabled = false;
var startButtonEnabled = true;
var Beaver = function(x, y) { // Beaver Constructor
this.x = x;
this.y = y;
this.img = getImage("creatures/Hopper-Happy");
this.sticks = 0;
};
Beaver.prototype.draw = function() { // Draw function to draw beaver
fill(255, 0, 0);
this.x = constrain(this.x, 0, width-40);
this.y = constrain(this.y, 0, height-50);
image(this.img, this.x, this.y, 40, 40);
};
Beaver.prototype.hop = function() { // Hop function to make beaver hop
this.img = getImage("creatures/Hopper-Jumping");
this.y -= speed * 5;
};
Beaver.prototype.hopLeft = function() {
this.img = getImage("creatures/Hopper-Jumping");
this.x -= speed * 5;
};
Beaver.prototype.hopRight = function() {
this.img = getImage("creatures/Hopper-Jumping");
this.x += speed * 5;
};
Beaver.prototype.fall = function() { // fall function makes beaver fall on the ground
this.img = getImage("creatures/Hopper-Happy");
this.y += speed * 5;
};
Beaver.prototype.checkForStickGrab = function(stick) { // function that checks sticks grab
if ((stick.x >= this.x && stick.x <= (this.x + 40)) &&
(stick.y >= this.y && stick.y <= (this.y + 40))) {
stick.y = -400;
this.sticks++;
}
};
Beaver.prototype.checkForBadStickGrab = function(badstick) { // function that checks badsticks grab
if ((badstick.x >= this.x && badstick.x <= (this.x + 40)) &&
(badstick.y >= this.y && badstick.y <= (this.y + 40))) {
badstick.y = -400;
this.sticks--;
}
};
Beaver.prototype.checkForRockHit = function(rock) { // function that checks rocks hit
if ((rock.x >= this.x - 40 && rock.x <= (this.x + 40)) &&
(rock.y >= this.y - 30 && rock.y <= (this.y + 40))) {
rock.x = -400;
this.sticks--;
}
};
// Drawing Sticks
var Stick = function(x, y) { // Stick constructor
this.x = x;
this.y = y;
};
Stick.prototype.draw = function() { // Draw function to draw sticks
fill(0, 0, 0);
rectMode(CENTER);
rect(this.x, this.y, 5, 40);
};
var Badstick = function(x, y) { // Bad Sticks constructor
Stick.call(this, x, y);
};
//Badstick.prototype = Object.create(Stick);
Badstick.prototype.draw = function() { //Draw function to draw badsticks
fill(255, 0, 13);
rectMode(CENTER);
rect(this.x, this.y, 5, 40);
};
// Drawings Rocks
var Rock = function(x, y) { // rocks constructor
this.x = x;
this.y = y;
this.img = getImage("cute/Rock");
};
Rock.prototype.draw = function(x, y) { // function to draw rocks
fill(0, 0, 0);
image(this.img, this.x, this.y, 40, 40);
};
var beaver = new Beaver(200, 300);
var sticks = [];
for (var i = 0; i < nosOfSticks; i++) {
sticks.push(new Stick(i * 100 + 400, random(20, 260)));
}
var badSticks = [];
for (var i = 0; i < nosOfSticks/2; i++) {
badSticks.push(new Badstick(i * 200 + 400, random(20, 270)));
}
var rocks = [];
for ( var i = 0; i < nosOfSticks * 0.375; i++) {
rocks.push(new Rock(random(0, 375), i * random() - (i * 100)));
}
var grassXs = [];
for (var i = 0; i < 25; i++) {
grassXs.push(i*20);
}
var blockXs = [];
for (var i = 0; i < 25; i++) {
blockXs.push(i*20);
}
var Button = function (x, y, w, h, color, text, size, font, textcolor, best) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.text = text;
this.size = size;
this.font = font;
this.textcolor = textcolor;
this.best = best;
};
Button.prototype.draw = function() {
rectMode(CORNER);
fill(this.color);
rect(this.x, this.y, this.w, this.h);
fill(this.textcolor);
stroke(this.textcolor);
textFont(this.font, this.size);
text(this.text, this.x + (this.w/2 - this.w/2.5), this.y + (this.h/2 + this.size/2.5));
/*textFont(this.font, this.size / 2);
text("Best : " + this.best, this.x + 10, this.y + 90);*/
};
Button.prototype.clicked = function() {
if(mouseIsPressed && mouseX >= this.x && mouseX <= this.x + this.w && mouseY >= this.y && mouseY <= this.y + this.h ) {
return true;
}
};
var nextButton = new Button(315, 360, 75, 30, color(0, 255, 0), "Next Level", 12, "Aerial Bold", color(0, 0, 0));
var startButton = new Button(315, 360, 75, 30, color(0, 255, 0), "Start Again", 12, "Aerial Bold", color(0, 0, 0));
var playButton = new Button(140, 250, 120, 50, color(0, 0, 0), "PLAY", 40, "Aerial Bold", color(255, 255, 255));
var level1Button = new Button(30, 120, 100, 100, color(0, 0, 0), "Level 1", 25, "Aerial Bold", color(255, 255, 255));
var level2Button = new Button(140, 120, 100, 100, color(0, 0, 0), "Level 2", 25, "Aerial Bold", color(255, 255, 255));
var level3Button = new Button(250, 120, 100, 100, color(0, 0, 0), "Level 3", 25, "Aerial Bold", color(255, 255, 255));
var drawWin = function() {
fill(255, 0, 0);
textSize(36);
text("YOU WIN!!!!", 100, 200);
nextButton.draw();
};
var drawLoss = function() {
fill(255, 0, 0);
textSize(36);
text("YOU LOSE!!!!", 100, 200);
startButton.draw();
};
var movement = function() {
if (keyIsPressed) {
if(keyCode === UP) {
beaver.hop();
} /*else if(keyCode === LEFT) {
beaver.hopLeft();
} else if(keyCode === RIGHT) {
beaver.hopRight();
} */
} else { beaver.fall();}
};
var drawScore = function() {
fill(0, 255, 0);
textSize(18);
text("Score: " + beaver.sticks, 10, 390);
};
var isWin = function() {
if(beaver.sticks >= target) {
drawWin();
speed = 1;
return true;
}
};
var isLoss = function() {
if (beaver.sticks < target ) {
speed = 1;
drawLoss();
return true;
}
};
var drawBackground = function() {
//static
speed = 1;
background(227, 254, 255);
stroke(0, 0, 0);
rectMode(CORNER);
rect(0, height*0.90, width, height*0.10);
for (var i = 0; i < grassXs.length; i++) {
image(getImage("cute/GrassBlock"), grassXs[i], height*0.85, 35, 20);
image(getImage("cute/DirtBlock"), grassXs[i], height*0.85, 35, 60);
grassXs[i] -= speed;
if (grassXs[i] <= - 20) {
grassXs[i] = width;
}
}
};
var drawSticks = function() {
for (var i = 0; i < sticks.length; i++) {
sticks[i].draw();
beaver.checkForStickGrab(sticks[i]);
sticks[i].x -= speed;
}
};
var drawBadSticks = function() {
for (var i = 0; i < badSticks.length; i++) {
badSticks[i].draw();
beaver.checkForBadStickGrab(badSticks[i]);
badSticks[i].x -= speed;
}
};
var drawRocks = function() {
for (var i = 0; i < rocks.length; i++) {
rocks[i].draw();
beaver.checkForRockHit(rocks[i]);
rocks[i].y += speed;
}
};
var drawLevel = function() {
speed = 1;
drawBackground();
if (level === 1) {
target = 1;
drawSticks();
}
if (level === 2) {
target = 1;
drawSticks();
drawBadSticks();
}
if (level === 3) {
target = 1;
drawBadSticks();
drawSticks();
drawRocks();
}
beaver.draw();
movement();
drawScore();
if (sticks[nosOfSticks - 1].x < -5) {
isWin();
isLoss();
}
};
var drawLevels = function() {
level = "l";
background(0, 0, 0);
level1Button.draw();
level2Button.draw();
level3Button.draw();
if (level1Button.clicked() && level === "l") {
level = 1;
drawLevel();
} else if (level2Button.clicked() && level === "l") {
level = 2;
drawLevel();
} else if (level3Button.clicked() && level === "l") {
level = 3;
drawLevel();
}
};
var drawStart = function() {
level = 0;
background(0);
text("Hoppy Beaver", 75, 50);
text("Extreme", 120, 100);
playButton.draw();
if (playButton.clicked() && level === 0) {
levelButtonEnabled = false;
drawLevels();
}
};
//drawStart();
mouseClicked = function() {
if (nextButton.clicked() || startButton.clicked()) {
if (beaver.sticks >= 1) {
if (level === 0) {
level = 1;
sticks = [];
draw();
isWin = false;
}
if (level === 1) {
level = 2;
sticks = [];
draw();
isWin = false;
}
if (level === 2) {
level = 3;
sticks = [];
draw();
isWin = false;
}
if (level === 3) {
level = 1;
sticks = [];
isWin = false;
draw();
}
} else if (beaver.sticks < 1) {
if (level === 1) {
level = 1;
sticks = [];
drawLevel();
isLoss = false;
}
if (level === 2) {
level = 2;
sticks = [];
drawLevel();
isLoss = false;
}
if (level === 3) {
level = 3;
sticks = [];
drawLevel();
isLoss = false;
}
}
}
};
draw = function() {
speed = 1;
if (level === 1) {
drawLevel();
} else if (level === 2) {
drawLevel();
} else if (level === 3) {
drawLevel();
} else if (level === "l") {
drawLevels();
} else { drawStart(); }
};
welcome to stackoverflow. The problem with your code is this bit right here in the drawLevel function.
if (sticks[nosOfSticks - 1].x < -5) {
isWin();
isLoss();
}
At the start of your program you initialize the sticks array with some stick objects in line 124. When level 1 ends and the next button is clicked, you set the sticks array to an empty array sticks=[] in the mouseClicked function.However, you never re-add anything into the sticks array. Thus, when that block of code runs, the element at position nosOfSticks-1 is undefined, leading to your problem.My suggestion is to make a for loop after sticks=[] to refill the sticks array just like in line 124.
Good Luck!
Also, take a look at this guide for debugging help, how to debug small programs.
i have a simpel game but when the red ball hits the blue ball while in motion the SPLICING desen't work i get the error form the movement script. I think the best solution to this problem is to registrer a collition when only the red ball hits the blu ball. can somone help me whith that?
To se a demo clik the linkDEMO press R to restart
Code:
var canvas = document.getElementById("canvas");
ctx = canvas.getContext("2d");
var tileldig = Math.floor((Math.random() * 300) + 1);
var tekst = document.getElementById("tekst")
var log = document.getElementById("log")
var highlog = document.getElementById("highlog")
var kuler = [{
r: 10,
x: canvas.width / 2,
y: canvas.height - 100,
f: "red",
dy: 0
}, ];
var fiender = [{
r: 20,
x: tileldig,
y: -20,
vx: 0,
vy: 1,
}, ];
//var snd = new Audio("Skudd.m4a");
var poeng = 0;
var highscore = 0;
var høyre = 0;
var venstre = 0;
var opp = 0;
var ned = 0;
var restart = 0;
var død = 0;
document.onkeydown = function tast(e) {
if (e.keyCode == 39) { // høyre
høyre = 1;
}
if (e.keyCode == 37) { // venstre
venstre = 1;
}
if (e.keyCode == 38) { // opp
opp = 1;
}
if (e.keyCode == 40) { // ned
ned = 1;
}
if (e.keyCode == 32) {
newskudd();
// snd.play();
console.log("hit space")
}
if (e.keyCode == 82) {
init();
log.innerHTML += ("Poeng: " + poeng)
poeng = 0;
}
}
document.onkeyup = function tast2(e) {
if (e.keyCode == 39) { // høyre
høyre = 0;
}
if (e.keyCode == 37) { // venstre
venstre = 0;
}
if (e.keyCode == 38) { // opp
opp = 0;
}
if (e.keyCode == 40) { // ned
ned = 0;
}
}
function spill() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var i = 0; i < kuler.length; i++) {
kuler[i].x += 0;
kuler[i].y += kuler[i].dy;
ctx.fillStyle = kuler[i].f;
ctx.beginPath();
ctx.arc(kuler[i].x, kuler[i].y, kuler[i].r, 2 * Math.PI, 0);
ctx.closePath();
ctx.fill();
if (kuler[0].x >= canvas.width - kuler[0].r) {
kuler[0].x = canvas.width - kuler[0].r
};
if (kuler[0].x <= 0 + kuler[0].r) {
kuler[0].x = 0 + kuler[0].r
};
if (kuler[0].y >= canvas.height - kuler[0].r) {
kuler[0].y = canvas.height - kuler[0].r
};
if (kuler[0].y <= 0 + kuler[0].r) {
kuler[0].y = 0 + kuler[0].r
};
for (var j = 0; j < fiender.length; j++) {
ctx.fillStyle = "blue";
ctx.beginPath();
ctx.arc(fiender[j].x, fiender[j].y, fiender[j].r, 2 * Math.PI, 0);
ctx.closePath();
ctx.fill();
if (fiender[j].x >= canvas.width - fiender[j].r) {
fiender[j].x = canvas.width - fiender[j].r;
};
if (fiender[j].x <= 0 + fiender[j].r) {
fiender[j].x = 0 + fiender[j].r;
};
if (fiender[j].vy >= 2) {
fiender[j].vy = 2;
};
var distanceFromCenters = Math.sqrt(Math.pow(Math.abs(fiender[j].x - kuler[i].x), 2) + Math.pow(Math.abs(fiender[j].y - kuler[i].y), 2)); // you have a collision
if (distanceFromCenters <= (fiender[j].r + kuler[i].r)) {
fiender.splice(j, 1);
kuler.splice(i, 1);
poeng += 1;
restart = 1;
} else if (fiender[j].y > canvas.height) {
fiender.splice(j, 1)
}
if (j > 1) {
fiender.splice(j, 1)
}
log.innerHTML = ("<br>" + "Score denne runden: " + poeng + "</br>" + "<br>" + "Highscore: " + highscore + "</br>")
if (poeng >= highscore) {
log.innerHTML += ("<br>" + "Ny Highscore: " + highscore + "</br>")
highscore = poeng;
}
}
}
for (var j = 0; j < fiender.length; j++) {
fiender[j].y += fiender[j].vy;
}
if (venstre == 1) {
kuler[0].x -= 4;
}
if (høyre == 1) {
kuler[0].x += 4;;
}
if (opp == 1) {
kuler[0].y -= 4;
}
if (ned == 1) {
kuler[0].y += 4;
}
requestAnimationFrame(spill);
return;
}
document.onload = spill();
function newskudd() {
var nyttskudd = {
x: kuler[0].x,
y: kuler[0].y,
r: 5,
dy: -5,
f: "white"
};
kuler.push(nyttskudd);
};
setInterval(function() {
fiender.push({
r: 20,
x: Math.floor((Math.random() * 300) + 1),
y: -20,
vx: 0,
vy: 1,
f: "green"
});
}, 1000);
function init() {
kuler = [{
r: 10,
x: canvas.width / 2,
y: canvas.height - 100,
f: "red",
dy: 0
}, ];
fiender = [{
r: 20,
x: tileldig,
y: -20,
vx: 0,
vy: 1,
}, ];
}