For one of my school projects, I have to create a game with Javascript. My Javascript experience is very minimal, and therefore I'm really stuck on how to create multiple levels within my game. With JSON, I load blocks for Mario to walk on:
createBlocks: function () {
console.log('game -> createBlocks');
$.getJSON('js/boxes.json', function (data) {
data.boxes.level1.forEach(function (blockData) {
this.stage.removeChild(this.block.el);
var block = new Block(blockData);
this.block.push(block);
this.stage.addChild(block.el);
}.bind(this));
}.bind(this));
}
With the function "createStars" the game loads another JSON. My goal is to have the game switch to another level with every 5 stars being collected. What is the best way to create this with JSON?
My JSON file for the blocks are created as follow:
{
"boxes": {
"level1": [
{
"x": 0,
"y": 115,
"width": 25,
"height": 25
},
{
"x": 25,
"y": 115,
"width": 25,
"height": 25
}
],
"level2": [
{
"x": 0,
"y": 95,
"width": 25,
"height": 25
}
]
}
}
Please let me know if you need my complete code to answer my question? I can also give a link to the game as it currently is hosted on my own site: http://school.carlavanloon.com/cp/
Furthermore, I'd like the game to stop the time after collecting 20 stars. This will then be the end time for the user of the game.
Many thanks in advance for your reply. And please let me know if I need to give any additional information.
Instead of making your json file around "boxes" you should design the json structure top down,
first load game json, which contains level objects - which contain boxes arrays etc. ie. something like this
var json = {
"game_data": {
"some_global_settings" : {"game_speed": 30, "theme": "dark"},
"level1": {
"boxes": [
{
"x": 0,
"y": 115,
"width": 25,
"height": 25
},
{
"x": 25,
"y": 115,
"width": 25,
"height": 25
}
],
"stars": [
{
"x": 0,
"y": 50,
"width": 25,
"height": 25
},
{
"x": 125,
"y": 120,
"width": 25,
"height": 25
}
],
"player_position" : {"x": 0,"y": 50},
"victory_condition" : {"stars_required" : 5, "time_limit" : "10min"}
},
"level2": {"same structure as above with different data" : 1}
}
}
and then make a level builder function which picks a level object and creates everything in it. To reload a new level, check the number of stars remaining, if its 0, call your createLevel(gamelevel) with n+1 for building the next level.
below is pseudo code sample.
Every time user collects a star, you will check if it was the last star required, and if so, increment the level counter and call level builder function which could be something like this
function buildLevel( levelNr ) {
var gdata = json.game_data["level"+levelNr];
//check if next level exists in game_data object
if (!gdata) {
finishGame();
return false;
}
//next level data exists, so build whats in it
//clear level from previous stuff
clearLevel();//perhaps replace canvas with new one
createBoxes( gdata.boxes);
createStars( gdata.stars);
createPlayer( gdata.player_position);
//everything is ready, add listeners / timers etc, and start the game
}
Related
I am trying to create a slide in Google App Script and then add a text box to this newly created slide. The first call is to the Slides api and the second call is made using inbuilt methods. However, because of the asynchronous nature of these two lines, the 2nd is operating before the 1st and causing an obvious error.
Slides.Presentations.batchUpdate({'requests': requests}, presentationId);
var shape = presentation.getSlideById(newpageId).insertShape(SlidesApp.ShapeType.TEXT_BOX, 0, 0, width, height/4);
My question would be: How to create a callback or use a promise to make the needed adjustments?
I tried a different approach, I grouped all the request in chronological order and it worked:
var requests = [{
'createSlide': {
'objectId': newpageId,
'insertionIndex': current_index,
'slideLayoutReference': {
'predefinedLayout': 'BLANK'
}
}
},
{
"createShape": {
"objectId": `silaComment${questionNumber}${token}`,
"elementProperties": {
"pageObjectId": newpageId,
"size": {
"width": {
"magnitude": 3000000,
"unit": "EMU"
},
"height": {
"magnitude": 3000000,
"unit": "EMU"
}
},
"transform": {
"scaleX": 0.6807,
"scaleY": 0.4585,
"translateX": 6583050,
"translateY": 1673950,
"unit": "EMU"
}
},
"shapeType": "WAVE"
}
},
{
"insertText": {
"objectId": `silaComment${questionNumber}${token}`,
"text": comment + '\nasked by ' + name,
"insertionIndex": 0
}
}];
Slides.Presentations.batchUpdate({'requests': requests}, presentationId);
You could simply wait:
Utilities.sleep();
But this requires estimating the api call execution time.
Apps script currently doesn't support promises. Even if it did, the batchUpdate call to the api doesn't return a promise.
I am trying to adapt the 'simplify polygon' function from the the clipper.js library. I am not sure I understand what is wrong with the following script:
var five_pointed_star = [{
"X": 114.11152626295,
"Y": 22.213863709855
}, {
"X": 114.11262775355,
"Y": 22.214272283475
}, {
"X": 114.1133008867,
"Y": 22.214885143905
}, {
"X": 114.1133008867,
"Y": 22.21619257949
}, {
"X": 114.11164865079,
"Y": 22.216233436852
}, {
"X": 114.11152626295,
"Y": 22.213863709855
}];
var ten_pointed_star = ClipperLib.Clipper.SimplifyPolygon(five_pointed_star, ClipperLib.PolyFillType.pftNonZero);
console.log(ten_pointed_star);
The code however works as expected if I change the five_pointed_star to the following:
var five_pointed_star = [{
"X": 147,
"Y": 313
}, {
"X": 247,
"Y": 34
}, {
"X": 338,
"Y": 312
}, {
"X": 86,
"Y": 123
}, {
"X": 404,
"Y": 124
}];
Any ideas what I am doing wrong?
The polygon uses a path as a parameter, and the path has the following definition in the documentation:
This structure contains a sequence of IntPoint vertices defining a single contour (see also terminology). Paths may be open and represent a series of line segments bounded by 2 or more vertices, or they may be closed and represent polygons. Whether or not a path is open depends on context. Closed paths may be 'outer' contours or 'hole' contours. Which they are depends on orientation.
And IntPoint reads:
The IntPoint structure is used to represent all vertices in the Clipper Library.
So this means that the numbers you need to give it, have to be Integers - whereas you were trying to use floating point numbers, or floats for short.
So if you use Integers it should always work fine, if your calculations return floats, you can use rounding methods like floor() to get rid of the values after the dot.
I'm making an incremental game and I have what I want working in a JSFiddle but I can't for the life of me get it to work on my actual website. Here's what happens on my website.
Here's my code for working this out:
SetInterval(function() {
for(var outer in user.upgrades)
{
for(var inner in user.upgrades[outer])
{
loadedUser.upgrades[outer][inner].cost = Math.floor(user.upgrades[outer][inner].cost * Math.pow(user.upgrades[outer][inner].scale, loadedUser.upgrades[outer][inner].owned));
}
}
}, 10);
The loadedUser object and user object:
var costScaling = 1.15;
const user = {
"name": "",
"stats": {
"click": 1,
"level": 1,
"xp": 0,
"melons": 0,
"mps": 0,
},
"upgrades": {
"melons": {
"mash": {
"name": "Mash - 1MPS",
"cost": 50,
"value": 1,
"owned": 0,
"scale": costScaling
}
The loadedUser would be the same as this however in the upgrades.melons in the amount but there would be how many they own.
So, my issue is as you can see in the gyazo is that it turns into a really big number very quickly however on the JSFiddle is exactly what I want and I'm struggling to get it work locally, on the console is the value of user.upgrades which shouldn't even change. If you need anymore code just ask.
I have some JSON that resembles this:
{
"Variable": "Id",
"Stat": 250,
"Value": 2,
"Data": {
"Key1_std": 20,
"Key1_25%": 100,
"Key1_count": 14,
"Key1_75%": 13,
"Key1_mean": 10,
"Key2_std": 20,
"Key2_25%": 100,
"Key2_count": 14,
"Key2_75%": 13,
"Key2_mean": 10,
"Key3_std": 20,
"Key3_25%": 100,
"Key3_count": 14,
"Key3_75%": 13,
"Key3_mean": 10,
},
"Omega": 0.1
}
I need to create a graph that displays only the values for the "*_mean" keys.
How should I go about fetching these specific values from the JSON?
They are randomly spaced throughout the real file. Since JSON is not a regular language, I've avoided regex ... lest my computer be
p͏͔͚̣o͚̤͙̟̟̖ͅss̷̱̣̩̞̟͙e͉̘̩͟s̩͖̹͍s̯͓͍̱͠e̩d̡̯̯̦̣̱ͅͅ b̠̙̗͓y͓̹̳̩̫͎̳͢ ͞C̢͇̹t͎͇h̻͇͜ͅu̻̭͜l͈̝̫u̢̩̹͎̭̫.
Thanks in advance.
You can iterate over keys with object.keys.
Code is like this:
var keys = object.keys(json.Data);
var finalArr = [];
for(i=0;i<keys.length;i++){
if(keys[i].indexOf('mean') > -1){ // mean is part of string
finalArr.push(json.Data[keys[i]]);
}
}
I'm looping through an array of objects called $scope.points which looks like this:
[
{"x": 200, "y": 200, "index": 0}
{"x": 200, "y": 200, "index": 1}
{"x": 200, "y": 200, "index": 2}
]
This is the JS, which loops through $scope.points and saves them using Parse:
var createPanodatas = function() {
console.log('POINTS:', $scope.points)
_.each($scope.points, function(point) {
console.log('INDEX:', point.index)
var Panodata = AV.Object.extend('PanoramaData'),
panodata = new Panodata()
var json = {
'index': point.index,
'x': point.x,
'y': point.y,
'roomModelId': $scope.pano.id
}
panodata.save(json, {
success: function(panodata) {
console.log('Panodata saved.')
},
error: function(panodata, error) {
console.log('Failed to create new pano object, with error message: ' + error.message)
}
})
})
}
The saved items are saved ordered by date but with random index:
[
{
"objectId": "56a1e3dc7db2a2005a15533a",
"index": 1,
"roomModelId": "56a1e3d72e958a00515cfe3e",
"createdAt": "2016-01-22T08:10:04.646Z"
},
{
"objectId": "56a1e3dcc24aa8005415772f",
"index": 0,
"roomModelId": "56a1e3d72e958a00515cfe3e",
"createdAt": "2016-01-22T08:10:04.646Z"
},
{
"objectId": "56a1e3dc816dfa005919182b",
"index": 2,
"roomModelId": "56a1e3d72e958a00515cfe3e",
"createdAt": "2016-01-22T08:10:04.670Z"
},
]
Which confused me since console.log('POINTS:', $scope.points) outputs the items in correct index order:
And console.log('INDEX:', point.index) too:
INDEX: 0
INDEX: 1
INDEX: 2
Why are the items saved with random index? How to save the index in order? (e.g. 0, 1, 2 ...)?
This looks like the items are being saved just fine and with the correct index.
The underscore _.each function will iterate through the array in-order as you would expect, which will also result in the creation of the PanoramaData in the same order.
The crucial bit of information to be aware of is that saving with Parse is an asynchronous process and you will have no guarantees about which actually completes first. Intuitively, you would expect that the saves which are executed first would fulfill their promises first and that will probably be the case, however you still cannot make any guarantees about that.
This doesn't seem to be the case in your example since the data appears to be saved just fine, but if you need to know that they are saved in the exact same order as the array then you can use promise chaining, in particular serial promise chaining.
Again, it looks like the data is being properly set but the creation time is causing concern for you since in your example index 1 and 0 both were created at 2016-01-22T08:10:04.646Z. Unless you have a particular use-case for it, try not to rely too heavily on serial processes.