News:

Don't forget to visit the main site! There's lots of helpful docs, patches, and more!

Main Menu

room transitions [SOLVED]

Started by liamnajor, April 15, 2017, 07:15:23 PM

Previous topic - Next topic

liamnajor

As you all know, I'm working on a Metroid Engine in JavaScript. However, I have a problem I can't solve. when I make a room, it saves it as a separate .js file. each tile is a separate entity within the code. it works very efficiently, both for loading times and file size. But, I have no way to differentiate between rooms if I load them all at once(which would be slow anyway). if I load them one at a time, I can't load a new room without manually modifying the .html file(which, obviously, that will not work for a full game). is there any way to trigger the .js file to modify the .html in a specific way, or to load the .js from ANOTHER .js file? or should I use a whole new tactic for room loading?

monktroid

#1
Quote from: liamnajor on April 15, 2017, 07:15:23 PM
As you all know, I'm working on a Metroid Engine in JavaScript. However, I have a problem I can't solve. when I make a room, it saves it as a separate .js file. each tile is a separate entity within the code. it works very efficiently, both for loading times and file size. But, I have no way to differentiate between rooms if I load them all at once(which would be slow anyway). if I load them one at a time, I can't load a new room without manually modifying the .html file(which, obviously, that will not work for a full game). is there any way to trigger the .js file to modify the .html in a specific way, or to load the .js from ANOTHER .js file? or should I use a whole new tactic for room loading?

While my knowledge of canvas is pretty rusty (i wrote a prototype engine a few years back), I'm pretty savvy in a webdev context. 
At a glance, I was surprised to see lots of callbacks in your room js file.   Here's my 2 pence.  I would probably take a different course: JSON! It's fast, native to JS and very readable.  Furthermore, it allows you to completely decouple your room data from your algorithms.

so for example, something along these lines:
var room1 = {
  "Area": "Crateria",
  "TileMap":
    [{"offsetX":"0px", "offsetY":"0px","src":"<SOME_LOCATION>/<RAW_HEX>","BTS":"Solid"},
     {"offsetX":"16px", "offsetY":"0px","src":"<SOME_LOCATION>/<RAW_HEX>","BTS":"Air"},
     etc.],
  "enemies":
    [{"type_id":1, "initX":"28px", "initY":"42px", "special_id":1},
     etc]
  "FX1": ...
  "Layer1": ... // you get the jist
}

you then run JSON.parse(room1) in your engine.  You choose when and where, maybe you have transition points like the lifts in SM where you load all rooms in an area, or just have a load screen at the start of the game and shove the whole lot into RAM; hey, people have a lot of RAM these days!  Another beauty with JSON is that it's easy to benchmark. Try the whole lot in one file. Try it in a bunch of different structured setups (area, blocks, one room per file). TBH, Double buffering and screen transitions can easily hide a multitude of sins nowadays, I would think you'll be able to load your rooms on the fly really; if you're worried, have the game load some kind of indices to each of your rooms when it's first loaded.  For example, have a separate master JSON table that has an offset for each one of your rooms by area or something.

The beauty of doing it this way is that each component is modular.  That makes your engine modular and extensible (say you wanna add some special metadata to certain rooms, now you can.  You just test for "yourSpecialMetaData" node in your json, if it has said data: give that room the special treatment!)

If JSON's footfall is too high, you could do similar with n-dimensional arrays and use a set of global variables to store the meanings of each index (a bit like accessing stuff with Enums in a language like C++ or Java):


var AREA = 0
var ENEMY = 1

room1[AREA]
for (var i in room1[ENEMY]) { ... }

you get the idea.

liamnajor

my only issue with the JSON method is this: I have no experience with JSONs format, as I've never used it before. so, I'll use that if all else fails, but is there any way for me to use javascript only for this? if not, that's OK, but I'd prefer only javascript.

liamnajor

Quote from: monktroid on April 15, 2017, 07:53:07 PM
Quote from: liamnajor on April 15, 2017, 07:15:23 PM
As you all know, I'm working on a Metroid Engine in JavaScript. However, I have a problem I can't solve. when I make a room, it saves it as a separate .js file. each tile is a separate entity within the code. it works very efficiently, both for loading times and file size. But, I have no way to differentiate between rooms if I load them all at once(which would be slow anyway). if I load them one at a time, I can't load a new room without manually modifying the .html file(which, obviously, that will not work for a full game). is there any way to trigger the .js file to modify the .html in a specific way, or to load the .js from ANOTHER .js file? or should I use a whole new tactic for room loading?

While my knowledge of canvas is pretty rusty (i wrote a prototype engine a few years back), I'm pretty savvy in a webdev context. 
At a glance, I was surprised to see lots of callbacks in your room js file.   Here's my 2 pence.  I would probably take a different course: JSON! It's fast, native to JS and very readable.  Furthermore, it allows you to completely decouple your room data from your algorithms.

so for example, something along these lines:
var room1 = {
  "Area": "Crateria",
  "TileMap":
    [{"offsetX":"0px", "offsetY":"0px","src":"<SOME_LOCATION>/<RAW_HEX>","BTS":"Solid"},
     {"offsetX":"16px", "offsetY":"0px","src":"<SOME_LOCATION>/<RAW_HEX>","BTS":"Air"},
     etc.],
  "enemies":
    [{"type_id":1, "initX":"28px", "initY":"42px", "special_id":1},
     etc]
  "FX1": ...
  "Layer1": ... // you get the jist
}

you then run JSON.parse(room1) in your engine.  You choose when and where, maybe you have transition points like the lifts in SM where you load all rooms in an area, or just have a load screen at the start of the game and shove the whole lot into RAM; hey, people have a lot of RAM these days!  Another beauty with JSON is that it's easy to benchmark. Try the whole lot in one file. Try it in a bunch of different structured setups (area, blocks, one room per file). TBH, Double buffering and screen transitions can easily hide a multitude of sins nowadays, I would think you'll be able to load your rooms on the fly really; if you're worried, have the game load some kind of indices to each of your rooms when it's first loaded.  For example, have a separate master JSON table that has an offset for each one of your rooms by area or something.

The beauty of doing it this way is that each component is modular.  That makes your engine modular and extensible (say you wanna add some special metadata to certain rooms, now you can.  You just test for "yourSpecialMetaData" node in your json, if it has said data: give that room the special treatment!)

If JSON's footfall is too high, you could do similar with n-dimensional arrays and use a set of global variables to store the meanings of each index (a bit like accessing stuff with Enums in a language like C++ or Java):


var AREA = 0
var ENEMY = 1

room1[AREA]
for (var i in room1[ENEMY]) { ... }

you get the idea.
how would I load individual data points? I think I know how, but I need a refresher.

monktroid

JSON is super easy!

it's basically just JS object literals.  I mean, canvas suggests you're sending stuff to clients from a server.  If so, I'd definitely use the JSON approach.

it's almost identical to using object literals:
var objectLiteral = { a: "foo", b: "bar }

try the following in your browser's console:

var myJsonObject= '{"a": "something","b": "somethingElse","c": "etc."}'

//all you do is run
var foo = JSON.parse(myJsonObject)

console.log("The output of myJsonObject is: " + foo.a)


here's a pretty nice intro.  Trust me, compared to learning stuff like closures in JS, JSON is the easiest thing in the world!

https://www.w3schools.com/js/js_json_intro.asp

p.s.  Totally learn closures at some point. they are awesome!

monktroid

Quote from: liamnajor on April 15, 2017, 08:23:53 PM
how would I load individual data points? I think I know how, but I need a refresher.


var myJsonObject= '{"a": "something","b": "somethingElse","c": "etc."}'
var foo = JSON.parse(myJsonObject)
for (var i in foo) {
console.log(foo[i])
}

liamnajor

Quote from: monktroid on April 15, 2017, 08:29:57 PM
Quote from: liamnajor on April 15, 2017, 08:23:53 PM
how would I load individual data points? I think I know how, but I need a refresher.


var myJsonObject= '{"a": "something","b": "somethingElse","c": "etc."}'
var foo = JSON.parse(myJsonObject)
for (var i in foo) {
console.log(foo[i])
}

so, to load myJsonObject's "a" portion into another variable, I'd type

var newVariable = myJsonObject.a

right?

monktroid

if jsonObject is a string (I messed up on my first post because you only run JSON.parse on  JSON objects if they're formatted as strings, sorry, I'm tired, it's super early in the morning where I am):

var myJsonObject= '{"a": "something","b": "somethingElse","c": "etc."}'

you would use:


var myObject = JSON.parse(myJsonObject)

var nodeA = myObject.a

console.log(nodeA) // will print "something" to the console.


liamnajor

Thank you very, very much! I really needed this info (in fact, I don't know why I didn't ask earlier). now I have a lot work to do to get this working, and need to start right away. Thank you!