Canvas mouseover - javascript

I'm having a canvas on which i have created dynamically some rectangles and when you hover over them i need to show an username that's stored, i tried to do it like this but i didn't got the result that i desired. The rectangles are not html elements so i can't use classes or ids.
This is the code that i tried:
canvas.addEventListener('mouseover', (evt)=>{
mousePos = onMousePos(canvas,evt);
for(let i=0;i<rectArray.length;i++)
if(ctx.isPointInPath(mousePos.x,mousePos.y))
console.log(rectArray[i].username);
});
The onMousePos function checks the that the mouse is inside of an hexagon and i use the same function for mouseup, mousedown and mousemove and it works.
EDIT the onMousePos is this:
function onMousePos(canvas, evt) {
const rect = canvas.getBoundingClientRect();
if (history && timeline) {
return {
x: Math.round(evt.clientX - rect.left) * 1.18,
y: Math.round(evt.clientY - rect.top) * 1.05
};
}
if (timeline && history === false) {
return {
x: Math.round(evt.clientX - rect.left),
y: Math.round(evt.clientY - rect.top) * 1.05
};
}
if (history && timeline === false) {
return {
x: Math.round(evt.clientX - rect.left) * 1.18,
y: Math.round(evt.clientY - rect.top)
};
}
return {
x: Math.round(evt.clientX - rect.left),
y: Math.round(evt.clientY - rect.top)
};
}

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
body {
background-color: black;
}
canvas {
display: block;
margin: auto;
border: solid 1px white;
border-radius: 10px;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script type="application/javascript">
void function() {
"use strict";
// Classes
/*
Constructor function
when called with new, everything attached to the 'this' keyword
becomes a new member of the new object
*/
function ToolTip(text) {
this.text = text;
}
/*
Constructor prototype, a collection
of values & functions that are shared across all instances,
use for constant values and member functions
*/
ToolTip.prototype = {
TEXT_SIZE: 15,
TEXT_FONT: "15px Arial",
TEXT_COLOUR: "#FFFFFFFF",
BOX_BORDER_COLOUR: "#000000FF",
BOX_BACKGROUND_COLOUR: "#990000FF",
render: function(ctx,x,y) {
ctx.fillStyle = this.BOX_BACKGROUND_COLOUR;
ctx.strokeStyle = this.BOX_BORDER_COLOUR;
ctx.font = this.TEXT_FONT;
ctx.beginPath();
ctx.rect(
x,
y - this.TEXT_SIZE,
ctx.measureText(this.text).width,
this.TEXT_SIZE
);
ctx.fill();
ctx.stroke();
ctx.fillStyle = this.TEXT_COLOUR;
ctx.fillText(this.text,x,y - 2);
}
};
function Rectangle(x,y,width,height,name) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.tooltip = new ToolTip(name);
}
Rectangle.prototype = {
BORDER_COLOUR: "#000000FF",
BACKGROUND_COLOR: "#0000AAFF",
contains: function(x,y) {
return x > this.x && x < this.x + this.width
&& y > this.y && y < this.y + this.height;
},
render: function(ctx) {
ctx.strokeStyle = this.BORDER_COLOUR;
ctx.fillStyle = this.BACKGROUND_COLOR;
ctx.beginPath();
ctx.rect(this.x,this.y,this.width,this.height);
ctx.fill();
ctx.stroke();
}
};
// Variables
var canvasWidth = 150;
var canvasHeight = 150;
var canvas = null;
var ctx = null;
var rectangles = null;
// Functions
function onMouseMove(e) {
var bounds = canvas.getBoundingClientRect();
var x = e.clientX - bounds.left;
var y = e.clientY - bounds.top;
draw();
for (var i = 0; i < rectangles.length; ++i) {
var rectangle = rectangles[i];
if (rectangle.contains(x,y)) {
rectangle.tooltip.render(ctx,x,y);
return;
}
}
}
function draw() {
ctx.fillStyle = "gray";
ctx.fillRect(0,0,canvasWidth,canvasHeight);
for (var i = 0; i < rectangles.length; ++i) {
rectangles[i].render(ctx);
}
}
// Entry Point
onload = function() {
canvas = document.getElementById("canvas");
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.onmousemove = onMouseMove;
ctx = canvas.getContext("2d");
rectangles = [
new Rectangle(10,10,25,25,"User 1"),
new Rectangle(45,10,25,25,"User 2"),
new Rectangle(80,10,25,25,"User 3"),
new Rectangle(115,10,25,25,"User 4"),
new Rectangle(10,45,25,25,"User 5"),
new Rectangle(45,45,25,25,"User 6"),
new Rectangle(80,45,25,25,"User 7"),
new Rectangle(115,45,25,25,"User 8"),
new Rectangle(10,80,25,25,"User 9"),
new Rectangle(45,80,25,25,"User 10"),
new Rectangle(80,80,25,25,"User 11"),
new Rectangle(115,80,25,25,"User 12"),
new Rectangle(10,115,25,25,"User 13"),
new Rectangle(45,115,25,25,"User 14"),
new Rectangle(80,115,25,25,"User 15"),
new Rectangle(115,115,25,25,"User 16")
];
draw();
}
}();
</script>
</body>
</html>

Related

Javascript Canvas Flashing When Drawing Frames

Been having issues with this for a couple days, not sure why the text I'm rendering on the canvas is flashing so much. I'm using the requestAnimationFrame() function, but its still flickering.
What I want to have happen is for the text to move smoothly and they remove themselves from the array when they move completely off screen.
var canvas = document.getElementById("myCanvas");
var c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var w = canvas.width;
var h = canvas.height;
var texts = [];
window.addEventListener("load", init);
function init() {
draw();
mainLoop();
}
function mainLoop() {
texts.push(createText("wow", "blue"));
texts.push(createText("wow", "green"));
texts.push(createText("wow", "red"));
setTimeout(function() { mainLoop(); }, 100);
}
function Text(x, y, vx, vy, varText, theColor){
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.color = theColor;
this.draw = function() {
drawStroked(varText, this.x, this.y, this.color);
}
}
function drawStroked(text, x, y, color) {
c.font = "30px bold Comic Sans MS";
c.strokeStyle = 'black';
c.lineWidth = 8;
c.strokeText(text, x, y);
c.fillStyle = color;
c.fillText(text, x, y);
}
function createText(varText, color) {
var x = (Math.random() * w / 2 ) + w/4;
var y = (Math.random() * h / 2) + h/2;
var vx = (Math.random() * .5) - .25
var vy = -(Math.random() * 3) - 1
return new Text(x, y, vx, vy, varText, color);
}
function draw() {
c.clearRect(0, 0, c.canvas.width, c.canvas.height);
for(var i = 0;i < texts.length; i++) {
var currentText = texts[i];
currentText.x += currentText.vx;
currentText.y += currentText.vy;
currentText.draw();
if(currentText.x>w||currentText.x<0||currentText.y<10){
texts.splice(i, 1);
}
}
requestAnimationFrame(draw);
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
<title>Game Screen</title>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>
The flickering you are seeing results from your looping code, where you skip elements of the array when deleting elements (Element 3 needs to be deleted? You call splice(3, 1) and then continue with the loop at index 4. Since the array shifts when you call splice, you should process element 3 again).
The imho easiest way to fix this is to iterate backwards over the array. Please note that iterating backwards is less CPU cache efficient (because every array access leads to a cache miss), so another fix would be
if(currentText.x>w||currentText.x<0||currentText.y<10){
texts.splice(i--, 1); // decrement i after accessing and deleting
}
var canvas = document.getElementById("myCanvas");
var c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var w = canvas.width;
var h = canvas.height;
var texts = [];
window.addEventListener("load", init);
function init() {
draw();
mainLoop();
}
function mainLoop() {
texts.push(createText("wow", "blue"));
texts.push(createText("wow", "green"));
texts.push(createText("wow", "red"));
setTimeout(function() { mainLoop(); }, 100);
}
function Text(x, y, vx, vy, varText, theColor){
this.x = x;
this.y = y;
this.vx = vx;
this.vy = vy;
this.color = theColor;
this.draw = function() {
drawStroked(varText, this.x, this.y, this.color);
}
}
function drawStroked(text, x, y, color) {
c.font = "30px bold Comic Sans MS";
c.strokeStyle = 'black';
c.lineWidth = 8;
c.strokeText(text, x, y);
c.fillStyle = color;
c.fillText(text, x, y);
}
function createText(varText, color) {
var x = (Math.random() * w / 2 ) + w/4;
var y = (Math.random() * h / 2) + h/2;
var vx = (Math.random() * .5) - .25
var vy = -(Math.random() * 3) - 1
return new Text(x, y, vx, vy, varText, color);
}
function draw() {
c.clearRect(0, 0, c.canvas.width, c.canvas.height);
for(var i = texts.length - 1;i >= 0; i--) {
var currentText = texts[i];
currentText.x += currentText.vx;
currentText.y += currentText.vy;
currentText.draw();
if(currentText.x>w||currentText.x<0||currentText.y<10){
texts.splice(i, 1);
}
}
requestAnimationFrame(draw);
}
body {
margin: 0;
padding: 0;
overflow: hidden;
}
<!DOCTYPE html>
<html>
<head>
<title>Game Screen</title>
</head>
<body>
<canvas id="myCanvas"></canvas>
</body>
</html>

Too many objects getting created while creating shapes in html5 canvas

I'm creating a simple paint app in html5 canvas and JavaScript which creates triangles of variable size. I have just figured out how to do this and am now trying to drag and move the triangles that have been created. For this, I'm using a "triangles" array to store all the triangle objects.
When I try to push one object of one triangle into the array, too many objects get created. How do I fix this? I just want one object per triangle.
My code:
HTML:
<body>
<h1>Simple Paint App</h1>
<div id="canvs">
<canvas id="paint-canvas" width="800" height="400"></canvas>
<button id="buttn" >Clear/Reset</button>
</div>
<noscript>This site requires JavaScript to be activated.</noscript>
</body>
JavaScript:
let canvas = document.querySelector("#paint-canvas");
let context = canvas.getContext("2d");
let triangles = []
let offsetX = canvas.getBoundingClientRect().left;
let offsetY = canvas.getBoundingClientRect().top;
let startX, startY;
let dragOk = false;
let imageData;
function getCoordinates(e){
const X = parseInt(e.clientX - offsetX);
const Y = parseInt(e.clientY - offsetY);
return {x: X, y: Y};
}
function getRandomColor(){
const colors =
["#DFFF00", "#FFBF00", "#FF7F50", "#DE3163", "#9FE2BF", "#40E0D0", "#6495ED", "#CCCCFF"];
return colors[Math.floor(Math.random() * colors.length)];
}
canvas.onmousedown = mouseDown;
canvas.onmouseup = mouseUp;
canvas.onmousemove = mouseMove;
document.querySelector("#buttn").addEventListener("click", () => resetCanvas());
function mouseDown(e){
dragOk = true;
const start = getCoordinates(e);
startX = start.x;
startY = start.y;
storeImageData();
}
function mouseUp(e){
dragOk = false;
restoreImageData();
let position = getCoordinates(e);
drawTriangle(position);
console.log(triangles);
}
function mouseMove(e){
if (!dragOk) {
return;
}
let position;
restoreImageData()
position = getCoordinates(e);
drawTriangle(position);
}
function storeImageData() {
imageData = context.getImageData(0, 0, canvas.width, canvas.height);
}
function restoreImageData() {
context.putImageData(imageData, 0, 0);
}
function drawTriangle(position) {
let tri = { x:startX, y:startY, points: [{x:0,y:0},{x:0,y:0},{x:0,y:0}], outline: "#000000", fill:"#000000", dragOk: false };
const radius = Math.sqrt(Math.pow((startX - position.x), 2) + Math.pow((startY - position.y), 2));
let i = 0;
let angle = 100;
// 3 because triangle has 3 sides
for (i = 0; i < 3; i++) {
tri.points[i].x = startX + radius * Math.cos(angle);
tri.points[i].y = startY - radius * Math.sin(angle);
angle += (2 * Math.PI) / 3;
}
context.beginPath();
context.moveTo(tri.points[0].x, tri.points[0].y);
for (i = 1; i < 3; i++) {
context.lineTo(tri.points[i].x, tri.points[i].y);
}
context.closePath();
// the outline
context.lineWidth = 5;
tri.outline = "#000000"
context.strokeStyle = tri.outline;
context.stroke();
// the fill color
tri.fill = getRandomColor();
context.fillStyle = tri.fill;
context.fill();
triangles.push(tri)
}
function resetCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
Edit:
I am pushing the newly created triangles in the drawTriangle function.
JSFiddle: Code
The problem is that your drawTriangle function is chained to the onMouseMove event. Of course this event is required to size the triangles but you shouldn't use it to stuff objects inside the triangles array, as this means as long as the mouse is moving, your creating new objects which are pushed into the array.
Better do it like this:
create a global variable tempTriangle
inside the drawTriangle function assign tri to tempTriangle
if the mouse button is released push tempTriangle into the triangles array
Here's an example based on your code:
let canvas = document.querySelector("#paint-canvas");
let context = canvas.getContext("2d");
let triangles = []
let offsetX = canvas.getBoundingClientRect().left;
let offsetY = canvas.getBoundingClientRect().top;
let startX, startY;
let dragOk = false;
let imageData;
let tempTriangle;
function getCoordinates(e) {
const X = parseInt(e.clientX - offsetX);
const Y = parseInt(e.clientY - offsetY);
return {
x: X,
y: Y
};
}
function getRandomColor() {
const colors = ["#DFFF00", "#FFBF00", "#FF7F50", "#DE3163", "#9FE2BF", "#40E0D0", "#6495ED", "#CCCCFF"];
return colors[Math.floor(Math.random() * colors.length)];
}
canvas.onmousedown = mouseDown;
canvas.onmouseup = mouseUp;
canvas.onmousemove = mouseMove;
function mouseDown(e) {
dragOk = true;
const start = getCoordinates(e);
startX = start.x;
startY = start.y;
storeImageData();
}
function mouseUp(e) {
dragOk = false;
restoreImageData();
let position = getCoordinates(e);
drawTriangle(position);
triangles.push(tempTriangle)
console.log(triangles, triangles.length);
}
function mouseMove(e) {
if (!dragOk) {
return;
}
let position;
restoreImageData()
position = getCoordinates(e);
drawTriangle(position);
}
function storeImageData() {
imageData = context.getImageData(0, 0, canvas.width, canvas.height);
}
function restoreImageData() {
context.putImageData(imageData, 0, 0);
}
function drawTriangle(position) {
let tri = {
x: startX,
y: startY,
points: [{
x: 0,
y: 0
}, {
x: 0,
y: 0
}, {
x: 0,
y: 0
}],
outline: "#000000",
fill: "#000000",
dragOk: false
};
const radius = Math.sqrt(Math.pow((startX - position.x), 2) + Math.pow((startY - position.y), 2));
let i = 0;
let angle = 100;
// 3 because triangle has 3 sides
for (i = 0; i < 3; i++) {
tri.points[i].x = startX + radius * Math.cos(angle);
tri.points[i].y = startY - radius * Math.sin(angle);
angle += (2 * Math.PI) / 3;
}
context.beginPath();
context.moveTo(tri.points[0].x, tri.points[0].y);
for (i = 1; i < 3; i++) {
context.lineTo(tri.points[i].x, tri.points[i].y);
}
context.closePath();
// the outline
context.lineWidth = 5;
tri.outline = "#000000"
context.strokeStyle = tri.outline;
context.stroke();
// the fill color
tri.fill = getRandomColor();
context.fillStyle = tri.fill;
context.fill();
tempTriangle = tri;
}
function resetCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height);
}
#import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');
h1 {
display: flex;
justify-content: center;
font-family: 'Roboto', sans-serif;
}
#paint-canvas {
border: 1vh solid black;
}
#canvs {
display: flex;
flex-flow: column;
align-items: center;
}
#buttn {
margin: 5vh 0 0 0;
}
<div id="canvs">
<canvas id="paint-canvas" width="800" height="400"></canvas>
<button id="buttn" onclick="resetCanvas()">Clear/Reset</button>
</div>

HTML Canvas & JavaScript - Scale Object on Hover

The script below draws 4 curved rectangles and detects if they are hovered over or clicked on with mouseup and mousemove event listeners. When one of the rectangles is hovered over, I would like it to grow slightly over the course of a second - it should then shrink back when the cursor moves off the rectangle.
The problem I have is that the only way I can think of doing this is by writing a function inside the if (this.selected) { clause which plots a new version of the rectangle for each frame in an animation lasting a second, but this clause is inside the function that plots a new version of the rectangle itself! How, then, can I write a function outside of curvedRect.prototype.makeCurvedRect which only runs when the cursor is over one of the rectangles? Any help will be appreciated.
var c=document.getElementById('game'),
canvasX=c.offsetLeft,
canvasY=c.offsetTop,
ctx=c.getContext('2d');
var curvedRect = function(id, x, y, w, h) {
this.id = id;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.selected = false;
}
curvedRect.prototype.makeCurvedRect = function() {
ctx.beginPath();
ctx.lineWidth='8';
ctx.strokeStyle='white';
ctx.moveTo(this.x+10, this.y);
ctx.lineTo(this.x+this.w-10, this.y);
ctx.quadraticCurveTo(this.x+this.w, this.y, this.x+this.w, this.y+10);
ctx.lineTo(this.x+this.w, this.y+this.h-10);
ctx.quadraticCurveTo(this.x+this.w, this.y+this.h, this.x+this.w-10, this.y+this.h);
ctx.lineTo(this.x+10, this.y+this.h);
ctx.quadraticCurveTo(this.x, this.y+this.h, this.x, this.y+this.h-10);
ctx.lineTo(this.x, this.y+10);
ctx.quadraticCurveTo(this.x, this.y, this.x+10, this.y);
ctx.stroke();
if (this.selected) {
// BM67 edit By Blindman67 removed annoying alert and replaced it with console.log
// As I did not want to add elsewhere to the code to declare hoverMessageShown is safely declared here to stop the console repeating the message.
if(window["hoverMessageShown"] === undefined){
window["hoverMessageShown"] = true;
console.log('When hovered over, I would like this box to grow slightly over a short period of time (say a second). When the mouse is removed I would like it to shrink back.')
}
// BM67 end.
}
}
curvedRect.prototype.hitTest = function(x, y) {
return (x >= this.x) && (x <= (this.w+this.x)) && (y >= this.y) && (y <= (this.h+this.y));
}
var Paint = function(element) {
this.element = element;
this.shapes = [];
}
Paint.prototype.addShape = function(shape) {
this.shapes.push(shape);
}
Paint.prototype.render = function() {
this.element.w = this.element.w;
for (var i=0; i<this.shapes.length; i++) {
this.shapes[i].makeCurvedRect();
}
}
Paint.prototype.setSelected = function(shape) {
for (var i=0; i<this.shapes.length; i++) {
this.shapes[i].selected = this.shapes[i] == shape;
}
this.render();
}
Paint.prototype.select = function(x, y) {
for (var i=this.shapes.length-1; i >= 0; i--) {
if (this.shapes[i].hitTest(x, y)) {
return this.shapes[i];
}
}
return null
}
var paint = new Paint(c);
var img1 = new curvedRect('1', 200, 55, 150, 150);
var img2 = new curvedRect('2', 375, 55, 150, 150);
var img3 = new curvedRect('3', 200, 230, 150, 150);
var img4 = new curvedRect('4', 375, 230, 150, 150);
paint.addShape(img1);
paint.addShape(img2);
paint.addShape(img3);
paint.addShape(img4);
paint.render();
function mouseUp(event) {
var x = event.x - canvasX;
var y = event.y - canvasY;
var shape = paint.select(x, y);
if (shape) {
alert(shape.id);
}
// console.log('selected shape: ', shape);
}
function mouseMove(event) {
var x = event.x - canvasX;
var y = event.y - canvasY;
var shape = paint.select(x, y);
paint.setSelected(shape);
}
c.addEventListener('mouseup', mouseUp);
c.addEventListener('mousemove', mouseMove);
canvas {
display: block;
margin: 1em auto;
border: 1px solid black;
background: #FF9900;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>uTalk Demo</title>
<link rel='stylesheet' type='text/css' href='game.css' media='screen'></style>
</head>
<body>
<canvas id="game" width = "750" height = "500"></canvas>
</body>
</html>
Change the makeCurvedRect method to something like this:
var c=document.getElementById('game'),
canvasX=c.offsetLeft,
canvasY=c.offsetTop,
ctx=c.getContext('2d');
var curvedRect = function(id, x, y, w, h) {
this.id = id;
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.selected = false;
}
curvedRect.prototype.makeCurvedRect = function() {
var delta = this.selected?10:0 ;
var x = this.x - delta;
var y = this.y - delta;
var w = this.w + (2*delta);
var h = this.h + (2*delta);
ctx.beginPath();
ctx.lineWidth='8';
ctx.strokeStyle='white';
ctx.moveTo(x+10, y);
ctx.lineTo(x+ w -10, y);
ctx.quadraticCurveTo(x + w, y,x + w,y + 10);
ctx.lineTo( x + w, y + h-10);
ctx.quadraticCurveTo( x + w, y + h, x + w - 10, y + h);
ctx.lineTo(x + 10,y + h);
ctx.quadraticCurveTo( x, y + h, x, y+h-10);
ctx.lineTo(x, y+10);
ctx.quadraticCurveTo(x, y, x+10, y);
ctx.stroke();
}
curvedRect.prototype.hitTest = function(x, y) {
return (x >= this.x) && (x <= (this.w+this.x)) && (y >= this.y) && (y <= (this.h+this.y));
}
var Paint = function(element) {
this.element = element;
this.shapes = [];
}
Paint.prototype.addShape = function(shape) {
this.shapes.push(shape);
}
Paint.prototype.render = function() {
this.element.width = this.element.width;
for (var i=0; i<this.shapes.length; i++) {
this.shapes[i].makeCurvedRect();
}
}
Paint.prototype.setSelected = function(shape) {
for (var i=0; i<this.shapes.length; i++) {
this.shapes[i].selected = this.shapes[i] == shape;
}
this.render();
}
Paint.prototype.select = function(x, y) {
for (var i=this.shapes.length-1; i >= 0; i--) {
if (this.shapes[i].hitTest(x, y)) {
return this.shapes[i];
}
}
return null
}
var paint = new Paint(c);
var img1 = new curvedRect('1', 200, 55, 150, 150);
var img2 = new curvedRect('2', 375, 55, 150, 150);
var img3 = new curvedRect('3', 200, 230, 150, 150);
var img4 = new curvedRect('4', 375, 230, 150, 150);
paint.addShape(img1);
paint.addShape(img2);
paint.addShape(img3);
paint.addShape(img4);
paint.render();
function mouseUp(event) {
var x = event.x - canvasX;
var y = event.y - canvasY;
var shape = paint.select(x, y);
if (shape) {
alert(shape.id);
}
// console.log('selected shape: ', shape);
}
function mouseMove(event) {
var x = event.x - canvasX;
var y = event.y - canvasY;
var shape = paint.select(x, y);
paint.setSelected(shape);
}
c.addEventListener('mouseup', mouseUp);
c.addEventListener('mousemove', mouseMove);
canvas {
display: block;
margin: 1em auto;
border: 1px solid black;
background: #FF9900;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>uTalk Demo</title>
<link rel='stylesheet' type='text/css' href='game.css' media='screen'></style>
</head>
<body>
<canvas id="game" width = "750" height = "500"></canvas>
</body>
</html>

How to update text written on canvas

When I try to change the scoreboard using the computerCount variable (as you can see in my if statement in the update function for the ball variable) the other numbers aren't shown properly. Keep in mind that at first 0 works properly.
JSFiddle format - You can change code by going at top right corner that says "Edit" in JSFiddle.
Code:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Pong</title>
<!-- Basic styling, centering the canvas -->
<style>
canvas{
position: absolute;
margin: auto;
top:60px;
bottom:0;
right:0;
left:0;
}
#scoreBoard{
position: absolute;
margin: auto;
top:0;
bottom:640px;
right:720px;
left:20px;
}
</style>
</head>
<body>
<canvas id = "scoreBoard" width="500" height = "100"></canvas>
<script>
var WIDTH = 700
var HEIGHT = 600
var pi = Math.PI
var canvas
var ctx
var keystate
var upArrow = 38;
var downArrow = 40;
var computerCount = 0;
var playerCount = 0;
var player = {
x: null,
y: null,
width: 20,
height: 100,
/**
* Update the position depending on pressed keys
*/
update: function() {
if(keystate[upArrow]){
this.y-=7;
}
if(keystate[downArrow]){
this.y+=7;
}},
/**
* Draw the player paddle to the canvas
*/
draw: function() {
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
/**
* The ai paddle
*
* #type {Object}
*/
var ai = {
x: null,
y: null,
width: 20,
height: 100,
/**
* Update the position depending on the ball position
*/
update: function() {
var desty = ball.y-(this.height - ball.side)*0.5
this.y += (desty-this.y)*0.2;
},
draw: function() {
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
/**
* The ball object
*
* #type {Object}
*/
var ball = {
x: null,
y: null,
vel:null,
side: 20,
speed:5,
update: function() {
this.x += this.vel.x;
this.y += this.vel.y;
if(0>this.y || this.y+this.side>HEIGHT){
var offset = this.vel.y<0 ? 0-this.y : HEIGHT-(this.y+this.side);
this.y+=2*offset
this.vel.y*=-1;
}
var AABBIntersect = function(ax, ay, aw, ah, bx, by, bw, bh) {
return ax < bx+bw && ay < by+bh && bx < ax+aw && by < ay+ah;
};
var pdle = this.vel.x<0 ? player : ai;
if(AABBIntersect(pdle.x,pdle.y,pdle.width,pdle.height, this.x, this.y, this.side, this.side)){
this.x = pdle===player ? player.x + player.width : ai.x - this.side;
var n = (this.y+this.side-pdle.y)/(pdle.height+this.side)
var phi = 0.25*pi*(2*n - 1) // pi/4 = 45
this.x = pdle===player ? player.x+player.width : ai.x - this.side;
var n = (this.y+this.side - pdle.y)/(pdle.height+this.side);
var phi = 0.25*pi*(2*n - 1); // pi/4 = 45
this.vel.x = (pdle===player ? 1 : -1)*this.speed*Math.cos(phi);
this.vel.y = this.speed*Math.sin(phi);
}
if(ball.x<0){
computerCount =+1;
ball.x = (WIDTH - ball.side) / 2;
ball.y = (HEIGHT - ball.side) / 2;
}
},
// reset the ball when ball outside of the canvas in the
draw: function() {
ctx.fillRect(this.x, this.y, this.side, this.side);
}
}
function score(){
}
/**
* Starts the game
*/
function main() {
// create, initiate and append game canvas
canvas = document.createElement("canvas");
canvas.width = WIDTH;
canvas.height = HEIGHT;
ctx = canvas.getContext("2d");
document.body.appendChild(canvas);
canvas2 = document.createElement("canvas");
canvas2.setAttribute("id", "scoreBoard");
canvas2.width = 200;
canvas2.height = 100;
ctx2 = canvas2.getContext("2d");
document.body.appendChild(canvas2);
keystate = {};
document.addEventListener("keydown" , function(event){
keystate[event.keyCode] = true;
})
document.addEventListener("keyup" , function(event){
delete keystate[event.keyCode];
})
init();
var loop = function() {
update();
draw();
window.requestAnimationFrame(loop, canvas);
};
window.requestAnimationFrame(loop, canvas);
}
/**
* Initatite game objects and set start positions
*/
function init() {
player.x = player.width;
player.y = (HEIGHT - player.height) / 2;
ai.x = WIDTH - (player.width + ai.width);
ai.y = (HEIGHT - ai.height) / 2;
ball.x = (WIDTH - ball.side) / 2;
ball.y = (HEIGHT - ball.side) / 2;
ball.vel = {
x:ball.speed,
y: 0
}
}
/**
* Update all game objects
*/
function update() {
ball.update();
player.update();
ai.update();
}
function draw(){
ctx.fillStyle = "black"
ctx.fillRect(0,0,WIDTH,HEIGHT)
ctx.save();
ctx2.fillStyle = "red"
ctx2.fillText(String(computerCount),100,100)
ctx2.fillText("VS",120,100)
ctx2.fillText(String(playerCount),175,100)
ctx2.font = "bold 40px monaco"
ctx.fillStyle = "white"
ball.draw();
player.draw();
ai.draw();
var w=4;
var x= (WIDTH-w)*0.5;
var y=2;
var step = HEIGHT/20;
while(y<HEIGHT){
ctx.fillRect(x,y+step*0.25,w,step*0.5)
y+=step;
}
ctx.restore();
}
// start and run the game
main();
</script>
</body>
</html>
You have two problems:
When you draw a number, you do not erase the previous number that is already printed. That is, when the score becomes 1, you render 1 on top of already rendered 0. The easiest way to address it is to do fillRect and draw a black rectangle on top of the previously written score before you draw a new score.
When you fix that, you will notice that your score never goes above 1. The reason is a typo in the code that increments it, replace
computerCount =+1;
with
computerCount += 1;
Mentioned by #Ishamael, line 139's computer count needs to be changed to computerCount += 1; //After this if statement add if the player scores.
In line 221,
function draw(){
ctx.fillStyle = "black";
ctx.fillRect(0,0,WIDTH,HEIGHT);
ctx.save();
ctx2.fillStyle = "black";
ctx2.fillRect(0,0,WIDTH, 100);
ctx2.save();
ctx2.fillStyle = "red";
ctx2.font = "bold 40px monaco";
ctx2.fillText(String(computerCount),100,100);
ctx2.fillText("VS",120,100);
ctx2.fillText(String(playerCount),175,100);
ctx2.save();
ctx.fillStyle = "white";
. . .
}
remember your semicolons and set text style before writing. I also added the repaint to erase the previous scoreboard.

Html5 canvas image on click

I'm having a problem whit my code.
I draw some circles in a circular path and I expect when to click on them to return something other than 0 in firebug console but that's not happening;
I don't know what is wrong with my code and i hope someone will tell me.
Here's my code:
var canvas, ctx;
var circle_data = [];
function circles(x, y, radius) {
this.x = x;
this.y = y;
this.radius = radius;
circle_data.push(this);
}
circles.prototype = {
draw: function (context) {
context.beginPath();
context.arc(this.x, this.y, this.radius / 5, 0, 2 * Math.PI, false);
context.fillStyle = "red";
context.fill();
}
}
function draw() {
ctx.translate(250, 250);
for (var n = 0; n < 10; n++) {
var radi = (Math.PI / 180);
var x = Math.sin(radi * n * 36) * 70;
var y = Math.cos(radi * n * 36) * 70;
var radius = 50;
var thiscircle = new circles(x, y, radius);
thiscircle.draw(ctx);
}
}
function mouseDown(e) {
var img_data = ctx.getImageData(e.pageX, e.pageY, 1, 1);
console.log(img_data.data[3]);
}
function init() {
canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
canvas.addEventListener('mousedown', mouseDown, false);
}
init();
It dosen't matter is i use data[3];
I tried whit console.log(img_data.data[0]+" "+img_data.data[1]+" "+img_data.data[2]);
Still getting 0 0 0
Your detecting the mouse position relative to the page and not the canvas, you need to get the position of the canvas on the page and subtract that from the X and Y of the mouse to find you position relative to the canvas. I use functions similar to the ones below when working with canvas.
getOffsetPosition = function(obj){
/*obj is the Canvas element*/
var offsetX = offsetY = 0;
if (obj.offsetParent) {
do {
offsetX += obj.offsetLeft;
offsetY += obj.offsetTop;
}while(obj = obj.offsetParent);
}
return [offsetX,offsetY];
}
getMouse = function(e,canvasElement){
OFFSET = getOffsetPosition(canvasElement);
mouse_x = (e.pageX || (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft)) - OFFSET[0];
mouse_y = (e.pageY || (e.clientY + document.body.scrollTop + document.documentElement.scrollTop)) - OFFSET[1];
return [mouse_x,mouse_y];
}
The following code works.
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>Untitled Document</title>
</head>
<body>
<canvas id="canvas" width="500" height="500" style="background-color:#999999;"></canvas>
</body>
<script>
var canvas,ctx;
var circle_data = [];
function circles(x,y,radius)
{
this.x = x;
this.y = y;
this.radius = radius;
circle_data.push(this);
}
circles.prototype = {
draw: function(context){
context.beginPath();
context.arc(this.x, this.y, this.radius / 5, 0, 2* Math.PI, false);
context.fillStyle = "red";
context.fill();
}
}
getOffsetPosition = function(obj){
/*obj is the Canvas element*/
var offsetX = offsetY = 0;
if (obj.offsetParent) {
do {
offsetX += obj.offsetLeft;
offsetY += obj.offsetTop;
}while(obj = obj.offsetParent);
}
return [offsetX,offsetY];
}
getMouse = function(e,canvasElement){
OFFSET = getOffsetPosition(canvasElement);
mouse_x = (e.pageX || (e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft)) - OFFSET[0];
mouse_y = (e.pageY || (e.clientY + document.body.scrollTop + document.documentElement.scrollTop)) - OFFSET[1];
return [mouse_x,mouse_y];
}
function draw(){
ctx.translate(250, 250);
for (var n = 0; n < 10; n++) {
var radi = (Math.PI/180);
var x = Math.sin(radi*n*36)*70;
var y = Math.cos(radi*n*36)*70;
var radius = 50;
var thiscircle = new circles(x,y,radius);
thiscircle.draw(ctx);
}
}
function mouseDown(e)
{
var pos = getMouse(e,ctx.canvas);
var img_data = ctx.getImageData(pos[0],pos[1],1,1);
console.log(img_data.data[3]);
}
function init() {
canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d');
draw();
canvas.addEventListener('mousedown', mouseDown, false);
}
init();
</script>
</html>

Categories

Resources