I'm following a tutorial on using vanilla JS/HTML/CSS to create a 2D animation game. I'm currently stuck, however, because some of my "spiders" become stuck in their path, and won't moveāand some of them do so out of the screen such that their webs are visible and won't disappear. I went back to the tutorial's code and tried to find any differences in the code, but couldn't find any. I've been playing around with the vertical values, as well as the part where I deal with animation frames, but couldn't fix the bug.
Could someone please help me figure out what I'm doing wrong?
document.addEventListener('DOMContentLoaded', function() {
const canvas = document.getElementById('canvas1');
const ctx = canvas.getContext('2d');
canvas.width = 500;
canvas.height = 800;
class Game {
constructor(ctx, width, height) {
this.ctx = ctx;
this.width = width;
this.height = height;
this.enemies = [];
this.enemyInterval = 400;
this.enemyTimer = 0;
this.enemyTypes = ["worm", "ghost", "spider"];
}
update(deltaTime) {
this.enemies = this.enemies.filter(object => !object.markedForDeletion);
if (this.enemyTimer > this.enemyInterval) {
this.#addNewEnemy();
this.enemyTimer = 0;
} else {
this.enemyTimer += deltaTime;
}
this.enemies.forEach(object => object.update(deltaTime));
}
draw() {
this.enemies.forEach(object => object.draw(this.ctx));
}
#addNewEnemy() {
const randomEnemy = this.enemyTypes[Math.floor(Math.random() * this.enemyTypes.length)];
if (randomEnemy === "worm") this.enemies.push(new Worm(this));
else if (randomEnemy === "ghost") this.enemies.push(new Ghost(this));
else if (randomEnemy === "spider") this.enemies.push(new Spider(this));
// this.enemies.sort(function(a, b) {
// return a.y - b.y;
// });
}
}
class Enemy {
constructor(game) {
this.game = game;
this.markedForDeletion = false;
this.frameX = 0;
this.maxFrame = 5;
this.frameInterval = 100;
this.frameTimer = 0;
}
update(deltaTime) {
this.x -= this.vx * deltaTime;
if (this.x < 0 - this.width) this.markedForDeletion = true;
if (this.frameTimer > this.frameInterval) {
if (this.frameX < this.maxFrame) this.frameX++;
else this.frameX = 0;
this.frameTimer = 0;
} else {
this.frameTimer += deltaTime;
}
}
draw(ctx) {
ctx.drawImage(this.image, this.frameX * this.spriteWidth, 0, this.spriteWidth, this.spriteHeight, this.x, this.y, this.width, this.height);
}
}
class Spider extends Enemy{
constructor() {
super(game);
this.spriteWidth = 310;
this.spriteHeight = 175;
this.width = this.spriteWidth/2;
this.height = this.spriteHeight/2;
this.x = Math.random() * this.game.width;
this.y = 0 - this.height;
this.image = spider;
this.vx = 0;
this.vy = Math.random() * 0.1 + 0.1;
this.maxLength = Math.random() * this.game.height * 0.7;
}
update(deltaTime) {
super.update(deltaTime);
if (this.y < 0 - this.height * 1.5) this.markedForDeletion = true;
this.y += this.vy * deltaTime;
if (this.y > this.maxLength) this.vy *= -1;
}
draw(ctx) {
ctx.beginPath();
ctx.moveTo(this.x + this.width/2, 0);
ctx.lineTo(this.x + this.width/2, this.y + 10);
ctx.stroke();
super.draw(ctx);
}
}
const game = new Game(ctx, canvas.width, canvas.height);
let lastTime = 1;
function animate(timeStamp) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const deltaTime = timeStamp - lastTime;
lastTime = timeStamp;
game.update(deltaTime);
game.draw();
requestAnimationFrame(animate);
}
animate(0);
})
#canvas1 {
border: 3px solid black;
width: 500px;
height: 800px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
img {
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Enemy Variety</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<canvas id="canvas1"></canvas>
<img src="images/enemy_worm.png" id="worm">
<img src="images/enemy_ghost.png" id="ghost">
<img src="images/enemy_spider.png" id="spider">
<script src="script.js"></script>
</body>
</html>
Apologies for the current snippet not working. I assume it's because I can't find a way to upload the image with the code, but I'm attaching it here for reference: https://www.frankslaboratory.co.uk/downloads/enemy_spider.png (Warning: this image is only to be used for educational purposes)
In the draw() method inside the Spider class, you must call super.draw() before running other code:
draw(ctx) {
super.draw(ctx);
ctx.beginPath();
ctx.moveTo(this.x + this.width/2, 0);
ctx.lineTo(this.x + this.width/2, this.y + 10);
ctx.stroke();
}
Related
When the mouse moves it doesn't point in the mouseX or mouseY direction.
The current method points and rotates at the top right point slightly offset on the canvas.
All the other SO questions didn't work for this specific game.
I would prefer the most straightforward answer and an explanation of how it works.
I need a vanilla javascript answer.
/**
* #type { HTMLCanvasElement }
*/
var scene = document.getElementById("scene");
var ctx = scene.getContext("2d");
var mouseX = 0;
var mouseY = 0;
var prevSceneTranslateXL = 0;
var prevSceneTranslateYL = 0;
var prevSceneTranslateXR = 0;
var prevSceneTranslateYR = 0;
var sceneTranslateX = 0;
var sceneTranslateY = 0;
var friction = 4 / 5;
var keysDown = [];
scene.width = window.innerWidth;
scene.height = window.innerHeight;
var bg = new Image();
bg.src = "./assets/groundBgAlt.png";
class Player {
constructor(x, y, radius, color, borderColor) {
this.x = x;
this.y = y;
this.radius = radius;
this.color = color;
this.borderColor = borderColor;
this.velX = 0;
this.velY = 0;
this.speed = 15;
this.angle = 0;
}
}
class Enemy {
constructor(radius, color, borderColor) {
this.x = Math.random() * scene.width + 25;
this.y = Math.random() * scene.height + 25;
this.radius = radius;
this.color = color;
this.borderColor = borderColor;
this.velX = 0;
this.velY = 0;
this.speed = 15;
this.angle = 0;
}
}
var player1 = new Player(1000, 1000, 25, "#0080ff", "#606060");
var enemies = [];
// for (i = 0; i < 20; i++) {
// enemies.push(new Enemy(50, 50, "#ff0000", "#bb0000"));
// }
function drawPlayer(player) {
ctx.strokeStyle = "#606060";
ctx.lineWidth = 2;
ctx.fillStyle = "#cccccc";
ctx.save();
ctx.beginPath();
ctx.translate(player.x, player.y);
ctx.rotate(player1.angle);
ctx.roundRect(-10, -45, 20, 25, 2);
ctx.fill();
ctx.stroke();
ctx.closePath();
ctx.restore();
ctx.strokeStyle = player.borderColor;
ctx.lineWidth = 2;
ctx.fillStyle = player.color;
ctx.beginPath();
ctx.arc(player.x, player.y, player.radius, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
ctx.closePath();
}
function drawEnemies(enemy) {
ctx.strokeStyle = enemy.borderColor;
ctx.lineWidth = 3;
ctx.fillStyle = enemy.color;
ctx.beginPath();
ctx.rect(enemy.x, enemy.y, enemy.width, enemy.height);
ctx.fill();
ctx.stroke();
ctx.closePath();
}
var gradientBG = ctx.createRadialGradient(1000, 1000, 1000, 1000, 1000, 100);
gradientBG.addColorStop(0.0, "#ffffff");
gradientBG.addColorStop(1.0, "#eeeeee");
function main() {
ctx.clearRect(-250, -250, 2500, 2500);
ctx.fillStyle = gradientBG;
ctx.fillRect(0, 0, 2000, 2000);
if (player1.x < 0) {
sceneTranslateX = prevSceneTranslateXL;
player1.x = 0;
player1.velX = 0;
}
if (player1.x > 2000) {
sceneTranslateX = prevSceneTranslateXR;
player1.x = 2000;
player1.velX = 0;
}
if (player1.y < 0) {
sceneTranslateY = prevSceneTranslateYL;
player1.y = 0;
player1.velY = 0;
}
if (player1.y > 2000) {
sceneTranslateY = prevSceneTranslateYR;
player1.y = 2000;
player1.velY = 0;
}
if (keysDown["w"] || keysDown["ArrowUp"]) {
if (player1.velY > player1.speed * -1) {
player1.velY--;
}
}
if (keysDown["a"] || keysDown["ArrowLeft"]) {
if (player1.velX > player1.speed * -1) {
player1.velX--;
}
}
if (keysDown["s"] || keysDown["ArrowDown"]) {
if (player1.velY < player1.speed) {
player1.velY++;
}
}
if (keysDown["d"] || keysDown["ArrowRight"]) {
if (player1.velX < player1.speed) {
player1.velX++;
}
}
player1.velX *= friction;
player1.velY *= friction;
player1.x += player1.velX;
player1.y += player1.velY;
sceneTranslateX *= friction;
sceneTranslateY *= friction;
sceneTranslateX += -player1.velX;
sceneTranslateY += -player1.velY;
prevSceneTranslateXL = sceneTranslateX - 1;
prevSceneTranslateYL = sceneTranslateY - 1;
prevSceneTranslateXR = sceneTranslateX + 1;
prevSceneTranslateYR = sceneTranslateY + 1;
ctx.translate(sceneTranslateX / 5, sceneTranslateY / 5);
drawPlayer(player1);
// for (i = 0; i < enemies.length; i++) {
// drawEnemies(enemies[i]);
// }
requestAnimationFrame(main);
}
ctx.translate((scene.width / 2) - player1.x, (scene.height / 2) - player1.y);
main();
document.addEventListener("keydown", (e) => {
keysDown[e.key] = true;
});
document.addEventListener("keyup", (e) => {
keysDown[e.key] = false;
});
document.addEventListener("mousemove", (e) => {
var angle = Math.atan2(e.pageY - player1.y, e.pageX - player1.x);
player1.angle = angle;
});
* {
font-family: roboto, Arial, Helvetica, sans-serif, system-ui, system 'Courier New', Courier, monospace;
padding: 0px 0px;
margin: 0px 0px;
box-sizing: border-box;
}
body {
background: radial-gradient(circle, #bbbbbb 10%, #cccccc);
overflow: hidden;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles/styles.css">
<script src="scripts/index.js" defer></script>
<title>Document</title>
</head>
<body>
<canvas id="scene" width="1024" height="576"></canvas>
</body>
</html>
The way the game is made makes it really hard to rotate objects.
I am practicing making games with HTML canvas and JavaScript. I am making a flappy bird clone, and it is almost done. One of my friends wanted to see it but I couldn't figure out how they could play it. I sent them the folder with all the files in it, but it looked like the only problem was that when he tried to play it, he couldn't load the images. How would I go about letting people play the games I make. Was I on the right track, just sending them the folder?
const canvas = document.getElementById("canvas");
const c = canvas.getContext("2d");
const backgroundImage = document.getElementById("image")
const flappyBirdImage = document.getElementById("flappy-bird-image");
const topPipe1Image = document.getElementById("top-pipe-image");
const bottomPipe1Image = document.getElementById("bottom-pipe-image");
const gainAPointSound = document.getElementById("gain-a-point-sound");
const startButtonImage = document.getElementById("start-button-image")
let pause = true;
let scoreSet = 0;
let controlsKeyDown = {up: false, right: false, down: false, left: false};
let dx = 2;
let dy = 2;
let score = 0;
let seconds = 0;
if(pause === false) {
let secondsInterval = setInterval(() => {
seconds ++;
console.log(seconds)
}, 1000)
}
canvas.width = innerWidth;
canvas.height = innerHeight;
class Bird {
constructor(x, y, width, height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
draw() {
c.beginPath();
c.fillStyle = 'blue';
c.strokeStyle = 'lightBlue';
c.drawImage(flappyBirdImage, this.x, this.y, this.width, this.height)
c.fill()
c.stroke();
c.closePath();
}
}
class Pipe {
constructor(x, y, height, width) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
draw() {
c.beginPath();
c.drawImage(bottomPipe1Image, this.x, this.y, this.width, this.height)
c.fill();
}
drawtop() {
c.beginPath();
c.drawImage(topPipe1Image, this.x, this.y, this.width, this.height);
c.closePath()
}
}
class Button {
constructor(x,y,height,width) {
this.x = x;
this.y = y;
this.height = height;
this.width = width;
}
draw() {
c.beginPath();
c.drawImage(startButtonImage, this.x, this.y, this.height, this.width);
c.closePath();
}
}
// Game Objects
const topPipe1 = new Pipe(canvas.width - 300, 0, 300, 200)
const bottomPipe1 = new Pipe(canvas.width - 300, canvas.height - 300, 300, 200)
const topPipe2 = new Pipe(canvas.width + 300, 0, 300, 200);
const bottomPipe2 = new Pipe(canvas.width + 300, canvas.height - 300, 300, 200);
const myBird = new Bird(200, 200, 60, 60)
const startButton = new Button(canvas.width/2 - 300, canvas.height/2 - 75, 400, 150)
console.log(startButton)
// Game Mechanics
function birdControlsKeyDown(Event) {
if(Event.key === 'ArrowUp') {
controlsKeyDown.up = true;
}
if(Event.key === 'ArrowRight') {
controlsKeyDown.right = true;
}
if(Event.key === 'ArrowLeft') {
controlsKeyDown.left = true;
}
if(Event.key === "ArrowDown") {
controlsKeyDown.down = true;
}
}
function birdControlsKeyUp(Event) {
if(Event.key === 'ArrowUp') {
controlsKeyDown.up = false;
}
if(Event.key === 'ArrowRight') {
controlsKeyDown.right = false;
}
if(Event.key === 'ArrowLeft') {
controlsKeyDown.left = false;
}
if(Event.key === 'ArrowDown') {
controlsKeyDown.down = false;
}
}
//Bird With Edge Collision Detection
function birdCollisionDetection() {
// Bird Hits Bottom Of Screen
if(myBird.y + myBird.height >= canvas.height){
myBird.y = canvas.height - 100;
alert("You Lost")
document.location.reload()
}
// Bird Hits Top Of Screen
if(myBird.y <= 0) {
myBird.y += dy;
}
// Bird Hits Left Of Screen
if(myBird.x<= 0) {
myBird.x += dx;
}
// Bird Hits Right Of Screen
if(myBird.x + myBird.height >= canvas.width) {
myBird.x -= dx;
}
// Bird With Pipe Collision Detection
}
function birdWithPipeCollisionDetection(a,b) {
if(a.x + a.width >= b.x && a.x <= b.x + b.width && a.y <= b.y + b.height && a.y + a.height >= b.y){
console.log('test');
document.location.reload()
alert("You Lost")
}
}
function writeScore() {
c.font = '30px Georgia'
c.fillStyle = 'black';
c.fillText(`Score: ${score}`, 30, 30)
}
function writeTime() {
c.font = '30px Georgia';
c.fillStyle = 'black';
c.fillText(`Seconds: ${seconds}`, canvas.width/2 - 100, 30)
}
function writeStats() {
writeScore()
writeTime()
}
function resetPipePositions() {
if(topPipe1.x + topPipe1.width/2 < 0) {
topPipe1.x = canvas.width
topPipe1.height = Math.floor(Math.random() * 200 + 300);
scoreSet++;
}
if(bottomPipe1.x + bottomPipe1.width/2 < 0) {
bottomPipe1.x = canvas.width
bottomPipe1.height = canvas.height - topPipe1.height
}
if(bottomPipe2.x + bottomPipe2.width/2 < 0) {
bottomPipe2.x = canvas.width
bottomPipe2.height = canvas.height - topPipe2.height
}
if(topPipe2.x + topPipe2.width/2 < 0) {
topPipe2.x = canvas.width
topPipe2.height = canvas.height - bottomPipe2.height
}
}
function resetBirdPosition() {
if(myBird.x < 200) {
myBird. x += dx;
}
}
function updateScore() {
if(myBird.x + myBird.width >= bottomPipe1.x && myBird.x <= bottomPipe1.x + bottomPipe1.width && myBird.y + myBird.height <= bottomPipe1.y && myBird.y >= topPipe1.y + topPipe1.height) {
score = (scoreSet + 1)
}
}
function ifPause() {
addEventListener('keypress', (Event) => {
if(Event.key === 'Enter') {
console.log(pause)
pause = false;
} else if(Event.key === ' ') {
console.log(pause)
pause = true
}
console.log(pause)
})
}
function resizeScreen() {
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
}
function startButtonOnClick() {
pause = false;
}
// Game Loop
function draw() {
c.drawImage(backgroundImage, 0,0,canvas.width,canvas.height);
myBird.draw();
topPipe1.drawtop();
bottomPipe1.draw();
topPipe2.drawtop();
bottomPipe2.draw()
startButton.draw()
resetPipePositions();
resetBirdPosition();
updateScore();
ifPause()
writeStats();
// Check If Paused
if(pause === false) {
// Bird Controls
addEventListener('keydown', birdControlsKeyDown)
addEventListener('keyup', birdControlsKeyUp)
if(controlsKeyDown.up) {
setInterval(myBird.y -= dy, 10);
} else {
myBird.y += dy;
}
topPipe1.x -= dx;
bottomPipe1.x -= dx;
topPipe2.x -= dx;
bottomPipe2.x -= dx;
birdCollisionDetection();
birdWithPipeCollisionDetection(myBird, topPipe1);
birdWithPipeCollisionDetection(myBird, bottomPipe1);
birdWithPipeCollisionDetection(myBird, bottomPipe2);
birdWithPipeCollisionDetection(myBird, topPipe2);
}
requestAnimationFrame(draw)
}
draw()
html {
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
}
canvas {
overflow: hidden;
}
image {
background: transparent;
}
#start-button {
z-index: 100
}
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="icon" type="image/png" href="./Flappy Bird Pictures and Animations/Flappy Bird Icon.png" type="icon" height="100px" width="75px">
<script src="Flappy Bird.js" defer></script>
<link rel="stylesheet" href="Flappy Bird.css">
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Flappy Bird</title>
</head>
<body>
<canvas id="canvas"></canvas>
<img src="./Flappy Bird Pictures and Animations/background image.png" id="image">
<img src="./Flappy Bird Pictures and Animations/The Flappy Bird.png" id="flappy-bird-image">
<img src="./Flappy Bird Pictures and Animations/Bottom Pipe.png" id="bottom-pipe-image">
<img src="./Flappy Bird Pictures and Animations/Top Pipe.png" id="top-pipe-image">
<audio src="D:/Coding/2d Games/Flappy Bird/Audio" id="gain-a-point-sound"></audio>
<img src="./Flappy Bird Pictures and Animations/Start Button_files/Start-button-sprite.png" id="start-button-image">
</body>
</html>
Well, the simplest solution is to put the game online :). Services like Netlify allow you to do this in no time and for free. To get started, you can literally drag and drop the files to Netlify. Netlify creates a public link* of the form somename.netlify.app for you which you can then share with your friends.
When uploading your files make sure that there is no absolute path since this will not work on other machines let alone the internet. In your source code, "D:/Coding/2d Games/Flappy Bird/Audio" is an example of an absolute path. You need to use relative paths instead. As for your images, you need to make sure that your project folder has a directory "/Flappy Bird Pictures and Animations" and that this gets uploaded to Netlify (or other services) as well.
*You can also edit the link in case it is not taken already.
I'm trying to make a very simple interactive segment for a webpage, and I need to render many small circles that bounce around the screen... However I am running into a very strange issue. When I render a small circle (with a radius of ~10 or less) it renders with a chunk taken out of the upper right corner for no apparent reason. If I increase the size of the circle then it begins to render properly.
Here is all of my code so far:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Nothing</title>
<style>
#header{
background: red;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 25%;
text-align: center;
}
#header h1{
position: relative;
top: 8%;
font-size: 200%;
}
#header canvas{
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<div id = "header">
<canvas></canvas>
<h1>(Removed for privacy)</h1>
</div>
<script>
let canvas = document.getElementById("header").getElementsByTagName("canvas")[0];
canvas.width = Math.round(window.innerWidth);
canvas.height = Math.round(window.innerHeight * 0.25);
let ctx = canvas.getContext("2d");
let width = canvas.width;
let height = canvas.height;
function d2r(degrees){
return(degrees * (Math.PI / 180));
}
function random(min,max){
const diff = (max - min) + 1;
return(Math.floor(Math.random() * diff) + min);
}
</script>
<script>
class Bubble{
constructor(x,y){
this.x = x;
this.y = y;
this.r = random(0,d2r(360));
this.speed = 0.6;
this.xvel = Math.cos(this.r) * this.speed;
this.yvel = Math.sin(this.r) * this.speed;
this.size = 10;
}
draw(){
ctx.beginPath();
ctx.fillStyle = "black";
ctx.arc(this.x,this.y,this.size / 2,this.size / 2,0,d2r(360));
ctx.fill();
}
update(){
this.x += this.xvel;
this.y += this.yvel;
if(this.x < this.size / 2){
this.x = this.size / 2;
this.xvel = -this.xvel;
}
if(this.x > width - this.size / 2){
this.x = width - this.size / 2;
this.xvel = -this.xvel;
}
if(this.y < this.size / 2){
this.y = this.size / 2;
this.yvel = -this.yvel;
}
if(this.y > height - this.size / 2){
this.y = height - this.size / 2;
this.yvel = -this.yvel;
}
}
}
let bubbles = [];
for(let i = 0;i < 50;i++){
bubbles.push(new Bubble(random(4,width - 4),random(4,height - 4)));
}
</script>
<script>
let drawLoop = setInterval(function(){
ctx.fillStyle = "rgb(84, 48, 23)";
ctx.fillRect(0,0,width,height);
for(let i = 0;i < bubbles.length;i++){
bubbles[i].update();
bubbles[i].draw();
}
},1000 / 60);
</script>
</body>
</html>
You can change the this.size = 10; to different sizes to see how it looks, and when the problem comes and goes. When I set it to something tiny (like 5) it renders as almost a line.... It's very very strange.
Any help is appreciated. I assume I'm going to have to use some kind of workaround to get this working the way I want.
Edit: The code in question is in the Bubble class, inside the draw method.
Parameters for 2dArc is
void ctx.arc(x, y, radius, startAngle, endAngle [, anticlockwise]);
Inside your class member draw() you gave,
ctx.arc(this.x,this.y,this.size / 2,this.size / 2,0,d2r(360));
Among which the second this.size / 2 is not required,
removing that will fix it,
ctx.arc(this.x,this.y,this.size / 2,0,d2r(360));
Im trying to create a canvas animation of starfield. It has a fixed speed value so stars moving in same speeds but now I want to start it with stars not moving and when you click a button i want to start it slowly and then gradually increase the speed and then again slow down and stop. How do I achieve this?
Speeds should be like this example
https://www.shadertoy.com/view/Xdl3D2
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<canvas id="c" width="900px" height="700px"></canvas>
<script type="text/javascript">
const canvas = document.getElementById('c');
const c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
window.addEventListener('wheel', (event) => {
if (event.deltaY < 0) speed *= 1.1;
else speed *= 0.9;
if (speed < 0.01) speed = 0.01;
else if (speed > 0.1) speed = 0.1;
});
class Star {
constructor() {
this.x = Math.random()*canvas.width-canvas.width/2;
this.y = Math.random()*canvas.height-canvas.height/2;
this.px, this.py;
this.z = Math.random()*4;
}
update() {
this.px = this.x;
this.py = this.y;
this.z += speed;
this.x += this.x*(speed*0.2)*this.z;
this.y += this.y*(speed*0.2)*this.z;
if (this.x > canvas.width/2+50 || this.x < -canvas.width/2-50 ||
this.y > canvas.height/2+50 || this.y < -canvas.height/2-50) {
this.x = Math.random()*canvas.width-canvas.width/2;
this.y = Math.random()*canvas.height-canvas.height/2;
this.px = this.x;
this.py = this.y;
this.z = 0;
}
}
show() {
c.lineWidth = this.z;
c.beginPath();
c.moveTo(this.x, this.y);
c.lineTo(this.px, this.py);
c.stroke();
}
}
let speed = 0.09;
let stars = [];
for (let i = 0; i < 1000; i++) stars.push(new Star());
c.fillStyle = 'rgba(0, 0, 0, 0.4)';
c.strokeStyle = 'rgb(255, 255, 255, 0.5)';
c.translate(canvas.width/2, canvas.height/2);
function draw() {
requestAnimationFrame(draw);
c.fillRect(-canvas.width/2, -canvas.height/2, canvas.width, canvas.height);
for (let s of stars) {
s.update();
s.show();
}
}
draw();
</script>
<style type="text/css">
body {
padding: 0;
margin: 0;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</body>
</html>
You have to increase the speed in the function draw to create a speeding up effect, and decrease to slowdown.
const canvas = document.getElementById('c');
const c = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
class Star {
constructor() {
this.x = Math.random() * canvas.width - canvas.width / 2;
this.y = Math.random() * canvas.height - canvas.height / 2;
this.px, this.py;
this.z = Math.random() * 4;
}
update() {
this.px = this.x;
this.py = this.y;
this.z += speed;
this.x += this.x * (speed * 0.2) * this.z;
this.y += this.y * (speed * 0.2) * this.z;
if (this.x > canvas.width / 2 + 50 || this.x < -canvas.width / 2 - 50 ||
this.y > canvas.height / 2 + 50 || this.y < -canvas.height / 2 - 50) {
this.x = Math.random() * canvas.width - canvas.width / 2;
this.y = Math.random() * canvas.height - canvas.height / 2;
this.px = this.x;
this.py = this.y;
this.z = 0;
}
}
show() {
c.lineWidth = this.z;
c.beginPath();
c.moveTo(this.x, this.y);
c.lineTo(this.px, this.py);
c.stroke();
}
}
let speed = 0.005;
let speed_inc = 0.0002;
let stars = [];
for (let i = 0; i < 1000; i++) stars.push(new Star());
c.fillStyle = 'rgba(0, 0, 0, 0.4)';
c.strokeStyle = 'rgb(255, 255, 255, 1)';
c.translate(canvas.width / 2, canvas.height / 2);
function draw() {
requestAnimationFrame(draw);
c.fillRect(-canvas.width / 2, -canvas.height / 2, canvas.width, canvas.height);
for (let s of stars) {
s.update();
s.show();
}
if (speed >= 0.005) {
speed += speed_inc
if (speed > 0.1)
speed_inc = -0.0004;
}
}
draw();
body {
padding: 0;
margin: 0;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
<canvas id="c" width="900px" height="700px"></canvas>
I've created a script for a bouncing ball, and I wanted to try to add another ball to make it more interesting. But the code doesn't seem to work and add another ball as I'm trying to do. I want to use the same function to do that because its more compact and flexible.
function startGame() {
GameArea.start();
Ball = new CircComp('red' , window.innerWidth/ 2 , window.innerHeight / 2.5 );
Ball.yAngle = 10;
Ball.xAngle = 10;
Ball.radius = 20;
Ball1 = new CircComp('green' , window.innerWidth/ 2 , window.innerHeight / 2.5 );
Ball1.yAngle = -10;
Ball1.xAngle = -10;
Ball1.radius = 20;
}
var GameArea = {
canvas : canvas = document.querySelector("canvas"),
start : function (){
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
this.ctx = this.canvas.getContext('2d');
this.interval = setInterval(updateGameArea, 20);
},
clear : function() {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
}
}
function CircComp(color, x , y){
this.x = x;
this.y = y;
context = GameArea.ctx;
this.update = function(){
context.beginPath();
context.fillStyle = color;
context.arc(this.x,this.y,this.radius,0,2*Math.PI);
context.fill();
context.stroke();
}
this.updateGameComp = function(){
GameArea.clear();
this.y += this.yAngle;
this.x += this.xAngle;
if(this.x + this.radius > GameArea.canvas.width){
this.xAngle = -1 * this.xAngle;
}
if(this.y + this.radius > GameArea.canvas.height){
this.yAngle = -1 * this.yAngle;;
}
if(this.x - this.radius < 0){
this.xAngle = -1 * this.xAngle;
}
if(this.y - this.radius < 0){
this.yAngle = -1 * this.yAngle;
}
this.update();
}
}
function updateGameArea(){
Ball.updateGameComp();
Ball1.updateGameComp();
}
<html>
<head>
<meta charset='urf-8'>
<style>
canvas{
border: 0px solid black;
}
body{
margin: 0;
overflow: hidden;
}
</style>
</head>
<body onload='startGame()'>
<canvas></canvas>
<script src='Pong.js'></script>
</body>
</html>
Both CircComp objects call GameArea.clear() in updateGameComp. You should only clear the canvas once, before drawing anything, probably in updateGameArea.