In this document described how Sand-Box2D operates with its levels files.
You can input numbers in default JSON format ("number": 123
or "number_float": 12.3
),
but you can also input a string like that: "random": "100:5000"
,
it means that you want to input a random number between 100 and 5000.
Float and negative numbers are also supported: "random_float": "-1.5:5"
.
Every level file is just a JSON with the structure below:
{
"options": {"...": "..."},
"camera": {"...": "..."},
"actions": {"...": "..."},
"objects": [{"...": "..."}, {"...": "..."}],
"cycles": [{"...": "..."}, {"...": "..."}]
}
In this sector are global world options located.
It has the following structure:
"options": {
"bg_r": 50,
"bg_g": 50,
"bg_b": 50,
"gravity_x": 0,
"gravity_y": 9.81,
"border_width": 200,
"border_height": 200
}
Where:
bg_r
,bg_g
andbg_r
- color of the world backround (RGB values from 0 to 255). Maybe later optionbg_texture
will appear, but I don't know yet how to scale it properly (add scaling options?).gravity_x
andgravity_y
- world gravity force. If Y set to 9.81 objects will fall down vertically, if X is 0 objects won't move by themselves horizontally (like actual gravity).border_width
- width of world boundaries in Box2D meters. If set to 0 there's no borders (even ifborder_height
value is set), meaning that objects cannot be deleted by moving too much away from center (that's dangerous for perfomance); if set to 200 it means that object can fly 100m to the right of world center and 100m to the left. If it will move any further it will be deleted if it doesn't haveundeletable
flag.border_height
- same asborder_width
but for height. If set to 0 there's no borders (even ifborder_width
value is set).
In this sector described how Sand-Box2D should place camera at the start, can player move it and etc.
It has the following structure (keys attached_id
and attached_remain
are exceed intentionally):
"camera": {
"type": "static",
"attached_id": 15,
"attached_remain": 75,
"zoom": true,
"move": true,
"x": 6,
"y": 3.5,
"height": 8
}
Where:
type
- type of the camera. It can be:static
- camera doesn't move by itself. Player can move it and change zoom if it's allowed below.attached
- camera is attached to some object and spectates them. Zooming is allowed, but not movement.
attached_id
- ID of the object to be spectated when camera type is attached (more here). Ignored whentype
is notattached
.attached_remain
- value that shows how many percents are left each frame when spectating object. If you leave 0, camera will spectate object strictly, without smooth effect (it encounters object by 100% each frame). When you set 75, it means that camera is going to encounter object by 25% each frame, which means that you're gonna see smooth effect. If you set 100, camera won't move at all (it encounters object by 0% each frame, i.e. it's just static). If you set >100, camera will fly away from object (no sense to do that). Ignored whentype
is notattached
.zoom
- can user change camera zoom in game (true/false)?move
- can user move camera in game? Ignored whentype
isattached
.x
andy
- starting position of the camera in Box2D meters (point to which camera is centered). Ignored whentype
isattached
.height
- it used for setting zoom value at the beginning. It describes how much Box2D meters should camera capture in altitude, i.e. from screen top to bottom.
In this sector you can add some actions (move objects or something) that will perform when user press special buttons.
With this thing you can change (set or add) any value of any object in-game.
Here's example:
"actions": {
"up": {
"keydown_hold": [
{
"id": 10,
"type": "add",
"param": "vel_y",
"value": -0.75
}
]
},
"right": {
"keydown_hold": [
{
"id": 10,
"type": "add",
"param": "vel_x",
"value": 0.75
},
{
"id": 10,
"type": "add",
"param": "vel_ang",
"value": 0.25
}
]
},
"down": {
"keydown_hold": [
{
"id": 10,
"type": "add",
"param": "vel_y",
"value": 0.75
}
]
},
"left": {
"keydown_hold": [
{
"id": 10,
"type": "add",
"param": "vel_x",
"value": -0.75
},
{
"id": 10,
"type": "add",
"param": "vel_ang",
"value": -0.25
}
]
},
"enter": {
"keydown_once": [
{
"id": 10,
"type": "set",
"param": "vel_x",
"value": 0
},
{
"id": 10,
"type": "set",
"param": "vel_y",
"value": 0
},
{
"id": 10,
"type": "set",
"param": "angle",
"value": 0
},
{
"id": 10,
"type": "set",
"param": "vel_ang",
"value": 0
}
],
"keydown_hold": [
{
"id": 10,
"type": "set",
"param": "vel_x",
"value": 0
},
{
"id": 10,
"type": "set",
"param": "vel_y",
"value": -0.2
}
],
"keyup": [
{
"id": 10,
"type": "set",
"param": "vel_x",
"value": "-100:100"
},
{
"id": 10,
"type": "set",
"param": "vel_y",
"value": "-100:100"
}
]
}
}
Where:
up
,right
,down
,left
andenter
- corresponding buttons to call actions. Each game platform can have different buttons for this. They all can contain following keys:keydown_hold
is called every frame when corresponding button is hold.keydown_once
is called only once when user just pressed this button.keyup
is called only once when user stopped holding this button.
And all these keys are containing list of actions, one of them look like this:
{
"id": 10,
"type": "add",
"param": "vel_y",
"value": -0.75
}
Where:
id
- ID of the object to be involved in this action.type
- type of the action:set
- you want to set some object parameter to some value (param = value
);add
- you want to add something to the param of the object (param += value
).
param
- name of the object parameter to be modified.value
- value to be setted-added to object parameter.
In this example we added move controls for the box with ID 10
. When we press directional
buttons it starts to move in this direction. When we press enter
button it stops, but
if we stop pressing it, box will fly in random direction.
Read full article to understand how to create certain objects.
This sector describes which physics objects Sand-Box2D need to create once at the beginning.
It has the following structure:
"objects": [
{
"type": "platform",
"x1": 2,
"y1": 7,
"x2": 10,
"y2": 7,
"r": 255,
"g": 255,
"b": 0
},
{
"type": "platform",
"x1": 1,
"y1": 1,
"x2": 2,
"y2": 7,
"r": 255,
"g": 255,
"b": 0
},
{
"type": "platform",
"x1": 10,
"y1": 7,
"x2": 11,
"y2": 1,
"r": 255,
"g": 255,
"b": 0
},
{
"type": "box",
"id": 10,
"x": 6,
"y": 5,
"w": 2,
"h": 2,
"texture": "./box.png"
}
]
In this example we just create 3 static platforms
and box with ID 10
(to which will point our action).
Read full article to understand how to create certain objects.
This sector does the same thing as the objects sector, but periodically. You can declare several cycles with different delays.
It has the following structure:
"cycles": [
{
"delay": "25:100",
"objects": [
{
"type": "circle",
"x": 5,
"y": 0,
"radius": "0.05:0.75",
"vel_x": -10,
"vel_y": 10,
"r": "0:255",
"g": "0:255",
"b": "0:255"
}
]
},
{
"delay": "100:200",
"objects": [
{
"type": "box",
"x": 7,
"y": 0,
"w": "0.1:2.0",
"h": "0.1:2.0",
"vel_x": 10,
"vel_y": 10,
"texture": "./box.png"
}
]
}
]
Where:
delay
- amount of frames between cycle steps. Why its value is a string read here.objects
- should be filled with objects as here.
Here we declare two cycles with box and circle with random width/height and radius respectively. Circles with random color will spawn continuously every 25-100 frames (0.5-2 seconds), and boxes will do it every 100-200 frames (2-3 seconds, ~2 times slower).
You can refer to the default level for example built with this tutorial.
But you can also view other levels from theirs directory.