I am trying to make a sonic 2d platformer. However I am struggling with making my sonic entity collide with my platform. Right now my sonic is falling through the platform as if my collisionCheck() method does not work at all.
Here is my sonic.js:
class Sonic {
constructor(game) {
this.game = game;
this.game.sonic = this; // special entity
this.position = {
x: 0,
y: 0
}
this.velocity = {
x: 0, //increase as to the right ->
y: 0 // increase as downwards
}
this.speed = 1300;
this.jumpSpeed = 200;
this.spinSpeed = 1400;
this.spritesheet = ASSET_MANAGER.getAsset("./sprites/realSonicSheet.png");
this.updateBB();
this.animations = [];
this.state = 0;
this.direction = 0;
this.loadAnimations();
this.ground = 550;
this.onGround = false;
this.BB = null;
this.lastBB = null;
}
loadAnimations() {
for (var i = 0; i < 4; i++) { // four states (idle, running, jumping and spinning)
this.animations.push([]);
for (var k = 0; k < 2; k++) { // two directions (right or left)
this.animations[i].push([]);
}
}
// idle animation for state = 0
// facing right = 0
this.animations[0][0] = new Animator(this.spritesheet, 5, 723, 45, 45, 1, 0.33, 0, false, true);
// facing left = 1
this.animations[0][1] = new Animator(this.spritesheet, 741, 38, -41, 47, 1, 0.33, 0, true, true); // change to true true if issues
// run animation
// facing right
this.animations[1][0]= new Animator(this.spritesheet, 2, 916, 49, 45, 14, 0.08, 0, false, true);
// facing left
this.animations[1][1] = new Animator(this.spritesheet, 745, 230, -49, 47, 14, 0.08, 0, false, true);
// jump animation
// facing right
this.animations[2][0] = new Animator(this.spritesheet, 340, 1160, 47, 56, 8, 0.08, 0, false, true);
// facing left
this.animations[2][1] = new Animator(this.spritesheet, 410, 480, -47, 56, 8, 0.08, 0, false, true);
// spinning animation
// facing right
this.animations[3][0] = new Animator(this.spritesheet, 1, 1113, 47, 40, 10, 0.08, 0, false, true);
// facing left
this.animations[3][1] = new Animator(this.spritesheet, 746, 427, -47, 40, 10, 0.08, 0, false, true);
}
updateBB() {
this.BB = new BoundingBox(this.position.x, this.position.y, 155, 130, "red");
this.lastBB = new BoundingBox(this.BB.x, this.BB.y, this.BB.width, this.BB.height, this.BB.color);
console.log("This is this.BB", this.BB);
}
update() {
const GRAVITY = 0.5;
this.updateBB();
let standingOnPlatform = false;
let canvasHeight = 768;
// Move left
if (this.game.left) {
console.log(this.game.left);
this.position.x -= this.speed * this.game.clockTick;
this.direction = 1;
this.state = 1;
console.log(this.position.x);
}
// Move right and spinning left
if (this.game.spin && this.game.left) {
this.position.x -= this.spinSpeed * this.game.clockTick;
this.state = 3;
}
// Move right
if (this.game.right) {
console.log(this.game.right);
this.position.x += this.speed * this.game.clockTick;
this.direction = 0;
this.state = 1
console.log(this.position.x)
}
// Jump
if (this.game.jump) {
console.log(this.game.jump)
this.position.y -= 20;
this.state = 2;
this.direction = 0;
}
this.velocity.y += GRAVITY; // Gravity to pull sonic down after jumping
this.position.y += this.velocity.y;
// Spin
if (this.game.spin) {
console.log(this.game.spin)
this.position.x += this.spinSpeed * this.game.clockTick;
this.position.y += 10;
this.state = 3;
}
// Set state back to idle if no actions are being performed
if (!this.game.left && !this.game.right && !this.game.jump && !this.game.spin) {
this.state = 0;
}
// If Sonic is not standing on a platform, check if he has fallen off the screen
if (!standingOnPlatform) {
this.velocity.y += GRAVITY;
this.position.y += this.velocity.y;
// // Check if Sonic has fallen off the screen
// if (this.position.y > canvasHeight) {
// // Reload the game
// window.location.reload();
// this.position.y = 300; // start at y position 300
// }
}
// Update the bounding box for Sonic's new position
this.updateBB();
this.collisionCheck();
}
collisionCheck() {
this.game.entities.forEach(entity => {
if (this !== entity && entity.BB && this.BB.collide(entity.BB)) {
if (entity instanceof Platform) {
if (this.velocity.y > 0 && this.lastBB.bottom <= entity.BB.top) {
this.position.y = entity.BB.top - this.BB.height;
this.velocity.y = 0;
this.onGround = true;
return;
}
if (this.velocity.y < 0 && this.lastBB.top >= entity.BB.bottom) {
this.position.y = entity.BB.bottom;
this.velocity.y = 0;
return;
}
if (this.velocity.x > 0 && this.lastBB.right <= entity.BB.left) {
this.position.x = entity.BB.left - this.BB.width;
this.velocity.x = 0;
return;
}
if (this.velocity.x < 0 && this.lastBB.left >= entity.BB.right) {
this.position.x = entity.BB.right;
this.velocity.x = 0;
return;
}
}
}
});
}
draw(ctx) {
if(this.state < 0 || this.state > 3) this.state = 0;
let done = this.animations[this.state][this.direction].drawFrame(this.game.clockTick, ctx, this.position.x - this.game.camera.x , this.position.y);
if (done) {
this.animations[this.state][this.direction].elapsedTime = 0;
this.state = 0;
}
if (PARAMS.DEBUG) {
this.game.ctx.strokeStyle = "red";
this.game.ctx.strokeRect(this.BB.x - this.game.camera.x, this.BB.y, this.BB.width, this.BB.height);
}
}
}
Here is my platform.js
class Platform {
constructor(game, x, y, width, height) {
this.game = game;
this.position = {
x: x,
y: y
};
this.width = width;
this.height = height;
this.boundingBox = {
x: this.position.x,
y: this.position.y,
width: this.width,
height: this.height
};
this.spritesheet = ASSET_MANAGER.getAsset("./sprites/floor.png");
}
updateBB() {
this.boundingBox.x = this.position.x;
this.boundingBox.y = this.position.y;
}
update() {
this.updateBB();
}
draw(ctx) {
ctx.drawImage(this.spritesheet, this.position.x - this.game.camera.x, this.position.y, this.width, this.height);
if (PARAMS.DEBUG) {
ctx.strokeStyle = "lime";
ctx.strokeRect(
this.boundingBox.x - this.game.camera.x,
this.boundingBox.y,
this.boundingBox.width,
this.boundingBox.height
);
}
}
}
I have tried debugging my collisionCheck method (line 142 of sonic.js)and seeing if my bounding boxes are drawn correctly around my sonic and platforms and they are drawn correctly.
Related
i am trying to make my bullet travel towards the cursor location. I have tried lots of things and I just can't get it to work. I have the player arm set up to always move to the player shoulder level. The player's arm and the gun has the same rotation value. The rotation value is calculated using Phaser.Math.Angle.BetweenPoints(playerArm, player1Aim);. I found a couple examples but i couldn't get them to work. Please teach me how to use it. I am a newbie. Please help. Here is my code:
var config = {
type: Phaser.AUTO,
width: 512,
height: 512,
physics: {
default: 'arcade',
arcade: {
gravity: {
y: 1500
},
debug: false
}
},
scene: {
preload: preload,
create: create,
update: update
}
// plugins: {
// global: [{
// key: 'PhaserPauseRenderPlugin',
// plugin: PhaserPauseRenderPlugin,
// mapping: 'render'
// }]
// }
};
// class SceneMain extends Phaser.Scene {
// constructor() {
// super('SceneMain');
// }
// preload() {}
// create() {
// //make 3 bars
// let healthBar = this.makeBar(140, 100, 0x2ecc71);
// this.setValue(healthBar, 100);
// // let powerBar = this.makeBar(140, 200, 0xe74c3c);
// // this.setValue(powerBar, 50);
// // let magicBar = this.makeBar(140, 300, 0x2980b9);
// // this.setValue(magicBar, 33);
// }
// makeBar(x, y, color) {
// //draw the bar
// let bar = this.add.graphics();
// //color the bar
// bar.fillStyle(color, 1);
// //fill the bar with a rectangle
// bar.fillRect(0, 0, 200, 50);
// //position the bar
// bar.x = x;
// bar.y = y;
// //return the bar
// return bar;
// }
// setValue(bar, percentage) {
// //scale the bar
// bar.scaleX = percentage / 100;
// }
// update() {}
// }
var player;
var platforms;
var cursors;
var gameOver = false;
var score = 0;
var time;
var waves;
var enemies;
var enemy;
var health;
var hacking = false;
var timer;
var enemyCount = 0;
var startGame = false;
var timeSpeed = 1;
var keys;
var damageStrike = 0;
var toMouse = 0;
var toPlayer = 0;
var bullets;
var ship;
var speed;
var stats;
var cursors;
var lastFired = 0;
var fire = false;
var pointerDown = false;
// var healthBar = new SceneMain();
// spaceBar input
// var spaceBar = Phaser.Input.Keyboard.KeyCodes.SPACE;
var game = new Phaser.Game(config);
function preload() {
//this.load.image('platform', 'images/platform.png');
// this.load.image('background', 'images/background.png');z
this.load.image('background', 'images/background.png');
this.load.image('platform', 'images/platform.png');
this.load.image('longPlatform', 'images/platform long.png');
this.load.image('itembg', 'images/item bg.png');
this.load.image('playerArm', 'images/player arm.png');
this.load.image('enemyArm', 'images/enemy arm.png');
this.load.image('playerGun', 'images/player gun.png');
this.load.image('enemyGun', 'images/enemy gun.png');
this.load.image('medkit', 'images/medkit.png');
this.load.image('aim', 'images/aim.png');
this.load.image('bullet', 'images/laser.png');
this.load.spritesheet('player', 'images/player idle-1.png', {
frameWidth: 49,
frameHeight: 128
});
this.load.spritesheet('enemy', 'images/enemy.png', {
frameWidth: 49,
frameHeight: 128
});
}
function create() {
// var Bullet = new Phaser.Class({
// Extends: Phaser.GameObjects.Image,
// initialize:
// // Bullet Constructor
// function Bullet(scene) {
// Phaser.GameObjects.Image.call(this, scene, 0, 0, 'bullet');
// this.speed = 1;
// this.born = 0;
// this.direction = 0;
// this.xSpeed = 0;
// this.ySpeed = 0;
// this.setSize(12, 12, true);
// },
// // Fires a bullet from the player to the reticle
// fire: function(player, target) {
// this.setPosition(player.x, player.y); // Initial position
// this.direction = Math.atan((target.x - this.x) / (target.y - this.y));
// // Calculate X and y velocity of bullet to moves it from shooter to target
// if (target.y >= this.y) {
// this.xSpeed = this.speed * Math.sin(this.direction);
// this.ySpeed = this.speed * Math.cos(this.direction);
// } else {
// this.xSpeed = -this.speed * Math.sin(this.direction);
// this.ySpeed = -this.speed * Math.cos(this.direction);
// }
// this.rotation = player.rotation; // angle bullet with shooters rotation
// this.born = 0; // Time since new bullet spawned
// },
// // Updates the position of the bullet each cycle
// update: function(time, delta) {
// this.x += this.xSpeed * delta;
// this.y += this.ySpeed * delta;
// this.born += delta;
// if (this.born > 500) {
// this.setActive(false);
// this.setVisible(false);
// }
// }
// });
// playerBullets = this.physics.add.group({
// classType: Bullet,
// runChildUpdate: true
// });
speed = Phaser.Math.GetSpeed(300, 1);
// healthBar.makeBar(32, 32, 0xffffff);
// console.log(timer);
// add background
// this.add.image(256, 256, 'background');
background = this.add.image(256, 256, 'background');
background.alpha = 0.8;
itemBg = this.add.image(256, 520, 'itembg')
platforms = this.physics.add.staticGroup();
// Here we create the ground.
platforms.create(256, 450, 'longPlatform').refreshBody();;
// platforms.create(256, 450, 'platform');
platforms.create(50, 175, 'platform');
platforms.create(460, 175, 'platform');
platforms.create(50, 350, 'platform');
platforms.create(460, 350, 'platform');
platforms.create(265, 250, 'platform');
player = this.physics.add.sprite(256, 10, 'player');
player.setScale(0.5);
player.setBounce(0.1);
player.setCollideWorldBounds(true);
playerArm = this.add.image(256, 256, 'playerArm');
playerArm.setScale(0.5);
playerArm.angle = 0;
playerGun = this.add.image(256, 256, 'playerGun');
playerGun.setScale(0.5);
playerGun.angle = 0;
enemyArm = this.add.image(256, 256, 'enemyArm');
enemyArm.setScale(0.5);
enemyArm.angle = 0;
enemyGun = this.add.image(256, 256, 'enemyGun');
enemyGun.setScale(0.5);
enemyGun.angle = 0;
player1Aim = this.add.image(256, 256, 'aim');
player1Aim.setScale(2);
player1Aim.angle = 0;
bullet = this.add.image(256, 10, 'bullet');
bullet.setScale(0.25);
bullet.angle = 0;
var playerX = player.x;
var playerY = player.y;
enemies = this.physics.add.group();
medkits = this.physics.add.group();
spawn = (x, enemyName) => {
enemyPlayer = this.physics.add.sprite(x, 20, enemyName);
// enemyPlayer = this.physics.add.sprite.destroy(true);
console.log(enemyPlayer);
enemyPlayer.setScale(0.5);
enemyPlayer.setBounce(0.1);
enemyPlayer.setCollideWorldBounds(true);
enemyPlayer.allowGravity = true;
return enemyPlayer;
}
spawnMedkit = (x, enemyName) => {
enemyPlayer = this.physics.add.sprite(x, 20, enemyName);
// enemyPlayer = this.physics.add.sprite.destroy(true);
console.log(enemyPlayer);
enemyPlayer.setScale(1);
enemyPlayer.setBounce(0.1);
enemyPlayer.setCollideWorldBounds(true);
enemyPlayer.allowGravity = true;
return enemyPlayer;
}
enemy = spawn(450, 'enemy');
medkit = spawnMedkit(100, 'medkit');
enemyCount += 1;
console.log(enemyCount);
// enemy = enemies.create(450, 20, 'enemy')
// // enemies.create(250, 20, 'enemy')
// enemy.setScale(0.5)
// enemy.setBounce(0.1);
// enemy.setCollideWorldBounds(true);
// enemy.allowGravity = true;
cursors = this.input.keyboard.createCursorKeys();
this.physics.add.collider(player, platforms);
this.physics.add.collider(enemy, platforms);
this.physics.add.collider(medkit, platforms);
// this.physics.add.collider(bombs, platforms);
health = 100;
waves = 0;
// timer = this.time.create(false);
// The score
scoreText = this.add.text(16, 16, 'score: 0', {
fontSize: '25px',
fill: '#00FFFF'
});
// FPS
fps = this.add.text(16, 50, game.loop.actualFps, {
fontSize: '15px',
fill: '#00FFFF'
});
timeScale = this.add.text(16, 70, this.physics.world.timeScale, {
fontSize: '15px',
fill: '#00FFFF'
});
gunRotation = this.add.text(16, 100, 'gun rotation: 0', {
fontSize: '15px',
fill: '#00FFFF'
});
// gameStatus = this.add.text(16, 60, 'Game Status: Alive', {
// fontSize: '25px',
// fill: '#00FFFF'
// });
// hp = this.add.text(16, 100, 'Health: ' + health, {
// fontSize: '25px',
// fill: '#00FFFF'
// });
// add collisions
this.physics.add.collider(player, enemy, damage, null, this);
this.physics.add.collider(player, medkit, healByMedkit, null, this);
// this.physics.add.collider(laser, enemy, hit, null, this);
keys = this.input.keyboard.addKeys('W,A,S,D,F,J,K,L,SPACE');
var r1 = this.add.rectangle(playerX, playerY - 15, 200, 69, 10, 0x6666ff);
this.input.on('pointermove', function(pointer) {
toMouse = Phaser.Math.Angle.BetweenPoints(playerArm, player1Aim);
});
this.input.on('pointerdown', function(pointer) {
// shoot the bullet towards the cursor (player1Aim)
});
startGame = true;
}
function update(time, delta) {
var playerX = player.x;
var playerY = player.y;
var enemyX = enemy.x;
var enemyY = enemy.y;
var playerArmX = playerArm.x;
var playerArmY = playerArm.y;
var playerArmRotation = playerArm.angle;
var mouseX = game.input.mousePointer.x;
var mouseY = game.input.mousePointer.y;
// var theta =
// console.log(playerArmRotation);
// position the arm to the shoulder level of the player
playerArm.x = playerX;
playerArm.y = playerY - 5;
playerGun.x = playerX;
playerGun.y = playerY - 3;
enemyArm.x = enemyX;
enemyArm.y = enemyY - 5;
enemyGun.x = enemyX;
enemyGun.y = enemyY - 5;
player1Aim.x = mouseX;
player1Aim.y = mouseY;
toPlayer = Phaser.Math.Angle.BetweenPoints(enemy, player);
playerArm.rotation = Phaser.Math.Angle.BetweenPoints(playerArm, player1Aim);
playerGun.rotation = Phaser.Math.Angle.BetweenPoints(playerArm, player1Aim);
enemyArm.rotation = toPlayer;
enemyGun.rotation = toPlayer;
// rotate gun for player
if (playerGun.angle >= 90 || playerGun.angle <= -90) {
playerGun.flipY = true;
// console.log('flipped')
} else {
playerGun.flipY = false;
}
// rotate gun for player
if (enemyGun.angle >= 90 || enemyGun.angle <= -90) {
enemyGun.flipY = true;
// console.log('flipped')
} else {
enemyGun.flipY = false;
}
// this.input.on('pointerdown', function(pointer) {
// if (pointerDown == false) {
// pointerDown = true;
// fire();
// console.log('FIRE');
// } else {
// pointerDown = false;
// }
// });
// this.input.on('pointerdown', function(pointer, time, lastFired) {
// if (player.active === false)
// return;
// // Get bullet from bullets group
// var bullet = playerBullets.get().setActive(true).setVisible(true);
// if (bullet) {
// bullet.fire(playerGun, player1Aim);
// // this.physics.add.collider(enemy, bullet, enemyHitCallback);
// }
// }, this);
// this.input.on('pointerdown', function(pointer) {
// if (time > lastFired) {
// var bullet = bullets.get();
// console.log('test2');
// if (bullet) {
// // bullet.rotation = playerGun.rotation;
// bullet.fire(playerGun.x, playerGun.y);
// lastFired = time + 50;
// }
// }
// });
if (startGame == true) {
if (keys.J.isDown) {
this.physics.world.timeScale = 1.75;
// console.log(this.physics.world.timeScale);
// timeSpeed = 0.5;
// console.log(timeSpeed);
} else
if (keys.K.isDown) {
this.physics.world.timeScale = 0.75;
// timeSpeed = 1;
}
if (keys.L.isDown) {
}
if (gameOver) {
return;
gameStatus.setText('Game Status: Dead')
}
if (cursors.left.isDown || keys.A.isDown) {
player.setVelocityX(-160 * timeSpeed);
} else if (cursors.right.isDown || keys.D.isDown) {
player.setVelocityX(160 * timeSpeed);
} else {
player.setVelocityX(0 * timeSpeed);
}
if (cursors.up.isDown && player.body.touching.down) {
player.setVelocityY(-650 * timeSpeed);
}
if (keys.W.isDown && player.body.touching.down) {
player.setVelocityY(-650 * timeSpeed);
}
if (keys.SPACE.isDown && player.body.touching.down) {
player.setVelocityY(-650 * timeSpeed);
}
if (waves == 0) {
waves += 1;
console.log(waves)
}
fps.setText('fps: ' + game.loop.actualFps);
scoreText.setText('Score: ' + score);
timeScale.setText('timeScale: ' + this.physics.world.timeScale);
gunRotation.setText('gun rotation: ' + playerGun.angle);
}
}
function damage(player, enemy) {
enemy.disableBody(true, true);
// enemy.body.enable = false;
// enemy.body.gameObject.active = false;
enemyCount -= 1;
console.log(enemyCount);
health -= 10;
score -= 10;
damageStrike += 1;
if (enemyCount === 0) {
var randomX = Phaser.Math.FloatBetween(0, 500);
enemy.enableBody(true, randomX, 15, true, true);
enemyCount += 1;
console.log(enemyCount);
}
if (damageStrike === 3 && medkits.countActive(false) == 0) {
var randomX = Phaser.Math.FloatBetween(0, 500);
medkit.enableBody(true, randomX, 15, true, true);
damageStrike = 0;
}
console.log('Health: ' + health);
if (health <= 0) {
gameOver = true;
}
}
function hit(laser, enemy) {
score += 10;
enemy.disableBody(true, true);
}
function healByMedkit(player, medkit) {
score += 5;
health += 15;
console.log(health);
medkit.disableBody(true, true);
}
Well if you want to rotate a gameObjects and shoot something in a specific angle, in Phaser you should have to keep somethings in mind:
Origin of the gameObject (since the rotation occurs around this point)
The direction / angle offset of the gameObject you want to rotate
Apart from that, everything is more or less straightforward, calculate the vector for "shooting" a bullet and set the velocity of that bullet.
Here a short demo:
In this Demo, the both main factors are shown, origin and "angle-offset".
(It should cover the basic from your code)
document.body.style = 'margin:0;';
var config = {
type: Phaser.AUTO,
width: 536,
height: 183,
physics: {
default: 'arcade',
arcade: {
gravity:{ y: 50 },
}
},
scene: {
create,
update
},
banner: false
};
function create () {
this.add.text(10, 10, 'Click to shoot bullets')
.setOrigin(0);
// head
this.add.circle ( 42, 60, 8, 0xffffff)
.setOrigin(0);
// body
let player = this.add.rectangle( 40, 80, 20, 50, 0xffffff)
.setOrigin(0);
// sholder
this.add.circle ( 50, 90, 5, 0xff0000)
.setOrigin(0.5);
// arm
let playerArm = this.add.rectangle( 50, 90, 10, 30, 0xff0000)
// Point #1: the Point of rotation is more or less the shoulder
.setOrigin(.5, 0)
.setDepth(10);
// create bullet Group
this.bullets = this.add.group();
this.input.on('pointermove', pointer => {
let rotation = Phaser.Math.Angle.BetweenPoints(playerArm, pointer);
// Point #2: Angle-Offset since the 0 Degrees is on the right,
// and the arm is pointing down I need to subtract 90° 0 PI/2
playerArm.rotation = rotation - Math.PI / 2;
});
this.input.on('pointerdown', pointer => {
let speed = 300;
// create bullet
let bullet = this.add.circle( playerArm.x, playerArm.y, 4, 0xffff00)
.setDepth(9);
this.physics.add.existing(bullet);
// get Vector where to shoot bullet
let vector = new Phaser.Math.Vector2( pointer.x - playerArm.x, pointer.y - playerArm.y );
// set Speed of bullet
vector.setLength(speed);
// DEMO: to shoot in a straightline, just comment the following line in
// bullet.body.setAllowGravity(false);
// DEMO: QuickFix to destroy the bullet after 1 Second automatically
// setTimeout( () => bullet.destroy(), 1000);
// add bullet to group
this.bullets.add(bullet);
bullet.body.setVelocity(vector.x, vector.y);
});
}
function update(){
this.bullets.getChildren().forEach(bullet => {
if(bullet.x > config.width){
bullet.destroy();
}
})
}
new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>
If you want the bullet to fly without gravity / in a straight line, just add this line bullet.body.setAllowGravity(false); after the creation of the bullet, to turn off the physics effect for the bullet.
When I was writing the code I saw that the code would not reset the canvas to (400, 400) after being changed to (600, 600). It would disorientate the canvas and stretch all the shapes with it in evaporation(). When going through all the screens and trying to go back to reset back.
//Variables
let screen = 0;
let bugs = [];
let amt = 1000;
let xpos=0;
function setup() {
colorMode(HSB);
//Changes Colormode to HSB(Hue-Saturation-Brightness)
//Creates the particles for the evaporation screen
//For loop with increasement that states more of the smoke is created
for (let i = 0; i < amt; i++) {
let x = 200;
let y = 300;
let rad = random(10, 50);
let b = new Bug(x, y, rad);
bugs[i] = b;
}
}
//Says if the value of screen changes so does the screen
function draw() {
if(screen == 0) {
evaporationscreen();
} else if(screen == 1) {
condensation();
} else if(screen == 2) {
presipitation();
}
}
//Evaporation
function evaporationscreen() {
background('#d2b48c');
createCanvas(400, 400);
//NOT RGB, HSB COLOR PALLETE(DO NOT MIX UP);
//HTML Color pallete('e928320');
noStroke();
fill('#3895d3') //Lake
circle(400, 400, 600)
fill('#18bdf0') //Sky
rect(0, 0, 400, 200);
fill('#ffff00'); //Sun
circle(300, 60, 70);
fill('#e9bd15'); //Darkspots on Sun
circle(315, 75, 10);//Forms the Sun and Darkspots
circle(280, 52, 8);//Forms the Sun and Darkspots
circle(299, 60, 13);//Forms the Sun and Darkspots
circle(320, 48, 9);//Forms the Sun and Darkspots
circle(295, 30, 6);//Forms the Sun and Darkspots
circle(284, 79, 9);//Forms the Sun and Darkspots
fill(240, 100, 50);//Forms the Sun and Darkspots
rect(0, 200, 400, 400); //Beach
console.log("EVAPORATION");
//Lots of variables
let stoprip = 45;
let lake = int(dist(400, 400, mouseX, mouseY));
var starx = random(0, 400);
var stary = random (10, 190);
var sun = int(dist(300, 60, mouseX, mouseY));
//If Statement that creates ripples
if (mouseIsPressed && lake < 300) {
if (mouseY >= 200) {
noFill();
stroke('#3895d3');
strokeWeight(4);
circle(mouseX, mouseY, ripple);
ripple = ripple + 5;
console.log('lake rippling');
if (ripple >= stoprip) {
ripple = 10
}
} else {
ripple = 10
}
} else if (mouseIsPressed && sun <=35) {
fill('#fee12b');
circle(starx, stary, 10);
console.log('stars');
}
background(50, 0.25);
//For loop that creates the smoke effect with an increasement
for (let i = 0; i < bugs.length; i++) {
bugs[i].show();
bugs[i].move();
if( bugs[i].radius > 100 ) {
bugs.splice(i, 1);
}
}
let x = 200;
let y = 300;
let rad = random(10, 50);
let b = new Bug(x, y, rad);
bugs.push(b);
}
//Particles for evaporation
class Bug {
constructor(tempX, tempY, tempRadius) {
this.x = tempX;
this.y = tempY;
this.radius = tempRadius;
this.color = color(random(80,100), 0.05);
}
//Creates the sketch for it
show() {
noStroke();
fill(this.color);
ellipse(this.x, this.y, this.radius);
}
//Moves it up at a random pace
move() {
this.x = this.x + random(-5, 5);
this.y = this.y - random(2);
this.radius = this.radius + 0.4;
}
}
function condensation() {
//Changes the canvas from 400,400 to 600,600
createCanvas(600, 600);
//Changes background to grey to imitate storm,
background(50);
console.log("CONDENSATION");
//Colors the cloud and fills it with white
noStroke();
fill(255);
//States where cloud spawns
cloud(xpos,50,1);
cloud(xpos,50,2);
cloud(xpos,80,0.75);
xpos++;
//Has cloud with an increasement
if (xpos>600) {
xpos=0;
}
}
function presipitation() {
createCanvas(600, 600);
ellipseMode(RADIUS);
noFill();
background(211, 69, 93);
console.log("PRESIPITATION")
//If statement that create a for loop that spawns new particles(rain)
if (particles.length < 200) particles.push(new Particle());
for (var i = 0; i < particles.length; i++) {
particles[i].update();
particles[i].display();
}
}
var particles = [];
//Variable
//Rain drop / Particle
class Particle {
constructor() {
this.reset();
}
//Resets Particle after update
reset() {
this.x = random(width);
this.y = random(-150, 0);
this.vy = random(0.1, 2);
this.maxy = this.y + height;
this.r = 0;
this.tr = 50;
this.w = random(0.1, 2);
}
//If statement that creates the gravity for the particle
update() {
if (this.y < this.maxy) {
this.y += this.vy;
} else {
this.r++;
}
if (this.r > this.tr) this.reset();
}
//If statement(says it will remain the raindrop form or change into the puddle
display() {
strokeWeight(this.w);
if (this.y < this.maxy) {
stroke(255);
push();
translate(this.x,this.y);
beginShape();
strokeWeight(1);
vertex(0,-5);
quadraticVertex(3, 0, 0, 1);
quadraticVertex(-3,0, 0, -5);
endShape(CLOSE);
pop();
} else {
stroke(255, map(this.r, 0, this.tr, 255, 0));
ellipse(this.x, this.y, this.r, this.r*.5);
}
}
}
//Changes Screen from evaporation, condensation, precipitation
function mousePressed(){
if(screen==0){
screen=1;
}else if(screen==1){
screen = 2;
} else if(screen == 2) {
screen = 0;
}
}
//Makes cloud
function cloud(x,y,sc){
push()
scale(sc);
ellipse(x,y,50,30);
ellipse(x,y+20,80,30);
ellipse(x+20,y,40,30);
ellipse(x+30,y+10,70,40);
pop()
}
html, body {
margin: 0;
padding: 0;
}
canvas {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sketch</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="libraries/p5.min.js"></script>
<script src="libraries/p5.sound.min.js"></script>
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
From the documentation for createCanvas:
Creates a canvas element in the document, and sets the dimensions of it in pixels. This method should be called only once at the start of setup. Calling createCanvas more than once in a sketch will result in very unpredictable behavior.
Instead of calling createCanvas repeatedly in your drawing functions, you should use resizeCanvas once when transitioning from one screen to another.
I couldn't actually reproduce whatever issue you were describing (partly because I could not make sense of your description). However I did also notice an issue with the variable ripple not being declared anywhere, so I fixed that, and now the sketch appears to be working correctly.
//Variables
let previousScreen = 0;
let screen = 0;
let bugs = [];
let amt = 1000;
let xpos = 0;
let ripple = 0;
function setup() {
createCanvas(400, 400);
colorMode(HSB);
//Changes Colormode to HSB(Hue-Saturation-Brightness)
//Creates the particles for the evaporation screen
//For loop with increasement that states more of the smoke is created
for (let i = 0; i < amt; i++) {
let x = 200;
let y = 300;
let rad = random(10, 50);
let b = new Bug(x, y, rad);
bugs[i] = b;
}
}
//Says if the value of screen changes so does the screen
function draw() {
if (screen == 0) {
if (previousScreen !== screen) {
resizeCanvas(400, 400);
previousScreen = screen;
}
evaporationscreen();
} else if (screen == 1) {
if (previousScreen !== screen) {
resizeCanvas(600, 600);
previousScreen = screen;
}
condensation();
} else if (screen == 2) {
if (previousScreen !== screen) {
resizeCanvas(600, 600);
previousScreen = screen;
}
presipitation();
}
}
//Evaporation
function evaporationscreen() {
background('#d2b48c');
//NOT RGB, HSB COLOR PALLETE(DO NOT MIX UP);
//HTML Color pallete('e928320');
noStroke();
fill('#3895d3') //Lake
circle(400, 400, 600)
fill('#18bdf0') //Sky
rect(0, 0, 400, 200);
fill('#ffff00'); //Sun
circle(300, 60, 70);
fill('#e9bd15'); //Darkspots on Sun
circle(315, 75, 10); //Forms the Sun and Darkspots
circle(280, 52, 8); //Forms the Sun and Darkspots
circle(299, 60, 13); //Forms the Sun and Darkspots
circle(320, 48, 9); //Forms the Sun and Darkspots
circle(295, 30, 6); //Forms the Sun and Darkspots
circle(284, 79, 9); //Forms the Sun and Darkspots
fill(240, 100, 50); //Forms the Sun and Darkspots
rect(0, 200, 400, 400); //Beach
console.log("EVAPORATION");
//Lots of variables
let stoprip = 45;
let lake = int(dist(400, 400, mouseX, mouseY));
var starx = random(0, 400);
var stary = random(10, 190);
var sun = int(dist(300, 60, mouseX, mouseY));
//If Statement that creates ripples
if (mouseIsPressed && lake < 300) {
if (mouseY >= 200) {
noFill();
stroke('#3895d3');
strokeWeight(4);
circle(mouseX, mouseY, ripple);
ripple = ripple + 5;
console.log('lake rippling');
if (ripple >= stoprip) {
ripple = 10
}
} else {
ripple = 10
}
} else if (mouseIsPressed && sun <= 35) {
fill('#fee12b');
circle(starx, stary, 10);
console.log('stars');
}
background(50, 0.25);
//For loop that creates the smoke effect with an increasement
for (let i = 0; i < bugs.length; i++) {
bugs[i].show();
bugs[i].move();
if (bugs[i].radius > 100) {
bugs.splice(i, 1);
}
}
let x = 200;
let y = 300;
let rad = random(10, 50);
let b = new Bug(x, y, rad);
bugs.push(b);
}
//Particles for evaporation
class Bug {
constructor(tempX, tempY, tempRadius) {
this.x = tempX;
this.y = tempY;
this.radius = tempRadius;
this.color = color(random(80, 100), 0.05);
}
//Creates the sketch for it
show() {
noStroke();
fill(this.color);
ellipse(this.x, this.y, this.radius);
}
//Moves it up at a random pace
move() {
this.x = this.x + random(-5, 5);
this.y = this.y - random(2);
this.radius = this.radius + 0.4;
}
}
function condensation() {
//Changes background to grey to imitate storm,
background(50);
console.log("CONDENSATION");
//Colors the cloud and fills it with white
noStroke();
fill(255);
//States where cloud spawns
cloud(xpos, 50, 1);
cloud(xpos, 50, 2);
cloud(xpos, 80, 0.75);
xpos++;
//Has cloud with an increasement
if (xpos > 600) {
xpos = 0;
}
}
function presipitation() {
ellipseMode(RADIUS);
noFill();
background(211, 69, 93);
console.log("PRESIPITATION")
//If statement that create a for loop that spawns new particles(rain)
if (particles.length < 200) particles.push(new Particle());
for (var i = 0; i < particles.length; i++) {
particles[i].update();
particles[i].display();
}
}
var particles = [];
//Variable
//Rain drop / Particle
class Particle {
constructor() {
this.reset();
}
//Resets Particle after update
reset() {
this.x = random(width);
this.y = random(-150, 0);
this.vy = random(0.1, 2);
this.maxy = this.y + height;
this.r = 0;
this.tr = 50;
this.w = random(0.1, 2);
}
//If statement that creates the gravity for the particle
update() {
if (this.y < this.maxy) {
this.y += this.vy;
} else {
this.r++;
}
if (this.r > this.tr) this.reset();
}
//If statement(says it will remain the raindrop form or change into the puddle
display() {
strokeWeight(this.w);
if (this.y < this.maxy) {
stroke(255);
push();
translate(this.x, this.y);
beginShape();
strokeWeight(1);
vertex(0, -5);
quadraticVertex(3, 0, 0, 1);
quadraticVertex(-3, 0, 0, -5);
endShape(CLOSE);
pop();
} else {
stroke(255, map(this.r, 0, this.tr, 255, 0));
ellipse(this.x, this.y, this.r, this.r * .5);
}
}
}
//Changes Screen from evaporation, condensation, precipitation
function mousePressed() {
if (screen == 0) {
screen = 1;
} else if (screen == 1) {
screen = 2;
} else if (screen == 2) {
screen = 0;
}
}
//Makes cloud
function cloud(x, y, sc) {
push();
scale(sc);
ellipse(x, y, 50, 30);
ellipse(x, y + 20, 80, 30);
ellipse(x + 20, y, 40, 30);
ellipse(x + 30, y + 10, 70, 40);
pop();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.3.1/p5.min.js"></script>
I have a game in which there si a rocket. When rockets health is 0 the game over screen should appear and when any key is pressed the game should restart.
I tried using redraw and loop keywords in p5.js
let x = 240;
let x1 = 258;
let score = 0;
let health = 5;
let opelsins = [];
let ecllipseOpelsin = [];
let monsterimg;
let meteorimg;
let inGameSound;
let opelsinimg;
let gameOverSound;
let backgroundsun;
let gameoverScreen;
function collideRectangleCircle(rx, ry, rw, rh, cx, cy, cr)
{
return rx+rw > cx-cr && cx+cr > rx && ry+rh > cy-cr && cy+cr > ry;
}
function Opelsin() {
this.x = random(40,560);
this.y = random(-200,-190);
this.speed = random(3,10);
this.fall = function() {
this.y = this.y + this.speed;
if (this.y > height) {
this.y = random(-200,-100);
this.x = random(40,560);
this.speed = random(3, 10);
}
};
this.show = function() {
fill(255)
ellipse(this.x + 15,this.y + 34, 10, 10)
image(opelsinimg,this.x,this.y, 40, 40)
};
}
function opelsinmodel() {
this.x = random(0,600);
this.y = random(-300,-310);
this.speed = random(3,10);
this.show = function() { ellipse(this.x,this.y, 20, 20) };
}
function setup() {
createCanvas(600, 400);
frameRate(300)
inGameSound.setVolume(1);
inGameSound.loop();
interval = setInterval(scoreCount, 500);
}
function gameOver() {
textSize(20);
text("GAME OVER", 250, 200);
text("SCORE: " + score, 270, 220);
fill(255);
}
function newGame() {
if (keyIsPressed === true) {
//redraw();
loop();
}
}
function preload() {
soundFormats('m4a')
monsterimg = loadImage('assets/monster.png');
opelsinimg = loadImage('assets/opelsin.png');
inGameSound = loadSound('assets/spaceBotInGameMusic.m4a');
gameOverSound = loadSound('assets/gameOverInGameSound.m4a');
backgroundsun = loadImage('assets/backgroundsun.jpg');
gameoverScreen = loadImage('assets/gameoverScreen.png');
}
function scoreCount() {
score++;
}
function draw() {
// background(11, 72, 170);
image(backgroundsun, 0, 0, 700, 400);
if (score == 0) {
for (let i = 0; i < 5; i ++) {
opelsins[i] = new Opelsin();
ecllipseOpelsin[i] = new opelsinmodel();
}
} if (score == 50) {
for (let i = 0; i < 10; i ++) {
opelsins[i] = new Opelsin();
ecllipseOpelsin[i] = new opelsinmodel();
}
}
if (score == 100) {
for (let i = 0; i < 15; i ++) {
opelsins[i] = new Opelsin();
ecllipseOpelsin[i] = new opelsinmodel();
}
}
if (score == 150) {
for (let i = 0; i < 20; i ++) {
opelsins[i] = new Opelsin();
ecllipseOpelsin[i] = new opelsinmodel();
}
}
if (score == 200) {
for (let i = 0; i < 25; i ++) {
opelsins[i] = new Opelsin();
ecllipseOpelsin[i] = new opelsinmodel();
}
}
if (keyIsDown(LEFT_ARROW) && x > -14) {
x -= 5;
}
if (keyIsDown(RIGHT_ARROW) && x < 550) {
x += 5;
}
if (keyIsDown(LEFT_ARROW) && x1 > 9) {
x1 -= 5;
}
if (keyIsDown(RIGHT_ARROW) && x1 < 565) {
x1 += 5;
}
fill(255, 255, 0)
rect(x1, 345, 20, 20)
image(monsterimg,x,310,60,60)
for (let opelsin of opelsins) {
opelsin.fall();
opelsin.show();
}
textSize(20);
text("Health: " + health, 10, 20);
fill(255);
textSize(20);
text("Score: " + score, 10, 40);
fill(255);
for (let opelsin of opelsins) {
hit = collideRectCircle(x1, 335, 20, 30, opelsin.x, opelsin.y, 40);
if(hit == true) {
health -= 1;
opelsin.y = height+1;
if (health == 0) {
inGameSound.stop();
gameOverSound.setVolume(1);
gameOverSound.loop();
image(gameoverScreen, 0, 0, 600, 400);
gameOver();
noLoop();
newGame();
}
}
}
}
What I expect is when the game over screen appears and then when the random key is pressed the game should restart.
The issue is that the game loop is stopped by noLoop() when the game is over. The loop is never restarted.
Set a state (e.g waitRestart) when the game is over (instead of newGame()):
let waitRestart = false;
function draw() {
// [...]
for (let opelsin of opelsins) {
hit = collideRectCircle(x1, 335, 20, 30, opelsin.x, opelsin.y, 40);
if(hit == true) {
health -= 1;
opelsin.y = height+1;
if (health == 0) {
inGameSound.stop();
gameOverSound.setVolume(1);
gameOverSound.loop();
image(gameoverScreen, 0, 0, 600, 400);
gameOver();
noLoop();
// newGame(); <----- delete
waitRestart = true; // <----- wait for restart
}
}
}
}
Add a keyPressed() callback instead of the newGame() function, which restarts the game and set all initial states like health and score:
function keyPressed() {
if (waitRestart) {
waitRestart = false;
score = 0;
health = 5;
loop();
}
}
I want to modify the platformer game that I find in codepen.
http://codepen.io/loktar00/pen/JEdqD
the original is like the below image.
I want to change it to be:
I want to zoom in the viewport to player and making a camera-like view where I could scroll a level within a canvas element.
Like this game http://www.html5quintus.com/quintus/examples/platformer_full/
The viewport and camera is tracking the player.
This is my code:
(function () {
var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
window.requestAnimationFrame = requestAnimationFrame;
})();
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d"),
width = 100,
height = 100,
player = {
x: width / 2,
y: height - 15,
width: 5,
height: 5,
speed: 3,
velX: 0,
velY: 0,
jumping: false,
grounded: false
},
keys = [],
friction = 0.8,
gravity = 0.3;
var boxes = [];
// player's position
var playerX = 20;
var playerY = 20;
// how far offset the canvas is
var offsetX = 0;
var offsetY = 0;
// dimensions
boxes.push({
x: 0,
y: 0,
width: 10,
height: height
});
boxes.push({
x: 0,
y: height - 2,
width: width,
height: 50
});
boxes.push({
x: width - 10,
y: 0,
width: 50,
height: height
});
boxes.push({
x: 120,
y: 10,
width: 80,
height: 80
});
boxes.push({
x: 170,
y: 50,
width: 80,
height: 80
});
boxes.push({
x: 220,
y: 100,
width: 80,
height: 80
});
boxes.push({
x: 270,
y: 150,
width: 40,
height: 40
});
canvas.width = width;
canvas.height = height;
function update() {
// check keys
if (keys[38] || keys[32] || keys[87]) {
// up arrow or space
if (!player.jumping && player.grounded) {
player.jumping = true;
player.grounded = false;
player.velY = -player.speed * 2;
}
}
if (keys[39] || keys[68]) {
// right arrow
if (player.velX < player.speed) {
player.velX++;
offsetX--;
}
}
if (keys[37] || keys[65]) {
// left arrow
if (player.velX > -player.speed) {
player.velX--;
offsetX++;
}
}
player.velX *= friction;
player.velY += gravity;
ctx.clearRect(0, 0, width, height);
ctx.fillStyle = "black";
ctx.beginPath();
player.grounded = false;
for (var i = 0; i < boxes.length; i++) {
ctx.rect(boxes[i].x, boxes[i].y, boxes[i].width, boxes[i].height);
var dir = colCheck(player, boxes[i]);
if (dir === "l" || dir === "r") {
player.velX = 0;
player.jumping = false;
} else if (dir === "b") {
player.grounded = true;
player.jumping = false;
} else if (dir === "t") {
player.velY *= -1;
}
}
if(player.grounded){
player.velY = 0;
}
player.x += player.velX;
player.y += player.velY;
ctx.save();
ctx.translate(offsetX, offsetY);
// clear the viewport
ctx.clearRect(-offsetX, -offsetY, 100,100);
ctx.fill();
ctx.fillStyle = "red";
ctx.fillRect(player.x, player.y, player.width, player.height);
ctx.fillRect(playerX-offsetX, playerY-offsetY, 8, 8);
// draw the other stuff
var l = boxes.length;
for (var i = 0; i < l; i++) {
// we should really only draw the things that intersect the viewport!
// but I am lazy so we are drawing everything here
var x = boxes[i][0];
var y = boxes[i][1];
ctx.fillStyle = 'lightblue';
ctx.fillRect(x, y, 8, 8);
ctx.fillStyle = 'black';
ctx.fillText(x + ', ' + y, x, y) // just to show where we are drawing these things
}
ctx.restore();
requestAnimationFrame(update);
}
function colCheck(shapeA, shapeB) {
// get the vectors to check against
var vX = (shapeA.x + (shapeA.width / 2)) - (shapeB.x + (shapeB.width / 2)),
vY = (shapeA.y + (shapeA.height / 2)) - (shapeB.y + (shapeB.height / 2)),
// add the half widths and half heights of the objects
hWidths = (shapeA.width / 2) + (shapeB.width / 2),
hHeights = (shapeA.height / 2) + (shapeB.height / 2),
colDir = null;
// if the x and y vector are less than the half width or half height, they we must be inside the object, causing a collision
if (Math.abs(vX) < hWidths && Math.abs(vY) < hHeights) {
// figures out on which side we are colliding (top, bottom, left, or right)
var oX = hWidths - Math.abs(vX),
oY = hHeights - Math.abs(vY);
if (oX >= oY) {
if (vY > 0) {
colDir = "t";
shapeA.y += oY;
} else {
colDir = "b";
shapeA.y -= oY;
}
} else {
if (vX > 0) {
colDir = "l";
shapeA.x += oX;
} else {
colDir = "r";
shapeA.x -= oX;
}
}
}
return colDir;
}
document.body.addEventListener("keydown", function (e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function (e) {
keys[e.keyCode] = false;
});
window.addEventListener("load", function () {
update();
});
<h3>A, D or Arrow keys to move, W or space to jump</h3>
<canvas id="canvas"></canvas>
But this does not work.
You can use the same code that you had in the codepen, but add a couple lines in the load event, before the first update().
Let's say something like:
window.addEventListener("load", function () {
ctx.scale(2,2);
ctx.translate(-100,-100);
update();
});
This will zoom by two times and center on new coordinates, BUT keep in mind that you have to do it yourself if you want to re-center when the player is going out of the view.
As a partial way of doing this, you can check if the player moved and translate the canvas using the opposite values of player.velX and player.velY. Something like:
var playerMoved = false;
if (keys[38] || keys[32] || keys[87]) {
playerMoved = true;
//...Other stuff
}
if (keys[39] || keys[68]) {
playerMoved = true;
//...Other stuff
}
if (keys[37] || keys[65]) {
playerMoved = true;
//...Other stuff
}
if (playerMoved) {
// You still need to check quite a few things, like
// the player being out of bounds, the view not translating
// when x less than or bigger then a specific value, and so on
ctx.translate(-player.velX, -player.velY);
}
This is not a complete solution because that would require quite some code, but it should get you started.
I have made a program that is supposed to make several balls move along a path. So far, I have only been able to make one ball successfully traverse the course because whenever I add another ball (from the array of balls) it begins to flicker and spasmodically disappears. I would appreciate any assistance in solving this problem.
JS bin
<!DOCTYPE html>
<html>
<head>
<style>
* {
padding: 0;
margin: 0;
}
canvas {
background: #eee;
display: block;
margin: 0 auto;
}
</style>
</head>
<body>
<canvas id="Circuit" width="500" height="320"></canvas>
<script>
var dad = [];
var canvas = document.getElementById("Circuit");
var ctx = canvas.getContext("2d");
var bool = false;
var dx1 = 2;
var dx2 = -2;
var dy1 = 0;
var dy2 = 2;
var memes = [{
x: 0,
y: 100,
}, {
x: 0,
y: 100,
}, {
x: 0,
y: 100,
}, {
x: 0,
y: 100,
}];
function drawCircle(index) {
ctx.beginPath();
ctx.arc(memes[index].x, memes[index].y, 10, 0, Math.PI * 2);
ctx.fillStyle = "#0095DD";
ctx.fill();
ctx.closePath();
}
function draw(index) {
if (index == 0) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
if (memes[index].x < 490 && memes[index].y < 291 && !bool) {
drawCircle(index);
memes[index].x += dx1;
memes[index].y += dy1;
}
else if (memes[index].x == 490) {
drawCircle(index);
memes[index].x += 1;
}
else if (memes[index].x > 490 && memes[index].y < 291) {
drawCircle(index);
memes[index].y += dy2;
}
else if (memes[index].y == 291) {
drawCircle(index);
memes[index].y += 1;
}
else if (memes[index].y > 291 && memes[index].x > 2) {
drawCircle(index);
bool = true;
memes[index].x -= 2;
}
else if (memes[index].x == 2 && memes[index].y > 291) {
drawCircle(index);
memes[index].x -= 1;
}
else if (memes[index].x < 2) {
drawCircle(index);
memes[index].y -= dy2;
if (memes[index].y < 100) {
clearInterval(dad[index]);
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
}
ctx.strokeStyle = "red";
ctx.strokeRect(2, 101, 490, 190);
ctx.strokeStyle = "blue";
ctx.strokeRect(2, 82, 40, 40);
}
setTimeout(function() {
setTimeout(function() {
dad[1] = setInterval(function() {
draw(1);
}, 20);
}, 1000);
dad[0] = setInterval(function() {
draw(0);
}, 20);
}, 1000);
</script>
</body>
</html>
The flicker happens when the second ball tries to render the frame. You have two sprites (animating things) clearing and drawing the frame. You also have multiple timers and when animating you usually want a nextFrame function that handles movement of the sprites and drawing the frame.
The sprites array is a list of things that need to be moved and drawn. I added some properties to the meme sprites so you can see that their state needs to be internal like with the "bool" value. Without that you end up effecting the other balls. You'll need to figure out how to remove sprites when they're no longer in play.
var dad = [];
var canvas = document.getElementById("Circuit");
var ctx = canvas.getContext("2d");
var bool = false;
var dx1 = 2;
var dx2 = -2;
var dy1 = 0;
var dy2 = 2;
var memes = [{
x: 0,
y: 100,
color: "#0095DD",
draw: drawMeme,
move: moveMeme,
vx: 1.2,
vy: 1.5,
}, {
x: 0,
y: 100,
vx: 1.5,
vy: 1,
color: "#DD9500",
draw: drawMeme,
move: moveMeme
}, {
x: 0,
y: 100,
vx: 2,
vy: 1,
color: "#FF0000",
draw: drawMeme,
move: moveMeme
}, {
x: 0,
y: 100,
vx: 3,
vy: 2,
color: "#009999",
draw: drawMeme,
move: moveMeme
}];
function drawMeme(meme) {
ctx.beginPath();
ctx.arc(meme.x, meme.y, 10, 0, Math.PI * 2);
ctx.fillStyle = meme.color;
ctx.fill();
ctx.closePath();
}
var sprites = [];
function nextFrame () {
ctx.clearRect(0, 0, canvas.width, canvas.height);
var len = sprites.length;
for (var i = 0; i < len; i++) {
var sprite = sprites[i];
sprite.move(sprite);
sprite.draw(sprite);
}
ctx.strokeStyle = "red";
ctx.strokeRect(2, 101, 490, 190);
ctx.strokeStyle = "blue";
ctx.strokeRect(2, 82, 40, 40);
requestAnimationFrame(nextFrame);
}
function moveMeme(meme) {
if (meme.x < 490 && meme.y < 291 && !meme.bool) {
meme.x += dx1 * meme.vx;
meme.y += dy1 * meme.vy;
}
else if (meme.x == 490) {
meme.x += 1 * meme.vx;
}
else if (meme.x > 490 && meme.y < 291) {
meme.y += dy2 * meme.vy;
}
else if (meme.y == 291) {
meme.y += 1 * meme.vy;
}
else if (meme.y > 291 && meme.x > 2) {
meme.bool = true;
meme.x -= 2 * meme.vx;
}
else if (meme.x == 2 && meme.y > 291) {
meme.x -= 1 * meme.vx;
}
else if (meme.x < 2) {
meme.y -= dy2 * meme.vy;
if (meme.y < 100) {
// stop drawing this sprite
meme.draw = function(){};
meme.delete = 1; // for a cleanup function
}
}
}
nextFrame();
function startMeme(index) {
var meme = memes[index];
sprites.push(meme);
}
setTimeout(function() {
setTimeout(function() {
startMeme(1);
}, 1000);
startMeme(0);
startMeme(2);
startMeme(3);
}, 1000);
<canvas id="Circuit" width="500" height="320"></canvas>