Canvas crispy text rendering - html

i am using electron(nodejs framework ) and i want to render crispy text for convert it into bitmap and show it on led brick.
like led show software please help.
my code is working but it's system dependent it working fine in some computer but to blurry in some computer.
calling parameter in main.js.
let height = 96;
let width = 288;
let letterSpacing = 1;
var font = "Arial";
var fontSize = 11;
let text_x = 1;
let text_y = 1;
const canvas = new Canvas(height, width, letterSpacing, font, fontSize, text_x, text_y);
here is my canvas.js file.
class Canvas {
constructor(height, width, latterSpacing = 1, font, fontSize, text_x, text_y) {
this.width = width;
this.height = height;
this.letterSpacing = latterSpacing;
this.font = font;
this.fontSize = fontSize;
this.text_x = text_x;
this.text_y = text_y;
this.maxWidth = 32;
this.offset = 0.5;
this.canvas = document.getElementById("myCanvas");
this.ctx = this.canvas.getContext("2d");
}
PIXEL_RATIO = (function () {
// var ctx = document.createElement("canvas").getContext("2d"),
var ctx = document.getElementById("myCanvas").getContext("2d"),
// var ctx = this.ctx,
dpr = window.devicePixelRatio || 1,
bsr = ctx.webkitBackingStorePixelRatio ||
ctx.mozBackingStorePixelRatio ||
ctx.msBackingStorePixelRatio ||
ctx.oBackingStorePixelRatio ||
ctx.backingStorePixelRatio || 1;
return dpr / bsr;
})();
setwidth(maxwidth) {
this.maxWidth = maxwidth;
// this.offset = ofset;
}
setoffset(ofset) {
// this.maxWidth = maxwidth;
this.offset = ofset;
}
createHiDPICanvas = function (w, h, ratio) {
if (!ratio) { ratio = this.PIXEL_RATIO; }
// var can = document.createElement("canvas");
var can = this.canvas;
can.width = w * ratio;
can.height = h * ratio;
can.style.width = w + "px";
can.style.height = h + "px";
can.getContext("2d").setTransform(ratio, 0, 0, ratio, 0, 0);
return can;
}
createCanvas() {
try {
const canvas = document.getElementById("myCanvas");
this.canvas.retinaResolutionEnabled = false;
// this.canvas.style.letterSpacing = "1px";
this.canvas.height = this.height;
this.canvas.width = this.width;
this.canvas.style.letterSpacing = `${this.letterSpacing}px`
/*word spacing*/
// var can = this.createHiDPICanvas(this.width, this.height, 4)
// this.ctx = can.getContext("2d")
this.ctx.beginPath();
// this.ctx = this.canvas.getContext("2d");
this.ctx.fillStyle = "#FF0000";
this.ctx.font = `${this.fontSize}px ` + this.font;
/*Font style and size*/
this.ctx.strokeStyle = "#FF0000";
this.ctx.textBaseline = "top";
this.ctx.textAlign = 'start';
this.ctx.shadowOffsetX = 0;
this.canvas.retinaResolutionEnabled = false;
// this.ctx.fillText("WELCOME TO TICO", 10, 20);
return true;
} catch (error) {
return false;
}
}
clrCanvas(ix = 0, iy = 0, ex = this.canvas.width, ey = this.canvas.height) {
this.ctx.clearRect(ix, iy, ex, ey);
}
fillTextCanvas(str, row = 0, col = 0, vac = 0, hac = 1, _fontSize = this.fontSize, _font = this.font)
{
this.ctx.font = `${_fontSize}px ` + _font;
if (vac) {
col = ((this.canvas.height - (str.length * _fontSize)) / 2) + 1;
}
if (hac) {
this.ctx.textAlign = "center";
row = this.width / 2;
}
for (let index = 0; index < str.length; index++) {
// const element = array[index];
let y = (_fontSize * index) + col;
// this.ctx.fillText(str[index], width / 2, y);
/*text,x,y*/
this.ctx.fillText(str[index], row - 0.8, y - 0.8);
/*text,x,y*/
// this.ctx.fillText("hello", width/2, y);
/*text,x,y*/
}
// display_hex["Screen2"] = jsonArr;
// fillMatrix(jsonArr);
}
async getBitmap() {
var jsonArr = {};
var bin = '';
for (var j = 0; j < this.canvas.width; j++) {
bin = ""
for (var i = 0; i <= this.canvas.height; i++) {
var data = this.ctx.getImageData(j, i, 1, 1); /*getPixel,x,y*/
if (!(i % 32) && i) {
// jsonArr[j + (width * (Math.floor(i / 32) - 1))] = ("0x" + (("00000000" +
ConvertBase.bin2hex(bin)).substr(-8)));
jsonArr[j + (this.width * (Math.floor(i / 32) - 1))] =
parseInt(ConvertBase.bin2dec(bin));
bin = "";
}
if (data['data'][0] >= 200 && data['data'][3] >= 90) {
bin += "1";
} else {
bin += "0";
}
}
}
return jsonArr;
}
fillCanvas(_char, row, col, _fontSize = 11, _font = "Arial") {
this.clrCanvas();
this.ctx.font = `${_fontSize}px ` + _font;
this.ctx.textAlign = "start";
this.ctx.imageSmoothingEnabled = false;
// let linesPos = [[0, 45, 80, 119, 157, 196, 235], [1, 24, 36, 48, 60, 72, 84]]
// let linesPos = [[0, 49, 81, 119, 157, 196, 235], [1, 22, 33, 44, 55, 66, 77]]
let linesPos = [[0, 60, 98, 135, 174, 213, 252], [1, 23, 34, 45, 56, 67, 78]]
this.findColPos(_char);
// console.log(_char)
for (let _row = row; _row < _char.length; _row++) {
// let y = parseInt(text_y) + ((parseInt(fontSize) + 2) * _row);
let y = parseInt(this.text_y + 1) + ((parseInt(_fontSize)) * _row);
for (let index = col; index < _char[_row].length; index++) {
let x = parseInt(this.text_x) + linesPos[0][index];
console.log(this.ctx.measureText(_char[_row][index]).width)
// this.ctx.fillText(_char[_row][index], x + 1.8, y + 0.8,32);
/*text,x,y*/
this.ctx.fillText(_char[_row][index], x + this.offset, y + this.offset, this.maxWidth);
/*text,x,y*/
this.ctx.moveTo(0, linesPos[1][index + 1] + 0.5);
this.ctx.lineTo(this.canvas.width, linesPos[1][index + 1] + 0.5);
this.ctx.moveTo(linesPos[0][index] + 0.5, 0);
this.ctx.lineTo(linesPos[0][index] + 0.5, this.canvas.height);
}
}
this.ctx.stroke();
this.ctx.strokeRect(0, 0, this.canvas.width, this.canvas.height);
// display_hex["Screen1"] = jsonArr;
// canvasImg["Screen1"] = ($('#myCanvas')[0]).toDataURL("image/png");
// fillMatrix(jsonArr);
// return jsonArr;
}
findColPos(__char) {
let maxRow = []
maxRow[0] = 0;
let splitData = [];
maxRow[0] = [];
maxRow[1] = [];
for (let pos = 0; pos < __char[0].length; pos++) {
if (__char[0][pos].split(" ")[1]) {
splitData.push(__char[0][pos].split(" ")[1]);
} else {
// __char[0][pos] = "";
splitData[pos] = " "
}
__char[0][pos] = __char[0][pos].trim().split(" ")[0]; //_char[0][pos] _char[0].splice[];
// _char[0][pos] = splitData[0];
// _char[0].splice
// console.log(_char[0][pos].split(" ")[0]); //_char[0][pos] _char[0].splice[];
}
console.log(__char)
__char.splice(1, 0, splitData)
console.log(__char)
for (let row = 0; row < __char.length; row++) {
for (let col = 0; col < __char[row].length; col++) {
let width = this.ctx.measureText(__char[row][col]).width + 3;
if (!maxRow[0][col + 1]) {
maxRow[0][col + 1] = 0;
}
maxRow[0][col + 1] = maxRow[0][col + 1] < width ? width : maxRow[0][col + 1];
}
}
// console.log(maxRow)
for (let i = 1; i < maxRow.length; i++) {
maxRow[0][i] = maxRow[0][i] + maxRow[0][i - 1];
}
/* for (let index = 0; index < _char.length; index++) {
// const element = array[index];
maxRow[index] = ctx.measureText(_char[index]).width;
} */
// _char = __char
return maxRow;
}
createFonts(start, end) {
let arr = [];
// clearEvents();
for (let index = "/".charCodeAt(0); index <= ":".charCodeAt(0); index++) {
// const element = array[index];
// fillCanvas(index);
let txt = String.fromCharCode(index);
fillTextCanvas(txt, 0, 0, 1, 0, 32);
createCanvas(32, this.ctx.measureText(txt).width, 32);
this.ctx.textBaseline = "middle";
// fillTextCanvas(txt, text_x, text_y);
this.clrCanvas();
fillTextCanvas(txt, 0, 0, 1, 0, 32);
arr.push(display_hex);
// fillMatrix();
}
console.log(JSON.stringify(arr));
// startEvents();
}
findFirstPositive(b, a, i, c) {
c = (d, e) => e >= d ? (a = d + (e - d) / 2, 0 < b(a) && (a == d || 0 >= b(a - 1)) ? a : 0 >=
b(a) ? c(a + 1, e) : c(d, a - 1)) : -1
for (i = 1; 0 >= b(i);) i *= 2
return c(i / 2, i) | 0
}
getDPI() {
var dpi = findFirstPositive(x => matchMedia(`(max-resolution: ${x}dpi)`).matches);
return dpi
}
getImage() {
return this.canvas.toDataURL('image/png', 1.0);
}
}
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = Canvas;
}

The canvas does not respect your devices pixel ratio, this is not a specific electron issue.
The code you have copy and pasted from another StackOverflow won't work because you change the size/height again without respecting the ratio. If you uncomment it and adjust it correctly, it will work.

Related

HTML how to replace single colour object with picture? [duplicate]

This question already has answers here:
Change a shape on JavaScript canvas to become an image
(1 answer)
moving an image across a html canvas
(5 answers)
Closed 3 months ago.
I'm currently working on a simple HTML game and want to replace the yellow square with a picture. The yellow square's colour is defined by line 20, with "yellow". How can I make this a picture instead of a singular colour?
The line in question:
myGamePiece = new component(30, 30, "yellow", 10, 120);
This is what the game looks like currently:
This is ideally what the game will look like, hopefully it's a pretty simple fix but I can't figure out how to solve it.
var myGamePiece;
var myObstacles = [];
var myScore;
function startGame() {
myGamePiece = new component(30, 30, "yellow", 10, 120);
myGamePiece.gravity = 0.05;
myScore = new component("30px", "Consolas", "black", 280, 40, "text");
myGameArea.start();
}
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 480;
this.canvas.height = 270;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas, document.body.childNodes[0]);
this.frameNo = 0;
this.interval = setInterval(updateGameArea, 20);
},
clear : function() {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function component(width, height, color, x, y, type) {
this.type = type;
this.score = 0;
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.gravity = 0;
this.gravitySpeed = 0;
this.update = function() {
ctx = myGameArea.context;
if (this.type == "text") {
ctx.font = this.width + " " + this.height;
ctx.fillStyle = color;
ctx.fillText(this.text, this.x, this.y);
} else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.gravitySpeed += this.gravity;
this.x += this.speedX;
this.y += this.speedY + this.gravitySpeed;
this.hitBottom();
}
this.hitBottom = function() {
var rockbottom = myGameArea.canvas.height - this.height;
if (this.y > rockbottom) {
this.y = rockbottom;
this.gravitySpeed = 0;
}
}
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) || (mytop > otherbottom) || (myright < otherleft) || (myleft > otherright)) {
crash = false;
}
return crash;
}
}
function updateGameArea() {
var x, height, gap, minHeight, maxHeight, minGap, maxGap;
for (i = 0; i < myObstacles.length; i += 1) {
if (myGamePiece.crashWith(myObstacles[i])) {
return;
}
}
myGameArea.clear();
myGameArea.frameNo += 1;
if (myGameArea.frameNo == 1 || everyinterval(150)) {
x = myGameArea.canvas.width;
minHeight = 20;
maxHeight = 200;
height = Math.floor(Math.random()*(maxHeight-minHeight+1)+minHeight);
minGap = 50;
maxGap = 200;
gap = Math.floor(Math.random()*(maxGap-minGap+1)+minGap);
myObstacles.push(new component(10, height, "green", x, 0));
myObstacles.push(new component(10, x - height - gap, "green", x, height + gap));
}
for (i = 0; i < myObstacles.length; i += 1) {
myObstacles[i].x += -1;
myObstacles[i].update();
}
myScore.text="SCORE: " + myGameArea.frameNo;
myScore.update();
myGamePiece.newPos();
myGamePiece.update();
}
function everyinterval(n) {
if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
return false;
}
function accelerate(n) {
myGamePiece.gravity = n;
}
window.addEventListener("DOMContentLoaded",startGame);
canvas {
border:1px solid #d3d3d3;
background-color: #3A93DC;
}
<br>
<button onmousedown="accelerate(-0.2)" onmouseup="accelerate(0.05)">ACCELERATE</button>
<p>Use the ACCELERATE button to stay in the air</p>
<p>How long can you stay alive?</p>

Corner blob animation

I found a post a while back were someone made a corner blob animation similar to the one on the old discord login page (jsfiddle). I want to move it to the right side of the page. I don't know exactly how it works.
const SCALE = 0.25;
const TWO_PI = Math.PI * 2;
const HALF_PI = Math.PI / 2;
const canvas = document.createElement("canvas");
const c = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
class Blob {
constructor() {
this.wobbleIncrement = 0;
// use this to change the size of the blob
this.radius = 500;
// think of this as detail level
// number of conections in the `bezierSkin`
this.segments = 12;
this.step = HALF_PI / this.segments;
this.anchors = [];
this.radii = [];
this.thetaOff = [];
const bumpRadius = 100;
const halfBumpRadius = bumpRadius / 2;
for (let i = 0; i < this.segments + 2; i++) {
this.anchors.push(0, 0);
this.radii.push(Math.random() * bumpRadius - halfBumpRadius);
this.thetaOff.push(Math.random() * TWO_PI);
}
this.theta = 0;
this.thetaRamp = 0;
this.thetaRampDest = 12;
this.rampDamp = 25;
}
update() {
this.thetaRamp += (this.thetaRampDest - this.thetaRamp) / this.rampDamp;
this.theta += 0.03;
this.anchors = [0, this.radius];
for (let i = 0; i <= this.segments + 2; i++) {
const sine = Math.sin(this.thetaOff[i] + this.theta + this.thetaRamp);
const rad = this.radius + this.radii[i] * sine;
const theta = this.step * i;
const x = rad * Math.sin(theta);
const y = rad * Math.cos(theta);
this.anchors.push(x, y);
}
c.save();
c.translate(-10, -10);
c.scale(SCALE, SCALE);
c.fillStyle = "blue";
c.beginPath();
c.moveTo(0, 0);
bezierSkin(this.anchors, false);
c.lineTo(0, 0);
c.fill();
c.restore();
}
}
const blob = new Blob();
function loop() {
c.clearRect(0, 0, canvas.width, canvas.height);
blob.update();
window.requestAnimationFrame(loop);
}
loop();
// array of xy coords, closed boolean
function bezierSkin(bez, closed = true) {
const avg = calcAvgs(bez);
const leng = bez.length;
if (closed) {
c.moveTo(avg[0], avg[1]);
for (let i = 2; i < leng; i += 2) {
let n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.quadraticCurveTo(bez[0], bez[1], avg[0], avg[1]);
} else {
c.moveTo(bez[0], bez[1]);
c.lineTo(avg[0], avg[1]);
for (let i = 2; i < leng - 2; i += 2) {
let n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.lineTo(bez[leng - 2], bez[leng - 1]);
}
}
// create anchor points by averaging the control points
function calcAvgs(p) {
const avg = [];
const leng = p.length;
let prev;
for (let i = 2; i < leng; i++) {
prev = i - 2;
avg.push((p[prev] + p[i]) / 2);
}
// close
avg.push((p[0] + p[leng - 2]) / 2, (p[1] + p[leng - 1]) / 2);
return avg;
}
I hope these 2 changes in update function help you:
c.translate(canvas.width-10, -10);
c.rotate(Math.PI / 2)
Full Code:
const SCALE = 0.25;
const TWO_PI = Math.PI * 2;
const HALF_PI = Math.PI / 2;
const canvas = document.createElement("canvas");
const c = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
class Blob {
constructor() {
this.wobbleIncrement = 0;
// use this to change the size of the blob
this.radius = 500;
// think of this as detail level
// number of conections in the `bezierSkin`
this.segments = 12;
this.step = HALF_PI / this.segments;
this.anchors = [];
this.radii = [];
this.thetaOff = [];
const bumpRadius = 100;
const halfBumpRadius = bumpRadius / 2;
for (let i = 0; i < this.segments + 2; i++) {
this.anchors.push(0, 0);
this.radii.push(Math.random() * bumpRadius - halfBumpRadius);
this.thetaOff.push(Math.random() * TWO_PI);
}
this.theta = 0;
this.thetaRamp = 0;
this.thetaRampDest = 12;
this.rampDamp = 25;
}
update() {
this.thetaRamp += (this.thetaRampDest - this.thetaRamp) / this.rampDamp;
this.theta += 0.03;
this.anchors = [0, this.radius];
for (let i = 0; i <= this.segments + 2; i++) {
const sine = Math.sin(this.thetaOff[i] + this.theta + this.thetaRamp);
const rad = this.radius + this.radii[i] * sine;
const theta = this.step * i;
const x = rad * Math.sin(theta);
const y = rad * Math.cos(theta);
this.anchors.push(x, y);
}
c.save();
c.translate(canvas.width-10, -10);
c.rotate(Math.PI / 2)
c.scale(SCALE, SCALE);
c.fillStyle = "blue";
c.beginPath();
c.moveTo(0, 0);
bezierSkin(this.anchors, false);
c.lineTo(0, 0);
c.fill();
c.restore();
}
}
const blob = new Blob();
function loop() {
c.clearRect(0, 0, canvas.width, canvas.height);
blob.update();
window.requestAnimationFrame(loop);
}
loop();
// array of xy coords, closed boolean
function bezierSkin(bez, closed = true) {
const avg = calcAvgs(bez);
const leng = bez.length;
if (closed) {
c.moveTo(avg[0], avg[1]);
for (let i = 2; i < leng; i += 2) {
let n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.quadraticCurveTo(bez[0], bez[1], avg[0], avg[1]);
} else {
c.moveTo(bez[0], bez[1]);
c.lineTo(avg[0], avg[1]);
for (let i = 2; i < leng - 2; i += 2) {
let n = i + 1;
c.quadraticCurveTo(bez[i], bez[n], avg[i], avg[n]);
}
c.lineTo(bez[leng - 2], bez[leng - 1]);
}
}
// create anchor points by averaging the control points
function calcAvgs(p) {
const avg = [];
const leng = p.length;
let prev;
for (let i = 2; i < leng; i++) {
prev = i - 2;
avg.push((p[prev] + p[i]) / 2);
}
// close
avg.push((p[0] + p[leng - 2]) / 2, (p[1] + p[leng - 1]) / 2);
return avg;
}

mouse background image with canvas in html5

I want something like this site , look at mouse background in header section:
Link
when i check page source i found this:
<canvas id="header-canvas" width="1360" height="676"></canvas>
Take a look at source code and identify which JS plugins are being used.
I have pulled it apart and found its using green sock https://greensock.com
Take a look at http://codepen.io/elliottgg/pen/YpQBpZ
Scroll down to line 40 to see where the magic is happening
(function() {
var width, height, largeHeader, canvas, ctx, points, target, animateHeader = true;
// Main
initHeader();
initAnimation();
addListeners();
function initHeader() {
width = window.innerWidth;
height = window.innerHeight;
target = {x: width/2, y: height/2};
largeHeader = document.getElementById('header');
largeHeader.style.height = height+'px';
canvas = document.getElementById('header-canvas');
canvas.width = width;
canvas.height = height;
ctx = canvas.getContext('2d');
// create points
points = [];
for(var x = 0; x < width; x = x + width/20) {
for(var y = 0; y < height; y = y + height/20) {
var px = x + Math.random()*width/20;
var py = y + Math.random()*height/20;
var p = {x: px, originX: px, y: py, originY: py };
points.push(p);
}
}
// for each point find the 5 closest points
for(var i = 0; i < points.length; i++) {
var closest = [];
var p1 = points[i];
for(var j = 0; j < points.length; j++) {
var p2 = points[j]
if(!(p1 == p2)) {
var placed = false;
for(var k = 0; k < 5; k++) {
if(!placed) {
if(closest[k] == undefined) {
closest[k] = p2;
placed = true;
}
}
}
for(var k = 0; k < 5; k++) {
if(!placed) {
if(getDistance(p1, p2) < getDistance(p1, closest[k])) {
closest[k] = p2;
placed = true;
}
}
}
}
}
p1.closest = closest;
}
// assign a circle to each point
for(var i in points) {
var c = new Circle(points[i], 2+Math.random()*2, 'rgba(255,255,255,0.8)');
points[i].circle = c;
}
}
// Event handling
function addListeners() {
if(!('ontouchstart' in window)) {
window.addEventListener('mousemove', mouseMove);
}
window.addEventListener('scroll', scrollCheck);
window.addEventListener('resize', resize);
}
function mouseMove(e) {
var posx = posy = 0;
if (e.pageX || e.pageY) {
posx = e.pageX;
posy = e.pageY;
}
else if (e.clientX || e.clientY) {
posx = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
posy = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;
}
target.x = posx;
target.y = posy;
}
function scrollCheck() {
if(document.body.scrollTop > height) animateHeader = false;
else animateHeader = true;
}
function resize() {
width = window.innerWidth;
height = window.innerHeight;
largeHeader.style.height = height+'px';
canvas.width = width;
canvas.height = height;
}
// animation
function initAnimation() {
animate();
for(var i in points) {
shiftPoint(points[i]);
}
}
function animate() {
if(animateHeader) {
ctx.clearRect(0,0,width,height);
for(var i in points) {
// detect points in range
if(Math.abs(getDistance(target, points[i])) < 4000) {
points[i].active = 0.3;
points[i].circle.active = 0.6;
} else if(Math.abs(getDistance(target, points[i])) < 20000) {
points[i].active = 0.1;
points[i].circle.active = 0.3;
} else if(Math.abs(getDistance(target, points[i])) < 40000) {
points[i].active = 0.02;
points[i].circle.active = 0.1;
} else {
points[i].active = 0.0;
points[i].circle.active = 0.0;
}
drawLines(points[i]);
points[i].circle.draw();
}
}
requestAnimationFrame(animate);
}
function shiftPoint(p) {
TweenLite.to(p, 1+1*Math.random(), {x:p.originX-50+Math.random()*100,
y: p.originY-50+Math.random()*100, ease:Circ.easeInOut,
onComplete: function() {
shiftPoint(p);
}});
}
// Canvas manipulation
function drawLines(p) {
if(!p.active) return;
for(var i in p.closest) {
ctx.beginPath();
ctx.moveTo(p.x, p.y);
ctx.lineTo(p.closest[i].x, p.closest[i].y);
ctx.strokeStyle = 'rgba(255,255,255,'+ p.active+')';
ctx.stroke();
}
}
function Circle(pos,rad,color) {
var _this = this;
// constructor
(function() {
_this.pos = pos || null;
_this.radius = rad || null;
_this.color = color || null;
})();
this.draw = function() {
if(!_this.active) return;
ctx.beginPath();
ctx.arc(_this.pos.x, _this.pos.y, _this.radius, 0, 2 * Math.PI, false);
ctx.fillStyle = 'rgba(255,255,255,'+ _this.active+')';
ctx.fill();
};
}
// Util
function getDistance(p1, p2) {
return Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2);
}

How can I create a color with values for green, blue, orange, and gold only?

If one knows the "weights" of red, green, and blue, one can create a color using a class like
.blaRGB {
color: rgb(128, 128, 128)
}
.blaHSL {
color: hsl(33%, 34%, 33%)
}
and use it in HTML like so:
<p class="blaRGB">BLA RGB</p>
<p class="blaHSL">BLA HSL</p>
With the values shown above, blaRGB is dingy gray and blaHSL is white.
But what if one wants to represent combinations of other colors, such as green, blue, orange, and gold?
Is there a way to define such colors with a notation like the following?
.CyndiLauper {
color: truecolors(24, 13, 11, 12)
}
Or with color: gbog(24, 13, 11, 12) where the letters in gbog stand for green, blue, orange, and gold respectively?
The intent is that with the CSS definition above, the HTML
<p class="CyndiLauper">These are your True Colors, shining through!</p>
would display the text in a weighted combination of those four colors.
I believe this is possible using some convoluted math using the RGB values of green, blue, orange, and gold, but I don't know how to proceed with that.
UPDATE
I realize that a key component to the question, which I initially omitted, would be, "What exactly do you mean by green, blue, orange, and gold"?
To answer that, according to the official "True Colors" website, and using the ColorZilla browser add-in, the RGB values for these colors are:
green = 15, 167, 73
blue = 0, 152, 215
orange = 243, 123, 38
gold = 255, 230, 101
(They actually look more like forest green, dodger blue, red-orange, and yellow to me.)
There are many ways to mix colors, depending on what color model you're using:
additive mixing
subtractive mixing
alpha compositing
The following code snippet demonstrates two mixing methods. The leftmost column displays the four original colors. The next column shows the same colors with 0.25 opacity, resulting in translucent colors. The third column layers the translucent colors on top of one another, which is equivalent to alpha compositing.
The fourth column shows an alternative approach to mixing. Here we see the result of separately averaging the R, G, and B components of each of the four original colors.
var Colors = {
names: ['green', 'blue', 'orange', 'gold'],
values: {
green: { r: 15, g: 167, b: 73 },
blue: { r: 0, g: 152, b: 215 },
orange: { r: 243, g: 123, b: 38 },
gold: { r: 255, g: 230, b: 101 }
}
};
Colors.toHex2 = function (decimal) {
var hex = decimal.toString(16);
return (hex.length == 1 ? '0'+hex : hex);
};
Colors.toColorString = function (value) {
var g = Colors,
toHex2 = g.toHex2;
var parts = [ '#', toHex2(value.r), toHex2(value.g), toHex2(value.b) ];
return parts.join('');
};
Colors.load = function () {
var g = Colors,
names = g.names,
values = g.values,
containers = {
original: document.getElementById('original'),
translucent: document.getElementById('translucent'),
layered: document.getElementById('layered'),
averaged: document.getElementById('averaged')
},
averaged = { r: 0, g: 0, b: 0 };
document.body.style.paddingTop = 10*(1+names.length) + 'px';
for (var i = 0; i < names.length; ++i) {
var name = names[i],
value = values[name],
color = g.toColorString(value),
swatch = document.createElement('div'),
proportion = 1 / names.length;
swatch.className = 'swatch';
swatch.style.backgroundColor = color;
containers.original.appendChild(swatch);
swatch = swatch.cloneNode();
swatch.style.opacity = proportion;
containers.translucent.appendChild(swatch);
swatch = swatch.cloneNode();
swatch.style.height = 60 + 10*(names.length-1) + 'px';
swatch.style.top = 10*(1+i-names.length) + 'px';
containers.layered.appendChild(swatch);
averaged.r += proportion * value.r;
averaged.g += proportion * value.g;
averaged.b += proportion * value.b;
}
swatch = document.createElement('div');
swatch.className = 'swatch';
averaged.r = Math.round(averaged.r);
averaged.g = Math.round(averaged.g);
averaged.b = Math.round(averaged.b);
swatch.style.backgroundColor = g.toColorString(averaged);
containers.averaged.appendChild(swatch);
};
window.onload = Colors.load;
body {
font-family: sans-serif;
font-size: 24px;
margin: 0;
padding-left: 20px;
}
.display {
width: 120px;
float: left;
}
.swatch {
width: 100px;
height: 60px;
margin-bottom: 10px;
}
.layered {
position: relative;
height: 60px;
}
.layered .swatch {
position: absolute;
}
<div id="original" class="display"></div>
<div id="translucent" class="display"></div>
<div id="layered" class="display layered"></div>
<div id="averaged" class="display"></div>
In the demonstration above, we let the web browser do the alpha compositing for us. We can also do alpha compositing directly. Layer opacity is equivalent to the alpha channel, so we set the alpha channel of each color to the weight of the color. In other words, if the weight of a color is 25%, we set its alpha channel to 0.25.
Note that the alpha channel ranges from 0 to 1. However, our RGB components range from 0 to 255.
Suppose we are mixing these two colors:
RGB value background with alpha channel alpha.background
RGB value foreground with alpha channel alpha.foreground
We calculate the resulting color's alpha channel alpha.mix like so:
alpha.mix = 1 - (1-alpha.background)*(1-alpha.foreground);
To compute the R component of the RGB value mix, we do this:
mix.r = 255 * (foreground.r/255.0 * alpha.foreground/alpha.mix +
mix.r/255.0 * alpha.background*(1-alpha.foreground)/alpha.mix);
And likewise for the G component mix.g and the B component mix.b.
The code snippet below is an interactive demonstration that compares alpha compositing with the simpler approach of averaging the RGB components in parallel. Run the code and play around with the sliders to see the difference between these two approaches.
var Mixer = {
color: {
names: ['green', 'blue', 'orange', 'gold'],
rgb: {
green: { r: 15, g: 167, b: 73 },
blue: { r: 0, g: 152, b: 215 },
orange: { r: 243, g: 123, b: 38 },
gold: { r: 255, g: 230, b: 101 }
}
},
style: {
swatch: { width: 150, height: 90, margin: { right: 15 } },
slider: { height: 20 },
handle: { width: 20, height: 34 }
}
};
Mixer.toHex2 = function (decimal) {
var hex = decimal.toString(16);
return (hex.length == 1 ? '0'+hex : hex);
};
Mixer.toCSS = function (rgb) {
var g = Mixer,
toHex2 = g.toHex2;
var parts = [ '#', toHex2(rgb.r), toHex2(rgb.g), toHex2(rgb.b) ];
return parts.join('');
};
Mixer.toString = function (rgb) {
return 'rgb(' + [rgb.r, rgb.g, rgb.b].join(', ') + ')';
};
Mixer.makeUnselectable = function (element) {
element.className += ' unselectable';
element.ondragstart = element.onselectstart = function (event) {
event.preventDefault();
};
};
Mixer.makeElement = function (tag, className, innerHTML, unselectable) {
var g = Mixer,
element = document.createElement(tag);
element.className = (className ? className : '');
element.innerHTML = (innerHTML ? innerHTML : '');
if (unselectable) {
g.makeUnselectable(element);
}
return element;
};
Mixer.handleDown = function (event) {
event = event || window.event;
var g = Mixer;
g.mouseX = { depart: event.screenX };
g.activeHandle = this;
window.onmousemove = Mixer.handleMove;
window.onmouseup = Mixer.handleUp;
};
Mixer.handleMove = function (event) {
event = event || window.event;
var g = Mixer,
handle = g.activeHandle,
pos = handle.pos,
handles = g.handles,
num = g.num,
slider = g.slider,
proportion = g.proportion,
segments = g.segments,
handleWidth = g.style.handle.width,
swatches = g.swatches,
canvas = g.canvas,
context = g.context,
mixingFunctions = g.mixingFunctions,
limit = {
min: (pos == 0 ? 0 : handles[pos-1].right),
max: (pos == num-2 ? slider.length.total : handles[pos+1].left) -
handleWidth
},
mouseX = g.mouseX;
mouseX.current = event.screenX;
var left = handle.left + mouseX.current - mouseX.depart;
if (left < limit.min) {
left = limit.min;
}
if (left > limit.max) {
left = limit.max;
}
handle.newLeft = left;
segments[pos] = left - limit.min;
context.fillStyle = swatches[pos].css;
context.fillRect(limit.min, 0, segments[pos], canvas.height);
segments[pos+1] = limit.max - left;
context.fillStyle = swatches[pos+1].css;
context.fillRect(left + handleWidth, 0, segments[pos+1], canvas.height);
handle.style.left = left + 'px';
var segmentSpan = segments[pos] + segments[pos+1],
proportionSpan = proportion[pos] + proportion[pos+1];
if (segmentSpan != 0) {
proportion[pos] = Math.round(segments[pos]/segmentSpan * proportionSpan);
proportion[pos+1] = proportionSpan - proportion[pos];
swatches[pos].percent.innerHTML = proportion[pos] + '%';
swatches[pos+1].percent.innerHTML = proportion[pos+1] + '%';
}
g.mixColors();
};
Mixer.handleUp = function (event) {
var g = Mixer,
handle = g.activeHandle;
window.onmousemove = null;
window.onmouseup = null;
handle.left = handle.newLeft;
handle.right = handle.left + g.style.handle.width;
};
Mixer.makeFunctionName = function (title) {
var parts = ['mix'],
tokens = title.split(' ');
for (var i = 0; i < tokens.length; ++i) {
var token = tokens[i];
parts.push(token[0].toUpperCase() + token.substring(1));
}
return parts.join('');
};
Mixer.mixAlphaCompositing = function (swatch, label) {
return function () {
var g = Mixer,
swatches = g.swatches,
proportion = g.proportion,
num = g.num,
mix = {},
subs = ['r', 'g', 'b'];
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = swatches[0].rgb[x];
}
var alpha = { back: proportion[0]/100 };
for (var pos = 1; pos < num; ++pos) {
var fore = swatches[pos].rgb;
alpha.fore = proportion[pos]/100,
alpha.mix = 1 - (1-alpha.back)*(1-alpha.fore);
if (alpha.mix >= 1.0e-6) {
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = 255 * (fore[x]/255 * alpha.fore/alpha.mix +
mix[x]/255 * alpha.back*(1-alpha.fore)/alpha.mix);
}
}
alpha.back = alpha.mix;
}
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = Math.round(mix[x]);
}
var css = g.toCSS(mix);
label.rgb.innerHTML = g.toString(mix);
label.css.innerHTML = css;
swatch.style.backgroundColor = css;
swatch.style.opacity = alpha.mix;
};
};
Mixer.mixWeightedAverage = function (swatch, label) {
return function () {
var g = Mixer,
swatches = g.swatches,
proportion = g.proportion,
num = g.num,
mix = { r: 0, g: 0, b: 0 },
subs = ['r', 'g', 'b'];
for (var pos = 0; pos < num; ++pos) {
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] += proportion[pos]/100 * swatches[pos].rgb[x];
}
}
for (var i = 0; i < subs.length; ++i) {
var x = subs[i];
mix[x] = Math.round(mix[x]);
}
var css = g.toCSS(mix);
label.rgb.innerHTML = g.toString(mix);
label.css.innerHTML = css;
swatch.style.backgroundColor = css;
};
};
Mixer.mixColors = function () {
var g = Mixer,
mixingFunctions = g.mixingFunctions;
for (var i = 0; i < mixingFunctions.length; ++i) {
mixingFunctions[i]();
}
};
Mixer.load = function () {
var g = Mixer,
style = g.style;
// Make color swatches.
var palette = g.palette = document.getElementById('palette'),
names = g.color.names,
swatches = g.swatches = [],
num = g.num = names.length;
for (var i = 0; i < num; ++i) {
var name = names[i],
rgb = g.color.rgb[name],
css = g.toCSS(rgb),
container = g.makeElement('div', 'swatchContainer', '', true),
percent = g.makeElement('div', 'title', '', true),
swatch = g.makeElement('div', 'swatch', '', true);
swatches[i] = { rgb: rgb, css: css, percent: percent };
container.appendChild(percent);
swatch.style.backgroundColor = css;
swatch.style.width = style.swatch.width + 'px';
swatch.style.height = style.swatch.height + 'px';
swatch.style.marginRight = style.swatch.margin.right + 'px';
container.appendChild(swatch);
container.appendChild(g.makeElement('div', 'label', g.toString(rgb), true));
container.appendChild(g.makeElement('div', 'label', css, true));
palette.appendChild(container);
}
var totalWidth = num*style.swatch.width + (num-1)*style.swatch.margin.right;
// Initialize proportions.
var proportion = g.proportion = new Array(num),
each = Math.floor(100/num);
for (var i = 0; i < num-1; ++i) {
proportion[i] = each;
}
proportion[num-1] = 100 - (num-1)*each;
for (var i = 0; i < num; ++i) {
swatches[i].percent.innerHTML = proportion[i] + '%';
}
// Prepare the blended swatches.
var blend = g.blend = { container: document.getElementById('blend') },
mixers = ['alpha compositing', 'weighted average'],
between = (totalWidth - mixers.length*style.swatch.width) /
(mixers.length + 1);
g.makeUnselectable(blend);
blend.container.style.width = totalWidth + 'px';
blend.container.style.height = style.swatch.height + 'px';
g.mixingFunctions = [];
for (var i = 0; i < mixers.length; ++i) {
var mixer = mixers[i],
container = g.makeElement('div', 'swatchContainer', '', true),
title = g.makeElement('div', 'title', mixer, true),
swatch = g.makeElement('div', 'swatch', '', true),
label = {
rgb: g.makeElement('div', 'label', '', true),
css: g.makeElement('div', 'label', '', true)
};
swatch.style.width = style.swatch.width + 'px';
swatch.style.height = style.swatch.height + 'px';
container.style.left = i*style.swatch.width + (i+1)*between + 'px';
container.appendChild(title);
container.appendChild(swatch);
container.appendChild(label.rgb);
container.appendChild(label.css);
blend.container.appendChild(container);
var functionName = g.makeFunctionName(mixer),
mixingFunction = g[functionName](swatch, label);
g.mixingFunctions.push(mixingFunction);
}
// Assemble the slider widget.
var slider = g.slider = document.getElementById('slider');
slider.length = {
total: totalWidth,
free: totalWidth - (num-1)*style.handle.width
};
var segments = g.segments = new Array(num);
var tail = slider.length.free;
for (var i = 0; i < num-1; ++i) {
var current = Math.round(proportion[i]/100*slider.length.free);
segments[i] = current;
tail -= current;
}
segments[num-1] = tail;
slider.style.width = slider.length.total + 'px';
slider.style.height = style.slider.height + 'px';
var canvas = g.canvas = g.makeElement('canvas'),
context = g.context = canvas.getContext('2d');
g.makeUnselectable(slider);
g.makeUnselectable(canvas);
canvas.width = slider.length.total;
canvas.height = style.slider.height;
slider.appendChild(canvas);
var handles = g.handles = new Array(num-1);
var left = 0;
for (var i = 0; i < num; ++i) {
context.fillStyle = swatches[i].css;
context.fillRect(left, 0, segments[i], canvas.height);
if (i == num-1) {
break;
}
var handle = handles[i] = g.makeElement('div', 'handle', '', true);
handle.pos = i;
handle.style.width = style.handle.width + 'px';
handle.style.height = style.handle.height + 'px';
handle.style.top = (style.slider.height - style.handle.height)/2 + 'px';
handle.left = left + segments[i];
handle.style.left = handle.left + 'px';
handle.right = handle.left + style.handle.width;
left = handle.right;
handle.onmousedown = g.handleDown;
slider.appendChild(handle);
}
g.mixColors();
};
window.onload = Mixer.load;
body {
font-family: sans-serif;
color: #444;
}
.unselectable {
-webkit-user-select: none;
-khtml-user-drag: none;
-khtml-user-select: none;
-moz-user-select: none;
-moz-user-select: -moz-none;
-ms-user-select: none;
user-select: none;
}
#blend {
position: relative;
padding: 10px 0 90px;
}
#blend .swatchContainer {
position: absolute;
}
#blend .swatchContainer .title {
font-size: 17px;
padding-bottom: 5px;
}
#slider {
margin: 20px 0;
position: relative;
}
.handle {
position: absolute;
background: #444;
border-radius: 5px;
cursor: pointer;
}
.swatchContainer {
float: left;
}
.swatchContainer .title {
font-size: 25px;
text-align: center;
}
.swatchContainer .label {
font-size: 17px;
}
<div id="blend"></div>
<div id="slider"></div>
<div id="palette"></div>
No, you cannot. Here is a link to W3 Css Colors definition which states at the top that only blue, red, and green can be used.
Edit: Ok, so let me clarify. Natively, this is not possible, from my understanding. However, there may be things you can do using Less and Sass that can achieve your desired result. Here is some tutorial regarding Less Color functions. Most interestingly is the part about Mixing colors:
.box.mix {
background-color: mix(#blue, #yellow, 50%);
}
You would need to explore this, however, as I have no experience with it.
I wonder if the answer isn't just to 'mix' colors in RGB?
var green = [15, 167, 73];
var blue = [0, 152, 215];
var orange = [243, 123, 38];
var gold = [255, 230, 101];
generateTrueColor(greenRatio, blueRatio, orangeRatio, goldRatio){
for(var i = 0; i < 3, i++){
RGB[i] = greenRatio * green[i] + blueRatio * blue[i] + orangeRatio * orange[i] + goldRatio * gold[i];
}
return RGB;
for(var i = 0; i < 3, i++){
if(RGB[i] > 255) RGB[i] = 255;
}
}
generateTrueColor(1, 0.1, 0.1, 0.1);
I'm not sure dividing by 50 is the right/best thing to do, but this pretty much works:
// Note that the results differ from "true" blue, green, orange, and gold; the colors used to represent these are custom versions of those colors, as found on the True Colors website
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Sandbox
{
public partial class FormTrueColorsMain : Form
{
// Primary constituents of the "True Colors" hues
const int GREEN_RED = 15;
const int GREEN_GREEN = 167;
const int GREEN_BLUE = 73;
const int BLUE_RED = 0;
const int BLUE_GREEN = 152;
const int BLUE_BLUE = 215;
const int ORANGE_RED = 243;
const int ORANGE_GREEN = 123;
const int ORANGE_BLUE = 38;
const int GOLD_RED = 255;
const int GOLD_GREEN = 230;
const int GOLD_BLUE = 101;
Color tcGreen = Color.FromArgb(15, 167, 73);
Color tcGreenComplement = Color.FromArgb(240, 88, 182);
Color tcBlue = Color.FromArgb(0, 152, 215);
Color tcOrange = Color.FromArgb(243, 123, 38);
Color tcGold = Color.FromArgb(255, 230, 101);
public FormTrueColorsMain()
{
InitializeComponent();
InitializeControls();
}
private void InitializeControls()
{
lblGreen.ForeColor = tcGreen;
lblGreen.BackColor = Color.White; // tcGreenComplement;
lblBlue.ForeColor = tcBlue;
lblBlue.BackColor = Color.White;
lblOrange.ForeColor = tcOrange;
lblOrange.BackColor = Color.Black;
lblGold.ForeColor = tcGold;
lblGold.BackColor = Color.Black;
// For these to work, needed to also comment out "Application.EnableVisualStyles();" in Program.cs (see Crispy's answer at http://stackoverflow.com/questions/778678/how-to-change-the-color-of-progressbar-in-c-sharp-net-3-5)
progressBarGreen.ForeColor = tcGreen;
progressBarGreen.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarBlue.ForeColor = tcBlue;
progressBarBlue.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarOrange.ForeColor = tcOrange;
progressBarOrange.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
progressBarGold.ForeColor = tcGold;
progressBarGold.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
}
private void button1_Click(object sender, EventArgs e)
{
// If they have already been set (user clicked the arrows rather than entered the value directly), this is moot but it's
// probably not worthwhile checking to see whether their value is 0, and only calling the methods conditionally in that case.
SetGreenProgressBar();
SetBlueProgressBar();
SetOrangeProgressBar();
SetGoldProgressBar();
int greenVal = (int)numericUpDownGreen.Value;
int blueVal = (int)numericUpDownBlue.Value;
int orangeVal = (int)numericUpDownOrange.Value;
int goldVal = (int)numericUpDownGold.Value;
Color trueColor = GetTrueCombinedColor(greenVal, blueVal, orangeVal, goldVal);
pictureBoxTCCombo.BackColor = trueColor;
}
private Color GetTrueCombinedColor(int greenVal, int blueVal, int orangeVal, int goldVal)
{
// tcBlue has no red, so can disregard blueVal for redTotal
int redTotal = ((greenVal * GREEN_RED) + (orangeVal * ORANGE_RED) + (goldVal * GOLD_RED));
int greenTotal = ((greenVal * GREEN_GREEN) + (blueVal * BLUE_GREEN) + (orangeVal * ORANGE_GREEN) + (goldVal * GOLD_GREEN));
int blueTotal = ((greenVal * GREEN_BLUE) + (blueVal * BLUE_BLUE) + (orangeVal * ORANGE_BLUE) + (goldVal * GOLD_BLUE));
int redWeight = redTotal / 50;
int greenWeight = greenTotal / 50;
int blueWeight = blueTotal / 50;
if (redWeight <= 0) redWeight = 1;
if (greenWeight <= 0) greenWeight = 1;
if (blueWeight <= 0) blueWeight = 1;
if (redWeight >= 256) redWeight = 255;
if (greenWeight >= 256) greenWeight = 255;
if (blueWeight >= 256) blueWeight = 255;
Color trueColorCombo = Color.FromArgb(redWeight, greenWeight, blueWeight);
//Color trueColorCombo = Color.FromArgb(redWeight, greenWeight, blueWeight, 10);
return trueColorCombo;
}
private void numericUpDownGreen_ValueChanged(object sender, EventArgs e)
{
SetGreenProgressBar();
}
private void SetGreenProgressBar()
{
progressBarGreen.Value = (int)numericUpDownGreen.Value;
}
private void numericUpDownBlue_ValueChanged(object sender, EventArgs e)
{
SetBlueProgressBar();
}
private void SetBlueProgressBar()
{
progressBarBlue.Value = (int)numericUpDownBlue.Value;
}
private void numericUpDownOrange_ValueChanged(object sender, EventArgs e)
{
SetOrangeProgressBar();
}
private void SetOrangeProgressBar()
{
progressBarOrange.Value = (int)numericUpDownOrange.Value;
}
private void numericUpDownGold_ValueChanged(object sender, EventArgs e)
{
SetGoldProgressBar();
}
private void SetGoldProgressBar()
{
progressBarGold.Value = (int)numericUpDownGold.Value;
}
}
}
Here's what the util looks like:
Cyndi Lauper, eat your heart out!

Asteroids Canvas Game: Splitting the asteroid

I'm still making Asteroids game in canvas in html5. Everything were going good, but now I'm in deadlock. Collision works, but I have no idea how to split an asteroid after shooting in it.
Here is code:
window.addEventListener('keydown',doKeyDown,true);
window.addEventListener('keyup',doKeyUp,true);
var canvas = document.querySelector('#pageCanvas');
var context = canvas.getContext('2d');
var angle = 0;
var H = /*500;*/window.innerHeight; //*0.75,
var W = /*500;*/window.innerWidth; //*0.75;
canvas.width = W;
canvas.height = H;
var xc = W/2; //zeby bylo w centrum :v
var yc = H/2; //jw.
var x = xc;
var y = yc;
var dv = 0.2;
var dt = 1;
var vx = 0;
var vy = 0;
var fps = 30;
var maxVel = 5;
var maxVelLeft = -5;
var frict = 0.99;
var brakes = 0.90;
var keys = new Array();
var fire = false;
var points = 0;
var lives = 3;
var randomize = true;
//zamiennik do setintervala
var requestAnimationFrame = window.requestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.msRequestAnimationFrame;
var fps = 30;
var now;
var then = Date.now();
var interval = 1000/fps;
var delat;
//laser
var laserF = false;
var lasery = [];
var shootVel = 12; //velocity of laser
//asteroids
var asteroidy = [];
var newasteroid1 ={
ax : ((Math.round(Math.random()*1000))%500),
ay : ((Math.round(Math.random()*1000))%500),
avx : 1*(Math.random() > 0.5 ? -1 : 1),
avy : 1*(Math.random() > 0.5 ? -1 : 1),
ar : 30,
aangle : 3,
colour : "gray"
};
asteroidy.push(newasteroid1);
var newasteroid2 ={
ax : ((Math.round(Math.random()*1000))%500),
ay : ((Math.round(Math.random()*1000))%500),
avx : 1*(Math.random() > 0.5 ? -1 : 1),
avy : 1*(Math.random() > 0.5 ? -1 : 1),
ar : 30,
aangle : 2,
colour : "gray"
};
asteroidy.push(newasteroid2);
var newasteroid3 ={
ax : ((Math.round(Math.random()*1000))%500),
ay : ((Math.round(Math.random()*1000))%500),
avx : 1*(Math.random() > 0.5 ? -1 : 1),
avy : 1*(Math.random() > 0.5 ? -1 : 1),
ar : 30,
aangle : 2,
colour : "gray"
};
asteroidy.push(newasteroid3);
var newasteroid4 ={
ax : ((Math.round(Math.random()*1000))%500),
ay : ((Math.round(Math.random()*1000))%500),
avx : 1*(Math.random() > 0.5 ? -1 : 1),
avy : 1*(Math.random() > 0.5 ? -1 : 1),
ar : 30,
aangle : 0,
colour : "fuchsia"
};
asteroidy.push(newasteroid4);
function doKeyUp(evt){
keys[evt.keyCode] = false;
fire = false;
if (laserF) {
var newlaser ={
lx: x,
ly: y,
//lw : 4,
//lh : 4,
lr : 2,
lvx : Math.cos(convertToRadians(angle)),
lvy : Math.sin(convertToRadians(angle))
}
lasery.push(newlaser);
laserF = false;
}
}
function doKeyDown(evt){
keys[evt.keyCode] = true;
if(40 in keys && keys[40]){
if(randomize){
x = (Math.round(Math.random()*1000))%W;
y = (Math.round(Math.random()*1000))%H;
vx = 0;
vy = 0;
randomize = false;
setTimeout(function(){randomize = true;}, 2000);
}
}
}
function drawPoints(){
context.save();
context.setTransform(1,0,0,1,0,0);
context.beginPath();
context.fillText("Score: " + points, 50, 50);
context.fillStyle = "#FFFFFF";
context.fill();
context.closePath();
context.restore();
}
function drawLives(){
context.save();
context.setTransform(1,0,0,1,0,0);
context.beginPath();
context.fillText(lives + " lives left", 150, 50);
context.fillStyle = "#FFFFFF";
context.fill();
context.closePath();
context.restore();
}
function drawAsteroids(idx){
var asteroid = asteroidy[idx];
context.save();
context.setTransform(1,0,0,1,0,0);
context.rotate(0);
context.translate(asteroid.ax, asteroid.ay);
context.rotate(asteroid.aangle);
context.translate(-25,-25);
context.beginPath();
context.fillText(asteroid.ax + " " + asteroid.ay, 0,50);
context.arc(0, 0, asteroid.ar, 0, 2 * Math.PI, false);
context.fillStyle = asteroid.colour;
context.fill();
context.closePath();
/*beginPath();
moveTo(0,0);
lineTo()*/
context.restore();
}
function moveAsteroids(idx){
var asteroid = asteroidy[idx]
asteroid.ax += asteroid.avx;
asteroid.ay += asteroid.avy;
asteroid.aangle += 0.009;
if(asteroid.ax > W){
asteroid.ax = 0 -25;
}
else{
if(asteroid.ax < -25){
asteroid.ax = W;
}
}
if(asteroid.ay > H){
asteroid.ay = 0 -25;
}
else{
if(asteroid.ay < -25){
asteroid.ay = H;
}
}
}
function drawLaser(idx) {
var laser = lasery[idx];
context.save();
context.translate(laser.lx,laser.ly);
context.fillStyle = "red";
//context.fillText(laser.lx + " " + laser.ly,10,10);
//context.fillRect(0,0,laser.lw,laser.lh);
context.beginPath();
context.arc(0, 0, laser.lr, 0, 2 * Math.PI, false);
context.fillStyle = "red";
context.fill();
context.closePath();
context.restore();
}
function moveLaser(idx) {
var laser = lasery[idx];
laser.lx += laser.lvx * shootVel;
laser.ly += laser.lvy * shootVel;
if (laser.lx > W || laser.lx < 0 || laser.ly > H || laser.ly < 0) {
lasery.splice(idx, 1);
}
}
//OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
function ogienZdupy(){
context.fillStyle = "red";
context.beginPath();
context.moveTo(-2,2);
context.lineTo(2,10);
context.lineTo(-2,18);
context.lineTo(-25,10);
context.lineTo(-2,2);
context.strokeStyle = "red";
context.stroke();
}
function convertToRadians(degree) {
return degree*(Math.PI/180);
}
function incrementAngle() {
angle += 5;
if(angle > 360){
angle = 0;
}
}
function decrementAngle(){
angle -= 5;
if(angle > 360){
angle = 0;
}
}
function xyVelocity(){
vx += dv * Math.cos(convertToRadians(angle)); //* friction;
vy += dv * Math.sin(convertToRadians(angle)); //* friction;
if(vx > maxVel){
vx = maxVel;
}
if(vy < maxVelLeft){
vy = maxVelLeft;
}
if(vx < maxVelLeft){
vx = maxVelLeft;
}
if(vy > maxVel){
vy = maxVel;
}
}
function shipMovement(){
if(66 in keys && keys[66]){ //it's B
vx = 0;
vy = 0;
}
if(38 in keys && keys[38]){
xyVelocity();
fire = true;
}
if(37 in keys && keys[37]){
decrementAngle();
};
if (39 in keys && keys[39]){
incrementAngle();
};
if (32 in keys && keys[32]){
laserF = true;
};
}
function xyAndFriction(){
x += vx * dt;
y += vy * dt;
vx *= frict;
vy *= frict;
}
function outOfBorders(){
if(x > W){
x = x - W;
}
if(x< 0){
x = W;
}
if(y > H){
y = y - H;
}
if(y < 0){
y = H;
}
}
function blazeatron420(){ //the ship
context.beginPath();
context.moveTo(0,0);
context.lineTo(20,10);
context.lineTo(0,20);
context.lineTo(7,10);
context.lineTo(0,0);
context.strokeStyle = "green";
context.stroke();
}
function space(){
context.fillStyle = "black";
context.fillRect(0,0,W,H);
}
/*
function superLaserCollider(){
for(var i in asteroidy){
var ax = asteroidy[i].ax,
ay = asteroidy[i].ay,
ar = asteroidy[i].ar
for(var j in lasery){
var xl = lasery[j].lx,
yl = lasery[j].ly,
rl = lasery[j].lr
}
}
/*var dx = Math.abs(ax - (xl+wl/2));
var dy = Math.abs(ay - (yl+yl/2));
if(dx > ar + wl){
return (false);
}
if(dy > ar + hl){
return (false);
}
if(dx <= wl){
return (true);
}
if(dy <= hl){
return (true);
}
var dx = dx - wl;
var dy = dy - hl;
return(dx * dx + dy * dy <= ar * ar);
var dx = ax - xl;
var dy = ay - yl;
var distance = Math.sqrt(dx * dx + dy * dy);
if(xl > ax && yl > ax){
console.log("kolizja");
}
}
*/
function bigAsteroidExplosion(idx){
var asteroid = asteroidy[idx];
context.clearRect(asteroid.ax, asteroid.ay, 100, 100);
}
function superLaserCollider(){
for(var i in asteroidy){
var ax = asteroidy[i].ax,
ay = asteroidy[i].ay,
ar = asteroidy[i].ar;
for(var j in lasery){
var xl = lasery[j].lx,
yl = lasery[j].ly,
rl = lasery[j].lr;
var dx = ax - xl;
var dy = ay - yl;
var distance = Math.sqrt(dx * dx + dy * dy);
if(distance < ar + rl){
console.log("kabom");
points = points + 100;
//alert("BOOM");
console.log(points);
}
}
}
}
/*
context.beginPath();
context.fillText(points, 100, 100);
context.fillStyle = "#FFFFFF";
context.fill();
context.closePath();
*/
function drawEverything() {
shipMovement();
xyAndFriction();
outOfBorders();
//context.save();
//;
space();
context.save();
context.translate(x,y);
//context.translate(25,25);
context.rotate(convertToRadians(angle));
context.translate(-7,-10);
if(fire){
ogienZdupy();
}
context.fillStyle = "green";
//context.fillText(vx + " km/h",50,50);
/*context.fillText("dupa",-30,0);
context.beginPath();
context.moveTo(-20,5);
context.lineTo(-5,10);
context.strokeStyle = "green"; //KOLOR LINII ;_;
context.stroke();*/
if(asteroidy.length > 0 ){
for (var tmp in asteroidy){
drawAsteroids(tmp);
moveAsteroids(tmp);
}
}
//putAsteroids();
blazeatron420();
//shootAsteroid(idx);
context.translate(-x+7,-y+10);
drawPoints();
drawLives();
context.restore();
console.log(asteroidy.length);
//superCollider();
//for(var i = 0; i < asteroidy.length; i++)
if(lasery.length > 0){
for (var tmp in lasery) {
drawLaser(tmp);
moveLaser(tmp);
}
}
superLaserCollider();
}
//setInterval(drawEverything, 20);
function draw(){
requestAnimationFrame(draw);
now = Date.now();
delta = now - then;
if (delta > interval){
then = now - (delta % interval);
}
drawEverything();
}
draw();
body{
margin:0;
padding:0;
overflow:hidden;
}
<body>
<canvas id="pageCanvas" style="display:block">
You do not have a canvas enabled browser. Please, stop using IE :P
</canvas>
</body>