cooperuser / blockade

A minimal but challenging puzzle game, inspired by the ice puzzles in The Legend of Zelda: Twilight Princess.
2 stars 0 forks source link

Level JSON structure #52

Closed grady404 closed 8 years ago

grady404 commented 8 years ago

So I thought about the two different versions of the wiring system for a while, and realized that if you have a lot of inputs/outputs in the same area (for example, if you wanted to make a level that was a maze of doors) it would be impossible to do so using the grid-based wiring system. For this reason I really think you should use the Starbound-esque wiring system, as it would allow for much greater flexibility when creating compact wiring systems. And because of that, I think you should keep the JSON files in a format similar to what they are now, so that you can set the start and end points of wires right next to each other, and wouldn't have to use wire IDs or something weird like that to connect the two points. No, this doesn't go against the entire overhaul, I think the way the objects are stored in-game is fine, but as far as the way objects are saved to the JSON files, I think it should be more similar to how it is currently. So forget the example JSON I AirDropped to you in class; I'll make a new example JSON, and upload it here as soon as I can.

grady404 commented 8 years ago

Alright, here's the new example.json. A few things you might consider changing about it:

grady404 commented 8 years ago

Here's the final example.json. You don't need to worry about everything in here for now. I'll upload another example.json that only shows you the stuff you need to worry about right now.

grady404 commented 8 years ago

Here's example-simple.json, a simplified version of example.json. This is all you should focus on implementing for now. Note that if any of the variables in the data section are missing (e.g. name, creators, creator-score, and flags) the game is prepared to handle that.

cooperuser commented 8 years ago

new2.json.zip Here, check out this idea. It uses a hybrid of both of our systems by having a list of each object, but it has a variable for the class and attribute, where you would enter all other details. I am still considering if I should have the position variable not be under the attribute variable though.

grady404 commented 8 years ago

Hmm... I do like where you're going with that, with the attributes and all, but there are a few problems. First of all, it's not compact enough - I designed my version so that each individual object would be as compact as possible. That's why I like "position": [0, 0] better than "position": {"x": 0, "y": 0}. I also don't think position should be an attribute, since attributes determine characteristics about an object, not information about its position. To put it in non-programming terms, the fact that I have blond hair is an attribute of me, while the fact that I am in my bedroom right now is not. Also, position is something an object must have, while attributes are not (hollow blocks don't need a specified color, for instance).

To make it more compact, I think the color attribute should correspond to a number, not a string. 0 would signify blue, 1 would signify red, 2 would signify green, and 3 would signify orange. In fact, there's another reason I think we should do this besides compactness - what if one of the themes we implement later (see #15) has different colors of blocks/plates/switches? The "main" block color might be purple in one of the themes, and all the block colors might be in a different order, so it makes more sense to simply denote it as a number.

The rotation and state attributes would also be numbers. The state attribute would either be 0 for disabled, or 1 for enabled. The rotation attribute would depend on the object. If the object has four-way rotational symmetry (like a block, plate, or the letter O), there would be no rotation attribute at all. If an object has two-way rotational symmetry (like the letter H), rotation would either be set to 0 or 1. If it has no rotational symmetry (like the letter A), rotation could be 0, 1, 2, or 3, with each new number rotating the object clockwise by 90 degrees.

So here's the final block object for reference: {"class": "Standard", "position": [0, 0], "attributes": {"color": 0}}

There are a couple more problems down at the bottom of the JSON - first of all, where did the data section go? Now those variables are all just piled into a jumbled mess down there... Anyway, the size variable needs to go, completely. You don't need it there. You can determine the size of the level without a specific variable for it, simply by looking at the positions of all the objects on the board and taking the maximum x and y values. Also, "par" is a defunct idea now, since there are two scores (moves and distance). If you look at my example.json above, you'll see that I combined them into something that looks like this: "creator-score": {"moves": 8, "distance": 27}. I called it creator-score because the creator(s) of a level won't know for sure that that's the minimum amount of moves needed to complete the level, so it becomes a sort of challenge for people playing a level to beat the creator's score. Anyway, you should see the data section of my example.json for an idea of what it should look like.

cooperuser commented 8 years ago

I agree with the whole position part not being in attribute, and the rotation part. About the stuff at the bottom of the JSON, I like not having the whole data part, I think it makes it less intuitive because, I mean, its all data... Also I think that par is a better name than creator-score because it IS the par, pars aren't supposed to be unbeatable, Also are these values going to be changing if the score is beaten? if not then I guess both par and creator-score are good names.

grady404 commented 8 years ago

I think rotation should be an attribute (unlike position), since it sorta corresponds to how the object behaves.

And yes, there is one difference between a par and a creator score - a creator score is the best score the creator could possibly get, whereas a par kind of implies that it was just some score that they felt would be good for players to shoot for. For example, the creator could beat the level in nine moves, but think "it was really hard to do that in nine moves, I think 12 moves would be a better par" and set the par to 12 moves. A creator score is different; if the creator beat the level in nine moves, then the creator score would be nine moves, period. I like the creator score system better than the par system because it challenges the players to beat the score of the creator, rather than beating some arbitrary score (which in most cases probably wouldn't even be that hard to beat).

And I think it would be weird not to include the data section at the bottom of the JSON, since it separates those values from the values that make up the board's structure. It's weird in the same way that storing the user levels in a subdirectory of the default level directory was (back before you reorganized the game's files). But I agree that "data" probably isn't the best word for that section. Maybe info, or details?

cooperuser commented 8 years ago

I agree that rotation should be an attribute. And now that you have elaborated on the creator-score thing it makes a lot more sense to go with your methods. And for the data part, in code it makes sense for it to be level.board and level.grid, but level.data.name or level.details.name doesn't really make as much sense as level.name. These names would be better because if anyone were to make a new block or plate, interacting with the level would be more intuitive.

grady404 commented 8 years ago

What did you mean with that last sentence?

And I would definitely prioritize ease of user experience over ease of programming. The way the JSON is organized is something the user will actually see, whereas the way it is coded isn't. And I personally think level.data.name or level.info.name is perfectly fine.

cooperuser commented 8 years ago

The user will be seeing the JSON?

grady404 commented 8 years ago

Yeah, why not? There's nothing wrong with them screwing with the level files, as long as they can't upload broken levels to the sharing service (we'll use encrypted certificates to fix that)

cooperuser commented 8 years ago

Hmm...

cooperuser commented 8 years ago

I'm not too sure, but I still think that

"name": "Test Level",
"creators": ["Cooper Anderson", "Grady Shoemaker"],
"creator-score": {
    "moves": 8,
    "distance": 27
}

is better than

"info": {
    "name": "Test Level",
    "creators": ["Cooper Anderson", "Grady Shoemaker"],
    "creator-score": {
        "moves": 8,
        "distance": 27
    }
}
grady404 commented 8 years ago

If you're giving someone a watermelon and a bunch of grapes, do you put them all in the same bag? Or do you put all the grapes in one bag, and then hand that to them alongside the watermelon?

cooperuser commented 8 years ago

Yeah but... These aren't grapes...

cooperuser commented 8 years ago

Neither of these things are very different coding wise, I just think that not having another subobject makes things simpler coding wise.

grady404 commented 8 years ago

name, creators, creator-score, and flags are the grapes. grid/board is the watermelon. (I think you should call it board btw.)

grady404 commented 8 years ago

But JSON-wise, I think it makes much more sense to put all the "grapes" in their own container. Think about it: there will only be one JS file with the code in it, there will be hundreds and hundreds of level JSON files.

cooperuser commented 8 years ago

Yeah I did end up calling it board but I made that change after I sent the file

cooperuser commented 8 years ago

I guess we could go with your method, If we ever need to change it, it wouldn't be the hardest thing to change anyway

cooperuser commented 8 years ago

But we should not use data as the keyword, because everything in the file is data

grady404 commented 8 years ago

Yeah, that's why I proposed info instead. I realized data was a terrible name

cooperuser commented 8 years ago

info, details, any others?

grady404 commented 8 years ago

The only other useful synonym I could find was attributes, but we already used that for the attributes of each object within the level. I like info, because level.info.name for instance sounds cleaner than level.details.name.

cooperuser commented 8 years ago

Yeah, I guess we will go with info then

grady404 commented 8 years ago
screen shot 2016-09-15 at 7 14 36 pm

level.poop.name level.poop.creator-score level.poop.flags

grady404 commented 8 years ago

level.dope.creators

cooperuser commented 8 years ago

what!?!?!

grady404 commented 8 years ago

Don't ask me...

grady404 commented 8 years ago

anyway, there aren't a whole lot of useful synonyms in there. info would be our best choice

cooperuser commented 8 years ago

Yeah

grady404 commented 8 years ago

What else do you need to do to finish the overhaul?

cooperuser commented 8 years ago

Hmm.. Right now I need to implement an efficient way of rendering the game.

grady404 commented 8 years ago

Wrong file...

cooperuser commented 8 years ago

oops that wrong hang on

cooperuser commented 8 years ago
{
  "grid": {
    "Tiles": [
      {"class": "Standard", "position": [0, 1]},
      {"class": "Standard", "position": [0, 2]},
      {"class": "Standard", "position": [0, 3]},
      {"class": "Standard", "position": [1, 1]},
      {"class": "Standard", "position": [1, 2]},
      {"class": "Standard", "position": [1, 3]},
      {"class": "Standard", "position": [2, 1]},
      {"class": "Standard", "position": [2, 2]},
      {"class": "Standard", "position": [2, 3]}
    ],
    "Plates": [
      {"class": "Standard", "position": [1, 1], "attributes": {"color": "blue"}}
    ],
    "Blocks": [
      {"class": "Standard", "position": [0, 2], "attributes": {"color": "blue"}}
    ],
    "Gates": [

    ],
    "Wiring": [

    ]
  },
  "info": {
    "name": "Debug",
    "creators": [
      "Cooper Anderson"
    ],
    "creator-score": {
      "moves": -1,
      "distance": -1
    },
    "flags": []
  }
}
grady404 commented 8 years ago

A few minor things...

cooperuser commented 8 years ago

Oh yeah... this wasnt the version where i renamed it to board

cooperuser commented 8 years ago

Should we get rid of the empty flags variable?

grady404 commented 8 years ago

Yeah I do think so actually, if the level doesn't have any flags there shouldn't be an empty list there. I would also make it so that your game is equipped to handle the lack of any other info variables (name, creators, etc.)

cooperuser commented 8 years ago

Yeah, of course

grady404 commented 8 years ago

And why the -1 creator scores? If there isn't a creator score, don't have that object there

cooperuser commented 8 years ago

New and improved:

{
  "board": {
    "Tiles": [
      {"class": "Standard", "position": [0, 1]},
      {"class": "Standard", "position": [0, 2]},
      {"class": "Standard", "position": [0, 3]},
      {"class": "Standard", "position": [1, 1]},
      {"class": "Standard", "position": [1, 2]},
      {"class": "Standard", "position": [1, 3]},
      {"class": "Standard", "position": [2, 1]},
      {"class": "Standard", "position": [2, 2]},
      {"class": "Standard", "position": [2, 3]}
    ],
    "Plates": [
      {"class": "Standard", "position": [1, 1], "attributes": {"color": "blue"}}
    ],
    "Blocks": [
      {"class": "Standard", "position": [0, 2], "attributes": {"color": "blue"}}
    ]
  },
  "info": {
    "name": "Debug",
    "creators": ["Cooper Anderson"],
    "creator-score": {"moves": -1, "distance": -1}
  }
}
cooperuser commented 8 years ago

but this level is impossible

cooperuser commented 8 years ago

It is purely for showing this

grady404 commented 8 years ago

Oh this is the impossible one, didn't realize that

cooperuser commented 8 years ago

Yeah, I should of specified that in the name

grady404 commented 8 years ago

You forgot to use the singular names (Tile, Plate, etc.)

grady404 commented 8 years ago

And you forgot to make the color 0 rather than "blue"

cooperuser commented 8 years ago

oh yeah,