LPCGame icon indicating copy to clipboard operation
LPCGame copied to clipboard

Creating the Editor

Open Twinklebear opened this issue 13 years ago • 14 comments

Tile Maps

  • Need support for any size tile map, ie. can just place random tiles from the tileset anywhere to create the map, instead of being limited to predefined blank maps to edit.

Entity Creation

  • Need to be able to create new Entity prefabs for usage in States.
  • Need to be able to set Entity properties such as attached Image, Script, Physics components and so on.

Importing Images and Other Files

  • How does SDL's drag-drop work? Does it even have support for this?
  • Need to be able to drag in files to the editor and have them copied to the appropriate folder.
  • Need to be able to create Image and AnimatedImage config files through a GUI in the editor.

Twinklebear avatar Oct 13 '12 07:10 Twinklebear

I'm going try to tackle this next. Starting with beefing up the map editor.

Things I hope to add.

First Additons
  1. New button / Select # tiles.
  2. Save/Save As buttons.
  3. Open button.
  4. Clear button.
  5. Map Info (saved location, rows vs columns).
Additional Additions to Add
  1. Warp zones (to travel between maps).
  2. TileBar (with additions).

Not sure how to implement warp zones yet.

Question: How do I implement buttons that don't load another state, but rather call C++ code.

I've written two functions that run the default Windows OpenFileDialog and SaveFileDialog, I just need to find out how to bind them with buttons. I'd hope it'd just be through c++ but maybe lua?

btstevens89 avatar Oct 18 '12 02:10 btstevens89

Unfortunately, the buttons are still very much a WIP, at the moment all the C++ ones can call is to setexit on the current scene and change to the next with the scene param set to whatever is described in json.

The Lua one can do the same thing but from Lua, and can do any other Lua operations currently supported.

Buttons and their interactions is actually where I'm actively working, so at the moment it's really got nothing. I was thinking in the future of having some sort of dispatch system for button function calls, where they can try to call some function and send some parameters, either a C++ function or Lua function, or get a function to cache for later through the lookup system (should be doable if the lookup system is lua_cfunctions(?))

I guess the only way to do the buttons for now would be to hardcode the call, or maybe detect the call to do based on some param. Ie. param = OpenFileDialog then instead of calling the default registered function, call the one you want. Once buttons and the function dispatcher are in place this will then be pushed entirely into Lua.

As far as warp zones, what you could do is have a non-rendered entity (this flag isn't implemented, ie. render toggle for entities), although you could just give it no image file. That when interacted with (OnClick/OnMouseDown/etc are the only options for now) will call the StateManager to change state to whatever it should warp to. You could take a look at the Lua button i've made and just change it to some entity to click.

What I would like to add are callback functions for OnCollision events (don't exist yet) which will call an OnCollision function on both colliding entities, passing the tag/name of what they collided with. So then you'd have the warpzone waiting for OnCollision where the name is player, and then trigger a state change.

I'm not sure how much you've been keeping up with the Lua Embedding issue , but there you'll find an explanation as to why buttons can't do this yet and what I plan to make them do in the future and can see the progress in making this stuff possible. The code for that work is found in Experiments/LuaCrossStateCallTest

Twinklebear avatar Oct 18 '12 03:10 Twinklebear

It may take me a bit to get this working in a form where it's ready to merge into the engine, as there's some wierdness occurring with luabind vs. lua C API where userdata that's usable and defined via luabind can't be recast back to a usable version in the lua C API.

I'd suggest going with some ugly hardcoding of the function pointers for now, and when I've got the C++/Lua function dispatch and buttons put together I'll let you know and we can get it put together.

Sounds pretty awesome though! Is it through the win32 api? Or is SDL able to do some cross platform stuff?

A nice thing for the editor would be the ability to place tiles anywhere starting from an empty map. Although it may be a bit tricky. Easier method is definitely to select # tiles for x y

Twinklebear avatar Oct 18 '12 05:10 Twinklebear

Several things...

  • I'm going to let you sort out the Lua handles and all of that. I've never done anything in Lua so I'm not well suited. I'll figure it out eventually if need be.
  • I'm going to stick with key presses for now rather than binding buttons with functions for the reason above.
  • DialogBoxes are from the win32api. Everything is in dialogbox.h.
  • I think we should have everything predefined. We could make add an option to resize though?

I want to move everything out of the json files and into predefined code. TileBar and all of the editor's buttons should be hardcoded. What do you think?

As for warpzones. I'm going to add something that can define warpzone areas on the map. We can implement something for doing the actual changes later.

btstevens89 avatar Oct 20 '12 02:10 btstevens89

Yep I'd agree with hardcoding the editor, we're the only ones who will need to be tweaking it ever, and it should be something that's not easy for a user to break on accident by fiddling with some json.

For anything game related i was planning to leave it up to the user to define entity/map/scene interactions, but since the Lua API and the Lua -> C++ and Lua -> Lua function dispatching isn't made, the warparea sounds fine for a temporary method.

It may be really hard to allow random placement of tiles of a map, having a pre-defined blank map would be fine, perhaps of a grid style blank editor tile. Then once the map is finished and saved simply ignore the editor's filler tiles to prune the map down to only what was made. Actually this may be really hard since a non-rectangular map will mess up the tile index calculations, it'd probably need to be re-written to some different method entirely. Pre-defined rectangles is fine, or requesting a rectangle size to generate.

As far as Lua goes, my goal is to hide as much of the lua specific functions as possible from the rest of the C++ code as I'm doing in the test project, so there won't be any changes on the C++ side of things and when/if you write some Lua code to work with entities, Lua itself is really easy to pick up, and the API will call/act almost identical to the C++ code it's wrapping, so it should be easy to use/familiar. You probably won't have to deal with Lua's C API but if you do end up needing to work with it, it's not too bad.

Twinklebear avatar Oct 20 '12 03:10 Twinklebear

Currently Map is drawn with Math::FromSceneSpace and Math::Centering. Is there an easy way to bypass this and specify exactly where I want the map to be drawn from? That would make it a lot easier to work with maps.

Some things I've got working...

  • The map's box is by default 20x20. This makes it so that it won't run off the screen.
  • The map editor allows the map to be moved left right up and down, so you can access the tiles that are beyond 20x20.
  • The editor shows the index of the tiles within the map, and adjusts accordingly.
  • The tilebar does not by default load all of the tilesets. Rather, it loads the first tileset. Changing the tileset is implemented too.
  • Dialog boxes are coded. Creating a new map asks for the rows and columns. Changing the tilebar shows a list of tilesets to choose from.

The only issue i'm having with this is that when keeping the scene box at 20x20 I can't scroll the map past 20x20. When I change the scene box, the map is drawn out of view. Any ideas on that? Should I just overload Map::Draw in MapEditor?

btstevens89 avatar Nov 05 '12 05:11 btstevens89

If you wanted to bypass the map tile draw positioning, you would want to adjust the x,y for the Rectf pos in these lines:

Rectf pos = Math::FromSceneSpace(cam, mTiles.at(i).Box());
Window::DrawTexture(mTileSet->Texture(mTiles.at(i).Name()), pos, 
    &(Recti)mTileSet->Clip(mTiles.at(i).Name()));

so here you can set pos to anything you want to change the tile's draw x/y/w/h. When specifying x/y keep in mind that the draw x/y are used as the window-space coordinates to draw too. ie. 0,0 is the top left corner of the window.

As far as the issue goes, I'm not sure. There could be some weirdness going on in the camera or the drawing or somewhere. Perhaps the tiles aren't being marked as colliding with the camera beyond some point? Then their index wouldn't show up in the list of tile indices to be drawn. A wild guess haha, I'm not really sure. You may want to see if the issue also occurs in the game state, the camera should be set to follow the player already, so you could generate a very big map and walk around on it and see what happens.

If it's exclusive to the map editor it may be best to just override the function, although it may be an issue in both classes.

Twinklebear avatar Nov 05 '12 06:11 Twinklebear

What is the difference between Box and SceneBox?

btstevens89 avatar Nov 05 '12 17:11 btstevens89

So the scenBox is the size of the scene that's in the camera, so a 10x10 map is a 320x320 scene box. mBox is the size of the camera that we're looking through, so mBox should never be bigger than the sceneBox, but the sceneBox can be as big as it needs to be, and if it's bigger than the camera box, the camera will pan around the scene, following either a focus or pan instructions.

So centering is done to put mBox in the center of the window, and mBox x and y are clamped to be within the sceneBox and when setting either mBox or sceneBox a check is made to make sure mBox is <= the size of the sceneBox.

I probably should have a comment there haha, it is a bit confusing. Or maybe just clearer names.

Twinklebear avatar Nov 05 '12 17:11 Twinklebear

Then are scenebox.x and scenebox.y used for anything?

btstevens89 avatar Nov 06 '12 22:11 btstevens89

Not in the camera at the moment, it's assumed that the sceneBox starts at 0, 0. You can see this in the clamp operations for the camera x & y, where the minimum x,y is set as 0, 0 instead of sceneBox.x, sceneBox.y.

I guess it would be possible to use the values if for some reason the scenebox was to be put at 10, 10 or something, but i don't think that makes much sense to do.

so short answer, no. They're assumed to be 0

Twinklebear avatar Nov 07 '12 00:11 Twinklebear

Sounds good.

Another question, was there a reason you reused the mBox.X() and Y() in this function. Was it intentional?

void Camera::SetBox(Rectf box){
    //The camera box can't be bigger than the scene box
    if (mSceneBox.w != 0 && mSceneBox.h != 0){
        mBox.Set(box.X(), box.Y(),                           //Was mBox.X(), mBox.Y()
            Math::Clamp(box.w, 0, mSceneBox.w),
            Math::Clamp(box.h, 0, mSceneBox.h));
    }
    //If no scene box is set yet, just allow the change, as we check again 
    //when setting a scene box
    else
        mBox = box;
}   

btstevens89 avatar Nov 07 '12 01:11 btstevens89

Oh that looks like it was a mistake on my part, it doesn't make sense to set mBox to a new rect but keep the old position. That code is what it should be heh.

It may also make sense here to clamp the x & y to keep the camera from running outside of the scene, as is done in other areas of the code.

Edit: It looks like my intention may have been to make it resize the camera w & h, but that should be a different function than SetBox.

Twinklebear avatar Nov 07 '12 01:11 Twinklebear

As an aside for the editor ui elements (and any other ui elements you may have), you should take a look at the changes made in EntityManager vs. UIManager being closed when you're getting things ready to make a pull request (may not be a while, but a heads up on the changes)

Changing to the new method should be as simple as adding

"ui" : true,
"render" : true

to each of your ui elements and ui false to non-ui elements. The values are also switchable at runtime if you want to make some things disappear or move between ui and non-ui.

Twinklebear avatar Nov 07 '12 18:11 Twinklebear