How to repaint a text in javascript? - javascript

I have a problem in my game, whitch im preety sure its concerning repaint. So this game is that if you touch the blue cube by manually controlling your black cube by the arrow keys you get a point each time. Well when you do that as it adds up, the new score draws on it self. This picture is a better explanation(Thankyou):
Here is the JSFiddle Format , Click on edit in the top right corner to edit the code. WARNING : you need to click on the game to work.
Here is the code:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Snake Game</title>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<!-- Basic styling, centering the canvas -->
<style>
</style>
</head>
<body>
<canvas id = "game" width = "500" height = "500"></canvas>
<script>
$(document).ready(function(){
var WIDTH = 500;
var HEIGHT = 500;
var keys = {};
var canvas = document.getElementById('game');
var ctx = canvas.getContext('2d');
var score=0;
var snake = {
x:null,
y:null,
width:15,
height:15,
speed : 7,
draw:function(){
ctx.save();
ctx.fillStyle = 'black'
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.restore();
},
/*
left arrow 37
up arrow 38
right arrow 39
down arrow 40
*/
update:function(){
if(keys[39]){
ctx.clearRect(this.x, this.y, this.width, this.height);
this.x += this.speed;
}
if(keys[37]){
ctx.clearRect(this.x, this.y, this.width, this.height);
this.x -= this.speed;
}
if(keys[38]){
ctx.clearRect(this.x, this.y, this.width, this.height);
this.y -= this.speed;
}
if(keys[40]){
ctx.clearRect(this.x, this.y, this.width, this.height);
this.y += this.speed;
}
//Checks if it is out of Bounds
if(this.x>WIDTH-this.width){
this.x=WIDTH-this.width;
}
if(this.x<0){
this.x=0;
}
if(this.y>HEIGHT-this.width){
this.y=HEIGHT-this.width;
}
if(this.y<0){
this.y=0;
}
//Checks Collision
var Collision = function(ax, ay, aw, ah, bx, by, bw, bh) {
return ax < bx+bw && ay < by+bh && bx < ax+aw && by < ay+ah;
};
if(Collision(snake.x,snake.y,snake.width,snake.height,fruits.x,fruits.y,fruits.width,fruits.height)){
ctx.clearRect(fruits.x, fruits.y, fruits.width, fruits.height);
score +=1;
fruits.x = Math.floor(Math.random()*WIDTH);
fruits.y = Math.floor(Math.random()*HEIGHT);
}
}
}
var fruits = {
x:null,
y:null,
width:15,
height:15,
draw:function(){
ctx.save();
ctx.fillStyle = 'blue'
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.restore();
},
update:function(){
}
}
function main(){
document.addEventListener("keydown" , function(event){
keys[event.keyCode] = true;
})
document.addEventListener("keyup" , function(event){
delete keys[event.keyCode];
})
init();
var loop = function (){
update();
draw();
window.requestAnimationFrame(loop, canvas);
};
window.requestAnimationFrame(loop, canvas);
}
function init(){
snake.x = 20;
snake.y = 20;
fruits.x = (WIDTH)/2;
fruits.y = HEIGHT/2;
}
function draw(){
//Drawing the Square
ctx.save();
ctx.beginPath();
ctx.moveTo(0,0);
ctx.lineTo(0,HEIGHT);
ctx.lineTo(HEIGHT,WIDTH);
ctx.lineTo(WIDTH,0)
ctx.lineTo(0,0)
ctx.stroke();
ctx.save();
ctx.fillStyle = "red";
ctx.font = "bold 40px monaco";
ctx.fillText(score,60,100);
ctx.save();
snake.draw();
fruits.draw();
ctx.restore();
}
function update(){
snake.update();
fruits.update();
}
main();
})
</script>
</body>
</html>

Try this...
ctx.save();
ctx.clearRect(1, 1, WIDTH - 2, HEIGHT - 2);
ctx.fillStyle = "red";
ctx.font = "bold 40px monaco";
ctx.fillText(score,60,100);
ctx.save();
It seems to work ok for me in your JSFiddle. The rect is the whole screen so you reduce the size of it if you want.

Related

Marker shaped canvas pen - Issues with two silmutaneous strokes

I am trying to create a marker style pencil with which one can draw on a canvas: a slightly rotated rectangle as pencil tip. My idea was to simply have to simultaneous strokes on mousedown, one of which is moved to the right and to the top a little bit so that is appears like a marker.
This is my code:
function draw(e) {
if (e.buttons !== 1) return;
ctx.beginPath();
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.moveTo(pos.x, pos.y);
setPosition(e);
ctx.lineTo(pos.x, pos.y);
ctx.moveTo(pos.x + 2, pos.y + 2);
setPosition(e);
ctx.lineTo(pos.x + 2, pos.y+1);
ctx.stroke();
}
When I draw slowly, it works perfectly. When I speed up the cursor, however, one of the two strokes is not ecxecuted properly:
Does someone have an idea how I can get both strokes to work?
Thank you!
Edit: Removing some redundancy produced a new issue with the line:
function draw(e) {
if (e.buttons !== 1) return;
ctx.beginPath();
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.moveTo(pos.x, pos.y);
setPosition(e);
ctx.moveTo(pos.x + 2, pos.y + 2);
ctx.stroke();
}
EDIT: example:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
resize();
var pos = { x: 0, y: 0 };
window.addEventListener('resize', resize);
document.addEventListener('mousemove', draw);
document.addEventListener('mousedown', setPosition);
document.addEventListener('mouseenter', setPosition);
function setPosition(e) {
pos.x = e.clientX + $(document).scrollLeft();
pos.y = e.clientY + $(document).scrollTop();
}
function resize() {
ctx.canvas.width = $('#canvas').width();
ctx.canvas.height = $('#canvas').height();
}
function draw(e) {
if (e.buttons !== 1) return;
ctx.beginPath();
ctx.lineWidth = 5;
ctx.lineCap = 'round';
ctx.strokeStyle = '#000000';
ctx.moveTo(pos.x, pos.y);
setPosition(e);
ctx.lineTo(pos.x + 2, pos.y+2);
ctx.stroke();
}
#canvas {
width: 200px;
height: 200px;
border: 1px solid black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<canvas id="canvas"></canvas>

Javascript Canvas Movement

I have this movement in my canvas:
Gif
I am trying to move everything but the black-gray square. I have tried many times but i dont know how to get the result i need, the rotation is made like this:
ctx.translate(x, y);
if (or == 'R') {
ctx.rotate(Math.PI / movementSpeed);
}
else if (or == 'L'){
ctx.rotate(-Math.PI / movementSpeed);
}
ctx.translate(-x, -y);
drawRect();
drawRect2();
drawCircle();
And the black-gray square i am trying to not move is made like this:
function drawRect() {
ctx.fillStyle = "#393939";
ctx.fillRect(x-35, y-30, 180, 60);
ctx.stroke();
ctx.fill();
ctx.restore();
}
Code snippet:
<!DOCTYPE html>
<html lang="en">
<head>
<style type="text/css">
#import url('https://fonts.googleapis.com/css2?family=Jost:wght#500&display=swap');
body
{
overflow: hidden;
}
div#cerradura {
position: absolute;
width: 100%;
left:5%;
text-align: center;
font-size: 18px;
}
</style>
</head>
<body>
<div onclick="" id="cerradura">
<canvas id="myCanvas" width="1600" height="800">
</canvas>
</div>
</body>
<script>
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
let tensorAdentro = false;
let movimiento = 500;
let rotacion = 0;
let x = 1100;
let y = 400;
function dibujarGanzua() {
// GanzĂșa
ctx.lineWidth = 7;
ctx.strokeStyle = "#595959";
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y+190);
ctx.stroke();
ctx.restore();
}
function dibujarManija() {
// Rectangulo de la cerradura
ctx.fillStyle = "#393939";
ctx.fillRect(x-35, y-30, 180, 60);
ctx.stroke();
ctx.fill();
ctx.restore();
}
function dibujarCerradura() {
ctx.strokeStyle = "#000000";
// Circulo de la cerradura
ctx.fillStyle = '#909090';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(x, y, 20, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
ctx.restore();
// Hueco de la cerradura
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(x-10, y);
ctx.lineTo(x+10, y);
ctx.stroke();
ctx.restore();
}
function girarGanzua(or) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(x, y);
if (or == 'R') {
ctx.rotate(Math.PI / movimiento);
rotacion += (((Math.PI / movimiento)*180)/Math.PI);
}
else if (or == 'L'){
ctx.rotate(-Math.PI / movimiento);
rotacion += (-((Math.PI / movimiento)*180)/Math.PI);
}
ctx.translate(-x, -y);
dibujarManija();
dibujarCerradura();
dibujarGanzua();
}
window.addEventListener('mousedown', (e) => {
if (!tensorAdentro && e.button === 0) {
dibujarGanzua();
tensorAdentro = !tensorAdentro;
}
});
// Lee input de mouse
var direction = "",
oldx = 0,
mousemovemethod = function (e) {
dx = e.clientX - oldx;
if (dx < 0 && tensorAdentro) {
if (rotacion <= 90) {
girarGanzua('R')
}
}
else if (dx > 0 && tensorAdentro){
if (rotacion > 0) {
girarGanzua('L')
}
}
oldx = e.clientX;
}
document.addEventListener('mousemove', mousemovemethod);
dibujarManija();
dibujarCerradura();
</script>
</html>
How can i make this happen?
Thanks.
What is happening here is that the context is getting rotated on every mouse move without getting restored to the original state. It would be better to save the context before drawing and restore it when finished drawing. And, to rotate it by the correct angle, just rotate it by rotacion * Math.PI / 180 every time.
function girarGanzua(or) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save(); // Save the context
dibujarManija(); // Draw the large Rect before rotating
ctx.translate(x, y);
ctx.rotate(rotacion * Math.PI / 180);
if (or == 'R') {
rotacion += (((Math.PI / movimiento)*180)/Math.PI);
}
else if (or == 'L'){
rotacion += (-((Math.PI / movimiento)*180)/Math.PI);
}
ctx.translate(-x, -y);
dibujarCerradura();
dibujarGanzua();
ctx.restore(); // Restore the context
}
Also, there is no need to restore the context after drawing each entity.
Working Snippet:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
let tensorAdentro = false;
let movimiento = 500;
let rotacion = 0;
let x = 200;
let y = 200;
function dibujarGanzua() {
// GanzĂșa
ctx.lineWidth = 7;
ctx.strokeStyle = "#595959";
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x, y+190);
ctx.stroke();
//ctx.restore(); No Need
}
function dibujarManija() {
// Rectangulo de la cerradura
ctx.fillStyle = "#393939";
ctx.fillRect(x-35, y-30, 180, 60);
ctx.stroke();
ctx.fill();
//ctx.restore(); No Need
}
function dibujarCerradura() {
ctx.strokeStyle = "#000000";
// Circulo de la cerradura
ctx.fillStyle = '#909090';
ctx.lineWidth = 2;
ctx.beginPath();
ctx.arc(x, y, 20, 0, 2 * Math.PI);
ctx.stroke();
ctx.fill();
//ctx.restore(); No Need
// Hueco de la cerradura
ctx.lineWidth = 6;
ctx.beginPath();
ctx.moveTo(x-10, y);
ctx.lineTo(x+10, y);
ctx.stroke();
//ctx.restore(); No Need
}
function girarGanzua(or) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.save();
dibujarManija();
ctx.translate(x, y);
ctx.rotate(rotacion * Math.PI / 180);
if (or == 'R') {
rotacion += (((Math.PI / movimiento)*180)/Math.PI);
}
else if (or == 'L'){
rotacion += (-((Math.PI / movimiento)*180)/Math.PI);
}
ctx.translate(-x, -y);
dibujarCerradura();
dibujarGanzua();
ctx.restore();
}
window.addEventListener('mousedown', (e) => {
if (!tensorAdentro && e.button === 0) {
dibujarGanzua();
tensorAdentro = !tensorAdentro;
}
});
// Lee input de mouse
var direction = "",
oldx = 0,
mousemovemethod = function (e) {
dx = e.clientX - oldx;
if (dx < 0 && tensorAdentro) {
if (rotacion <= 90) {
girarGanzua('R')
}
}
else if (dx > 0 && tensorAdentro){
if (rotacion > 0) {
girarGanzua('L')
}
}
oldx = e.clientX;
}
document.addEventListener('mousemove', mousemovemethod);
dibujarManija();
dibujarCerradura();
#import url('https://fonts.googleapis.com/css2?family=Jost:wght#500&display=swap');
body
{
overflow: hidden;
}
div#cerradura {
position: absolute;
width: 100%;
left:5%;
text-align: center;
font-size: 18px;
}
<div onclick="" id="cerradura">
<canvas id="myCanvas" width="1600" height="800"></canvas>
</div>

"OOP" in canvas correct way

I'm trying to draw something on canvas with sugar code that we received not that long time ago. I'm using babel of course. I have two questions. First of all you can find my code below:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
class Rectangle {
constructor(x, y) {
this.x = x;
this.y = y;
}
draw() {
ctx.beginPath();
ctx.rect(this.x, this.y, 50, 50);
ctx.fillStyle = "#000";
ctx.fill();
ctx.closePath();
};
move() {
document.addEventListener('keydown', event => {
if (event.keyCode === 37) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
this.x--
this.draw();
}
if (event.keyCode === 39) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
this.x++
this.draw();
}
})
}
}
class Ball {
constructor(x, y) {
this.x = x;
this.y = y;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, 10, 0, Math.PI*2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
};
}
const rect = new Rectangle(130, 50);
const ball = new Ball(60, 40)
setInterval(() => {
rect.draw();
rect.move();
ball.draw();
}, 100);
I made two classes. One is rectangle, second ball. Rectangle is the one that can move with arrows. When i move, ball disapears for a brief second, then appears on the screen again. What am i doing wrong in this case? How game flow should look like properly?
Second question is: how can i make these two classes interract with each other? For example, i want that when rectangle will touch ball simple console.log will apear. Thanks
Most of the code is yours. Since I prefer using requestAnimationFrame I'm adding an identifier for the request: let requestId = null;.
The move() method of the rectangle deals only with the value of x, and takes the key as an attribute.
Also I've written the frame function that builds your animation frame by frame.
function frame() {
requestId = window.requestAnimationFrame(frame);
ctx.clearRect(0, 0, canvas.width, canvas.height);
rect.move(key);
rect.draw();
ball.draw();
}
On keydown you change the value for the key variable, you cancel the current animation, and you call the frame function to start a new animation.
I've added as well a keyup event to stop the animation on key up.
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
let key;
let requestId = null;
class Rectangle {
constructor(x, y) {
this.x = x;
this.y = y;
}
draw() {
ctx.beginPath();
ctx.rect(this.x, this.y, 50, 50);
ctx.fillStyle = "#000";
ctx.fill();
//ctx.closePath();
}
move(key) {
if (key == 37) {
this.x--;
}
if (key == 39) {
this.x++;
}
}
}
class Ball {
constructor(x, y) {
this.x = x;
this.y = y;
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, 10, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
//ctx.closePath();
}
}
const rect = new Rectangle(130, 50);
const ball = new Ball(60, 40);
rect.draw();
ball.draw();
function frame() {
requestId = window.requestAnimationFrame(frame);
ctx.clearRect(0, 0, canvas.width, canvas.height);
rect.move(key);
rect.draw();
ball.draw();
}
document.addEventListener("keydown", event => {
if (requestId) {
window.cancelAnimationFrame(requestId);
}
key = event.keyCode;
frame();
});
document.addEventListener("keyup", event => {
if (requestId) {
window.cancelAnimationFrame(requestId);
}
});
canvas{border:1px solid;}
<canvas id="myCanvas"></canvas>
PS: Please read this article requestAnimationFrame for Smart Animating

nothing is drawn on page using javascript and canvas

I am trying to develop a game and i am starting to dip my toes into the HTML <canvas> tag and using it with javascript. My program here is my work in progress clone of PONG. I have managed to add the two paddles with no error but as i have added the Ball function it simply refuses to draw anything on the screen and thus i am given a page covered in black.
Could it be because i am using classes?
Here is the code:
// ctx.fillStyle = 'rgba(red, green, blue, alpha)';
// ctx.fillRect(x, y, width, height);
var canvas;
var ctx;
var dx = 5;
var dy = 5;
//Class Definitions
function Game(width, height, colour) {
this.width = width;
this.height = height;
this.colour = colour;
}
function Player(width, height, colour, x, y, up, down) {
this.width = width;
this.height = height;
this.colour = colour;
this.x = x;
this.y = y;
this.up = up;
this.down = down;
this.move = function(ny) {
this.y = this.y + ny;
ctx.fillStyle = this.colour;
ctx.fillRect(this.x, this.y, this.width, this.height);
};
}
function Ball(width, height, colour, x , y, isTouched, isInGoal) {
this.width = width;
this.height = height;
this.colour = colour;
this.x = x;
this.y = y;
this.isTouched = isTouched;
this.isInGoal = isInGoal;
this.move = function() {
clear();
this.x = this.x + 1;
ctx.fillStyle = this.colour;
ctx.fillRect(this.x, this.y, this.width, this.height);
};
}
//Creating new Classes
var gameStage = new Game((window.innerWidth), (window.innerHeight), 'rgb(0,0,0)');
var paddleOne = new Player(10, 150, 'rgb(255,255,255)', (gameStage.width/10), (gameStage.height/2), 38, 40);
var paddleTwo = new Player(10, 150, 'rgb(255,255,255)', (gameStage.width/1.1), (gameStage.height/2), 87, 83);
var ball = new Ball(20, 20, 'rgb(255,255,255)', (gameStage.width/2), (gameStage.height/2), 0, 0);
//Initialisation
function init(){
canvas = document.getElementById('game');
canvas.setAttribute('width', gameStage.width);
canvas.setAttribute('height', gameStage.height);
canvas.setAttribute('tabindex', 0);
if (game.getContext){
ctx = canvas.getContext('2d');
return setInterval(ball.move, 10);
return setInterval(draw, 10);
}
}
//Canvas Functions
function clear(){
ctx.clearRect(0, 0, gameStage.width, gameStage.height);
}
function draw() {
clear();
ctx.fillStyle = gameStage.colour;
ctx.fillRect(0, 0, gameStage.width, gameStage.height);
ctx.fillStyle = paddleOne.colour;
ctx.fillRect(paddleOne.x, paddleOne.y, paddleOne.width, paddleOne.height);
ctx.fillStyle = paddleTwo.colour;
ctx.fillRect(paddleTwo.x, paddleTwo.y, paddleTwo.width, paddleTwo.height);
console.log("PlayerOne Y Coordinate: " + paddleOne.y + "\n");
console.log("PlayerTwo Y Coordinate: " + paddleTwo.y + "\n");
}
//Player Control
function doKeyDown(e) {
if (e.keyCode == paddleOne.up){
paddleOne.move(-5);
} else if (e.keyCode == paddleOne.down) {
paddleOne.move(5);
} else if (e.keyCode == paddleTwo.up) {
paddleTwo.move(-5);
} else if (e.keyCode == paddleTwo.down) {
paddleTwo.move(5);
}
}
//For HTML
function beginStuff(){
init();
window.addEventListener('keydown', doKeyDown, true);
}
* { margin: 0; padding: 0;}
body, html {height: 100%;}
#game {
position: absolute;
width:100%;
height:100%;
background-color: #000000;
}
<!DOCTYPE HTML>
<htmL>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>A game</title>
<script type="text/javascript" src="game.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body onload="beginStuff();" >
<canvas id="game">
Please upgrade your browser to support HTML5. <br/>
</canvas>
</body>
</htmL>
This looks wrong to me:
return setInterval(ball.move, 10);
return setInterval(draw, 10);
Firstly, you've got 2 returns. Secondly, you've lost the binding on the move method:
return setInterval(ball.move.bind(ball), 10);
If that doesn't fix it I suggest stepping through in a debugger, line-by-line, making sure that everything is doing exactly what you expect it to.
With help from #skirtle, i moved the ball.move(); to the draw() function and removed the clear() call from the ball.move() function.

Insert drawn shape over canvas background image

In an html document, I have a canvas with a background image, and am drawing a shape and storing it as an object, and then reinserting it as an element of the canvas. As it stands now, the act of reinserting the shape as a canvas element imposes part of the canvas over the background, so that the shape is surrounded by the color of the canvas instead of being drawn over the canvas background. Is there a way to avoid this but still be able to insert the image where I would like? (I know I could save the image as a png and then make its background transparent, but I'd like to do it in the html itself.) I've seen a few things tangential to this, but none that I've found address it directly.
Fiddle: https://jsfiddle.net/ZLevine/h3mo50w8/4/
I used sample code from https://msdn.microsoft.com/en-us/library/gg589516(v=vs.85).aspx to draw the shape.
Code in fiddle:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
canvas {
border:1px solid #d3d3d3;
background-image: white;
}
</style>
<head>
<body onload="startGame()">
<script>
var ship = new Image();
var myBackground;
function startGame() {
myBackground = new component(656, 541, "http://wallpapercave.com/wp/PU5vVEd.jpg", 0, 0, "background");
myScore = new component("30px", "Consolas", "white", 280, 40, "text");
myGameArea.start();
makeShip();
}
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 480;
this.canvas.height = 540;
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);
},
stop : function() {
clearInterval(this.interval);
}
}
function makeShip() {
ctx = myGameArea.context
// Draw saucer bottom.
ctx.beginPath();
ctx.moveTo(28.4, 16.9);
ctx.bezierCurveTo(28.4, 19.7, 22.9, 22.0, 16.0, 22.0);
ctx.bezierCurveTo(9.1, 22.0, 3.6, 19.7, 3.6, 16.9);
ctx.bezierCurveTo(3.6, 14.1, 9.1, 11.8, 16.0, 11.8);
ctx.bezierCurveTo(22.9, 11.8, 28.4, 14.1, 28.4, 16.9);
ctx.closePath();
ctx.fillStyle = "rgb(222, 103, 0)";
ctx.fill();
// Draw saucer top.
ctx.beginPath();
ctx.moveTo(22.3, 12.0);
ctx.bezierCurveTo(22.3, 13.3, 19.4, 14.3, 15.9, 14.3);
ctx.bezierCurveTo(12.4, 14.3, 9.6, 13.3, 9.6, 12.0);
ctx.bezierCurveTo(9.6, 10.8, 12.4, 9.7, 15.9, 9.7);
ctx.bezierCurveTo(19.4, 9.7, 22.3, 10.8, 22.3, 12.0);
ctx.closePath();
ctx.fillStyle = "rgb(51, 190, 0)";
ctx.fill();
// Save ship data.
ship = ctx.getImageData(0, 0, 30, 30);
}
function component(width, height, color, x, y, type) {
this.type = type;
if (type == "image" || type == "background") {
this.image = new Image();
this.image.src = color;
}
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
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);
} if (type == "image" || type == "background") {
ctx.drawImage(this.image,
this.x,
this.y,
this.width, this.height);
if (type == "background") {
ctx.drawImage(this.image, this.x,
this.y - this.height,
this.width, this.height);
}
}
else {
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
}
this.newPos = function() {
this.x += this.speedX;
this.y += this.speedY;
if (this.type == "background") {
if (this.y == (this.height)) {
this.y = 0;
}
}
}
}
function updateGameArea() {
myGameArea.clear();
myBackground.speedY = 1;
myBackground.newPos();
myBackground.update();
myGameArea.frameNo += 1;
ctx.putImageData(ship, 200, 200);
}
function everyinterval(n) {
if ((myGameArea.frameNo / n) % 1 == 0) {return true;}
return false;
}
</script>
</div>
</body>
</html>
The problem is that using putImageData() will draw verbatim what you stored as ImageData when using getImageData(). As the ship is surrounded by transparent pixels also these are copied to the canvas overriding what is there.
As markE mentions in his answer, drawing to a temporary canvas is a better solution. All you need to do is to change a couple of places in the code:
// Save ship data.
//ship = ctx.getImageData(0, 0, 30, 30);
ship = document.createElement("canvas"); // create canvas
ship.width = ship.height = 30; // set size
var shipCtx = ship.getContext("2d"); // temp. context
shipCtx.drawImage(ctx.canvas, 0, 0); // draw ship to canvas
Then when you want to draw it back:
function updateGameArea() {
myGameArea.clear();
myBackground.speedY = 1;
myBackground.newPos();
myBackground.update();
myGameArea.frameNo += 1;
//ctx.putImageData(ship, 200, 200);
ctx.drawImage(ship, 200, 200); // draw ship from canvas
}
Updated fiddle
An alternative approach is to draw the shape directly onto the canvas, but using a intermediate canvas will give performance benefits.
Draw the ship on a second in-memory canvas:
var memCanvas=document.createElement('canvas');
... draw your ship on the second canvas
Then use the second canvas to draw your ship on the main canvas:
canvas.drawImage(memCanvas,x,y);

Categories

Resources