Best Way to Load in/Create a Map

I am creating a top down puzzle game currently and I have got most of the main framework created. This game is to be cube-based and my kind of roll model for it is this youtube video:

[video]http://www.youtube.com/watch?v=IL3MIwlnfdU[/video]

As you can see this person has cubes as the “walls” in the game. I was wondering, it looks like he would load that in from a map instead of hand coding it, so how would you do this? I was thinking of making an image with different colors representing different checkpoints/elements, however this doesn’t seem very dynamic because each time I want to create a new element (bridge, pressure plate, door, etc) I would have to code a pointer to the element and color into the map loader.
How would you go about making a map for this kind of game? Hand code it? JSON? Image? Or is there someway to do it in Blender?

I appreciate any advice, Thanks.

ok, i already made games like this, one of them being Yuyu, here: http://sourceforge.net/projects/yuu/

As you say, you have many approch for this problem. Actually, i didn’t chose any of them. Instead of that, i chosed to embed a lua script interpreter and let it decide how to do it.

To make a long story short : every map IS a script, and the only job of the core engine is to provide tools for the script, like ways to create maps from cube, load objets and add them in scene, remove object, open image, access an xml tree. Then, every script can chose its own approach. If the map is simple and really “procedurally generated” (like labyrinths), then it will do it itself (actually if will use a labyrinth-maker tool provided by the core engine), is it’s something more “human” (aesthetic) i use an image. For exemple, the last level of the last version is made with an image as model.

The “problem” of the image approach is that it can become very hard to represent something that has more than one level. You can use more than one image, but then you get other problems.

This lua approach also allow people to create (and share) their own level, as i don’t give a lot of rights to the lua script. For exemple, they CAN’T write files or open sockets. So, the risk of a “level” with a virus in it is low. And, with lua, you have to provide the source code.
And also, you can have a key to reload the level, so you don’t have to restart/recompile your app, you cann see changements almost “on the fly”.

@bubuche said: ok, i already made games like this, one of them being Yuyu, here: http://sourceforge.net/projects/yuu/

As you say, you have many approch for this problem. Actually, i didn’t chose any of them. Instead of that, i chosed to embed a lua script interpreter and let it decide how to do it.

To make a long story short : every map IS a script, and the only job of the core engine is to provide tools for the script, like ways to create maps from cube, load objets and add them in scene, remove object, open image, access an xml tree. Then, every script can chose its own approach. If the map is simple and really “procedurally generated” (like labyrinths), then it will do it itself (actually if will use a labyrinth-maker tool provided by the core engine), is it’s something more “human” (aesthetic) i use an image. For exemple, the last level of the last version is made with an image as model.

The “problem” of the image approach is that it can become very hard to represent something that has more than one level. You can use more than one image, but then you get other problems.

This lua approach also allow people to create (and share) their own level, as i don’t give a lot of rights to the lua script. For exemple, they CAN’T write files or open sockets. So, the risk of a “level” with a virus in it is low. And, with lua, you have to provide the source code.
And also, you can have a key to reload the level, so you don’t have to restart/recompile your app, you cann see changements almost “on the fly”.

Thanks for the reply bubuche.

This is interesting as Lua was actually my first language.
So your saying I should find a way to use the lua interpreter with Java in order to let Lua access jMonkey functions?
I’m afraid I don’t quite understand what you mean by it, would you mind elaborating and maybe posting a (short) example Lua script so I can see what you mean?

Thanks alot!

you can download the source code of my game.

Ok, i’ll show you one. In this level, you have a big room with a ball. when you come close to the ball, it run away. You have to put it on a special place in order to validate the level.

(i comment the code just after)

[java]
world:doFile(“Levels/level_helper.lua”)

function main()
level:setSize(30, 7, 3)
level:setLevelNumber(12)

createBoxAroundTheWorld(level, 1)

local saved_id
saved_id = putActionsBox(3, 3, 1, {“activate”, “ball”})
level:setMetaData(saved_id, “onActivate”, addBall)

for i = 7, level:width() - 5 do
local d, a
d = putActionsBox(i, 1, 2, {“walk”, “death”})
a = world:addActionsBox(1, 0, 2, {})

local f = temporaryStop(d, a)
level:setMetaData(d, "onStand", f)

end

world:physic():setPosition(playerId, 2, 2, 2)

local safe_id
safe_id = world:addActionsBox(-5, -5, -5, {})
level:setLevelMetaData(“safe”, safe_id)

local unsafe_id
unsafe_id = world:addActionsBox(-5, -4, -5, {“walk”, “death”})
level:setLevelMetaData(“unsafe”, unsafe_id)

saved_id = putActionsBox(29, 1, 2, {“ball”, “walk”, “death”})
level:setMetaData(saved_id, “onStand”, killBall)

saved_id = putActionsBox(28, 1, 2, {“walk”, “exit”})
level:setMetaData(saved_id, “onStand”, changeLevel)

end

function addBall()
local saved_id

saved_id = level:levelMetaData(“ball”)
if ( saved_id ~= nil ) then
world:kill(saved_id)
end
saved_id = world:addItem(“Ball”, 6, 3, 2)
level:setLevelMetaData(“ball”, saved_id)
local delay
delay = 2
world:delayedCall(impulseBall(saved_id), delay)
world:applyFunctionCD(addBall, delay-1)

end

function impulseBall(old_id)
return function ()
local ball_id
ball_id = level:levelMetaData(“ball”)
if ( ball_id ~= old_id ) then
return
end

world:physic():setMass(ball_id, 0.1)
world:physic():setFriction(ball_id, 0)
world:physic():applyCentralForce(ball_id, 30, 0, 0)

end
end

function sum(number)
return function(anothernumber)
return number + anothernumber
end
end

function temporaryStop(itemID, alternateID)
return function ()
local otherID = params:get(“otherId”)
if ( otherID == playerId ) then
killPlayer()
return
end
level:setMetaData(itemID, “onStand”, nil)
world:changeMaterial(level:levelMetaData(“safe”), itemID)
world:delayedCall(reenable(itemID, alternateID), 2)
end
end

function reenable(itemID, alternateID)
return function ()
level:setMetaData(itemID, “onStand”, temporaryStop(itemID, alternateID))
world:changeMaterial(level:levelMetaData(“unsafe”), itemID)
end
end

function alternate(itemID, otherID)
local pos_item
pos_item = world:physic():positionOf(itemID)
local pos_other
pos_other = world:physic():positionOf(otherID)

world:physic():setPosition(itemID, pos_other:getX(), pos_other:getY(), pos_other:getZ())
world:physic():setPosition(otherID, pos_item:getX(), pos_item:getY(), pos_item:getZ())
end

function killBall()
local saved_id
saved_id = params:get(“otherId”)
if ( saved_id == playerId ) then
return
end
world:kill(saved_id)
end

function changeLevel()
local saved_id
saved_id = params:get(“otherId”)
if ( saved_id == playerId ) then
world:changeLevel(“13”)
end
end
[/java]

ok, the “Levels/level_helper.lua” contains some helpfull functions, like “createBoxAroundTheWorld” which basically if a 3 loop for that create an empty box. Nothing really hard to understand.

All of my program is around an idea: each item has an id, then i can attach “onThings” on each item and when the “thing” happens it calls a function. Just like javascript, you know.

So, basically, the program is

create an environnement create a box add trigger "onActivate" on the box. for this trigger : kill the precedent ball (if any) then add a new ball.

every time you add a ball, add a trigger “onNear” to this ball.
for this trigger if the player is near enough, push the ball in the opposite direction.

in the world, add a box with the trigger “onStand” (triggered when you walk/stand on it).
for this trigger, check the id of the item standing on the box. If it’s the ball, SUCCESS !

As you can see, this rely on a “good” core, and you’ll have a lot of works to do here. However, this is not really hard to do, it’s only a bit time consumming.
Here, i added a lot of functions like “create an item composed of boxes” (and you can implement this by using the “cubeworld” plugin as backend), change the gravity, load “custom items” (like the ball) apply physics things on items etc.
Plus the “trigger” part, which allow me to add dynamic as easily as you can do it with these yummy functions in javascript.

I’ll not hide the fact that you’ll have problem with triggered effect that happens in a level that is not here any longer. This happened when i added a “onTimeElapsed” (or something like that) trigger,

But nothing that you can’t solve (you only need to check that the level of the callback is still running).

(the addactionbox is a tool of my core that create a box with icons on faces. I used that as a hint for the player during game. You can read the wiki on the sourceforge).

This core is old, i developped a new one but … yeah, this approach is not really good when you want to create networked games.

And, btw, you have the lib “luaj” which i used and is exactly that : a binding for lua in java.
If you go this way, i can give you a lot of advice to solve a lot of bugs that can consume a lot of time to understand. For exemple, you cannot use the iterator method for Collection (list, set etc.) you need to do a little trick here.
But, once this is done, you can give an object to the lua script, and call method of this object from the lua script. AND, if these methods returns a java object, you can get it from the lua code as a normal return value from a method, and use it etc. approximatively, you can “do” java in lua at least for the “runtime” part.

2 Likes

That’s really awesome, thanks for explaining it in such detail.
This kind of method seems like it would go better for a Portal-esque game, is that correct?
It also seems like I could definitely use it for what I’m doing, however with simple things such as moving the player ball to an area to push down a pressure plate or something like that, wouldn’t that be going overboard?

My game is essentially a maze of blocks in which there are pressure plates, water, and other elements that the ball (player) is trying to get through. Wouldn’t it kind of be a pain to hand code each block for that maze?
This really does look like a great method, so do you think there is a way I can scale it down to suit my purposes?

Thanks again, I can’t begin to explain how much you’re helping me here.

Yeah, my game was a portal-like one. Actually, i even tried to add the portal gun in it, but i failed to create something good enough in the core.

I think that a good start for you is that:
http://hub.jmonkeyengine.org/forum/topic/cubes-a-block-world-framework/

You can try to create some “test” level in java with a pseudo code like this:

[java]

// levelName is a String that contains the name of the level
// we are in a SimpleApplication instance, or at least in something that can access rootNode and physicspace

/* clean previous instance of level is any */
cleanAllPhysics(rootNode);
rootNode.detachAllChildren();

/* ok, now we load the level */
loadLevel(levelName);

[/java]

And, in the loadLevel method:

[java]
public void loadLevel(String levelName)
{
/* right now we create a test level in Java. */

for ( int i = 0; i < 10; i++ )
{
for ( int j = 0; j < 10; j++ )
{
//add a cube at (i, 0, j)
}
}

/* let’s break the symetrie */
//add a cube at (1, 1, 1)

//attach the result to the root node, enable physics for it
}

[/java]

Then, later, when this will work, you can replace this code by the call to the lua script. Or don’t do it like that and create an interface “Level” with a single method “load” with good arguments and do everything in java.

But you will need an approach like this anyway, as you have many levels that are much more “geometric” than “aesthetic”. For exemple, this approach would be very bad to create halo-like levels (there you would use blender).

For all the dynamic part, i still think that the “yell” approach is good. I made that because i come from c++ and i love how Qt is with its signal/slot thing.

You also have this script+core thing in TES games, where all quests are just scripts that can do a lot of “dumb” things like play animations etc. It’s very powerfull, cause you can create a complex comportement (like open a portal from Portal game) and place the call to this very complex comportement behind a very simple method.

For exemple, change the gravity was a pain in the bot to do, as you CAN’T change the gravity of a CharacterControl. I had to extends the class and tweak a lot of part + remove the charactercontrol and add a new one with the modified grvity every time i want to change gravity. But, from the script, it was just a call to a method with one parameter.

So; my final advice is : start to create a very small game, with a working ball and a “fake” level. Then, use my lib
http://hub.jmonkeyengine.org/forum/topic/labyrinths-librairy/
and replace this fake level with a labyrinth.

then come back and we will talk more about how to do the dynamic part :slight_smile:

2 Likes

Sounds great!

Thank you again for the advice, and the labyrinth lib, I’ll check that out.
After I’ve done a little more on it as you suggested I’ll shoot you a pm and we can work out some other stuff.