Jump to content

Josh

Staff
  • Posts

    23,339
  • Joined

  • Last visited

Blog Entries posted by Josh

  1. Josh
    A new update is available on the beta branch. A few months ago, Valve introduced the SteamUGC API to Steamworks SDK. This replaces the original RemoteStorage API, and allows unlimited file sizes and a simpler command set. I also suspect the internals in the Steam client and servers are more reliable, because it is a second-iteration design. The beta build can download Workshop items published with the old legacy API, or with the new one. However, Workshop items published with the beta build will not be downloadable by the release build until version 3.5 is released. I am implementing this now because I think it will be more future-proof, and because I suspect it will solve some problems people have had syncing Workshop items.
     
    A command-line switch has been added to allow Leadwerks to automatically install Workshop items. This is now integrated together with the Steam browser protocol in our site, so that pressing the "Install" button on a Workshop item's page will launch Leadwerks and install the item. (This requires the beta build):
    http://www.leadwerks.com/werkspace/page/viewitem_?fileid=429595109
     
    The games section by default is now showing Workshop games from Leadwerks Game Launcher. If you have the Leadwerks Game Launcher beta, you can press the "Play" button to automatically launch a game in Steam. Games will show up automatically when they are published to the Workshop.
     

     
    A new Screenshots section on the site displays in-game screenshots people have uploaded from Leadwerks Game Launcher. By default Leadwerks Game Launcher screenshots are set to private because the application is unreleased. However, you can change this setting on the screenshot's page in Steam, and it will appear in the stream.
     

     
    These changes are all part of the overall direction Leadwerks is going in, which will benefit all members in our ecosystem, including developers, artists, and players.
  2. Josh
    The beta branch on Steam has received an update with some important changes.
    A new project template called "Tutorial Samples" has been added, which includes the files you need to complete the new tutorials found here.
    A new script, Main.lua, has been introduced to take over the main entry point of your program. As explained in detail here, this will have no effect on your existing projects.
    The screenshot publish feature is fixed.
    Flowgraph arguments no longer require the EnableLegacyFeatures setting to be enabled.
    A sweet new welcome page has been designed.

     
    (Build 621802 was updated to 626936.)
  3. Josh
    The Workshop in Leadwerks Editor has been updated to use the same web interface as the game launcher. Page numbers have also been added to both. In the future, the Leadwerks Workshop interface will probably start to resemble the Game Launcher interface more.
     

  4. Josh
    To help with your games in the Summer Games Tournament, Rich DiGiovanni has created a fun set of summer-themed models, including a beautiful sandy terrain texture for laxing out at the beach.
     

     
    You can install this pack free from the Leadwerks Workshop:
    http://www.leadwerks.com/werkspace/page/viewitem?fileid=464751401
     
    If you need any custom models made, check out Ancient Idol Studio for quality work at reasonable rates.
  5. Josh
    I previously reported that Leadwerks Game Launcher had obtained 4000 users. My records in Steam have changed and it now reflects a user base of 1765 users. I think the reporting for free applications was not working correctly, because this number is much closer to what I would expect based on game subscriptions.
     
    The application is still in early release mode and has not been officially launched, and it will have low visibility before the final release. This gives us a period of time to work out any glitches, add support for SteamOS, and add to the number of games offered.
  6. Josh
    You may have noticed our deferred decals (presently in beta) tend to shift with distance. Something was wrong with the screen space to world space conversion, but it's a hard problem to describe. I wrote a function based on the work Igor did for his SSLR shader, like this:

    vec4 ScreenPositionToWorldPosition(in vec2 texCoord) { float x = (texCoord.s / buffersize.x - 0.5) * 2.0; float y = (texCoord.t / buffersize.y - 0.5) * 2.0; float z = texelFetch(texture5, ivec2(texCoord),gl_SampleID).r; vec4 posProj = vec4(x,y,z,1.0); vec4 posView = inverse(projectioncameramatrix) * posProj; posView /= posView.w; posView+=cameraposition; return posView; }
     
    OpenGL stores depth values in a non-linear manner, which yields more precision closer to the camera. This allows a 24-bit depth buffer to cover a much greater distance than a linear depth buffer would allow with acceptable visual fidelity. The problem with the above equation is that the exponential value isn't being converted back into a linear value before being multiplied by the inverse camera projection matrix.
     
    I found a PDF with a formula I had come across before and started messing around with it: The trick is this:

    lineardepth = exponentialdepth / 0.5 - 1.0
     
    This equation can change if you have set glDepthRange to anything other than the defaults. (Coincidentally, calling glDepthRange() was what messed up my deferred renderer for iPad a couple years ago and forced me to use an extra floating-point buffer for storing screen depth at my GDC talk.)
     
    Plugging this into my function and eliminating the camera position add results in the following code:

    vec4 ScreenPositionToWorldPosition(in vec2 texCoord) { float x = (texCoord.s / buffersize.x - 0.5) * 2.0; float y = (texCoord.t / buffersize.y - 0.5) * 2.0; float z = texelFetch(texture5, ivec2(texCoord),gl_SampleID).r; z = z / 0.5 - 1.0; vec4 posProj = vec4(x,y,z,1.0); vec4 posView = inverse(projectioncameramatrix) * posProj; posView /= posView.w; return posView; }
     
    This also eliminated a couple of strange divide by twos I had in the texture mapping, which didn't really make sense to me at the time. Below you can see a decal rendered on a surface from a far distance, with no inaccuracies in the texture alignment.
     

     
    In reality, this was probably about five hours of work with "River Monsters" playing in the background.
  7. Josh
    Leadwerks Game Launcher is now marked as "Ready for Review" by Valve and scheduled for release Monday, August 24. I decided to allow one week for final testing of Leadwerks Game Engine 3.6, which will be released at the same time (and to try to get a few more games in before the release). The application will be released as a free "early access" software application (and will remain free). There's a good lineup of games that are pretty enticing, and the price point will gain a lot of enthusiasm for your games and demos.
     
    My target is to bring you 10,000 players for your games by Christmas. This will help you build a fanbase, get useful feedback, and will make it easy to recruit help or conduct a successful Kickstarter or Greenlight campaign for your game. It's important to manage expectations for this application and not give the wrong impression about what it is. Our Workshop games are not going to be what every Steam user wants, but I believe there is a market segment that wants to play something a little more experimental and "off the beaten path", instead of the latest generic AAA shooter. My description makes it clear what kind of gamer we are targeting with this, so that we can build a cult following for your games.
     
    If you want to publish a game before next week, contact me to receive a free beta key to get access to the program early.
     

  8. Josh
    An update is available on the beta branch. This will improve rendering speed of uncollapsed brushes in-game. You may also see a speed increase in the editor when viewing maps with lots of CSG brushes. You can read about this in detail in this thread.
     
    Lunarovich's suggestion here has also been implemented.
     
    I also tweaked a few stock prefabs and the FPS example map. The crates and boxes will now all use the dynamic shadow setting, and the red cage light prefab is set to only cast static shadows now. This prevents a lot of excessive shadow rendering in the big elevator room, since each point light requires six passes. You can see in the screenshot below the monsters aren't casting shadows from the red light on the right, but they are casting a shadow from the big overhead spotlight. It looks good and the performance is a lot more consistent now.
     

     
    Don't forget we are scheduling a Google Hangout Saturday the 5th at 1:00 PM PST to review the release of Leadwerks Game Launcher.
  9. Josh
    I'm very happy with the progress our community as a whole is making. Instead of getting distracted with endless technical features, we're releasing games.

    Lean Game Development
    The Lean Startup Methodology basically states that life is too short to build a product no one wants. Companies invest years in development to release a product onto the market, only to discover that early design flaws doomed the product from the start. Lean Startup Methodology posits that one should release a minimum viable product before investing too much time in an idea that might be quite a ways of from what your user really wants. The idea is to put something out, get a response, use that response to formulate ideas, and then release again. This is how Leadwerks Game Launcher is meant to be used as a tool. 

     
    Many people have completed the first three steps and have a product out now that other people are playing. The next step is to measure the response to your product. This can be done in two ways.
     
    Quantitative data is numerical or categorical data that is measured in a uniform manner. The number of subscribers to your game is one piece of quantitative data. Quantitative is easy to analyze with a formula, but the only data you will get are the metrics you record; If your number of players goes down, you don't really have any idea why.
     
    Qualitative data is open-ended feedback. Comments on your game's Workshop page are an example. Qualitative data is useful because it helps reveal information you did not specifically ask for, but it can be difficult to compare among subjects, because the information isn't easily quantified.
     
    At this stage in your game I recommend using a tool that can provide both quantitative and qualitative feedback. This tool is usability testing,and we have a way to easily perform it in Steam.

    Usability Testing with Steam Broadcasts
    Steam broadcasting allows you to view another player's game in real-time. Want to find out how a new player actually performs in your game? Want to find out where people are running into problems, getting frustrated, or getting bored? The truth is, user feedback isn't always that useful. Only a small percentage of your players will bother commenting about anything, and their opinions aren't necessarily reflective of your users as a whole. On top of that, users are pretty bad at describing what they really want because it's not their job to design your product. Usability testing allows you to find major usage problems in an objective manner without relying on the opinions of a few vocal players. 
    You can use Steam Broadcasting either by requesting to watch a player's game, or inviting someone to watch yours. To request to watch a game, just select the "Watch Game" menu item from your friend list, while the player is Leadwerks Game Launcher.
     

     
    If you want to invite someone to watch your game, this can be easily done by inviting them in the chat dialog. (You can open the Steam overlay while you are in-game and open a chat dialog from there.)
     

     
    Once the broadcast has started, you will see the video in the Steam interface.
     

     
    The great thing about usability testing is it doesn't take much effort or time. If you have glaring problems that people get stuck on, you will find them very quickly with this method. I think you will be very surprised when you see how people are actually playing your game, and it will become immediately clear what needs to be fixed.
     
    To get the most out of usability testing, I recommend the following:
    Use subjects who are completely new to your game and have never played it before.
    Don't bother testing more than three people. Any more than that is a waste of time. Trust me, they will find problems you had no idea existed, and it will be really clear afterwards what needs to be improved.
    Measure your results. You should write down notes as they are playing, and also measure some quantitative values like how many people got through a level or were able to accomplish some task.
    Don't answer questions or help the player, just passively watch.

     
    Once your usability testing is complete, now you have real actionable data! Read over that data, learn from it, and use it to come up with ideas how you can make your game better. Build a new version,publish, and repeat. Your steps are as follows:
    Perform usability tests and record data.
    Quantitative data (number of players that completed a task, time taken, etc.)
    Qualitative data (notes)
    [*]Analyze data and come up with ideas for improvement.
    [*]Release a new version and repeat.


     
    This approach will help you create a game people love instead of guessing what players want and working blindly. Don't wait until after your game is released to find out what you did wrong. Release early, test, and learn how people are really playing your game.
  10. Josh
    I just got a ticket to GamesBeat 2015 Summit. Message me if you'd like to meet up during the event.
    https://www.linkedin.com/profile/view?id=AAMAAABZ4BAB_h-adCunzdSr7r90HFOdx_MLrow
  11. Josh
    Based on the results of the summer games tournament, we can expect each new tournament to produce about 10 games:
    http://www.leadwerks.com/werkspace/blog/41/entry-1510-leadwerks-summer-games-tournament-results/
     
    Right now we're at 35, which means by the end of the winter games tournament it is reasonable to expect 50 Game Launcher games.
     
    My Steam Workshop changes are now implemented to provide more reliable downloads.
     
    Support for SteamOS will be added in November, with a full-screen GUI that works with a controller.
     
    So here's my tentative schedule:
    November 20: SteamOS support added.
    January 15: Game Launcher switches to full release mode with 50 games, appears on Steam new releases.
  12. Josh
    The Workshop interface will now more closely match our website. Item pages will now display videos, multiple images, and other information about the items.
     

  13. Josh
    The Workshop interface is updated with new options to let you quickly find items to use in your games.
     

     
    When you buy an item, you will now be directed to the Steam purchase page in the editor interface itself, without having to sign into an external web browser.
     

  14. Josh
    The beta branch contains a small update which affects the SoldierAI and Projectile scripts. The SoldierAI script now has a modifiable field that lets you choose a prefab for the projectile his weapon fires. The default value is "Prefabs\Projectiles\tracer.pfb" so your existing instances of these objects will be unaffected.
     
    By making the projectile prefab a modifiable value, we can use different types of projectiles with this script. For example, a medieval archer could fire arrows by creating a new prefab using a model of an arrow with the projectile script attached to it. Other types of weapons can be set up like energy weapons or rocket launchers. For example, you could create a "chicken gun" by selecting a prefab for the projectile that used a chicken model with the MonsterAI script attached to it.
  15. Josh
    In this series of blogs I am going to describe my implementation of AI for a new Workshop Store model, the Leadwerks turret. The model is shown below, without the weapon inserted.
     

     
    Before writing any code I first decided the main behaviors I wanted this script to involve.
    The turret should scan the area to identify an enemy (using the team ID to differentiate between enemy types) and choose the closest target. Unlike the soldier AI, the turret AI will not change targets when another enemy attacks it.
    If the target is lost or occluded, another target will be chosen.
    The turret will fire a continuous rapid stream of bullets whenever an enemy is in view. We want this to be an obstacle you have to take cover from, or you will quickly be killed.
    The turret can be killed by either incurring enough damage to bring the health down to zero, or by knocking it over to deactivate it. If the turret is damaged to the point of "death" it will shoot sparks out once and then emit a cloud of smoke. The smoke will be continuous, to clearly indicate the turret is inactive.
    The turret movement will not use the physics system. The model is relatively small and I can't think of any really useful reasons I would want the motion to interact with physics, so I'm not going to implement this.

     
    The first draft of the script uses the World:ForEachEntityInAABB() function to perform a search and find a target enemy within a certain range. I set a breakpoint at line 18 to confirm that the script was successfully finding the player: Notice that a distance check is used so the turret will locate the closest enemy.

    Script.target = nil--enemy to shoot Script.mode = "idle" Script.lastsearchtime=0 Script.searchfrequency = 500 Script.range = 20 function TurretSearchHook(entity,extra) if entity.script~=nil then if type(entity.script.health)=="number" then if entity.script.health>0 then local d = extra:GetDistance(entity) if d<extra.script.range then if extra.script.target~=nil then if extra.script:GetDistance(extra.script.target)>d then extra.script.target = entity.script end else extra.script.target = entity.script end end end end end end function Script:UpdateWorld() --Search for target if self.target==nil then local currenttime = Time:GetCurrent() if currenttime - self.lastsearchtime > self.searchfrequency then self.lastsearchtime = currenttime local pos = self.entity:GetPosition(true) local aabb = AABB(pos - Vec3(self.range), pos + Vec3(self.range)) self.entity.world:ForEachEntityInAABBDo(aabb,"TurretSearchHook",self.entity) end end end
  16. Josh
    Yesterday I tried a plugin I've been meaning to try out for a long time, Steam Sign-in for IPB. It worked without a hitch and I was able to easily figure out how to locate a Steam ID from a forum account, and vice versa. You can sign straight into Leadwerks using your Steam ID, or you can add a Steam ID to your existing account. (See "Edit Profile".)
     
    The gallery, videos, Workshop, and games sections will now correctly link to your Leadwerks profile page. Notice when you click on the author's name, it now navigates to their forum profile page:
    http://www.leadwerks.com/werkspace/page/viewitem?fileid=634076765
     
    This also will allow me to add sections in your profile to show all your screenshots, videos, Workshop items, and games. A Steam badge will be shown next to your forum posts that links to your Steam profile.
     
    But wait, there's more we can do with this. Here are some of the ideas I've wanted to try for a long time:
    Display statistics like hours played and boxes created next to your forum posts.
    Display your achievements in the forum (and add some more!)
    Add achievements for forum posts, blogs, etc.
    Add achievements that unlock free custom assets.
    Gamify the game creation and learning process. (Quizzes?)
    Gain more transparency on how people are actually using the engine.

     
    Basically, this allows us to integrate community interaction with the editor usage more closely. I'm not exactly sure how it will work out, but it allows us to try a lot of new ideas in the future.
  17. Josh
    An update is available on the beta branch. This adds the Window::Center style back into the new refactored Window class, and adds a missing header file in the Professional Edition.
     
    If you'd like to try out a basic implementation of the new GUI, download and extract the attached scripts:
    Scripts.zip
     
    This code will create a GUI on the rendering context. It simply consists of a solid background filling the screen and a textless button.

    --Initialize Steamworks (optional) Steamworks:Initialize() --Set the application title title="test" --Create a window local windowstyle = window.Titlebar + window.Resizable if System:GetProperty("fullscreen")=="1" then windowstyle=windowstyle+window.FullScreen end window=Window:Create(title,0,0,System:GetProperty("screenwidth","1024"),System:GetProperty("screenheight","768"),windowstyle) --window:HideMouse() --Create the graphics context context=Context:Create(window,0) if context==nil then return end --Create a world world=World:Create() world:SetLightQuality((System:GetProperty("lightquality","1"))) --Load a map local mapfile = System:GetProperty("map","Maps/start.map") if Map:Load(mapfile)==false then return end --Create a GUI local gui = GUI:Create(context) gui:GetBase():SetScript("Scripts/GUI/Panel.lua") local widget = Widget:Create(20,20,75,30,gui:GetBase()) widget:SetScript("Scripts/GUI/Button.lua") while window:KeyDown(Key.Escape)==false do --If window has been closed, end the program if window:Closed() then break end --Handle map change if changemapname~=nil then --Clear all entities world:Clear() --Load the next map Time:Pause() if Map:Load("Maps/"..changemapname..".map")==false then return end Time:Resume() changemapname = nil end --Update the app timing Time:Update() --Update the world world:Update() --Render the world world:Render() --Render statistics context:SetBlendMode(Blend.Alpha) if DEBUG then context:SetColor(1,0,0,1) context:DrawText("Debug Mode",2,2) context:SetColor(1,1,1,1) context:DrawStats(2,22) context:SetBlendMode(Blend.Solid) else --Toggle statistics on and off if (window:KeyHit(Key.F11)) then showstats = not showstats end if showstats then context:SetColor(1,1,1,1) context:DrawText("FPS: "..Math:Round(Time:UPS()),2,2) end end --Refresh the screen context:Sync(true) end
     
    This code will create the same GUI directly on the window, with no rendering context initialized, using the native OS drawing commands:

    --Initialize Steamworks (optional) Steamworks:Initialize() --Set the application title title="test" --Create a window local windowstyle = window.Titlebar + window.Resizable if System:GetProperty("fullscreen")=="1" then windowstyle=windowstyle+window.FullScreen end window=Window:Create(title,0,0,System:GetProperty("screenwidth","1024"),System:GetProperty("screenheight","768"),windowstyle) --window:HideMouse() --Create a GUI local gui = GUI:Create(window) gui:GetBase():SetScript("Scripts/GUI/Panel.lua") local widget = Widget:Create(20,20,75,30,gui:GetBase()) widget:SetScript("Scripts/GUI/Button.lua") while window:KeyDown(Key.Escape)==false do --If window has been closed, end the program if window:Closed() then break end end
     
    The second example isn't really useful for games, but it will allow me to build a cross-platform UI for our own tools, and create an official GUI for in-game use, all in one step.
  18. Josh
    An update is available on the beta branch. This includes all recent bug fixes, and is a full build with C++ libs for Windows and Linux.
     
    The following header search path needs to be added to your Visual Studio projects:
    $(LeadwerksHeaderPath)\Libraries\glslang
  19. Josh
    It took a few hours to add scrolling to the textfield widget. Now when the caret moves beyond the bounds of the box, text will slide over to keep the caret visible. This really isn't much different from a full text editor. The script is available now on the beta branch on Steam and presently weights in at 381 lines of Lua code.
     


     
    The Draw function is pretty short and easy to understand. I think most people will customize the appearance of these widgets more than the behavior:

    function Script:Draw(x,y,width,height) local gui = self.widget:GetGUI() local pos = self.widget:GetPosition(true) local sz = self.widget:GetSize(true) local scale = gui:GetScale() local item = self.widget:GetSelectedItem() local text = self.widget:GetText() self:UpdateOffset() --Draw the widget background gui:SetColor(0.2,0.2,0.2) gui:DrawRect(pos.x,pos.y,sz.width,sz.height,0) --Draw the widget outline if self.hovered==true then gui:SetColor(51/255/4,151/255/4,1/4) else gui:SetColor(0,0,0) end gui:DrawRect(pos.x,pos.y,sz.width,sz.height,1) --Draw text selection background if self.sellen~=0 then local n local x = gui:GetScale()*self.textindent local px = x local fragment = self:GetSelectedText() local w = gui:GetTextWidth(fragment) local c1 = math.min(self.caretposition,self.caretposition+self.sellen) local c2 = math.max(self.caretposition,self.caretposition+self.sellen) local prefix = String:Left(text,c1) px = px + gui:GetTextWidth(prefix) gui:SetColor(0.4,0.4,0.4) gui:DrawRect(pos.x + px + self.offsetx, pos.y+2*scale,w,sz.height-4*scale,0) end --Draw text gui:SetColor(0.75,0.75,0.75) if text~="" then gui:DrawText(text,scale * self.textindent + pos.x+self.offsetx,pos.y,math.max(sz.width,sz.width-self.offsetx),sz.height,Text.Left+Text.VCenter) end --Draw the caret if self.cursorblinkmode then if self.focused then local x = self:GetCaretCoord() gui:DrawLine(pos.x + x + self.offsetx,pos.y+2*scale,pos.x + x + self.offsetx,pos.y + sz.height-4*scale) end end end
  20. Josh
    I've got the Steamworks HTML renderer working with Leadwerks GUI now. The current build on Steam uses the Windows HTML renderer, which is part of IE. This isn't cross-platform, which is one reason why game launcher isn't available for Linux right now. The Chromium-based Steamworks HTML renderer is cross-platform but there are some issues.
     
    The HTML renderer works by rendering a web page into a memory buffer and then uploading that buffer to a texture and drawing it onscreen. The visible rendering is performed in a 3D graphics context, which means the Steam overlay will appear in it. So for example, it shows the little notification box in the lower-right popping up when you start the application. In Leadwerks Editor, we have the Steam overlay disabled for the entire application. This prevents the Steam overlay from appearing on all the viewports and 3D views in Leadwerks. This is also why games launched from Leadwerks Editor do not display the Steam overlay.
     
    In game launcher, we DO want the overlay to appear on launched games. So disabling it for that application isn't an option.
     
    At the same time, game launcher presently relies on an internet connection to a web page on our server that uses the Steam web API to query Steam's servers and display a grid of games. I've wanted to make it work in offline mode for a while, and now I have another reason to do this.
     
    So it looks like I will be writing a routine that builds a list of all available games, downloads their preview images, and creates an initial cache. The preview images will then be displayed in a custom widget I will write with a Leadwerks GUI widget script.
     
    Long story short, Game Launcher is going to ditch the HTML interface, work offline, and is coming to Linux. This blog entry was a window into some of the design decisions I deal with every day.
     

  21. Josh
    Over the recent months the Leadwerks Workshop Store has experienced a noticeable increase in sales, correlating to an increased number of products offered. Although Workshop Store sales are quite a bit lower than DLC sales, the Workshop Store is more scaleable because it allows third parties to submit a greater variety of products.
     
    We're also able to send out payments to Russia and other regions that other stores and websites may have trouble sending payments to, because our transaction system is built on Steam.
     

     
    I am meeting with Valve in October to make my recommendations on how we can maximize sales through this system for third-party authors. In the meantime, you can submit your items to the Workshop now:
    http://www.leadwerks.com/werkspace/page/tutorials/_/workshop-r11
×
×
  • Create New...