how to use the 'map' function using Brackets and p5.js? - javascript

I'm currently taking a course on intro to computer programming. It's an online course and doesn't have much help when you're stuck.
I'm using Brackets and p5.js.
I unfortunately don't know how to use the map function, I've tried different possibilities, but so far I haven't been able to solve the question below:
When the mouse button is pressed:
- Use the 'random' function to produce random values ranging from 2 to 14.
- Assign the output to Secure_vault_key0
When the mouse button is released:
- Use the 'random' function to produce random values ranging from 2 to 8.
- Assign the output to Secure_vault_key1
When any key is pressed:
- Make Secure_vault_key2 equal to the value of 'key'
When the mouse button is pressed:
- Use the 'map' function to scale mouseX to values ranging from 14 to 77.
- Assign the output to Secure_vault_key3
When the mouse button is pressed:
- Use the 'map' function to scale mouseY to values ranging from 22 to 76.
- Assign the output to Secure_vault_key4
Whilst the mouse is being dragged:
- Use the 'map' function to scale mouseX to values ranging from 14 to 80.
- Assign the output to Secure_vault_key5
This time you'll need to create the relevant event handlers yourself.
There are many possible ways of investigating this case, but you
should use ONLY the following commands:
- The assignment operator aka. the equals sign !
- mouseX, mouseY
- key, keyCode
- random
- map
*/
//declare the variables
var Secure_vault_key0;
var Secure_vault_key1;
var Secure_vault_key2;
var Secure_vault_key3;
var Secure_vault_key4;
var Secure_vault_key5;
function preload()
{
//IMAGES WILL BE LOADED HERE
}
function setup()
{
createCanvas(512,512);
//initialise the variables
Secure_vault_key0 = 0;
Secure_vault_key1 = "";
Secure_vault_key2 = "";
Secure_vault_key3 = 0;
Secure_vault_key4 = 0;
Secure_vault_key5 = 0;
}
///////////////////EVENT HANDLERS///////////////////
//Create event handlers here to open the safe ...
function mouseDragged()
{
console.log("mouseDragged", mouseX, mouseY);
Secure_vault_key5 = map(mouseX, 14, 80);
}
function mousePressed()
{
console.log("mousePressed");
Secure_vault_key0 = random(2,14);
Secure_vault_key3 = map(mouseX, 14, 76);
}
function keyPressed()
{
console.log("keyPressed");
Secure_vault_key2 = key;
}
function mouseRealesed()
{
console.log("mouseReleased");
Secure_vault_key1 = random(2,8);
}
///////////////DO NOT CHANGE CODE BELOW THIS POINT///////////////////

Check out the p5.js reference page for map() : https://p5js.org/reference/#/p5/map
It looks like you're only using three parameters in your map functions, and it requires five (with an optional sixth parameter). The five necessary parameters are as follows (in this order):
variable you want to map the value of (in your case mouseX)
the current minimum of that value (if you're working with mouseX, you most likely want to use zero)
the current maximum of that value (again, if you're working with mouseX, you probably want to use the width of your canvas here, which you can do using the built in width variable or hardcoding in the value)
the new minimum value you want to be stored in one of your Secure_vault variables
the new maximum value you want
It might seem silly or redundant that you need to specify the current maximum and minimum of a built-in variable like mouseX, but it's just one of those programming things where the computer demands as much explicit instruction as possible in order to properly execute your instructions.
Look at the second example on the reference page linked above for a good example of using the map() function with mouseX. And if you're going to be working in p5.js beyond this project these reference pages are a really great place to look for answers to all kinds of questions!

update!! I just corrected in below code. use height and width
/*oh I also met such issues, I know I have to define five arguments, I just can't understand what the second and third arguments should be, I wrote 0,mouseY/X, but it's not correct.
only SecretStoreCombination0 is correct, I've used up the chances today, I will try tomorrow!*/
function keyReleased(){
SecretStoreCombination0 = random()*10+1;
SecretStoreCombination2 = key;
}
function mouseReleased(){
SecretStoreCombination1 = map(mouseY,0,height,3,13);
SecretStoreCombination4 = map(mouseY,0,height,20,79);
}
function mousePressed(){
SecretStoreCombination3= map(mouseX,0,width,6,69);
SecretStoreCombination5= map(mouseY,0,height,16,73);
}

Related

I want to push unnamed or dynamically named objects (class instances) to an array

Context: "Umo Space" is a javascript game I'm working on Umo Space is a javascript game I'm working on, with a class "Umo" (universal moving object) which includes the needed variables and member functions to do stuff with an object moving around in 2d space. Currently the game world has predefined planets and enemy ships, but I'm trying to create randomized systems. In doing so, I need to fill the "planets" array with a random number of "Umo" instances. I thought I could just push() an unnamed new "Umo" instance into the array, and it seems that I can when I create the first Umo (the sun basically) in the center of the system before the loop for the randomized planets. However, inside the loop, I do what seems to be the same thing, and shortly thereafter I get an error when I try to use member functions or assign to member variables of the Umo instance.
Uncaught TypeError: Cannot read property 'setorbit' of undefined
at System.randomplanets (UmoSpace68.html:567)
at UmoSpace68.html:591
If I comment out that particular line (which uses a member function of Umo), I instead will get an error for assigning the ".name" or ".parentid" member variables. I thought maybe I needed to assign the Umo dynamic variable names using an "eval()" rather than pushing it unnamed, but that didn't fix anything (and seems to be an... unfavored practice). In any case, it seems like the push() failed without generating an error message, inside the loop.
This problem also somehow causes another error downstream, in seemingly unrelated code, un-defining my "ships" array (not a member variable of anything, just an array of predefined "Umo"s).
UmoSpace68.html:789 Uncaught ReferenceError: Cannot access 'ships'
before initialization
at update (UmoSpace68.html:789)
If I comment out the function call "testsystem.randomplanets();" all the problems disappear, and all of the Umo functionality is used elsewhere without issue, so the problem is almost certainly in the randomplanets() member function or at least the "System" class (which is not yet used meaningfully).
Here is the smallest relevant code snippet I could muster:
class System{
constructor(index, name){
this.index = index; //integer identifying system
this.name = name; //name of system for display
this.planets = []; //list of planets (to be generated)
this.ships = []; //list of ships (to be generated)
this.bombs = []; //list of bombs used in system
this.difficulty = 1; //Scales ship generation attributes
}
randomplanets(){
var numplanets = Math.floor(Math.random()*16+2);//random number of planets, 2-17
var orbitradius = 0; //randomized in the loop
var planetsize = 0; //randomized in the loop
this.planets.push( new Umo(0,0,Math.floor(Math.random()*3000+1000), "orange") ); //make the sun
this.planets[0].name = this.name; // Star name is same as system name
i=0;
while (i<numplanets-1){
i=i+1; //planets[0] is already the sun, so we can skip index 0;
orbitradius = Math.floor( (Math.random()*500)*(Math.random()*500) + 2000); //Minimum radius 2000, 0-500^2 more concentrated in center
planetsize = Math.floor( Math.random()*1000 + 80); //Even distribution of sizes, 80-1080
this.planets.push( new Umo(0,0,planetsize, randcolor() ) );//this is where the planet gets added to the array
this.planets[i].name = randname(4);//random 4 character name
this.planets[i].setorbit(this.planets[0], orbitradius, Math.random()*6.28, 1);
this.planets[i].parentid = 0; //establishes star (planet[0] as parent planet
//this.randommoons(i);
}
}
randommoons(index){//index is of planet
var nummoons = Math.floor(Math.random()*planets[index].s/150 )//Planets < 150 in size have 0 chance of a moon, planet 300 in size has 50% chance of 1 moon, etc.
var moonsize = 0; //randomized in loop
var moonorbitr = 0;//randomized in loop
var moonindex = 0; //set in loop
i = nummoons;
while (i>0){
i=i-1;
moonsize = Math.floor(Math.random()*this.planets[index].s/3+10);//radius is 10 plus up to 1/3 of parent planet
moonorbitr = Math.floor(this.planets[index].s*(Math.random()*3+1.5)); //orbit radius is 1.5x parent planet radius + up to 3x parent planet radius
moonindex = this.planets.length;
this.planets.push( new Umo(0,0,moonsize, randcolor()) );
this.planets[moonindex].name = randname(4);
this.planets[moonindex].parentid = index;
this.planets[moonindex].setorbit(this.planets[index],moonorbitr,Math.random()*6.28, 1);//orbit direction is 1, not random
}
}
}//end of system class////////////////////////////////////////////////////////////////////////////////////////////////////////////////
let testsystem = new System(2,"thetestsystem");
testsystem.randomplanets();
It seems the problem was not in the randomplanets() function after all. #Sal suggested changing the while loop to a for loop, which DID fix the problem, but more importantly led me to later discover a more fundamental problem while developing random ship generation. I eventually isolated the problem to the randname(namelength) function, which initiated it's own while loop with:
i=namelength;
which i changed to
var i=namelength;
I think that leaving out the "var" caused the randname function to operate on the "i" immediately outside the randname function, inside the randomplanets function (perhaps globally as well). I think that using a for loop must have protected the "i" used in the for loop from this scope error.
Moral of the story: Remember to declare your iterator with a "var" each time you use it, especially if you habitually use i,j,k, etc.

How to get a circle to move when you click on it in javascript?

I'm making a whack-a-mole game based on a 3x3 grid for one of my classes but i'm having trouble getting the mole(an ellipse made using p5.js) to move to a different grid square on click. I want it to automatically move after 7 seconds which i achieved using function sleep(milliseconds), but if the player clicks the mole before the 7 seconds is up then I want it to switch grid squares right then. This is my code for mousePressed and moveCircle.
function mousePressed() {
var distance = int(dist(mouseX, mouseY, moleX, moleY));
if(distance <= circleDiameter/2 ) {
moveCircle();
score += 1;
}
document.getElementById('playerScore').innerHTML=score;
}
function moveCircle(){
var randomX = [110, 260, 410];
var randomY = [95, 245, 395];
var moleX = random(randomX);
var moleY = random(randomY);
}
Your sleep() function is not how you should handle timing in P5.js, or in JavaScript in general.
Your sleep() function causes your program to become completely unresponsive, which is bad for a lot of reasons. One problem is that your event code will not trigger, which is the problem you're seeing.
Instead, you need to use the millis() function or the frameCount variable to handle your timing without blocking your whole program. Here's a small example:
function setup() {
createCanvas(200,200);
background(32);
}
function draw(){
// 60 frames is 1 second
if(frameCount % 60 == 0){
ellipse(random(width), random(height), 25, 25);
}
}
This code uses the frameCount variable along with the % modulus operator to check whether 1 second has elapsed. In other words, this program draws a circle every second.
You need to do something similar to move your mole, which will allow your event code to be fired even while the mole is "waiting".
int(dist(mouseX, mouseY, moleX, moleY))
This int keyword does not make sense. If you want it to be a whole number, use the Math.round() function (or just round() in p5js).
Try console.loging the distance variable.

How do I use the AddForce function? It won't work

I don't know why the sprite wont jump... I want to use AddForce() instead of directly changing the velocity.
var trump;
function Start() {
// Assigns the Rigidbody to a variable
trump = GetComponent(Rigidbody2D);
// Variable Switches:
}
function FixedUpdate() {
GetComponent.<Rigidbody2D>().velocity.x = Input.GetAxis("Horizontal") * 10;
if (Input.GetKeyDown(KeyCode.UpArrow)) {
GetComponent.<Rigidbody2D>().AddForce(Vector2(0, 10));
}
}
instead of
GetComponent.<Rigidbody2D>().AddForce(Vector2(0, 10));
try this
GetComponent.<Rigidbody2D>().AddForce(Vector2.up * 10);
Hope this works
Try this:
GetComponent.<Rigidbody2D>().AddForce(Vector2(0, 10), ForceMode2D.Impulse);
This will launch him into the air in an instant. I believe the problem is that you're using ForceMode2D.Force (by default), which expects to be called multiple times over several ticks. For example, ForceMode2D.Force could be used to stay on when pushing an object like a car forward.
You may consider changing this function in the future to provide smoother jumping. One good method would be applying force according to a sin function period.

The logic of multiple travelling animations in javascript

I have an image of a bug. I want to make 5 copies of that image fly in from the side of the screen and bounce around the screen and bounce off the sides. I want them to all have different starting positions and different directions.
so I made some a global variables
var flyVar;
var flySpeed = 5;
var widthMax = 0;
var heightMax = 0;
var xPosition = 0;
var yPosition = 0;
var xDirection = "";
var yDirection = "";
var bugFly;
var count = 1;
var bug = "bug";
I have a function called setBugs() that I use to set the value of widthMax and heightMax depending on the size of the users screen.
I have a bugStartingPlace function to set the initial starting place for each bug. I won't post the whole function but it does the same for "bug1" through "bug5", giving them different values.
function bugStartingPlace(bugName) {
//Accepts string as argument and sets the starting position and starting direction of each bug.
if (bugName == "bug1") {
xPosition = 0;
yPosition = 100;
xDirection = "right";
yDirection = "up";
}
}
I have a function called flyBug() that does the animation and sets the position of the image. It consists of a bunch of statements like this. I know it works because I can make it work with 1 bug. The problem is doing it with 5 bugs.
function flyBug() {
if (xDirection == "right" && xPosition > (widthMax - document.getElementById("bugImage").width - flySpeed))
xDirection = "left";
<!--More flow control statements are here-->
document.getElementById("bug1").style.left = xPosition + "px";
document.getElementById("bug1").style.top = yPosition + "px";
<!-- More statements are here that set the position of the image -->
}
So, I need some way to get the animation going with the body onload() event. One problem is that setInterval does not allow functions that contain parameters. So I can't put multiple statements in the body onload event that pass "bug1" as a parameter to this function, "bug2" as a parameter to this function and so on. That's why I made the global count variable. That way, any time I need to change the name of the bug, I change the name of count and then do
bug = bug + count;
But that adds a lot of complexity. I need the name of the bug for the bugStartingPlace() function, so I need to change the value of count and also change the value of bug before I use that function. Once I use the bugStartingPlace() function, that changes the value of the global variables. Then I need to use flyBug() before I change the value of bug again.
I guess one of the problems is that I'm using global variables for direction and position even though I have multiple bugs. It works fine for one bug but not for multiple bugs.
Can anyone give me tips on how the logic of this program should work?
setInterval allows, like setTimeout, the use of parameters in the function BUT:
setInterval(funcName(param1,param2...), 100);
wont work. Youll get it to work like that:
var func = function () { funcName(param1,param2..); }
setInterval(func, 100);
To understand that part of javascript, read through dougles crockfords explanation of functions, he tells about this very clear and deep. Link to a video of him
EDIT: Sry i understood your question wrong...
The problem why it wont work is, like you figured out the global vars. You could just make bug an object. His actions will then be methods, which can contain a function and so on. If you then initialize a new bug (you can do this a thousand times then), all the vars stay in the object, without conflicting each other. This is a secure way to provide solidness of your code.
You could do it very simple, with nested functions.
Another way would be, to send the name of the bug vie parameter to the, for example, fly function. And the only work in that function with the parameter given to it.

Javascript bit map for simple collision detection

I need help/advice for improving/commenting my current design please :)
This relates to collision detection in a simple game: Dynamic bodies (moving ones) might collide with static bodies (i.e. ground, walls). I'm porting my Obj-C model to Javascript and am facing memory/performance questions as to my way of implementing this.
I'm using a very basic approach: An array of arrays represents my level in terms of physic opacity.
bit set to 0: Transparent area, bodies can go through
bit set to 1: Opaque area, bodies collide
Testing the transparency/opacity of a pixel simply goes as follows:
if (grid[x][y]) {
// collide!
}
My knowledge of JS is pretty limited in termes of performance/memory and can't evaluate how good this approach is :) No idea of the efficiency of using arrays that being said.
Just imagine a 1000-pixel wide level that's 600px high. It's a small level but this already means an array containing 1000 arrays each containing up to 600 entries. Besides, I've not found a way to ensure I create a 1bit-sized element like low-level languages have.
Using the following, can I be sure an entry isn't something "else" than a bit?
grid[x][y] = true;
grid[x][y] = false;
Thanks for your time and comments/advices!
J.
If you have an 1000x600 grid, you can guarantee you have at least 601 arrays in memory (1001 if you do it the other way round).
Rather than doing this, I would consider using either 1 array, or (preferrably) one object with a mapping scheme.
var map = {};
map["1x1"] = 1;
map["1x3"] = 1;
// assume no-hits are empty and free to move through
function canGoIn(x, y) {
return map.hasOwnProperty(x + "x" + y);
};
Alternately;
var map = [];
var width = 600;
map.push(0);
map.push(1);
// etc
function canGoIn(x, y) {
return map[(x * width) + y] == 1;
}
a boolean value won't be stored as just one bit, and that is also true for any other language I know (C included).
If you are having memory issues, you should consider implementing a bitarray like this one: https://github.com/bramstein/bit-array/blob/master/lib/bit-array.js
You will have to make your 2d array into a simple vector and converting your x, y coordinates like this: offset = x + (y * width);
Browsing an array will still lead to a multiplication to evaluate the offset so using a vector is equivalent to arrays.
But I suspect that calling a function (in case your using a bit-array) and doing some evaluations inside will lead to poorer performances.
I don't think you can gain performances and save memory at the same time.

Categories

Resources