❄️🎁⛄ The Winter Games Tournament is Live! 🎄🎅❄️
Jump to content

Recommended Posts

Posted
  • Game Mechanics video tutorial series is added on Leadwerks Game Engine beta branch.
  • The last three videos produce an error "Error 2" (?) but there does not seem to be any problem with audio or video playing.
  • Like 1

Let's build cool stuff and have fun. :)

  • 2 weeks later...
Posted

5.0.1 beta

The first build of version 5.0.1 is available on the beta branch. This revises brush picking so that brush faces of all sizes can be successfully picked in the editor. Only the editor is updated at this time.

You must opt into the beta branch on Steam if you want to test this version before a new release goes out to the default branch. Right-click on the application in the Steam interface, select the Properties menu, and in the Betas section, select "Beta - Development branch for testing".

  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

In this build, the requirement for an environment variable is removed, and a Visual Studio property sheet is used instead,

  • The rules for environment variables on Windows are unclear, and even if I spend a lot of time studying and testing them, they could change at some point in the future, or potentially act differently on some configation.
  • Having information in three different places (project folder, install directory, env var) is confusing.
  • If you have a shared project, and two different people have Leadwerks installed in different locations, you will need to remove the PropertySheet.props file from the repo. This is a slight inconvenience, but that's not as bad as having a magic variable hidden in the Windows settings.

Existing C++ projects will not be affected by this. If you want to modify them, place this in a file called "PropertySheet.props", then "Add an existing property sheet" and include this in your project:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <ImportGroup Label="PropertySheets" />
  <PropertyGroup Label="UserMacros">
    <LEADWERKS>C:/Program Files (x86)/Steam/steamapps/common/Leadwerks</LEADWERKS>
  </PropertyGroup>
</Project>

 

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

An update for the C++ programming library is available now.

  • Fixes error reported in textfield hiding infinite loop, in some situations
  • Includes new raycasting method for brush entities
  • Brush::meshes member is now exposed, contains the visual meshes built to display the brush entity
  • Like 2
  • Upvote 1

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

In this build, when you create a new map, the editor will select the create object mouse tool, and when you open a map file the editor will choose the Selection mouse tool.

  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

Editor will now compile all shaders as soon as they go to the GPU, instead of waiting until they are about to be used. Editor starts in 2.3 secinds instead of 1.8, but there's no delay now when you enable tessellation on a material, for example.

There is a compile error on one of the vertex shader variations right now, will fix.

This will get extended to the engine soon.

  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

Whole engine is updated to precompile shaders now, I'm going to see about that vertex shader fix now...

  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

This update rolls back the always-precompile change I made. I think this will require more time to be done properly.

  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

Fixed some JSON definition files for the C++ template that did not have "auto-generated" set to true, so they would not get updated automatically if the C++ code changes.

  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

  • Fixed problem with new C++ projects referencing invalid files.
  • Fixed bug that was printing an extra line return.
  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

  • Full update of C++ lib and Lua EXEs.
  • C++ header and entity definition files updated.
  • Think it's time to release this on default branch soon.
  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.1

  • Version 5.0.1 is now on the default branch. This removes the need for a system environment variable for C++ projects, and fixes several bugs.
  • Beta and default are in sync.
  • Version 5.0.0 is now archived.
  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.2 beta

  • Added option in general settings to not show the project name in the title bar.
  • WASD keys can now be remapped, for users who don't have English keyboards with WASD keys in the top-left. Open the file "C:\ProgramData\Leadwerks\settings.json" and find the section called "controls". You can modify the navigation keys here. It's not the ideal user experience right now, but this is just the first step.
    	"controls":
    	{
    		"back": 83,
    		"down": 81,
    		"forward": 87,
    		"left": 65,
    		"right": 68,
    		"up": 69
    	},
  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.2 beta

  • Adjusted the behavior of search and replace fields in script editor.
  • Adjusted behavior of search field in project tab. Wildcards are no longer used, it just does a simple lower-case find/match for the search term.
  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.1 beta

I recompiled the current build, with the version marked 5.0.1. It's on the beta branch and it will go onto default tomorrow. This will be the stable build that goes out right before tournament time.

  • Like 1

Let's build cool stuff and have fun. :)

Posted

5.0.2 beta

Added experimental Camera:SetMouseLook command. This handles mouse looking in the rendering thread, right before a frame is drawn, in the same way that our VR orientation updating code operates. This will provide you with very low-latency mouse feedback, ideal for fast-paced games.

The arguments are mode, speed, and smoothness and it should be called like this:

camera:SetMouseLook(true, 0.1, 0.5)-- 0.1 degree / pixel moved, 0.5 smoothness

Speed (second value) should be greater than zero. Smoothness (last value) should be less than 1.0, 0.0 for no smoothing.

You only need to call this command once. You should not mix this with your own mouse look code. The camera rotation will be retrieved back from the rendering thread automatically.

Note this does not yet handle objects parented to the camera, like a weapon view model.

Here is a version of the CameraControls.lua script, adjusted to use this feature. Since the looking behavior is controlled in the rendering thread, you need to disable it before switching to the menu, or is it keep control of the mouse. Hit Alt + F4 to close the window if you get stuck.

---@class CameraControls : Entity
CameraControls = {}
CameraControls.mousesmoothing = 0.5--"Mouse smoothing"
CameraControls.mouselookspeed = 1.0--"Look speed"
CameraControls.movespeed = 4.0--"Move speed"

---@param self CameraControls
function CameraControls:Start()
	local camera = Camera(self)
	if camera ~= nil then camera:SetMouseLook(true, self.mouselookspeed * 0.1, self.mousesmoothing) end
	self:ListenEvent(EVENT_WORLDPAUSE, self.world)
	self:ListenEvent(EVENT_WORLDRESUME, self.world)
end

---@param self CameraControls
---@param event Event
function CameraControls:ProcessEvent(event)
	local camera = Camera(self)
	if event.id == EVENT_WORLDPAUSE then
		if camera ~= nil then camera:SetMouseLook(false, self.mouselookspeed * 0.1, self.mousesmoothing) end
	elseif event.id == EVENT_WORLDRESUME then
		if camera ~= nil then camera:SetMouseLook(true, self.mouselookspeed * 0.1, self.mousesmoothing) end
	end
end

---@param self CameraControls
function CameraControls:Update()
    local window = ActiveWindow()
    if window == nil then
        return
    end
    
    local speed = self.movespeed / 60.0
    
    if window:KeyDown(KEY_SHIFT) then
        speed = speed * 10.0
    elseif window:KeyDown(KEY_CONTROL) then
        speed = speed * 0.25
    end
    
    if window:KeyDown(KEY_E) then
        self:Translate(0, speed, 0)
    end
    
    if window:KeyDown(KEY_Q) then
        self:Translate(0, -speed, 0)
    end
    
    if window:KeyDown(KEY_D) then
        self:Move(speed, 0, 0)
    end
    
    if window:KeyDown(KEY_A) then
        self:Move(-speed, 0, 0)
    end
    
    if window:KeyDown(KEY_W) then
        self:Move(0, 0, speed)
    end
    
    if window:KeyDown(KEY_S) then
        self:Move(0, 0, -speed)
    end
end

 

  • Like 2

Let's build cool stuff and have fun. :)

Posted

5.0.2 beta

  • Added Display:GetRefreshRate method.
  • Added Hmd:GetRefreshRate method.
  • Fixed player physics to work the same at any update frequency.
  • Improved timing and thread sychronization. This is experimental. If you don't want your workflow interupted, switch to the default branch now.

In this build, timing works differently. The third command argument for World:Render has been replaced with a new value, syncedframes:

World::Render(framebuffer, bool vsync = true, int syncedframes = -1)

This value allows you to specify how many frames the rendering thread should draw before it waits for a new update from the main thread. The max framerate value this command previously supported will no longer be used, because this value is now calculated from the world update frequency and number of synced frames.

Emulating 5.0.1 Standard Behavior

The standard behavior previous builds use is a 60 hz game loop, and the rendering thread is allowed to go as fast as it wants. This will work with any display or VR headset refresh rate:

world->Update(60);
world->Render(framebuffer, true, 0);

Or if you want to test the maximum framerate set VSync to false:

world->Update(60);
world->Render(framebuffer, false, 0);

Improved Synchronization at 60 hz

If you set syncedframes to 1, and the world update rate is 60, then for every one iteration of the game loop, one frame will be rendered. The main and rendering threads will still be running at the same time, but they will be more closely synchronized, for lower-latency input:

world->Update(60);
world->Render(framebuffer, true, 1);

However, on high-frequency displays this will give you a framerate lower than the max refresh rate.

Competitive E-Sports Games

If want to adjust the game speed to support any display with minimal latency, you can do this:

world->Update(window->display->GetRefreshRate());
world->Render(framebuffer, true, 1);

This is the best setting for minimal latency for twitch shooters written in C++. Note that if a frequency other than 60 is used, you will need to multiply all the time-dependent values in your code by world->GetSpeed(). Velocity does not need to be modulated with this, because it is already in units of distance over time.

 If you want your game to run at a speed faster than the screen refresh rate, you can set vsync to false:

world->Update(200);
world->Render(framebuffer, false, 1);

I believe this is how the timing in the newer Doom games works, and it explains why the game cannot run at a framerate faster than 200. Anything higher than that would probably start to affect how physics and other game code works, causing erratic behavior.

Tight Synchronization with Varying Game and Rendering Frequencies

The problem with perfectly synced timing on high-frequency displays is it decreases the amount of time your code has to run in the main thread. At 60 hz your game code has 16.667 milliseconds to run. If the screen refresh rate is 240 hz, that only allows 4.16 milliseconds for your game code to run. If there are a lot of enemies with complex code or if the game is written with Lua, this will probably cause the game to slow down. You might also want to always make the game update at 60 hz so that you don't have to multiply everything by world->GetSpeed().

You can combine a higher rendering frequency with a lower game frequency, by specifying more than one synced frames:

world->Update(60);
world->Render(framebuffer, false, 2);

This will update the game at 60 hz, but render the world at 120 hz, drawing two frames for every game loop. The previous two orientations of each entity will be interpolated, so you have smooth motion even though two frames are rendered for every one iteration of the game loop. If you wanted the game to render at 180 hz, you could set the third argument to 3.

To support any display frequency with close synchronization of frames, you might wish to do something like this:

float refreshrate = window->display->GetRefreshRate();
int syncedframes = Floor(refreshrate / 60.0f);
int updatespeed = Round(refreshrate / syncedframes);

world->Update(updatespeed);
world->Render(framebuffer, true, syncedframes);

The above code will give you these values:

Display refresh rate: 90 hz
Update speed: 90
Synced frames: 1

Display refresh rate: 120 hz
Update speed: 60
Synced frames: 2

Display refresh rate: 144 hz
Update speed: 72
Synced frames: 2

Display refresh rate: 240 hz
Update speed: 60
Synced frames: 4

If you are rendering at a faster speed than the game loop, you may wish to use the Camera::SetMouseLook feature to handle camera looking in the rendering thread. This will give you low-latency camera movement, with a few caveats:

  • The player movement will still be updating at a lower frequency and might feel slightly mushier, but since player movement has inertia anyways it might not be very noticable.
  • The camera rotation will be fed back to the main loop, so it will always be a few milliseconds behind. This could matter in E-sports type hyper-competitive shooters, but probably doesn't matter for regular FPS games.

On the other hand, someone with a 240 hz display is likely to also have a top-of-the-line CPU, so maybe it all balances out. It's up to you.

Default Behavior

If you don't understand any of this, or don't care, then you can just not specify any parameter, and the engine will choose settings for you based on the display refresh rate. For 75% of players this will be 60 hz, so if your game loop is running at 60 hz and vsync is enabled, the engine will choose 1 for the number of synced frames, otherwise it will be set to 0.

Visualizing the Technique

This code provides a dramatic example that shows how varying game and rendering frequencies works.

turret2.thumb.gif.5a3b059a9005fb268d2d9936f665394d.gif

Here the game updates at just one update per second, but the renderer displays smooth motion at 120 frames per second, using just the inputted information! (Don't actually do this in your own games, this is just for learning.)

#include "Leadwerks.h"

using namespace Leadwerks;

int main(int argc, const char* argv[])
{
    auto displays = GetDisplays();

    auto window = CreateWindow("Leadwerks", 0, 0, 1280, 720, displays[0], WINDOW_CENTER | WINDOW_TITLEBAR);

    auto world = CreateWorld();

    auto framebuffer = CreateFramebuffer(window);

    auto camera = CreateCamera(world);
    camera->SetClearColor(0.125);
    camera->SetPosition(0, 0, -2);

    auto light = CreateBoxLight(world);
    light->SetRotation(45, 35, 0);
    light->SetRange(-10, 10);
    light->SetColor(2);

    auto A = CreateBox(world);
    A->SetPosition(-1,0,0);
    A->SetColor(0, 0, 1);

    auto B = CreateBox(world);
    B->SetPosition(1, 0, 0);
    B->SetColor(0, 0, 1);

    while (window->Closed() == false and window->KeyDown(KEY_ESCAPE) == false)
    {
        // The box on the left will show smoothed motion
        A->Turn(0, 0, 22.5);

        // The box on the right will show the true state of the game
        B->Turn(0, 0, 22.5);
        B->Sync();

        // Game updates once per second
        world->Update(1);

        // Game renders 120 frames, evenly spaced, for every one game loop iteration
        world->Render(framebuffer, false, 120);
    }
    return 0;
}

 

 

  • Thanks 1

Let's build cool stuff and have fun. :)

Guest
This topic is now closed to further replies.
×
×
  • Create New...