The main game of JS Canvas

I am working on the canvas-based JS foundation, which is something like missile defense and space invaders, and I need help.

I have a small tower at the bottom of the screen that shoots circles from the trunk, but for some reason, the last shot circle seems to be behind the second circle. However, when the shot of another shot, the lagging circle disappears due to the original, and then appears after a new shot. In addition, I have a square that comes down from the screen, which is an alien invader that acts strangely. An alien flies at 250 pixels, and then begins to move along a square path until it is destroyed. It seems that the square representing the alien changes size when it moves along the edges of the square path, which obviously should not occur.

Besides these two issues, I would like to hear any suggestions about the code. I have never used JavaScript before and really don't code much in general, so any help / guidance is appreciated.

This is a working demo: http://jsbin.com/ehezuj/1/edit

This is my code:

<!doctype html> <html> <head> <meta charset="UTF-8" /> <title>Space Game Demo</title> </head> <body> <section> <div> <canvas id="canvas" width="800" height="600"> Your browser does not support HTML5. </canvas> </div> <script type="text/javascript"> //Start of script var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); var x = 400; var y = 0; var direction = 0; var mouseDown = false; var gloop; var shots = new Array; var aliens = new Array; aliens.push(new basicAlien()); var playerTurret = new (function() { //turret object var that = this; that.draw = function() { ctx.fillStyle = "white"; ctx.strokeStyle = "white"; ctx.rect(380, 540, 40, 60); //draw base ctx.fill(); ctx.beginPath(); ctx.arc(400, 540, 20, Math.PI, 2*Math.PI); ctx.fill(); ctx.beginPath(); ctx.lineWidth="10"; ctx.moveTo(400, 540); var tempX, tempY, temp; temp = getTrajectory(x, y); tempX = 35 * temp[0]; tempY = 35 * temp[1]; ctx.lineTo(tempX + 400, 540 - tempY); ctx.stroke(); } }); function basicAlien() { var that = this; that.step = 0; that.bottom = false; that.vel = 2; that.pos = [(Math.random() * 740) + 30, -10]; that.move = function() { if (that.pos[1] >= 250) {that.bottom = true;} if (!that.bottom) { that.pos[1] += that.vel; } else { if (that.step < 20) { that.pos[0] += that.vel; } else if (that.step < 40) { that.pos[1] -= that.vel; } else if (that.step < 60) { that.pos[0] -= that.vel; } else { that.pos[1] += that.vel; } that.step = (that.step+1)%80; } } that.draw = function() { ctx.fillStyle = "white"; ctx.rect(that.pos[0] - 10, that.pos[1] - 5, 20, 10); ctx.fill(); } }; function shotObject(shotX, shotY) { var that = this; that.traj = getTrajectory(shotX, shotY); that.vel = 10; that.pos = [400, 540]; that.draw = function() { ctx.fillStyle = "white"; ctx.beginPath(); ctx.arc(that.pos[0], that.pos[1], 5, 0, 2 * Math.PI); ctx.fill(); } that.move = function() { that.pos[0] += that.vel * that.traj[0]; that.pos[1] -= that.vel * that.traj[1]; if (that.pos[0] < -10 || that.pos[0] > 810 || that.pos[1] < -10 || that.pos[1] > 610) { shots.splice(shots.indexOf(that), 1); } } }; function getTrajectory(coordx, coordy) { var tempX, tempY, neg = false; if (coordx == 400) { if (coordy <= 540) { direction = degToRad(90); } else { direction = degToRad(270); } } else { direction = Math.atan((540 - coordy)/(coordx - 400)); if (coordx < 400) { neg = true; } } tempX = Math.cos(direction); tempY = Math.sin(direction); if (neg) { tempX = -tempX; tempY = -tempY; neg = false; } return [tempX, tempY]; }; function degToRad(angle) { return angle * (Math.PI/180); }; //end degToRad() function getMousePos(canvas, e) { var rect = canvas.getBoundingClientRect(); return { x: e.clientX - rect.left, y: e.clientY - rect.top }; }; function process() { for (var i = 0; i < shots.length; i++) { shots[i].move(); }; for (var i = 0; i < aliens.length; i++) { aliens[i].move(); }; }; function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); playerTurret.draw(); for (var i = 0; i < shots.length; i++) { shots[i].draw(); }; for (var i = 0; i < aliens.length; i++) { aliens[i].draw(); }; }; //end draw() function loop() { process(); draw(); gloop = setTimeout(loop, 25); }; //end loop() canvas.addEventListener('mousemove', function(e) { var mousePos = getMousePos(canvas, e); x = mousePos.x; y = mousePos.y; }, false); canvas.addEventListener('mousedown', function(e) { var mousePos = getMousePos(canvas, e); var shotX = mousePos.x; var shotY = mousePos.y; shots.push(new shotObject(shotX, shotY)); mouseDown = true; }, false); canvas.addEventListener('mouseup', function(e) { mouseDown = false; }); loop(); </script> </section> </body> </html> 
+4
source share
2 answers

You have several places where you do not call beginPath , and you should be. The one in particular that triggers the extra shot and alien lengthening is in your player turret play function:

 ctx.beginPath(); // THIS LINE FIXES IT ctx.fillStyle = "white"; ctx.strokeStyle = "white"; ctx.rect(380, 540, 40, 60); //draw base ctx.fill(); 

Your rect here is added to the path of the last shot from the previous iteration and fills it. Similarly, the alien path from the previous iteration is filled, forcing the box to closely monitor the alien, making it appear to be stretched in the direction in which it is currently moving (wider when left or right, higher, up or down).

http://jsfiddle.net/W3wKw/

EDIT: This demo I think it illustrates the problem well. This is the exact code from the original question with the colors changed. Red - fill / hit the tower, yellow - fill the aliens, and green - fill.

+4
source

In the draw () of the basicAlien element, add ctx.beginPath ();

 that.draw = function() { ctx.fillStyle = "white"; ctx.beginPath(); ctx.rect(that.pos[0] - 10, that.pos[1] - 5, 20, 10); ctx.fill(); } 
+2
source

Source: https://habr.com/ru/post/1488771/


All Articles