Jump to content

Rick

Members
  • Posts

    7,936
  • Joined

  • Last visited

Posts posted by Rick

  1. I usually think of the coding side when thinking about games created in this kid of setting. Coordinating is hard even when in person so doing it over the internet is even harder. So I'd prefer a game where we can have many pretty isolated scripts vs the bulk of the game being in 1 script (like the player script). This makes it easier to give someone a small script to create as long as the functionality is defined. Even if they don't know all the details about all the other scripts. It makes helping be a low barrier of entry I think. Nobody wants to read thousands of lines of code just to get caught up to help. It also makes it easier to expand on the game later.

    For that reason I personally think the Third person, low-poly, world exploration/monster fighting is a great choice. Each monster can have it's own script with their own personalities. Can have power-up type scripts that alter the player in some way. We can make some interesting level puzzle scripts.

  2. I’d like to see the map format be plain text and easier to work with honestly. That would open the doors to some external editors I think. The current editor would probably need to be more flexible in working with the map format as well. Ie be ok with added fields and not crash.

    One could make an added editor that adds functionality and fields to existing entities in the map file and then have some runtime library that uses those extra fields to run the functionality. 

    Thos idea requires a less rigid map file format. You’d suffer map loading times in the editor, could have a binary compile process for production maybe, but the flexibility would be worth it.

  3. 1 hour ago, Argent Arts said:

    If you make your code so that it is editable in the editor (like you already can via LUA) so the end-user can affect things like which direction a door opens (slides up, slides left, etc.), how fast it moves, etc., then you have a system of things that don't need to be coded. A door is a door, etc. And with the Flow Graph, setting up triggers and other such things becomes a breeze.

    The flowgraph leaves much to be desired at this point. It can become overwhelming and unorganized very quickly. Something like UDK has a more structured way of handling that and a more universal interface. LE's is fairly barebones and without having built in events that can be triggered per entity, how you set that up is custom to your game and your ideas and is not a common structure throughout the engine which hurts it. If LE entities had  a common set of events that we can then expand on, it would be more useful.

    Think of a "click" event. Something as simple as that. When you click an entity you want to raise an event. This should, in my view, be part of all entities. Picking entities is a very common task in games. You can do this in LE but it becomes very specific to your game. Entities can only have 1 script attached and handling that click has to be inside that 1 script. So you'll find yourself doing a lot of copy/pasting code and "surgery" to that script to get this functionality. Not ideal. If you could add multiple scripts to an entity then someone could make 1 script that handles a lot of these common events and you could attach that script without having to know anything about it. Then you add another script that is more specific to your game that has actions and then you could link them up via the flowgraph.

    The decision to only allow 1 script, which it sounds like Turbo will stick with, sounds like a thing that keeps things simple, but in reality it makes things more complicated because of the code management that you have to end up doing. You'll be duplicating code all over the place and it doesn't give users a chance to make an ecosystem around the event/action idea.

    There are ways to get around this but again most people don't know them or how to use them or because they aren't official it won't drive any interest from others and using it still requires some coding vs a pure UI approach. 

    Entities should have a bunch of events built in if you ask me:

    1. OnCollisionEnter
    2. OnCollisionLeave
    3. OnCollision
    4. OnHide
    5. OnShow
    6. OnClicked
    7. OnDblClicked
    8. OnDestroyed
    9. OnCreated
    10. OnTimer

    At the end of the day all games can be described with events and actions so having a better system to support those would be ideal. I also think it's easier for new people to think of things in that way. When this happens, do this. Easy.

    I also think allowing 1 flowgraph per entity would be good as well. I like having a scene level flowgraph too, but an entity flowgraph would allow non coders to create complex entities from smaller scripts.

    When flowgraphs were first introduced to LE I created what I called logical entities which didn't have a presence in the scene but would run code. You could do logical things like if's, loops, etc with them to make something complex without typing code but because you only get 1 flowgraph per scene it would become too unruly to work with.

    • Upvote 1
  4. I’ve never used that engine but looking it up the idea of actions and events is a thing I always thought made sense. Leadwerks sadly doesn’t get that high level though. I’m a big advocate to the event style programming model because it just makes sense. You can sort of set this up in Leadwerks but without editor support you won’t get an ecosystem of actions and events from the community going. It would be great to get action/event support for entities that we can expand via Lua scripts and link together in the editor. Josh doesn’t like being tied to that level of how users should make their app. 

  5. The forums are generally less busy when josh is working on a new major version of the engine. He generally loses some regulars when he does this too. I remember LE 4 suffered some community losses but he picks up new people with the new version.

     

  6. 2 minutes ago, Yue said:

    In Turbo, will it be possible to add multiple scripts to one entity?

    I think that would be tough to do given the functions/variables are right on the entity itself. If 2 scripts share names by chance you wouldn't be able to differentiate them.

    • Like 1
  7. 8 minutes ago, havenphillip said:

    How do you "loop over all entities in the world'? Talking about an AABB box?

     

    It's been awhile so I might mess this up, but CurrentWorld().entities I believe would be the list to loop over. Every entity loaded in the current world would be there. Even dynamic ones. It could be expensive so ideally do it on startup.

    • Like 1
    • Upvote 1
  8. I assume you mean entity scripts (scripts attached to entities). There would be a couple ways to do it.

    1. You could link the entity via a script properties. In the script you want to access the other script make a Script variable like say Script.otherEntity = nil --entity. In the properties you'll have a section for this that you can drag and drop another entity in your scene onto. Now you can access it's scripts variables via self.otherEntity.script.theVariableIWant.
    2. You could loop over all entities in the world and find the one(s) you want and then access it via entity.script.theVariableIWant.

    So the idea is once you get a hold of the entity itself it has a .script property which gives you access to it's script variables and functions and there are a couple ways to access an entity from another entity. If you have just a few design time entities #1 works well. If you have a lot or run-time entities then method 2 works well I think.

    • Like 1
    • Thanks 1
  9. Glad you got it working. I always wondered why LE didn't have this load/save mechanism built in. I know Josh said he didn't want to get into that area because saving is unique per game, but this general idea of Load/Save callbacks per script is flexible enough to let the developer decide what is saved and loaded while still giving some kind of common structure to do it at least. Glad someone got some use from the script.

  10. Yeah, the Vec3() might not save correctly so breaking them up is probably best or creating your own lua table to store them vs the Vec3 with:

    entityTable.pos = { x = pos.x, y = pos.y, z = pos.z }

     

    Not 100% sure though. It's been awhile.

    • Like 1
  11. It loads each time it sees an import but since you're importing the same thing (and generally it's definitions of functions and tables) it generally doesn't matter as the result is the same. If you want to avoid this you can do checks up front if something is defined or not to determine to do the rest of the script.

     

    util.lua

    if _UTIL_ ~= nil then return end
    
    -- define util so we only will define the util stuff once even if there are multiple imports of it
    _UTIL_ = {}
    
    --define util functions here

     

  12. It's been awhile since I created that, but the entity script LoadData() function passes in the table structure that you saved the data in. In your GenericItem you aren't doing that and you aren't using that. You're using entityTable variable which really is a global variable that you created in SaveData() which is a bad idea. Don't use globals like that. So the steps to try to fix would be.

     

    1. In SaveData change the creation of entityTable to have local in front of it (local entityTable = {}) so that it's just local to the function instead of global to the entire application.

    2. Put a parameter to Script:LoadData() so it looks like Script:LoadData(data). This data parameter is the data that was saved originally. It gets loaded in the same structure you saved it as. This means you don't use entityTable[2]. Instead you'd do data[2]. However, I'd advise you store the data in named variables instead of array indexes for easier reading. So in SaveData() do something like entityTable.name = name, entityTable.pos = pos, etc. Then read it back in data.name, data.pos.

     

    function Script:SaveData()
    
    	prefab = self.entity:GetKeyValue("prefab")
    	name = self.entity:GetKeyValue("name")
    	pos = self.entity:GetPosition()
    	rot = self.entity:GetRotation()
    	
    	local entityTable ={}
    	entityTable.name = name
    	entityTable.pos = pos
    	entityTable.rot = rot
    	entityTable.prefab = prefab
    
    	System:Print("Object"..name.. "At" ..rot.x)
    	return entityTable
    end
    function Script:LoadData(data)
    
    	rot = data.rot
    	pos = data.pos
    	self.entity:SetRotation(rot)
    	self.entity:SetPosition(pos)
    	System:Print('Entity Loaded')
    end

     

    But as far as the names go, you have to have unique names. How is it supposed to know the difference between 2 entities if they have the same name?

    • Like 1
  13. If that script just has functions in it then you can just call the functions as the import of the script will define the functions to be used. You can't just import an LE entity script like that and use it though. There are ways to get "classes" so you can do a self.whatever though. If you aren't an object oriented person then just define normal functions.

     

     

  14. I solved this by having the idea that everything is an "element" that has a bounding box area. That bounding box area (the size of the element) is the thing that's resized based on resolution so it looks the same between all resolutions. Then I have a label "widget" which is basically an element with just text. I can set the size of the text by setting it to be "x-small, small, medium, large, x-large, Fill". When the game starts it loads a bunch of fonts going up by 2 in size and stores them in a table. It then uses the font width and height functions to find the max font that fills the height and/or width (makes sure the font width/height isn't bigger than the bounding box of the element).

    Basically it starts at the biggest font loaded and goes down in size until the width and height fit into the element bounding box area. That's the fill font and all the other fonts are percentages of that. x-large = 80% of fill font, large = 70% etc (might not be exact numbers as I don't recall but you get the point). If the fill font size was 30 then x-large is 80% of 30 or 24. Since I only loaded fonts by multiples of 2 if the math works out to be an odd number (I truncate any decimals) then I subtract 1 to get the even number that is smaller so I know it'll fit. I mark the font as being used and assign that element that font object and any font in the table that isn't used is deleted from memory.

  15. I'd like to see some automatic configuration around this (if it doesn't already exist) based on a naming convention. Perhaps open the model and click one button that brings them all in with the same name and an underscore or perhaps the @ which is popular format for this kind of thing. Perhaps a dialog that shows all them and you can multi-select which ones you want to add.

  16. 3 hours ago, Josh said:

    There is no technical design I could put out that would result in an immediate ecosystem because it's a business problem, not a technology problem.

    If you removed the word immediate then I don't agree with this statement. Nothing is immediate we all know that, that technology supporting the growth of an ecosystem is a technology problem. One of the reasons FB got really popular is because they created a way to make FB apps. They created a technical way to support an ecosystem. It's a mindset of "If you build it, they will come". If you give a technically sound way to extend things then those 2.5% innovators will build your engine for you (to some extent). 

     

    3 hours ago, Josh said:

    My choice was to make new game templates and try to better support the second group (beginners) or to dive back into technology and re-attack the first segment again now that Leadwerks is a lot stronger than when I started.

    In my view it's a waste of your time to build templates. Let the 2.5% innovators do this for you. BUT, they need a standard way of doing this and they need your support and promotion (no technical needs here really just promotion stuff) of those things to gain credibility to the other groups. What could be an example of what you'd do around this? Well how about a more dynamic template system when someone creates a new game. That screen should be reading from some place online to list the templates available instead of local machine. There should be an official and community section of templates at the point of creating a new project. We should be then given a streamline way to create & publish these templates. When you create a means to do something officially, people create stuff for that.

    In my view your 2.5% innovators are an extension of any company. Often they are free labor because they do things out of love and learning and not profit. You've generally not empowered those 2.5% innovators for a fear of giving up some control I would think. The innovators have been marginalized because they are all doing things their own way and get no promotion or help from a framework that guides how things should be done and how users access their work. This is all about technology. This is about standard systems of game template creation/promotion and plugin type systems and standard ways to hook into LE. All which don't exist.

     

    3 hours ago, Josh said:

    This is the only way to penetrate a market segment where everyone by default prefers to use the incumbent.

    In my view Leadwerks selling point is it's simplicity. Period. Performance just has to be there and be competitive. It's a must have, not a selling point. Leadwerks attracts noobs because it's simple to use compared to the competition.

     

    *Disclaimer: The above was just my opinion. I'm just acting as a sounding board :)

    • Like 1
    • Thanks 1
    • Upvote 1
  17. The current state of the Main.lua is pretty bloated honestly. It's strange Josh says he likes the simplistic one when the current one has a ton of other stuff in it. I generally comment out/delete/change the current one to my liking. I guess nothing prevents me from doing the hook idea. I'll try that out. It's just always nice when there is a general hook system so ideas/systems can be easily shared between people. That's where I go with this stuff. We still have a harder time sharing systems between each other because of this. If I have a system that needs an update and a 2D drawing part and an init sections, explaining where to put those in Main.lua is kind of a pain and could be harder for a new person. Explaining where to put them in defined hooks is a little cleaner.

    The LE ecosystem is still the wild west. While there are good things about that, in my view there are more bad things about that. Unity's ecosystem is simply amazing. I'm not saying their product is good, I'm saying they've created a great ecosystem and their app store reflects this. It's much easier for programmers to create systems for others to use because they have a solid structure for that. They make design decisions to support that idea. LE does not and that's reflected in the limited workshop items and if most of them even work today without some getting into the details to configure/change to make them run.

    In my view when you create a good ecosystem it keeps people on your platform. It's why Windows wins vs Linux in the desktop world. Much better and more user friendly ecosystem. Little to no fiddling around to get some driver to work.

    These are reasons why "hooks" are important. Until that idea is introduced into LE, it'll always be the wild west and devs basically create their games from the ground up. Which as we see isn't that easy because of the amount of time and knowledge required to do so for a lot of different systems.

    @AggrorJorn as you're seeing I'm sure there is little incentive to create some kind of system or framework to help people. Trying to integrate such things without any sort of help from the LE platform makes it difficult to integrate into everyone's projects.

    From a business perspective having an ecosystem/platform is what every software company tires to do these days. Every system in Unity's app store helps expand Unity at no cost to Unity itself. Being a 1 man show in LE, Josh I would think you would want this because it basically outsources work for you. You can then pick the good ones to integrate into LE if you so decide. However, it's a feeling of losing control. I get that.

    • Thanks 1
  18. 38 minutes ago, Josh said:

    I really like the fact we can do this:

    
    CreateContext(CreateWindow())
    world = CreateWorld()
    CreateCamera(world)
    while window:KeyHit(KEY_ESCAPE)==false do
    	world:Update()
    	world:Render()
    end

    Do not like crazy hooks that take over your life.

    Except no game closes on pressing the escape key and games need ways to set the window size and do UI updating/drawing and other game loop stuff specific to the game that you can't think of. It's nice to look at the simplicity of this but this can't be used for any real game without modification which then gets into the issue at hand.

    On a side note it's even easier when we don't have to see the game setup and loop and just have a handful of functions that get called.

  19. 4 minutes ago, AggrorJorn said:

    I like your suggestion Rick. Still, I think lua files should not be updated in general. How often has the FPS player script changed throughout the years? This is what broke Project Saturn eventually. 

    Yeah that's true. The hook stuff should be there just for simplicity sake but not for this reason. I agree no lua files should be updated when updating a project. New projects should use the updated files though.

  20. OK, we used this in urWorld game.

     

    Below is the code you need to manipulate the images. It's an example. In this example we had a shape of a human body as the border of the progressbar and I think it had another image as the filler. I've also included the shaders you need to have too.

     

    if BodyTemp ~= nil then return end
    
    import "Scripts/UI/UI.lua"
    
    BodyTemp = {}
    
    function BodyTemp:Create(actor, OnFreezingTick)
    	local obj = {}
    
    	obj.thermBg = Texture:Load("Materials/UI/Gameplay/stat_background.tex")
    	obj.thermMask = Texture:Load("Materials/UI/Gameplay/stat_fill_mask.tex")
    	obj.thermFill = Texture:Load("Materials/UI/Gameplay/stat_fill.tex")
    	obj.thermOl = Texture:Load("Materials/UI/Gameplay/stat_border.tex")
    	obj.thermIc = Texture:Load("Materials/UI/Gameplay/stat_icon_bodyTemp.tex")
    	obj.thermFill:SetClampMode(true, true)
    	obj.maskShader = Shader:Load("Shaders/Drawing/gui.shader")
    	obj.drawShader = Shader:Load("Shaders/Drawing/drawimage.shader")
    
    	obj.name = "Body Temp Stat"
    
    	obj.max = 100
    	--obj.bodyTemp = obj.max
    	obj.bodyTemp = 10
    	
    	obj.bodyTempCheckInterval = 2500
    	obj.bodyTempLastInterval = Time:GetCurrent()
    
    	obj.owner = actor
    	obj.OnFreezingTick = OnFreezingTick
    
    	--obj.x = 5
    	--obj.y = 4
    	obj.x = 0.0100
    	obj.y = -0.177
    	obj.ratio = obj.thermMask:GetHeight() / obj.thermMask:GetWidth()
    	--obj.width = 48
    	--obj.height = obj.width * obj.ratio
    	obj.width = 0.0700
    	obj.height = 0.1650
    	obj.anchor = ui.Anchors.BottomLeft
    
    	obj.freezingInterval = 5000
    	obj.lastFreezingTick = 0
    
    	local k,v
    	for k,v in pairs(BodyTemp) do
    		obj[k] = v
    	end
    
    	return obj
    end
    
    function BodyTemp:Increase(value, source)
    	self.bodyTemp = self.bodyTemp + value
    	self.bodyTemp = Math:Min(100, self.bodyTemp)
    	self.bodyTemp = Math:Max(0, self.bodyTemp)
    end
    
    function BodyTemp:Decrease(value)
    	self.bodyTemp = self.bodyTemp - value
    	self.bodyTemp = Math:Min(100, self.bodyTemp)
    	self.bodyTemp = Math:Max(0, self.bodyTemp)
    end
    
    function BodyTemp:Update()
    	if self.bodyTemp > 0 then
    		if Time:GetCurrent() >= self.bodyTempCheckInterval + self.bodyTempLastInterval then
    			self.bodyTempLastInterval = Time:GetCurrent()
    			self:Decrease(1)
    		end
    		self.lastFreezingTick = Time:GetCurrent()
    	end
    
    	if self.bodyTemp == 0 then
    		if Time:GetCurrent() >= self.freezingInterval + self.lastFreezingTick then
    			self.lastFreezingTick = Time:GetCurrent()
    			self.OnFreezingTick(self.owner)
    		end
    	end
    
    	-- for pos/scale
    	--if Window:GetCurrent():MouseDown(2) then
    	--	if ui.pointOverElement(self) then
    	--		ui.selectElement(self)
    	--	end
    	--end
    end
    
    function BodyTemp:Draw(context)
    	context:SetBlendMode(Blend.Alpha)
    
    	local pos = ui.getPosition(self)
    	local scale = ui.getScale(self)
    
    	context:SetShader(self.drawShader)
    	context:SetColor(1, 1, 1, 1)
    	context:DrawImage(self.thermBg, pos.x, pos.y, scale.width, scale.height)
    	
    	context:SetColor(1, 1, 1, (self.bodyTemp / self.max))
    	context:SetShader(self.maskShader)
    	self.thermFill:Bind(1)
    	context:DrawImage(self.thermMask, pos.x, pos.y, scale.width, scale.height)
    
    	context:SetColor(1, 1, 1, 1)
    	context:DrawImage(self.thermOl, pos.x, pos.y, scale.width, scale.height)
    
    	context:DrawImage(self.thermIc, pos.x, pos.y, scale.width, scale.height)
    	
    	--[[
    	context:SetShader(self.drawShader)
    	context:SetColor(1, 1, 1, 1)
    	context:DrawImage(self.thermBg, self.x, context:GetHeight() - self.height - self.y, self.width, self.height)
    	
    	context:SetColor(1, 1, 1, (self.bodyTemp / self.max))
    	context:SetShader(self.maskShader)
    	self.thermFill:Bind(1)
    	context:DrawImage(self.thermMask, self.x, context:GetHeight() - self.height- self.y, self.width, self.height)
    
    	context:SetColor(1, 1, 1, 1)
    	context:DrawImage(self.thermOl, self.x, context:GetHeight() - self.height - self.y, self.width, self.height)
    
    	context:DrawImage(self.thermIc, self.x, context:GetHeight() - self.height - self.y, self.width, self.height)
    	]]
    
    	context:SetColor(Vec4(1))
    	context:SetBlendMode(Blend.Solid)
    end

     

    Shader (drawimage shader might already be part of LE and I don't think it changed but including it anyway):

     

    gui.shader

    SHADER version 1
    @OpenGL2.Vertex
    #version 400
    
    uniform mat4 projectionmatrix;
    uniform mat4 drawmatrix;
    uniform vec2 offset;
    uniform vec2 position[4];
    uniform vec2 texcoords[4];
    
    in vec3 vertex_position;
    in vec2 vertex_texcoords0;
    
    out vec2 vTexCoords0;
    
    void main(void)
    {
    	gl_Position = projectionmatrix * (drawmatrix * vec4(position[gl_VertexID], 0.0, 1.0));
    	vTexCoords0 = texcoords[gl_VertexID];
    }
    @OpenGLES2.Vertex
    
    @OpenGLES2.Fragment
    
    @OpenGL4.Vertex
    #version 400
    
    uniform mat4 projectionmatrix;
    uniform mat4 drawmatrix;
    uniform vec2 offset;
    uniform vec2 position[4];
    uniform vec2 texcoords[4];
    
    in vec3 vertex_position;
    in vec2 vertex_texcoords0;
    
    out vec2 vTexCoords0;
    
    void main(void)
    {
    	gl_Position = projectionmatrix * (drawmatrix * vec4(position[gl_VertexID], 0.0, 1.0));
    	vTexCoords0 = texcoords[gl_VertexID];
    }
    @OpenGL4.Fragment
    #version 400
    
    uniform vec4 drawcolor;
    uniform sampler2D texture0;
    uniform sampler2D texture1;
    
    in vec2 vTexCoords0;
    
    out vec4 fragData0;
    
    void main(void)
    {
    	vec4 gui=texture(texture0,vTexCoords0);
    	
    	if (gui.r == 0. && gui.a > 0.)
    	{
    		gui.a = 0;
    		gui = texture(texture1,vTexCoords0);
    		if (1-drawcolor.a > vTexCoords0.y) gui.a=0;
    	}
        fragData0 = gui;
    }

     

    drawimage.shader

    SHADER version 1
    @OpenGL2.Vertex
    #version 400
    
    uniform mat4 projectionmatrix;
    uniform mat4 drawmatrix;
    uniform vec2 offset;
    uniform vec2 position[4];
    uniform vec2 texcoords[4];
    
    in vec3 vertex_position;
    in vec2 vertex_texcoords0;
    
    out vec2 vTexCoords0;
    
    void main(void)
    {
    	gl_Position = projectionmatrix * (drawmatrix * vec4(position[gl_VertexID], 0.0, 1.0));
    	vTexCoords0 = texcoords[gl_VertexID];
    }
    @OpenGLES2.Vertex
    
    @OpenGLES2.Fragment
    
    @OpenGL4.Vertex
    #version 400
    
    uniform mat4 projectionmatrix;
    uniform mat4 drawmatrix;
    uniform vec2 offset;
    uniform vec2 position[4];
    uniform vec2 texcoords[4];
    
    in vec3 vertex_position;
    in vec2 vertex_texcoords0;
    
    out vec2 vTexCoords0;
    
    void main(void)
    {
    	gl_Position = projectionmatrix * (drawmatrix * vec4(position[gl_VertexID], 0.0, 1.0));
    	vTexCoords0 = texcoords[gl_VertexID];
    }
    @OpenGL4.Fragment
    #version 400
    
    uniform vec4 drawcolor;
    uniform sampler2D texture0;
    
    in vec2 vTexCoords0;
    
    out vec4 fragData0;
    
    void main(void)
    {
    	fragData0 = drawcolor * texture(texture0,vTexCoords0);
    }

    I should really add this to the workshop and get more formal with it for people to easily use it. Maybe I'll do that this weekend.

    • Like 2
    • Thanks 1
×
×
  • Create New...