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

Complete JSON/Class Redesign #39

Closed cooperuser closed 8 years ago

cooperuser commented 8 years ago

This recreation is a big requirement because this allows us to integrate new features with ease, as apposed to the old method.

Also, @grady404, can you link your Python code that solves for the amount of moves necessary please? I will be integrating that into this redone version.

cooperuser commented 8 years ago

Also, in case you were wondering, this is what the new .json file format will look like:

{
  "grid": {
    "0": {
      "0": {
        "tile": {
          "position": {
            "x": 0,
            "y": 0
          },
          "color": "white",
          "passable": true,
          "class": "StandardTile",
          "objectType": "Tile"
        }
      },
      "1": {
        "tile": {
          "position": {
            "x": 0,
            "y": 1
          },
          "color": "white",
          "passable": true,
          "class": "StandardTile",
          "objectType": "Tile"
        }
      },
      "2": {
        "tile": {
          "position": {
            "x": 0,
            "y": 2
          },
          "color": "white",
          "passable": true,
          "class": "StandardTile",
          "objectType": "Tile"
        },
        "block": {
          "position": {
            "x": 0,
            "y": 2
          },
          "color": "white",
          "passable": false,
          "velocity": {
            "x": 0,
            "y": 0
          },
          "moveable": true,
          "class": "StandardBlock",
          "objectType": "Block"
        }
      }
    },
    "1": {
      "0": {
        "tile": {
          "position": {
            "x": 1,
            "y": 0
          },
          "color": "white",
          "passable": true,
          "class": "StandardTile",
          "objectType": "Tile"
        }
      },
      "1": {
        "tile": {
          "position": {
            "x": 1,
            "y": 1
          },
          "color": "white",
          "passable": true,
          "class": "StandardTile",
          "objectType": "Tile"
        },
        "plate": {
          "position": {
            "x": 1,
            "y": 1
          },
          "color": "white",
          "passable": true,
          "active": false,
          "class": "StandardPlate",
          "objectType": "Plate"
        }
      },
      "2": {
        "tile": {
          "position": {
            "x": 1,
            "y": 2
          },
          "color": "white",
          "passable": true,
          "class": "StandardTile",
          "objectType": "Tile"
        }
      }
    },
    "2": {
      "0": {
        "tile": {
          "position": {
            "x": 2,
            "y": 0
          },
          "color": "white",
          "passable": true,
          "class": "StandardTile",
          "objectType": "Tile"
        }
      },
      "1": {
        "tile": {
          "position": {
            "x": 2,
            "y": 1
          },
          "color": "white",
          "passable": true,
          "class": "StandardTile",
          "objectType": "Tile"
        }
      },
      "2": {
        "tile": {
          "position": {
            "x": 2,
            "y": 2
          },
          "color": "white",
          "passable": true,
          "class": "StandardTile",
          "objectType": "Tile"
        }
      }
    }
  },
  "name": "Debug",
  "creators": [
    "Cooper Anderson"
  ],
  "par": 0,
  "flags": [],
  "size": {
    "x": 3,
    "y": 3
  }
}
grady404 commented 8 years ago

My python program is broken. But I can explain the algorithm at least, which I'm pretty sure should work. The only problem with it is that for levels that take longer than about 15 moves, the algorithm takes exponentially longer to verify (so it's a lot better for small levels). Let me read over this new format and then I'll get to explaining it.

cooperuser commented 8 years ago

Ah, I see. Well either way, I'm sure that we will be able to make a sustainable algorithm that does this, and me "we" I mostly mean you, because you are the one who is good at that XD

grady404 commented 8 years ago

Ok I need a few things explained about this new format. What is "passable"? And "velocity"?

grady404 commented 8 years ago

Why are you storing these things in the raw level file? It's not like you're going to open a level, and a block is already going to be set to have velocity, and start moving right away without you touching anything. It seems like there's a ridiculous amount of unnecessary information in this file.

grady404 commented 8 years ago

And have you been checking general discussion?

cooperuser commented 8 years ago

I need the class and the objectType variables for specific reasons, and the passable variable lets me see if the block can go on the tile, (or board the tile as I decided to call it in code). Having the velocity vector is nice because then I don't have to create and delete the variable each time it is created.

grady404 commented 8 years ago

But I think the way you store the JSON files should be different than the way you store the raw JS classes. Because you don't need to store EVERYTHING that you need in-game in the level file (like the velocity). Or else some people might go in and screw with those values making for some VERY strange levels.

cooperuser commented 8 years ago

And yes, I have been looking at the General Discussion, and by recreating the game, I will make this the default.

cooperuser commented 8 years ago

hahaha! I just realized if the change the velocity from {x: 0, y: 0} to {x: 1, y: 1} it would move diagonally. wait.. no it wont, it only moves on click, and when you click it will reset the velocity

grady404 commented 8 years ago

Ok, another thing I think is weird is the "color" attribute, since not all objects have a color, it's kind of strange to include this. What I think you should do is have a sort of item ID, something like Block.Standard.Green or Wiring.Logic.XOR.

cooperuser commented 8 years ago

Unless I do:

$(".block").on("click", function() {
    if (click == "up") {
        block.velocity.y = -1;
    }
});

instead of:

$(".block").on("click", function() {
    if (click == "up") {
        block.velocity = new Vector2(0, -1);
    }
});
cooperuser commented 8 years ago

oh... that Block.Standard.Green way of doing things looks like a good way of doing it..... shit.

cooperuser commented 8 years ago

Also, look at how I am currently doing the Object code for the Block type

class Block {
    constructor(position=new Vector2(), color="white") {
        this.position = position;
        this.color = color;
        this.passable = false;
        this.velocity = new Vector2();
        this.moveable = true;
        this.class = this.constructor.name;
        this.objectType = "Block";
    }
}
Block.CheckMove = function(block, grid) {

};
Block.Move = function (block, grid) {
    var isPassable = function(gridSpace) {
        var passable = [];
        for (var key in gridSpace) {
            passable.push(gridSpace[key].passable);
        }
        return !passable.includes(false);
    };
    var pos = block.position;
    var dir = block.velocity;
    var dest = new Vector2(pos.x + dir.x, pos.y + dir.y);
    if (!(dir.x == 0 && dir.y == 0) && typeof grid[dest.x] != "undefined" && typeof grid[dest.x][dest.y] != "undefined" && isPassable(grid[dest.x][dest.y]) && typeof grid[dest.x][dest.y].tile != "undefined") {
        eval(eval(`grid[dest.x][dest.y].tile.class`)).Depart(grid, dest);
    }
    while (true) {
        if (!(dir.x == 0 && dir.y == 0) && typeof grid[dest.x] != "undefined" && typeof grid[dest.x][dest.y] != "undefined" && isPassable(grid[dest.x][dest.y]) && typeof grid[dest.x][dest.y].tile != "undefined") {
            eval(eval(`grid[dest.x][dest.y].tile.class`)).Slide(grid, dest)
            eval(`delete grid[pos.x][pos.y].${block.objectType.toLowerCase()}`);
            eval(`grid[dest.x][dest.y].${block.objectType.toLowerCase()} = block`);
        } else {
            eval(eval(`grid[dest.x][dest.y].tile.class`)).Board(grid, dest)
            break;
        }
        pos = dest;
        dest = new Vector2(pos.x + dir.x, pos.y + dir.y);
    }
    return grid;
};

class StandardBlock extends Block {
    constructor(position=new Vector2(), color="white") {
        super(position, color);
    }
}

class HollowBlock extends Block {
    constructor(position=new Vector2()) {
        super(position);
        this.class = this.constructor.name;
    }
}

module.exports = {Block, StandardBlock, HollowBlock};
cooperuser commented 8 years ago

This way, unless I need to override the .Move() method, I don't have to reprogram it! Because I'm using subclasses!

grady404 commented 8 years ago

In fact, I think you should use those Item IDs for everything about an item except for its position (so that would include its rotation, initial state, etc.) so something like Wiring.Logic.XOR.LeftFacing.Enabled. Or maybe if that's too weird, just have "flags" for each block the same way you have those for the entire level. Then you would have Wiring.Logic.XOR with flags LeftFacing and Enabled. The reason I don't think you should have rotation as an attribute is because all blocks have different "spins" as you could call them, for example some might have no rotational symmetry, some might have 2-way, and most (like blocks and plates) would have 4-way rotational symmetry. So for the latter, you wouldn't want to set any rotation states, the middle would only have two states, and the former would have four.

cooperuser commented 8 years ago

Okay, but this will already be a thing we can do,

cooperuser commented 8 years ago

I don't oppose your idea about all variations being a subclass, I just need to think of a way of integrating it.

grady404 commented 8 years ago

Oh wait oops, the XOR gate won't have an enabled/disabled state, my bad, but memory circuits will (T flip-flops, etc.) which will correspond to their initial state when the level starts.

grady404 commented 8 years ago

Here's another idea, split the level into three different "layers", and in each layer no two objects would be able to occupy the same spot. Bottom layer would be board tiles, middle layer would be plates and switches, top layer would be blocks, teleporters, and gates (not logic gates). Wires are kind of weird for this system, since they kind of need to occupy both layer 2 (so they can interact with switches) and layer 3 (so they can interact with gates), but they can't fully occupy layer 3 or else blocks wouldn't be able to pass over them.

cooperuser commented 8 years ago

thats why I have the passable variable, so I can have doors, or gates as you called them, open and close

grady404 commented 8 years ago

Well the state of a gate wouldn't be stored in the JSON file, because it's an output block, and upon starting the level the gate would automatically assume the state of the wire being fed into its input.

cooperuser commented 8 years ago

why assume though?

grady404 commented 8 years ago

And I guess calling them doors is a good idea, so we don't mix them up with logic gates (even though doors isn't quite the right word for them)

cooperuser commented 8 years ago

what if a block starts on a plate, powering the door?

grady404 commented 8 years ago

"Assume" in that context means to take the role of

grady404 commented 8 years ago

If a block starts on the switch (it's a switch, not a plate), then upon starting the level the game will realize that, and start feeding power into the wire, and then power the door

grady404 commented 8 years ago

See general discussion, it's pretty important

grady404 commented 8 years ago

Also did you see my pull request?

cooperuser commented 8 years ago

I see that you added me as the Assignees of all of the issues,

cooperuser commented 8 years ago

Because for a couple of minutes, my notification manager was going crazy because it only allows 3-4 on the screen at once.

grady404 commented 8 years ago

oh LMFAO why did it give you a different notification for each one? I did it all at once

cooperuser commented 8 years ago

bad design..?

grady404 commented 8 years ago

I guess. Btw it's a lot less annoying without that cursor now, but could you remove the buttons completely? I think it would make it look a lot more streamlined.

cooperuser commented 8 years ago

(I think you put that in the wrong thread..)

grady404 commented 8 years ago

Yeah, but you never seem to see things unless I put them in the thread we're currently talking in (due to GitHub's shitty notification system), so...

cooperuser commented 8 years ago

I have a separate notification system that seems to work well, the only issue is the update frequency, about once every 1-2 minutes

cooperuser commented 8 years ago

so I usually get to them

grady404 commented 8 years ago

You going to remove those buttons?

cooperuser commented 8 years ago

did you see the image?

cooperuser commented 8 years ago

on #27

grady404 commented 8 years ago

I don't think you should wait until this is finished before you reorganize the filesystem, I think the filesystem is more of a priority and once you do that, you can add a preferences.json file easily

grady404 commented 8 years ago

See #6

grady404 commented 8 years ago

How's the overhaul going?

cooperuser commented 8 years ago

Good, I might not implement it tonight though, still needs a lot of thinking

grady404 commented 8 years ago

How long are you planning on staying up working on the game?

cooperuser commented 8 years ago

today, not much. I might go take my driving test tomorrow, so I kinda need sleep

grady404 commented 8 years ago

Alright, think I'm gonna hit the sack too, so I guess I'll talk to you tomorrow

cooperuser commented 8 years ago

K see ya then

cooperuser commented 8 years ago

Progress!!!: screen shot 2016-09-18 at 3 44 18 pm