Why does collision function won't remove an enemy? - javascript

I am trying to remove enemies when they get hit by a bullet, but as i can see this doesn't work.
I am writing this in codehs worksheet (javascript bootcamp).
var char;
var bullet;
var enemy;
var life = 5;
var enemyTimer = Randomizer.nextInt(0,50);
var enemies = [];
function start(){
makeChar();
keyDownMethod(movements);
makeBullet();
setTimer(shootBullet, 30);
addEnemy();
setTimer(makeEnemy, 5);
checkCollision();
}
function makeChar(){
char = new Circle(10);
char.setColor(Color.red);
char.setPosition(getWidth()/2, 430);
add(char);
}
function movements(e){
if (e.keyCode == Keyboard.RIGHT){
char.move(10,0);
}
if (e.keyCode == Keyboard.LEFT){
char.move(-10,0);
}
}
function makeBullet(){
bullet = new Rectangle(5,10);
bullet.setPosition(char.getX(), char.getY());
bullet.setColor(Color.green);
add(bullet);
}
function shootBullet(){
bullet.move(0,-10);
if (bullet.getY() < 0){
bullet.setPosition(char.getX(), char.getY());
}
}
function makeEnemy(){
for (var i = 0; i < enemies.length; i ++){
var b = enemies[i];
b.move(0,5)
b.move(Randomizer.nextInt(-3,3),0);
}
}
function addEnemy(){
setTimer(en,800);
}
function en(){
enemy = new Rectangle(50,50);
var x = Randomizer.nextInt(10, 350);
var y = enemy.getY();
y += 10;
enemy.setPosition(x,y);
add(enemy);
enemies.push(enemy);
}
function intersects(a,b){
return (a.getX() < b.getX() + b.getHeight() && a.getX() + a.getWidth() >b.getX() && a.getY() < b.getY() + b.getHeight() && a.getY() + a.getHeight() > b.getY());
}
function checkCollision(){
for(var i =0; i < enemies.length; i++){
var en = enemies[i];
if (intersects(bullet, en)){
println("hi");
remove(en);
i--;
remove(bullet);
}
}
}
With print I tried to see if it did read collision but it did not even print it.
I want it to remove enemies when it gets hit by a bullet,
Can somebody help?

Related

How to resolve a constructor console error in p5.js - data visual

I am basically trying to implement the bubble code (this code will just display the data from the csv file and display them in a bubble ellipse) into a data visualization template and the bubble code should be in an external constructor (meaning it should be in another file with the constructor name). To give u a general idea, i'm making a few tabs and once a tab is clicked - its designated code(constructor) will run.
I created a tab named as 'Food Data in Bubbles' and when that tab is clicked, the constructor should be called.
I don't have any problem with calling the constructor. The thing im having an issue with is that when the constructor is called, it gives an console error as you can see in this image
I want to know how i can resolve this Issue. Just for reference, I'll provide you with the files and code.
This is the index file that I'm using:
<!DOCTYPE html>
<html lang="en">
<head>
<script src="lib/p5.min.js"></script>
<!-- Main sketch file -->
<script src="sketch.js"></script>
<script src="bubble.js"></script>
<body>
<div id="app" class="container">
<ul id="visuals-menu"></ul>
</div>
</body>
</html>
This is the sketch file:
var dataTable;
var myScatter;
var data;
var bubbles = [];
var maxAmt;
var years = [];
var yearButtons = [];
function preload()
{
dataTable = loadTable('data/tech-diversity/gender-2018.csv', 'header');
data = loadTable("data/bubble/foodData.csv", "csv", "header");
}
function setup() {
// Create a canvas to fill the content div from index.html.
var c = createCanvas(1024, 576);
c.parent('app');
// Add the visualisation objects here.
gallery.addVisual(new BubbleData());
}
function draw() {
background(255);
if (gallery.selectedVisual != null) {
gallery.selectedVisual.draw();
}
translate(width/2, height/2);
for(var i = 0; i < bubbles.length; i++)
{
bubbles[i].update(bubbles);
bubbles[i].draw();
}
}
and this is the main Constructor file:
function BubbleData() {
// Name for the visualisation to appear in the menu bar.
this.name = 'Food Data in Bubbles';
// Each visualisation must have a unique ID with no special
// characters.
this.id = 'bubble-data';
// Property to represent whether data has been loaded.
this.loaded = false;
this.setup = function() {
var rows = data.getRows();
var numColumns = data.getColumnCount();
for(var i = 5; i < numColumns; i++)
{
var y = data.columns[i];
years.push(y);
b = createButton(y,y);
b.parent('years')
b.mousePressed(function()
{
changeYear(this.elt.value);
})
yearButtons.push(b);
}
maxAmt = 0;
for(var i = 0; i < rows.length; i++)
{
if(rows[i].get(0) != "")
{
var b = new Bubble(rows[i].get(0));
for(var j = 5; j < numColumns; j++)
{
if(rows[i].get(j) != "")
{
var n = rows[i].getNum(j);
if(n > maxAmt)
{
maxAmt = n; //keep a tally of the highest value
}
b.data.push(n);
}
else
{
b.data.push(0);
}
}
bubbles.push(b);
}
}
for(var i = 0; i < bubbles.length; i++)
{
bubbles[i].setData(0);
}
};
function changeYear(year)
{
var y = years.indexOf(year);
for(var i = 0; i < bubbles.length; i++)
{
bubbles[i].setData(y);
}
};
// Create a new pie chart object.
this.pie = new PieChart(width / 2, height / 2, width * 0.4);
this.draw = function() {
translate(width/2, height/2);
for(var i = 0; i < bubbles.length; i++)
{
bubbles[i].update(bubbles);
bubbles[i].draw();
}
};
this.Bubble = function(_name)
{
this.size = 20;
this.target_size = 20;
this.pos = createVector(0,0);
this.direction = createVector(0,0);
this.name = _name;
this.color = color(random(0,255), random(0,255), random(0,255));
this.data = [];
this.draw = function()
{
push();
textAlign(CENTER);
noStroke();
fill(this.color);
ellipse(this.pos.x, this.pos.y, this.size);
fill(0);
text(this.name,this.pos.x,this.pos.y);
pop();
};
this.update = function(_bubbles)
{
this.direction.set(0,0);
for(var i = 0; i < _bubbles.length; i++)
{
if(_bubbles[i].name != this.name)
{
var v = p5.Vector.sub(this.pos,_bubbles[i].pos);
var d = v.mag();
if(d < this.size/2 + _bubbles[i].size/2)
{
if(d > 0)
{
this.direction.add(v)
}
else
{
this.direction.add(p5.Vector.random2D());
}
}
}
}
this.direction.normalize();
this.direction.mult(2);
this.pos.add(this.direction);
if(this.size < this.target_size)
{
this.size += 1;
}
else if(this.size > this.target_size)
{
this.size -= 1;
}
};
this.setData = function(i)
{
this.target_size = map(this.data[i], 0, maxAmt, 20, 250);
};
};
}
there is another file which is the helper function file through which I'm calling this function and other task but that's unnecessary here, the only problem here is with the constructor file

Trying to save changes as a whole as array inside an array that contains a custom object

I'm trying to make an if statement, that if the array board is the same as 2 changes ago, it will warn me by saying "undid illegal play".
However every array becomes the same after 3 turns (because of if(boardHistory.length >= 3){) but it warns me always while I see no reason for warning me since it's always changing and never becomes the same value.
What did I wrong?
var turn;
var boardSize;
var board;
var boardHistory;
var changer;
function setup() {
createCanvas(400, 400);
boardSize = 8;
turn = false;
board = [];
boardHistory = [];
changer = 0;
for (var y = 0; y < boardSize; y++) {
for (var x = 0; x < boardSize; x++) {
board.push(new Piece(x, y, 0));
}
}
boardHistory.push(board);
}
function mouseClicked() {
for (var y = 0; y < boardSize; y++) {
for (var x = 0; x < boardSize; x++) {
board[y * boardSize + x].colour = changer;
}
}
var play = true;
if (boardHistory.length >= 3) {
if (board == boardHistory[(boardHistory.length - 3)]) {
play = false;
}
}
if (play) {
turn = !turn;
boardHistory.push(board);
console.log("played");
} else {
console.log("undid illegal play, " + (boardHistory.length - 3));
console.log(boardHistory[(boardHistory.length - 3)]);
}
console.log(board);
changer++;
}
function Piece(x, y, colour) {
this.x = x;
this.y = y;
this.colour = colour;
this.arrayNum = this.y * boardSize + this.x;
}
var turn;
var boardSize;
var board;
var boardHistory;
var changer;
function setup() {
createCanvas(400, 400);
boardSize = 8;
turn = false;
board = [];
boardHistory = [];
changer = 0;
for(var y = 0; y < boardSize; y++){
for(var x = 0; x < boardSize; x++){
board.push(new Piece(x,y,0));
}
}
boardHistory.push(board);
}
function mouseClicked(){
for(var y = 0; y < boardSize; y++){
for(var x = 0; x < boardSize; x++){
board[y*boardSize+x].colour = changer;
}
}
var play = true;
if(boardHistory.length >= 3){ if(board == boardHistory[(boardHistory.length-3)]){ play = false; } }
if(play){
turn = !turn;
boardHistory.push(board);
console.log("played");
} else {
console.log("undid illegal play, ");
}
changer++;
}
function Piece(x, y, colour) {
this.x = x;
this.y = y;
this.colour = colour;
this.arrayNum = this.y*boardSize+this.x;
}
<!DOCTYPE html>
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/addons/p5.sound.min.js"></script>
<link rel="stylesheet" type="text/css" href="style.css">
<meta charset="utf-8" />
</head>
<body>
<script src="sketch.js"></script>
</body>
</html>
I believe that the problem that you are facing is in 2 different places:
boardHistory.push(board);
and
if (board == boardHistory[(boardHistory.length - 3)])
Eventhough you are modifying in the function mouseclicked the value of board, the variable contains the reference of the object, and not a copy of it. So if you make a change in one place you will see it in another place.
I think it will be more clear with an example:
var board = [1,2,3]
var boardHist = []
boardHist[0] = board; //This is similar of what you are doing
console.log(board == boardHist[0]); //Obviously we are getting true
board[0] = 5; //Now we change the first value of board
console.log(board == boardHist[0]); //This is still true
console.log(boardHist[0]); //We will get [5,2,3]

How to generate random divs but not overlap

I want to generate random divs but not overlap with JavaScript.
Just like this:
random div example
But when the number of DIVS gets larger the browser will be blocked!
Then I use the Web Workers to generate the random divs,the browser will be blocked too.
here is my main js code:
self.onmessage = function(e){
var itemslength = e.data;
console.log(itemslength);
var position = [];
for(var i = 0 ; i < itemslength ; i++){
var length = position.length;
if(length == 0){
x = 900*Math.random();
y = 400*Math.random();
var relxy = [x,y];
position.push(relxy);
}else{
var flag = true;
x = 900*Math.random();
y = 400*Math.random();
do{
console.log('RUNNING!!');
x = x + 50;
y = y + 50;
var relxy = [x,y];
for(var j = 0 ; j < length ; j++){
var x1 = position[j][0];
var y1 = position[j][1];
var z = (x - x1)*(x - x1) + (y - y1)*(y - y1);
if(z > 10000){
flag = flag && true;
}else{
flag = flag && false;
}
}
}while(!flag);
position.push(relxy);
}
}
console.log('FINSHED!!');
postMessage(position);
};
<script>
var worker = new Worker('./js/bubbleworker.js');
var itemslengh = $('.items').length;
worker.postMessage(itemslengh);
worker.onmessage = function(data){
for(var i=0;i<data.data.length;i++){
var x = data.data[i][0];
var y = data.data[i][1];
$('.items:eq(' + i + ')').css({
'position':'absolute','left':x + 'px','top':y + 'px'
})
}
}
</script>
Am i right?
Someone who has a better idea? Thanks!

Reset values Issue

Building a dice game and you get 3 rolls. Once you finish your turn i'm trying to have a "reset" button that will reset the values back to the original spot so the "next person" can play. The values reset as I expected but when I "roll" none of the functions are taking place and i'm pretty new in js so i'm not sure what the problem is.
var playerScore = document.getElementById('firstPlayerScore');
var rollButton = document.getElementById('roll_button');
var dice1 = new dice(1);
var dice2 = new dice(2);
var dice3 = new dice(3);
var dice4 = new dice(4);
var dice5 = new dice(5);
var diceArray = [dice1, dice2, dice3, dice4, dice5];
var cargo = 0;
var numOfRolls = 0;
var cargoButton = document.getElementById('cargo');
var canHaveCargo = false;
function restart(){
dice1 = new dice(1);
dice2 = new dice(2);
dice3 = new dice(3);
dice4 = new dice(4);
dice5 = new dice(5);
diceArray = [dice1, dice2, dice3, dice4, dice5];
cargo = 0;
numOfRolls = 0;
canHaveCargo = false;
addGlow();
updateDiceImageUrl();
document.getElementById("dice1").classList.remove('glowing');
document.getElementById("dice2").classList.remove('glowing');
document.getElementById("dice3").classList.remove('glowing');
document.getElementById("dice4").classList.remove('glowing');
document.getElementById("dice5").classList.remove('glowing');
}
//dice object
function dice(id){
this.id = id;
this.currentRoll = 1;
this.previousRoll = 1;
this.isSelected = false;
this.diceImageUrl = "img/dice/dice1.png";
this.roll = function(){
this.previousRoll = this.currentRoll;
this.currentRoll = getRandomRoll(1, 6);
}
}
//returns an array of all dice that are not currently selected so they can be rolled.
function getRollableDiceList(){
var tempDiceList = [];
for(var i = 0; i < diceArray.length; i++){
if(!diceArray[i].isSelected){
tempDiceList.push(diceArray[i]);
}
}
return tempDiceList;
}
// gets a random number between min and max (including min and max)
function getRandomRoll(min,max){
return Math.floor(Math.random() * (max-min + 1) + min);
}
// calls the roll function on each dice
function rollDice(rollableDiceList){
for(var i = 0; i < rollableDiceList.length; i++){
rollableDiceList[i].roll();
}
}
// updates each dice with the new url for the image that corresponds to what their current roll is
function updateDiceImageUrl(){
for(var i = 0; i < diceArray.length; i++){
var currentDice = diceArray[i];
currentDice.diceImageUrl = "http://boomersplayground.com/img/dice/dice" + currentDice.currentRoll + ".png";
//update div image with img that cooresponds to their current roll
updateDiceDivImage(currentDice);
}
}
//Displays the image that matches the roll on each dice
function updateDiceDivImage(currentDice) {
document.getElementById("dice"+currentDice.id).style.backgroundImage = "url('" + currentDice.diceImageUrl +"')";
}
// returns an array of all
function getNonSelectedDice(){
var tempArray = [];
for(var i = 0; i < diceArray.length; i++){
if(!diceArray[i].isSelected){
tempArray.push(diceArray[i]);
}
tempArray.sort(function(a, b){
return b.currentRoll - a.currentRoll;
});
}
return tempArray;
}
function getSelectedDice(){
var selectedDice = [];
for(var i = 0; i < diceArray.length; i++){
if(diceArray[i].isSelected){
selectedDice.push(diceArray[i]);
}
}
return selectedDice;
}
//boolean variables
var shipExist = false;
var captExist = false;
var crewExist = false;
//checks each dice for ship captain and crew. Auto select the first 6, 5 , 4.
function checkForShipCaptCrew(){
//array of dice that are not marked selected
var nonSelectedDice = getNonSelectedDice();
for(var i = 0; i < nonSelectedDice.length; i++){
//temp variable that represents the current dice in the list
currentDice = nonSelectedDice[i];
if (!shipExist) {
if (currentDice.currentRoll == 6) {
shipExist = true;
currentDice.isSelected = true;
}
}
if (shipExist && !captExist) {
if (currentDice.currentRoll == 5) {
captExist = true;
currentDice.isSelected = true;
}
}
if (shipExist && captExist && !crewExist) {
if (currentDice.currentRoll == 4) {
crewExist = true;
currentDice.isSelected = true;
canHaveCargo = true;
}
}
}
}
function addGlow(){
var selectedDice = getSelectedDice();
for (var i = 0; i < selectedDice.length; i++){
var addGlowDice = selectedDice[i];
var element = document.getElementById('dice' + addGlowDice.id);
element.className = element.className + " glowing";
}
}
function getCargo(){
var cargo = 0;
var moreDice = getNonSelectedDice();
if (canHaveCargo){
for(var i=0; i < moreDice.length; i++){
cargo += moreDice[i].currentRoll;
playerScore.innerHTML = 'You have got ' + cargo + ' in ' + numOfRolls + ' rolls!';
}
} else {
alert("You don't have Ship Captain and the Crew yet!");
}
}
rollButton.addEventListener('click', function(){
//generate rollable dice list
if (numOfRolls < 3) {
var rollableDiceList = getRollableDiceList();
//roll each dice
rollDice(rollableDiceList);
//update dice images
updateDiceImageUrl();
getNonSelectedDice();
// //auto select first 6, 5, 4 (in that order)
checkForShipCaptCrew();
addGlow();
// //adds a red glow to each dice that is selected
numOfRolls++;
}
});
cargoButton.addEventListener('click', getCargo);
var startButton = document.getElementById('restart');
startButton.addEventListener('click', restart);
http://boomer1204.github.io/shipCaptainCrew/
Here is a link to the live game since it's the only way I can describe the problem since I don't know what's not working. If you roll the dice a couple times the dice will get a blue border and be "saved" according to the rules. Now after you hit th restart button that doesn't happen anymore.
Thanks for the help in advance guys
Just add this to your restart()
function restart(){
...
shipExist = false;
capExist = false;
crewExist = false;
...
}
It's hard to replicate without a fiddle, but it seems that you are adding and removing the 'glowing' class using separate processes. Have you tried adding the glowing class the same way you are removing it?
element.classList.add("glowing")
See an example within a fiddle: https://jsfiddle.net/5tstf2f8/

Drawing multiple random canvas images in a loop

I'm trying to draw a grid with random images assigned to each square. I'm having trouble with the draw sequence and potentially closure issues with the Javascript variables. Any help is appreciated.
var tileSize = 30;
var drawCanvasImage = function(ctx,tile,x,y) {
return function() {
ctx.drawImage(tile,x,y);
console.log("x = " + x + "/ y = " + y);
}
}
function textures(ctx) {
var grass = new Image();
var sea = new Image();
var woods = new Image();
for (var i=0; i<=10; i++) {
for (var j=0; j<=20; j++) {
rand = Math.floor(Math.random()*3 + 1);
x = i * tileSize;
y = j * tileSize;
if (rand == 1) {
grass.onload = drawCanvasImage(ctx,grass,x,y);
} else if (rand == 2) {
sea.onload = drawCanvasImage(ctx,sea,x,y);
} else {
woods.onload = drawCanvasImage(ctx,woods,x,y);
}
}
}
grass.src = "textures/grass.png";
sea.src = "textures/sea.png";
woods.src = "textures/woods.png";
}
//function called by the onload event in the html body tag
function draw() {
var ctx = document.getElementById("grid").getContext('2d');
grid(ctx); //a function to draw the background grid - works fine
textures(ctx);
}
The current result is three drawn tiles, all at the position of x = 300 (equivalent to the i loop of 10 * the tileSize of 30) and a random y position.
After following a lead and accounting for (maybe?) closure issues by creating the variable drawCanvasImage, I at least got those three tiles to draw.
----Edit----
Working Code - Revision 2:
function randomArray() {
for (var i=0; i<=(xValue/tileSize); i++) {
terrainArray[i] = [];
for (var j=0; j<=(yValue/tileSize); j++) {
rand = Math.floor(Math.random()*4 + 1);
if (rand == 1) {
terrainArray[i][j] = 3;
} else if (rand == 2) {
terrainArray[i][j] = 2;
} else if (rand == 3) {
terrainArray[i][j] = 1;
} else {
terrainArray[i][j] = 0;
}
}
}
}
var drawTerrain = function(ctx,tile,landUseValue) {
return function() {
for (var i=0; i<=(xValue/tileSize); i++) {
for (var j=0; j<=(yValue/tileSize); j++) {
if (terrainArray[i][j] == landUseValue) {
ctx.drawImage(tile,i*tileSize,j*tileSize);
}
}
}
}
}
function textures(ctx) {
var grass = new Image();
var sea = new Image();
var woods = new Image();
var desert = new Image();
grass.onload = drawTerrain(ctx,grass,3);
sea.onload = drawTerrain(ctx,sea,0);
woods.onload = drawTerrain(ctx,woods,2);
desert.onload = drawTerrain(ctx,desert,1);
grass.src = "textures/grass.png";
sea.src = "textures/sea.png";
woods.src = "textures/woods.png";
desert.src = "textures/desert.png";
}
You're rewriting the onloads of the three images in every iteratiom. So, it will only execute the last-added onload f or every image.
Suggestion: run your drawing method only after the thred are loaded(and them just call drawCanvasImage every iteration without an .onload=)
Even better:store the randoms in an array, have each image independantly walk through the array on load and add copies of only itself wherever applicable .
Improvement to rev 2
function randomArray() {
for (var i=0; i<=(xValue/tileSize); i++) {
terrainArray[i] = [];
for (var j=0; j<=(yValue/tileSize); j++) {
rand = Math.floor(Math.random()*4 + 1);
terrainArray[i][j] = 4-rand;
//OR: replace above two lines with terrainArray[i][j]=Math.floor(Math.random()*4 + 1);. There's no need to have them in exactly reverse order.
}
}
}
var drawTerrain = function(ctx,tile,landUseValue) {
return function() {
for (var i=0; i<=(xValue/tileSize); i++) {
for (var j=0; j<=(yValue/tileSize); j++) {
if (terrainArray[i][j] == landUseValue) {
ctx.drawImage(tile,i*tileSize,j*tileSize);
}
}
}
}
}
function textures(ctx) {
var grass = new Image();
var sea = new Image();
var woods = new Image();
var desert = new Image();
grass.onload = drawTerrain(ctx,grass,3);
sea.onload = drawTerrain(ctx,sea,0);
woods.onload = drawTerrain(ctx,woods,2);
desert.onload = drawTerrain(ctx,desert,1);
grass.src = "textures/grass.png";
sea.src = "textures/sea.png";
woods.src = "textures/woods.png";
desert.src = "textures/desert.png";
}
To make it even more flexible, you could use an array to store the images, and then use length. This way, if you want to add another image, all you have to do is modify the array.
var srcArray=["textures/grass.png","textures/sea.png","textures/woods.png","textures/desert.png"];
var imgArray=[];
var terrainArray=[];
function textures(ctx){
randomArray();
for(var i=0;i<srcArray.length;i++){
imgArray[i]=new Image();
imgArray[i].src=srcArray[i];
imgArray[i].onload=drawTerrain(ctx,i);
}
}
function randomArray() {
for (var i=0; i<=(xValue/tileSize); i++) {
terrainArray[i] = [];
for (var j=0; j<=(yValue/tileSize); j++) {
terrainArray[i][j]=Math.floor(Math.random()*srcArray.length);
}
}
}
var drawTerrain = function(ctx,index) {
return function() {
for (var i=0; i<=(xValue/tileSize); i++) {
for (var j=0; j<=(yValue/tileSize); j++) {
if (terrainArray[i][j] == index) {
ctx.drawImage(imgArray[index],i*tileSize,j*tileSize);
}
}
}
}
}
So now, all you have to do is call terrain(ctx) when you want to load all the images. And, whenever you want to add an image to the list of images, just add it to the array up top. You won't have to dig deeper and modify the random values and whatnot.
It's because every time you do a loop, you assign a new function to [image].onload, overwriting the previous one. That's how you end up with only three images.
This should work:
if (rand == 1) {
grass.addEventlistener('load', drawCanvasImage(ctx,grass,x,y), false);
} else if (rand == 2) {
sea.addEventlistener('load', drawCanvasImage(ctx,sea,x,y), false);
} else {
woods.addEventlistener('load', drawCanvasImage(ctx,woods,x,y), false);
}
Here you just add a new listener for every loop.

Categories

Resources