Hello there,
I’d like to be able to create a level on my own, but I never done that before. So I’d like to post here the idea I worked on before wasting time in fighting the level editor. If the idea seems ok enough to be crafted as a new level, I’d like some tips from experienced users to limit the time I’ll take to implement it.
The level I’m working on is themed on remainder operator, and its specific use in array wrapping. I worked in game, in the CragTag level, with a PotionMaster and the Golden Rod and BossStar 1 in order to create a situation where I have few units walking around in circle. Of course, I ignore Pender totally. The movement of the units would be part of the level (whereas here, I’m stuck with making them move myself, as the player), and no other action would be asked from the player than “this.say” clever sentences. Illustration :
The idea is to cache the array of units in the initialization, and make the units walk in circle. Every time a unit comes close, your hero perform an interaction (say ?) with this unit. As they walk several times around the circle, the player will be introduced to the use of the remainder to circle through the array, wrapping around indexes. The whole level is based on the new concept :
kSoldier=( kSoldier + 1 ) % nSoldiers
The plot would be “We’ll celebrate soon the [XXX] festival ! Your troups need to rehearse their Parade walk ! Tell your soldiers wether they’re too slow or too quick ! We need them to be equally distributed around the circle during the Parade”.
Your units aren’t evenly distributed around the circle, because of the arrFakRnd parameter. The random number (I suggest within -0.2 and +0.2) messes up the positionning of every soldier by a tiny bit. Every time a soldier passes by your hero, your hero will react to tell him/her to adapt their position, based on
closeSolder.pos.y>this.pos.y
I couldn’t make the hero react as “say” in the code below, because it locks my hero and he can’t command the troups in the mean time, and that messes up the whole timing. So I made him moveXY a tinybit left of right depending on the result of the test. In a real level, the player’s hero would “say” instead of moveXY of course. (again limited with ingame engine)
If the reaction of the hero is correct, the level should react by making the arrFakRnd numbers lower and lower in order to be closer and closer to the even distribution :
arrFakRnd [kSoldier] /= - 3 ;
Below is a copy-pastable code you can use in CragTag with a Wizard that can cast GoldStorm and command soldiers.
I hope you will see that your hero goes [left, right , right, right, left, right] during the first round because the arrFakRnd number I chose are : [negative , positive , positive , positive , negative , positive];
I think this concept of circular arrays illustrated with units walking in circle is a good start to create similar levels like this. Two quick examples : What happens if the units walk the other way ? How to check the distance between two units in a circular array ? I think modulo / remainder is tricky stuff for young people, and needs a lot of levels about it in order to even get familiar to it.
Disclaimer, this is a sketch. Don’t pick too much on me ^^. Make it run before anything else. I hope my syntax is somewhat understandable, and my comments are clear enough.
// Initializing variables
var soldierTarget=origPos;
var Pi=3.14159;
// Circle parameters
var origPos={x:39,y:36};
var r=10; // radius
var timeBlock= 2;// number of sec a soldier takes to reach the position of the soldier before him.
// Setting up the level
this.cast("goldstorm");
this.say("Waiting for gold to fall down");
this.wait(10);
loop { // Collecting coins to summon soldiers.
var coins=this.findByType("coin");
if(coins[0]){
this.move(this.findNearest(coins).pos);
}
else {
break;
}
}
this.moveXY(origPos.x+5,origPos.y); // Going near the 0th soldier at start.
this.moveXY(origPos.x+5,origPos.y); // no ice skating when arrived.
while (this.gold>=20) { // Summoning soldiers
this.summon("soldier");
}
var mySoldiers=this.findByType("soldier");
var nSoldiers=mySoldiers.length;
var arrFakRnd=[-0.1,0.2,0.05,0.1,-0.2,0.1]; // This array should be random seeded by the Send button. Numbers within [-0.2 , 0.2 ]
for(var k=0;k<nSoldiers;k++){ // Soldiers walking to their starting positions.
soldierTarget={
x:origPos.x + r*Math.cos(2*Pi*(k+arrFakRnd[k])/nSoldiers),
y:origPos.y + r*Math.sin(2*Pi*(k+arrFakRnd[k])/nSoldiers)
};
this.command(mySoldiers[k], "move",soldierTarget );
}
this.wait(5);
this.say("This setup is the starting setup");
this.say("Starting level now !");
// End of setup
kSoldier=0;
var t0=this.now();
loop {
var t=this.now();
if( (t-t0) % timeBlock<0.01){ // every timeBlock seconds, a new soldier passes by.
// This if statement would be what the player will write to solve the level.
var closeSolder=mySoldiers[kSoldier];
if(closeSolder.pos.y>this.pos.y){
this.moveXY(origPos.x+6, origPos.y); // arrFakRnd[kSoldier]>0
this.moveXY(origPos.x+6, origPos.y); // No ice skating.
//this.say(mySoldiers[kSoldier].id+", Slow down !");
arrFakRnd[kSoldier] /= -3 ; // This would be the level reacting to the "say"
}else{
this.moveXY(origPos.x+7, origPos.y);// arrFakRnd[kSoldier]<0
this.moveXY(origPos.x+7, origPos.y); // No ice skating
//this.say(mySoldiers[kSoldier].id+", Hurry up ! !");
arrFakRnd[kSoldier] /= - 3; // This would be the level reacting to the "say"
}
kSoldier=(kSoldier+1) % nSoldiers; // New concept line. Most important line.
}
for(k=0;k<6;k++){ // This for loop will be taken care of by the level itself.
// This is just making the soldiers walking around in circle at known positions.
soldierTarget={
x:origPos.x+r*Math.cos(2*Pi*((k+arrFakRnd[k])-(t-t0)/timeBlock)/nSoldiers),
y:origPos.y+r*Math.sin(2*Pi*((k+arrFakRnd[k])-(t-t0)/timeBlock)/nSoldiers)
};
this.command(mySoldiers[k], "move",soldierTarget);
}
}