How to move an object across a game board. Multiple Objects - javascript

I am an extreme beginner in the field of P5.JS. I am way more knowledgeable in Java which will be apparent in my broken code. I have attempted a multitude of Java approaches to cycling through objects of the same class and applying methods to them. My attempt is to implement buttons that will move them forward as of now and once I understand that move on to more complicated interactions.
https://openprocessing.org/sketch/1564721 6
This is the link to the code I am attempting to fix it currently, but if you have any tips or advice for streamlining this please let me know.
var gridCellSizeX = 80;
var gridCellSizeY = 100;
var gridAlpha = 1000;
let img;
var gridCellSizeSlider;
turnValue = 1;
var count = 1;
var gameOn = true;
var forward = false;
function preload() {
img = loadImage('vagg02.jpg');
}
function setup() {
createCanvas(800, 600);
image(img, 0,0,800,500);
image( img ,0, 500, 800,100);
stroke(0, gridAlpha);
for (var x = 0; x < width; x += gridCellSizeX) {
line(x, 0, x, 500);
}
for (var y = 0; y < height; y += gridCellSizeY) {
line(0, y, width, y);
}
token1 = new token(15, 5, 100, 5000, 'reb', 1)
token2 = new token(15, 205, 100, 5000,'reb', 2 )
token3 = new token(15, 405, 100, 5000, 'reb', 3)
token4 = new token(735, 5, 100, 5000,'union', 4)
token5 = new token(735, 205, 100, 5000, 'union', 5)
token6 = new token(735, 405, 100, 5000, 'union', 6)
const tokens = new Array(token1, token2, token3, token4, token5, token6);
forwardButton = createButton('Move -->')
forwardButton.position(300, 525);
forwardButton.mousePressed(moveForward());
//button = createButton('Move -->'); button.position(300, 525); button.mousePressed();
button2 = createButton('Move Up');
button2.position(400, 525);
button2.mousePressed();
button3 = createButton('Move Down');
button3.position(500, 525);
button3.mousePressed();
button4 = createButton('Move <--');
button4.position(600, 525);
button4.mousePressed();
}
function draw() {
if(forward == true) token1.x =+ 500;
//for(let i = 0; gameOn == true; i++){ if(i > 6){ i = 0; }}
}
function mousePressed() {
if (mouseX >= 300 && mouseX <= 325 &&
mouseY >= 525 && mouseY <= 500){
token1.moveForward();
}
return false;
}
// new file token
class token {
constructor(xpos, ypos, t, a, s, turn) {
this.x = xpos;
this.y = ypos;
this.troopSize = t / 2;
this.accuracy = a / 100.0;
this.side = s;
this.moveTurn = turn;
this.loaded = true;
if(this.side == 'reb'){
fill('red');
rect(this.x, this.y, this.troopSize, 90)
}
if(this.side == 'union'){
fill('blue');
rect(this.x, this.y, this.troopSize, 90)
}
}
getToken(){
if(count > 6){
count = 1;
}
if(count == 1) {
return token1;
}
else if(count == 2){
return token2;
}
else if(count == 3){
return token3;
}
else if(count == 4){
return token4;
}
else if(count == 5){
return token5;
}
else if(count == 6){
return token6;
}
count++;
}
///////// Beginning of Basic Functions for the TOKEN CLASS
moveForward(){
if(this.side == 'reb'){
token1.x += 50;
redraw(token1);
}
if(this.side == 'union'){
this.x += -50;
redraw();
}
}
////
moveBackward(){
if(this.side == 'reb'){
this.x = this.x - 50;
}
if(this.side == 'union'){
this.x = this.x + 50;
}
}
/////
fire(){
if(loaded == true){
}
}
//////
load(){
}
///////
fixBayonet(){
}
////////
charge(){
}
///////// END of Basic Functions for the TOKEN CLASS
}

Related

i cant get my shot to travel directly to my cursor

I am making a 2d game with javascript and i can't get the shot to travel in a line directly to the cursor. I want it so when the shoot function is called th make the shot travel to the cursor and not alter the path when the cursor is moved after the shot is already out. Right now it is onnly going diagonal to the player
<!DOCTYPE html>
<html lang="en" onclick="shoot()">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta charset="utf-8">
<style>
canvas {
border:4px solid #000000;
background-color: #26af2d;
}
</style>
<body onload="startGame()">
<div name="buttonDiv">
<button type="button" id="startRoundBtn" onclick= startWave();>dont mind this</button>
</div>
<p id="demo">
</p>
<script>
let playerHealth = 100;
let shot = false;
let enemyOut = false;
let waveActive = false;
let enemyDmg = 25;
let playerImmuneTime = 0;
//start
var player;
var TopEdge;
var BottomEdge;
var RightEdge;
var LeftEdge;
let Enemy;
var projectile;
function startGame() {
player = new component(30, 30, "red", 10, 120);
TopEdge = new component(10000, 200, "purple", 0, -200);
BottomEdge = new component(10000, 1, "purple", 0, 500);
RightEdge = new component(1000, 500, "purple", 1150, 0);
LeftEdge = new component(1000, 500, "purple", -1000, 0);
var x = document.getElementById("startRoundBtn");
myGameArea.start();
}
//game area
var myGameArea = {
canvas : document.createElement("canvas"),
start : function() {
this.canvas.width = 1150;
this.canvas.height = 500;
this.context = this.canvas.getContext("2d");
document.body.insertBefore(this.canvas,
document.body.childNodes[0]);
this.interval = setInterval(updateGameArea, 10);
window.addEventListener('keydown', function (e) {
myGameArea.keys = (myGameArea.keys || []);
myGameArea.keys[e.keyCode] = (e.type == "keydown");
})
window.addEventListener('keyup', function (e) {
myGameArea.keys[e.keyCode] = (e.type == "keydown");
})
},
clear : function(){
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height);
},
stop : function(){
clearInterval(this.interval);
}
}
//coords
var pointerX = 0;
var pointerY = 0;
document.onmousemove = function(event) {
pointerX = event.pageX;
pointerY = event.pageY;
}
setInterval(pointerCheck, 1);
function pointerCheck() {
var cursorCoords = 'Cursor Location: '+pointerX+'X, '+pointerY+'Y health: ' + playerHealth + ' imune time:' +playerImmuneTime
document.getElementById("demo").innerHTML = cursorCoords;
}
//compenents
function component(width, height, color, x, y) {
this.width = width;
this.height = height;
this.speedX = 0;
this.speedY = 0;
this.x = x;
this.y = y;
this.update = function() {
ctx = myGameArea.context;
ctx.fillStyle = color;
ctx.fillRect(this.x, this.y, this.width, this.height);
}
//new pos
this.newPos = function() {
this.X += this.speedX;
this.Y += this.speedY;
}
//crashing
this.crashWith = function(otherobj) {
var myleft = this.x;
var myright = this.x + (this.width);
var mytop = this.y;
var mybottom = this.y + (this.height);
var otherleft = otherobj.x;
var otherright = otherobj.x + (otherobj.width);
var othertop = otherobj.y;
var otherbottom = otherobj.y + (otherobj.height);
var crash = true;
if ((mybottom < othertop) ||
(mytop > otherbottom) ||
(myright < otherleft) ||
(myleft > otherright)) {
crash = false;
}
return crash;
}
}
//updates
function updateGameArea() {
myGameArea.clear();
if (playerHealth > 0) {
player.newPos();
player.update();
}
TopEdge.update();
BottomEdge.update();
RightEdge.update();
LeftEdge.update();
if (shot == true) {
projectile.update();
projectile.newPos();
projectile.speedX = 0;
projectile.speedY = 0;
}
if (enemyOut == true && playerHealth > 0) {
if (Enemy.crashWith(player) && playerImmuneTime <= 0) {
playerHealth = playerHealth -= enemyDmg;
playerImmuneTime = 50;
} if (playerImmuneTime >= 0) {
playerImmuneTime -= 1;
}
Enemy.newPos();
Enemy.update();
Enemy.speedX = 0;
Enemy.speedY = 0;
}
player.speedX = 0;
player.speedY = 0;
//movement
if (myGameArea.keys[65] ) {player.speedX = -2.5; }
if (myGameArea.keys[68] ) {player.speedX = 2.5; }
if (myGameArea.keys[87] ) {player.speedY = -2.5; }
if (myGameArea.keys[83] ) {player.speedY = 2.5; }
if (myGameArea.keys[82]) {waveActive = true;}
if (myGameArea.keys[75]) {waveActive = false;}
if (enemyOut == true && player.x >= Enemy.x) {Enemy.speedX = 1; }
if (enemyOut == true && player.x <= Enemy.x) {Enemy.speedX = -1; }
if (enemyOut == true && player.y >= Enemy.y) {Enemy.speedY = 1; }
if (enemyOut == true && player.y <= Enemy.y) {Enemy.speedY = -1; }
if (waveActive == true && enemyOut == false) {
createEnemy();
}
if (shot == true && pointerX > player.x) {projectile.speedX = 10};
if (shot == true && pointerX < player.x) {projectile.speedX = -10};
if (shot == true && pointerY > player.y) {projectile.speedY = 10};
if (shot == true && pointerY < player.y) {projectile.speedY = -10};
if (shot == true && enemyOut == true && projectile.crashWith(Enemy)) {
shot = false;
enemyOut = false;
waveActive = false;
}
//edges of game area
if (player.crashWith(TopEdge) && myGameArea.keys[87]) {
player.speedY = 0;
}
if (player.crashWith(RightEdge) && myGameArea.keys[68]) {
player.speedX = 0;
}
if (player.crashWith(BottomEdge) && myGameArea.keys[83]) {
player.speedY = 0;
}
if (player.crashWith(LeftEdge) && myGameArea.keys[65]) {
player.speedX = 0;
}
player.x += player.speedX;
player.y += player.speedY;
Enemy.x += Enemy.speedX;
Enemy.y += Enemy.speedY;
projectile.x += projectile.speedX;
projectile.y += projectile.speedY;
}
function createEnemy() {
Enemy = new component(30, 30, "purple",
Math.floor(Math.random() * 1100),
Math.floor(Math.random() * 500));
enemyOut = true;
}
function shoot() {
let midPlayerX = player.x + 12;
let midPlayerY = player.y + 12;
projectile = new component(5, 5, "white", midPlayerX, midPlayerY);
shot = true;
}
</script>
</body>
</html>
you need to 'freeze' the pointerX and pointerY values between the shot being fired and reaching its destination (otherwise those values will change on mousemove).
You already have shot=true when the projectile is launched so it can be read in a conditional you add to your mousemove event listener. That will take care of freezing the pointers when the projectile is fired :
document.onmousemove = function (event) {
if (!shot) {
pointerX = event.pageX
pointerY = event.pageY
} // prevent updates to pointers when shot is fired;
}
but you will need to reactivate the listener by setting shot to false when the projectile colides with the stored pointerX and pointerY values.

How to add collision between the player and the image?

I'm trying to make a program where the user moves with a circle using the keyboard to collect coins. What I tried so far is using an if statement to see if they collide and if they do, the user gets 1 coin and the image disappears. When I try this method, the code runs normally, but the collision doesn't happen.
/* Credit: https://openprocessing.org/sketch/525131
*/
var left, right, up, down;
var coin = [];
var player, posX, posY, radius, speed, colour, gameScreen, coins;
function setup() {
createCanvas(400, 400);
left = right = up = down = false;
gameScreen = "game";
coins = 0;
for (var i = 0; i < 10; i++) {
coin[i] = new Coin(random(width), random(height), 20, 20);
}
player = new Player();
}
function game() {
background(0);
if (left == true) {
player.moveLeft();
}
if (right == true) {
player.moveRight();
}
if (up == true) {
player.moveUp();
}
if (down == true) {
player.moveDown();
}
for (var i = 0; i < 10; i++) {
coin[i].display();
}
player.display();
//player.collision();
fill(255);
textSize(20);
text("Coins: " + coins, 10, 30);
}
function draw() {
game();
}
function keyPressed() {
// if (keyPressed) { For Processing add this line
if (keyCode == LEFT_ARROW || key == 'a') {
left = true;
}
if (keyCode == RIGHT_ARROW || key == 'd') {
right = true;
}
if (keyCode == UP_ARROW || key == 'w') {
up = true;
}
if (keyCode == DOWN_ARROW || key == 's') {
down = true;
}
// }
}
function keyReleased() {
if (keyCode == LEFT_ARROW || key == 'a') {
left = false;
}
if (keyCode == RIGHT_ARROW || key == 'd') {
right = false;
}
if (keyCode == UP_ARROW || key == 'w') {
up = false;
}
if (keyCode == DOWN_ARROW || key == 's') {
down = false;
}
}
function Coin(coinX, coinY, coinR) {
this.img = loadImage("https://www.paulwheeler.us/files/Coin120.png");
this.coinX = coinX;
this.coinY = coinY;
this.coinR = coinR;
this.display = function() {
image(this.img, this.coinX, this.coinY, this.coinR, this.coinR);
}
}
function Player() {
this.posX = width / 2;
this.posY = height / 2;
this.radius = 10;
this.speed = 4;
this.colour = "blue";
this.display = function() {
fill(this.colour);
ellipse(this.posX, this.posY, this.radius * 2, this.radius * 2);
}
this.moveLeft = function() {
// posX = posX - speed;
this.posX = constrain(this.posX - this.speed, this.radius, width - this.radius);
}
this.moveRight = function() {
// posX = posX + speed;
this.posX = constrain(this.posX + this.speed, this.radius, width - this.radius);
}
this.moveUp = function() {
// posY = posY-speed;
this.posY = constrain(this.posY - this.speed, this.radius, height - this.radius);
}
this.moveDown = function() {
// posY = posY+speed;
this.posY = constrain(this.posY + this.speed, this.radius, height - this.radius);
}
/*this.collision = function(){
if (this.posX > this.coinX && this.posX < this.coinX + this.coinR && this.posY > this.coinY && this.posY < this.coinY + this.coinR){
coins+=1;
//Coin disappears
}
}
*/
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>
You can use dist() in p5 to determine the distance between the center of the two circles and then see if it smaller than the two radi combined. Once you have that you can execute whatever code is needed.
for (let i = 0; i < coin.length; i++) {
if (
dist(player.posX, player.posY, coin[i].coinX, coin[i].coinY) <
player.radius + coin[i].coinR
) {
coin.splice(i, 1);
coins++;
i--;
}
}
Snippet
/* Credit: https://openprocessing.org/sketch/525131
*/
var left, right, up, down;
var coin = [];
var player, posX, posY, radius, speed, colour, gameScreen, coins;
function setup() {
createCanvas(400, 400);
left = right = up = down = false;
gameScreen = "game";
coins = 0;
for (var i = 0; i < 10; i++) {
coin[i] = new Coin(random(400), random(400), 20);
}
player = new Player();
}
function game() {
background(0);
if (left == true) {
player.moveLeft();
}
if (right == true) {
player.moveRight();
}
if (up == true) {
player.moveUp();
}
if (down == true) {
player.moveDown();
}
//change to coin.length to prevent error
for (var i = 0; i < coin.length; i++) {
coin[i].display();
}
player.display();
//player.collision();
fill(255);
textSize(20);
text("Coins: " + coins, 10, 30);
for (let i = 0; i < coin.length; i++) {
if (
dist(player.posX, player.posY, coin[i].coinX, coin[i].coinY) <
player.radius + coin[i].coinR
) {
coin.splice(i, 1);
coins++;
i--;
}
}
}
function draw() {
game();
}
function keyPressed() {
// if (keyPressed) { For Processing add this line
if (keyCode == LEFT_ARROW || key == "a") {
left = true;
}
if (keyCode == RIGHT_ARROW || key == "d") {
right = true;
}
if (keyCode == UP_ARROW || key == "w") {
up = true;
}
if (keyCode == DOWN_ARROW || key == "s") {
down = true;
}
// }
}
function keyReleased() {
if (keyCode == LEFT_ARROW || key == "a") {
left = false;
}
if (keyCode == RIGHT_ARROW || key == "d") {
right = false;
}
if (keyCode == UP_ARROW || key == "w") {
up = false;
}
if (keyCode == DOWN_ARROW || key == "s") {
down = false;
}
}
function Coin(coinX, coinY, coinR) {
/*this.img = loadImage(
"https://www.searchpng.com/wp-content/uploads/2019/04/Game-Coins-PNG-jpeg-715x715.png"
);*/
this.coinX = coinX;
this.coinY = coinY;
this.coinR = coinR;
this.colour = "yellow";
this.display = function () {
fill(this.colour);
ellipse(this.coinX, this.coinY, this.coinR * 2, this.coinR * 2);
};
}
function Player() {
this.posX = width / 2;
this.posY = height / 2;
this.radius = 10;
this.speed = 4;
this.colour = "blue";
this.display = function () {
fill(this.colour);
ellipse(this.posX, this.posY, this.radius * 2, this.radius * 2);
};
this.moveLeft = function () {
// posX = posX - speed;
this.posX = constrain(
this.posX - this.speed,
this.radius,
width - this.radius
);
};
this.moveRight = function () {
// posX = posX + speed;
this.posX = constrain(
this.posX + this.speed,
this.radius,
width - this.radius
);
};
this.moveUp = function () {
// posY = posY-speed;
this.posY = constrain(
this.posY - this.speed,
this.radius,
height - this.radius
);
};
this.moveDown = function () {
// posY = posY+speed;
this.posY = constrain(
this.posY + this.speed,
this.radius,
height - this.radius
);
};
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.min.js" integrity="sha512-N4kV7GkNv7QR7RX9YF/olywyIgIwNvfEe2nZtfyj73HdjCUkAfOBDbcuJ/cTaN04JKRnw1YG1wnUyNKMsNgg3g==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
Your collision function was trying to access this.coinX, this.coinY, and this.coinR but it was defined on Player which doesn't have any of those properties. You need to use a loop to check each coin for collision:
this.collision = function() {
for (let ix = 0; ix < coin.length; ix++) {
const currentCoin = coin[ix];
if (this.posX > currentCoin.coinX &&
this.posX < currentCoin.coinX + currentCoin.coinR &&
this.posY > currentCoin.coinY &&
this.posY < currentCoin.coinY + currentCoin.coinR) {
coins += 1;
// Coin disappears:
// delete the current coin from the array
coin.splice(ix, 1);
// Since the coin that was at ix + 1 is now at position ix in
// the coin array, we need to set ix back by one.
ix--;
}
}
}
/* Credit: https://openprocessing.org/sketch/525131
*/
var left, right, up, down;
var coin = [];
var player, posX, posY, radius, speed, colour, gameScreen, coins;
function setup() {
createCanvas(400, 400);
left = right = up = down = false;
gameScreen = "game";
coins = 0;
for (var i = 0; i < 10; i++) {
coin[i] = new Coin(random(width), random(height), 20, 20);
}
player = new Player();
}
function game() {
background(0);
if (left == true) {
player.moveLeft();
}
if (right == true) {
player.moveRight();
}
if (up == true) {
player.moveUp();
}
if (down == true) {
player.moveDown();
}
for (var i = 0; i < coin.length; i++) {
coin[i].display();
}
player.display();
player.collision();
fill(255);
textSize(20);
text("Coins: " + coins, 10, 30);
}
function draw() {
game();
}
function keyPressed() {
// if (keyPressed) { For Processing add this line
if (keyCode == LEFT_ARROW || key == 'a') {
left = true;
}
if (keyCode == RIGHT_ARROW || key == 'd') {
right = true;
}
if (keyCode == UP_ARROW || key == 'w') {
up = true;
}
if (keyCode == DOWN_ARROW || key == 's') {
down = true;
}
// }
}
function keyReleased() {
if (keyCode == LEFT_ARROW || key == 'a') {
left = false;
}
if (keyCode == RIGHT_ARROW || key == 'd') {
right = false;
}
if (keyCode == UP_ARROW || key == 'w') {
up = false;
}
if (keyCode == DOWN_ARROW || key == 's') {
down = false;
}
}
function Coin(coinX, coinY, coinR) {
this.img = loadImage("https://www.paulwheeler.us/files/Coin120.png");
this.coinX = coinX;
this.coinY = coinY;
this.coinR = coinR;
this.display = function() {
image(this.img, this.coinX, this.coinY, this.coinR, this.coinR);
}
}
function Player() {
this.posX = width / 2;
this.posY = height / 2;
this.radius = 10;
this.speed = 4;
this.colour = "blue";
this.display = function() {
fill(this.colour);
ellipse(this.posX, this.posY, this.radius * 2, this.radius * 2);
}
this.moveLeft = function() {
// posX = posX - speed;
this.posX = constrain(this.posX - this.speed, this.radius, width - this.radius);
}
this.moveRight = function() {
// posX = posX + speed;
this.posX = constrain(this.posX + this.speed, this.radius, width - this.radius);
}
this.moveUp = function() {
// posY = posY-speed;
this.posY = constrain(this.posY - this.speed, this.radius, height - this.radius);
}
this.moveDown = function() {
// posY = posY+speed;
this.posY = constrain(this.posY + this.speed, this.radius, height - this.radius);
}
this.collision = function() {
for (let ix = 0; ix < coin.length; ix++) {
const currentCoin = coin[ix];
if (this.posX > currentCoin.coinX &&
this.posX < currentCoin.coinX + currentCoin.coinR &&
this.posY > currentCoin.coinY &&
this.posY < currentCoin.coinY + currentCoin.coinR) {
coins += 1;
// Coin disappears:
// delete the current coin from the array
coin.splice(ix, 1);
// Since the coin that was at ix + 1 is now at position ix in
// the coin array, we need to set ix back by one.
ix--;
}
}
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.0/p5.js"></script>

Having trouble using instance mode

I am getting errors when I used instance mode in my code. My mini game isn't showing up I am not sure where the error is coming from. It works fine without the instance mode but I need to use the instance mode so that I can reference this code in another file. I'm using this link as a reference. http://p5js.org/examples/instance-mode-instantiation.html
let sketch = function(p) {
let blob;
let blobs = [];
let zoom = 1;
let timer = 20;
let hits = false;
let score = 0;
p.setup = function() {
p.createCanvas(600, 600);
blob = new Blob(0, 0, 64);
for (let i = 0; i < 300; i++) {
let x = p.random(-p.width,p.width);
let y = p.random(-p.height,p.height);
blobs[i] = new Blob(x, y, 15);
}
};
p.draw = function() {
p.background(0);
p.translate(width/2, height/2);
let newzoom = 64 / blob.r;
p.zoom = p.lerp(zoom, newzoom, 0.1);
p.scale(zoom);
p.translate(-blob.pos.x, -blob.pos.y);
for (var i = blobs.length-1; i >=0; i--) {
blobs[i].show();
if (blob.eats(blobs[i])) {
blobs.splice(i, 1);
}
}
if (frameCount % 60 == 0 && timer > 0) { // if the frameCount is divisible by 60, then a second has passed. it will stop at 0
p.timer --;
}
if (timer == 0 && score >=250) {
p.text("You Win", 0, 0);
p.noLoop();
}
if (blob.eats){
p.console.log("hit");
}
if (timer == 0 && score <= 250){
p.text("You Lose", 0, 0);
p.textSize(200);
p.noLoop();
}
blob.show();
blob.update();
};
};
let myp5 = new p5(sketch);
class Blob {
constructor(x, y, r) {
this.pos = createVector(x, y);
this.r = r;
this.vel = createVector(0,0);
}
show(p) {
p.ellipse(this.pos.x, this.pos.y, this.r, this.r);
}
eats(other) {
let d = p5.Vector.dist(this.pos, other.pos);
if (d < this.r + other.r) {
let sum = PI * this.r * this.r + PI * other.r * other.r;
score ++;
this.r = sqrt(sum / PI);
//this.r += other.r;
return true;
} else {
return false;
}
}
While width, height and frameCount are properties of the canvas, console is it not.
p.translate(width/2, height/2);
p.translate(p.width/2, p.height/2);
if (frameCount % 60 == 0 && timer > 0) {
if (p.frameCount % 60 == 0 && timer > 0) {
console.log("hit");
console.log("hit");
I don't know the implementation of Blob. but you have to passe the canvas object (p) to the show method and the let constructor.
The variable score can't be accessed in the class Blob
See the example, where I applied the suggested changes to your original code:
class Blob {
constructor(p, x, y, r) {
this.pos = p.createVector(x, y);
this.r = r;
this.vel = p.createVector(0,0);
}
show(p) {
p.ellipse(this.pos.x, this.pos.y, this.r, this.r);
}
eats(other) {
let d = this.pos.dist(other.pos);
if (d < this.r + other.r) {
let sum = Math.pi * this.r * this.r + Math.pi * other.r * other.r;
this.r = Math.sqrt(sum / Math.pi);
//this.r += other.r;
return true;
} else {
return false;
}
}
update() {
// ...
}
}
let sketch = function(p) {
let blob;
let blobs = [];
let zoom = 1;
let timer = 20;
let hits = false;
let score = 0;
p.setup = function() {
p.createCanvas(600, 600);
blob = new Blob(p, 0, 0, 64);
for (let i = 0; i < 300; i++) {
let x = p.random(-p.width,p.width);
let y = p.random(-p.height,p.height);
blobs[i] = new Blob(p, x, y, 15);
}
};
p.draw = function() {
p.background(0);
p.translate(p.width/2, p.height/2);
let newzoom = 64 / blob.r;
p.zoom = p.lerp(zoom, newzoom, 0.1);
p.scale(zoom);
p.translate(-blob.pos.x, -blob.pos.y);
for (var i = blobs.length-1; i >=0; i--) {
blobs[i].show(p);
if (blob.eats(blobs[i])) {
score ++;
blobs.splice(i, 1);
}
}
if (p.frameCount % 60 == 0 && timer > 0) {
p.timer --;
}
if (timer == 0 && score >=250) {
p.text("You Win", 0, 0);
p.noLoop();
}
if (blob.eats){
console.log("hit");
}
if (timer == 0 && score <= 250){
p.text("You Lose", 0, 0);
p.textSize(200);
p.noLoop();
}
blob.show(p);
blob.update();
};
};
let myp5 = new p5(sketch)
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.1/p5.js"></script>

snake game crashes after eating several times with TypeError variable undefined

It's been few days that I've been learning JavaScript. So I'm completely new to this.
This is my code for snake game and it isn't complete yet but I've run into a problem. I'm not completely sure that if it's a logical error or not.
After eating the food several times, the game crashes with
TypeError: snakeBody[l] is undefined.
Screenshot of the error is here.
The entire code is given below:
<!DOCTYPE html>
<html lang="en">
<head>
<style>
canvas {
background: #080d16;
border: 5px solid green;
padding: 0;
}
</style>
</head>
<body>
<canvas id="mycan" class="mycan" width="1860" height="920"></canvas>
<script>
var canvas = document.getElementById('mycan');
var ctx = canvas.getContext('2d');
var snakeSize = 20;
var snakeX = 100;
var snakeY = 100;
var foodX = 310;
var foodY = 310;
var foodSize = 10;
var dx = 20;
var dy = 20;
var leftPressed = false;
var rightPressed = true;
var topPressed = false;
var bottomPressed = false;
var snakeBody = [{x:snakeX,y:snakeY},{x:snakeX-20,y:snakeY}];
var z = 0;
//keypress event listner
document.addEventListener('keypress', keyHandler, false);
//keypress event handler function
function keyHandler(e) {
if (e.keyCode == 37) {
leftPressed = true;
rightPressed = false;
topPressed = false;
bottomPressed = false;
} else if (e.keyCode == 38) {
leftPressed = false;
rightPressed = false;
topPressed = true;
bottomPressed = false;
} else if (e.keyCode == 39) {
leftPressed = false;
rightPressed = true;
topPressed = false;
bottomPressed = false;
} else if (e.keyCode == 40) {
leftPressed = false;
rightPressed = false;
topPressed = false;
bottomPressed = true;
}
}
//draw food
function food() {
ctx.beginPath();
ctx.arc(foodX, foodY, foodSize, 0, Math.PI * 2);
ctx.fillStyle = "pink";
ctx.fill();
ctx.closePath();
}
//draw snake
function snake() {
for (var l = 0; l < snakeBody.length; l++) {
ctx.beginPath();
ctx.rect(snakeBody[l].x, snakeBody[l].y, snakeSize, snakeSize);
if (l == 0) {
ctx.fillStyle = "lightblue";
} else {
ctx.fillStyle = 'grey';
}
ctx.fill();
ctx.closePath();
}
console.log(l);
var head = {
x: snakeX,
y: snakeY
};
snakeBody.pop();
snakeBody.unshift(head);
}
function tail() {
if ((snakeX + dx / 2 > foodX - foodSize && snakeX + dx / 2 < foodX + foodSize) && (snakeY + dy / 2 > foodY - foodSize && snakeY + dy / 2 < foodY + foodSize)) {
foodX = (Math.floor(Math.random() * 88) + 1) * 20 + 10;
foodY = (Math.floor(Math.random() * 45) + 1) * 20 + 10;
z++;
if (snakeBody[snakeBody.length - 1].x == snakeBody[snakeBody.length - 2].x && snakeBody[0].y < snakeBody[1].y) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x,
y: snakeBody[snakeBody.length - 1].y + 20
};
} else if (snakeBody[snakeBody.length - 1].x == snakeBody[snakeBody.length - 2].x && snakeBody[0].y > snakeBody[1].y) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x,
y: snakeBody[snakeBody.length - 1].y - 20
};
} else if (snakeBody[snakeBody.length - 1].y == snakeBody[snakeBody.length - 2].y && snakeBody[0].x > snakeBody[1].x) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x - 20,
y: snakeBody[snakeBody.length - 1].y
};
} else if (snakeBody[snakeBody.length - 1].y == snakeBody[snakeBody.length - 2].y && snakeBody[0].x < snakeBody[1].x) {
snakeBody[z] = {
x: snakeBody[snakeBody.length - 1].x + 20,
y: snakeBody[snakeBody.length - 1].y
};
}
}
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
snake();
food();
tail();
if (rightPressed && snakeX + dx < canvas.width) {
snakeX += dx;
} else if (leftPressed && snakeX > 0) {
snakeX += -dx;
} else if (topPressed && snakeY > 0) {
snakeY += -dy;
} else if (bottomPressed && snakeY + dy < canvas.height) {
snakeY += dy;
}
}
setInterval(draw, 80);
</script>
</body>
</html>
You have error in algorithm - your snakeBody put/pops elements and you miss some "corner cases" when use indexes in this array - the problem is not with JS but with algorithm - debug it and also use "triangle" in chrome konsole on left side of error to see more details (stacktrace)
I check and run your code more than once. This error does not appear for me. It is good for you to check the values in snake function and then use them. Modify your snake function to this
function snake() {
for (var l = 0; l < snakeBody.length; l++) {
ctx.beginPath();
if(snakeBody && snakeBody[l] && snakeBody[l].hasOwnProperty('x') && snakeBody[l].hasOwnProperty('y')) {
ctx.rect(snakeBody[l].x, snakeBody[l].y, snakeSize, snakeSize);
}
if (l == 0) {
ctx.fillStyle = "lightblue";
} else {
ctx.fillStyle = 'grey';
}
ctx.fill();
ctx.closePath();
}
console.log(l);
var head = {
x: snakeX,
y: snakeY
};
snakeBody.pop();
snakeBody.unshift(head);
}
As you can see, snakeBody has no indexes 24 and 25. But this condition satisfy this.

Why the nextButton/startButton does not work?

I am working on a project on Khan Academy in which I have to create a game with at least 3 levels. I have developed most of the game but when I tried to proceed from one level to next the game somehow stops.
Here is the full project:
Project Link
/**
* Contains 3 levels
*
*
* Changed Ground
* Brown rectangle is replaced with Dirt Block.
*
* Scoring system changed
* Collecting Good sticks gets 1 point.
* Collecting Bad sticks gets -1 point. (i.e. loses point).
* Hitting rocks will lose 1 point.
*
**/
var level = 0;
var nosOfSticks = 5;
var target = 0;
var speed = 1;
var endLevel = false;
var buttonClicked = false;
var levelButtonEnabled = false;
var startButtonEnabled = true;
var Beaver = function(x, y) { // Beaver Constructor
this.x = x;
this.y = y;
this.img = getImage("creatures/Hopper-Happy");
this.sticks = 0;
};
Beaver.prototype.draw = function() { // Draw function to draw beaver
fill(255, 0, 0);
this.x = constrain(this.x, 0, width-40);
this.y = constrain(this.y, 0, height-50);
image(this.img, this.x, this.y, 40, 40);
};
Beaver.prototype.hop = function() { // Hop function to make beaver hop
this.img = getImage("creatures/Hopper-Jumping");
this.y -= speed * 5;
};
Beaver.prototype.hopLeft = function() {
this.img = getImage("creatures/Hopper-Jumping");
this.x -= speed * 5;
};
Beaver.prototype.hopRight = function() {
this.img = getImage("creatures/Hopper-Jumping");
this.x += speed * 5;
};
Beaver.prototype.fall = function() { // fall function makes beaver fall on the ground
this.img = getImage("creatures/Hopper-Happy");
this.y += speed * 5;
};
Beaver.prototype.checkForStickGrab = function(stick) { // function that checks sticks grab
if ((stick.x >= this.x && stick.x <= (this.x + 40)) &&
(stick.y >= this.y && stick.y <= (this.y + 40))) {
stick.y = -400;
this.sticks++;
}
};
Beaver.prototype.checkForBadStickGrab = function(badstick) { // function that checks badsticks grab
if ((badstick.x >= this.x && badstick.x <= (this.x + 40)) &&
(badstick.y >= this.y && badstick.y <= (this.y + 40))) {
badstick.y = -400;
this.sticks--;
}
};
Beaver.prototype.checkForRockHit = function(rock) { // function that checks rocks hit
if ((rock.x >= this.x - 40 && rock.x <= (this.x + 40)) &&
(rock.y >= this.y - 30 && rock.y <= (this.y + 40))) {
rock.x = -400;
this.sticks--;
}
};
// Drawing Sticks
var Stick = function(x, y) { // Stick constructor
this.x = x;
this.y = y;
};
Stick.prototype.draw = function() { // Draw function to draw sticks
fill(0, 0, 0);
rectMode(CENTER);
rect(this.x, this.y, 5, 40);
};
var Badstick = function(x, y) { // Bad Sticks constructor
Stick.call(this, x, y);
};
//Badstick.prototype = Object.create(Stick);
Badstick.prototype.draw = function() { //Draw function to draw badsticks
fill(255, 0, 13);
rectMode(CENTER);
rect(this.x, this.y, 5, 40);
};
// Drawings Rocks
var Rock = function(x, y) { // rocks constructor
this.x = x;
this.y = y;
this.img = getImage("cute/Rock");
};
Rock.prototype.draw = function(x, y) { // function to draw rocks
fill(0, 0, 0);
image(this.img, this.x, this.y, 40, 40);
};
var beaver = new Beaver(200, 300);
var sticks = [];
for (var i = 0; i < nosOfSticks; i++) {
sticks.push(new Stick(i * 100 + 400, random(20, 260)));
}
var badSticks = [];
for (var i = 0; i < nosOfSticks/2; i++) {
badSticks.push(new Badstick(i * 200 + 400, random(20, 270)));
}
var rocks = [];
for ( var i = 0; i < nosOfSticks * 0.375; i++) {
rocks.push(new Rock(random(0, 375), i * random() - (i * 100)));
}
var grassXs = [];
for (var i = 0; i < 25; i++) {
grassXs.push(i*20);
}
var blockXs = [];
for (var i = 0; i < 25; i++) {
blockXs.push(i*20);
}
var Button = function (x, y, w, h, color, text, size, font, textcolor, best) {
this.x = x;
this.y = y;
this.w = w;
this.h = h;
this.color = color;
this.text = text;
this.size = size;
this.font = font;
this.textcolor = textcolor;
this.best = best;
};
Button.prototype.draw = function() {
rectMode(CORNER);
fill(this.color);
rect(this.x, this.y, this.w, this.h);
fill(this.textcolor);
stroke(this.textcolor);
textFont(this.font, this.size);
text(this.text, this.x + (this.w/2 - this.w/2.5), this.y + (this.h/2 + this.size/2.5));
/*textFont(this.font, this.size / 2);
text("Best : " + this.best, this.x + 10, this.y + 90);*/
};
Button.prototype.clicked = function() {
if(mouseIsPressed && mouseX >= this.x && mouseX <= this.x + this.w && mouseY >= this.y && mouseY <= this.y + this.h ) {
return true;
}
};
var nextButton = new Button(315, 360, 75, 30, color(0, 255, 0), "Next Level", 12, "Aerial Bold", color(0, 0, 0));
var startButton = new Button(315, 360, 75, 30, color(0, 255, 0), "Start Again", 12, "Aerial Bold", color(0, 0, 0));
var playButton = new Button(140, 250, 120, 50, color(0, 0, 0), "PLAY", 40, "Aerial Bold", color(255, 255, 255));
var level1Button = new Button(30, 120, 100, 100, color(0, 0, 0), "Level 1", 25, "Aerial Bold", color(255, 255, 255));
var level2Button = new Button(140, 120, 100, 100, color(0, 0, 0), "Level 2", 25, "Aerial Bold", color(255, 255, 255));
var level3Button = new Button(250, 120, 100, 100, color(0, 0, 0), "Level 3", 25, "Aerial Bold", color(255, 255, 255));
var drawWin = function() {
fill(255, 0, 0);
textSize(36);
text("YOU WIN!!!!", 100, 200);
nextButton.draw();
};
var drawLoss = function() {
fill(255, 0, 0);
textSize(36);
text("YOU LOSE!!!!", 100, 200);
startButton.draw();
};
var movement = function() {
if (keyIsPressed) {
if(keyCode === UP) {
beaver.hop();
} /*else if(keyCode === LEFT) {
beaver.hopLeft();
} else if(keyCode === RIGHT) {
beaver.hopRight();
} */
} else { beaver.fall();}
};
var drawScore = function() {
fill(0, 255, 0);
textSize(18);
text("Score: " + beaver.sticks, 10, 390);
};
var isWin = function() {
if(beaver.sticks >= target) {
drawWin();
speed = 1;
return true;
}
};
var isLoss = function() {
if (beaver.sticks < target ) {
speed = 1;
drawLoss();
return true;
}
};
var drawBackground = function() {
//static
speed = 1;
background(227, 254, 255);
stroke(0, 0, 0);
rectMode(CORNER);
rect(0, height*0.90, width, height*0.10);
for (var i = 0; i < grassXs.length; i++) {
image(getImage("cute/GrassBlock"), grassXs[i], height*0.85, 35, 20);
image(getImage("cute/DirtBlock"), grassXs[i], height*0.85, 35, 60);
grassXs[i] -= speed;
if (grassXs[i] <= - 20) {
grassXs[i] = width;
}
}
};
var drawSticks = function() {
for (var i = 0; i < sticks.length; i++) {
sticks[i].draw();
beaver.checkForStickGrab(sticks[i]);
sticks[i].x -= speed;
}
};
var drawBadSticks = function() {
for (var i = 0; i < badSticks.length; i++) {
badSticks[i].draw();
beaver.checkForBadStickGrab(badSticks[i]);
badSticks[i].x -= speed;
}
};
var drawRocks = function() {
for (var i = 0; i < rocks.length; i++) {
rocks[i].draw();
beaver.checkForRockHit(rocks[i]);
rocks[i].y += speed;
}
};
var drawLevel = function() {
speed = 1;
drawBackground();
if (level === 1) {
target = 1;
drawSticks();
}
if (level === 2) {
target = 1;
drawSticks();
drawBadSticks();
}
if (level === 3) {
target = 1;
drawBadSticks();
drawSticks();
drawRocks();
}
beaver.draw();
movement();
drawScore();
if (sticks[nosOfSticks - 1].x < -5) {
isWin();
isLoss();
}
};
var drawLevels = function() {
level = "l";
background(0, 0, 0);
level1Button.draw();
level2Button.draw();
level3Button.draw();
if (level1Button.clicked() && level === "l") {
level = 1;
drawLevel();
} else if (level2Button.clicked() && level === "l") {
level = 2;
drawLevel();
} else if (level3Button.clicked() && level === "l") {
level = 3;
drawLevel();
}
};
var drawStart = function() {
level = 0;
background(0);
text("Hoppy Beaver", 75, 50);
text("Extreme", 120, 100);
playButton.draw();
if (playButton.clicked() && level === 0) {
levelButtonEnabled = false;
drawLevels();
}
};
//drawStart();
mouseClicked = function() {
if (nextButton.clicked() || startButton.clicked()) {
if (beaver.sticks >= 1) {
if (level === 0) {
level = 1;
sticks = [];
draw();
isWin = false;
}
if (level === 1) {
level = 2;
sticks = [];
draw();
isWin = false;
}
if (level === 2) {
level = 3;
sticks = [];
draw();
isWin = false;
}
if (level === 3) {
level = 1;
sticks = [];
isWin = false;
draw();
}
} else if (beaver.sticks < 1) {
if (level === 1) {
level = 1;
sticks = [];
drawLevel();
isLoss = false;
}
if (level === 2) {
level = 2;
sticks = [];
drawLevel();
isLoss = false;
}
if (level === 3) {
level = 3;
sticks = [];
drawLevel();
isLoss = false;
}
}
}
};
draw = function() {
speed = 1;
if (level === 1) {
drawLevel();
} else if (level === 2) {
drawLevel();
} else if (level === 3) {
drawLevel();
} else if (level === "l") {
drawLevels();
} else { drawStart(); }
};
welcome to stackoverflow. The problem with your code is this bit right here in the drawLevel function.
if (sticks[nosOfSticks - 1].x < -5) {
isWin();
isLoss();
}
At the start of your program you initialize the sticks array with some stick objects in line 124. When level 1 ends and the next button is clicked, you set the sticks array to an empty array sticks=[] in the mouseClicked function.However, you never re-add anything into the sticks array. Thus, when that block of code runs, the element at position nosOfSticks-1 is undefined, leading to your problem.My suggestion is to make a for loop after sticks=[] to refill the sticks array just like in line 124.
Good Luck!
Also, take a look at this guide for debugging help, how to debug small programs.

Categories

Resources