I’ve used the procedural generation tutorial to make it randomize how many missile trucks and houses there are but I need a third tile, being empty. When I tried to implement this, it came up with errors. How do I properly implement a third tile type? The tutorial is here, http://developer.playcanvas.com/en/tutorials/procedural-levels/
This question does not states exact problem, nor shares the link to simple project that replicates the problem.
Literally, impossible to answer.
I’m trying to make it to where it will randomly select one of three tmplates pet tile, but whenn I changed “template1 : template2” to “template1 : template2 : template3” it came up with errors. How am I supposed to make it choose between three templates? https://playcanvas.com/project/448323/overview/global-nuclear-war
I’m guessing you are referring to this line of code:
var tile = (Math.random() > 0.8) ? house : MissileDefense;
This is known as a Conditional (ternary) operator and is basically a shorthand if statement. It is the equivalent of:
var tile;
if (Math.random() > 0.8) {
tile = house;
else {
tile = MissleDefence;
}
What you need is to set a range of values for each tile type for the generator to use. E.g. 0 > 0.5 for template1, 0.5 > 0.75 for template2 and 0.75 > 1 for template3.
I tried the below code but it gave me the error “Cannot read property ‘clone’ of undefined”.
for (var y = 0; y < this.numTilesY; y++) {
for (var x = 0; x < this.numTilesX; x++) {
// Pick a tile at random, with grass more likely than a house
var tile;
if (0 > Math.random() > 0.5) {
tile = Nothing;
}
if (0.5 > Math.random() > 0.9) {
tile = house;
}
if (0.9 > Math.random() > 1) {
tile = MissileDefense;
}
// Clone the tile
var e = tile.clone();
How do I fix? I’m totally clueless on this one.
The error is basically saying tile is null so you need to recheck your logic.
The only way for tile to be null is if it never enters any of the if statements. So double check your code and consider the possibilities on how the code doesn’t enter any of the if statements.
What ways can you debug this to understand what is happening?
Well, I no longer get errors, but now it just spawns in a butt ton of houses.
I’m looking at the code for the project and it still looks the same with the same problem as before. Have you changed it since my last reply or using a different project?
I have indeed changed it, the capitalization was messed. I dunno any other problems.
Your code still has problems and I have just noticed something in the snippet you posted before:
if (0 > Math.random() > 0.5)
I actually don’t know how that evaluates as that is saying ‘if 0 is greater than Math.random() is greater than 0.5’ which doesn’t make sense.
You need to have another look at Logical Operators and recheck the code.
It is also worth noting that every time you call Math.random(), it generates a new random number. So on the first call, it may be 1, second call, it may be 0.1 and on the third it may be 0.5 and therefore the code flow never enters any of the if statements to assign a template to the variable tile.
I changed the code to.
for (var y = 0; y < this.numTilesY; y++) {
for (var x = 0; x < this.numTilesX; x++) {
// Pick a tile at random, with grass more likely than a house
var tile;
if (0 < number < 0.5) {
tile = nothing;
}
if (0.5 < number < 0.9) {
tile = house;
}
if (0.9 < number < 1) {
tile = MissileDefense;
}
// Clone the tile
var e = tile.clone();
// Set the world position of the cloned tile. Note that because
// our tiles are 10x10 in X,Z dimensions, we have to multiply
// the position by 10
e.setPosition((x - this.numTilesX / 2) * 10, 0, (y - this.numTilesX / 2) * 10);
// Add the tile to the scene's hierarchy
this.app.root.addChild(e);
But now it spawns a bunch of missile trucks and one house in the center.
As mentioned in the last reply, look at logical operators. The if statements are not correct in the code.
Also, in the project you are calling Math.random only once. This means that you are always checking against the same number.
Take a step back and look at what the code you have written is doing and compare it to what you are trying to achieve. It feels like you are rushing this without taking the time to understand the code you are using.
I changed the code again according to the logical operators page and how a felt it would work but it gives me the old error “Cannot read property ‘clone’ of undefined”. I dunno what to do at this point.
for (var y = 0; y < this.numTilesY; y++) {
for (var x = 0; x < this.numTilesX; x++) {
// Pick a tile at random, with grass more likely than a house
var tile;
if (0 < number1 && number1 < 0.5) {
tile = nothing;
}
if (0.5 < number2 && number2 < 0.9) {
tile = house;
}
if (0.9 < number3 && number3 < 1) {
tile = MissileDefense;
}
// Clone the tile
var e = tile.clone();
// Set the world position of the cloned tile. Note that because
// our tiles are 10x10 in X,Z dimensions, we have to multiply
// the position by 10
e.setPosition((x - this.numTilesX / 2) * 10, 0, (y - this.numTilesX / 2) * 10);
// Add the tile to the scene's hierarchy
this.app.root.addChild(e);
}
}
You have to debug and learn to solve problems. It is mandatory skill for a developer of any level.
Start from debugging - http://developer.playcanvas.com/en/user-manual/scripting/debugging/
Taking your code in full here:
var number1 = Math.random();
var number2 = Math.random();
var number3 = Math.random();
// initialize code called once per entity
Generate.prototype.initialize = function() {
// We've created a couple of templates that are our world tiles
// In the Editor hierarchy, we have disabled the templates because
// we don't want them to be visible. We just want our generated
// world to be visible
var templates = this.app.root.findByName('Templates');
var MissileDefense = templates.findByName('MissileDefense');
var house = templates.findByName('House');
var nothing = templates.findByName('Nothing');
for (var y = 0; y < this.numTilesY; y++) {
for (var x = 0; x < this.numTilesX; x++) {
// Pick a tile at random, with grass more likely than a house
var tile;
if (0 < number1 && number1 < 0.5) {
tile = nothing;
}
if (0.5 < number2 && number2 < 0.9) {
tile = house;
}
if (0.9 < number3 && number3 < 1) {
tile = MissileDefense;
}
// Clone the tile
var e = tile.clone();
// Set the world position of the cloned tile. Note that because
// our tiles are 10x10 in X,Z dimensions, we have to multiply
// the position by 10
e.setPosition((x - this.numTilesX / 2) * 10, 0, (y - this.numTilesX / 2) * 10);
// Add the tile to the scene's hierarchy
this.app.root.addChild(e);
}
}
};
Global scope gets executed first so number1, number2 and number3 are going to be assigned random numbers.
Then initialize() will be called at some point during the scene load and we enter the for loop. In that for loop, the values of number1, number2 and number3 are never going to change so you are ALWAYS creating the same tile for the whole grid.
Even worse, if the random number generates the following values:
number1 = 0.6;
number2 = 0.3;
number3 = 0.1;
Can you see what would happen in that loop?
Like I said before, take a step back and understand the logic flow and go line by line either with the debugger or in your head on what the code is doing so you can fix it properly.