Animated canvas background flashing? - javascript

I'm attempting to make a typing game with moving words on a canvas, which move left to right and lives are lost if they leave the canvas however i'm trying to animate a simple looping background image for my canvas, I have gotten it working and looping and moving left, however for some reason when this is in use my entire canvas is flashing as if it is constantly redrawing in a strange way or something I don't really know.
var canvas;
var canvasContext;
let x=20;
var string;
let score = 0;
let highscore = 0;
var lives = 3;
var WordID;
var difficultyWordID
var bg = new Image();
bg.src = "client/img/stars.jpg";
window.onload = function(){
canvas = document.getElementById('typingCanvas');
var typeval = document.getElementById("typingValue"); //user typed value.
canvasContext = canvas.getContext('2d');
document.getElementById("Button2").style.display = "none";
document.getElementById("gameOver").style.display = "none";
document.getElementById("scoreText").style.display = "none";
let fps=40;
setInterval(function(){
if(x==20){
string = getWord()
}
moveEverything()
drawEverything(x,string);
if (x>900) {
lives--;
} else if (lives<1) {
canvas.style.display="none";
document.getElementById("Button2").style.display = "block";
document.getElementById("GameTable").style.display = "none";
document.getElementById("gameHR2").style.display = "none";
document.getElementById("gameHR3").style.display = "none";
document.getElementById("gameOver").style.display = "block";
document.getElementById("scoreText").style.display = "block";
document.getElementById("GameHeading").textContent = "Results below: ";
document.getElementById("scoreText").textContent = "Your Score: " + score;
function updateUserScore() {
fetch("/leaderboard/update", {method: 'post', body: formData}
).then(response => response.json()
).then(responseData => {
if (responseData.hasOwnProperty('error')) {
alert(responseData.error);
} else {
}
});
}
}
if(x>900 || check()){
x=20;
document.getElementById("val").value = ''; //if inputed value get match then blank the input box.
}
},1000/fps)
}
function drawEverything(x,string ){ // draws text etc
canvasContext.fillStyle="rgba(0,0,200,0)"; // background colour
canvasContext.border="white"
canvasContext.fillRect(20,20,canvas.width,canvas.height);
drawString(x,string);
scoreBoard(score);
highScoreBoard(highscore);
}
function moveEverything(){
x+=4; // movement speed of the word
}
function drawString(x,string) {
canvasContext.font="30px Verdana";
canvasContext.fillStyle='gray';
canvasContext.fillText(string,x,280); // place of text appearing.
}
function Background(){ // sets background
this.x = 0, this.y = 0, this.w = bg.width, this.h = bg.height;
this.render = function(){
canvasContext.drawImage(bg, this.x--, 0);
if(this.x <= -499){
this.x = 0;
}
}
}
var background = new Background(); // actual background animation
function animate(){
background.render();
}
var animateInterval = setInterval(animate, 40);
function getWord(WordID) {
WordID = Math.floor(Math.random()*30) +1
difficultyWordID = WordID
if (WordID === null) {
} else
fetch("/words/single/" + WordID, {method: 'get'}
).then(response => response.json()
).then(responseData => {
if (responseData.hasOwnProperty('error')) {
alert(responseData.error);
} else {
string = responseData.Definition;
}
});
}
function check(WordID){
var userVal = document.getElementById("val").value;
if(userVal==string){
return true;
}
return false;
}
function scoreVal(){
if(check()){
fetch("/words/single/" + difficultyWordID, {method: 'get'}
).then(response => response.json()
).then(responseData => {
if (responseData.hasOwnProperty('error')) {
alert(responseData.error);
} else {
let difficultyScore = 1;
difficultyScore = responseData.Difficulty;
score=score + difficultyScore;
}
});
}
}
function highScoreVal(){
if(score>highscore){
highscore=score;
}
}
function scoreBoard(score){
scoreVal(WordID);
canvasContext.fillStyle = "White";
canvasContext.font = "40px hot_sauceitalic";
canvasContext.fillText("Your Score: ",50,60);
canvasContext.fillStyle = "White";
canvasContext.fillText(score, 250, 60);
}
function highScoreBoard(highscore){
highScoreVal();
canvasContext.fillStyle = "White";
canvasContext.fillText("Lives:",750,60);
canvasContext.fillStyle = "White";
canvasContext.font = "40px hot_sauceitalic";
canvasContext.fillText(lives, 850, 60);
}
I am unsure how to go about fixing this as I cant really work out the problem myself, I am assuming that it is to do with how it is drawing the background alongside the moving words.
EDIT - Tried using background-image and got this instead.
https://i.stack.imgur.com/UhNai.png

Related

I can't reset the image on JavaScript

I can't reset the image on javascript, codepen say imagem in not defined.
Codepen link: https://codepen.io/AlissonTelez/pen/ExPJBvv
Thats variables:
var originalImage;
var grayImage = null;
var redImage = null;
var rainbowImage = null;
var windowImage = null;
var canvas = document.getElementById("can1");
thats function to make filter red:
function makeRedy() {
if (imgCarregada(imagemRedy)) {
filtroVermelho();
var canNovo = document.getElementById("can");
imagemRedy.drawTo(canvas);
}
}
function filtroVermelho() {
for (var pixel2 of imagemRedy.values()) {
avg2 = (pixel2.getRed()+pixel2.getGreen()+pixel2.getBlue()/3);
if (avg2 < 128) {
pixel2.setRed(2*avg2);
pixel2.setGreen(0);
pixel2.setBlue(0);
}
else {
pixel2.setRed(255);
pixel2.setGreen((2*avg2)-255);
pixel2.setBlue((2*avg2)-255);
}
}
}
that's reset function:
function resete() {
if (imgCarregada(imagem)) {
imagem.drawTo(canvas);
}
}
function imgCarregada(x) {
if (x === null) {
return false;
}
else if (x !== null) {
return true;
}
}
You have not defined imagem. But it appears your original image is being stored as imagemOriginal.
Change your resete() function to this;
function resete() {
if (imgCarregada(imagemOriginal)) {
imagemOriginal.drawTo(canvas);
}
}
Based on your CodePen. Which appears to hold different values to what you pasted in your question.
read my comments in code and try understand what's new
// for checking later if null or not
var imagemOriginal = null;
var imagemRedy = null;
var imagemGray = null;
var avg;
var avg2;
// ctx for canvas api 2d
var canvas , ctx;
function upload() {
var img = document.getElementById("Finput");
canvas = document.getElementById("can");
// defined canvas context 2d for drawing and accessing all canvas api
ctx = canvas.getContext("2d");
imagemOriginal = new SimpleImage(img);
imagemGray = new SimpleImage(img);
imagemRedy = new SimpleImage(img);
imagemOriginal.drawTo(canvas);
}
// calling upload as first step for making canvas ready
upload();
function makeGray() {
if (imgCarregada(imagemGray)) {
filtroCinza();
var canNovo = document.getElementById("can");
imagemGray.drawTo(canvas);
}
}
function filtroCinza() {
for (var pixel of imagemGray.values()) {
avg = (pixel.getRed()+pixel.getGreen()+pixel.getBlue())/3;
pixel.setRed(avg);
pixel.setGreen(avg);
pixel.setBlue(avg);
}
}
function makeRedy() {
if (imgCarregada(imagemRedy)) {
filtroVermelho();
var canNovo = document.getElementById("can");
imagemRedy.drawTo(canvas);
}
}
function filtroVermelho() {
for (var pixel2 of imagemRedy.values()) {
avg2 = (pixel2.getRed()+pixel2.getGreen()+pixel2.getBlue()/3);
if (avg2 < 128) {
pixel2.setRed(2*avg2);
pixel2.setGreen(0);
pixel2.setBlue(0);
}
else {
pixel2.setRed(255);
pixel2.setGreen((2*avg2)-255);
pixel2.setBlue((2*avg2)-255);
}
}
}
// in resete function you put arguments not exist 'imagem' ! and that give you error
// soo sloution is checking 'imagemOriginal'
function resete() {
// soo here do your check // if true call restCanvas for make canvas clear :)
if (imgCarregada(imagemOriginal)) resetCanvas();
}
// this function using 'ctx' or canvas context for make canvas clean
function resetCanvas(){
// fillstyle for select your draw color
ctx.fillStyle = "white";
// fillrect for draw with resloution :)
ctx.fillRect(0,0,canvas.width,canvas.height);
}
// here just syntax better :)
function imgCarregada(x) {
if (x === null) return false;
else if (x !== null) return true;
}

Uncaught Type error: is not a function

I am making a javascript game, using Canvas. It works well superficially, but "Uncaught TypeError: game_state.Update is not a function" keeps going. I cannot know the reason for all day...How can I solve the problem?
error image1, error image2
Suspected files are below.
gfw.js
function onGameInit()
{
document.title = "Lion Travel";
GAME_FPS = 30;
debugSystem.debugMode = true;
//resourcePreLoading
resourcePreLoader.AddImage("/.c9/img/title_background.png");
resourcePreLoader.AddImage("/.c9/img/title_start_off.png");
resourcePreLoader.AddImage("/.c9/img/title_start_on.png");
resourcePreLoader.AddImage("/.c9/img/title_ranking_off.png");
resourcePreLoader.AddImage("/.c9/img/title_ranking_on.png");
resourcePreLoader.AddImage("/.c9/img/game_background_sky.png");
soundSystem.AddSound("/.c9/background.mp3", 1);
after_loading_state = new TitleState();
game_state = TitleState;
setInterval(gameLoop, 1000 / GAME_FPS);
}
window.addEventListener("load", onGameInit, false);
GameFramework.js
window.addEventListener("mousedown", onMouseDown, false);
window.addEventListener("mouseup", onMouseUp, false);
var GAME_FPS;
var game_state;
function onMouseDown(e)
{
if(game_state.onMouseDown != undefined)
game_state.onMouseDown(e);
// alert("x:" + inputSystem.mouseX + " y:" + inputSystem.mouseY);
}
function onMouseUp(e)
{
if(game_state.onMouseUp != undefined)
game_state.onMouseUp(e);
}
function ChangeGameState(nextGameState)
{
if(nextGameState.Init == undefined)
return;
if(nextGameState.Update == undefined)
return;
if(nextGameState.Render == undefined)
return;
game_state = nextGameState;
game_state.Init();
}
function GameUpdate()
{
timerSystem.Update();
**game_state.Update();**
debugSystem.UseDebugMode();
}
function GameRender()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
game_state.Render();
if(debugSystem.debugMode)
{
Context.fillStyle = "#ffffff";
Context.font = '15px Arial';
Context.textBaseline = "top";
Context.fillText("fps: "+ frameCounter.Lastfps, 10, 10);
}
}
function gameLoop()
{
game_state = after_loading_state;
GameUpdate();
GameRender();
frameCounter.countFrame();
}
RS_Title.js
function TitleState()
{
this.imgBackground = resourcePreLoader.GetImage("/.c9/img/title_background.png");
this.imgButtonStartOff = resourcePreLoader.GetImage("/.c9/img/title_start_off.png");
this.imgButtonStartOn = resourcePreLoader.GetImage("/.c9/img/title_start_on.png");
this.imgButtonRankingOff = resourcePreLoader.GetImage("/.c9/img/title_ranking_off.png");
this.imgButtonRankingOn = resourcePreLoader.GetImage("/.c9/img/title_ranking_on.png");
soundSystem.PlayBackgroundMusic("/.c9/background.mp3");
return this;
}
TitleState.prototype.Init = function()
{
soundSystem.PlayBackgroundMusic("/.c9/background.mp3");
};
TitleState.prototype.Render = function()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
Context.drawImage(this.imgBackground, 0, 0);
//drawing button
if(inputSystem.mouseX > 170 && inputSystem.mouseX < 170+220
&& inputSystem.mouseY > 480 && inputSystem.mouseY < 480+100)
{
Context.drawImage(this.imgButtonStartOn, 170, 480);
this.flagButtonStart = true;
}
else
{
Context.drawImage(this.imgButtonStartOff, 170, 480);
this.flagButtonStart = false;
}
if(inputSystem.mouseX > 420 && inputSystem.mouseX < 420+220
&& inputSystem.mouseY > 480 && inputSystem.mouseY < 480+100)
{
Context.drawImage(this.imgButtonRankingOn, 420, 480);
this.flagButtonRanking = true;
}
else
{
Context.drawImage(this.imgButtonRankingOff, 420, 480);
this.flagButtonRanking = false;
}
};
TitleState.prototype.Update = function()
{
};
TitleState.prototype.onMouseDown = function()
{
if(this.flagButtonStart)
ChangeGameState(new PlayGameState());
after_loading_state = PlayGameState;
game_state = PlayGameState;
if(this.flagButtonRanking)
ChangeGameState();
};
RS_PlayGame.js
function PlayGameState()
{
this.imgBackgroundSky = resourcePreLoader.GetImage("/.c9/img/game_background_sky.png");
}
PlayGameState.prototype.Init = function()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
Context.drawImage(this.imgBackgroundSky, 0, 0);
};
PlayGameState.prototype.Render = function()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
Context.drawImage(this.imgBackgroundSky, 0, 0);
};
PlayGameState.prototype.Update = function()
{
var theCanvas = document.getElementById("GameCanvas");
var Context = theCanvas.getContext("2d");
Context.drawImage(this.imgBackgroundSky, 0, 0);
};
As mentioned by the others, in the onMouseDown method you are assigning after_loading_state and game_state to PlayGameState which is a function and not an object. So later on when you want to access the Update method, it simply doesn't exist, because it is defined over the object prototype and not the function. You might want to do something like this so that you also avoid instantiating (calling) PlayGameState multiple times:
game_state = new PlayGameState();
ChangeGameState(game_state);
after_loading_state = game_state;

Trying to select lines or rectangles on a canvas

I want to be able to click any line(muscle) and new line then highlight it in my program like I can do with the nodes right now. I want to use context.isPointInPath(), but I feel like that will be too limiting in the fact that the lines are only 1 pixel wide. And now I want to look at changing the lines to rectangles. Because then I would be able to just see if the mouseclick is within the rectangle height and width. But, I'm having trouble finding out a way to connect the rectangle to two nodes like I have it with the strokes right now.
My program so far:
/*jshint esversion: 6 */
//draw everything on canvas
//TODO: Change use of canvas to a container and moving elements around to avoid the buffer of frame drawing
//Node class
class Node {
constructor(x, y, r, color, highlight, highlightColor) {
this.x = x;
this.y = y;
this.r = r || 20;
this.color = color || "#ff0";
this.highlight = highlight || false;
this.highlightColor = highlightColor || "#0000FF";
}
}
//Muscle class
class Muscle {
constructor(node1, node2, width, color) {
this.node1 = node1;
this.node2 = node2;
this.width = width || 5;
this.color = color || "#f00";
//Properties of the nodes this muscle attaches to
Object.defineProperties(this, {
node1x: {
"get": () => this.node1.x,
"set": x => {
this.node1.x = x;
}
},
node1y: {
"get": () => this.node1.y,
"set": y => {
this.node1.y = y;
}
},
node2x: {
"get": () => this.node2.x,
"set": x => {
this.node2.x = x;
}
},
node2y: {
"get": () => this.node2.y,
"set": y => {
this.node2.x = y;
}
}
});
}
}
function setParentForNodes() {
this.nodes.forEach(node => {
node.parentCreature = this;
});
}
class Creature {
constructor(nodes, muscles, nodeColors) {
this.nodes = nodes;
this.muscles = muscles;
this.nodeColors = nodeColors || "#ff0";
setParentForNodes.call(this);
Object.defineProperties(this, {
creatureNumber: {
"get": () => creatures.indexOf(this),
}
});
}
addNewNode(newNode) {
newNode.parentCreature = this;
this.nodes.push(newNode);
}
addNewNodes(newNodes) {
newNodes.forEach(function(node) {
node.parentCreature = this;
}, this);
this.nodes = this.nodes.concat(newNodes);
}
}
var nodes = [
new Node(100, 100),
new Node(200, 200)
];
var muscles = [
new Muscle(nodes[0], nodes[1])
];
var creatures = [
new Creature(nodes, muscles)
];
var addNodePressed = false;
var attachMusclePressed = false;
var addLimbPressed = false;
function draw(container, ctx, nodes, creatureMuscles) {
//draw in the container
ctx.fillStyle = "#000000";
ctx.fillRect(container.y, container.x, container.width, container.height);
// for loop to draw all objects of nodes
for (let i = 0; i < creatures.length; i++) {
var creatureNodes = creatures[i].nodes;
for (let i = 0; i < creatureNodes.length; i++) {
ctx.beginPath();
ctx.arc(creatureNodes[i].x, creatureNodes[i].y, creatureNodes[i].r, 0, 2 * Math.PI);
ctx.fillStyle = creatureNodes[i].color;
ctx.closePath();
ctx.fill();
//check if node needs to be highlighted
if (creatureNodes[i].highlight == true) {
ctx.beginPath();
ctx.arc(creatureNodes[i].x, creatureNodes[i].y, creatureNodes[i].r, 0, 2 * Math.PI);
ctx.strokeStyle = creatureNodes[i].highlightColor;
ctx.lineWidth = 5; // for now
ctx.closePath();
ctx.stroke();
}
}
creatureMuscles = creatures[i].muscles;
//loop and draw every muscle
for (let i = 0; i < creatureMuscles.length; i++) {
ctx.beginPath();
ctx.moveTo(creatureMuscles[i].node1x, creatureMuscles[i].node1y);
ctx.lineTo(creatureMuscles[i].node2x, creatureMuscles[i].node2y);
ctx.strokeStyle = creatureMuscles[i].color;
ctx.lineWidth = creatureMuscles[i].width;
ctx.closePath();
ctx.stroke();
}
}
}
//Handle moving a node with mousedrag
function handleMouseDrag(canvas, creatureNodes) {
var isDrag = false;
var dragNode;
var offset = {
x: 0,
y: 0,
x0: 0,
y0: 0
};
canvas.addEventListener("mousedown", function(e) {
//mousedown then save the position in var x and y
var x = e.offsetX,
y = e.offsetY;
//loop through all the nodes to find the first node that is within radius of the mouse click
for (let i = 0; i < creatures.length; i++) {
var creatureNodes = creatures[i].nodes;
for (let i = 0; i < creatureNodes.length; i++) {
if (Math.pow(x - creatureNodes[i].x, 2) + Math.pow(y - creatureNodes[i].y, 2) < Math.pow(creatureNodes[i].r, 2)) {
isDrag = true;
dragNode = creatureNodes[i];
//offset.x&y = where the node is currently
//offset x0&y0 = where the user clicked
offset = {
x: dragNode.x,
y: dragNode.y,
x0: x,
y0: y
};
return;
}
}
}
});
// when mouse moves and isDrag is true, move the node's position
canvas.addEventListener("mousemove", function(e) {
/*when the user moves the mouse, take the difference of where his mouse is right now and where the user clicked.
Then, add that to where the node is right now to find the correct placement of the node without centering on your mouse
*/
if (isDrag) {
dragNode.x = e.offsetX - offset.x0 + offset.x; // where the mouse is right now - where the user mousedown + where the node is right now
dragNode.y = e.offsetY - offset.y0 + offset.y;
}
});
canvas.addEventListener("mouseup", function(e) {
isDrag = false;
});
canvas.addEventListener("mouseleave", function(e) {
isDrag = false;
});
}
//Handle highlighting and button functionality
function handleMouseClick(canvas, nodes, muscles) {
var highlighted;
var highlightedNode;
canvas.addEventListener("mousedown", function(e) {
var x = e.offsetX,
y = e.offsetY;
var loopbreak = false;
for (let i = 0; i < creatures.length; i++) {
var creatureNodes = creatures[i].nodes;
for (let i = 0; i < creatureNodes.length; i++) {
// check if click is within radius of a node, if it is, highlight and set highlight boolean to true.
if (Math.pow(x - creatureNodes[i].x, 2) + Math.pow(y - creatureNodes[i].y, 2) < Math.pow(creatureNodes[i].r, 2)) {
var clickedNode = creatureNodes[i];
if (addNodePressed) {
console.log("Not valid. Cannot add a node on top of another node.");
loopbreak = true;
break;
} else if (addLimbPressed) {
console.log("Not valid. Cannot add a limb on top of another node.");
loopbreak = true;
break;
} else if (attachMusclePressed) {
if (highlightedNode == clickedNode) {
console.log("Not valid. Cannot attach muscle to the same node.");
loopbreak = true;
break;
} else {
var newMuscle;
if (highlightedNode.parentCreature.creatureNumber == clickedNode.parentCreature.creatureNumber) {
newMuscle = new Muscle(highlightedNode, clickedNode);
highlightedNode.parentCreature.muscles.push(newMuscle);
attachMuscle();
highlightedNode.highlight = false;
highlighted = false;
devTools(true, false, false, false);
} else {
var newNodes = [];
var newMuscles = [];
if (highlightedNode.parentCreature.creatureNumber > clickedNode.parentCreature.creatureNumber) {
highlightedNode.parentCreature.nodes.forEach(function(node) {
newNodes.push(node);
});
highlightedNode.parentCreature.muscles.forEach(function(muscle) {
newMuscles.push(muscle);
});
newMuscle = new Muscle(highlightedNode, clickedNode);
clickedNode.parentCreature.muscles.push(newMuscle);
clickedNode.parentCreature.muscles = clickedNode.parentCreature.muscles.concat(newMuscles);
creatures.splice(creatures.indexOf(highlightedNode.parentCreature), 1);
clickedNode.parentCreature.addNewNodes(newNodes);
} else {
clickedNode.parentCreature.nodes.forEach(function(node) {
newNodes.push(node);
console.log("Clicked node is bigger.");
});
clickedNode.parentCreature.muscles.forEach(function(muscle) {
newMuscles.push(muscle);
});
newMuscle = new Muscle(highlightedNode, clickedNode);
highlightedNode.parentCreature.muscles.push(newMuscle);
highlightedNode.parentCreature.muscles = highlightedNode.parentCreature.muscles.concat(newMuscles);
creatures.splice(creatures.indexOf(clickedNode.parentCreature), 1);
highlightedNode.parentCreature.addNewNodes(newNodes);
}
highlightedNode.highlight = false;
attachMuscle();
devTools(true, false, false, false);
}
}
}
//no button pressed - highlight/unhighlight node
else {
if (highlighted || creatureNodes[i].highlight) {
if (highlightedNode != creatureNodes[i]) {
highlightedNode.highlight = false;
highlightedNode = creatureNodes[i];
highlightedNode.highlight = true;
devTools(false, true, true, true);
} else {
highlightedNode = creatureNodes[i];
highlightedNode.highlight = false;
highlighted = false;
highlightedNode = undefined;
devTools(true, false, false, false);
}
} else {
highlightedNode = creatureNodes[i];
highlightedNode.highlight = true;
highlighted = true;
devTools(false, true, true, true);
}
loopbreak = true;
break;
}
}
}
}
// if click was not in radius of any nodes then check for add limb or create node button press.
if (!loopbreak) {
loopbreak = false;
var newNode;
if (addNodePressed) {
newNode = new Node(x, y);
let newNodes = [];
let newMuscles = [];
newNodes.push(newNode);
var newCreature = new Creature(newNodes, newMuscles);
creatures.push(newCreature);
addNode();
addNodePressed = false;
devTools(true, false, false, false);
} else if (addLimbPressed) {
newNode = new Node(x, y);
let newMuscle = new Muscle(newNode, highlightedNode);
highlightedNode.parentCreature.addNewNode(newNode);
highlightedNode.parentCreature.muscles.push(newMuscle);
addLimb();
addLimbPressed = false;
highlightedNode.highlight = false;
highlighted = false;
highlightedNode = undefined;
devTools(true, false, false, false);
}
}
});
}
//Handle Devtools
function devTools(addNode, removeNode, attachMuscle, addLimb) {
var creatureNumberHTML = document.getElementById("creatureNumber");
var selectedHTML = document.getElementById("selected");
var addNodeB = document.getElementById("addNode");
var removeNodeB = document.getElementById("removeNode");
var attachMuscleB = document.getElementById("attachMuscle");
var addLimbB = document.getElementById("addLimb");
addNodeB.disabled = (addNode) ? false : true;
removeNodeB.disabled = (removeNode) ? false : true;
attachMuscleB.disabled = (attachMuscle) ? false : true;
addLimbB.disabled = (addLimb) ? false : true;
for (let i = 0; i < creatures.length; i++) {
var creatureNumber = i;
var creatureNodes = creatures[i].nodes;
for (let i = 0; i < creatureNodes.length; i++) {
if (creatureNodes[i].highlight == true) {
selectedHTML.innerHTML = `Selected: ${i} node`;
creatureNumberHTML.innerHTML = `Creature number: ${creatureNumber}`;
return;
} else {
creatureNumberHTML.innerHTML = "Creature number: -";
selectedHTML.innerHTML = "Selected: None";
}
}
}
}
//Handle add node button
function addNode() {
var addNodeB = document.getElementById("addNode");
if (addNodePressed) {
addNodePressed = false;
addNodeB.style.background = "";
} else {
addNodePressed = true;
addNodeB.style.backgroundColor = "#808080";
//and unhighlight
}
}
//Handle remove node button
function removeNode() {
for (let i = 0; i < creatures.length; i++) {
var creatureNodes = creatures[i].nodes;
var creatureMuscles = creatures[i].muscles;
for (let i = 0; i < creatureNodes.length; i++) {
if (creatureNodes[i].highlight == true) {
let highlightedNode = creatureNodes[i];
for (let i = 0; i < creatureMuscles.length; i++) {
if (creatureMuscles[i].node1 == highlightedNode || creatureMuscles[i].node2 == highlightedNode) {
creatureMuscles.splice(i, 1);
i--;
}
}
creatureNodes.splice(i, 1);
}
}
}
devTools(true, false, false, false);
}
//Handle attach muscle button
function attachMuscle() {
var attachMuscleB = document.getElementById("attachMuscle");
if (attachMusclePressed) {
attachMusclePressed = false;
attachMuscleB.style.background = "";
} else {
attachMusclePressed = true;
attachMuscleB.style.backgroundColor = "#808080";
}
}
//Handle add limb button
function addLimb() {
var addLimbB = document.getElementById("addLimb");
if (addLimbPressed) {
addLimbPressed = false;
addLimbB.style.background = "";
} else {
addLimbPressed = true;
addLimbB.style.backgroundColor = "#808080";
}
}
//Main - Grabs document elements to draw a canvas on, init node and muscle arrays and then continuously updates frame to redraw
function main() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var container = {
x: 0,
y: 0,
get width() {
return canvas.width;
},
get height() {
return canvas.height;
}
};
handleMouseDrag(canvas, nodes);
handleMouseClick(canvas, nodes, muscles);
// refresh and redraw with new properties in an updateframe infinite loop
function updateFrame() {
ctx.save();
draw(container, ctx, nodes, muscles);
ctx.restore();
requestAnimationFrame(updateFrame);
}
updateFrame();
}
main();
#canvas {
display: block;
}
#info {
display: inline-block;
text-overflow: clip;
overflow: hidden;
margin-right: 200px;
}
#commands {
display: inline-block;
text-align: center;
margin-left: 200px;
}
#devTools {
background-color: aqua;
width: 1500px;
}
section {
width: 200px;
height: 200px;
background-color: grey;
vertical-align: top;
}
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" type="text/css" href="styles.css" />
</head>
<body>
<!--TODO: Adjust the size of the canvas to fit the window-->
<canvas id="canvas" width="1500" , height="600"></canvas>
<!--TODO: Create buttons for all devtools under the canvas-->
<!--TODO: Make a container for all devtools under the canvas, then add all the functionality to it after-->
<div id="devTools">
<section id="info">
<p>Info</p>
<p id="creatureNumber">Creature Number: -</p>
<p id="selected">Selected: </p>
</section>
<section id="commands">
<p>Commands</p>
<button type="button" id="addNode" onclick="addNode()">Add node</button>
<button type="button" id="removeNode" disabled=true onclick="removeNode()">Remove node</button>
<button type="button" id="attachMuscle" disabled=true onclick="attachMuscle()">Attach muscle</button>
<button type="button" id="addLimb" disabled=true onclick="addLimb()">Add Limb</button>
<div id="muscleLength">
<button type="button" id="increaseLengthB">↑</button>
<p>Muscle Length</p>
<button type="button" id="decreaseLengthB">↓</button>
</div>
</section>
</div>
<script src="scripts/script.js"></script>
</body>
</html>
Another way to solve this is to use a thicker line-width and use isPointInStroke() instead.
var ctx = c.getContext("2d");
var path = new Path2D(); // to store and reuse path
var onLine = false; // state (for demo)
path.moveTo(10, 10); // store a line on path
path.lineTo(200, 100);
ctx.lineWidth = 16; // line width
render(); // initial render
function render() {
ctx.clearRect(0,0,300,150);
ctx.strokeStyle = onLine ? "#09f" : "#000"; // color based on state
ctx.stroke(path); // stroke path
}
c.onmousemove = function(e) { // demo: is mouse on stroke?
onLine = ctx.isPointInStroke(path, e.clientX, e.clientY);
render();
};
body, html {margin:0}
<canvas id=c></canvas>
Note: IE11 does not support the path argument - for it you will need to use ordinary path on the context itself (ctx.moveTo etc.)

How can I get div to move up and down on hover? Mouseover and Mouseout conflict

I am trying to use run an animation using setInterval which works quiet well. Although I am trying to get the animation to run all the way through and then stop after mouse out.
I can get the div to move up and down but if you move the mouse in and out too fast it get's stuck in a loop of adding and subtracting pixels. Or other times it will stop moving altogether and get stuck at the top of bottom.
You can see the issue here, move the mouse in and out of the small box a few times fast.
https://jsfiddle.net/L16fdbrj/1/
Here is my Javascript:
var blog_folder_index = false;
var blog_folder_pos = 0;
var blog_folder_interval;
var framespeed = 5;
function blog_folder_mouseover()
{
if (blog_folder_index == false)
{
document.getElementById("blog_folder_button").style.cursor = "pointer";
blog_folder_interval = setInterval(function (){ blog_folder_add();}, 35);
}
}
function blog_folder_mouseout()
{
blog_folder_interval = setInterval(function (){ blog_folder_subtract();}, 50);
console.log("mouseout");
}
function blog_folder_add()
{
if (blog_folder_pos <= -30)
{
console.log(blog_folder_pos);
stop_function();
}
else if (blog_folder_pos > -30)
{
blog_folder_pos -= framespeed;
document.getElementById("blog_folder").style.marginTop = blog_folder_pos + 'px ';
}
}
function blog_folder_subtract()
{
if (blog_folder_pos >= 0)
{
console.log(blog_folder_pos);
stop_function();
}
else if (blog_folder_pos < 0)
{
blog_folder_pos += framespeed;
document.getElementById("blog_folder").style.marginTop = blog_folder_pos + 'px ';
}
}
function blog_folder_click()
{
blog_folder_index = true;
portfolio_folder_index = false;
about_folder_index = false;
document.getElementById("blog_folder_button").style.cursor = "default";
document.getElementById("portfolio_folder").style.zIndex = "2";
document.getElementById("blog_folder").style.zIndex = "3";
document.getElementById("about_folder").style.zIndex = "1";
blog_folder_interval = setInterval(function (){ blog_folder_subtract();}, 35);
}
function stop_function()
{
clearInterval(blog_folder_interval);
}
You simply need to clear your previous interval before creating a new one:
https://jsfiddle.net/L16fdbrj/2/
function blog_folder_mouseover() {
if (blog_folder_index == false) {
document.getElementById("blog_folder_button").style.cursor = "pointer";
// clear previous interval
stop_function();
blog_folder_interval = setInterval(function () {
blog_folder_add();
}, 35);
}
}
function blog_folder_mouseout() {
// clear previous interval
stop_function();
blog_folder_interval = setInterval(function () {
blog_folder_subtract();
}, 50);
console.log("mouseout");
}

Displaying frames properly in JavaScript

Okay, so I am developing a game in JavaScript. I have organized all the parts of the game in different JavaScript files. So, this is the Player.js file, every time I run this in my browser ( run from a html file of course), I come into this problem where the Player object flickers from a image to a transparent rectangle: heres the code:
function Player() {
this.frames = [];
this.right = true;
this.currentFrame = 0;
this.currentAction = "WALKING";
this.image = new Image();
this.x = 0;
this.y = 0;
this.setPosition = function(x, y) {
this.x = x;
this.y = y;
};
this.setVector = function(x, y) {
this.x += x;
this.y += y;
};
this.setAction = function(action) {
this.currentAction = action;
};
this.setRight = function(bool) {
this.right = bool;
}
this.draw = function(context) {
if(this.right == true) {
if(this.currentAction == "WALKING") {
this.frames = [ "res/playerRight.png" ];
}
} else if(this.right == false) {
if(this.currentAction == "WALKING") {
this.frames = [ "res/playerLeft.png" ];
}
}
if(this.currentFrame < this.frames.length) {
this.currentFrame += 1;
this.image.src = this.frames[this.currentFrame - 1];
context.drawImage(this.image, this.x,
this.y, 32, 32);
} else {
this.currentFrame = 0;
}
};
}
heres some images of what it does:
http://i.stack.imgur.com/1RcOC.png
http://i.stack.imgur.com/fxbNY.png
How about you preload all the images and you choose the correct one in your condition. Currently everytime you set the source the image is reloaded, and you are drawing it before it is ready.
// you can improve this part for your needs
var image1Loaded = false;
var image2Loaded = false;
this.preLoadImages = function (){
this.image1.onload = function (){
image1Loaded = true;
}
this.image2.onload = function (){
image2Loaded = true;
}
this.image1.src = "res/playerRight.png";
this.image2.src = "res/playerLeft.png";
}
now you can use the images directly in your draw method:
this.draw = function(context) {
var currentImage = "image1";
if(this.right == true) {
if(this.currentAction == "WALKING") {
currentImage = "image1";
}
} else if(this.right == false) {
if(this.currentAction == "WALKING") {
currentImage = "image2";
}
}
if(this.currentFrame < this.frames.length) {
this.currentFrame += 1;
var image = this[currentImage];
context.drawImage(image, this.x,
this.y, 32, 32);
} else {
this.currentFrame = 0;
}
};
Just make sure your images are already loaded before using them to draw on the canvas
Here's the bug:
if(this.currentFrame < this.frames.length) {
this.currentFrame += 1;
context.drawImage(); // <---------------- draw an image
} else {
this.currentFrame = 0; // <-------------- draw nothing!
}
So, let's run through this logic shall we. At the moment, frame length is 1.
currentFrame = 0
so we increment currentFrame
we draw the image
currentFrame = 1
currentFrame is not less than frames.length
we do not draw anything
we set current frame to 0
currentFrame = 0
so we increment currentFrame
we draw the image
repeat....
Result: flicker! If frame length is 2 it will flicker 33% of the time, if the frame length is 3 it will flicker 25% of the time etc.
The correct way to handle this:
this.currentFrame += 1;
if(this.currentFrame >= this.frames.length) {
this.currentFrame = 0;
}
this.image.src = this.frames[this.currentFrame]; // **
context.drawImage();
// **note: no need for -1 because currentFrame here is always
// less than frame.length
Or, if you're mathematical:
this.currentFrame = (this.currentFrame + 1) % this.frames.length;
this.image.src = this.frames[this.currentFrame];
context.drawImage();

Categories

Resources