-
Posts
7,936 -
Joined
-
Last visited
Content Type
Blogs
Forums
Store
Gallery
Videos
Downloads
Everything posted by Rick
-
You will want to keep 1 instance of all the textures/models you will ever use. Otherwise you'll run into pauses while loading.
-
Max cameras per map? GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
Rick replied to CangoJoe's topic in Programming
I would just make pivots for the pos/rot you want and then move/rotate the 1 camera in your game to these pivots when you need to and then snap it back to it's original position when done. -
Because it never hurts to learn other things
-
If you don't see it as an issue then that's fine. So many questions for knowing that quality loss happens when images are scaled. I'm exhausted already, and have lost interest in the battle
-
I'm not 100% sure what you are asking but it seems like you're asking can we have the same Lua script like behavior in C++ where maybe 1 class is the same as a Lua script and you assign said class to an entity? If that's the case then there is a way to do it. The engine callback functions in a Lua script have C++ callback equivalents. However those are global C function callbacks that will pass in an LE entity of the entity that's being called for. If you store an instance of the C++ class you want loaded for each entity "inside" the LE entity itself (using SetUserData() function that LE entities have). Then inside the C callbacks you can get that C++ class instance with (GetUserData() function from the passed in entity) and then call it's specific class method that matches that callback. If you look at the bottom of this page (http://www.leadwerks.com/werkspace/page/api-reference/_/entity/) the Hooks section. This shows you the global C hook functions that match the callbacks in Lua scripts. Every LE entity derives from Object (http://www.leadwerks.com/werkspace/page/api-reference/_/object/object-r25) and here you can see there is a SetUserData() function and GetUserData() function. You can create a pointer of an instance of a class and pass it in and get it out with those functions. There is also an AddHook() function that allows you to add those hooks I mentioned above to any entity. That means the engine will automatically call the C hook callback for that entity when it should. So now create a base class (that's like your Lua script) and have virtual functions that match all the possible hooks like: class MyBaseObject { protected: Entity* entity; public: void MyBaseObject(Entity* e) : entity(e) {} virtual void UpdateWorld(){} virtual void PostRender(){} // etc }; Now create specific classes that derive from this. These would be just like the specific Lua scripts you create on the Lua side. So for example: class Player : public MyBaseObject { public: void Player(Entity* e) : MyBaseObject(e) {} virtual void UpdateWorld() { /* do player specific update stuff*/ } // override all the virtuals you care about }; Now when you load the map you need to loop over all the world->entities and somehow identify what entity should get what C++ class instance. foreach(e in world->entities) { if(e->GetKeyValue("name") == "player") { // create a new instance of this class and "attach" it to the LE entity e->SetUserData((void*)new Player(e)); // assign all the callbacks to the entity here e->AddHook(Entity::UpdateWorldHook, (void)UpdateWorldCallback); } } void UpdateWorldCallback(Entity* e) { // pull out the user data we stored in this entity and cast it back to the base class MyGameObject* obj = (MyGameObject*)e->GetUserData(); // if the cast worked then call that specific objects virtual function UpdateWorld(). Now in our example we'll be in Player class UpdateWorld() function. if(obj != NULL) { obj->UpdateWorld(); } } Some of this is pseudo code but it shows the idea on how to mimic Lua script behavior in C++. You create all the global C callbacks/hooks. Inside them you cast the entity's user data to your base class that has all the virtual functions. Then you call that specific virtual function. Then you have to figure out a method after the world is loaded how to tell which C++ class you should create for what LE entity that was loaded in the map. One way is to do it by the name you give the entity in the editor like in my example. Since you can name things the same in the LE editor you can treat this name more like the C++ class you want to load. My example had an if statement to check that and that could get really long so a better way would be to have some kind of factory pattern where you are registering C++ class to a string name and then you are just matching those up when looping over the world entities that were loaded. Hope that made sense. It's a little setup to do on the C++ side of things but if you need specific help I can provide more help in an IM or something. I've done this setup in the past and it's worked out well.
-
Because you're asking every widget creator who wants to support non vector style widget images ( which I would think would be the majority because raster images are easier to create and are more creative than anything one can make with using drawing commands) to add this to their widget instead of the framework doing it built in? That means your not supporting non vector images for widgets in you GUI framework because you know they won't look good when there is only one version of them and you scale them and you're saying you don't care about that to unify how widget creators handle that problem. If that's the case then so be it but then your framework is marginalized some. It's not a framework that's solves these ui problems, and if that's the case what the benefit of it? Why would I use it if it's likely I'll run into a widget where the creator didn't know about the script above or worse yet they all make their own implementation and how they handle it is different and I have to remember for the button widget I'm using I have to do this system to image swap and for they combo of widget it's this method to image swap. What a pain that is. It's not needed if your GUI framework would offer a consistent way to handle this issue. That's the point of a framework is it not? Give a consistent way to do something? I guess the other option is to resample the image so the quality stays crisp no matter what size it is.
-
Here is a little bit of code that won't run or anything but it gets the idea across. From a widget creation standpoint here is what we'd do if we want to use a non vector image. -- Button.lua function Script:Start() self.normal = Widget:LoadImage("Materials/UI/button.png") -- in this UI directory there could be button1.png, button2.png, button3.png and/or just button.png end function Script:Draw() -- draw self.normal image end Leadwerks would define this as default but the user of the widgets could define this custom in main.lua if they wanted: -- main.lua -- this would be defaulted to some values but users could override it GUI.config[1] = { min = 0, max = 640 } GUI.config[2] = { min = 641, max = 720 } GUI.config[3] = { min = 721, max = 1920 } Then the framework implementation of Widget:LoadImage() which does the magic would look at the GUI.config table and compare the current screen width to get what index to use. Then it'll look to see if that image exists using the passed in image name as the "base". If it can't it'll keep looking and if no other "lod" images exist it'll just load the one passed in as a fallback that'll at least work (not give a run-time error) but won't look ideal when scaled to any resolution, but all the user of the widget has to do is add those 'lod" images later. -- leadwerks framework function (could be some engine function or whatever this is just an idea that we need a load image function that has some smarts behind it) function Widget:LoadImage(src) local screenWidth = Context:GetCurrent():GetWidth() local path = GetFilePath(src) local filename = GetFileNameFromPathWithoutExtension(src) local ext = GetFileExtension(src) local imageLOD = nil for i in ipairs(GUI.config) do if screenWidth >= GUI.config[i].min and screenWidth <= GUI.config[i].max then local f = filename..i..ext -- if a file with this number exists make it the file we will load if FileExists(f) then imageLOD = i break end end end -- if imageLOD stays nil then we don't look for an lod image we simply load the one they passed into this function, which won't scale but it'll allow something to make things not fail return Texture:Load(path..'/'..filename..(imageLOD or '')..ext) end
-
The process I have in mind allows things to work simply and with default behaviors but also lets people who are more serious about their game configure it. So the simple aspect needs to allow me to just load 1 image for my widget and have it scale. It will look bad at that point pending the resolutions but it'll work with no extra work at this point. That's key so entry is easy for people. Next step is to allow the user to simply make new image resolution files of the one image bit just append a number at the end of it. No code change needed by them. Your load image they used would be setup to look for this and load the right one based on the last step. The last step is to Allow the user to configure, but you also give a default config so they don't have to, what numbers are what resolution width. So I should be able to say 1 mean 0 to 640, 2 means 641 - 720, 3 means 721 to 1920. This is a framework that anyone can start with, just one image, and build apon once they realize they need it, because a lot of people don't know this problem until they are mostly done with the game and testing on different resolutions and things look bad. The learning curve for a user is easy and the ability to polish doesn't require any code changes to their ui code. Just adding image files and setting some config at the start of the app!
-
You click on trees without any tool equipped. Some trees don't have any sticks to offer and it's a variable amount of sticks that trees have. Currently it's a point and click game with A* pathfinding. It's like this to keep some things easier from an Indie standpoint. One of those being if/when multiplayer added it's easier to work with than real-time movement you'd get with WASD. Syncing movement becomes a lot easier to manage. You can think of it like Age of Empires or other RTS's in that respect,but we'll talk about this internally and see what we think. Currently when you click on grass we pathfind the tile the grass is on and move there. With other items like a log we just distance. We will look at this for consistency. Thanks for pointing this out! Thanks for your feedback. We really crave it to help shape the game!
-
This seems to be a decent place to get some vector graphics for testing: http://www.freepik.com/free-vector/colors-buttons-set_831742.htm
-
So really with you telling me "my" script could swap images you're saying your framework won't support non vector images for the UI's. If we play the scenario where you don't incorporate image swapping into your framework here is what we see. I create a button widget that uses non vector images and I do the swapping. Joe Blow creates a list view where my buttons are used as column headers that can be clicked to be sorted but he doesn't use image swapping because he doesn't know about it and doesn't seem to care. Nancy Smith uses Joe Blow's list view widget but notices at different resolutions the buttons look OK but the rest of the control looks bad. Or a game developer has to use some widgets from a handful of different people and some implemented image swapping and some didn't. You know that 1 non vector image file doesn't scale well to all screen resolutions yet you won't include image swapping in your framework so really you're saying you don't support non vector images in your framework but you'd want people who make widgets with non vector images to implement image swapping. If you want the users to do a certain thing then it's a prime candidate to be included in the framework as that's the point of a framework. Make a common way for users to do things.
-
I wasn't using it because I'm not drawing my ui controls. That seems crazy to me. I'm all about using images for that and you didn't have resolution independence before so there was no point. The framework structure is the easy part of UIs so it's of no benefit really to me. I'll test now that it seems you have this now. Complex controls are generally just a composite of simple controls. Controls are really 2 things. Events and visuals. You could have controls with just events and then we are just skimming the visuals in any fashion we want right.
-
Game developers would need to create their GUI gfx no matter what game they are making. With svg you'd be asking them to make their GUI images with an app that supports svg exports/gfx. It seems like your experience with GUIs is drawn from code but that's a small percentage of games that do that like half life did. Most games I play are image files for the GUI elements. I'm not sure what angle you are attacking here with this GUI framework.
-
I view that as very far from the same thing. If the art isn't vector graphics than scaling the same size image to any screen resolution won't work well. Image swapping is common when coding for mobile since the resolutions have a wide range. This is the issue with PC UIs. Having the ability to have the system swap images is one small but important step in a UI system. It's far from the main thing and seems strange to justify not creating one in general because of that. Event processing, resolution independence for size and position are very important aspects of a UI and they can be complicated for people to create on their own. You could support scalable vector graphics and avoid all of this I think. Supporting svg would be sweet I think. If you were to stick with image swapping it's not like the user has to do that. It should be an option that you can configure or auto configured but if no images exist it just keeps using the main one. It's really an optimization step.
-
From my experience downscaling will have issues as well with high resolution images. So ideally the system would be able to allow/or have auto swapping of images based on the screen resolution. Maybe something like button_1.png, button_2.png, button_3.png, etc and we can configure (but there is a default) what button number is used from a range of resolution widths (for example). If this system doesn't do stuff like that for us then the framework is minimized in it's use. The stuff you are finding is the hardest part about making a GUI for us all. The framework you have up until now is not the hard part and won't save anyone time or help anyone make a GUI that works beyond their testing on 1 resolution. It's this stuff that prevents people from making a GUI.
-
I think that's why you can't use %'s with this stuff. I won't put it in our game but one of the more complex controls that we have is the list view control for the high score. I can try this system out in a test project with that.
-
I took a page out of Aggror's and use Anchors for positioning and then I have a "units" for x,y,w,h. Also, when using images, I believe you have to have a system where you can have it swap what detailed image is used for a range of resolutions given what you've just pointed out. You can't pick 1 image resolution and have it scale nicely to any screen resolution. The hardest part about using "units" is that the values don't really make much sense and it's hard to position/scale things but in my opinion that's why placing and scaling in a wysiwyg editor is ideal for GUI. This is my entire gui code for anchor/position/scale (it also alters with keys when an element is selected), but all of the things you're running into is why users need a GUI system that does all of this for them. Because it's a pain in the *** to do it on our own . It's also why GUI's are entire libraries of their own. A lot goes into making a good system. if ui ~= nil then return end ui = {} ui.selectedElement = nil ui.Anchors = {} ui.Anchors.TopLeft = 0 ui.Anchors.TopCenter = 1 ui.Anchors.TopRight = 2 ui.Anchors.RightCenter = 3 ui.Anchors.BottomRight = 4 ui.Anchors.BottomCenter = 5 ui.Anchors.BottomLeft = 6 ui.Anchors.LeftCenter = 7 ui.Anchors.Center = 8 ui.anchorText = function(anchor) if anchor == 0 then return "Top Left" end if anchor == 1 then return "Top Center" end if anchor == 2 then return "Top Right" end if anchor == 3 then return "Right Center" end if anchor == 4 then return "Bottom Right" end if anchor == 5 then return "Bottom Center" end if anchor == 6 then return "Bottom Left" end if anchor == 7 then return "Left Center" end if anchor == 8 then return "Center" end end -- look at key presses to change the position/scale/anchor settings for given element ui.update = function() if ui.selectedElement == nil then return end local window = Window:GetCurrent() local moveScale = 0.001 -- position if window:KeyDown(Key.Left) then ui.selectedElement.x = ui.selectedElement.x - moveScale end if window:KeyDown(Key.Right) then ui.selectedElement.x = ui.selectedElement.x + moveScale end if window:KeyDown(Key.Down) then ui.selectedElement.y = ui.selectedElement.y + moveScale end if window:KeyDown(Key.Up) then ui.selectedElement.y = ui.selectedElement.y - moveScale end -- scale if window:KeyDown(Key.A) then ui.selectedElement.width = ui.selectedElement.width - moveScale end if window:KeyDown(Key.D) then ui.selectedElement.width = ui.selectedElement.width + moveScale end if window:KeyDown(Key.W) then ui.selectedElement.height = ui.selectedElement.height + moveScale end if window:KeyDown(Key.S) then ui.selectedElement.height = ui.selectedElement.height - moveScale end -- anchoring if window:KeyDown(Key.D1) then ui.selectedElement.anchor = ui.Anchors.TopLeft end if window:KeyDown(Key.D2) then ui.selectedElement.anchor = ui.Anchors.TopCenter end if window:KeyDown(Key.D3) then ui.selectedElement.anchor = ui.Anchors.TopRight end if window:KeyDown(Key.D4) then ui.selectedElement.anchor = ui.Anchors.RightCenter end if window:KeyDown(Key.D5) then ui.selectedElement.anchor = ui.Anchors.BottomRight end if window:KeyDown(Key.D6) then ui.selectedElement.anchor = ui.Anchors.BottomCenter end if window:KeyDown(Key.D7) then ui.selectedElement.anchor = ui.Anchors.BottomLeft end if window:KeyDown(Key.D8) then ui.selectedElement.anchor = ui.Anchors.LeftCenter end if window:KeyDown(Key.D9) then ui.selectedElement.anchor = ui.Anchors.Center end end ui.draw = function(context) if ui.selectedElement == nil then return end local pos = ui.getPosition(ui.selectedElement) local scale = ui.getScale(ui.selectedElement) context:DrawText("Selected ui element: "..ui.selectedElement.name, 0, 0) context:DrawText(string.format("x: %s, y: %s, w: %s, h: %s, anchor: %s", ui.selectedElement.x, ui.selectedElement.y, ui.selectedElement.width, ui.selectedElement.height, ui.anchorText(ui.selectedElement.anchor)), 0, 20) end ui.selectElement = function(e) ui.selectedElement = e end ui.pointOverElement = function(e) local pos = ui.getPosition(e) local scale = ui.getScale(e) local window = Window:GetCurrent() local mpos = window:GetMousePosition() if mpos.x < pos.x then return false end if mpos.x > pos.x + scale.width then return false end if mpos.y < pos.y then return false end if mpos.y > pos.y + scale.height then return false end return true end ui.getPosition = function(e) local res = {} res.width = context:GetWidth() res.height = context:GetHeight() return ui.GetPositionInPixels(e.anchor, e.x, e.y, res.height) end ui.getScale = function(e) local res = {} res.width = context:GetWidth() res.height = context:GetHeight() return ui.GetSizeInPixels(res, e.width, e.height) end ui.GetPositionInPixels = function(anchor, x, y, resHeight) local pos = {} pos.x = ui.XUnitsToPixels(anchor, x, resHeight) pos.y = ui.YUnitsToPixels(anchor, y, resHeight) return pos end ui.GetSizeInPixels = function(res, elementWidth, elementHeight) local size = {} size.width = ui.WidthUnitsToPixels(res, elementWidth) size.height = ui.HeightUnitsToPixels(res, elementHeight) return size end ui.WidthUnitsToPixels = function(res, eWidth) local size = 0 if res.height < res.width then size = res.height else size = res.width end return eWidth * size end ui.HeightUnitsToPixels = function(res, eHeight) local size = 0 if res.height < res.width then size = res.height else size = res.width end return eHeight * size end ui.XUnitsToPixels = function(anchor, x, resHeight) return ui.GetAnchorPoint(anchor).x + (x * resHeight) end ui.YUnitsToPixels = function(anchor, y, resHeight) return ui.GetAnchorPoint(anchor).y + (y * resHeight) end ui.GetAnchorPoint = function(anchor) local p = {} local context = Context:GetCurrent() local width = context:GetWidth() local height = context:GetHeight() if anchor == ui.Anchors.TopLeft then p.x = 0 p.y = 0 elseif anchor == ui.Anchors.TopCenter then p.x = (width / 2) p.y = 0 elseif anchor == ui.Anchors.TopRight then p.x = width p.y = 0 elseif anchor == ui.Anchors.RightCenter then p.x = width p.y = (height / 2) elseif anchor == ui.Anchors.BottomRight then p.x = width p.y = height elseif anchor == ui.Anchors.BottomCenter then p.x = (width / 2) p.y = height elseif anchor == ui.Anchors.BottomLeft then p.x = 0 p.y = height elseif anchor == ui.Anchors.LeftCenter then p.x = 0 p.y = (height / 2) elseif anchor == ui.Anchors.Center then p.x = (width / 2) p.y = (height / 2) end return p end
-
What does that button look like on a 640x480 screen vs a 1920x1080. ie are you handling scaling for us?
-
The hardest part of indie game development is often not the skill level a person is but time. Hope it works out for you.
-
Now that's what I'm talking about. I assume the background color to that is set with context's SetColor() so we can have transparent or any color? Now if you can figure out a way to have the font size be more dynamic because when dealing with different resolutions you'd want different font sizes. Maybe we can determine small/med/large font sizes that this uses or something? I've always thought the font style and the size shouldn't be tied so closely like it is as style is 1 thing and size you'd want more dynamic based on the screen resolution.
-
In your example if you print out mpac what does it show?
-
Is this packing library available in C++ as well? I wouldn't recommend anyone really having a Lua server but instead a C++ server app if possible.
-
I'd also recommend using the AnimationManager lua class that Josh has provided. It's just a nice utility class to deal with animation/blending/complete callback.
-
My vote is defining callbacks vs polling.
-
Which given the lua enet pre-built dll doesn't seem to be an option.